WeChall - Training - Register Globals

Challenge

利用 PHP register_globals 漏洞。该挑战模拟了旧版 PHP register_globals=On 的行为:

1
foreach ($_GET as $k => $v) { $$k = $v; }

register_globals 启用时,GET/POST 参数会自动成为全局变量。目标是以 admin 身份登录。

提供了一个测试账号 test:test,但只能以用户 test 身份登录,无法登录 admin

挑战的核心代码:

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
# EMULATE REGISTER GLOBALS = ON
foreach ($_GET as $k => $v) { $$k = $v; }

# Send request?
if (isset($_POST['password']) && isset($_POST['username'])
&& is_string($_POST['password']) && is_string($_POST['username']))
{
$uname = GDO::escape($_POST['username']);
$pass = md5($_POST['password']);
$query = "SELECT level FROM ... WHERE username='$uname' AND password='$pass'";
$db = gdo_db();
if (false === ($row = $db->queryFirst($query))) {
echo GWF_HTML::error(...);
} else {
# Login success
$login = array($_POST['username'], (int)$row['level']);
}
}

if (isset($login))
{
echo GWF_HTML::message('Register Globals', 'Welcome back, ...');
if (strtolower($login[0]) === 'admin') {
$chall->onChallengeSolved(GWF_Session::getUserID());
}
}

Solution

register_globals=On 的行为是将 GET/POST 参数直接提升为全局变量。代码中的 foreach ($_GET as $k => $v) { $$k = $v; }(variable variables)模拟了这一机制。

直接传入 login[0]=admin 构造 $login 数组:

1
2
$ curl -b 'WC=...' -g \
'https://www.wechall.net/en/challenge/training/php/globals/globals.php?login[0]=admin'

foreach ($_GET as $k => $v) { $$k = $v; }$_GET['login'] = ['admin'] 赋给 $loginisset($login)$login[0] === 'admin' 同时通过,挑战完成。userlevel 为空是因为绕过了数据库查询——没有真实用户被认证,但这不影响 flag 发放。

注意 URL 中的 [] 需要用 -g--globoff)防止 curl 解释为通配符。