Metasploitable2でWebアプリの脆弱性を勉強する(SQLi その3)

※記事の内容は、ご自身が管理するサイト以外には絶対に使用しないでください。

[OWASP TOP10] A1_Injection_SQLi_3_Insert_injection_Register


f:id:jiranyan:20190305183631p:plain

Insert injection・・・なんか曖昧です。Registerなので登録時のインサートをインジェクションしろ!ってことでしょう。

例によって、どのようなサイト(機能)かどうかを調査します。

お題のとおりユーザ登録画面です。

f:id:jiranyan:20190305184001p:plain

ブラウザからどのようなリクエストを送信しているか調査します。

usernameとpassword(確認用含む)、signatureなどを送信しています。

f:id:jiranyan:20190307082251p:plain

今回は脆弱性診断ぽく、パラメータに「'」を挿入してアプリケーションの動作を確認してみます。(test0')

f:id:jiranyan:20190307082607p:plain

さすがの脆弱なシステムです、エラー(システム情報)が表示されました。末尾のシングルクォートがSQLの一部と解釈されエラーとなってます。

f:id:jiranyan:20190307082939p:plain

表示されたSQLを見ると、パラメータに挿入した「'」がSQLに組み込まれていることがわかります。SQLiは効きそうです。

INSERT INTO accounts (username, password, mysignature) VALUES ('testuser0','testuser0','test0'')

上記のSQLは「test0''」にシングルクォートが1つ余計に入っているため文法エラーを引き起こしていますので、試しにパラメータに挿入する文字列を「')-- 」にして強制的にSQLを終了させ、末尾の余計な文字列はコメント扱いにしてみます。

SQLのイメージは下記のようになります。

INSERT INTO accounts (username, password, mysignature) VALUES ('testuser0','testuser0','test0')-- ')

パラメータに「')-- 」を挿入します。

f:id:jiranyan:20190307085539p:plain

正常にユーザ登録が完了しました。末尾のコメントが有効に作用し正常にInsert文が実行されたようです。

f:id:jiranyan:20190307090028p:plain

SQLiが効いていることはわかりましが、なにか悪用できないか考えてみます。ご丁寧なエラー情報によりアカウント情報が格納されているテーブル(accounts)のカラム(username, password, mysignature)がわかります。攻撃者としては認証情報が欲しいところです。Metasploitable2でWebアプリの脆弱性を勉強する(SQLi その1)で利用したアカウント情報を表示する機能がありますので、攻撃者が自らのアカウントを登録する際に「mysignature」に他ユーザのパスワード(パスワード平文・・・)を挿入できるかもしれません。

SQLのイメージです。mysignature列に副問い合わせで「admin」のパスワードを挿入するイメージです。

INSERT INTO accounts (username, password, mysignature) VALUES ('hogehogehoge', 'hoge',(select password from (select password from accounts where username='admin') as temp1))

試してみます(ブラウザからのリクエストを改ざん)

f:id:jiranyan:20190307092310p:plain

パラメータ「password」の値「hoge」のあとに「',(select password from (select password from accounts where username='admin') as temp1))-- 」を挿入するイメージです。

SQLのイメージです。

INSERT INTO accounts (username, password, mysignature) VALUES ('hogehogehoge', 'hoge',(select password from (select password from accounts where username='admin') as temp1))-- ', 'hogehoge')

アカウント登録に成功しました。

f:id:jiranyan:20190307092935p:plain

試しにカウント情報を表示する機能を使って、「admin」のパスワードが取れるか確認してみます。

f:id:jiranyan:20190307093048p:plain

f:id:jiranyan:20190307093103p:plain

Signatureに「admin」のパスワードが格納されていることが確認できます。

SQLiもそうなのですが

  • アプリのエラー処理でSQLを含むエラー情報を画面に表示させている
  • パスワードを平文で格納している

のような脆弱性にも気をつけなければなりませんね。