インフラ勉強会 / 20180810 「作ってみようWAF」を聞きました&Ubuntuでやってみました。
みなさまこんにちは。 はてなでの6つめの記事は、@柴雑種さまの インフラ勉強会 20180810 「作ってみようWAF」を聞いた感想や、その後試してみたことのメモになります!
WAF😍😍 https://t.co/14zYsWprQ4
— たかのあきこ@野生のウサギ (@akiko_pusu) August 8, 2018
https://wp.infra-workshop.tech/event/作ってみようwaf/
LTの流れ
ハンズオンの流れ
LT自体は、ハンズオン形式で進めてくださいました。 ライブで伺っている段階では、ハンズオン用の環境をすぐには用意できなかったので、お話を伺うのに専念。
- CentOS7にApacheをインストールする
- mod_securityをインストールする
- 簡単なデモ用のconfを適用する
- デモでブロック対象になるパターンでアクセスしてみる
といった流れでした。
実際に同じタイミングで参加されていたみなさんも、「curlで叩いてみたら確かにブロックされた!」というコメントをされていたり、やはり実際にやってみるのは大事だなと感じた次第です。
フリートーク
30分くらいのハンズオンのあとは、参加されているみなさんの間でのフリートーク。 実際にWAFを導入したり、設定で色々ご経験がある方が割といらしたようで、こちらも大変参考になりました。
今であれば、今回のmod_securityのようなシグネチャ型(攻撃パターン、パラメータ定義に従ってフィルタする)方式だけでなく、一定間隔のアクセスパターンを判断したりして攻撃と判断するような、振る舞い型の防御策も採られているようで、いろいろ進化しているんだな..と思った次第。
(振る舞いを観測するものといえば、たとえばログを収集して解析するような、Splunkといったものも該当するのかな?)
とにかく、(現在運用の当事者ではないのですが)ワクワクしてお話を伺っておりました。
また、クラウドを利用した環境であれば、クラウド型のWAFを使うのが良い、といったお話も出ていました。 こちらに関しては、クラウドベンダーのエンドポイントにWAFを適用する場合、証明書はどこに置くの?といった質問も出ていました。 実際は、ベンダ側のDNSを利用するとかベンダに証明書を渡す、ただし証明書の更新は自分たちでやる...といった方法をとるようです。 (ベンダさんに色々お話を聞くと、このあたりは面白いと思います)
なるほど、ですね。
その他の話題
今回のWAFの件をもう少し踏み込んでみたり、OWASPについて触れてみたり、脆弱性のあるアプリケーションを攻撃してみるハンズオン...といったことも良さそう、という話題が出ていました。 あとは、マルウェア、ボットウェア(miraiとかその亜種とか)のソースコードを読んでみようといったものなど。
まずは@柴雑種さま、お話ありがとうございました!
以下は、あとからUbuntuにmod_securityを組み込んでみたので、その覚書になります。
Ubuntuでやってみる
ハンズオンではCentOS7をベースにということでしたが、手っ取り早く立ち上げられる環境がなかったので、Ubuntuで試すことにしました。 以下、淡々とした作業のメモになります。
Vagrantで "bento/ubuntu-18.04” を指定してインストール。
そのあとに、apcheを追加してみます。
vagrant@vagrant:~$ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=18.04 DISTRIB_CODENAME=bionic DISTRIB_DESCRIPTION="Ubuntu 18.04 LTS” vagrant@vagrant:~$ sudo apt install apache2 vagrant@vagrant:~$ curl -I -v localhost:80 * Rebuilt URL to: localhost:80/ * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 80 (#0) > HEAD / HTTP/1.1 > Host: localhost > User-Agent: curl/7.58.0 > Accept: */* > < HTTP/1.1 200 OK HTTP/1.1 200 OK < Date: Sun, 12 Aug 2018 03:12:20 GMT Date: Sun, 12 Aug 2018 03:12:20 GMT < Server: Apache/2.4.29 (Ubuntu) Server: Apache/2.4.29 (Ubuntu) < Last-Modified: Sun, 12 Aug 2018 03:11:18 GMT Last-Modified: Sun, 12 Aug 2018 03:11:18 GMT < ETag: "2aa6-573345495bd3a" ETag: "2aa6-573345495bd3a" < Accept-Ranges: bytes Accept-Ranges: bytes < Content-Length: 10918 Content-Length: 10918 < Vary: Accept-Encoding Vary: Accept-Encoding < Content-Type: text/html Content-Type: text/html < * Connection #0 to host localhost left intact
うまく入りました。 確認は、Vagrant内であればcurlコマンドを利用しましが、VagrantのホストOS (Mac側) の localhost 8000 番にもポートフォワードして、ホスト側のブラウザでも確認できるようにしてみました。
ModSecurityの公式に行ってみる
Ubuntuの場合はこのあと、どうすれば良いのかな?ということで、公式サイトを見て見ます。 Ubuntu / Debianでは libapache2-mod-security をインストール、と書いてありますが、どうやら libapache2-mod-security2 な模様です。
ということで、aptで追加をいたしました。
$ sudo apt install libapache2-mod-security2 -- [ 中略 ] -- Setting up liblua5.1-0:amd64 (5.1.5-8.1build2) ... Setting up libapache2-mod-security2 (2.9.2-1) ... apache2_invoke: Enable module security2 Processing triggers for libc-bin (2.27-3ubuntu1) ...
公式に従うと、a2enmod を使ってモジュールを有効化しないといけない模様です。 (こちらが済むまでは適用されません)
NAME a2enmod, a2dismod - enable or disable an apache2 module vagrant@vagrant:/var/www/html$ sudo a2enmod Your choices are: access_compat actions alias allowmethods asis auth_basic auth_digest auth_form authn_anon authn_core authn_dbd authn_dbm -- [ 中略 ] -- usertrack vhost_alias xml2enc Which module(s) do you want to enable (wildcards ok)?
有効化 / 無効化
単純にa2enmodコマンドを打つと、どれを有効にしたいか聞かれます。
securityは mod_security2ではなくて、security2 のようなので、a2enmod security2 を実行してみます。 実行する前は、/etc/apache2/mods-enabled/ には mod_security関連の設定がありませんが、実行後は設定が追加されたのが分かります。
vagrant@vagrant:/var/www/html$ ls -la /etc/apache2/mods-enabled/security2.* ls: cannot access '/etc/apache2/mods-enabled/security2.*': No such file or directory vagrant@vagrant:/var/www/html$ sudo a2enmod security2 Considering dependency unique_id for security2: Module unique_id already enabled Enabling module security2. To activate the new configuration, you need to run: systemctl restart apache2 vagrant@vagrant:/var/www/html$ ls -la /etc/apache2/mods-enabled/security2.* lrwxrwxrwx 1 root root 32 Aug 12 04:04 /etc/apache2/mods-enabled/security2.conf -> ../mods-available/security2.conf lrwxrwxrwx 1 root root 32 Aug 12 04:04 /etc/apache2/mods-enabled/security2.load -> ../mods-available/security2.load
設定をもう少し読み解く
/etc/apache2/mods-enabled/security2.conf
さて、security2.confが読み込まれているようなので、こちらを確認してみます。 /etc/modsecurity/*.conf が追加で読み込まれること、それから、OWASPが提供しているCSRが読みこまれるよ、という設定になっています。
CRSとは、攻撃を検知するための基本的なルールセット (Core Rule Set) のことです。 *1
<IfModule security2_module> # Default Debian dir for modsecurity's persistent data SecDataDir /var/cache/modsecurity # Include all the *.conf files in /etc/modsecurity. # Keeping your local configuration in that directory # will allow for an easy upgrade of THIS file and # make your life easier IncludeOptional /etc/modsecurity/*.conf # Include OWASP ModSecurity CRS rules if installed IncludeOptional /usr/share/modsecurity-crs/owasp-crs.load </IfModule>
さらに /etc/ 以下の設定と、CRSについても確認してみます。
/etc/modsecurity/*.conf
パッケージでインストールした直後は、該当する *.conf は無く、modsecurity.conf-recommended という雛形が配置されています。 なので、いったんはこの設定が読み込まれていない状態。
有効化した場合の、一部の設定を載せてみます。
SecRuleEngine DetectionOnly SecRequestBodyAccess On SecAuditLogType Serial SecAuditLog /var/log/apache2/modsec_audit.log
/usr/share/modsecurity-crs/owasp-crs.load
/usr/share/modsecurity-crs/owasp-crs.load は、こんな内容でした。
## ## This file loads OWASP CRS's rules when the package is installed ## It is Included by libapache2-mod-security2 ## Include /etc/modsecurity/crs/crs-setup.conf IncludeOptional /etc/modsecurity/crs/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf Include /usr/share/modsecurity-crs/rules/*.conf IncludeOptional /etc/modsecurity/crs/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
有効化してみる
まず簡単に、modsecurity.conf-recommended を modsecurity.conf として配置し、設定を有効化してみます。 そのうえで、q=? といったパラメータをつけてアクセスしてみると...。
SecRuleEngine DetectionOnly なので防御はされませんが、定義にひっかかるようなリクエストだと、modsec_audit.log にメッセージが出力されるようになります。
$ sudo tail -f /var/log/apache2/modsec_audit.log -- [ 抜粋 ] -- --6881f71e-H-- Message: Warning. detected XSS using libinjection. [file "/usr/share/modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "64"] [id "941100"] [rev "2"] [msg "XSS Attack Detected via libinjection"] [data "Matched Data: accept found within ARGS:q: <script></script>"] [severity "CRITICAL"] [ver "OWASP_CRS/3.0.0"] [maturity "1"] [accuracy "9"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "OWASP_CRS/WEB_ATTACK/XSS"] [tag "WASCTC/WASC-8"] [tag "WASCTC/WASC-22"] [tag "OWASP_TOP_10/A3"] [tag "OWASP_AppSensor/IE1"] [tag "CAPEC-242"]
/usr/share/modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf にひっかかるよ、ということなので、そちらも見てみます。 対象業の近辺はこのようになっていました。
37 SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|XML:/* "@detectXSS" \ 38 "msg:'XSS Attack Detected via libinjection',\ 39 id:941100,\ 40 phase:request,\ 41 severity:'CRITICAL',\ 42 rev:'2',\ 43 ver:'OWASP_CRS/3.0.0',\ 44 maturity:'1',\ 45 accuracy:'9',\ 46 t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ 47 block,\ 48 ctl:auditLogParts=+E,\ 49 capture,\ 50 tag:'application-multi',\ 51 tag:'language-multi',\ 52 tag:'platform-multi',\ 53 tag:'attack-xss',\ 54 tag:'OWASP_CRS/WEB_ATTACK/XSS',\ 55 tag:'WASCTC/WASC-8',\ 56 tag:'WASCTC/WASC-22',\ 57 tag:'OWASP_TOP_10/A3',\ 58 tag:'OWASP_AppSensor/IE1',\ 59 tag:'CAPEC-242',\ 60 logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ 61 setvar:'tx.msg=%{rule.msg}',\ 62 setvar:tx.xss_score=+%{tx.critical_anomaly_score},\ 63 setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},\ 64 setvar:tx.%{rule.id}-OWASP_CRS/WEB_ATTACK/XSS-%{matched_var_name}=%{tx.0}"
ルールエンジンをOnにしてみる
では、SecRuleEngine DetectionOnly を SecRuleEngine On にして、apacheの設定をreloadしてみます。 この状態で、curlで同じように ?q= といったリクエストしてみると...。
403 Forbiddenになりました。
vagrant@vagrant:~$ curl -I -v http://localhost:80/?q=%3Cscript%3E%3C/script%3E * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 80 (#0) > HEAD /?q=%3Cscript%3E%3C/script%3E HTTP/1.1 > Host: localhost > User-Agent: curl/7.58.0 > Accept: */* > < HTTP/1.1 403 Forbidden HTTP/1.1 403 Forbidden < Date: Sun, 12 Aug 2018 05:18:51 GMT Date: Sun, 12 Aug 2018 05:18:51 GMT < Server: Apache/2.4.29 (Ubuntu) Server: Apache/2.4.29 (Ubuntu) < Content-Type: text/html; charset=iso-8859-1 Content-Type: text/html; charset=iso-8859-1 < * Connection #0 to host localhost left intact[f:id:akiko-pusu:20180813050113p:plain]
同じく、ブラウザからアクセスしてみても、403になることが分かりました。
ハンズオンの設定をあててみる
さて、Ubuntuのmod_securityを有効化した場合、サンプル設定ではOWASPのCSRに従った強力な?(厳しい)定義が適用されています。 こちらを、ハンズオンでの設定に置き換えてみます。
具体的には、/etc/apache2/mods-enabled/ 以下の security2.conf を書き換える形で、apacheを再起動しました。
ハンズオンでのサンプル設定
SecRuleEngine On SecRequestBodyAccess On SecDefaultAction "phase:1,deny,log,status:403" SecRule QUERY_STRING "zash11o" "id:'90000'" SecRule QUERY_STRING "zash.*11o" "id:'90001'"
再起動後、上記のパターンにあるとおり、リクエストのQueryStringにzash11oというパラメータをつけてみたところ...。
vagrant@vagrant:/etc/apache2/mods-enabled$ curl -i localhost:80?q=zash11o HTTP/1.1 403 Forbidden Date: Sun, 12 Aug 2018 05:32:37 GMT Server: Apache/2.4.29 (Ubuntu) Content-Length: 284 Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>403 Forbidden</title> </head><body> <h1>Forbidden</h1> <p>You don't have permission to access / on this server.<br /> </p> <hr> <address>Apache/2.4.29 (Ubuntu) Server at localhost Port 80</address> </body></html>
期待通りに弾かれました!
audit.log側もこのような感じ。 ブラウザでも確かに403が返りました。
vagrant@vagrant:/etc/apache2/mods-enabled$ vagrant@vagrant:/etc/apache2/mods-enabled$ sudo tail -f /var/log/apache2/modsec_audit.log Action: Intercepted (phase 2) Stopwatch: 1534051341366134 7127 (- - -) Stopwatch2: 1534051341366134 7127; combined=2252, p1=323, p2=1553, p3=0, p4=0, p5=375, sr=21, sw=1, l=0, gc=0 Response-Body-Transformed: Dechunked Producer: ModSecurity for Apache/2.9.2 (http://www.modsecurity.org/); OWASP_CRS/3.0.2. Server: Apache/2.4.29 (Ubuntu) Engine-Mode: "ENABLED"
まとめ
...ということで、@柴雑種さまのハンズオン的な内容を、Ubuntuに対してざっと試しみました。 まだ適用した、という簡単な自習ではありますが、どこに何を設定して、なにがログに書き出されるかというのは、やってみるとなるほど、と思いました。
あらためて、お話ありがとうございました!!