title: Netlifyの裏側とSHA-1
author: Amane Katagiri
summary: ねっとり
date: 2017-08-18T03:20:00+09:00
modified: 2020-09-27T02:42:00+09:00
category: tech
license: CC BY 4.0
rating: sfw
ai_summary: NetlifyでSHA-1ハッシュが衝突する2つの異なるPDFを公開した際、同じファイルとして扱われる現象を報告した記事。Netlifyがハッシュ値をキーにファイルを管理している仕様が原因で、内容が異なるファイルが同一視される問題が発生しました。ユーザー側での対策は難しく、サービス側でSHA-256への移行が進んでいるとされています。筆者はこの件を受け、サイトのバックエンド構成を変更しました。
ai_keywords: Netlify, SHA-1, ハッシュ衝突, ホスティングサービス, PDF, ファイル管理, SHA-256, 仕様, 技術ブログ

++(2020-09-27) **もうこのサイトのバックエンドはNetlifyではありません。**言及されているファイルへのリンクはama.ne.jp上のものに戻されています。++

先日投稿した[SHA-1をぶつけた](/post/sha1/)に対して、たくさんの反応ありがとうございました。

さて、この記事で生成した**SHA-1ハッシュが一致する**異なるPDFファイルへのリンクが、ama.ne.jp上のものからGitHub上のものへ変わったことにはお気づきでしょうか？

旧(on ama.ne.jp): [a.pdf](/appendices/sha1/a.pdf)と[b.pdf](/appendices/sha1/b.pdf)

~~新(on GitHub): a.pdfとb.pdf~~

それぞれのリンクを開くとおかしな点に気付きませんか？　今回はこの問題についての報告です。

[TOC]

# Netlifyって何？

[Netlify](https://www.netlify.com/)はイケイケのホスティングサービスで、以下のような特徴があります。

* GitHubとかのpushを契機にビルド、デプロイしてくれる。ビルドのタイミングはもちろん手動でも。
* 適当にやりたい時は、ファイルを直接アップロードしても公開できる。
* Let's Encryptに対応（向こうで取得と更新をしてくれる）している。
* 複数のブランチデプロイを使ってA/Bテストみたいなことができるみたい。
* スクリプトをくっつけたりとか自動minifyとか画像の最適化とか、他にも色んな細かい機能があるよ。

静的サイトの公開のために作られている上にホスティングまでくっついているので、他のCIを使ってシコシコタスクを書いて`gh-pages`にpushして……よりは楽な気がする。分からん。

# 何が起こったの？

そんな素晴らしいNetlifyですが、先程の旧リンクでは、どちらのリンクも赤い大仏のPDFファイルを指してしまいます。ファイルのアップロードミスでもリンクのミスでもなく、Netlifyの仕様のせいです。

Netlifyでは、SHA-1ハッシュをキーにしてファイルを管理しているそうです[^hashindex]。そのため、同じSHA-1ハッシュを持つ複数のファイルが全て同じファイルとして取り扱われました。ただし、このインデックスはサイトごとに独立したもので、他のサイトのファイルを差し替えるというような攻撃はできないそうです。

[^hashindex]: URL→SHA-1ハッシュ→ファイルみたいな感じなのかな？

おそらく、データを先頭から比較して最も小さいファイルが代表になるようです。

## 赤い大仏の方がデータが小さい（？）

```text
$ python
>>> red = open("red.pdf", "rb").read()
>>> blue = open("blue.pdf", "rb").read()
>>> red[:193]
b'%PDF-1.3\n%\xe2\xe3\xcf\xd3\n\n\n1 0 obj\n<</Width 2 0 R/Height 3 0 R/Type 4 0 R/Subtype 5 0 R/Filter 6 0 R/ColorSpace 7 0 R/Length 8 0 R/BitsPerComponent 8>>\nstream\n\xff\xd8\xff\xfe\x00$SHA-1 is dead!!!!!\x85/\xec\t#9u\x9c9\xb1\xa1\xc6<L\x97\xe1\xff\xfe\x01s'
>>> blue[:193]
b'%PDF-1.3\n%\xe2\xe3\xcf\xd3\n\n\n1 0 obj\n<</Width 2 0 R/Height 3 0 R/Type 4 0 R/Subtype 5 0 R/Filter 6 0 R/ColorSpace 7 0 R/Length 8 0 R/BitsPerComponent 8>>\nstream\n\xff\xd8\xff\xfe\x00$SHA-1 is dead!!!!!\x85/\xec\t#9u\x9c9\xb1\xa1\xc6<L\x97\xe1\xff\xfe\x01\x7f'
>>> red[192]
115
>>> blue[192]
127
```

## ファイル名に関係なく赤い大仏が出てくる

* [a.pdfが赤+b.pdfが青](https://sha1-collision-a.netlify.com/)
* [a.pdfが青+b.pdfが赤](https://sha1-collision-b.netlify.com/)

# どうやって直すの？

ユーザーでできる対策はないようです。順次、SHA-256を使ったインデックスに切り替えているとのことですが、詳細は分かりません。

# 最後に

というようなことを教えてもらった情報源のチャットログを紛失してしまいました。信頼ならない噂程度ということで。すみません。
