akkietech’s diary

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

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

関連記事
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

■実験3
では、準備編で書いていた内容
・IDSの遮断方法は検知後にクライアントとサーバの両方にRSTパケットを送ることで
 TCP接続を遮断すると書いてあった
 てことは接続初めのパケットはサーバに届いている?

これがyesかnoかを確かめる

リクエストの送り方は、実験その2でもやったようにBurp Suiteで改ざんしたリクエストを送る

は、途中からめんどくさくなったので
pythonであらかじめUser-AgentをセットしたHTTPリクエストを
送ることにした

import urllib2
url = "http://192.168.179.10"
agent = "Nmap Scanner"
req = urllib2.Request(url)
req.add_header("User-Agent", agent)
try:
    res = urllib2.urlopen(req)
except:
    pirint("request failed")

これで簡単に送れる
これでSnortを有効にした場合、"request failed"が返ってくる


そしてWebサーバ側のtcpumpで
・ポート80宛てのリクエス
・RSTパケット
の2つをキャプチャするように絞る
かつ「-A」オプションでASCII表示する
つまりリクエストとレスポンスの中身も見えるようにする

# tcpdump -A 'tcp[13] & tcp-rst != 0' or 'port 80'


すると出力結果流れとしてはこんな感じだった

kaliから80宛てにsynを受信

kaliからNmap Scannerを含むリクエストを受信
(予想通り)

kaliのIPからRSTパケットを受信
(予想通り)

Webサーバがhtmlページをkaliに送信
(想定外)

kaliがRSTパケットを送信

■考察
「接続初めのパケットはサーバに届いている?」の答えはyesでした

なのでDoS系のリクエストを受信した場合は
IDSで遮断設定してても影響が発生する可能性があると思う
そしてこれは別の機会に確かめてみたい
(コンピュターハイジャッキングのBOFの手法が使えるかな)


そして想定外の部分について
RSTパケットを受信していてもWebサーバは一旦レスポンスを返そうとしているのがわかる
これはRSTパケットが追いつかなかったからなのか

試しにKali側でもtcpdumpで同じフィルタ条件で確かめてみた

ブラウザやpythonでリクエストを送った時はレスポンスが受信できていないが
tcpdumpで出力してみると

なんとしっかりレスポンスのパケットが返ってきているではありませんか!!!!

これは意外、驚き

攻撃側はtcpdump等のキャプチャツールでパケットを見ていれば
例えばSQLインジェクションを狙った攻撃でも
ブラウザやスクリプトではレスポンスを確認でいなくても
パケットキャプチャレベルであれば確認できると考えられる

これにより、いかにIDSの遮断機能というのは
あくまで補助的な機能でしかない
ということが分かった

その4につづく
2/2 IDSとIPSの遮断の違い(実験編)その4 - akkietech’s diary

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

関連記事
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

■実験その2
NmapのOSスキャンだと大量にリクエストが発生してしまうので
Wiresharktcpdumpでパケットが追いきれない

その場合はBrup Suiteを使用して、firefoxからアクセスするときの
リクエストを改ざんすればよい
そしたら確認するパケットの数は格段に減る

Burp Suiteを使った流れとしては
firefoxで、Burp Suiteで設定されているIPをプロキシとしてを有効にする

Burp SutieでProxyタブ→Interceptタブから[Intercept is on]にする

firefoxで標的webサーバにアクセス

Burep Suiteでfirefoxのリクエストが捕捉されるので
NmapのUser-Agentを直接入力し[Forward]をクリック
(てかuser-agentじゃなくてもリクエストに'Nmap'が含まれればなんでも良い)

firefoxのブラウザでは「Connection reset」が返ってくる


つまり
リクエスト内にNmapが含まれるのでリクエストは遮断され
レスポンスが返ってこなかったことが確認できた


その3につづく
2/2 IDSとIPSの遮断の違い(実験編)その3 - akkietech’s diary

2/2 IDSとIPSの遮断の違い(実験編)その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


■実験その1
Kali Linux側でNmapを実行する
下記をコマンドを実行しOSスキャンを行うことで、
User-Agentを含むリクエストを投げることができる
# nmap -A -p 80 192.168.179.10

するとWebサーバ側のSnortのコンソールに下記のように表示される
02/01-10:45:44.691422 [**] [1:1000010:1] Nmap Access to port 80 [**] [Priority: 0] {TCP} 192.168.179.44:42288 -> 192.168.179.10:80

Webサーバ側のtcpdumpとKali側のWireSharkでも
WebサーバのIPからRSTパケットが送られていることが確認できた

これはつまりIDSの遮断機能により送られたRSTパケットであると思われる

そしてNmapのOSスキャンはというと
本来であればApacheWordPressのバージョンなどを持って帰って来てくれる
こんな感じで
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.2.15 (CentOS)
|-http-generator: WordPress 4.9.9

しかし今回はSnortでの遮断が有効化されているので、
そのあたりの情報は検出されなくなった
=>ばっちり遮断されてるじゃん!!

その2につづく
2/2 IDSとIPSの遮断の違い(実験編)その2 - akkietech’s diary

2/2 IDSとIPSの遮断の違い(準備編)

関連記事

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の遮断方法は検知後にクライアントとサーバの両方にRSTパケットを送ることで

 TCP接続を遮断すると書いてあった

 てことは接続初めのパケットはサーバに届いている?

 

・IPSのインラインでの遮断方法は、検知初めのパケットそのものを遮断しサーバに届かないようにする

 てことは検知後にクライアントにはRSTも届いていない?

 

たまにreset-both的なアクションをとるようなIDSもあるがそういうことなのか

ちなみになぜreset-serverがある?クライアントにrstを送らないことのメリットがある?

 

やりたいこと

snortrejectdrop?の2つくらいあったけど、上記のような違いで通信を遮断しているのか確かめたい

 

■準備

この実験では下記のホストと材料を使用する

Webサーバ側 (192.168.179.10)

Snort

iptables

tcpdump

 

Kali Linux側 (192.168.179.44)

Wireshark

・Nmap

・Burp suite

 

なんか今までやってきたことを存分に活かしている気がする

なんかわくわくする

 

・Webサーバ側

IDSには以前に導入したSnortを使用する

シグネチャの例としてsnortに、NmapのUser-Agentを含む場合に遮断するルールを追加する

 

ちなみにNmapのUser-Agentはこれ

User-Agent: Mozilla/5.0 (compatible; Nmap Scripting Engine; hxxps://nmap.org/book/nse.html

 

ルールは/etc/snort/rules/local.rulesファイルに下記を追加

reject tcp any any -> 192.168.179.10 80 (msg: "Nmap Access to port 80"; content:"Nmap"; sid:1000010; rev:1; )

 

とりあえずHTTPリクエストに「Nmap」が含まれる場合は遮断することにする

 

snortを起動 (-A consoleでコンソール出力させる)

# snort -c /etc/snort/snort.conf -A console

 

そしてポート80宛の通信が通るようにiptablesでポートをあける

# iptables -I INPUT -p tcp --dport 80 -j ACCEPT

 

さらにWebサーバ側でのパケットを見るためにtcpdumpも起動

# tcpdump port 80

 

ちなみにRSTパケットのみに絞りたければこう

# tcpdump 'tcp[13] & tcp-rst != 0'

 

Webサーバ側はこれで準備おk

 

 

・Kali Linux

こちらではWiresharkが使えるので、これでパケットを確認する

 

キャプチャ開始後に下記フィルタを設定

(http) || (tcp.flags.reset == 1)

これで

1. HTTP通信

2. RSTパケット

のいずれかを確認することができる

 

NmapとBrup Suiteは実際にリクエストを送る際に使用する

 

Kali Linux側の準備はこれで終了

 

準備だけでこれだけ書いてしまったので実験編に続く

2/2 IDSとIPSの遮断の違い(実験編)その1 - akkietech’s diary

2/1 ミニメモ snortが起動しない

とりあえずSnort久々に起動しようとして見たら全く起動しなかった

 

原因2つ

yum updateをしていなかったことによるカーネルパニックが発生していたらしい

 →yum -y updateで解決

 

MacOneNoteから起動コマンド貼り付けてたけど、以下のエラーが出てできず、1時間以上ハマってしまっていた

 

 DAQ BPF filter to '–A console' (pcap_daq_set_filterpcap_compileillegal token: –)! Fatal Error, Quitting..

 

 そして、なんとなく手打ちしたらあっさりできていた

 なんと、Macからコピペしていたコマンドをviで貼り付けるとこんななった

 

 snort -c /etc/snort/snort.conf <feff>-A console

 

 <feff>ってなんやねん...

 こんなんに1時間以上費やしたとか...

 

 ホストOSゲストOS間でコピペする際は気をつけよう

1/31 ミニメモ ハマっている時間==塩漬け

どうしてもkali側でのwiresharkが諦められなくて

もう一つ思い当たるものを1時間半やった

 

wiresharkはあくまでパケットキャプチャを解析するツール

 

そしてwifiアダプタはなにを使っても同じ

 

となると、パケットキャプチャを行なってるソフト自体に

Macとkaliで差があって、それが問題なのでは

と思った

 

で、色々試して見た

libpcapというのがキャプチャをするソフトというかライブラリというか

 

これのバージョンを確か見てみて、最新のを入れてみようしたけど

どうもうまく行かなそうだったんで1時間半で見切りつけて諦めた

 

もうmac側で十分にできるならもうそれでいいや

 

 

■余談

今日1時間半かけて色々やりながらふと思ったのは

こういう実技系に時間かけるのって株とかの投資に似ている

 

お金と一緒で自己投資は早い目に始めた方がいいし

投資した分だけリターンもある

 

ただ損切りのタイミングも、どちらのケースでも逃してはいけない

 

実践するのに時間を投資しているわけだが、上手くいくとは限らないし

下手するとあまりに生産性のないことに時間費やしすぎて

それ自体が時間の無駄になってしまっていたりする

 

それなら早めに見切りつけて、また日を開けてするとか

その時間を別のことに費やすとか

 

株でいう損切りのタイミングが重要だったりするのかも

 

悪い意味でハマっている時間 = 塩漬け状態

 

これはちょっといい気づきなったかもしれない

1/30 FlaskをSqlite3と連携させる

めっっっっちゃくちゃ苦戦

とりあえずflaskでの自作ページのログイン機能として
Register処理とLogin処理をSQLite3と連携させることを考えていた

dbファイルへのアクセスとしては
Registerが「書き込み」
Loginが「読み込み」
にあたる

Apacheの本番環境で動作させると
どちらの処理もdbファイルへのアクセスに問題があった

■背景
デバッグモードではDBへの連携はできていた
なのでApacheで動かしているときの動作に問題があるのだと気づいた

そしてログを確認
自分の場合は
tail -f /var/log/httpd/error_log

例えばRegisterページで登録しようとするとこのエラーが出ていた

sqlite3.OperationalError: unable to open database file

んーファイルがそもそも開けていないっぽい
開発環境でflask runでは処理できていたのに...

普通にdbファイルの権限の問題だと思って
chmodとかchownとか触りまくってたけど
そんな甘い世界ではなかった

そしてググりまくった結果判明した原因は3つ

原因1
dbファイルのパーミッション

原因2
__init__.pyでのdbファイルパスの渡し方

原因3
SELinuxによるアクセス制限


■原因1 dbファイルのパーミッション
これはとりあえずそう
ずっとrootでやってたこともありdbファイルを置くフォルダも全てrootでやっていた
だからapacheに変更

# chown -R apache:apache [dbファイルがあるフォルダ名]

まずこれが1つ

■原因2 __init__.pyでのdbファイルパスの渡し方
これはエラーログとかをコピペしてググりまくって
同じ境遇の人が記事書いているのを発見。

どうやらパスの渡し方が問題だったらしい

以下__init__.pyを一部抜粋

変更前

import os
from flask import Flask

app = Flask(__name__)
app.config.from_mapping(
		SECRET_KEY='dev',
		DATABASE=os.path.join(app.instance_path, 'FlaskApp.sqlite'),
	)

変更後

import os
from flask import Flask

app = Flask(__name__)

app.config.from_mapping(
		SECRET_KEY='dev',
		DATABASE=os.path.join('/var/www/FlaskApp/instance', 'FlaskApp.sqlite'),
	)

変更前のは公式のやつをそのまま持ってきてた
os.pathとapp.instance_pathを組み合わせてdbファイルのパスを取得しようとしている

そして変更後はdbファイルのパスを直接渡してみることにした

これでLoginは成功した、つまりdbファイルの「読み込み」はできるようになった
しかし、「書き込み」はできていなかった


■原因3 SELinuxによるアクセス制限
LoginはできてもRegisterはできなかった
つまり書き込み
何回やってもInternal Server Errorが返る

再度ログを確認してみる

sqlite3.OperationalError: attempt to write a readonly database

さっきとは微妙に違う
今回は明らかに権限が原因だと思ったので
またchmodとchownで色々してみたけどどれでもなかった

すると画面右上にあるエラーメッセージが上がっていることに気づいた

「AVC拒否」
SELinux は問題を検出しました」

うそだろ...?
ここにきてSELinuxによる制限どうこうが入ってくるのか?
たしかにCent7を使い始めたばかりだが

SELinuxのメッセージの詳細を確認したところ
やはり結局httpdがdbファイルへのアクセスを許可されていなかった

後々知ることになるが、SELinuxでの今回のエラーログはこんな感じで見れる
cat /var/log/audit/audit.log | grep "type=AVC"

type=AVC msg=audit(1548864798.247:345): avc: denied { write } for pid=8108 comm="httpd" name="FlaskApp.sqlite" dev="dm-0" ino=10397195 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_sys_content_t:s0 tclass=file


画面右上のメッセージをクリックして
さらに表示されている解決策となるコマンドを入力

# semanage fcontext -a -t httpd_sys_rw_content_t /var/www/FlaskApp/instance/FlaskApp.sqlite
# restorecon -v /var/www/FlaskApp/instance/FlaskApp.sqlite

#setsebool -P httpd_unified 1

#ausearch -c 'httpd' --raw | audit2allow -M my-httpd
#semodule -i my-httpd.pp

改行ごとのまとまりでそれぞれ解決策が異なるコマンドらしいが、
もうどっちでもいいので全てを入力した

そしてApacheを再起動

apachectl restart

きてる...

きてる!!!!!!
Registerがきちんと処理してくれた!!!!

ここでまさかのSELinixuが初対面でここまでしてくれていたとは...


■まとめ
学んだこととしては
・tail -f /var/log/error_logでエラーを確認することはとても大切
 そしてエラーログを元にググりまくるのもとても大切

パーミッションがいつもやっているようなchmodとかだけではなくて
 SELiuxのアクセス制御によっても行われている

・CentOS7に来てSELinuxと戦う必要が今後もあるかもしれない


これでDBとの連携はとりあえずは完了
あとは。。。なんだ

BBS作りか

■ちなみに
前回記事で書いたWifiアダプタ
注文したやつが届いたのやってみたが
そんなに変わらない印象

結局NEHの感度が悪いわけではなさそうだった。。。
まぁこれも勉強か