如何对PHP程序中的常见漏洞进行攻击(下)
翻译:analysist(分析家)
来源:http://www.china4lert.org

如何对PHP程序中的常见漏洞进行攻击(下)

原著:Shaun Clowes <http://www.securereality.com.au/>
翻译:analysist <http://www.nsfocus.com/>

[库文件]
正如我们前面讨论的那样,include()和require()主要是为了支持代码库,因为我们一般是把一些经常使用的函数放到一个独立的文件中,这个独立的文件就是代码库,当需要使用其中的函数时,我们只要把这个代码库包含到当前的文件中就可以了。

最初,人们开发和发布PHP程序的时候,为了区别代码库和主程序代码,一般是为代码库文件设置一个“.inc”的扩展名,但是他们很快发现这是一个错误,因为这样的文件无法被PHP解释器正确解析为PHP代码。如果我们直接请求服务器上的这种文件时,我们就会得到该文件的源代码,这是因为当把PHP作为Apache的模块使用时,PHP解释器是根据文件的扩展名来决定是否解析为PHP代码的。扩展名是站点管理员指定的,一般是“.php”, “.php3”和“.php4”。如果重要的配置数据被包含在没有合适的扩展名的PHP文件中,那么远程攻击者很容易得到这些信息。

最简单的解决方法就是给每个文件都指定一个PHP文件的扩展名,这样可以很好的防止泄露源代码的问题,但是又产生了新的问题,通过请求这个文件,攻击者可能使本该在上下文环境中运行的代码独立运行,这可能导致前面讨论的全部攻击。

下面是一个很明显的例子:

In main.php:
<?php
  $libDir = "/libdir";
  $langDir = "$libdir/languages";

  ...

  include("$libdir/loadlanguage.php":
?>

In libdir/loadlanguage.php:
<?php
  ...

  include("$langDir/$userLang");
?>

当“libdir/loadlanguage.php”被“main.php”调用时是相当安全的,但是因为“libdir/loadlanguage”具有“.php”的扩展名,因此远程攻击者可以直接请求这个文件,并且可以任意指定“$langDir”和“$userLang”的值。
[Session文件]
PHP 4或更新的版本提供了对sessions的支持,它的主要作用是在PHP程序中保存页与页之间的状态信息。例如,当一个用户登陆进入网站,他登陆了这个事实以及谁登陆进入这个网站都被保存在session中,当他在网站中到处浏览时,所有的PHP代码都可以获得这些状态信息。

事实上,当一个session启动时(实际上是在配置文件中设置为在第一次请求时自动启动),就会生成一个随机的“session id”,如果远程浏览器总是在发送请求时提交这个“session id”的话,session就会一直保持。这通过Cookie很容易实现,也可以通过在每页提交一个表单变量(包含“session id”)来实现。PHP程序可以用session注册一个特殊的变量,它的值会在每个PHP脚本结束后存在session文件中,也会在每个PHP脚本开始前加载到变量中。下面是一个简单的例子:

<?php
  session_destroy(); // Kill any data currently in the session
  $session_auth = "shaun";
  session_register("session_auth"); // Register $session_auth as a session variable
?>

新版本的PHP都会自动把“$session_auth”的值设置为“shaun”,如果它们被修改的话,以后的脚本都会自动接受修改后的值,这对无状态的Web来说的确是种很不错的工具,但是我们也应该小心。

一个很明显的问题就是确保变量的确来自session,例如,给定上面的代码,如果后续的脚本是下面这样的话:

<?php
  if (!empty($session_auth))
   // Grant access to site here
?>

上面的代码假定如果“$session_auth”被置位的话,就是从session,而不是从用户输入来置位的,如果攻击者通过表单输入来置位的话,他就可以获得对站点的访问权。注意攻击者必须在session注册该变量之前使用这种攻击方法,一旦变量被放进了session,就会覆盖任何表单输入。

Session数据一般是保存在文件中(位置是可配置的,一般是“/tmp”),文件名一般是类似“sess_<session id>”的形式,这个文件包含变量名称,变量类型,变量值和一些其它的数据。在多主机系统中,因为文件是以运行Web服务器的用户身份(一般是nobody)保存的,因此恶意的站点拥有者就可以通过创建一个session文件来获得对其它站点的访问,甚至可以检查session文件中的敏感信息。

Session机制也为攻击者把自己的输入保存在远程系统的文件中提供了另一个方便的地方,对于上面的例子来说,攻击者需要在远程系统放置一个包含PHP代码的文件,如果不能利用文件上载做到的话,他通常会利用session为一个变量按照自己的意愿赋一个值,然后猜测session文件的位置,而他知道文件名是“php<session id>”,所以只需猜测目录,而目录一般就是“/tmp”。

另外,攻击者可以任意指定“session id”(例如“hello”),然后用这个“session id”创建一个session文件(例如“/tmp/sess_hello”),但是“session id”只能是字母和数字组合。

[数据类型]
PHP具有比较松散的数据类型,变量的类型依赖于它们所处的上下文环境。例如:“$hello”开始是字符串变量,值为“”,但是在求值时,就变成了整形变量“0”,这有时可能会导致一些意想不到的结果。如果“$hello”的值为“000”还是为“0”是不同的,empty()返回的结果也不会为真。

PHP中的数组是关联数组,也就是说,数组的索引是字符串型的。这意味着“$hello["000"]”和“$hello[0]”也是不同的。

开发程序的时候应该仔细地考虑上面的问题,例如,我们不应该在一个地方测试某个变量是否为“0”,而在另外的地方使用empty()来验证。

[容易出错的函数]
我们在分析PHP程序中的漏洞时,如果能够拿到源代码的话,那么一份容易出错的函数列表则是我们非常需要的。如果我们能够远程改变这些函数的参数的话,那么我们就很可能发现其中的漏洞。下面是一份比较详细的容易出错的函数列表:

<PHP代码执行>
require():读取指定文件的内容并且作为PHP代码解释
include():同上
eval():把给定的字符串作为PHP代码执行
preg_replace():当与“/e”开关一起使用时,替换字符串将被解释为PHP代码

<命令执行>
exec():执行指定的命令,返回执行结果的最后一行
passthru():执行指定命令,返回所有结果到客户浏览器
``:执行指定命令,返回所有结果到一个数组
system():同passthru(),但是不处理二进制数据
popen():执行指定的命令,把输入或输出连接到PHP文件描述符

<文件泄露>
fopen():打开文件,并对应一个PHP文件描述符
readfile():读取文件的内容,然后输出到客户浏览器
file():把整个文件内容读到一个数组中

译者注:其实这份列表还不是很全,比如“mail()”等命令也可能执行命令,所以需要自己补充一下。
[如何增强PHP的安全性]
我在上面介绍的所有攻击对于缺省安装的PHP 4都可以很好的实现,但是我已经重复了很多次,PHP的配置非常灵活,通过配置一些PHP选项,我们完全可能抵抗其中的一些攻击。下面我按照实现的难度对一些配置进行了分类:

*低难度
**中低难度
***中高难度
****高难度

上面的分类只是个人的看法,但是我可以保证,如果你使用了PHP提供的所有选项的话,那么你的PHP将是很安全的,即使是第三方的代码也是如此,因为其中很多功能已经不能使用。

**** 设置“register_globals”为“off”
这个选项会禁止PHP为用户输入创建全局变量,也就是说,如果用户提交表单变量“hello”,PHP不会创建“$ hello”,而只会创建“HTTP_GET/POST_VARS['hello']”。这是PHP中一个极其重要的选项,关闭这个选项,会给编程带来很大的不便。

*** 设置“safe_mode”为“on”
打开这个选项,会增加如下限制:
1.    限制哪个命令可以被执行
2.    限制哪个函数可以被使用
3.    基于脚本所有权和目标文件所有权的文件访问限制
4.    禁止文件上载功能
这对于ISP来说是一个伟大的选项,同时它也能极大地改进PHP的安全性。

** 设置“open_basedir”
这个选项可以禁止指定目录之外的文件操作,有效地消除了本地文件或者是远程文件被include()的攻击,但是仍需要注意文件上载和session文件的攻击。

** 设置“display_errors”为“off”,设置“log_errors”为“on”
这个选项禁止把错误信息显示在网页中,而是记录到日志文件中,这可以有效的抵制攻击者对目标脚本中函数的探测。

* 设置“allow_url_fopen”为“off”
这个选项可以禁止远程文件功能,极力推荐!

好了,文章到此为止了,如果你想了解一些其它的相关信息,请参考原文http://www.securereality.com.au/studyinscarlet.txt。

<全文完>

如何对PHP程序中的常见漏洞进行攻击(下)的更多相关文章

  1. PHP个人网站架设连环讲(一)

    先下一个OmnihttpdProffesinalV2.06,装上就有PHP4beta3可以用了。PHP4给我们带来一个简单的方法,就是使用SESSION(会话)级变量。但是如果不是PHP4又该怎么办?我们可以假设某人在15分钟以内对你的网页的请求都不属于一个新的人次,这样你可以做个计数的过程存在INC里,在每一个页面引用,访客第一次进入时将访问时间送到cookie里。以后每个页面被访问时都检查cookie上次访问时间值。

  2. PHP实现文件安全下载

    例如你希望客户要填完一份表格,才可以下载某一文件,你第一个想法一定是用"Redirect"的方法,先检查表格是否已经填写完毕和完整,然后就将网址指到该文件,这样客户才能下载,但如果你想做一个关于"网上购物"的电子商务网站,考虑安全问题,你不想用户直接复制网址下载该文件,笔者建议你使用PHP直接读取该实际文件然后下载的方法去做。feof){echofread;}fclose;}这样就可以用PHP直接输出文件了。

  3. 使用sockets:从新闻组中获取文章(三)

    >我们从服务器的这个新闻组中读取了最后的十篇文章,。也可以通过使用HEAD命令读取文章的头信息,或者使用BODY命令读取文章内容。>关于fclose()的更多信息,请参考http://www.php.net/manual/function.fclose.php结论在上文中,我们看到了怎样打开、使用然后关闭一个socket:连接到一个NNTP服务器,取回一些文章。使用POST命令发表文章也复杂不到哪儿去。下一步就是编写一个基于WEB的新闻组客户端了。这样,你有了一个基于web的搜索新闻组的程序了。

  4. ThinkPHP 5.x远程命令执行漏洞复现

    这篇文章主要介绍了ThinkPHP 5.x远程命令执行漏洞复现的方法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

  5. PHP默认安装产生系统漏洞

    当你下载PHP後,在它内含的安装文件中帮助了PHP在NTApacheWebServer的安装方式,其中的安装帮助会要你将底下这几行设置加到apache的httpd.conf设置文件中,而这个安装文件将导引你将你的系统门户大开。

  6. 怎样在UNIX系统下安装php3

    #cd/usr/src#tarxvzfapache_1.3.6.tar.gz(产生apache_1.3.6目录)#tarxvzfphp-3.0.8.tar.gz(产生php-3.0.8目录)#cdapache_1.3.6#./configure--prefix=/usr/local/apache(把Apache的安装目录定为/usr/local/apache)#cdphp-3.0.8#./conf

  7. python 多线程threading程序详情

    这篇文章主要介绍了python 多线程threading程序详情,Thread类表示在单独的控制线程中运行的活动,下文相关资料需要的小伙伴可以参考一下

  8. ftp类(example.php)

    flush();$ftp_ini_datei=$argv[1];require('./ftp_class.php');require($ftp_ini_datei);echo"\nCronjobstarted:";echodate("d.m.Y-H:i:s");echo"\n";$newftp=newmyftp;if(!$anonymous){$result=$newftp->connect($host,$user,$password);}else{$result=$newftp->connect($ho

  9. PHP分页显示制作详细讲解

    搞定了最重要的如何获取数据的问题以后,剩下的就仅仅是传递参数,构造合适的sql语句然后使用php从数据库内获取数据并显示了。

  10. 如何防止IE缓存jsp文件

    1,使用java提供的方法,在jsp或者servlet中都可以2,使用HTML标记,如下面:

随机推荐

  1. PHP个人网站架设连环讲(一)

    先下一个OmnihttpdProffesinalV2.06,装上就有PHP4beta3可以用了。PHP4给我们带来一个简单的方法,就是使用SESSION(会话)级变量。但是如果不是PHP4又该怎么办?我们可以假设某人在15分钟以内对你的网页的请求都不属于一个新的人次,这样你可以做个计数的过程存在INC里,在每一个页面引用,访客第一次进入时将访问时间送到cookie里。以后每个页面被访问时都检查cookie上次访问时间值。

  2. PHP函数学习之PHP函数点评

    PHP函数使用说明,应用举例,精简点评,希望对您学习php有所帮助

  3. ecshop2.7.3 在php5.4下的各种错误问题处理

    将方法内的函数,分拆为2个部分。这个和gd库没有一点关系,是ecshop程序的问题。会出现这种问题,不外乎就是当前会员的session或者程序对cookie的处理存在漏洞。进过本地测试,includes\modules\integrates\ecshop.php这个整合自身会员的类中没有重写integrate.php中的check_cookie()方法导致,验证cookie时返回的username为空,丢失了登录状态,在ecshop.php中重写了此方法就可以了。把他加到ecshop.php的最后面去就可

  4. NT IIS下用ODBC连接数据库

    $connection=intodbc_connect建立数据库连接,$query_string="查询记录的条件"如:$query_string="select*fromtable"用$cur=intodbc_exec检索数据库,将记录集放入$cur变量中。再用while{$var1=odbc_result;$var2=odbc_result;...}读取odbc_exec()返回的数据集$cur。最后是odbc_close关闭数据库的连接。odbc_result()函数是取当前记录的指定字段值。

  5. PHP使用JpGraph绘制折线图操作示例【附源码下载】

    这篇文章主要介绍了PHP使用JpGraph绘制折线图操作,结合实例形式分析了php使用JpGraph的相关操作技巧与注意事项,并附带源码供读者下载参考,需要的朋友可以参考下

  6. zen_cart实现支付前生成订单的方法

    这篇文章主要介绍了zen_cart实现支付前生成订单的方法,结合实例形式详细分析了zen_cart支付前生成订单的具体步骤与相关实现技巧,需要的朋友可以参考下

  7. Thinkphp5框架实现获取数据库数据到视图的方法

    这篇文章主要介绍了Thinkphp5框架实现获取数据库数据到视图的方法,涉及thinkPHP5数据库配置、读取、模型操作及视图调用相关操作技巧,需要的朋友可以参考下

  8. PHP+jquery+CSS制作头像登录窗(仿QQ登陆)

    本篇文章介绍了PHP结合jQ和CSS制作头像登录窗(仿QQ登陆),实现了类似QQ的登陆界面,很有参考价值,有需要的朋友可以了解一下。

  9. 基于win2003虚拟机中apache服务器的访问

    下面小编就为大家带来一篇基于win2003虚拟机中apache服务器的访问。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  10. Yii2中组件的注册与创建方法

    这篇文章主要介绍了Yii2之组件的注册与创建的实现方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下

返回
顶部