PHP-Audit-Labs Day2 示例的简单分析

  • 漏洞位于themes/default/404.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php theme_include('header'); ?>

    <section class="content wrap">
    <h1>Page not found</h1>

    <p>Unfortunately, the page <code>/<?php echo current_url(); ?></code> could not be found. Your best bet is either to try the <a href="<?php echo base_url(); ?>">homepage</a>, try <a href="#search">searching</a>, or go and cry in a corner (although I don’t recommend the latter).</p>
    </section>

    <?php theme_include('footer'); ?> was not found
  • Anchor 使用了路由,如果访问的url不存在则会执行404.php
    比如访问/admin/xxx,会返回

    404
    The page admin/xxx was not found.
    Try the homepage

  • 其中xxx用户可控,处理不好就可能造成xss

  • 可以看到404.php中调用了base_url()获取用户访问的url

    1
    2
    3
    function current_url() {
    return Uri::current();
    }
  • 跟进Uri类的current静态方法

    1
    2
    3
    4
    5
    public static function current() {
    if(is_null(static::$current)) static::$current = static::detect();

    return static::$current;
    }
  • 跟进detect静态方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    /**
    * Try and detect the current uri
    *
    * @return string
    */
    public static function detect() {
    // create a server object from global
    $server = new Server($_SERVER);

    $try = array('REQUEST_URI', 'PATH_INFO', 'ORIG_PATH_INFO');

    foreach($try as $method) {

    // make sure the server var exists and is not empty
    if($server->has($method) and $uri = $server->get($method)) {

    // apply a string filter and make sure we still have somthing left
    if($uri = filter_var($uri, FILTER_SANITIZE_URL)) {

    // make sure the uri is not malformed and return the pathname
    if($uri = parse_url($uri, PHP_URL_PATH)) {
    return static::format($uri, $server);
    }

    // woah jackie, we found a bad'n
    throw new ErrorException('Malformed URI');
    }
    }
    }

    throw new OverflowException('Uri was not detected. Make sure the REQUEST_URI is set.');
    }
  • 先通过$server->get($method) 依次获得 $_SERVER的’REQUEST_URI’ ,’PATH_INFO’和’ORIG_PATH_INFO’键值,存储在$uri中

  • 如果filter_var($uri, FILTER_SANITIZE_URL) 和 parse_url($uri, PHP_URL_PATH) 都为真的话就将其返回,否则抛出一个错误

  • 其中FILTER_SANITIZE_URL过滤器的作用如下

    1
    2
    FILTER_SANITIZE_URL 过滤器删除字符串中所有非法的 URL 字符。
    该过滤器允许所有的字符、数字以及 $-_.+!*'(),{}|\\^~[]`"><#%;/?:@&=。

    该过滤器不会过滤<>/,直接可以插入

    1
    <scirpt></scirpt>

    标签

  • 只有严重不合格的url,parse_url才会返回false

    1
    2
    3
    4
    5
    php > print_r(parse_url('/admin/<script>alert(1)</script>'));
    Array
    (
    [path] => /admin/<script>alert(1)</script>
    )
  • 因此最后的payload

    1
    /admin/<script>alert(1)</script>