Sql注入基础原理介绍
分组:和20179205王雅哲共同完成实验
一、实验说明
1.1 sql注入
SQL注入攻击通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作。
SQL注入即是指web应用程序对用户输入数据的合法性没有判断,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
●SQL注入威胁表现形式可以体现为以下几点:
●绕过认证,获得非法权限
●猜解后台数据库全部的信息
●注入可以借助数据库的存储过程进行提权等操作
●SQL注入攻击的典型手段:
●判断应用程序是否存在注入漏洞
●收集信息、并判断数据库类型
●根据注入参数类型,重构SQL语句的原貌
●猜解表名、字段名
●获取账户信息、攻击web或为下一步攻击做准备
1.2 web程序三层架构
三层架构(3-tier architecture) 通常意义上就是将整个业务应用划分为:
-
界面层(User Interface layer)
-
业务逻辑层(Business Logic Layer)
-
数据访问层(Data access layer)。
区分层次的目的即为了“高内聚低耦合”的思想。在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构被应用于众多类型的软件开发。由数据库驱动的Web应用程序依从三层架构的思想也分为了三层:
-
表示层。
-
业务逻辑层(又称领域层)
-
数据访问层(又称存储层)
拓扑结构如下图所示:
当我们访问动态网页时, Web 服务器会向数据访问层发起 Sql 查询请求,如果权限验证通过就会执行 Sql 语句。这种网站内部直接发送的Sql请求一般不会有危险,但实际情况是很多时候需要结合用户的输入数据动态构造 Sql 语句,如果用户输入的数据被构造成恶意 Sql 代码,Web 应用又未对动态构造的 Sql 语句使用的参数进行审查,则会带来意想不到的危险。
二、实验过程
本实验将通过 LAMP 搭建 Sql 注入环境,两个实验分别介绍 Sql 注入爆破数据库、Sql 注入绕过验证两个知识点。
1、Sql 注入示例一.猜解数据库
(1)如下图所示,先下载文件并解压运行:
(2)进入 Firefox 浏览器,输入网址 : localhost/dvwasql , 点击create/Reset Database创建数据库:
(3)进入登录界面,默认用户名为:admin 密码为:password
(4)将 Security 级别调整为 low
(5)进入 SQL injection页面开始注入:
(6)先输入 1 ,查看回显 (URL中ID=1,说明php页面通过get方法传递参数):
(7)那实际上后台执行了什么样的Sql语句呢?点击 view source查看源代码 :
可以看到,实际执行的Sql语句是:
SELECT first_name, last_name FROM users WHERE user_id = '1';
我们是通过控制参数Id的值来返回我们需要的信息。如果我们不按常理出牌,比如在输入框中输入 1' order by 1#,实际执行的Sql语句就会变成:
SELECT first_name, last_name FROM users WHERE user_id = '1' order by 1#`;(按照Mysql语法,#后面会被注释掉,使用这种方法屏蔽掉后面的单引号,避免语法错误)
这条语句的意思是查询users表中user_id为1的数据并按第一字段排行。
(8)输入 1' order by 1#和 1' order by 2#时都返回正常,当输入 1' order by 3#时,返回错误:
由此可知,users表中只有两个字段,数据为两列。
接下来我们使用 union select联合查询继续获取信息。union 运算符可以将两个或两个以上 select 语句的查询结果集合合并成一个结果集合显示,即执行联合查询。需要注意在使用 union 查询的时候需要和主查询的列数相同,而我们之前已经知道了主查询列数为 2,接下来就好办了。输入1' union select database(),user()#进行查询 :
-
database()将会返回当前网站所使用的数据库名字.
-
user()将会返回执行当前查询的用户名.
实际执行的Sql语句是 :
SELECT first_name, last_name FROM users WHERE user_id = '1' union select database(),user()#`;
通过上图返回信息,我们成功获取到:
-
当前网站使用数据库为 dvwa .
-
当前执行查询用户名为 root@localhost .
同理我们再输入 1' union select version(),@@version_compile_os#进行查询:
-
version() 获取当前数据库版本.
-
@@version_compile_os 获取当前操作系统。
实际执行的Sql语句是:
SELECT first_name, last_name FROM users WHERE user_id = '1' union select version(),@@version_compile_os#`;
(9)接下来我们尝试获取 dvwa 数据库中的表名。
由经验我们可以大胆猜测users表的字段为 user 和 password ,所以输入:1' union select user,password from users#进行查询:
2、Sql 注入实例二.验证绕过
(1)如下图所示,先下载文件并解压运行:
(2)进入 Firefox 浏览器,输入网址 : localhost/sql2 , 按照顺序,初始化数据:
(3)准备工作完成之后,我们进入首页发现这是一个普通的登录页面,只要输入正确的用户名和密码就能登录成功。我们先尝试随意输入用户名 123 和密码 123 登录,发现提示错误。
(4)按照第一个实验的思路,我们尝试在用户名中输入 123' or 1=1 #, 密码同样输入 123' or 1=1 # :
为什么能够成功登陆呢?因为实际执行的语句是:
select * from users where username='123' or 1=1 #' and password='123' or 1=1 #'
按照 Mysql 语法,# 后面的内容会被忽略,所以以上语句等同于(实际上密码框里不输入任何东西也一样):
select * from users where username='123' or 1=1
由于判断语句 or 1=1 恒成立,所以结果当然返回真,成功登录。
(5)再尝试不使用 # 屏蔽单引号,采用手动闭合的方式:我们尝试在用户名中输入 123' or '1'='1, 密码同样输入 123' or '1'='1 (不能少了单引号,否则会有语法错误):
实际执行的 Sql 语句是:
select * from users where username='123' or '1'='1' and password='123' or '1'='1`