グリーン免許エンジニアのNotepad

エンジニアの免許を取得したてのほやほやエンジニアが作るNotepadです。Notepad(メモ帳)以上のことは書けません。

Dockerを動かすとufwで設定したはずのルールを回避して外部にサービスを公開してしまう事象

始めに

ConoHa VPSをレンタルして、WireGuardを構築し、自分だけがアクセス可能なWebアプリ構築まで後一歩のところでハマったことをこちらに記載します。 なお、今回の「自分だけがアクセス可能なWebアプリ」はすでにDockerを使って作成済みであり、VPSでもDockerにて動かす想定です。 ちなみに、内容としてはこちらの続きのような認識ですので、詳しく設定内容知りたい方はご覧ください。

起こった事象

VPSにてVPNサーバを構築の上、必要なポート(今回だとssh,VPNのポート)のみ許可する設定をufwにて設定した後、 docker-composeにてDockerサービスを起動すると、、、 なんと、ufwで許可していない(厳密にはローカルIPからのみ許可している)Webサービスに外部からアクセスができてしまいました。 ※python http serverにて起動したwebは公開されないのに、Dockerで起動した80ポートは公開されるような状態

Dockerを使用した場合のufwの問題

調査したところ、Dockerを使用してサービスを公開する場合、Dockerはufwの設定を回避し、サービスを外部に公開してしまうようです。 また、Dockerが変更したiptablesの設定は、ufw側から閲覧できず、公開されているのに気づきにくい状態です。

after.rulesを使用したufwのルール設定

after.rulesは、ufwコマンドで追加したルールの後で実行されるルールを設定するためのファイルです。以下の手順に従って、ufwのルールを設定することで外部に公開されることのないDockerサービスを起動できます。

  1. after.rulesファイルを開きます。
sudo vim /etc/ufw/after.rules
  1. ファイルの最後に、以下のルールを追加します。
# BEGIN UFW AND DOCKER
*filter
:ufw-user-forward - [0:0]
:ufw-docker-logging-deny - [0:0]
:DOCKER-USER - [0:0]
-A DOCKER-USER -j ufw-user-forward

-A DOCKER-USER -j RETURN -s 10.0.0.0/8
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
-A DOCKER-USER -j RETURN -s 192.168.0.0/16

-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN

-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12

-A DOCKER-USER -j RETURN

-A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
-A ufw-docker-logging-deny -j DROP

COMMIT
# END UFW AND DOCKER
  1. after.rulesを保存し、ufwを再起動します。
sudo ufw disable
sudo ufw enable

これで、Dockerを使用してサービスを起動しても、ufwの設定を回避することがなくなります。after.rulesを使用してufwのルールを設定することで、サーバーへのアクセスを制限することができます。

さいごに

Dockerを使用して外部にサービスを公開する場合、ufwの設定を回避してしまう問題があります。 今回は、気づいたのでよかったものの、この事象を知らずにDockerにてサービスを公開すると、セキュリティ上問題があります。 何かしら構築したあとは、意図した挙動になっているかどうか確認することが大事ということを再確認できた事象でした。 今回は、after.rulesを使用してufwのルールを設定することで、この問題を解決しましたが、そのほかにも「DOCKER_OPTSにiptables=false」を追加するや、「—expose」オプションを利用するなど解決策はあるようなので、個人のネットワークにあった解決法を実施いただければと思います。

参考

GitHub - chaifeng/ufw-docker: To fix the Docker and UFW security flaw without disabling iptables ufwでブロックしているはずのDocker環境のポートに外部からアクセスできてしまう

WireguardにてVPNを構築する 〜自分しかアクセスできないWebサーバを作ろう〜

WireguardというVPNソフトをUbuntu上に構築した際のメモです。

Wireguardとは

Wireguardは、OSSVPN(Virtual Private network)ソフトウェアとなっており、インターネットを使ってプライベートネットワークを構築することが可能。

従来のVPNソフトウェアに比べて処理速度が非常に高速で、非常にセキュアとのことです。また、軽量な設計により、様々なOSに対応しています。

Wireguardのメリット

Wireguardは、他のVPNソフトウェアに比べて以下のようなメリットがあります。

  1. 高速な処理速度
  2. セキュアな通信
  3. 軽量な設計
  4. 様々なOSに対応

シンプルイズベストということですね。

前提

以下の環境でWireGuardを構築します。

  • サーバ:ConoHaのVPS
  • サーバOS:Ubuntu 22.04.2 LTS
  • ConoHaの接続許可ポート:全て許可
  • ネットワーク:10.0.0.0/24
  • サーバIPアドレス:10.0.0.1
  • クライアント1のIPアドレス:10.0.0.2
  • クライアント2のIPアドレス:10.0.0.3

イメージ図

WireGuard構築 イメージ図

UFWの設定

最初にufwのポリシーを設定します。 ここでは、すべての通信をデフォルト拒否し、ロギング設定をしています。

$ sudo ufw default deny
$ sudo ufw logging on
$ sudo ufw logging medium

許可する通信の設定

$ sudo ufw allow 51820/udp
$ sudo ufw allow from 10.0.0.0/24 to any port 80 ←今回はWebにアクセスしたいのでこちらも追加
$ sudo ufw enable
$ sudo ufw status ←確認
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
51820/udp                  ALLOW       Anywhere
80                         ALLOW       10.0.0.0/24
51820/udp (v6)             ALLOW       Anywhere (v6)

IPフォワーディングの設定

VPNネットワークから別のネットワークへの通信をフォワーディングさせる設定

sudo vim /etc/sysctl.conf

28行めの行をコメントアウトする 変更前

27 # Uncomment the next line to enable packet forwarding for IPv4
28 # net.ipv4.ip_forward=1

変更後

27 # Uncomment the next line to enable packet forwarding for IPv4
28 net.ipv4.ip_forward=1

変更を反映

sudo sysctl -p

Wireguardインストール&鍵生成

インストール

$ sudo apt update
$ sudo apt install wireguard

サーバ用鍵の発行

$ wg genkey | sudo tee /etc/wireguard/privatekey | wg pubkey | sudo tee /etc/wireguard/publickey
$ sudo chmod 600 /etc/wireguard/privatekey /etc/wireguard/publickey

クライアント用鍵の発行

$ sudo mkdir /etc/wireguard/client ←クライアント用ディレクトリ

クライアント1
$ wg genkey | sudo tee /etc/wireguard/client/user01_privatekey | wg pubkey | sudo tee /etc/wireguard/client/user01_publickey
$ wg genpsk | sudo tee /etc/wireguard/client/user01_preshared
$ sudo sh -c "chmod 600 /etc/wireguard/client/user01_*"

クライアント2
$ wg genkey | sudo tee /etc/wireguard/client/user02_privatekey | wg pubkey | sudo tee /etc/wireguard/client/user02_publickey
$ wg genpsk | sudo tee /etc/wireguard/client/user02_preshared
$ sudo sh -c "chmod 600 /etc/wireguard/client/user02_*"

サーバの設定ファイル作成

$ sudo vim /etc/wireguard/wg0.conf
[Interface]
# server
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = {sudo cat /etc/wireguard/privatekey の値}

PostUp = ufw route allow in on wg0 out on eth0
PostUp = iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PreDown = ufw route delete allow in on wg0 out on eth0
PreDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# user01
[Peer]
publicKey = {$ sudo cat /etc/wireguard/client/user01_publickey の値}
PresharedKey = {$ sudo cat /etc/wireguard/client/user01_preshared の値}
AllowedIPs = 10.0.0.2/32

# user02
[Peer]
publicKey = {$ sudo cat /etc/wireguard/client/user02_publickey の値}
PresharedKey = {$ sudo cat /etc/wireguard/client/user02_preshared の値}
AllowedIPs = 10.0.0.3/32

クライアントの設定ファイル作成

クライアント1

sudo vim /etc/wireguard/client/user01.conf
[Interface]
# client
PrivateKey = {sudo cat /etc/wireguard/client/user01_privatekey の値}
Address = 10.0.0.2
DNS = 1.1.1.1, 8.8.8.8

[Peer]
# server
PublicKey = {sudo cat /etc/wireguard/publickey の値}
PresharedKey = {sudo cat /etc/wireguard/client/user01_preshared の値}
AllowedIPs = 10.0.0.0/24
Endpoint = example.com:51820 WireGuardサーバのドメイン:ポート番号(GIP:ポート番号 でもOK)

クライアント2

sudo vim /etc/wireguard/client/user02.conf
[Interface]
# client
PrivateKey = {sudo cat /etc/wireguard/client/user02_privatekey の値}
Address = 10.0.0.3
DNS = 1.1.1.1, 8.8.8.8

[Peer]
# server
PublicKey = {sudo cat /etc/wireguard/publickey の値}
PresharedKey = {sudo cat /etc/wireguard/client/user02_preshared の値}
AllowedIPs = 10.0.0.0/24
Endpoint = example.com:51820 WireGuardサーバのドメイン:ポート番号(GIP:ポート番号 でもOK)

動作確認

WireGuardサーバの起動

$ sudo wg-quick up /etc/wireguard/wg0.conf

自動起動設定

$ sudo systemctl enable wg-quick@wg0
$ sudo systemctl start wg-quick@wg0

以上でWireGuardの構築は完了です。

あとは、クライアント端末にWireGuardのクライアントソフトをインストール。

その後、今回作成したクライアントの設定ファイルuser○○.confをインポートの上、有効化するとVPNが接続されます。

参考

[ConoHa VPS] WireGuardでVPNサーバー構築 [Ubuntu 22.04 LTS] | Mulong.me

【Ubuntu】WireGuardで簡単VPN環境を構築 | VPS Life

おまけ

VPN繋いだ後にちゃんとwebが見れるかの確認としてPythonのHTTPServerが便利です。

使い方は任意のディレクトリにて以下のコマンドを実行すると、実行した場所をルートディレクトリとしたWebサーバが立ち上がります。

$ sudo python3 -m http.server 80

また、これを使用することで、confファイルのダウンロードも容易に行うことができますのでぜひ。

以上、Wireguardの構築についてのメモでした。

SECCON Beginners 2019 Write-up

CTF初心者ですがSECCON Beginnersに参加しました。 結果は見る気もなかったのでみてないけど、4問解けたうちの1問はflagを入力した時には時間がすぎてたので成功したけど点数にはならなかった。

解けた問題

  • misc Welcome

  • Web Ramen

  • Reversing Seccompare

  • Web katsudon


  • misc Welcome
SECCON Beginners CTFのIRCチャンネルで会いましょう。
IRC: freenode.net #seccon-beginners-ctf

freenode.netで検索し、chatでニックネームとチャット名にseccon-beginners-ctfと入力し、connect

#seccon-beginners-ctf:競技に関する質問等はこちらで受けますFLAG:ctf4b {welcome_to_seccon_beginners_ctf}

  • Web Ramen

ラーメン https://ramen.quals.beginners.seccon.jp

URLにアクセスすると f:id:tawatino:20190528105228p:plain usernameを入力するころがある

SQLで引っ張ってきている

sqlインジェクションが刺さるか確認 f:id:tawatino:20190528105910p:plain union select の確認 f:id:tawatino:20190528110009p:plain

ささったがテーブル名も項目名もわからないのでとりあえず表示

UNION SELECT table_name, column_name from information_schema.columns #

flagという文字列で検索すると

f:id:tawatino:20190528110205p:plain

flagテーブルのflagにflagがありそう union select でflagを連結 f:id:tawatino:20190528110321p:plain

ctf4b{a_simple_sql_injection_with_union_select} 

  • Reversing Seccompare

ltraceを使うと1発で出てくる

ltrace ./doseccompare hoge
strcmp("ctf4b{5tr1ngs_1s_n0t_en0ugh}", "hoge")   = -5
puts("wrong"wrong
)                                    = 6
+++ exited (status 0) +++

※別解

hexdump -C seccompare をして眺めていると

f:id:tawatino:20190528110615p:plain いらない文字を消していく

ctf4b{5tr1ngs_1s_n0t_en0ugh}

  • Web katsudon
Rails 5.2.1で作られたサイトです。
https://katsudon.quals.beginners.seccon.jp
クーポンコードを復号するコードは以下の通りですが、まだ実装されてないようです。
フラグは以下にあります。https://katsudon.quals.beginners.seccon.jp/flag
# app/controllers/coupon_controller.rb
class CouponController < ApplicationController
def index
end

def show
  serial_code = params[:serial_code]
  @coupon_id = Rails.application.message_verifier(:coupon).verify(serial_code)
  end
end

Railsがわからないし諦めようとしたが、これ以外に他に解けそうな問題がなかったためダメ元で色々やってみた( ・∇・)

/flagにアクセスしたら文字がでてくる

BAhJIiVjdGY0YntLMzNQX1kwVVJfNTNDUjM3X0szWV9CNDUzfQY6BkVU--0def7fcd357f759fe8da819edd081a3a73b6052a

店舗一覧ページにて

レストラン昭和
デリバリー可能

シリアルコード: BAhJIhRyZXN0YXVyYW50c2hvd2EGOgZFVA==--a78497e11151cffc45af945a1a243138b6084140

とあるので「--」の前はbase64だと推測 /flagの文字列の「--」の前の部分だけをbase64でデコード

echo 'BAhJIiVjdGY0YntLMzNQX1kwVVJfNTNDUjM3X0szWV9CNDUzfQY6BkVU' | base64 -d
I"%ctf4b{K33P_Y0UR_53CR37_K3Y_B453}:ET%
ctf4b{K33P_Y0UR_53CR37_K3Y_B453}

面白かったけどバイナリ関係弱すぎて辛い_:(´ཀ`」 ∠): 来年も楽しみにしてます!

今更ながら兵●県警が捕まえた無限アラートを体験してみた。

なんのこと?

不正なプラグラムのアドレスを掲示板に書き込んだとして、兵●県警が13歳の女子中学生を補導した。 f:id:tawatino:20190407005201p:plain

書き込まれた不正プログラムとは

ブラウザに無限にアラートが表示されるだけのプログラム。 ブラウザが落ちることもないしタブを閉じればすぐ消すことが可能。

実際に体験

ブラウザを開き開発者ツールを開く(win→[F12] , Mac→[command]+[option]+[i])

[console]モードにて以下を入力し実行

> while(true){alert('test')}

すると f:id:tawatino:20190407010550p:plain この画面がOKを押しても無限に出現する。 もちろんそのタブを閉じると消える。

兵●県警に捕まる覚悟で公開する方法

グローバルIPアドレスが割り振られているサーバにてWebサーバを構築する 構築方法↓

tawatino.hatenablog.jp

構築したWebサーバの/var/www/html/配置に以下のファイルを作成(ファイル名:index.html)

<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>サンプルコード</title>
</head>
<body>
    <script>while(true){alert('消えないよ〜')}</script>
</body>
</html>

自分のサーバのグローバルIPアドレス掲示板やSNSに公開する。

※くれぐれも自己責任でお願いします。

Linuxにて指定サイズ以下のファイルを一斉削除

やりたいこと

ハニーポットにダウンロードされているもののなかから面白くないものを取り除く。

※データ量が少ないものは見ても何も面白くないもの。


サイズが1k以下のファイルを削除する。

find ./ -size 1k -exec rm {} \;

これで実行ファイルや、コード以外を楽に削除できる。

Macで学校からtracerouteができない!?

現象

Macにてtracerouteを実行した際、正常に動かなかった。

traceroute to 8.8.8.8 (8.8.8.8), 64 hops max, 52 byte packets
 1  172.16.95.254 (172.16.95.254)  2.617 ms  2.001 ms  1.745 ms
 2  * * *
 3  * * *
 4  * * *
 5  * * *
 6  * * *
 7  * * *
 8  * * *
 9  * * *

でもWebは見ることができる。

ということは学校にてICMPがフィルタリングされてるのでは?

hatena-MacBook-puro: user$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=119 time=27.240 ms
64 bytes from 8.8.8.8: icmp_seq=1 ttl=119 time=28.356 ms

そういうことではないらしい。。。

考察

もしかするとtracerouteで使っているプロトコルがICMPじゃなかったりして。。。

検索

ほうほう。使うプロトコルが違うのか。 てっきりICMPを使うかと思ってた。

MacでICMPを使ったtracerouteをするには「-l」オプションを使うらしい

ということで

hatena-MacBook-puro: user$ traceroute -l 8.8.8.8
Version 1.4a12+Darwin
Usage: traceroute [-adDeFInrSvx] [-A as_server] [-f first_ttl] [-g gateway] [-i iface]
    [-M first_ttl] [-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]
    [-t tos] [-w waittime] [-z pausemsecs] host [packetlen]

なぜか実行できない。

でもオプション「-P」でプロトコルを指定できるっぽい。

ひとまずやってみる

hatena-MacBook-puro: user$ traceroute -P icmp 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 64 hops max, 72 byte packets
 1  172.16.95.254 (172.16.95.254)  4.569 ms  2.435 ms  2.022 ms
 2  XXX.XXX.XXX.XXX (xxx.xxx.xxx.xxx)  1.302 ms  1.625 ms  2.394 ms
:
:
:
:
13  66.249.95.141 (66.249.95.141)  32.950 ms  27.799 ms  27.257 ms
14  google-public-dns-a.google.com (8.8.8.8)  26.981 ms  29.815 ms  26.451 ms

できた!

まとめ

Macでtracerouteをするには「-P ICMP」をつかう

Apache2とpython3でCGIをしたい!

環境


CGIを置くディレクトリを作成

セキュリティ上 /var/www/html/ 配下に置くのではなく、/var/www/配下に置く

$ sudo su -
# cd /var/www/
/var/www# mkdir cgi-bin

ApacheCGIモジュールを有効化

# a2enmod cgi
# systemctl restart apache2

cigd.confの設定

# vim /etc/apache2/mods-enabled/cgid.conf

下記のように作成

ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"   
<Directory "/var/www/cgi-bin/">
    Options +ExecCGI
    AddHandler cgi-script .cgi .py
    AllowOverride None
    Require all granted
</Directory>

各種説明

ScriptAlias /cgi-bin/ "CGIファイルがあるディレクトリ"   
<Directory "CGIファイルがあるディレクトリ(最後の「/」を忘れずに">
    Options +ExecCGI
    AddHandler cgi-script .cgi .py ←pythonファイルをCGIとして実行
    AllowOverride None
    Require all granted
</Directory>

設定を変えたら再起動

# systemctl restart apache2

CGIファイル

CGIファイルのパーミッションは適切なものに変更しないと500エラーになる。

# chmod 755 test.py
© 2018-2023 tt. All Rights Reserved.