Yakit靶场通关教程|SQL注入篇总结
注:本文是从Yakit官方公众号文章中总结归纳,只保存漏洞修复建议以供后续学习参考。
原文链接:
https://mp.weixin.qq.com/s/1MqDt1aEy8RDot_jTlb6mA
https://mp.weixin.qq.com/s/-E5CDHIFCvyxzEYWvtQpiQ
ID 为数字型的简单边界 SQL 注入
SELECT * FROM users WHERE id = 输入的ID值;
修复建议:
使用参数化查询或预编译语句,确保用户输入的ID值不直接拼接到SQL查询中。
对输入的ID值进行验证,确保它是合法的数字,并限制ID值的范围在合理的边界内。
对输入的ID值进行过滤,确保它不包含任何恶意代码或特殊字符。
最小化数据库的权限,确保应用程序只能访问必要的数据,并限制对数据库的敏感操作。
定期进行安全审计和渗透测试,以发现和修复潜在的SQL注入漏洞。
GET 参数是 JSON
JSON中字段存在SQL注入
/*URL地址*/
http://127.0.0.1:8787/user/id-json?id={"uid":1,"id":"1"}
/*原SQL语句*/
select * from vulin_users where id = 1;
修复建议:
应该检查JSON对象中的每个字段和值,确保它们符合预期的数据类型和格式。
不应该直接将JSON数据作为SQL查询的一部分,而应该使用参数化查询或预编译语句,以确保输入数据不会被误解为可执行的SQL代码。
GET参数是被编码的JSON
JSON中字段存在SQL注入
http://127.0.0.1:8787/user/id-b64-json?id=eyJ1aWQiOjEsImlkIjoiMSJ9 (解码为{"uid":1,"id":"1"})
/*后端的查询如下*/
select * from vulin_users where id = 1;
修复建议:
避免直接拼接SQL查询:绝不要直接将用户提供的数据直接拼接到SQL查询中,无论数据是否经过Base64编码。直接拼接会导致SQL注入漏洞,攻击者可以通过恶意构造的数据修改查询语句,从而访问、修改或删除数据库中的数据。
解码Base64数据:首先,在服务器端接收到GET参数后,先进行Base64解码得到原始的JSON数据。
使用参数化查询或ORM:使用参数化查询或对象关系映射(ORM)库来与数据库进行交互。参数化查询将参数与查询语句分开,从而防止SQL注入攻击。
ID 为数字型的简单边界 SQL报错检测
SELECT * FROM users WHERE id = {user_input};
修复建议:
使用参数化查询:使用参数化查询(Prepared Statements)来执行SQL语句,确保用户输入的ID不会直接拼接到SQL查询语句中。参数化查询会将输入和查询逻辑分离,有效地防止SQL注入攻击。
输入验证:在接收用户输入的ID之前,进行输入验证,确保它是一个合法的数字。可以使用正则表达式或内置的类型转换函数进行验证。如果输入不是数字类型,应拒绝执行查询。
转义或过滤特殊字符:对于ID参数,可以在执行查询之前,对其进行转义或过滤,以确保不会解释为SQL代码。对于数字类型的ID,这一步通常是不必要的,因为数字不包含特殊字符。
Cookie-ID SQL注入
GET /user/cookie-id HTTP/1.1
Host: 127.0.0.1:8787
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Cookie: ID=1
#后端查询
select * from vulin_users where id = 1
修复建议:
参数化查询:无论从Cookie还是其他来源获取ID参数,都应使用参数化查询(Prepared Statements)来执行数据库查询。确保不直接将Cookie值拼接到SQL查询语句中,而是通过绑定参数的方式传递给数据库引擎。
验证和过滤Cookie数据:在应用程序接收Cookie数据之前,进行验证和过滤,确保它是预期的格式和类型。例如,如果ID是一个整数,验证其是否为合法的整数值。
限制Cookie访问范围:在设置Cookie时,将其限制在仅在必要的路径和域名下可见。避免在敏感操作之外的路径或域名下访问敏感的Cookie信息。
不要在Cookie中存储敏感信息:尽量避免在Cookie中存储敏感信息,特别是与用户身份认证相关的敏感数据。可以将敏感信息存储在服务器端的会话中,而在Cookie中只存储会话标识符。
加密Cookie数据:对于敏感的Cookie信息,可以进行加密处理,以增加攻击者解析Cookie的难度。
字符串为注入点的 SQL 注入
http://127.0.0.1:8787/user/name?name=admin
#查询名为admin的用户
select * from vulin_users where username = 'admin';
修复建议:
参数化查询:使用参数化查询(Prepared Statements)来执行SQL语句。参数化查询会将用户输入与查询逻辑分开,有效地防止SQL注入攻击。
输入验证:在接收字符串输入之前,进行输入验证,确保它是一个合法的格式和长度。例如,对于用户名,验证是否包含特殊字符或空格。
转义或过滤特殊字符:在执行查询之前,对用户输入进行转义或过滤,确保不会被误解为SQL代码。在大多数编程语言和数据库引擎中,都有提供相关的转义函数,例如在Python中可以使用escape_string()来转义字符串。
白名单验证:对于一些特定的输入字段,可以使用白名单验证,只接受预定义的合法输入,拒绝其他非法输入。
字符串注入点模糊查询
http://127.0.0.1:8787/user/name/like?name=a&debug=1
/*查询名称为a的用户*/
select * from vulin_users where username LIKE '%a%';
修复建议:
参数化查询:使用参数化查询(Prepared Statements)来执行SQL语句。参数化查询会将用户输入与查询逻辑分开,有效地防止SQL注入攻击。
字符串注入点模糊查询(括号边界)
http://127.0.0.1:8787/user/name/like/2?name=a&debug=1
#查询名称为a并且年龄大于20的用户
select * from vulin_users where (username LIKE '%a%') AND (age > 20);
修复建议:
使用参数化查询或预处理语句:不要将用户输入直接拼接到SQL查询中。使用参数化查询或预处理语句,将用户输入作为参数绑定到查询中,数据库引擎会自动处理输入的转义,避免注入攻击。
使用ORM(对象关系映射):使用ORM框架,例如Hibernate、Sequelize等,可以避免直接使用原始SQL查询,ORM框架会自动进行查询参数的处理。
输入验证和过滤:对于所有从用户获取的输入,进行合法性验证和适当的过滤,确保输入符合预期的格式和范围。拒绝非法的输入,防止恶意输入进入数据库查询。
参数编码字符串注入点模糊查询
(括号边界)
SELECT * FROM vulin_users WHERE (username LIKE '%a%') AND (age > 20);
修复建议:
为了防止参数编码字符串注入点模糊查询漏洞,应该始终使用参数化查询或预处理语句,不要直接拼接用户输入到SQL查询中,并对输入进行严格的过滤和验证。在示例中,可以使用预处理语句来避免漏洞,例如:
# 假设username和age是从用户输入获取的值
username = request.form['username']
age = request.form['age']
# 使用预处理语句构建查询
sql = "SELECT * FROM vulin_users WHERE (username LIKE ?) AND (age > ?)"
cursor.execute(sql, ('%' + username + '%', age))
result = cursor.fetchall()
Base64参数(JSON)嵌套字符串
注入点模糊查询(括号边界)
Base64参数(JSON)嵌套字符串注入点模糊查询是一种安全漏洞,通常出现在应用程序接受经过Base64编码的JSON格式参数,并将其作为模糊查询条件用于SQL语句中。攻击者可以通过注入特殊的Base64编码和JSON字符串来改变查询条件,绕过预期的过滤,导致数据泄露或非预期的查询结果。
假设应用程序接受经过Base64编码的JSON格式参数,并使用以下后端查询语句执行模糊查询:
SELECT * FROM vulin_users WHERE (username LIKE '%a%') AND (age > 20);
修复建议:
为了防止Base64参数(JSON)嵌套字符串注入点模糊查询漏洞,应该始终使用参数化查询或预处理语句,不要直接拼接用户输入到SQL查询中,并对输入进行严格的过滤和验证。