SISS/Natas,LOS, XSS

Natas 20 → 21

3190024 2020. 7. 16. 23:00

이 페이지를 메인 페이지라고 부르겠다.

 들어가 봤더니 http://natas21-experimenter.natas.labs.overthewire.org/ 와 같은 위치에 있다고 한다. 먼저 소스코드를 살펴보자.

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: natas22\n";
    print "Password: <censored></pre>";
    } else {
    print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas22.";
    }
}
/* }}} */

session_start();
print_credentials();

print_credentials(): $_SESSION에 "admin"이라는 key가 있어야 하고, 그 value의 값이 1이면 natas22의 비밀번호를 출력한다.

 

이번에는 링크로 걸어놓은 곳으로 들어가 보았다.

신기해서 꽉 채워서 캡처해 봤다. 아까 메인 페이지의 링크가 역시 마찬가지로 들어가 있다.

session_start();

// if update was submitted, store it
if(array_key_exists("submit", $_REQUEST)) {
    foreach($_REQUEST as $key => $val) {
    $_SESSION[$key] = $val;
    }
}

$_REQUEST에 "submit"이라는 key가 있으면 $_REQUEST의 key와 value를 각각 $_SESSION의 key와 value로 저장한다.

 

if(array_key_exists("debug", $_GET)) {
    print "[DEBUG] Session contents:<br>";
    print_r($_SESSION);
}

$_GET에 debug라는 key가 있으면 "[DEBUG] Session contents:"과 $_SESSION의 정보를 출력한다.

print_r(): 변수에 대한 정보를 사람이 읽을 수 있는 형태로 출력한다.

 

// only allow these keys
$validkeys = array("align" => "center", "fontsize" => "100%", "bgcolor" => "yellow");
$form = "";

$validkeys에 배열을 저장하고, $form을 ""로 초기화한다.

 

$form .= '<form action="index.php" method="POST">';
foreach($validkeys as $key => $defval) {
    $val = $defval;
    if(array_key_exists($key, $_SESSION)) {
    $val = $_SESSION[$key];
    } else {
    $_SESSION[$key] = $val;
    }
    $form .= "$key: <input name='$key' value='$val' /><br>";
}
$form .= '<input type="submit" name="submit" value="Update" />';
$form .= '</form>';

$form에 '<form action="index.php" method="POST">'를 이어 붙인다.

$validkeys의 각 key와 value들에 대해 value를 $val에 저장하고, $key가 $_SESSION에 존재하는 key라면 $_SESSION[$key]의 값을 $val에 저장한다. 그렇지 않은 경우에는 $val을 $_SESSION[$key]에 저장한다.

그 뒤, $form에 여러 문자열들을 이어 붙인다.

 

$style = "background-color: ".$_SESSION["bgcolor"]."; text-align: ".$_SESSION["align"]."; font-size: ".$_SESSION["fontsize"].";";
$example = "<div style='$style'>Hello world!</div>";

$style에 $_SESSION의 여러 key들의 value들을 이어붙인 문자열을 저장한다.

$example에 "<div style='$style'>Hello world!</div>"을 저장한다.

 

$_SESSION에 "admin"을 추가하기 위해서는 $validkeys에 손을 써야 하는 것 같다. 또는 $_SESSION 자체에 접근해야 하는 것 같다.

URL 뒤에 "?debug=true"를 붙여주고 Update 버튼을 누르고 다시 새로고침을 한 후의 화면이다.

validkeys에 접근할 수 없으므로 burp suite를 이용하여 $_SESSION을 수정한다.

 

메인 페이지의 PHPSESSID는 j5e40249g3invk8nlsk663d711

두 페이지는 colocated site의 관계에 있기 때문에 PHP session을 공유한다고 한다.  

이 페이지에서 proxy 서버 설정을 켜고 burp suite의 intercept도 켜준 뒤에 Update를 눌러준다.

그 뒤, PHPSESSID를 main 페이지의 PHPSESSID로 바꿔주고, 17행에서 Update 뒤에 &admin=1 을 붙여준 뒤에 intercept를 꺼 준다. 이렇게 하면 메인 페이지에 수정한 세션 값을 보낼 수 있게 된다. 그 뒤, burp suite를 실행했던 페이지에서 메인 페이지로 가는 링크를 클릭하면 다음과 같이 natas22의 비밀번호가 나온다.

natas22 비밀번호: chG9fbe1Tq2eWVMgjYYD1MsfIvN461kJ