- 来源:Root-Me
- 题型:Web-Server
- 题目:PHP register globals
- 分数:25 Points
前置知识可以参考 这里 。
大概意思就是,register_globals 是 PHP 的一个特性,在 4.2.0 版本之前,它是默认启用的。
当它启用的时候,PHP 会允许变量未初始化就使用(换言之在第一次使用的时候就是初始化的时候),这样就使得变量的来源变得不确定。
于是就可能直接在 URL 以传参的方式(如 ?key=val
)胁持变量初始化,若 PHP 代码没有考虑这种情况,就存在被入侵的风险。
知道这个知识点后,回到这题。
开启挑战后进入一个页面,但是找不到任何注入点。虽然说提示是 register_globals ,但是不知道应该挟持哪个变量也是于事无补。
因此应该先想办法找到页面的 PHP 代码,从而找到可能被挟持的变量。
注意到题目的另一个提示是(开发者经常留下备份文件):
It seems that the developper often leaves backup files around...
虽然不难测试到主页名称是 index.php
,但是要找到它的备份名称也不是容易的事情,只能靠猜。
最终猜到备份页面名称为 index.php.bak
(其实我真的很不喜欢猜文件名。。变成全凭运气解题好无语)
下载 index.php.bak
后得到页面的 PHP 代码为:
<?php
function auth($password, $hidden_password){
$res=0;
if (isset($password) && $password!=""){
if ( $password == $hidden_password ){
$res=1;
}
}
$_SESSION["logged"]=$res;
return $res;
}
function display($res){
$aff= '
<html>
<head>
</head>
<body>
<h1>Authentication v 0.05</h1>
<form action="" method="POST">
Password <br/>
<input type="password" name="password" /><br/><br/>
<br/><br/>
<input type="submit" value="connect" /><br/><br/>
</form>
<h3>'.htmlentities($res).'</h3>
</body>
</html>';
return $aff;
}
session_start();
if ( ! isset($_SESSION["logged"]) )
$_SESSION["logged"]=0;
$aff="";
include("config.inc.php");
if (isset($_POST["password"]))
$password = $_POST["password"];
if (!ini_get('register_globals')) {
$superglobals = array($_SERVER, $_ENV,$_FILES, $_COOKIE, $_POST, $_GET);
if (isset($_SESSION)) {
array_unshift($superglobals, $_SESSION);
}
foreach ($superglobals as $superglobal) {
extract($superglobal, 0 );
}
}
if (( isset ($password) && $password!="" && auth($password,$hidden_password)==1) || (is_array($_SESSION) && $_SESSION["logged"]==1 ) ){
$aff=display("well done, you can validate with the password : $hidden_password");
} else {
$aff=display("try again");
}
echo $aff;
?>
从代码不难分析到关键点是这段代码,当条件为真时,它会打印真正的密码 $hidden_password
:
if (( isset ($password) && $password!="" && auth($password,$hidden_password)==1) ||
(is_array($_SESSION) && $_SESSION["logged"]==1 ) ){
$aff=display("well done, you can validate with the password : $hidden_password");
} else {
$aff=display("try again");
}
而要令条件为真,可以利用 ||
后面的的条件 (is_array($_SESSION) && $_SESSION["logged"]==1 )
,
即我们要通过 register_globals 挟持的变量是 _SESSION["logged"]
,并将其初始化为 1 。
为此可以构造这样的 payload (测试发现双引号会被过滤,因此直接去掉亦可):
http://challenge01.root-me.org/web-serveur/ch17/?_SESSION[logged]=1
挟持变量成功,完成挑战。
答案下载
flag 下载后的 flagzip 的文件需要手动更改后缀为
*.zip
,然后解压即可(为了避免直接刷答案)