FEAT:🚩 Daily-AlpacaHack 「Guess IP」Easy
ブロードキャストアドレスの特性を利用したIPフィルタバイパス
20260608-daily_alpaca-misc-easy-guess-ip
Summary
本問は,ネットワークの予約済みIP (ブロードキャストアドレス) の特性を利用した問題です.
- Category: Misc
- Description:
10.0.0.1から10.255.255.254の中からIPアドレスを当ててみて!- Tools & TechStack:
- Python
- Release: 2026/06/08
階層構造
1
2
3
4
5
6
7
8
9
10
.
├── app
│ ├── app.py
│ └── Dockerfile
├── compose.yaml
└── server
├── Dockerfile
└── server.py
3 directories, 5 files
ソースコードの調査
compose.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
services:
app:
build: ./app
restart: unless-stopped
ports:
- "${PORT:-1337}:1337"
networks:
ctfnet: {}
server:
build: ./server
restart: unless-stopped
environment:
FLAG: "Alpaca{REDACTED}"
networks:
ctfnet:
ipv4_address: 10.99.99.99 # REDACTED. Different on remote. Can you guess the IP?
networks:
ctfnet:
driver: bridge
ipam:
config:
- subnet: 10.0.0.0/8
まず,10.0.0.1 から 10.255.255.254 を総当たりすることは不可能かつ,1度の試行で接続が切れます. もし総当たりするとすれば,sock.settimeout(1.0) のため少なくとも1つのリクエストに1秒はかかります. 最悪の場合は以下のようになり,$16,777,214 \text{ 秒}$ $\approx$ 約194日 かかる計算になるため現実的ではありません.
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) という記載から,このソケットでブロードキャストパケットの送信を許可する設定がされていることも分かりました.
app/app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import ipaddress
import socket
print("Example: 10.123.45.67")
ip = input("Enter IP> ").strip()
try:
ipaddress.IPv4Address(ip)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(1.0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.sendto(b"hello", (ip, 1234))
try:
data, _ = sock.recvfrom(4096)
print(data.decode())
except socket.timeout:
print("no response")
except Exception as e:
print(f"Error: {e}")
server.py では,sock.bind(("0.0.0.0", 1234)) で,全NICのUDPポートでなんらかのデータを受信した瞬間に,Flag文字列とアドレスをレスポンスする処理が記載されています. app.py で,sock.sendto(b"hello", (ip, 1234)) が使用されているため,正しいIPを入力できれば server.py にパケットが届き,FLAG が返ってくるはずです.
総当たりはできないため,有効なIPを指定する方法を考えていると,制限付きブロードキャストアドレスを思いつきました.
server/server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import os
import psutil
import socket
FLAG = os.environ.get("FLAG", "Alpaca{REDACTED}")
message = (
f"Hello from {psutil.net_if_addrs()['eth0'][0].address}\n"
f"Here is your flag: {FLAG}"
)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("0.0.0.0", 1234))
while True:
data, addr = sock.recvfrom(4096)
sock.sendto(message.encode(), addr)
制限付きブロードキャストアドレス
255.255.255.2551 は,予約済みIPであり,標準的なパブリック・プライベートIPとして割り当てられていません. このIPは,ブロードキャスト通信を行いブロードキャストパケットを使用します. ブロードキャストパケットは,他のサブネットにはルーティングされないため,送信元と同じネットワークセグメント内に存在するすべてのホスト に対してパケットを届けます.
この問題設定でも,server と app は同一のサブネットに属しているはずなので,このアドレスを使用することで FLAG が返ってくるはずです.
1
2
3
4
5
$ nc 34.170.146.252 32918
Example: 10.123.45.67
Enter IP> 255.255.255.255
Hello from xx.xxx.xxx.xx
Here is your flag: Alpaca{REDACTED}
Post-Mortem & Dead ends
SO_BROADCAST: そのソケットでブロードキャストパケットの送信を許可する設定