Post

FEAT:🚩 Daily-AlpacaHack 「Site 2」Easy

HTTP/2 (h2c) 通信の基礎

FEAT:🚩 Daily-AlpacaHack 「Site 2」Easy

20260615-dail_alpaca-web-easy-site_2

Summary

本問は,HTTP/2 (h2c) 通信の基礎を確認する問題です.

  • Category: Web
  • Description: HTTP/2 に対応した Web サイトを作ったんだけど、アクセスできなくて困ってます
  • Tools & TechStack:
    • Nodejs
    • node::http2
  • Release: 2026/06/15

階層構造

1
2
3
4
5
6
.
├── compose.yaml
├── Dockerfile
└── server.js

1 directory, 3 files

ソースコードの調査

とりあえず,HTTP/2 でサーバに接続することができれば,Flag が入手できるようです.

server.js

1
2
3
4
5
6
7
8
9
import http2 from "node:http2";

const server = http2.createServer();

server.on("stream", (stream) => {
    stream.end("🦙 Welcome to my website 🦙\nFlag: Alpaca{REDACTED}");
});

server.listen(3000, () => { console.log("http://localhost:3000"); });

HTTP/2 の調査

HTTP/2に関して知識がなかったため,まず関連情報を調べました.基本的に,HTTP/2を使用するためにはTLS (HTTPS通信) を前提としています. しかし,問題文で与えられているソースコードでは,http通信を行う http2.createServer() が使用されています.本来,HTTP/2 over TLS を有効化するには,証明書と秘密鍵を読み込み,http2.createSecureServer() を使用する必要があります. そのため,httpsを使用していない環境下で h2c (HTTP/2 Cleartext)1 通信を行う方法を調べました.

h2c の接続方式

1. Prior Knowledge (事前知識) 方式

これは,HTTP/2 通信を直接行う方式です. クライアント側が接続開始時に,24バイトのマジック文字列を送信し,HTTP/2 通信を開始します.

curl での接続コマンド

1
$ curl --http2-prior-knowledge <target>

2. Upgrade (negotiation) 方式

こちらは,既存の HTTP/1.1 での通信から,HTTP/2 通信へアップグレードする方式です. クライアント側は,HTTP/1.1 のリクエストにUpgrade: h2cHTTP2-Settings という Header を付けて送信し,サーバー側が 101 Switching Protocols で応答すれば,h2c に切り替わります.

curl での接続コマンド

1
$ curl --http2 <target>

[!warning] RFC 9113 において,Upgrade 方式による h2c の開始は正式に 廃止 (非推奨) されています. Nodejsにおいても,この手法は実装されていません.

Exploitation

--http2-prior-knowledge オプションを使用して GET リクエストを送ることで,正常に h2c 接続が完了し,Flag が表示されました.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ curl -v --http2-prior-knowledge http://localhost:3000       
* Host localhost:3000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:3000...
* Established connection to localhost (::1 port 3000) from ::1 port 48824 
* using HTTP/2
* [HTTP/2] [1] OPENED stream for http://localhost:3000/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: http]
* [HTTP/2] [1] [:authority: localhost:3000]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.20.0]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: localhost:3000
> User-Agent: curl/8.20.0
> Accept: */*
> 
* Request completely sent off
< HTTP/2 200 
< date: Mon, 15 Jun 2026 02:14:32 GMT
< 
🦙 Welcome to my website 🦙
* Connection #0 to host localhost:3000 left intact
Flag: Alpaca{REDACTED}%

Post-Mortem & Dead ends

HTTP/2 に関して無知すぎた…

References

This post is licensed under CC BY 4.0 by the author.