一.实验目的
SQL 注入是一种代码注入技术,利用 Web 应用程序和数据库服务器之间接口的漏洞。当用户的输入没有被 Web 应用程序正确检查就被发送到后端数据库服务器时,就会出现 SQL 注入漏洞。很多 Web 应用程序从用户处获取输入,并使用用户输入来构建 SQL 查询,以获得数据库中的数据信息。Web 应用程序也使用 SQL 查询在数据库中进行数据信息的存储。这些都是 Web 应用程序开发中的常见做法。如果没有仔细构造 SQL 查询,则可能会出现 SQL 注入漏洞。SQL 注入攻击是对 Web 应用程序最常见的攻击之一。
在本实验中,我们创建了一个易受 SQL 注入攻击的 Web 应用程序,它包含许多 Web 开发人员常犯的错误。实验的目标是找到利用 SQL 注入漏洞的方法,展示攻击所能造成的伤害,并掌握防御此类攻击的技术。本实验覆盖以下主题:
1. SQL 语句:SELECT 与 UPDATE
2. SQL 注入
3. 语句预处理
二.实验步骤与结果
2.1 Task 1:熟悉 SQL 语句
Task 1 的目标是通过使用提供的数据库来熟悉 SQL 命令。Web 应用程序所使用的数据存储在 MySQL数据库中,由 MySQL 容器托管。我们创建了一个名为 sqllab_users 的数据库,其中包含一个名为credential 的表。表中存储着每个员工的个人信息(例如 eid、password、salary、ssn 等)。本任务中,请通过操作数据库熟悉 SQL 查询语句。运行手册中所给出命令后,你需要使用一条 SQL 命令打印员工 Alice 的所有资料信息。请提供结果截图。
如上图所示,使用语句select * from credential where Name=’Alice’;即可得到并打印Alice的所有资料信息。
2.2 Task 2:基于SELECT语句的SQL注入攻击
攻击者通过 SQL 注入技术可以执行恶意 SQL 语句,即恶意负载。通过恶意的 SQL 语句,攻击者可以从数据库中窃取数据,甚至对数据库进行修改。我们的 Web 应用程序数据库含有 SQL 注入漏洞,模仿了开发人员的常犯错误。在登陆网站www.seed-server.com中进行 SQL 注入攻击的练习,登录页面见图 1。Web 应用程序根据用户名和口令认证用户,所以只有知道自己口令的员工才能登录。作为攻击者,请在无法得知任何员工口令的前提下成功登录 Web 应用程序。
Task 2.1 基于网页的 SQL 注入攻击
你的任务是以管理员的身份从登录页面登录到 Web 应用程序,这样你就可以查看所有员工的信息。管理员的用户名是 admin,口令未知。请在用户名与口令输入框中输入能成功完成攻击的内容。
如上图所示,在用户名框输入以上内容,即可成功登入管理员界面。其原理如下图所示:
在输入如上内容后,数据库中执行了上图中所展示的命令,#作为注释符,其后面的内容便无需再验证,即可成功进入管理员页面。
Task 2.2 基于命令行的 SQL 注入攻击
在不使用网页的情况下完成 Task 2.1 的目标。你可以使用命令行工具,如 curl,它可以发送 HTTP 请求。如需在 HTTP 请求中包含多个参数,需要把 URL 和参数用一对单引号括起来。否则,用于分隔参数的特殊字符 (如 &) 会被 shell 曲解,造成命令歧义。以下给出向Web 应用程序发送带有两个参数(username 和 Password)的 HTTP GET 请求的示例。
首先我们尝试输入正确的的用户名和口令,可以得到如下所示的结果。
然后我们进行SQL注入攻击,如下图所示:
我们可以观察到两次得到相同的结果,证明在命令行中SQL注入攻击实现成功。
Task 2.3 增加一条新的 SQL 语句
在 Task 2.1 与 Task 2.2 中,我们只能做到从数据库中窃取信息,进一步的攻击是通过登录页面上的相同漏洞对数据库的数据进行修改。请尝试在 SQL 注入攻击中使用两条SQL 语句,第二条是更新或删除语句。在 SQL 中,分号(;)被用来分隔两条 SQL 语句。请在登录页面使用两条 SQL 语句进行攻击。
首先在登录页面中进行尝试,得到如下报错:
然后再命令行中进行尝试,同样得到报错如下:
但是我们在数据库中直接运行以分号间隔的两条指令时,可以得到如下结果:
发现并未产生报错,说明在数据库中是支持两条指令的执行的。根据报错,我们可以在网站的源码中找到如下代码:
报错发生在query过程中,经过上网查询,可以得知,query函数执行针对数据库的某个查询,要实现多个语句的执行,需要将其修改为支持多个查询的multi_query函数,修改如下:
重新在命令行中进行SQL注入攻击,可以得到如下结果,未发生报错,说明语句成功执行。
2.3 Task 3:基于UPDATE语句的SQL注入攻击
Task 3.1 :修改自己的工资
编辑页面中只能修改员工的昵称、电子邮件、地址、电话号码和口令,而不能用于修改工资。假设你 (Alice) 由于老板 Boby 今年未给你加薪而感到不满。你想利用存在于编辑页面的SQL 注入漏洞来增加自己的工资。请展示你是如何实现这一目标的。已知列 salary 用于存储工资数额。首先我们使用Alice正确的用户名和口令进入自己的页面,可以得到如下结果:
可以观察到其工资为20000,然后在编辑页面进行如下操作:
修改后再观察自己的页面,可以发现攻击成功,工资变为99999
但是在数据库中,打印所有员工信息时,发现所有人的工资都被修改为了99999,如下图所示:
这样的攻击容易被发现,通过研究发现,原因在于注释后没有限定语句,因而将所有人的工资都进行了修改,需要把原有的语句修改为
muyoo’,salary=99999 where Name=’Alice’; # |
---|
即可单独修改Alice的工资。
Task 3.2:修改他人的工资
在提高自己的工资数额后,你决定惩罚你的老板 Boby,将他的工资减少到1 美元。请展示你是如何实现这一目标的。
在Alice的编辑页面中NickName一项中输入如下指令:
‘,salary=1 where Name=’Boby’; # |
---|
即可成功修改Boby的工资,如下图所示:
Task 3.3:修改他人的口令
修改完 Boby 的工资后,你仍心有不甘,所以你想修改 Boby 的口令,这样你就可以登录他的账户,做进一步的破坏。请展示你是如何实现这一目标的。你需要证明你可以用新的口令成功登录 Boby 的账户。需要注意,数据库存储的并非明文形式的口令,而是口令的哈希值。请在unsafe_edit_backend.php 中查看口令的存储方式,程序使用 SHA1 哈希函数来生成口令的哈希值。 由于在数据库中存储口令为sha1加密的,因而在Alice的编辑页面中NickName一项中输入如下指令:
‘,password=sha1(‘123’) where Name=’Boby’; # |
---|
即可成功修改Boby的口令为123
然后在登陆页面中输入用户名和口令即可成功进入Boby的主页,如下所示:
2.4 Task 4:对策:语句预处理
请使用语句预处理机制来修复 SQL 注入漏洞。为了简单起见,我们在文件夹 defense 内创建了一个简化程序,你需要对这个文件夹中的文件进行修改。访问下面给出的 URL,你会看到一个类似于 Web应用程序登录页面的网页,在网页中提供正确的用户名和口令即可查询员工的信息。
进入新的登录页面,利用SQL注入仍然可以成功登入页面,如下:
根据实验手册中所给出指导对源码进行修改如下:
重新在登录页面进行SQL注入攻击,发现登录进的页面不会显示个人信息:
如果输入正确的用户名和口令,仍然可以会显示个人信息如下:
证明防御措施的部署是成功的。
2.5 思考题
假设数据库只存储 password 和 eid 两列的 SHA256 值。使用下面 SQL 语句与数据库交互,其中$passwd 和 $eid 变量的值由用户提供。这个程序是否存在 SQL 注入问题?如果没有,请解释原因;如果有,请给出构造范例。
答:仍然存在 SQL 注入问题。原因在于参数是可以拼接的, 可以在 eid 一项中输入如下内容: 008,256)’and 1=1 # Passwd 中输入如下内容: 123,256)’and 1=1 # 都可以成功实现 SQL 注入攻击