Insomnia Writeup
2024年11月7日...大约 2 分钟
点击页面中的所有按钮,发现整个网站只有登录和注册两个功能,所以我们在源码中关注这两个功能。
在源码中全局搜索 flag
后,在 ProfileController
中发现了读取 flag
的代码。
public function index() {
$token = (string) $_COOKIE["token"] ?? null;
$flag = file_get_contents(filename: APPPATH . "/../flag.txt");
if (isset($token)) {
$key = (string) getenv("JWT_SECRET");
$jwt_decode = JWT::decode($token, new Key($key, "HS256"));
$username = $jwt_decode->username;
if ($username == "administrator") {
return view("ProfilePage", [
"username" => $username,
"content" => $flag,
]);
} else {
$content = "Haven't seen you for a while";
return view("ProfilePage", [
"username" => $username,
"content" => $content,
]);
}
}
}
可以发现,只要我们以 administrator
的身份登录,就可以获取到 flag
。
public function login() {
$db = db_connect();
$json_data = request()->getJSON(true);
if (!count($json_data) == 2) {
return $this->respond("Please provide username and password", 404);
}
$query = $db->table("users")->getWhere($json_data, 1, 0);
$result = $query->getRowArray();
if (!$result) {
return $this->respond("User not found", 404);
} else {
$key = (string) getenv("JWT_SECRET");
$iat = time();
$exp = $iat + 36000;
$headers = [
"alg" => "HS256",
"typ" => "JWT",
];
$payload = [
"iat" => $iat,
"exp" => $exp,
"username" => $result["username"],
];
$token = JWT::encode($payload, $key, "HS256");
$response = [
"message" => "Login Succesful",
"token" => $token,
];
return $this->respond($response, 200);
}
}
从登录部分的代码我们可以发现 if (!count($json_data) == 2)
这里的逻辑错误,应该是 if (count($json_data) != 2)
,所以无论我们的数据包中是否包含 username
和 password
,都不会返回 Please provide username and password
,这将成为后面的一个伏笔。
又因为查询语句 $query = $db->table("users")->getWhere($json_data, 1, 0);
是直接将我们的数据包作为查询条件,所以我们可以通过构造只有 username
的数据包,绕过密码验证。
把返回的 JWT token 放到 Cookie 中,然后访问 /index.php/profile
,即可获取到 flag
。
Powered by Waline v3.3.1