【问题标题】:Examples of vulnerable PHP code? [closed]易受攻击的 PHP 代码示例? [关闭]
【发布时间】:2010-12-19 11:33:27
【问题描述】:

好吧,我和一个朋友正在做一个关于 PHP 安全性的小型演示(虽然我并不真正喜欢 PHP),他让我找到一些易受攻击的 PHP 代码示例(一个容易受到 SQL 注入和所有其他问题的代码)攻击类型)。我想知道是否有任何网站包含好的和坏的代码片段显示你应该和不应该如何编码?

基本上我会将它们放入我们的网站,他会尝试破解它,然后我们将显示“正确”的网站,他会再次尝试破解它。

【问题讨论】:

    标签: php security


    【解决方案1】:

    SQL injection 很简单:

    $var = $_POST['var'];
    mysql_query("SELECT * FROM sometable WHERE id = $var");
    

    这很容易解决:

    $var = mysql_real_escape_string($_POST['var']);
    

    另一个常见的是XSS (cross site scripting)

    $var = $_POST['var'];
    echo "<div>$var</div>\n";
    

    允许您注入从您的站点运行的 Javascript。有几种处理方法,例如:

    $var = strip_tags($_POST['var']);
    

    $var = filter_var($_POST['var'], FILTER_SANITIZE_STRING);
    

    【讨论】:

    • 是的,基本上你永远不能信任用户输入,将其全部视为恶意输入并使用addslashes()strip_tags()htmlspecialchars() 进行转义。
    • strip_tags 不足以阻止 HTML 注入(想想属性值注入)。使用 FILTER_SANITIZE_STRING 修改请求数组是一种可怕的 hack,永远不应该使用。相反,通过在您放入 HTML 内容的每个字符串上调用 htmlspecialchars 来避免 HTML 注入。
    • 你可以用正则表达式解析它...
    • 现在这不公平 nickf,你知道这会引起我左眼无法控制的抽搐。
    • 请注意,mysql_real_escape_string 在这种情况下不会阻止注入。
    【解决方案2】:

    一个真正常见的初学者错误是在重定向后忘记终止脚本执行。

    <?php
    if ($_SESSION['user_logged_in'] !== true) {
        header('Location: /login.php');
    }
    
    omg_important_private_functionality_here();
    

    解决办法:

    if ($_SESSION['user_logged_in'] !== true) {
        header('Location: /login.php');
        exit();
    }
    

    在普通浏览器中测试时可能会忽略这一点,因为浏览器通常会跟随 Location 标头而不呈现任何脚本输出。

    【讨论】:

    • 对我来说可能还为时过早,但这里的漏洞是什么?
    • 可以忽略标头,php 脚本仍在执行。即使用户未登录,私有函数仍会执行。
    • header() 重定向可能不会立即生效,或者可以被故意忽略,从而暴露下面的私人数据。
    【解决方案3】:

    哦,孩子,你不会缺少例子。只要谷歌PHP tutorial,他们每个人都有足够的洞来填满阿尔伯特音乐厅。

    结果 1,w3schools。他们第一个包含用户输入的例子是什么?

    Welcome <?php echo $_POST["fname"]; ?>!<br />
    

    Bzzt。 HTML 注入,在每段示例代码中重复出现。他们的第一个数据库查询是什么?

    $sql="INSERT INTO Persons (FirstName, LastName, Age) VALUES ('$_POST[firstname]','$_POST[lastname]','$_POST[age]')";
    

    Bzzt。 SQL注入,你输了。接下来。

    结果 2,官方 PHP 教程。第一个输出变量的例子是什么?

    echo $_SERVER['HTTP_USER_AGENT'];
    

    Bzzt。 HTML 注入。这不是一个容易利用的方法,但仍然是在 php.net 的学习材料中重复出现的那种不好的做法。

    结果 3,tizag.com。第一个回显用户输入的例子是什么?

    echo "You ordered ". $quantity . " " . $item . ".<br />";
    

    Bzzt。

    结果 4,freewebmasterhelp.com。太基础了,无法包含太多内容,但仍然可以:

    print "Hello $name"; // Welcome to the user
    

    Bzzt。

    结果5,learnphp-tutorial.com。

    <title><?= $greeting ?> World!</title>
    

    Bz...

    我可以继续。

    难怪 PHP 代码的总体质量如此糟糕,而程序员正在学习这种可悲的垃圾?

    【讨论】:

    • 你是对的。看到示例代码向您展示如何测试您的代码以及引入/遗漏/遗漏其他漏洞示例,这很有趣......
    • 我最喜欢的是 Apress 书籍“Pro PHP Security”。作者简要介绍了常见漏洞并针对每个漏洞提出了解决方案(通常是非常不合适的一个,例如通过 SQL 转义映射 POST)。然后在解决其他漏洞的其余示例中,他又弄错了,给出的代码遭受了他刚刚在上一章警告我们的漏洞。 XSS 章节甚至在其示例中包含 XSS 漏洞,以说明如何避免略有不同的 XSS 漏洞。关于使用evalsystem 的部分非常可怕。确实是“专业”安全性。
    【解决方案4】:

    鲍比桌

    Bobby Tables 是一个专门用于详细说明脚本通过SQL injection 易受攻击的方式的页面。这不是 PHP 独有的,然而,SQL 注入是许多网页漏洞的原因。

    这可能是您想要包含在演示文稿中的内容。

    【讨论】:

      【解决方案5】:

      我以前见过这样的代码:

      foreach ($_REQUEST as $var => $val) {
          $$var = $val;
      }
      

      这是一种模拟被诽谤的register_globals 选项的方法。这意味着您可以像这样访问您的变量:

      $myPostedVar
      

      而不是非常复杂:

      $_POST['myPostedVar']
      

      在这样的情况下会出现安全风险:

      $hasAdminAccess = get_user_access();
      
      foreach ($_REQUEST as $var => $val) {
          $$var = $val;
      }
      
      if ($hasAdminAccess) { ... }
      

      因为您所要做的就是将?hasAdminAccess=1 添加到网址中,然后您就可以进入了。

      【讨论】:

      • 这里模拟的特征是register_globals
      • 啊,谢谢!这是我从脑海中阻止的事情之一。恐怖……恐怖……
      【解决方案6】:

      另一个 sql-injection-vulnerable 登录脚本示例。不幸的是,这在新程序员中很常见。

      $username = $_POST["username"];
      $password = $_POST["password"];
      $query = "SELECT username, password 
                FROM users 
                WHERE (username = '{$username}') 
                  AND (password = '{$password}')";
      

      【讨论】:

      • 更不用说以明文形式存储密码了。
      • @Vilx- 除非 $_POST["password"] 是在客户端散列的;) 这是不可靠的,因为客户端生成的散列不能在不向客户端透露盐的情况下被加盐-一边。
      • @dwarf015 - 嗯,如果散列函数本身足够慢,我认为揭示盐不会是一个大问题。但我不是专家,所以不要相信我的话。 :)
      【解决方案7】:

      Today's DailyWTF:

      if(strstr($username, '**')) {
      
          $admin = 1;
          $username = str_replace('**', '', $username);
          $_SESSION['admin'] = 1;
      
      } else {
      
          $admin = 0;
      
      }
      

      【讨论】:

      • 请在 thedailywtf 上阅读。那个代码很痛……
      • ...那个写的人自称是程序员?!
      • 后门是有目的的。由于显而易见的原因,这可能被严重过度简化了。但由于它显然是故意的,因此不是这个问题的有效答案。
      【解决方案8】:

      CSRF 赢得胜利。

      <?php
      $newEmail = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
      $pdoStatement = $pdoDb->prepare('UPDATE user SET email=:email WHERE ID=:id');
      $pdoStatement->execute(array(':email'=>$newEmail, ':id'=>$_SESSION['userId']));
      

      您对这种代码感到安全。一切都很好,因为您的代码,您的用户可以在不注入 SQL 的情况下更改他们的电子邮件。 但是,假设您在您的网站http://siteA/ 上有这个,您的一位用户已连接。 使用相同的浏览器,他继续http://siteB/,其中一些 AJAX 执行与此代码等效的操作:

      <form method="post" action="http://site/updateMyAccount.php">
        <p>
          <input name="email" value="badguy@siteB"/>
          <input type="submit"/>
        </p>
      </form>
      

      您的用户刚刚在他不知情的情况下更改了他的电子邮件。如果你觉得这种攻击不危险,ask google about it

      为了帮助抵御此类攻击,您可以:

      • 检查您的用户 REFERER(远非完美)
      • 在表单中实施一些令牌,并在取回数据时检查它们是否存在。

      另一个是会话劫持。其中一种方法是捎带。 如果您的服务器接受非 cookie 会话,您可以使用像 http://siteA/?PHPSESSID=blabla 这样的 URL,这意味着您的会话 ID 是 blabla。

      攻击者可以启动会话并记下其会话 ID,然后将链接 http://siteA/?PHPSESSID=attackerSessionId 提供给您网站的其他用户。当这些用户点击此链接时,他们与您的攻击者共享相同的会话:未记录的会话。所以他们登录。 如果网站不做任何事情,您的攻击者和您的用户仍然以相同的权限共享同一个会话。如果用户是管理员,那就不好了。

      为了缓解这种情况,当您的用户凭据发生更改(登录和注销、进入管理部分等)时,您必须使用 session_regenerate_id

      【讨论】:

        【解决方案9】:

        HTTP 响应拆分攻击

        如果 Web 应用程序将来自 HTTP 请求的输入存储在 cookie 中,比如说

        <?php setcookie("author",$_GET["authorName"]); ?>
        

        如果输入未正确验证“\r\n”字符,则很容易受到 HTTP 响应拆分攻击。

        如果攻击者提交了一个恶意字符串,例如“AuthorName\r\nHTTP/1.1 200 OK\r\n..”,那么HTTP响应将被分成如下形式的两个响应:

        HTTP/1.1 200 正常
        ...
        设置cookie:作者=作者姓名

        HTTP/1.1 200 正常 ...

        显然,第二个响应完全由攻击者控制,可以用任何标题和正文内容代替

        【讨论】:

        • 嗯,我认为这与 PHP 版本有关。 PHP 5 似乎将所有特殊字符编码为百分比编码。
        • HTTP 响应拆分问题已经解决了一段时间。 php.net/releases/5_1_2.php
        【解决方案10】:

        查看开放式 Web 应用程序安全项目。他们有很多不同类型的攻击的解释和例子。 http://www.owasp.org/index.php/Category:Attack

        【讨论】:

          【解决方案11】:

          Email headerinjection attacks 的颈部疼痛比您可能怀疑的要大得多(除非您必须处理它们)。

          这很糟糕:

          $to = 'contact@domain.com';
          $subject = $_POST["subject"];
          $message = $_POST["message"];
          $headers = "From: ".$_POST["from"];
          mail($to,$subject,$message,$headers);
          

          (从上面的第二个参考中复制的代码。)

          【讨论】:

            【解决方案12】:

            制作模板的错误方式。

            <?php
            
              include("header.php");
              include($_GET["source"]); //http://www.mysite.com/page.php?source=index.php
              include("footer.php");
            
            ?>
            

            【讨论】:

            • 您还应该展示制作模板的正确方法。
            • 问题是针对易受攻击的示例,而不是适当的示例。
            【解决方案13】:

            XSS 漏洞很容易显示。只需创建一个页面,将 GET 变量“q”的值放在页面的某处,然后点击以下 URL:

            http://mysite.com/vulnerable_page.php?q%3D%3Cscript%20type%3D%22javascript%22%3Ealert(document.cookie)%3B%3C%2Fscript%3E
            

            这将导致用户的 cookie 显示在警告框中。

            【讨论】:

              【解决方案14】:

              允许上传但不检查扩展。观察:

              站点 A 允许上传图像并显示它们。

              破解者上传一个文件并诱使您相信它是一个图像文件(通过 HTTP mimetypes)。该文件具有 PHP 扩展名并包含恶意代码。然后他试图查看他的图像文件,因为每个 PHP 扩展文件都是由 PHP 执行的,所以代码会运行。他可以做任何apache用户可以做的事情。

              【讨论】:

                【解决方案15】:

                基本(通常是安全敏感的)操作无法按预期工作,而是要求程序员使用第二个“真实”版本来获得未损坏的功能。

                其中最严重的情况是实际运算符受到影响:“==”运算符无法按预期工作,而是需要“===”运算符才能获得真正的相等比较。

                三大 PHP 论坛软件包之一受到其“保持登录”代码中的漏洞的影响。 cookie 将包含用户的 ID 和他们的密码哈希。 PHP 脚本会读取并清理 ID,使用它来查询用户在数据库中的正确哈希值,然后将其与 cookie 中的哈希值进行比较,看看他们是否应该自动登录。

                但是比较是用 == 进行的,所以通过修改 cookie,攻击者使用 boolean:true 的哈希“值”,使得哈希比较语句无用。因此,攻击者可以替换任何用户 ID 以无需密码即可登录。

                【讨论】:

                  【解决方案16】:

                  允许人们上传文件,无论该 API 是否应该由用户使用。例如,如果一个程序将一些文件上传到服务器,并且该程序永远不会上传坏文件,那很好。

                  但是黑客可以追踪发送的内容以及发送到哪里。他可以发现它允许上传文件。

                  从那里,他可以轻松地上传一个 php 文件。一旦完成,游戏就结束了。他现在可以访问您的所有数据,并且可以销毁或更改他想要的任何东西。

                  另一个常见的错误是允许泛滥。你应该对你的数据设置一些合理的限制。不允许用户输入无意义的数据。为什么用户名的长度是 2MB?这样的事情很容易让某人因为空间不足错误而淹没您的数据库或文件系统并导致系统崩溃。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-11-17
                    • 1970-01-01
                    • 2013-05-30
                    • 2011-04-28
                    • 2011-06-21
                    • 2016-01-14
                    相关资源
                    最近更新 更多