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>