航天科技Web安全的SQL注入攻击技巧和预防

Web安全简史

每当Web1.0时代,人们又多是关心服务器端动态脚本语言的安康问题,比如用一个不过尽脚本(俗称Webshell)通过脚本语言的纰漏上传到服务器上,从而获取服务器权限。在Web发展初,随着动态脚本语言的前行和推广,以及早期工程师对安全题材认知不足造成众多”安全血案”的发,至今还遗留下许多历史题材,比如PHP语言至今还是鞭长莫及从言语本身杜绝「文件包含漏洞」(参见这里),只能依靠工程师可以的代码规范以及安康意识。

陪着Web2.0、社交网络、微博等同样多样新型互联网产品的起来,基于Web环境之互联网采用更加普遍,Web攻击的招数也更为多样,Web安全史上之一个重要里程碑是横1999年察觉的SQL注入攻击,之后的XSS,CSRF等攻击手段进一步强大,Web攻击的思绪也自服务端转向了客户端,转向了浏览器和用户。

每当安康世界,一般用帽子的颜料来比喻黑客的易与恶,白帽子是据那些工作以倒黑客领域的技艺专家,这个部落是”善”的之表示;而黑帽子则是依赖那些使用黑客技术造成损坏还谋取私利造成违法之部落,他们是”恶”的意味。

“白帽子”和”黑帽子”是零星个精光对立的群落。对于黑帽子而言,他们而找到网的一个切入点就可直达入侵破坏的目的,而白帽子必须以自己系统有或让突破的地方还设防,以保证系统的平安运行。

马上看起好像是免公正的,但是安全世界里的平整就是是如此,可能咱们的网站1000处还布防的死去活来好,考虑的非常到,但是若有一个地方疏忽了,攻击者就会使这个点展开突破,让我们另外的1000高居努力白费。

广攻击方式

日常,在Web安全领域,常见的攻击方式大概有以下几种:
1、SQL注入攻击
2、跨站脚论攻击 – XSS
3、跨站伪造请求攻击 – CSRF
4、文件及污染漏洞攻击
5、分布式拒绝服务攻击 – DDOS

说个写外话,本来就首文章一开始的标题叫做
「Web安全之常表现攻击方法和防范」,我原本想将地方的就5种植艺术还满形容于平首稿子里,可是正写了第一单SQL注入攻击的下,就意识文章篇幅都休短缺了,又老为难还展开大的简短,所以干脆将Web安全分成一个名目繁多,分多首稿子来展现给大家,下面你盼的哪怕是首先首「Web安全之SQL注入攻击的技术及防范」。

SQL注入常见攻击技巧

SQL注入攻击是Web安全史上之一个重大里程碑,它由1999年首浅上人们的视线,至今都生十几年之史了,虽然我们现在已起矣要命周全的警备对策,但是其的威力依然拒绝小视,SQL注入攻击至今仍是Web安全领域受到的一个着重部分。

坐PHP+MySQL为条例,让咱们为一个Web网站中最为中心的用户系统来举行实例演示,看看SQL注入究竟是怎发的。

1、创建一个称为也demo的数据库:
<pre>
CREATE DATABASE demo DEFAULT CHARACTER SET utf8 COLLATE
utf8_general_ci;
</pre>

2、创建一个号称也user的数据表,并插入1长演示数据:
<pre>
CREATE TABLE demo.user (
uid INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT
‘用户uid’,
username VARCHAR( 20 ) NOT NULL COMMENT ‘用户名’,
password VARCHAR( 32 ) NOT NULL COMMENT ‘用户密码’
) ENGINE = INNODB;
INSERT INTO demo.user (uid, username, password) VALUES (‘1’,
‘plhwin’, MD5(‘123456’));
</pre>

实例一

由此传播username参数,在页面打印出这会员的详细信息,编写
userinfo.php 程序代码:

<pre>
<?php
header(‘Content-type:text/html; charset=UTF-8’);
$username = isset($_GET[‘username’]) ? $_GET[‘username’] : ”;
$userinfo = array();
if($username){
//使用mysqli驱动连接demo数据库
$mysqli = new mysqli(“localhost”, “root”, “root”, ‘demo’);
$sql = “SELECT uid,username FROM user WHERE username='{$username}'”;
//mysqli multi_query 支持实施多长达MySQL语句
$query = $mysqli->multi_query($sql);
if($query){
do {
$result = $mysqli->store_result();
while($row = $result->fetch_assoc()){
$userinfo[] = $row;
}
if(!$mysqli->more_results()){
break;
}
} while ($mysqli->next_result());
}
}
echo ‘<pre>’,print_r($userinfo, 1),'</pre>’;
</pre>

地方是序一旦贯彻之功用是基于浏览器传入的用户称参数,在页面及打印出之用户之详细信息,程序写的这样复杂是为自利用了mysqli的让,以便能够用到
multi_query
方法来支持而施行多长长的SQL语句,这样会还好之证明SQL注入攻击的危害性。

如我们得经 http://localhost/test/userinfo.php?username=plhwin
这个URL来走访到实际有会员的详情,正常情况下,如果浏览器里不胫而走的username是官的,那么SQL语句会实行:

<pre>
SELECT uid,username FROM user WHERE username=’plhwin’
</pre>

然,如果用户在浏览器里拿传播的username参数变为
plhwin';SHOW TABLES-- hack,也就算是当URL变为
http://localhost/test/userinfo.php?username=plhwin';SHOW TABLES-- hack
的上,此时我们先后实际履行的SQL语句变成了:

<pre>
SELECT uid,username FROM user WHERE username=’plhwin’;SHOW TABLES–
hack’
</pre>

只顾:在MySQL中,最后连的有数独减号表示忽略这个SQL减号后面的说话,我本机的MySQL版本号为5.6.12,目前几有SQL注入实例都是一直行使简单独减号结尾,但是事实上测试,这个版号的MySQL要求少单减号后面要要来空格才会健康注入,而浏览器是碰头自行删除掉URL尾部空格的,所以我们的流入会在片单减号后面统一上加任意一个字符或单词,本篇文章的SQL注入实例统一为
-- hack 结尾。

透过地方的SQL注入后,原本想要推行查询会员详情的SQL语句,此时还额外执行了
SHOW TABLES;
语句,这眼看不是开发者的本意,此时得以当浏览器里看看页面的输出:

<pre>
Array
(
[0] => Array
(
[uid] => 1
[username] => plhwin
)

[1] => Array
    (
        [Tables_in_demo] => user
    )

)
</pre>

汝能够清晰的看,除了会员的音,数据库表的讳user为给打印在了页面及,如果滋事的黑客此时以参数换成
plhwin';DROP TABLE user-- hack,那以产生灾难性的不得了结果,当您以浏览器中履行
http://localhost/test/userinfo.php?username=plhwin';DROP TABLE user-- hack
这个URL后,你晤面发现全 user 数据表都消失不见了。

由此上面的事例,大家早就认及SQL注入攻击的危害性,但是仍会有人心里存问题,MySQL默认驱动的mysql_query道现在都不支持多长语句以施行了,大部分开发者怎么可能像上面的演示程序那样以麻烦而休安全。

是的,在PHP程序中,MySQL是休允以一个mysql_query被采取分号执行多SQL语句的,这使森开发者都看MySQL本身就是不允许多语句子执行了,但骨子里MySQL早于4.1版就同意多告知句执行,通过PHP的源代码,我们发现实际只有是PHP语言自身限制了这种用法,具体情况大家可以看就首稿子「PHP+MySQL多报句执行」。

实例二

若果系统非允许以实施多长条SQL语句,那么SQL注入攻击是未是不怕不再这样可怕啊?答案是否认的,我们还以点的user数据表,用Web网站中常用的会员登录系统来做另外一个面貌实例,编写程序login.php,代码如下:

<?php
if($_POST){
$link = mysql_connect(“localhost”, “root”, “root”);
mysql_select_db(‘demo’, $link);
$username = empty($_POST[‘username’]) ? ” :
$_POST[‘username’];
$password = empty($_POST[‘password’]) ? ” :
$_POST[‘password’];
$md5password = md5($password);
$sql = “SELECT uid,username FROM user WHERE username='{$username}’ AND
password='{$md5password}'”;
$query = mysql_query($sql, $link);
$userinfo = mysql_fetch_array($query, MYSQL_ASSOC);
if(!empty($userinfo)){
//登录成功,打印出会员信息
echo ‘<pre>’,print_r($userinfo, 1),'</pre>’;
} else {
echo “用户称不存在或者密码错误!”;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset=”utf-8″>
<title>Web登录系统SQL注入实例</title>
</head>
<body>
<form name=”LOGIN_FORM” method=”post” action=””>
登录帐号: <input type=”text” name=”username” value=”” size=30
/><br /><br />
登录密码: <input type=”text” name=”password” value=”” size=30
/><br /><br />
<input type=”submit” value=”登录” />
</form>
</body>
</html>

这若是输入正确的用户名 plhwin 和密码 123456,执行的SQL语句为:

<pre>
SELECT uid,username FROM user WHERE username=’plhwin’ AND
password=’e10adc3949ba59abbe56e057f20f883e’
</pre>

面语句没有外问题,可以见见页面打印出了登录成功后的会员信息,但若起捣蛋鬼输入的用户称也
plhwin' AND 1=1-- hack,密码任意输入,比如aaaaaa,那么拼接之后的SQL查询语句就变成了如下内容:
<pre>
SELECT uid,username FROM user WHERE username=’plhwin’ AND 1=1– hack’
AND password=’0b4e7a0e5fe84ad35fb5f95b9ceeac79′
</pre>

履方的SQL语句,因为1=1凡是永远成立的口径,这表示黑客只待掌握别人的会员名,无需了解密码便可知顺风登录到网。

争规定SQL注入漏洞

经过上述之实例,我们仍还见面时有发生疑难:黑客并不知道我们程序代码的逻辑与SQL语句之写法,他是怎么样规定一个网站是否在SQL注入漏洞也?一般说来有以下2种途径:

1、错误提示

一经目标Web网站开启了错误显示,攻击者就足以经过反复调整发送的参数、查看页面打印的错误信息,推测出Web网站使用的数据库及支付语言等重要消息。

2、盲注

惟有运维人员大意,否则大部分的Web运营网站该还关门了错误提示信息,此时攻击者一般会以盲注的技术来进展多次的品味判断。
仍然为点的数据表user为条例,我们事先的查看会员详情页面的url地址为userinfo.php?username=plhwin,此时黑客分别走访userinfo.php?username=plhwin' AND 1=1-- hackuserinfo.php?username=plhwin' AND 1=2-- hack,如果前者访问能够回来正常的音讯一旦后人不可知,就核心可判明这个网站是SQL注入漏洞,因为后者的1=2这个表达式永远不立,所以便username传入了对的参数为无法通过,由是可以想见是页面是SQL注入漏洞,并且可以经username参数进行注入。

什么样防御SQL注入

对服务器配置范围的备,应该保证生产条件之Webserver是关错误信息的,比如PHP在产环境的布置文件php.ini中之display_errors应该设置也Off,这样即使倒闭了错误提示,下面我们又多之打编码的角度来探哪预防SQL注入。

地方用简单只实例分析了SQL注入攻击的技巧,可以观看,但凡有SQL注入漏洞的顺序,都是盖程序一旦承受来自客户端用户输入的变量或URL传递的参数,并且是变量或参数是结合SQL语句的相同部分,对于用户输入的情节还是传递的参数,我们理应使天天保持警惕,这是高枕无忧世界里的「外部数据不可相信」的准,纵观Web安全世界的各种攻击方式,大多数还是盖开发者违反了这个标准而导致的,所以本来能想到的,就是由变量的检测、过滤、验证下手,确保变量是开发者所预期的。

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

倘您的SQL语句是近似where id={$id}这种形式,数据库里所有的id都是数字,那么即使该当SQL被实施前,检查确保变量id是int类型;如果是受邮箱,那便相应检查并严厉保证变量一定是邮箱的格式,其他的种比如日期、时间相当呢是一个道理。总结起来:若果是发出固定格式的变量,在SQL语句执行前,应该严格以固定格式去检查,确保变量是咱们预料的格式,这样大十分程度及可以免SQL注入攻击。

遵,我们前面接受username参数例子中,我们的产品设计应该是在用户注册之平等上马,就产生一个用户名的条条框框,比如5-20个字符,只能由大小写字母、数字以及一些安全的符号组成,不包含特殊字符。此时咱们应有来一个check_username的函数来进行联合的自我批评。不过,仍然有许多例外情况并无可知运用及当时同一规,比如文章发布系统,评论系统等要要允许用户提交任意字符串的场面,这虽需使用过滤等其他方案了。

2、过滤特殊符号

于无法确定固定格式的变量,一定要是开展特殊符号过滤或转义处理。以PHP为例,通常是采取addslashes函数,它会以指定的预约义字符前补加反斜杠转义,这些预定义的字符是:单引号 (') 双引号 (") 反斜杠 (\) NULL

来看2条SQL语句:
<pre>
$uid = isset($_GET[‘uid’]) ? $_GET[‘uid’] : 0;
$uid = addslashes(uid);
$sql = “SELECT uid,username FROM user WHERE uid='{$uid}'”;
</pre>
以及
<pre>
$uid = isset($_GET[‘uid’]) ? $_GET[‘uid’] : 0;
$uid = addslashes(uid);
$sql = “SELECT uid,username FROM user WHERE uid={$uid}”;
</pre>

地方两个查询语句都通过了php的addslashes函数过滤转义,但以安全性及可大不相同,在MySQL中,对于int类型字段的规格查询,上面只报告句之查询功能完全一样,由于第一句子SQL的变量被单引号包含起来,SQL注入的下,黑客面临的严重性问题是必使先关前面的单引号,这样才会要后面的言语作为SQL执行,并且还要注释掉原SQL语句被之末尾的单引号,这样才堪成功注入,由于代码里采取了addslashes函数,黑客的攻击会无从下手,但第二词没有用引号包含变量,那黑客也并非考虑去关掉、注释,所以尽管相同应用addslashes转义,也还是在SQL攻击漏洞。

对于PHP程序+MySQL构架的次序,在动态的SQL语句被,使用单引号把变量包含起来相当addslashes函数是应本着SQL注入攻击的实惠手法,但迅即做的还不够,像面的2条SQL语句,根据「检查数据类型」的规则,uid都应经过intval函数格式为int型,这样不但能够立竿见影避免第二漫长告句子之SQL注入漏洞,还会令程序看起更当,尤其是以NoSQL(如MongoDB)中,变量类型一定要是同字段类型相匹配才可以。

自打者可以望,第二单SQL语句是发尾巴的,不过出于用了addslashes函数,你晤面发现黑客的口诛笔伐语句也设有未可知利用特殊符号的法限制,类似where username='plhwin'如此这般的口诛笔伐语句是迫于执行之,但是黑客可以将字符串转为16进制编码数据或以char函数进行转发,同样能够达平等的目的,如果对当下有些情节感兴趣,可以点击这里翻。而且由于SQL保留重要字,如「HAVING」、「ORDER
BY」的存在,即使是冲黑白名单之过滤方法还是会起或多要丢失问题,那么是否还有其他艺术来防御SQL注入呢?

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

MySQL的mysqli令提供了预编译语句之支撑,不同之程序语言,都分别有利用预编译语句之方式,我们这边仍然因PHP为条例,编写userinfo2.php代码:

<pre>
<?php
header(‘Content-type:text/html; charset=UTF-8’);
$username = isset($_GET[‘username’]) ? $_GET[‘username’] : ”;
$userinfo = array();
if($username){
//使用mysqli驱动连接demo数据库
$mysqli = new mysqli(“localhost”, “root”, “root”, ‘demo’);
//使用问号替代变量位置
$sql = “SELECT uid,username FROM user WHERE username=?”;
$stmt = $mysqli->prepare($sql);
//绑定变量
$stmt->bind_param(“s”, $username);
$stmt->execute();
$stmt->bind_result($uid, $username);
while ($stmt->fetch()) {
$row = array();
$row[‘uid’] = $uid;
$row[‘username’] = $username;
$userinfo[] = $row;
}
}
echo ‘<pre>’,print_r($userinfo, 1),'</pre>’;
</pre>

于地方的代码可以看到,我们先后里并无用addslashes函数,但是浏览器里运行
http://localhost/test/userinfo2.php?username=plhwin' AND 1=1-- hack里得无交其它结果,说明SQL漏洞以此程序里并无存。

实际,绑定变量使用预编译语句是提防SQL注入的顶尖办法,使用预编译的SQL语句语义不会见产生反,在SQL语句被,变量用问号?代表,黑客就是本事再杀,也无从更改SQL语句的结构,像上面例子中,username变量传递的plhwin' AND 1=1-- hack参数,也特会当作username字符串来诠释查询,从根本上杜绝了SQL注入攻击的发出。

数据库信息加密安全

相信大家都还对2011年暴露的CSDN拖库事件记忆犹新,这件工作导致CSDN处在风口浪尖被大家痛骂的故即在于他们还公开存储用户的密码,这引发了科技界对用户信息安全尤为是密码安全之明明关切,我们当防止SQL注入的出的以,也应有未雨绸缪,说不定下一个深受拖库的哪怕是您,谁知道啊。

于Web开发被,传统的加解密大致可分成三种植:

1、对如加密:即加密方和解密方都采用同样的加密算法和密钥,这种方案的密钥的保留好主要,因为算法是当众的,而密钥是保密的,一旦密匙泄露,黑客还是可以随意解密。常见的相辅相成加密算法来:AESDES等。

2、非对如加密:即采用不同之密钥来进展加解密,密钥被分成公钥和私钥,用私钥加密的数码要运用公钥来解密,同样用公钥加密的数额必须用相应之私钥来解密,常见的匪对如加密算法有:RSA等。

3、不可逆加密:利用哈希算法使数码加密之后无法解密回原数据,这样的哈希算法常用的出:md5SHA-1等。

于咱们地方登录体系的示范代码中,$md5password = md5($password);由当时句代码可以看出下了md5的不可逆加密算法来储存密码,这也是大抵年来业界常用的密码加密算法,但是及时还是未安全。为什么也?

及时是坐md5加密有一个表征:同样的字符串经过md5哈希计算后转的加密字符串也是平等的,由于业界采用这种加密的艺术长期,黑客们为准备了投机强大的md5彩虹表来接向匹配加密前的字符串,这种用于逆向反推MD5加密的彩虹表在互联网及随处可见,在Google里使用md5 解密当第一词搜索,一下就能找到md5于线破解网站,把咱插入用户数量时的MD5加以密字符串e10adc3949ba59abbe56e057f20f883e填入进,瞬间虽会博得加密前的密码:123456。当然为并无是各一个且能学有所成,但可以得的凡,这个彩虹表会越来越健全。

因而,我们有迫切的需使重复好之办法对密码数据开展不可逆加密,通常的做法是为每个用户确定不同之密码加盐(salt)后,再混合用户的忠实密码进行md5加密,如以下代码:

<pre>
//用户注册上装的password
$password = $_POST[‘password’];
//md5加密,传统做法直接拿加密后底字符串存入数据库,但这不够,我们延续改善
$passwordmd5 = md5($password);
//为用户生成不同的密码盐,算法可以因自己事情的消而不同
$salt = substr(uniqid(rand()), -6);
//新的加密字符串包含了密码盐
$passwordmd5 = md5($passwordmd5.$salt);
</pre>

小结

1、不要轻易敞开生产条件中Webserver的不当显示。
2、永远不要相信来用户端的变量输入,有固定格式的变量一定要从严检查对应的格式,没有固定格式的变量需要对引号等特殊字符进行必要的过滤转义。
3、使用预编译绑定变量的SQL语句。
4、做好数据库帐号权限管理。
5、严格加密处理用户航天科技之机密信息。

发表评论

电子邮件地址不会被公开。 必填项已用*标注