이번에는 로그인 폼이 아니라 이름을 바꾸는 폼이 있다. 소스를 보자:
session_set_save_handler(
"myopen",
"myclose",
"myread",
"mywrite",
"mydestroy",
"mygarbage");
session_start();
PHP의 기본 세션 핸들링 함수가 아니라 사용자가 정의한 함수로 동작하게 해놓았다.
if(array_key_exists("name", $_REQUEST)) {
$_SESSION["name"] = $_REQUEST["name"];
debug("Name set to " . $_REQUEST["name"]);
}
print_credentials();
POST값으로 name이 있다면 session의 name 값을 request의 값으로 바꾼다.
이후 print_credentials(); 함수를 실행한다.
function print_credentials() { /* {{{ */
if($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1) {
print "You are an admin. The credentials for the next level are:<br>";
print "<pre>Username: natas21\n";
print "Password: <censored></pre>";
} else {
print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas21.";
}
}
세션에 admin 키가 존재하고, 그 값이 1이라면 다음 레벨의 password를 출력한다.
즉 우리는 세션에 존재하는 admin 값을 1로 바꿔야 함을 유추할 수 있다.
session에 값을 할당하는 부분인 mywrite 함수를 보자:
function mywrite($sid, $data) {
// $data contains the serialized version of $_SESSION
// but our encoding is better
debug("MYWRITE $sid $data");
// make sure the sid is alnum only!!
if(strspn($sid, "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-") != strlen($sid)) {
debug("Invalid SID");
return;
}
$filename = session_save_path() . "/" . "mysess_" . $sid;
$data = "";
debug("Saving in ". $filename);
ksort($_SESSION);
foreach($_SESSION as $key => $value) {
debug("$key => $value");
$data .= "$key $value\n";
}
file_put_contents($filename, $data);
chmod($filename, 0600);
}
세션 데이터는 서버의 세션 파일에 저장되고, 세션 파일은 다음과 같은 형태로 작성된다:
키1 값1
키2 값2
키와 값은 공백문자(스페이스)로 구분되고, 각 키는 줄바꿈 문자(\n)로 구분된다.
내 세션 ID가 d44m1d03ti73ml614ev1sbr5q6고 내 이름이 natas20이라고 가정하면 내 세션 데이터는
PHP의 기본 세션 저장경로/mysess_d44m1d03ti73ml614ev1sbr5q6 파일에 저장될 것이고 그 내용은 다음과 같을 것이다:
name natas20
그리고 나는 내 세션 데이터의 admin 키가 값 1을 가지도록 파일을 수정하고 싶다.
mywrite 함수에서 각 키, 값의 구분자로 쓰이는 공백문자와 줄바꿈 문자를 필터링하지 않으므로 다음 request를 보내면 세션 파일에 내가 원하는 정보를 덮어 쓸 수 있을 것이다:
(아무 값)(줄바꿈 문자)admin 1
따라서 다음 값을 Post Request로 전송하면 다음 레벨의 password를 얻을 수 있다:
name=natas20%0Aadmin+1