前言
在之前的文章中牛牛给大家大致介绍了Yakit中的靶场Vulinbox安装教程【文末抽奖】Yak叫你来打靶了,实验环境安装就位后,接下来就是上手实操。接下来的日子里,牛牛将按照不同类型的漏洞为大家呈上通关教程,今天我们先来唠唠:SQL注入漏洞。
网安圈中,你或许之前听过某某通过攻击数据库修改自己考试成绩的案例,修改途径一般用的就是SQL注入方法。
SQL注入漏洞作为网络安全最普遍的漏洞之一,在OWASP发布的top10排行榜中危害排名极高,数据库注入一直是web中一个令人头疼的问题。什么是SQL注入?简单来说就是数据「越俎代庖」做了代码才能干的事情,恶意用户通过在表单中填写包含SQL关键字的数据来使数据库执行非常规代码的过程。至于更详细官方的解释,大家可以自行查询资料。
案例分享及教学
不存在SQL注入的情况(数字严格校验)
这个示例演示了如何通过对用户输入的参数进行数字严格校验,从而防止SQL注入攻击。数字严格校验确保只有有效的数字被用作SQL查询的参数,而不允许插入恶意的SQL代码。
示例代码:
{
DefaultQuery: "id=1",
Path: "/user/by-id-safe",
Title: "不存在SQL注入的情况(数字严格校验)",
Handler: func(writer http.ResponseWriter, request *http.Request) {
var a = request.URL.Query().Get("id")
i, err := strconv.ParseInt(a, 10, 64)
if err != nil {
writer.Write([]byte(err.Error()))
writer.WriteHeader(500)
return
}
u, err := s.database.GetUserById(int(i))
if err != nil {
writer.Write([]byte(err.Error()))
writer.WriteHeader(500)
return
}
sqliWriter(writer, request, []*VulinUser{u})
return
},
RiskDetected: false,
ExpectedResult: map[string]int{"参数:id未检测到闭合边界": 1},
}
代码分析:
-
这个示例接收一个名为
id
的查询参数,该参数预期是一个整数。 -
通过使用
strconv.ParseInt
函数,将用户提供的id
参数解析为一个64位整数。如果解析失败,将返回一个错误。 -
使用解析后的整数值来执行数据库查询,这个值不包含恶意的SQL注入代码。
-
最后,将查询结果返回给客户端。
注意:
数字严格校验是一种有效的防御措施,但在实际应用中,还需要考虑其他安全性方面的因素,例如权限控制和输入验证,以维护应用程序的安全性。
ID 为数字型的简单边界 SQL 注入
ID为数字型的简单边界SQL注入是一种常见的SQL注入漏洞,通常出现在Web应用程序中。这种漏洞的攻击目标是应用程序中处理ID参数的代码,由于没有对输入进行充分验证和过滤,导致攻击者可以在ID参数中注入恶意的SQL代码。
在这种情况下,攻击者通常会尝试构造特定的输入,以绕过应用程序的验证和过滤机制,注入恶意的SQL语句。
示例代码:
SELECT * FROM users WHERE id = 输入的ID值;
攻击示例:
1 OR 1=1
这样构造的SQL语句变成:
/*构造后的SQL*/
SELECT * FROM users WHERE id = 1 OR 1=1
由于1=1这个条件始终为真,整个查询语句将返回所有用户的数据,而不仅仅是匹配到的特定ID的用户数据。这就是SQL注入攻击的原理,攻击者可以通过注入恶意的SQL代码来绕过应用程序的身份验证,获取未授权的数据或执行恶意操作。
防御措施:
-
使用参数化查询或预编译语句,确保用户输入的ID值不直接拼接到SQL查询中。
-
对输入的ID值进行验证,确保它是合法的数字,并限制ID值的范围在合理的边界内。
-
对输入的ID值进行过滤,确保它不包含任何恶意代码或特殊字符。
-
最小化数据库的权限,确保应用程序只能访问必要的数据,并限制对数据库的敏感操作。
-
定期进行安全审计和渗透测试,以发现和修复潜在的SQL注入漏洞。
通过采取这些安全措施,可以有效地防止ID为数字型的简单边界SQL注入漏洞,并提高Web应用程序的安全性。
GET 参数是 JSON JSON中字段存在SQL注入
有时,开发人员可能会使用JSON格式作为GET参数来传递更复杂的数据结构。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写,因此在Web开发中广泛使用。JSON由键值对组成,使用花括号{}
表示,例如:http://example.com/api?data=
{
"name":"John","age":30}
。
然而,如果在处理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;
攻击示例:
id={"uid":1,"id":"1 OR 1=1"}
这样SQL语句就变成如下
/*构造后的SQL语句*/
SELECT * FROM users WHERE id = 1 OR 1=1
此时1=1
总是为真,将返回所有的用户信息。
防御措施:
-
应该检查JSON对象中的每个字段和值,确保它们符合预期的数据类型和格式。
-
不应该直接将JSON数据作为SQL查询的一部分,而应该使用参数化查询或预编译语句,以确保输入数据不会被误解为可执行的SQL代码。
只有这样,才能有效地防止JSON中字段存在SQL注入的风险。
GET参数是被编码的JSON JSON中字段存在SQL注入
这种漏洞是由于在处理GET参数时,服务器端接收到经过Base64编码的JSON数据,但在解码JSON数据后未对其中的字段进行适当的输入验证和处理,直接将其用于构建SQL查询语句,导致SQL注入漏洞的产生。
攻击者可以通过恶意构造经过Base64编码的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语句为查询id值为1的用户。
攻击示例:
http://127.0.0.1:8787/user/id-b64-json?id=eyJ1aWQiOjEsImlkIjoiMSBPUiAxPTEifQ==
/*解码为*/
{"uid":1,"id":"1 OR 1=1"}
/*构造后的查询如下*/
select * from vulin_users where id = 1 OR 1=1
构造简单的测试用例,并经过base64编码后发送,这将返回所有用户的数据,而不仅仅是匹配到的特定ID的用户数据。
防御措施:
-
避免直接拼接SQL查询:绝不要直接将用户提供的数据直接拼接到SQL查询中,无论数据是否经过Base64编码。直接拼接会导致SQL注入漏洞,攻击者可以通过恶意构造的数据修改查询语句,从而访问、修改或删除数据库中的数据。
-
解码Base64数据:首先,在服务器端接收到GET参数后,先进行Base64解码得到原始的JSON数据。
-
使用参数化查询或ORM:使用参数化查询或对象关系映射(ORM)库来与数据库进行交互。参数化查询将参数与查询语句分开,从而防止SQL注入攻击。
ID 为数字型的简单边界 SQL报错检测
边界SQL报错检测是一种测试方法,用于探测应用程序在处理数字型ID参数时是否存在SQL注入漏洞。在此测试中,我们会尝试构造一些特殊的输入,以观察应用程序的反应。这里给出了一些示例:
示例代码:
SELECT * FROM users WHERE id = {user_input};
现在有一个查询,用于从数据库中获取用户信息,其中,{user_input}
是应用程序接收的用户输入。
攻击示例:
-
正常输入:首先,我们使用正常的数字型输入来检查查询是否按预期工作:
user_input = 123
SELECT * FROM users WHERE id = 123;
如果查询正常执行并返回预期结果,说明应用程序对于正常输入的处理是正确的。
-
边界值测试:接下来,我们可以测试边界值,包括最小值、最大值和边界附近的值。例如:
user_input = 0 # 最小值
SELECT * FROM users WHERE id = 0;
user_input = 2147483647 # INT类型最大值
SELECT * FROM users WHERE id = 2147483647;
user_input = 1 # 边界附近的值
SELECT * FROM users WHERE id = 1;
通过测试边界值,我们可以确保应用程序在处理边界输入时没有出现错误或异常情况。
-
非数字输入:接下来,我们可以尝试输入非数字型数据,例如字符串或特殊字符,来观察应用程序的反应:
user_input = "abc"
SELECT * FROM users WHERE id = "abc";
通以上测试来查看程序是否出现异常错误,从而判断是否存在SQL注入漏洞。
防御措施:
防止ID为数字型的简单边界SQL注入,可以采取以下预防措施:
-
使用参数化查询:使用参数化查询(Prepared Statements)来执行SQL语句,确保用户输入的ID不会直接拼接到SQL查询语句中。参数化查询会将输入和查询逻辑分离,有效地防止SQL注入攻击。
-
输入验证:在接收用户输入的ID之前,进行输入验证,确保它是一个合法的数字。可以使用正则表达式或内置的类型转换函数进行验证。如果输入不是数字类型,应拒绝执行查询。
-
转义或过滤特殊字符:对于ID参数,可以在执行查询之前,对其进行转义或过滤,以确保不会解释为SQL代码。对于数字类型的ID,这一步通常是不必要的,因为数字不包含特殊字符。
Cookie-ID SQL注入
Cookie-ID SQL注入是一种特定类型的SQL注入漏洞,它涉及到在处理包含在Cookie中的ID时,未对输入进行适当的验证和处理,从而导致攻击者能够注入恶意的SQL代码,执行非授权的数据库操作。
当应用程序使用Cookie来存储用户会话信息,并在后续的请求中使用Cookie中的ID来执行数据库查询时,如果对Cookie中的ID参数没有进行充分的验证和过滤,攻击者可以构造恶意的Cookie,注入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中,后端查询利用cookie传输的值进行拼接查询。
攻击示例:
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 OR 1=1
#后端查询
select * from vulin_users where id = 1 OR 1=1
防御措施:
为了防止Cookie-ID SQL注入,以下是一些建议的预防措施:
-
参数化查询:无论从Cookie还是其他来源获取ID参数,都应使用参数化查询(Prepared Statements)来执行数据库查询。确保不直接将Cookie值拼接到SQL查询语句中,而是通过绑定参数的方式传递给数据库引擎。
-
验证和过滤Cookie数据:在应用程序接收Cookie数据之前,进行验证和过滤,确保它是预期的格式和类型。例如,如果ID是一个整数,验证其是否为合法的整数值。
-
限制Cookie访问范围:在设置Cookie时,将其限制在仅在必要的路径和域名下可见。避免在敏感操作之外的路径或域名下访问敏感的Cookie信息。
-
不要在Cookie中存储敏感信息:尽量避免在Cookie中存储敏感信息,特别是与用户身份认证相关的敏感数据。可以将敏感信息存储在服务器端的会话中,而在Cookie中只存储会话标识符。
-
加密Cookie数据:对于敏感的Cookie信息,可以进行加密处理,以增加攻击者解析Cookie的难度。
结尾
以上就是本次教学的SQL注入案例,大家可以根据示例代码以及教学视频进行靶场训练,在训练中能够更直观的感受到SQL注入的强大攻击性,牛牛在这里给出一个小tip:
SQL注入不止这些类型,在下次的文章中,牛牛会继续讲解更多,请大家持续关注Yak project公众号~
Loading...
字符串为注入点的 SQL 注入
字符串注入点模糊查询
字符串注入点模糊查询(括号边界)
参数编码字符串注入点模糊查询(括号边界)
Base64参数(JSON)嵌套字符串注入点模糊查询(括号边界)
Yak官方资源
Yak 语言官方教程:
https://yaklang.com/docs/intro/
Yakit 视频教程:
https://space.bilibili.com/437503777
Github下载地址:
https://github.com/yaklang/yakit
Yakit官网下载地址:
https://yaklang.com/
Yakit安装文档:
https://yaklang.com/products/download_and_install
Yakit使用文档:
https://yaklang.com/products/intro/
常见问题速查:
https://yaklang.com/products/FAQ