우선, register_globals이 뭔지부터 알아보자.
register globals는 internal PHP setting이다.
서버에 액세스하는 방법을 제어하며,
ON상태와 OFF상태가 있다. 디폴트 값은 OFF이다(보안 문제 때문).
ON상태 - Global배열( GET[], POST[], REQUEST[] 등) 없이 양식 속성에 액세스 가능
OFF상태 - Global배열을 통해서만 모든 속성에 액세스 가능
OFF 상태인 경우, Global배열을 이용해서 파라미터를 받으면 액세스가 가능하다.
아무래도 보안에 취약한 점을 이용해서 문제를 냈을테니까,
register globals가 ON상태임을 예상할 수 있다.
먼저, 힌트에서 준 백업 파일을 찾아보자.
패스워드가 어떤 방식으로 인증을 거치는지 알아야 되니까, 소스코드가 필요하다.
url에 index.php.bak를 넣어서 백업파일을 다운로드받은 후에, 에디터를 이용해 파일을 열어주면 페이지 소스 코드를 얻을 수 있다.
<?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;
?>
[첫 번째 풀이]
맨 아래 부분에 $aff값을 echo하기 전에 hidden_password를 불러온다.
따라서 저 부분을 포함하는 if문의 조건(이 방법에서는 OR연산의 두 번째 조건)이 True가 되게 만들어야 한다.
간단하게 $_SESSION["logged"]의 값이 1이면 될 것 같다.
url에는
ch17/?_SESSION[logged]=1 로 넣어주면 flag를 얻을 수 있다.
*URL을 작성하고 아래 버튼(connect)을 누르면 안된다. URL창에서 엔터 키를 눌러서 값을 전달해줘야 한다.
[두 번째 풀이]
마지막 if문의 첫 번째 조건에 주목한다.
1. isset(&password)이므로 무언가 값이 들어가서 True를 만들어 줘야 한다.
2. $password != "" - 마찬가지로 password에는 값이 들어가야 한다.
3. auth($password,$hidden_password)==1 - 위의 auth 함수에서 두 인자를 비교해서 같은지를 확인한다.
그래서 나는 url에 password=1&hidden_password=1을 넘겨주었다.
?password=1&hidden_password=1 로 넘겨주면,
You can validate with the password : 1
이라는 문구가 출력된다. 당연히 1은 답이 아닌데,
여기서 중요한 것은 서버에서 내가 hidden_password를 알고 있다고 인식했다는 것이다.
따라서 이 상태에서 url을 원래 상태(ch17까지만 있는 상태, url에 파라미터 없음)로 되돌려서 새로고침해주면 원래의 hidden_password가 호출된다.
'WebHacking' 카테고리의 다른 글
[root-me] Local File Inclusion - Double encoding (0) | 2020.01.06 |
---|---|
[root-me] Local File Inclusion (0) | 2020.01.06 |
[root-me] File upload - MIME type (0) | 2020.01.06 |
[root-me] PHP filters (0) | 2020.01.06 |
[root-me] File upload - null byte (0) | 2020.01.06 |