😺

ncコマンドで作るHTTPサーバモドキから画像返却

2024/12/18に公開

web系についてなんでも Advent Calendar 2024
18日目の記事です。
https://adventar.org/calendars/10590

Webと言えばHTTPですよね

ncコマンドでHTTPサーバみたいに80番ポートで待ち受けて、ブラウザからリクエストした画像を返却してみたくなった。

セキュリティエンジニア大好きncコマンドとは

nc(netcat)コマンドは、ネットワーク通信を行うためのツールで、主にTCP/UDP接続を確立するために使用されます。クライアントとしてもサーバとしても動作し、ネットワークのデバッグやテスト、データ転送などに利用されます。

80番ポートで待ち受け

advent $ sudo nc -vl 80
Listening on 0.0.0.0 80

ブラウザから画像をリクエスト

このアドベントカレンダーのロゴをローカルにダウンロードしたのでそれをリクエストしてみたいと思います。

待ち受け側にリクエストヘッダが届く

advent $ sudo nc -vl 80
Listening on 0.0.0.0 80
Connection received on localhost 37534
GET /e79dd47.png HTTP/1.1
Host: localhost
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: ja

画像を返却しようと思ったら

画像サイズは事前にチェックして23889バイト、フォーマットはpngと確認済みなので以下のようなヘッダが必要と判断しました。

HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 23889
Connection: close

あれ?上記までをncコマンド実行中のターミナルに張り付けるのは良いが、画像本体をどうやって貼り付けるんだ?
そもそもターミナル上でテキストしか入力出来ない、、、
その後いろいろ試行錯誤するも、ncコマンドで標準入力で渡すしかない模様。
でも、それだとncコマンド実行時点でファイルを指定しておく必要があり、リクエスト→レスポンスの順番に従わないので、何か違うな、、、どうにか出来ないかな。

とりあえず郷に入っては郷に従えということで

先ほどのリクエストは一回破棄して、レスポンス出力用のシェル(responsh.sh)を作成しました。

#!/bin/sh
echo -n "HTTP/1.1 200 OK\r\n"
echo -n "Content-Type: image/png\r\n"
echo -n "Content-Length: 23889\r\n"
echo -n "Connection: close\r\n"
echo -n "\r\n"
cat e79dd47.png

改めてncコマンド実行

作成したシェルをパイプでつないで実行します。

advent $ sh response.sh | sudo nc -vl 80
Listening on 0.0.0.0 80

ブラウザからリクエスト実行

無事画像が返却されてブラウザに表示されました。

本当にどうにか出来ないのか

例によって先駆者はいるもので、名前付きパイプを活用してリクエストパラメータの値をうまくレスポンスに活用する事が出来るようです。これを活用すれば、response.shの中で動的にContent-Type、Content-Length、catするファイル名を指定できそうです。(今回はもう時間が無いのでそこまでやらないですがw)
https://qiita.com/wf-yamaday/items/f890f3523eeacbe71153

さいごに

今回の施行で名前付きパイプの有効な使い方?を知ることができました。
ただのncコマンドを利用したHTTPレスポンス画像返却実験だったのですが知らないことを知ることが出来て、何事も手を動かして実践してみると気づきがあるものだなぁと改めて思いました。

おまけ宣伝

今回、少しセキュリティエンジニアに関係する話を書きましたが、セキュリティのLT会を2025年1月23日に企画しています。
ご興味があれば是非、遊びに来てくださいw
https://security-any.connpass.com/event/336993/

Discussion