[{"data":1,"prerenderedAt":311},["ShallowReactive",2],{"navigation_docs":3,"-article010":44,"-article010-surround":308},[4,8,12,16,20,24,28,32,36,40],{"title":5,"path":6,"stem":7},"開発者ブログをはじめました","/article001","article001",{"title":9,"path":10,"stem":11},"えるろだという名前について","/article002","article002",{"title":13,"path":14,"stem":15},"サイレントセレナからコードをコピペしているという話","/article003","article003",{"title":17,"path":18,"stem":19},"えるろだのウェブデザインの話","/article004","article004",{"title":21,"path":22,"stem":23},"カスみたいなエラーの話","/article005","article005",{"title":25,"path":26,"stem":27},"けーろだの愚痴とえるろだの保守","/article006","article006",{"title":29,"path":30,"stem":31},"サービスは呪い","/article007","article007",{"title":33,"path":34,"stem":35},"バトルKaitaiStruct","/article008","article008",{"title":37,"path":38,"stem":39},"リプ会主専用ダウンローダ ～KARTE","/article009","article009",{"title":41,"path":42,"stem":43},"サプライチェーン対策","/article010","article010",{"id":45,"title":41,"body":46,"description":99,"extension":302,"layout":303,"links":303,"meta":304,"navigation":305,"path":42,"seo":306,"stem":43,"__hash__":307},"docs/article010.md",{"type":47,"value":48,"toc":293},"minimark",[49,52,56,75,78,109,141,145,157,160,163,166,169,181,184,191,201,214,230,233,236,239],[50,51,41],"h1",{"id":41},[53,54,55],"h2",{"id":55},"サプライチェーン攻撃って何",[57,58,59,60,64,65,68,69,71,72,74],"p",{},"コンピュータは0と1で動くが当然ながら0と1でプログラムを書くわけがない。\nよって誰かの作った便利ツールを使って良しなに簡単に書くのが通常だ。\nしかしその『誰か』が乗っ取られて正規のパッケージとして悪意のある便利ツールを使ってしまったら攻撃が成立してしまう。\n特に最近はフロントエンドで使用されている ",[61,62,63],"code",{},"npm"," というツールで配布されている一部のパッケージが汚染された ",[61,66,67],{},"Shai-hulud"," というサプライチェーンが猛威をふるっていた。\nえるろだは ",[61,70,63],{}," を使っている。偶然にも汚染されたパッケージはダウンロードしなかったが対策を打たなければどこかのタイミングで死ぬと考えた。\nまた、 ",[61,73,63],{}," 以外のサプライチェーン攻撃の穴も塞いでおくべきと考えた。",[53,76,77],{"id":77},"フロントエンド",[57,79,80,82,83,85,86,89,90,102,103,105,106,108],{},[61,81,63],{}," を使っているので危機的である。\n今回 ",[61,84,63],{}," から ",[61,87,88],{},"pnpm"," という上位互換ツールに移行し、以下の対策を行った",[91,92,93],"sup",{},[94,95,101],"a",{"href":96,"ariaDescribedBy":97,"dataFootnoteRef":99,"id":100},"#user-content-fn-pnpm",[98],"footnote-label","","user-content-fnref-pnpm","1","。なお ",[61,104,88],{}," は ",[61,107,63],{}," に便利なセキュリティ機能を付けたものの認識だ。",[110,111,112,118,130,133],"ul",{},[113,114,115,117],"li",{},[61,116,63],{}," でインストールしてきたときにスクリプトの自動実行を許さない",[113,119,120,121,129],{},"バージョンやハッシュ",[91,122,123],{},[94,124,128],{"href":125,"ariaDescribedBy":126,"dataFootnoteRef":99,"id":127},"#user-content-fn-hash",[98],"user-content-fnref-hash","2","の検証と、失敗したらビルドを失敗させる",[113,131,132],{},"ハッシュが書かれたファイルを必ず使ってインストールする",[113,134,135,136],{},"出て24時間以内のパッケージは使わない\n",[110,137,138],{},[113,139,140],{},"24時間あればTwitterとかのニュースで汚染されているという警告が流れてきて自分も気づいているという想定",[53,142,144],{"id":143},"docker","Docker",[57,146,147,148,156],{},"Dockerはいわゆる仮想マシン",[91,149,150],{},[94,151,155],{"href":152,"ariaDescribedBy":153,"dataFootnoteRef":99,"id":154},"#user-content-fn-vm",[98],"user-content-fnref-vm","3","と考えてもらってよい。\nDockerはコンテナという仮想マシンの枠組みを使い、どの環境でも同じ環境を再現して環境差による動作の違いを無くしたり、仮に侵害されてもコンテナが動いているマシンに侵害されることができないといった、モダンな開発には欠かせない便利ツールだ。",[57,158,159],{},"一般にDockerイメージというものが配布されていてそれを使ってコンテナを建てるが、当然ながら自分の書いたえるろだコードもコンテナに入れ込みたい。よって一般配布のDockerイメージを参照してそれをもとに自分用にカスタマイズして新たなDockerイメージを建てる。",[57,161,162],{},"配布されているDockerイメージはバージョン単位で固定していたがハッシュ単位の固定はしていなかった。Dockerイメージを参照する全ての箇所でハッシュを指定することで一意にイメージが定まるようにした。",[53,164,165],{"id":165},"バックエンド",[57,167,168],{},"実はハッシュ単位で固定せずパッケージをインストールしていた。",[57,170,171,172,180],{},"これはPythonのパッケージと、Kaitai-Struct-Compiler(以下ksc)というyaml形式で書かれたバイナリファイルの定義をPythonコードに変換する",[91,173,174],{},[94,175,179],{"href":176,"ariaDescribedBy":177,"dataFootnoteRef":99,"id":178},"#user-content-fn-ksc",[98],"user-content-fnref-ksc","4","ツールの2つのパッケージだ。",[57,182,183],{},"Pythonパッケージはpip-compileによってハッシュ単位の指定をするようにした。",[57,185,186,187,190],{},"kscはビルド済ツールを ",[61,188,189],{},"apt"," でインストールしていたがこれでハッシュ指定はつらそうと考えた。そこで自分はソースコードをDockerイメージ作成時にビルドすることにした。",[57,192,193,196,197,200],{},[61,194,195],{},"git submodule"," というものでえるろだのソースコードにハッシュ単位で定まった ",[61,198,199],{},"ksc"," のソースコードを入れ込み、Dockerイメージ作成時にビルドする。",[57,202,203,204,207,208,210,211,213],{},"また、ここで ",[61,205,206],{},"マルチステージビルド"," という、ビルド用のDockerイメージを作ってさらにそれを使ってDockerイメージを作成するという仕組みを使った。\nこれにより ",[61,209,199],{}," のビルドだけをするDockerイメージを作り、その ビルドされた ",[61,212,199],{}," を使ってリプレイファイルの定義のコンパイルを行うだけのDockerイメージを作成、それによってできたソースコードのみを最終成果物であるDockerイメージに入れ込むということにした。",[57,215,216,217,219,220,222,223,226,227,229],{},"これによって最終成果物に ",[61,218,199],{}," 及び ",[61,221,199],{}," を動かすにあたって必要な ",[61,224,225],{},"java"," が載らないようになった。これで仮に ",[61,228,225],{}," とかに脆弱性があってバックエンドが動いているときにそれが踏まれる、ということが無くなった。",[53,231,232],{"id":232},"所感",[57,234,235],{},"なんか最近脆弱性とかサプライチェーン攻撃とか出過ぎてるだろ。",[57,237,238],{},"AIとかでソースコードを探索させてサクサク脆弱性を見つけては攻撃されて、守る側は後手後手に回る現状。一応それらしい対策は打ったがどこまで持つか…",[240,241,244,249],"section",{"className":242,"dataFootnotes":99},[243],"footnotes",[53,245,248],{"className":246,"id":98},[247],"sr-only","Footnotes",[250,251,252,266,275,284],"ol",{},[113,253,255,256,258,259],{"id":254},"user-content-fn-pnpm","このブログも ",[61,257,88],{}," 化による改修を行った。 ",[94,260,265],{"href":261,"ariaLabel":262,"className":263,"dataFootnoteBackref":99},"#user-content-fnref-pnpm","Back to reference 1",[264],"data-footnote-backref","↩",[113,267,269,270],{"id":268},"user-content-fn-hash","これが一致していれば0と1の羅列がほぼ一意に定まる。ごくごく稀にハッシュが同じだが違う0と1の羅列が一致するということがあるが、天文学的な確率と考えてもらって構わない。むしろしょっちゅう被ってたらそれは脆弱性と考えてよい。つまりハッシュが一致していれば偽のパッケージとは考えられない。 ",[94,271,265],{"href":272,"ariaLabel":273,"className":274,"dataFootnoteBackref":99},"#user-content-fnref-hash","Back to reference 2",[264],[113,276,278,279],{"id":277},"user-content-fn-vm","正確には違うが一旦簡単のために仮想マシンといった。勿論母艦のカーネルリソースを使ってソフトウェアを動かしているので仮想マシンではないことは理解している。 ",[94,280,265],{"href":281,"ariaLabel":282,"className":283,"dataFootnoteBackref":99},"#user-content-fnref-vm","Back to reference 3",[264],[113,285,287,288],{"id":286},"user-content-fn-ksc","えるろだはサイレントセレナからリプレイファイルの定義をコピペしている。サイレントセレナでkscを使ってリプレイファイルの構造を定義していたので差異が出ないようにえるろだでもkscを使うようにした。 ",[94,289,265],{"href":290,"ariaLabel":291,"className":292,"dataFootnoteBackref":99},"#user-content-fnref-ksc","Back to reference 4",[264],{"title":99,"searchDepth":294,"depth":294,"links":295},2,[296,297,298,299,300,301],{"id":55,"depth":294,"text":55},{"id":77,"depth":294,"text":77},{"id":143,"depth":294,"text":144},{"id":165,"depth":294,"text":165},{"id":232,"depth":294,"text":232},{"id":98,"depth":294,"text":248},"md",null,{},true,{"title":41,"description":99},"EEnkGFZShwFK0mavz_S1finxW8sf5BxbGLkQipXGAH8",[309,303],{"title":37,"path":38,"stem":39,"description":310,"children":-1},"カルテちゃそ～",1779643912905]