漏洞大致分为SQL注入、XSS、文件操作、代码/命令执行、变量覆盖以及逻辑处理等等,这些都是常见的Web漏洞。 什么是魔术引号: 魔术引号是程序自动将进入PHP脚本的数据进行转义的过程。当打开时,所有的单引号、双引号、反斜杠和NULL字符都会被自动加上一个反斜杠进行转义。其效果和addslashes()函数的效果一致。
1、SQL注入漏洞
SQL注入漏洞是目前被利用得最多得漏洞,SQL注入漏洞的原理非常简单,由于开发者在编写操作数据库代码时,直接将外部可控的参数拼接到SQL语句中,没有经过任何过滤就直接放入到数据库引擎执行。
通常利用SQL注入攻击方式有下面几种: 一是在权限比较大的情况下,通过SQL注入可以直接写入webshell,或者直接执行系统命令等。 二是在权限比较小的情况下,通过注入来获取管理员的密码等信息,或者修改数据库内容进行一些钓鱼或者其他间接利用。
sqlmap是目前被使用最多的注入工具,这是一款用Python开发的国外开源跨平台SQL注入工具,支持多种方式以及几乎所有类型的数据库注入,对SQL注入漏洞的兼容性较强。
①普通注入 指最容易利用的SQL注入漏洞,比如直接通过注入union查询就可以查询数据库,一般的SQL注入工具也能够非常好地利用。
简单测试如下:
 
②编码注入 程序在进行一些操作之前经常会进行一些编码处理,而做出编码处理地函数也是存在问题地,通过输入转码函数不兼容地特殊字符,可以导致编码输出的字符变成有害数据,在SQL注入里,最常见的编码注入是MySQL宽字节以及urldecode/rawurldecode函数导致的。 Ⅰ、宽字节注入 在使用PHP连接MySQL的时候,当设置“set character_set_client=gbk”时会导致一个编码转换的注入问题,也就是宽字节注入,当存在宽字节注入漏洞时,注入参数里带入%df%27,即可把程序中过滤的\(%5c)吃掉。举个例子,假设/1.php?id=1里面的id参数存在宽字节注入漏洞,当提交/1.php?id=-1’ and 1=1%23时,MySQL运行的SQL语句为select * from user where id = ‘1\’ and 1=1#’很明显,这是没有注入成功的,我们提交的单引号被转义导致没有闭合前面的单引号,但是我们提交/1.php?id=-1%df’ and 1=1%23时,这时候MySQL运行的SQL语句为:select * from user where id=’1運’ and 1=1#’。这是因为单引号被自动转义成\’,前面的%df和转义字符\放斜杠(%5c)组成了%df%5c,也就是“運”,这时候单引号还存在,于是成功闭合了前面的单引号。 出现这个漏洞的原因是在PHP连接MySQL的时候执行了如下设置: set character_set_client=gbk 告MySQL服务器客户端来源数据编码是GBK,然后MySQL服务器对查询语句进行GBK转码导致放斜杠\被%df吃掉,而一般都不是直接设置character_set_client=gbk,通常的设置方法是SET NAMES ‘gbk’,但其实SET NAMES ‘gbk’不过是比character_set_client=gbk多干了两件事而已,SET NAMES ‘gbk’等同于如下代码: 
解决该漏洞的几种方法: 1)在执行查询之前先执行SET NAMES ‘gbk’,character_set_client=binary设置character_set_client为binary。(推荐) 2)使用mysql_set_charset(‘gbk’)设置编码,然后使用mysql_real_escape_string()函数被参数过滤。 3)使用pdo方式,在PHP5.3.6及以下版本需要设置setAttribute(PDO::ATTR_EMULATE_PREPARES,false):来禁用prepared statements的仿真效果。(推荐)
对宽字节注入进行一个简单测试如下  
对宽字节注入的挖掘方法,只需要搜索以下几个关键字即可:

Ⅱ、二次urldecode注入 只要字符被进行转换就有可能产生漏洞,现在的Web程序大多都会进行参数过滤,通常使用addslashes()、mysql_real_escape_string()、mysql_escape_string()函数或者开启GPC的方式来防止注入,也就是给单引号、、双引号、放斜杠和NULL加上反斜杠转义。如果某处使用了urldecode或者rawurldecode函数,则会导致二次解码生成单引号而引发注入。原理是我们提交参数到WebServer时,WebServer会自动解码一次,假设目标程序开启了GPC,我们提交/1.php?id=1%2527,因为我们提交的参数里面没有单引号,所以第一次解码后的结果是id=1%27,%25解码的结果是%,如果程序里面使用了urldecode或者rawurldecode函数来解码id参数,则解码后的结果是id=1’,单引号成功出现并语法注入。 测试代码:  
挖掘方法: 搜索urldecode和rawurldecode函数来挖掘二次urldecode注入漏洞。
③漏洞防范 SQL注入漏洞虽然是目前最泛滥的漏洞,不过要解决SQL注入漏洞其实还比较简单。在PHP中可以利用魔术引号来解决,但是魔术引号在PHP5.4后被取消,并且gpc在遇到int型的注入时也会显得不那么给力,所以常用的还是过滤函数和类,像discuz、dedecms、phpcms等程序里面都使用过滤类,不过单纯的过滤函数写得不够严谨,还是会出现绕过的情况。因此,最好的方法还是利用预编译的方式。
④PDO prepare预编译 
以上的代码虽然使用的是预编译,但是当PHP版本在5.3.6之前还是存在宽字节SQL注入漏洞,因为这样的查询方式是使用PHP本地模拟prepare,再吧完整的SQL语句发送到MySQL服务器,并且有使用set names ‘gbk’语句,所以会有PHP和MySQL编码不一致的原因导致SQL注入,正确的写法应该是使用ATTR_EMULATE_PREPARES来禁用PHP本地模拟prepare,代码如下: 
2、XSS漏洞
XSS学名为跨站脚本攻击,在Web漏洞中XSS是出现最多的漏洞。 这种漏洞有两种情况: 一种是通过外部输入然后直接在浏览器端触发,即反射型XSS; 另外一种则是先把利用代码保存在数据库或文件中,当Web程序读取利用代码并输出在页面上时触发漏洞,也就是存储型漏洞XSS。 XSS攻击在服务器端触发,用一句话来说明该漏洞的危害就是:前端页面能做的事它都能做。 ①挖掘经验 挖掘XSS漏洞的关键在于没有被过滤的参数,且这些参数传入到输出函数,常用的输出函数列表如下:print、print_r、echo、printf、sprintf、die、var_dump、var_export,所以我们只要寻找带有变量的这些函数即可。另外在代码审计中,XSS漏洞在浏览器环境对利用的影响非常大,所以最重要的还要掌握各种浏览器容错、编码等特性和数据协议。关于XSS的学习,可阅读邱永华《XSS跨站脚本攻击剖析与防御》和余弦《Web前端黑客技术揭秘》。 XSS漏洞比SQL注入更多,而且在满足业务需求的情况下更难防御。XSS漏洞经常出现在文章发表、评论回复、留言以及资料设置等地方,特别是在发表文章的时候,因为这里大多都是富文本,有各种图片引用、文字格式设置等,所以经常出现对标签事件过滤不严格导致的XSS,同样,评论回复以及留言也是如此。其次在资料设置的地方,比如用户昵称、签名等,有的应用可能不知一处设置资料的地方,像在注册的地方可以设置、修改资料的地方可以设置,这时候要多留意,不一定所有设置这资料的地方都严格过滤了。
②反射型XSS 反射型XSS也就是我们在描述里面说直接通过外部输入然后在浏览器输出触发的类型,这种类型的漏洞比较容易通过扫描器黑盒直接发现,只需将尖括号、单双引号等提交到Web服务器,检查返回的HTML页面里面有没有保留原来的特殊字符即可判断。但是在白盒审计中,我们只需要寻找带有参数的输出函数,然后根据输出函数对输出内容回溯输入参数,观察有没有经过过滤。 
代码中echo “sig:”.KaTeX parse error: Undefined control sequence: \n at position 25: …th_signature"."\?n?"];直接将_GET[“oauth_signature”."\n"]的值输出到浏览器中,则可以直接用GET方式注入代码。
③存储型XSS 存储型XSS,顾名思义就是需要先把代码保存在比如数据库或文件中,当Web程序读取利用代码并输出在页面上时执行利用代码,它的原理流程图如图所示: 
存储型XSS比放射型要容易利用得多,不用考虑绕过浏览器的过滤,另外在隐蔽性上也更好,特别是在社交网络中的存储型XSS蠕虫能造成大面积的传播,影响非常大,曾经在新浪微博和百度贴吧都爆发过大规模的XSS蠕虫。 同样,要挖掘存储型漏洞XSS也是要寻找未过滤的输入点和未过滤的输出函数,这最终的输出点可能跟输入点完全不在一个业务流上,对于这类可以根据当前代码功能去猜,或者老老实实去追哪里有操作过这数据,使用表名、字段名去代码里面搜索。
④漏洞防范 由于XSS漏洞在不同浏览器下有不同的利用方式,而且特别是业务上有需求使用富文本编辑器的时候,防御起来就更加复杂,所以在XSS防御这块应该从多个方面入手,尽量减少XSS漏洞。 Ⅰ、特殊字符HTML实体转码 一般的XSS漏洞都是因为没有过滤特殊字符,导致可以通过注入单引号以及尖括号等字符利用漏洞,比如一个图片标签下 ,则可以通过输入双引号来闭合第一个单引号利用漏洞。防御这类的XSS漏洞只需要过滤掉相关特殊字符即可,特殊字符列表如下: 1)单引号 2)双引号 3)尖括号 4)反斜杠 5)冒号 6)and符号 7)#号
还有两个问题,这些字符应该怎么过滤,什么时候过滤?为了保证数据原始性,最好的过滤方式是在输出和二次调用的时候进行如HTML实体一类的转码,防止脚本注入的问题。
Ⅱ、标签事件属性黑白名单 上面提到过滤特殊字符来防止XSS漏洞,实际上即使过滤了也同样可能会被绕过,比如利用跟宽字节注入一样的方式来吃掉反斜杠,再利用标签的事情来执行js代码,面对这样的情况,我们还得加标签事件的黑白名单,这里更推荐使用白名单,实现规则可以直接使用正则表达式来匹配,如果匹配到的事件不在白名单列表,就直接拦截掉,而不是替换为空。
3、CSRF漏洞
CSRF全称为跨站请求伪造。说白一点就是可以挟持其他用户去进行一些请求,而这个CSRF的危害性就看当前这请求是进行上面操作的了。 而CSRF是怎么进行攻击的呢?举一个例子,比如直接请求http://x.com/del.php?id=1可以删除ID为1的账号,但是只有管理员有这删除权限,而如果别人在其他某个网站页面加入<img src=”http://x.com/del.php?id=1”>再把这个页面发送给管理员,只要管理员打开这页面,同时浏览器也会利用当前登录的这管理员发出http://x.com/del.php?id=1这请求,从而劫持了这个账号做一些攻击者没有权限做的事情。 上面举的这例子只是其中一个场景,更严重的像添加管理员账号、修改网站配置直接写入webshell等等都有很多案例。
①挖掘经验 CSRF主要是用于越权操作,所有漏洞自然在有权限控制的地方,像管理后台、会员中心、论坛帖子以及交易管理等,这几个场景里面,管理后台又是最高危的地方,而CSRF又很少被关注到,因此至今还有很多程序都存在这问题。我们在挖掘CSRF的时候可以先搭建好环境,打开几个有非静态操作页面,抓包看看有没有token,如果没有token的话,再直接请求这个页面,不带referer。如果返回的数据还是一样的话,那说明很有可能有CSRF漏洞了,这是一个黑盒的挖掘方法;从白盒角度看,只要读代码的时候看看几个核心文件里面有没有验证token和referer相关的代码,这里的核心文件指的是被大量文件引用的基础文件,或者直接搜”token”这关键字也能找,如果在核心文件没有,再去看看你比较关心的功能点的代码有没有验证。
②Token验证 Token翻译中文为“标志”,在计算机认证领域叫做令牌。利用验证Token的方式是目前使用的最多的一种,也是效果最好的一种,可以简单理解成在页面或者cookie里面加一个不可预测的字符串,服务器在解释操作亲求的时候只要验证下这字符串是不是上一次访问留下的即可判断是不是可信请求,因为如果没有访问是一个页面是无法得到这个Token的,除非结合XSS漏洞或者有2其他手段能够获取通信数据。 Token实现测试代码如下: 
运行结果,如果请求里面的Token值跟服务器端的一致,则输出“success”,否则则输出“failed”。
③验证码验证: 验证码验证没有Token那么实用,考虑到用户体验,不可能让每个用户在每个页面都去输入一次验证码,因此一般这种方式只用在敏感操作的页面,比如登录页面,实现的方式跟Token差不多,这里不在给出代码。
|