Ricerca CTF 2023 writeup

# Ricerca CTF 2023
https://2023.ctf.ricsec.co.jp/
12時間という短時間なのでやりやすそうだと思い参加。
順位は91位/187位でした。
## 目次
- welcome(81pts)
- crackme(88pts)
- Revolving Letters(93pts)
- BOFSec(97pts)
- Cat Café(95pts 時間内に解けませんでした・・・)
- 感想
## welcome(81pts)
discordの```#announcement```に2022/04/09 09:59に答えが投稿されました。
![welcome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982234/fbd4d1c5-254c-3bec-5a44-4185288378b7.png)
```RicSec{do_U_know_wh4t_Ricerca_means_btw?}```
Ricercaはイタリア語で「探検、探索」だそうです。
## crackme(88pts)
Linuxのコマンドで```strings```を使用します。
```strings```コマンドは、バイナリファイルの読める部分を表示してくれます。

すると見るからに怪しいものが。
![crackme_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982234/4a7a969e-5b79-88d9-c649-23b01ee47fcc.png)

Linuxで実行してパスワードを入力すると・・・
![crackme_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982234/68705e9e-6785-eca4-545b-500035944820.png)

```RicSec{U_R_h1y0k0_cr4ck3r!}```
ひよこクラッカーと呼ばれてしまいました。
## Revolving Letters(93pts)
ここの部分が何をやっているかが重要です。見てみましょう。
```python
def encrypt(secret, key):
  assert len(secret) <= len(key)
  
  result = ""
  for i in range(len(secret)):
    if secret[i] not in LOWER_ALPHABET: # Don't encode symbols and capital letters (e.g. "A", " ", "_", "!", "{", "}")
      result += secret[i]
    else:
      result += LOWER_ALPHABET[(LOWER_ALPHABET.index(secret[i]) + LOWER_ALPHABET.index(key[i])) % 26]

  return result
```
日本語に直すと

その文字がアルファベットの小文字かを1文字ずつ調べる。
→小文字の場合、変換する。
→そうでない場合、変換せずそのまま出力する。

変換するときは以下の法則に従って行います。
```key = "thequickbrownfoxjumpsoverthelazydog"```より

1.keyの長さをsecretの長さと同じにする。
2.アルファベットを数値と考える。a=0、z=25のように。
3.keyとsecretの同じ文字列目で和を求め、26以上の場合は26で割った余りを求める。

例えば、3文字目が小文字でxの場合
x(23) + e(4) = 27 % 26 = 1

4.アルファベットに変換する。
1はbなのでbと変換して完了。

つまり、Outputで出されていた暗号化されていたflagは
小文字の部分をkeyの文字の数値分引くと求められます。

(気づいたかもしれないですが、
```result += LOWER_ALPHABET[(LOWER_ALPHABET.index(secret[i]) + LOWER_ALPHABET.index(key[i])) % 26]```

を

```result += LOWER_ALPHABET[(LOWER_ALPHABET.index(secret[i]) - LOWER_ALPHABET.index(key[i])) % 26]```
に変換するだけでも解けるようです・・・私は自力でやりました・・・)

```RicSec{great_you_can_do_anything!}```

何でもできるようになりたいです。

## BOFSec(97pts)
これはあまり解説ができないです。なんかやっていたらできていたので・・・

この問題はバッファオーバーフローというメモリ領域内の場所を溢れさせる攻撃でした。

こうすることで正しいかどうか判定する場所を強制的にtrueに書き換えられるようです。

```if (user.is_admin)```と書かれているのでその場所を```if('a')```と置き換えるような感じです。```if('a')```になると必ずtrueになります。



260文字何でもいいので打ちます。(aaaaaa・・・とやっていくほうが楽かもしれない)
![bofsec.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982234/8e4b5382-53f7-6125-67c3-56213c35bec0.png)

```RicSec{U_und3rst4nd_th3_b4s1c_0f_buff3r_0v3rfl0w}```

基礎でも理解してるか怪しいです。
## Cat Café(95pts 時間内に解けませんでした・・・)
猫カフェ。
```flag.txt```にたどり着けばflagが手に入りそうです。
試しに猫の画像を新しいタブで開くと・・・

```http://cat-cafe.2023.ricercactf.com:8000/img?f=01.jpg```
URLが不自然。

この問題ではここが怪しそうです・・・
```python
@app.route('/img')
def serve_image():
    filename = flask.request.args.get("f", "").replace("../", "")
    path = f'images/{filename}'
    if not os.path.isfile(path):
        return flask.abort(404)
    return flask.send_file(path)
```

URLに```/img```が含まれているとこのような対応をとるようです。
ディレクトリトラバーサル攻撃すればflagにたどり着けそう・・・だが、ここで問題が。

```../```が空白に置き換わってしまう。

ここで何もひらめかず、解けなかったです・・・。

これは、```../```があれば空白に置き換えるだけで、うまく工夫して```../```を表現すれば
答えにたどり着けます。
置き換える回数は1回だけなので、それを逆手に利用して```..././```と入力すると
```../```と表現することが可能です。

```f=```の後に```..././flag.txt```と書いてアクセスすると・・・

![catcafe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982234/8f3d62ab-7341-ad5e-c2ad-e3670f77e3a1.png)

```RicSec{directory_traversal_is_one_of_the_most_common_vulnearbilities}```

ディレクトリトラバーサル攻撃は、閲覧できるファイル(ディレクトリ)から、非公開のファイル(ディレクトリ)の階層に横断するかのように移動してファイルを閲覧することです。
https://www.lrm.jp/security_magazine/directory_traversal/

## 感想
warmupだけど、1問以上解けたのは初めてで非常に楽しかったです。