设为首页 - 加入收藏
广告 1000x90
您的当前位置:皮皮彩票app下载 > 标准输出流 > 正文

浅谈PHP安全规范

来源:未知 编辑:admin 时间:2019-04-13

  php因天生支持web应用的开发,以其简单易学,开发效率高而备受喜爱。使其占据了大片的市场。但是php本身的安全问题却一直不曾消停,以及不规范的php代码编写规范,使得web应用漏洞百出。这篇文章从配置文件和代码编写角度出发,总结记录php相关安全。新手上路,向前辈致敬。

  注意到以下的文件结构在新版本php或者不同的发行版中略有不同,就好比在ubuntu18.04中安装php7就和下面的文件结构有较大的差别,所以下面的文件仅仅作为一个apache的架构参考。

  关于安全模式和粗暴的魔术引号过滤,注意到save_mode模式在php5.3以上版本,safe_mode被弃用,在php5.4以上版本,则将此特性完全去除了:

  “:反引号运算符在激活了安全模式或者关闭了 shell_exec() 时是无效的,同时与其它某些语言不同,反引号不能在双引号字符串中使用。否则将会当作shell命令执行,执行效果等同于shell_exec()。

  前人之述备矣,仅仅做个汇总。同样还可以参看官网给出的类型表(PHP 类型比较表)。

  如果已经弃用的 register_globals 指令被设置为 on 那么局部变量也将在脚本的全局作用域中可用。例如, $_POST[foo] 也将以 $foo 的形式存在。这将会造成一些变量覆盖,条件判断绕过。以下是简化的全局变量认证绕过模型:

  伪协议在很多绕过场景下发挥着举足轻重的作用,如后面提到的文件包含file://协议绕过,以及最近才提出的phar协议反序列化对象注入,我们可以在不存在可控unserialization()函数的情况下利用phar反序列化对象,实现对象注入。所以在web应用中不要忽视他们的存在,千里之堤,溃于蚁穴。

  在这个例子中,是最low安全等级的php代码编写样例,可以看到,代码中并没有对用户输入的id变量进行检查和过滤,同时使用的是$_REQUEST全局数组的方式,如果不是特别需要,我们编程的时候尽量不要使用$_REQUEST获取用户的参数,因为$_REQUEST的参数比较杂,包括$_GET,$_POST,$_COOKIE等超全局变量,并且二者还存在变量获取顺序的不一致,受配置文件中variables_order的约定,在存在waf的环境下,容易造成绕过。未经处理的用户输入直接与sql语句拼接交互,造成sql注入漏洞,十分危险。

  这个版本的代码,与之前的相比只是多了个mysql_real_escape_string函数的过滤,但是要知道这里的$id在sql语句中是数字类型,这样mysql_real_escape_string的转义就会形同虚设,注入仍旧是一马平川。当然不恰当的字符编码,可能会造成宽字节注入。

  在高级版本中只是把注入点隐匿在了$_SESSION全局变量里面,而session中的id值的注册是通过用户输入$_POST全局变量传入,所以是完全可控的,这样一来,就和之前的注入没有什么不一样。这段代码是要提醒我们对于session,只要注册值是用户可控的,也是可能存在sql注入的风险的。另外需要注意到的是,在这个High级别的注入中,回显和传参页面不是同一个,是一个二阶注入,如果使用工具注入,如sqlmap,别忘了加上自定义回显–second-order参数。

  根据DVWA的说法,这样写出来的应用,是不存在sql注入的。也即这是个十分安全的php代码编写规范。why?首先,我们可以看到它使用Anti-CSRF token的方法来避免csrf攻击(具体细节会在下文csrf防御谈到),然后在sql语句的编写中,使用的是预处理语句,所谓的预处理就是通过php的pdo预处理机制PDO::prepare,先往数据库送出语句模板,进行解析,编译,然后第二次向数据库传入查询参数,在第二次的查询过程中可以理解为不再进行语义解析,所以即使传入sql语句,也会因为不进行语义解析而失效。所以这是一种比较推荐的数据库交互sql语句编写规范。现在很多主流的数据库已经支持预处理,即使不支持,PHP的PDO也会进行预处理模拟实现,这样对于程序员接口一致,不需了解不同数据库对预处理支持的方式差异。

  所谓的CSRF(Cross-site request forgery)直白的翻译就是跨站点请求伪造。说人话就是攻击者通过诱使victim访问其精心构造的url或者访问其精心构造的页面,来使得攻击者可以以victim的身份做诸如发邮件,发消息,改密码等骚操作。在DVWA这个系列里面,模拟的是修改密码的界面。先来看下low等级的代码,可以说是没有进行仍和的再认证,试下为啥是“再认证”?其实我们在访问到这个修改密码界面的时候,已经登陆过一次,服务器会在每次访问时检查session。所以这是第一道认证。但是这种会话级别的认证对csrf是没有抵抗力的。具体的过程可以参看之前提到的链接。我们可以直接构造url: 。

  来实现欺骗隐匿行踪,达到修改密码的目的。顺便盗用两个别人的poc方便展示:

  在这个级别的CSRF漏洞中,服务端多了一句eregi( $_SERVER[ SERVER_NAME ], $_SERVER[ HTTP_REFERER ]校验,ereg()函数是模式匹配,通过超全局数组获取了请求头referer值(也就是访问者向host发起请求时所在的页面)和host值,并且检查host的值是否在referer中出现。根据权威 (),这两个值无法以编程的方式修改,抓包除外,因为在csrf中无法通过抓取客户端的包进行修改,所以按理来说是安全的。实则不然,通过公网服务器,诱使victim访问名字包含host的html文件就可以实现绕过。

  在高级别中的代码,主要是使用了Anti-csrf机制,用户每次访问改密页面时,服务器会返回一个随机的token,向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求。我们可以按F12来看看这个token:

  可以看到不同的用户会返回一个不同的token,这个token在hidden栏里面,这样一来,迫于同源策略,攻击者无法获取victim的token,也就无法实现CSRF攻击。但是真的无法实现吗?配合xss我们还是可以盗取token的,但是这难度无疑增大,我们必须要有服务器的一个xss漏洞来盗取token,然后再使用CSRF。攻击成本也增大。

  在high的基础上,直接进行了密码再认证,这样一来,即使盗取了token,没有原始密码,也无法进行修改密码的操作,这样CSRF就可以完全避免了。所以通过这个CSRF系列,我们可以知晓,在csrf防御中,采用关键操作的原子性认证,是避免这一漏洞攻击的不二办法。其实我们只关注了CSRF部分,在之前的level中,也还存在了sql注入,在这个impossible版本里,还使用了之前提到的预操纵来进行数据库交互,降低了sql注入的风险。

  过分相信用户的输入,直接拼接到ping 命令中,会造成命令注入。注意到常用的bash命令拼接的方式有.&&,,这五个,所以由于没有过滤完全,我们直接进行命令拼接,然后执行任意命令,如127.0.0.1;cat /etc/passwd。

  这里采用黑名单过滤的方式,注意到黑名单的办法存在的通病就是过滤不完全。可以看到这里也一样,没有把之前提到的东西给过滤完全。其实highlevel也是一样的,过滤语句写得不严谨,多加了空格,造成绕过,这里就不再展开叙述了。同过这个例子可以直观的看到黑名单式过滤方式是不安全的,容易出岔子。接着我们将看到Impossible等级下的白名单试想方式。直接指定只接受num.num.num.num型的输入,也就是我们期望的输入,从而避免了命令执行。

  暴力枚举攻击,服务端没有在后台设置错误次数上限和相关校验,就会给攻击者暴力枚举用户或者基于字典的密码暴力破解。所以正确的代码编写规范需要规定容许的错误尝试次数,超过这个值就会锁定账户一个定义长的时间。这里需要明确,光加入一个随机的token就想避免Brute Force是相当幼稚的,攻击者通过python脚本来抓取页面的token,就可以完全绕过,这也是high等级所犯的错。这里就不展示,只列出impossible等级和low 等级的代码,供对比阅读:

  我们可以看到,在impossible代码中,不但设置了错误次数锁,Anti-CSRF token,而且还提供了暴力尝试信息反馈,当用户登陆成功后会将被暴力登陆的次数给反馈给正确登陆的用户。这个实现得益于,每次错误尝试都会更新last_login的时间和failed_login+1操作,然后将之入库。

  include():只有代码执行到该函数时才会包含文件进来,发生错误时只给出一个警告并继续向下执行;

  include_once():和include()功能相同,区别在于当重复调用同一文件时,程序只调用一次。

  require():只要程序执行就包含文件进来,发生错误时会输出错误结果并终止运行;

  require_once():和require()功能相同,区别在于当重复调用同一文件时,程序只调用一次。

  文件包含光从字面意思来看是可以通过漏洞利用泄露一些本地敏感文件,但是益于以上几个函数在包含文件的时候是默认把文件当成代码来对待,如果出现可执行的php片段就会执行这一性质,文件包含漏洞一般是可以进行任意代码执行的,只要我们能够让服务器包含我们可控的代码段。

  没有对我们的输入做任何过滤,可以说是一点安全意识都没有。随便利用。举个栗子:[。当然也可以在服务端写下poc.php,利用http协议实现代码执行[ 。前提条件是allow_url_fopen和allow_url_include处于打开状态。

  首先这个基于黑名单的过滤,压根就没有把本地绝对路径考虑到,其次可以使用…/./,htthttpp进行绕过。

  这是一种基于白名单的过滤,只接受前缀为“file”的文件,咋一看很ok,然而却疏忽了file协议。[。

  这是相当的白名单,你赢了。但是想要文件量巨大的场景中维护这么一张白名单有点不太理智,所以笔者这种硬编码的方式不太常用。

  上传漏洞经常可以用来上传任意代码泄露系统信息,如,甚至可以直接上传webshell,拿下服务器权限,所以这个漏洞是十分严重的。

  可以看到上面的代码对用户上传的文件($_FILE全局数组的形式)没有进行任何的验证操作,就直接将其move到了upload目录,这是相当危险的操作,攻击者可以毫无忌惮的随意日。

  上面的代码加入了MIME判断,所谓的MIME判断是在请求头中的一个字段,用来指示文件类型,方便服务器进行对应的处理,只要抓包就可以随意修改,达到欺骗服务器的目的。(更多的解释可以查看:)

  首先判断文件名结尾是不是’jpg’,jepg’,png’类型,然后调用getimagesize()函数获取图像大小,其实就是判断图像格式是否规范。

  函数细节可以参看官网表述:。 然后文件大小也进行了判断。所以这里主要存在两个限制条件,首先必须以特定文件名结尾,然后文件格式还得满足特定的图片格式。但是这样的代码虽然加大攻击难度,在一些条件成立的条件下,仍旧可以进行攻击,上传shell,首先图片格式可以伪造,在元数据中包含webshell,然后找到一个文件包含漏洞,就可以成功实现攻击,上传shell。

  这个代码规范里,除了有之前所说的一些限制外,还加上了随机id与文件名结合MD5编码作为文件名,这会让webshell连接的时候找不到具体的文件而吃闭门羹。而且使用了imagecreatefromjpeg()函数来对上次的图进行了重构,去除了多余的元数据,使得webshell无法隐匿在图片里面。这样一来双重保险下,彻底断绝了upload漏洞的可能。当然这里仍旧加入了Anti-CSRFtoken来防止CSRF攻击。

  反射型xss是一种attack通过操作url,web应用将attack输入的url参数不加过滤或者过滤不全的情况下直接回显到客户端,造成前端脚本注入执行(多是JS执行),读者可以通过以下的实例看到漏洞的产生细节。当然在反射型xss中有一种别具一格的漏洞利用方式,那就是DOM型xss,这种类型的xss不会直接出现拼接到源码中,而是js在运行时操作dom对象来实现输出。DVWA只对xss笼统的归纳,归纳为反射型和存储型。那么我们就先对这两种编码规范进行理解(把dom 型xss放一放)。由于本身的代码量不大,所以直接给出所有反射型代码如下:

  通过以上的代码范例可以看到,在medium和high的防御措施上,仍旧是黑名单式的过滤,而且思考的很狭隘,只是过滤了返回搜狐,查看更多

本文链接:http://thacba.net/biaozhunshuchuliu/199.html

相关推荐:

网友评论:

栏目分类

现金彩票 联系QQ:24498872301 邮箱:24498872301@qq.com

Copyright © 2002-2011 DEDECMS. 现金彩票 版权所有 Power by DedeCms

Top