akkietech’s diary

セキュリティ関連メインの自分用メモ書き。twitter: @akkietech

2/26 脆弱BBSを使って、CSRFとXSSを実践

■動機
簡単に言えばXSSCSRFを本格的に実践してみたくなった


CSRFが分からなかった
SOCをやっていながら、「CSRFを説明して」と聞かれたら
完璧どころかおおまかも説明できる自信がなかった

まず実践するにあたり復習から始めた
下記がすごく参考になった
https://qiita.com/sagami1991/items/23f72ab4e6552221188a

CSRF攻撃の内容として、リンクを踏むことで
攻撃側が用意したページに飛ばされ、スクリプトが動作するなどして
標的Webページに意図せぬ処理をさせるというもの


CSRFXSSの違いとは
クロスサイトリクエストフォージェリー(CSRF)
クロスサイトスクリプティング(XSS)

似ているようで全く違う

CSRFはあくまで、標的Webページでの意図せぬ
・ログイン情報変更だったり
掲示板への投稿だったり

と意図しない処理が行われるもの

一方でXSSは(多分だけど)、javascriptを使用して
cookie情報の窃取だったり
・Webコンテンツの改ざんだったり

難しんんだが、XSSの方が手法として様々なことが行える印象がある


■実践してみた
・脆弱な簡易掲示
以前にflaskで作成したWebページを改良し
CSRFXSS脆弱性を持つ簡易掲示板を作成した

ただflaskは、デフォルトでエスケープ処理が施されるため、
あえてエスケープ処理を外す必要があった

{% autoescape false%}
{{ [出力する内容] ))
{% endautoescape %}

こんな感じで{% autoescape false%}を明示する必要がある

CSRF攻撃用のWebサイト
そして上記リンクを参考にし、攻撃用サーバにアクセスするだけで
BBSに投稿されるというものを用意した

やってみた感想
CSRFできた!ほんとに直接BBSにアクセスしていないのに
 攻撃側で用意した内容が投稿されていた

XSSに関しては、今回は標的が掲示板なので
 格納型XSSを実践することにした。
 確かに下のスクリプトを、エスケープ無効にした掲示板に投稿すると
 アクセスするたびに警告が出るようになった

<script>alert('xss')</script>


■対策
各攻撃に対する基本的な対策はこんな感じらしい

CSRF
トークンを生成し、session内のトークンとformのhiddenで送られるトークンが一致しているか確認
一致している場合のみ正規の投稿なのでリクエストを受け付ける
一致していなければCSRFの疑いがある

XSS
出力内容をエスケープ処理させるのが良いらしい
phpであればhtmlspecialchars的なものを使うのかと

■まとめ
CSRFXSSを実際に見て触ることでどういった攻撃なのか
より理解することができた
というかこの2つは特にセキュリティ初心者にとっては分かりにくい攻撃なので
見て実践してもらうのが一番良いと思う

Web開発をしている人たちにとってこのあたりの理解は重要っぽいが
自分のようなSOCをやっている人にとってもこのあたりを
理解できることでセキュリティスペシャリストの階段を1つ登れるのかな

2/26 ミニメモ centos7アップデートによる不具合

なんかcentos7のシャットダウンの時にソフトウェアアップデートしたんやけど

そのせいでマウス統合もできんなって、解像度も小さいままになってしまった

 

GuestAddtions挿入しようとしてもこんなエラー出るし

 

Could not mount the media/drive '/Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso

 

 

それで約2時間くらい苦戦とクッソイライラしたが、DB連携成功前の

スナップショットが残ってたから、それ使った方が早いと遅めに気づく

 

その時の備忘録を元になんとかほぼ復元できた

結局アップデート後の不具合は解決できんかったけど

今回はBBSページを作ることを意気込んでやろうとしてたから、

むしろそれに時間費やされてくっそはらたった

でも戻ってなんとかよかった

 

スナップショットはほんまにほんまにほんんんまに大事やなと実感した

アップデート前とかほんまにちょっとしたことでも

バックアップとかスナップショットを取っとく癖は徹底してつけていこう

2/21 XSS(過去セスペ午後問題の実践)

情報処理安全確保支援士を勉強中

 

28年春の午後I問題でXSSに関する問題が出題され、

興味深かったので、真似て実践してみた

 

■概要

問題の内容としてはあるWebアプリケーションに

XSS脆弱性が含まれていて、その影響だったりを回答するというもの

 

問題文の中には脆弱なソースコード

攻撃に使われるスクリプトの例が載っていた

それを使用してみる

 

ただ脆弱なソースコードは多分Javaで作られているっぽい?

Javaはできんから、以前に作った脆弱なPHPログインサイトで試してみる

 

■わかったこと

XSSの影響は警告を表示させたりCookieを窃取するだけではなかった

 

javascriptを使ってページの書き換えも可能なので、

 偽の入力フォームを表示させ、入力内容を攻撃者に入力させることが可能

 

javascriptのframeを使うことで、偽のURLページをユーザにアクセスさせて

 例えばログイン状態でのみ表示されるような情報ですらも

 frameの内容が取得されることで、同時にユーザ情報も取得される

 

Webブラウザには「Same Origin Plicy」という、異なるドメイン

 Webサイトにはリクエストを送らないようにする仕組みがある

 ただ、今回の実践では違いを確認することはできなかった

 

今日は寝る前に軽く始めたつもりだったので、あまり踏み込んだ内容までは

実践できなかった

だからメモ書き程度で

 

もう少しじかんあるときにこのあたり本格的に実践できたらいいな

 

セスペの午後問題はほんとうに実践的でやりごたえがある

2/7 snortでSQLインジェクションの検知シグネチャ作成

前回SQLmapでSQLインジェクションやってみたの続き

Snortで検知シグネチャ作成
SQLmapまでで約2時間ほど経ってしまったが
ようやくシグネチャ作成に移る

とりあえずcontentにSQLiを狙ったっぽい文字列が含まれていれば
検知することにする
下記に示す例は上から順番に
「'」、「"」、「and」、「or」、「union」、「sleep」
の文字列が含まれている場合のルール

alert tcp any any -> any 80 (msg: "['] SQL Injection Detected"; content: "%27"; sid:1000011; rev:1;)
alert tcp any any -> any 80 (msg: "[\"]SQL Injection Detected"; content: "%22"; sid:1000012; rev:1;)
alert tcp any any -> any 80 (msg: "AND SQL Injection Detected"; content: "%20and%20"; nocase; sid:1000013; rev:1;)
alert tcp any any -> any 80 (msg: "OR SQL Injection Detected"; content: "%20or%20"; nocase; sid:1000014; rev:1;)
alert tcp any any -> any 80 (msg: "UNION SQL Injection Detected"; content: "union"; nocase; sid:1000015; rev:1;)
alert tcp any any -> any 80 (msg: "SLEEP SQL Injection Detected"; content: "sleep"; nocase; sid:1000016; rev:1;)

個人的な工夫をした点として
・'と"はURLエンコードで文字列を定義している
・andとorの両端に%20(半角スペース)を入れる

そしてsnort起動して、同じようにsqlmapを実行すると
snortのコンソール側でこんな感じで大量に出力される

02/07-23:35:08.087927  [**] [1:1000015:1] UNION SQL Injection Detected [**] [Priority: 0] {TCP} 192.168.179.44:37038 -> 192.16
8.179.10:80
02/07-23:35:08.087927  [**] [1:1000011:1] ['] SQL Injection Detected [**] [Priority: 0] {TCP} 192.168.179.44:37038 -> 192.168.
179.10:80
02/07-23:35:08.087927  [**] [1:1000014:1] OR SQL Injection Detected [**] [Priority: 0] {TCP} 192.168.179.44:37038 -> 192.168.1
79.10:80

そして上で定義したシグネチャのactionを全てrejectにして
再度両方実行すると
sqlmapでは下記のように出力され、サーバ情報が取得できなくなったことがわかる

[23:51:26] [INFO] testing connection to the target URL
[23:51:26] [INFO] checking if the target is protected by some kind of WAF/IPS
[23:51:26] [WARNING] turning off pre-connect mechanism because of connection reset(s)
[23:51:26] [CRITICAL] heuristics detected that the target is protected by some kind of WAF/IPS
do you want sqlmap to try to detect backend WAF/IPS? [y/N] y
[23:51:40] [WARNING] dropping timeout to 10 seconds (i.e. '--timeout=10')
[23:51:40] [INFO] using WAF scripts to detect backend WAF/IPS protection
[23:51:40] [WARNING] there is a possibility that the target (or WAF/IPS) is resetting 'suspicious' requests
[23:51:40] [CRITICAL] WAF/IPS identified as 'Generic (Unknown)'
are you sure that you want to continue with further target testing? [y/N] y
[23:52:14] [WARNING] please consider usage of tamper scripts (option '--tamper')
[23:52:14] [INFO] testing if the target URL content is stable
[23:52:14] [INFO] target URL content is stable
[23:52:14] [INFO] testing if POST parameter 'name' is dynamic
[23:52:14] [INFO] POST parameter 'name' appears to be dynamic
[23:52:14] [CRITICAL] connection reset to the target URL. sqlmap is going to retry the request(s)
[23:52:14] [CRITICAL] connection reset to the target URL
[23:52:14] [WARNING] HTTP error codes detected during run:
404 (Not Found) - 1 times

ちゃんと続行するのかどうか聞いてくれるあたり親切だな


■ちなみに
flaskで作ったログインページをsqlmapでやってみたらどうなるのか
試してみた

[00:12:21] [CRITICAL] all tested parameters do not appear to be injectable. Try to increase values for '--level'/'--risk' options if you wish to perform more tests. If you suspect that there is some kind of protection mechanism involved (e.g. WAF) maybe you could try to use option '--tamper' (e.g. '--tamper=space2comment') and/or switch '--random-agent'

どうやらデフォルトの実行レベルでは探りが足りないようなので最大限までリスクレベルをあげてみる

# sqlmap -u "http://localhost/login" --data "username=abcde&password=abcde" --risk=3 --level=5

sqlmapの出力とかwiresharkの中身を見てみると
POSTリクエスト送りまくって徹底的にリサーチしていることがわかる

やっぱりflaskってちゃんとセキュリティ的にも考慮して
作られるようになってるのかなと感じた

■まとめ
SQLi用のWebページで苦労したけど
シグネチャ作成自体は思ってた通りで、サクサク進められた

ただクオテーションとかorとかandだけを検知するロジックだと
かなりfalse positiveが増える気がするから
もっとうまくできないものかなとは思う
気が向いたらそこ詰めてみるか

sqlmapは本気出したらかなり徹底的にやってくれることも知れた

2/7 SQLmapでSQLi

SnortSQLインジェクションの検知シグネチャを作成するにあたり
SQLインジェクションのおさらいとSQLmapのを使ってみようと思った

■準備
SQLインジェクション脆弱性を持つWebページを用意する
 →これは適当にググって出てきたやつを参考にした
・SQLiの手法を改めておさらいする(下記項で記載)

========
※一応備忘録として
PHPMySQLに接続できないところで1時間ハマる

ディレクトリ、phpファイル、dbのアクセス権限とか
いじってたけど、結局どれも違って

phpコードでMySQL接続するときのホスト名
127.0.0.1
が悪かったみたいで
localhost
なら接続できた

<?php 
$mysqli = new mysqli('localhost', 'root', 'password', 'sql_injection');
?>

今回の場合はディレクトリとかphpファイルの権限は全く関係なかった
========


■SQLiの手法のおさらい
基本的なSQLi

' or 'x' = 'x' #

SQLiの脆弱性があるか調査

' or 'x'='x' UNION SELECT table_name,3 FROM information_schema.tables #

スキーマのやつ使って存在するテーブルを調査

' UNION SELECT COLUMN_NAME, 3 FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'user' #

目的のテーブル名を指定し、保持しているカラムを調査

' UNION SELECT name, password FROM user #

該当するカラムを使ってクエリを送る

DBの情報が返ってくる

■SQLmapを使う
以下のコマンドでとりあえず実行できる

# sqlmap -u "http://localhost:8000/sqli/vulsql.php" --data "name=guest&password=guest"

ただBlind SQLi用でデータベース名を取得するために
"--dbs"をつけて実行してみると

[22:44:46] [INFO] fetching database names
[22:44:46] [INFO] fetching number of databases
[22:44:46] [INFO] retrieved: 
[22:44:46] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions 
[22:44:46] [WARNING] in case of continuous data retrieval problems you are advised to try a switch '--no-cast' or switch '--hex'
[22:44:46] [ERROR] unable to retrieve the number of databases
[22:44:46] [INFO] falling back to current database
[22:44:46] [INFO] fetching current database
[22:44:46] [INFO] retrieved: 
[22:44:46] [CRITICAL] unable to retrieve the database names

と出てデータベース名の取得が失敗していた

本来であれば
[INFO] fetching database names
の後あたりでDB名が列挙されるはずだが

ちょっとここでもハマって、しばらくググってみたけど
解決しなさそうだし、今回のメインの趣旨ではないので
これに関しては諦めた
また今度かな

次回はSnortで検知シグネチャ作る

IDSIPSの遮断の違いをラブレターで例えたら1つの物語ができた

関連記事
2/2 IDSとIPSの遮断の違い(準備編) - akkietech’s diary
2/2 IDSとIPSの遮断の違い(実験編)その1 - akkietech’s diary
2/2 IDSとIPSの遮断の違い(実験編)その2 - akkietech’s diary
2/2 IDSとIPSの遮断の違い(実験編)その3 - akkietech’s diary
2/2 IDSとIPSの遮断の違い(実験編)その4 - akkietech’s diary
IDSIPSの遮断の違いをラブレターで例えたら1つの物語ができた - akkietech’s diary

今さらながらIDSも通信を遮断する機能があることを知ったので、
IDSとIPSの遮断方法の違いを解釈するために、ラブレターに例えてみたら
1つの儚い恋物語ができてしまいました。

タイトル:とうきょうらぶすとーり
===
■登場人物
A君 (シャイ、B子さんに気がある)
B子さん (特にA君に興味はない)
IDS郵便局 (以下D郵便局)
IPS郵便局 (以下P郵便局)
配達員X

■あらすじ
A君はB子さんにラブレターを送ることにした。

でもA君はシャイなので直接渡すのが恥ずかしい。
そこで郵便局経由で手紙を届けることにした。

まずP郵便局を使って手紙を届けることにした。
しかし手紙を送ってしばらくしても音沙汰がない。
どうやら手紙は届いていないようだ。

「ダメだなぁP郵便局は」と思い
今度はD郵便局を利用することに。

手紙を送ってしばらくするとチャイムがなった。
配達員Xが玄関にいた。

「すみません、あの手紙は破棄したっすw」

A君は
「この町の郵便局はどうなっているんだ...」
と思うばかりであった

めでたしめでたし
===

さてA君の手紙には何が起こったでしょか?

===
■解説

IDSIPS郵便局には変わったルールがある

それは「手紙の文章が一部でも禁止ルールに一致する場合は、手紙は破棄される」
というもの
つまりに郵便局が手紙の中身を確認し、破棄するかどうかを判断するのだ

禁止ルールのなかにはこういった文章も禁止されている
「結婚を前提に」
これが含まれれば即破棄される

さらにD郵便局とP郵便局では手紙をチェックする「タイミング」が少し違う

・先にIPS郵便局の場合
P郵便局は「受取人に届く前」に手紙の中身をチェックします。

もし禁止ルールに一致していた場合、
手紙はその場で破棄されます。
手紙が受取人に届くことはありません。


・次にIDS郵便局の場合
D郵便局では「手紙のコピー」をチェックします。

そしてそのコピーをチェックするタイミングは
受取人に手紙が届くほぼ同じタミングです。

この時、実はB子さんには手紙が届いていました。
「A君からだわ」とB子さんは手紙を開き、冒頭から読み始めました。
「以前からB子さんのことが...」

しかしその時!

配達員XがB子さんのところに突然現れ、
「あ、すみません、今の手紙は無しでw」
と言って手紙をビリビリに破いて破棄しちゃいます。

B子さんは
「今の手紙はなんだったんだろう..?」
と唖然。

また配達員Xは駆け足で送り主のところにも行き、
こう通達します。

「すみません、あの手紙は破棄したっすw」


ちなみにA君の手紙に書かれていた内容はこうだ
「以前からB子さんのことが気になっていました。」
「結婚を前提にお付き合いしてください。」

これがA君の手紙に起こった全貌だった...
===

さて、こっから普通のIDSIPSの話になりますが、
手紙や郵便局以外にも、他にこんな例えを使っていました。

禁止ルール => シグネチャ
配達員X => RSTパケット
「結婚を前提に」=> ペイロード(攻撃コード的な)

これを簡単に言うならば
・もしパケットにペイロードが含まれていて
・それがシグネチャに一致した場合
・インライン構成のIPSではパケットがDrop(破棄)され
・IDSではサーバとクライアントの両方にRSTパケットが送られ
 TCPコネクションが切断される

ポイントとしては
IDSの遮断では受信側にパケットが一旦届いてしまっているので、
届いたパケットによってはサーバに影響する可能性があるようです。

これが上でいう
B子さんは少し手紙を読んでしまっていた
ところにあたりますね。

ざっっっっくり言えばこんな流れかと思います。
IDSがこういった流れで通信遮断をするんだというのを
最近知ったので書きたくなりました。

ちなみにCentOSSnortをインストールして
シグネチャ作ってIDSとして遮断させたら
クライアントにもサーバにもバッチリRSTパケットが
送られて遮断されていることが確認できました。

シグネチャが作れるというおもしろさ。

■まとめ
ラブレターは手渡しが良い

おしまい

2/2 IDSとIPSの遮断の違い(実験編)その4

関連記事
2/2 IDSとIPSの遮断の違い(準備編) - akkietech’s diary
2/2 IDSとIPSの遮断の違い(実験編)その1 - akkietech’s diary
2/2 IDSとIPSの遮断の違い(実験編)その2 - akkietech’s diary
2/2 IDSとIPSの遮断の違い(実験編)その3 - akkietech’s diary
2/2 IDSとIPSの遮断の違い(実験編)その4 - akkietech’s diary
IDSIPSの遮断の違いをラブレターで例えたら1つの物語ができた - akkietech’s diary

■実験4
それではIPSの場合、どのようなパケットの流れになるのか?

残念がらSnortでインライン構成する気力は残っていなかったので
iptablesのフィルタリングでIPSの代わりとして
パケットをドロップすることにした

多分趣旨が全然変わってしまうと思うが、ちょっとした発見はあった

iptablesには接続を拒否するアクションとして主に2つあり
DROPREJECTがある

DROPはただ単にパケットを破棄し、送信元には何も伝えない
# iptables -I INPUT -p tcp --dport 80 -j DROP

REJECTDROPのように破棄し、送信元にエラーメッセージを送る
エラーメッセージの例としてはこんな感じ
# iptables -I INPUT -p tcp --dport 80 -j REJECT --reject-with icmp-host-unreachable
# iptables -I INPUT -p tcp --dport 80 -j REJECT --reject-with tcp-rest

ちなみにデフォルトはicmp-port-unreachableらしい

そしてHTTPリクエストを送った際の
各アクション違いをパケットキャプチャを使ってしてみる

DROPの場合
kali側からSynを送り続ける
もちろんずっとACKは返ってこない

REJECTの場合
kalig側がSynを送ると、設定したRejectのメッセージが返ってきて
一発で接続は切断される

どっちがFWとして良いのかは
ケースバイケースらしい

そして肝心のIPSの代替として使ってみて
もしIPSの遮断がRSTパケットを送る設定ならば
確かに受け取り側にはパケットは届かないだろう
当たり前だが



■まとめ
IDSの遮断について5回に渡って書いてみたがなかなか長いものになった
でも曖昧な理解だったそれぞれの機能の理解はかなり深めることができた
気がする

■余談
いつもはOneNoteにメモ用として書き残しているものを
ほぼそのままここのブログに載せていた


今回は内容的に張り切って投稿用に書いてみようとした


書く内容に凝ってしまうのとついついあれもこれもと
内容が長くなってしまい

実践よりも書くことのほうに時間が費やされたことは
今となってはすこし心外だなと思う

たしかに自分が調べるときに技術系のブログを参考にして
問題が解決できたことは多々あったので、

些細な内容ではあるがこういった記事が
自分よりもっとセキュリティについてビギナーな人の
参考になればとは思う

自分の情報発信のきっかけにもなるし

ただ
書くことがメインになってしまうと本末転倒になってしまいそうなので
やっぱり今後殴り書きのメモ程度を投稿することにしようと決心した

よっぽど伝えたいことがあればきばって書くかもしれないが

さて
このIDSIPSの締めの内容として
IDSIPSの遮断方法の違いをラブレターに例えてみる

つづく
IDSIPSの遮断の違いをラブレターで例えたら1つの物語ができた - akkietech’s diary