セキュリティ
YCにハッキングして潜り込んだ
I got into YC by hacking it (obaid.wtf)
要約
著者は、Y Combinatorの応募プロセスで使用されるPaxelというツールに脆弱性があることを発見しました。この脆弱性を利用すると、応募者のコーディングスコアを偽造してデータベースに送信することが可能でした。著者がこの問題を公開すると、YCは迅速に対応し、脆弱性を修正するとともに、著者をStartup Schoolに招待しました。
全文翻訳
tldr: Y CombinatorがPaxelを通じて世界中の10万人以上の創業者を評価していることを発見しました。それを(イースターエッグの可能性あり)壊し、検証されていないhmacのおかげで、誰でもランキングデータベースに任意のスコアを偽造してプッシュできる脆弱性を見つけました。最新情報: YCは立派にも、気にも留めませんでした。最初の公開開示からわずか数時間後に、Jared Friedman自身が返信し、パッチを発表し、この夏サンフランシスコで開催されるStartup Schoolへの参加を招待してくれました!12日前にメールで非公開で開示しても返信はありませんでした。しかし、少なくとも公にはプロセスが機能しました。Jared Friedman、2026年7月11日これは、私が最初に開示を公開した以前のドラフトの書き直しです。ひどく書かれており、睡眠不足で、公開するのに十分だと思えませんでした。— — — すべては6月初旬に始まりました。Startup School 26の応募フォームを見つけたときです(Dhanushからの紹介:Audora S26、信じられないようなものが登場します!!)。今年のYCは、応募の一部としてPaxelというものを使うように求めてきました。私はスクリプト、非常に使いやすいcURLワンライナーを実行し、私のコンピュータに何かをインストールし、私が書いたすべてのコード行をコーディングエージェントで分析し、レポートをコンパイルしてYCのサーバーにアップロードする必要がありました。Paxelのメインサイトによると、主な機能は自分の仕事を「可視化」し、「あなたはどのアーキタイプですか?」や「あなたの最大の失敗は何ですか?」のような楽しい属性を割り当ててもらえることです。それは楽しそうでした。しかし、それがどのように機能するか正確に知りたかったのです。そして私の好奇心が強迫的な領域に忍び寄り始めると、それは伝説的な失敗に終わるか、何か偉大なことをするか、どちらかになります。幸いなことに、この場合は後者でした。また、嘘はつけません:私はそれをハッキングしたかった(または必要としていた)のです。応募書類を作成する上で不利な立場からスタートすることは分かっていました(正式なアイビーリーグ教育がないため)、しかしこれが受け入れを確認するための、迅速で確実な方法になると知っていました。私は現実逃避していません、もしそれができたらそれは狂っているだろうと知っていましたが、なぜすべてを賭けないのでしょうか?Paxel自身のサイトによると、これまでに120万人以上のコーダーがレポートをYCにアップロードしています。そしてその数字を見ると、私が世界で最初にすべてを理解し、壊した人間であることは正直ショックです。— — — 話を始める前に、余談ですが、エージェント対応LLMが登場して以来、世界の「ハック」の相対的な功績は大幅に減少したと思います。もちろん、LLMがそれらをどれほど簡単にしたかによって、それは現実に一致します。しかし、それらの多くの奇妙な盲点と、知性に対するある種の「ハッキング」または対立的なアプローチの欠如の両方のため、その容易さはいくぶん過大評価されていると思います。それが安全性の抑制によるものか、単にトレーニング方法によるものかは、別の機会に議論することにします。したがって、それらが世界を変えるのは、同じ教材を10倍、時には50倍少ない時間で(調査、捜査)進めるのを助けることですが、LLMとコミュニケーションを取り、LLMがハッキング可能なものはすべてそうではないと主張するときに、自分の心を鋭く独立させておくことはしばしば困難です。— — — Paxelは信じられないほどのUXを持っており、すべてが単一のワンライナー curl -fsSL https://paxel.ycombinator.com/upload.sh | bash から処理されます。それはあなたのシステム全体を自動的にスキャンし、質問を促し、アップロードを処理します—その後、あなたは何も心配する必要はありません。したがって、最初の出発点は、当然ながら、このインストールスクリプトでした。私は最初にそれを4つの別々のモジュールに分割しました。私がそれを完全に壊そうとしたとき、私が与えたすべてのLLMはひどく幻覚を見始めました(コンテキストウィンドウサイズの増加は完璧ではありません!)。インストールスクリプトは、実際には自分で実行されませんでした。それはRubyアプリをホストするDockerイメージ全体をダウンロードし、それを展開し、あなたのコンピュータにインストールされたDockerを通じてローカルで実行しました。したがって、アプリは実際には2つの部分に分かれています:① ─▶ upload.sh 302KBのインストールスクリプト。認証を処理し、プロジェクトを検出し、Git履歴を抽出し、Dockerを初期化します。② ─▶ Dockerイメージから展開されたRubyアプリ。各プロジェクトの実際のフルパイプラインを実行します。まず、すべてのチャットトランスクリプトをYCが発明した作業単位、「エピソード」にグループ化します。各エピソードは、PRごとのすべてのコミットです。それが失敗した場合、2時間のバースト期間内の各コミット。それが失敗した場合、すべてのチャットセッションが個々のエピソードになります。次に、それらをYCがスポンサー提供する(興味深い発見!)paxel-llm.ycombinator.comでホストされている無料のgpt-5.5プロキシにアップロードします。エピソードごとの要約を取得し、それを他のデータと組み合わせて、最終レポートをpaxel.ycombinator.com/api/v1/resultsにアップロードします。そしてここで、あなたがしたすべての仕事がYCによって採点され、スコアリングされ、ランク付けされ、地球上の120万人のコーダーのレポートがコンパイルされていることを発見しました。execution_leverage steering engineering_quality product_thinking planning これらは、LLMが採点し、1〜10のスコアと自由形式のメモを割り当てる5つの主要な軸です。そして、ここで最も gapingな脆弱性も見つけました。このプログラムは、分散/非中央集権型アプリケーションの非常に良い例です(すべてをプロプライエタリサーバーで実行して統合する必要はありません)。しかし、非中央集権型アプリケーションのことは、暗号化の非常に基本的な機能に大きく依存していることです。そして、このパイプラインには非常に、非常に重要なものが欠けていました。LLMプロキシは、各エピソードとともにナンス(nonce)を返します。このナンスは、LLMサーバーとアップロードサーバー間で共有されます。理論的には、これはLLM ─▶ ローカル ─▶ POST /v1/resultsから渡されるべきで、元のLLMの結果以外はエンドポイントで受け入れられないことを検証します。理論的には。しかし、起こったことは、このナンスがLLMの結果、スコア、メモの署名をエンコードするのに失敗したということです。そのため、ナンスは検証されましたが(サーバーは無効または欠落したナンスのリクエストを正しく拒否し、一度使用すると燃え尽きました)、署名が欠落していたため、エピソード全体とそのスコアは任意のスコアに変更され、YCにアップロードされる可能性がありました。そしてYCはそれを受け入れました。受け入れただけでなく、スコアをバフしたりメモを変更したりすると、同じプロジェクトのレポートは大きく異なりました。regular boosted exact same project, exact same chats. そして、さらに一歩進みました。同じワンライナー(PaxelのUXが大好きです!!)を使用して、paxel-boostedというハックを作成しました。これにより、世界中の誰でもミラーリングツールを起動することで、同じように偽造されたレポートをアップロードできるようになりました。ブーストプロキシを自己スポンサーしました。なぜなら、envを追加する必要があるのはひどいユーザーエクスペリエンスだからです。obaid.wtf — bash — boosted-paxel pre-patch ✓ post-patch ✗ 公開からYCがパッチを発表するまでの数時間で、私のユーザーの20人以上がYCのデータベースで世界トップ1%にランク付けされることができました。修正基本的な暗号化の2つの機能が欠けていました。blue+greenフィールドはハッシュに署名される必要があります。greenフィールドは密封され、暗号化される必要があります/v1/resultsによって受け入れられるすべてのフィールドを3つのカテゴリに分類できました(2つが重要で、1つがその他すべてをカバーします)、上記の図のように。1) LLM ─▶ /v1/resultsにほぼそのまま渡されるフィールド(上記のグラフィックで緑+青でハイライト)、これらはすべてナンスにhmacとしてロールされハッシュされるべきでした。ナンスはすでに検証されていましたが、これにより各ナンスが実際にLLMの応答に関連付けられていることが保証されます。nonce = hmac(request_id) ─▶ nonce = hmac(request_id + scores.steering + scores.product_thinking + ... + title) そして、これは実際にはYCが提供し発表したパッチであり、元のドラフトで提案したとおりです。2) (1) LLM ─▶ /v1/resultsにほぼそのまま渡され、(2) クライアント内で使用されないもの。上記のフィールドのサブセット(図で緑でハイライト)、これらはAEAD暗号(または非対称公開/秘密鍵)で暗号化されるべきです。サーバーのみが保持し共有するため、クライアントは5軸スコアリング、エピソードタイトル、メモなどの詳細を見ることができません。これはオプションであり、本質的には隠蔽ですが、最初から行われていれば、何を見ればよいのか決して知ることはできなかったでしょう。