■■debian stretchにWAF(modsecurity)を導入する。
評価目的の環境構築なので、
DBはここでは決めず、動的コンテンツに関するテストも行わない。
$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 9.1 (stretch)
Release: 9.1
Codename: stretch
■攻撃のトレンドを把握する。
2013年との比較とかも参考に。
$ w3m -dump "https://www.owasp.org/index.php/Category:OWASP_Top_Ten_2017_Project" | \
awk '/☆/{gsub(" *☆ ","",$0);print}'
A1-Injection
A2-Broken Authentication and Session Management
A3-Cross-Site Scripting (XSS)
A4-Broken Access Control
A5-Security Misconfiguration
A6-Sensitive Data Exposure
A7-Insufficient Attack Protection
A8-Cross-Site Request Forgery (CSRF)
A9-Using Components with Known Vulnerabilities
A10-Underprotected APIs
■IPAを以下も参考にどの機能を使うかを検討する。
情報セキュリティ 10大脅威 2017
https://www.ipa.go.jp/security/vuln/10threats2017.html
Web Application Firewall 読本
http://www.ipa.go.jp/security/vuln/waf.html
■modsecurityのコメントにもある、代表的な以下2つの検出機能は使えるようにする。
SQLインジェクション
クロスサイトスクリプティング
$ apt-cache search modsecurity
libapache2-mod-security2 - Tighten web applications security for Apache
libapache2-modsecurity - Dummy transitional package
modsecurity-crs - OWASP ModSecurity Core Rule Set
$ apt-cache show libapache2-mod-security2 | \
awk 'BEGIN{flag=0}{if($1=="Description-md5:"){flag=0}}{if($1=="Description-en:"){flag=1}}{if(flag==1){print}}'
Description-en: Tighten web applications security for Apache
Modsecurity is an Apache module whose purpose is to tighten the Web
application security. Effectively, it is an intrusion detection and prevention
system for the web server.
.
At the moment its main features are:
* Audit log; store full request details in a separate file, including POST
payloads.
* Request filtering; incoming requests can be analysed and offensive requests
can be rejected (or simply logged, if that is what you want). This feature
can be used to prevent many types of attacks (e.g. XSS attacks, SQL
injection, ...) and even allow you to run insecure applications on your
servers (if you have no other choice, of course).
■OS=Linux(debian)、DB=Unknown、Webサーバ=Apache2の構成とする。
CRS (Core Rule Set) というシグネチャを導入する必要がある。
$ sudo apt-get install -y apache2 libapache2-mod-security2 modsecurity-crs
■apache2の待受ポートを、IPv4のlocalhostでのみアクセスを受け付けるよう変更する。
$ netstat -an | grep :80
tcp6 0 0 :::80 :::* LISTEN
$ sudo sed -i -e 's/\(Listen \)80/\1127.0.0.1:80/' /etc/apache2/ports.conf
$ sudo systemctl restart apache2
$ netstat -an | grep :80
tcp 0 0 127.0.0.1:80 0.0.0.0:* LISTEN
■apache2のログを有効にする。
$ awk 'BEGIN{cnt=0}{if($2=="a"){cnt=16;print}else if(cnt>0){cnt-=1;print $0}}' /etc/apache2/apache2.conf
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
CustomLog ${APACHE_LOG_DIR}/access.log combined
$ sudo apache2ctl configtest && sudo systemctl enable apache2 && sudo systemctl restart apache2
Syntax OK
Synchronizing state of apache2.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable apache2
■apache2のアクセス確認。
curlのプロキシ除外方法がホスト名を指定する必要がある点に注意。
$ sudo apt-get install -y curl w3m
$ w3m -dump_head -no-proxy 'http://127.0.0.1'; \
curl -v --noproxy 127.0.0.1 -s 'http://127.0.0.1/' | w3m -T text/html | head -3; \
sudo tail -f /var/log/apache2/access.log
HTTP/1.1 200 OK
Date: Sun, 13 Aug 2017 03:36:18 GMT
Server: Apache/2.4.25 (Debian)
Last-Modified: Sat, 12 Aug 2017 16:44:37 GMT
ETag: "29cd-556912526f428-gzip"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 3041
Connection: close
Content-Type: text/html
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sun, 13 Aug 2017 03:36:18 GMT
< Server: Apache/2.4.25 (Debian)
< Last-Modified: Sat, 12 Aug 2017 16:44:37 GMT
< ETag: "29cd-556912526f428"
< Accept-Ranges: bytes
< Content-Length: 10701
< Vary: Accept-Encoding
< Content-Type: text/html
<
{ [10701 bytes data]
* Curl_http_done: called premature == 0
* Connection
Debian Logo Apache2 Debian Default Page
It works!
127.0.0.1 - - [13/Aug/2017:12:36:18 +0900] "HEAD / HTTP/1.0" 200 302 "-" "w3m/0.5.3+git20170102"
127.0.0.1 - - [13/Aug/2017:12:36:18 +0900] "GET / HTTP/1.1" 200 10956 "-" "curl/7.52.1"
■以下のサイトを参考にapache2の「AH00558」エラーに対処
ubuntuにおけるapache2のAH00558エラーを解決する。
http://mk-55.hatenablog.com/entry/2014/07/07/004510
$ sudo awk -F] '/apache2/{a[$NF]+=1}END{for (n in a){print a[n],n}}' /var/log/syslog | sed -e 's/,/\n\t/g'
3 : AH00558: apache2: Could not reliably determine the server's fully qualified domain name
using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
$ sudo echo ServerName $HOSTNAME > /etc/apache2/conf-available/fqdn.conf
$ sudo a2enconf fqdn && sudo systemctl reload apache2
Enabling conf fqdn.
To activate the new configuration, you need to run:
systemctl reload apache2
■SecRuleEngineをDETECTION_ONLYモード(検出、ログ出力のみ)でmodsecurity機能を有効にする。
$ sudo cp /etc/modsecurity/modsecurity.{conf-recommended,conf}
$ grep -B 8 ^SecRuleEngine /etc/modsecurity/modsecurity.conf
SecRuleEngine DetectionOnly
$ sudo apache2ctl -M | awk '/sec|crs|head/'
$ find /etc/apache2/mods-available/ /etc/apache2/mods-enabled/ | awk '/sec|crs|head/'
/etc/apache2/mods-available/headers.load
/etc/apache2/mods-available/security2.load
/etc/apache2/mods-available/security2.conf
$ sudo a2enmod security2
Considering dependency unique_id for security2:
Enabling module unique_id.
Enabling module security2.
To activate the new configuration, you need to run:
systemctl restart apache2
$ sudo a2enmod headers
Enabling module headers.
To activate the new configuration, you need to run:
systemctl restart apache2
sudo systemctl restart apache2
$ sudo apache2ctl -M | awk '/sec|crs|head/'
headers_module (shared)
security2_module (shared)
$ find /etc/apache2/mods-available/ /etc/apache2/mods-enabled/ | awk '/sec|crs|head/'
/etc/apache2/mods-available/headers.load
/etc/apache2/mods-available/security2.load
/etc/apache2/mods-available/security2.conf
/etc/apache2/mods-enabled/headers.load
/etc/apache2/mods-enabled/security2.load
/etc/apache2/mods-enabled/security2.conf
■CRSシグニチャを確認する。
これが無いと検出出来ないのでパスが通っているか確認する。
$ grep -v "#\|^\$" /etc/apache2/mods-enabled/security2.conf
<IfModule security2_module>
SecDataDir /var/cache/modsecurity
IncludeOptional /etc/modsecurity/*.conf
IncludeOptional /usr/share/modsecurity-crs/owasp-crs.load
</IfModule>
$ grep -v "#\|^\$" /etc/apache2/mods-enabled/security2.conf | awk '/ \//{print "ls -l "$NF}' | sh
合計 0
-rw-r--r-- 1 root root 46 8月 13 02:38 /etc/modsecurity/default.conf
-rw-r--r-- 1 root root 8440 8月 13 03:50 /etc/modsecurity/modsecurity.conf
-rw-r--r-- 1 root root 373 12月 21 2016 /usr/share/modsecurity-crs/owasp-crs.load
$ grep -v "#\|^\$" /usr/share/modsecurity-crs/owasp-crs.load
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
$ grep -v "#\|^\$" /usr/share/modsecurity-crs/owasp-crs.load | awk '/ \//{print "ls "$NF}' | sh
/etc/modsecurity/crs/crs-setup.conf
/etc/modsecurity/crs/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
/usr/share/modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf
/usr/share/modsecurity-crs/rules/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf
/usr/share/modsecurity-crs/rules/REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf
/usr/share/modsecurity-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf
/usr/share/modsecurity-crs/rules/REQUEST-910-IP-REPUTATION.conf
/usr/share/modsecurity-crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf
/usr/share/modsecurity-crs/rules/REQUEST-912-DOS-PROTECTION.conf
/usr/share/modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf
/usr/share/modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf
/usr/share/modsecurity-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf
/usr/share/modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf
/usr/share/modsecurity-crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf
/usr/share/modsecurity-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf
/usr/share/modsecurity-crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf
/usr/share/modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf
/usr/share/modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
/usr/share/modsecurity-crs/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf
/usr/share/modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf
/usr/share/modsecurity-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf
/usr/share/modsecurity-crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf
/usr/share/modsecurity-crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf
/usr/share/modsecurity-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf
/usr/share/modsecurity-crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf
/usr/share/modsecurity-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
/usr/share/modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf
/etc/modsecurity/crs/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
■modsecurityのログ出力場所と条件を確認。
$ grep ^SecAuditLog /etc/modsecurity/modsecurity.conf
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABDEFHIJZ
SecAuditLogType Serial
SecAuditLog /var/log/apache2/modsec_audit.log
$ grep ^SecDefaultAction /etc/modsecurity/crs/crs-setup.conf
SecDefaultAction "phase:1,log,auditlog,pass"
SecDefaultAction "phase:2,log,auditlog,pass"
■比較的無害なディレクトリトラバーサルでテスト
この単純なパスワード一覧の取得がそのまま通るようなWebサーバは存在しないし、
万が一通るならそのWebサーバは使ってはいけない。
$ w3m -dump_head -no-proxy 'http://127.0.0.1/../../etc/passwd'; \
curl -v --noproxy 127.0.0.1 -s 'http://127.0.0.1/../../etc/passwd' | w3m -T text/html | head -3; \
sudo tail -f /var/log/apache2/access.log
HTTP/1.1 400 Bad Request
Date: Sun, 13 Aug 2017 03:43:27 GMT
Server: Apache/2.4.25 (Debian)
Connection: close
Content-Type: text/html; charset=iso-8859-1
* Rebuilt URL to: http://127.0.0.1/etc/passwd
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET /etc/passwd HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Sun, 13 Aug 2017 03:43:27 GMT
< Server: Apache/2.4.25 (Debian)
< Content-Length: 283
< Content-Type: text/html; charset=iso-8859-1
<
{ [283 bytes data]
* Curl_http_done: called premature == 0
* Connection
Not Found
The requested URL /etc/passwd was not found on this server.
127.0.0.1 - - [13/Aug/2017:12:43:27 +0900] "HEAD /../../etc/passwd HTTP/1.0" 400 161 "-" "w3m/0.5.3+git20170102"
127.0.0.1 - - [13/Aug/2017:12:43:27 +0900] "GET /etc/passwd HTTP/1.1" 404 444 "-" "curl/7.52.1"
■apache2のアクセスログの時刻をキーにmodsecurityのログと突き合せ。
$ sudo strings /var/log/apache2/modsec_audit.log | \
awk 'BEGIN{flag=0} \
{if($1=="[13/Aug/2017:12:43:27"){flag=1;print} \
else{if($1=="Engine-Mode:" && flag==1){flag=0;print} \
else{if(flag==1){print}}}}' | sed -e 's/] /&\n\t/g'
[13/Aug/2017:12:43:27 +0900]
WY-K338AAQEAACLEEAkAAABD 127.0.0.1 40126 127.0.0.1 80
--e4c15b56-B--
HEAD /../../etc/passwd HTTP/1.0
User-Agent: w3m/0.5.3+git20170102
Accept: text/html, text/*;q=0.5, image/*, application/*
Accept-Encoding: gzip, compress, bzip, bzip2, deflate
Accept-Language: ja;q=1.0, en;q=0.5
Host: 127.0.0.1
--e4c15b56-F--
HTTP/1.1 400 Bad Request
Connection: close
Content-Type: text/html; charset=iso-8859-1
--e4c15b56-E--
--e4c15b56-H--
Apache-Error: [file "core.c"]
[line 4509]
[level 3]
AH00126: Invalid URI in request %s
Stopwatch: 1502595807705929 1579 (- - -)
Stopwatch2: 1502595807705929 1579; combined=1060, p1=690, p2=0, p3=69, p4=225, p5=76, sr=69, sw=0, l=0, gc=0
Response-Body-Transformed: Dechunked
Producer: ModSecurity for Apache/2.9.1 (http://www.modsecurity.org/); OWASP_CRS/3.0.0.
Server: Apache/2.4.25 (Debian)
Engine-Mode: "DETECTION_ONLY"
[13/Aug/2017:12:43:27 +0900]
WY-K338AAQEAACLEEAoAAABE 127.0.0.1 40128 127.0.0.1 80
--136e7961-B--
GET /etc/passwd HTTP/1.1
Host: 127.0.0.1
User-Agent: curl/7.52.1
Accept: */*
--136e7961-F--
HTTP/1.1 404 Not Found
Content-Length: 283
Content-Type: text/html; charset=iso-8859-1
--136e7961-E--
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /etc/passwd was not found on this server.</p>
<hr>
<address>Apache/2.4.25 (Debian) Server at 127.0.0.1 Port 80</address>
</body></html>
--136e7961-H--
Message: Warning. Pattern match "^[\\d.:]+$" at REQUEST_HEADERS:Host. [file "/usr/share/modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"]
[line "793"]
[id "920350"]
[rev "2"]
[msg "Host header is a numeric IP address"]
[data "127.0.0.1"]
[severity "WARNING"]
[ver "OWASP_CRS/3.0.0"]
[maturity "9"]
[accuracy "9"]
[tag "application-multi"]
[tag "language-multi"]
[tag "platform-multi"]
[tag "attack-protocol"]
[tag "OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST"]
[tag "WASCTC/WASC-21"]
[tag "OWASP_TOP_10/A7"]
[tag "PCI/6.5.10"]
Apache-Error: [file "apache2_util.c"]
[line 273]
[level 3]
[client %s]
ModSecurity: %s%s [uri "%s"]%s
Stopwatch: 1502595807732815 2916 (- - -)
Stopwatch2: 1502595807732815 2916; combined=1852, p1=824, p2=703, p3=42, p4=238, p5=45, sr=69, sw=0, l=0, gc=0
Response-Body-Transformed: Dechunked
Producer: ModSecurity for Apache/2.9.1 (http://www.modsecurity.org/); OWASP_CRS/3.0.0.
Server: Apache/2.4.25 (Debian)
Engine-Mode: "DETECTION_ONLY"
■ヘッダのリクエストでは引っかからないが、
IPアドレスのアクセスがあったという「id:920350」が報告されている。
IPアドレス:ポートでも同様のログが出るとのこと。
$ sudo strings /var/log/apache2/modsec_audit.log | \
awk 'BEGIN{flag=0} \
{if($1=="[13/Aug/2017:12:43:27"){flag=1;print} \
else{if($1=="Engine-Mode:" && flag==1){flag=0;print} \
else{if(flag==1){print}}}}' | grep ^Message | sed -e 's/] /&\n\t/g'
Message: Warning. Pattern match "^[\\d.:]+$" at REQUEST_HEADERS:Host. [file "/usr/share/modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"]
[line "793"]
[id "920350"]
[rev "2"]
[msg "Host header is a numeric IP address"]
[data "127.0.0.1"]
[severity "WARNING"]
[ver "OWASP_CRS/3.0.0"]
[maturity "9"]
[accuracy "9"]
[tag "application-multi"]
[tag "language-multi"]
[tag "platform-multi"]
[tag "attack-protocol"]
[tag "OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST"]
[tag "WASCTC/WASC-21"]
[tag "OWASP_TOP_10/A7"]
[tag "PCI/6.5.10"]
$ sudo grep -B 22 -A 26 920350 /usr/share/modsecurity-crs/rules/* | awk -F'conf-' '{print $NF}'
SecRule REQUEST_HEADERS:Host "^[\d.:]+$" \
"msg:'Host header is a numeric IP address',\
phase:request,\
rev:'2',\
ver:'OWASP_CRS/3.0.0',\
maturity:'9',\
accuracy:'9',\
t:none,\
block,\
logdata:'%{matched_var}',\
severity:'WARNING',\
/usr/share/modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf: id:920350,\
tag:'application-multi',\
tag:'language-multi',\
tag:'platform-multi',\
tag:'attack-protocol',\
tag:'OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST',\
tag:'WASCTC/WASC-21',\
tag:'OWASP_TOP_10/A7',\
tag:'PCI/6.5.10',\
setvar:'tx.msg=%{rule.msg}',\
setvar:tx.anomaly_score=+%{tx.warning_anomaly_score},\
setvar:tx.%{rule.id}-OWASP_CRS/POLICY/IP_HOST-%{matched_var_name}=%{matched_var}"
TODO
■IPアドレスをホスト名に変更して再テスト
$ w3m -dump_head -no-proxy 'http://localhost/../../etc/passwd'; \
curl -v --noproxy localhost -s 'http://localhost/../../etc/passwd' | w3m -T text/html | head -3; \
sudo tail -2 /var/log/apache2/access.log
HTTP/1.1 400 Bad Request
Date: Sun, 13 Aug 2017 04:16:05 GMT
Server: Apache/2.4.25 (Debian)
Connection: close
Content-Type: text/html; charset=iso-8859-1
* Rebuilt URL to: http://localhost/etc/passwd
* Trying ::1...
* TCP_NODELAY set
* connect to ::1 port 80 failed: 接続を拒否されました
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /etc/passwd HTTP/1.1
> Host: localhost
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Sun, 13 Aug 2017 04:16:05 GMT
< Server: Apache/2.4.25 (Debian)
< Content-Length: 283
< Content-Type: text/html; charset=iso-8859-1
<
{ [283 bytes data]
* Curl_http_done: called premature == 0
* Connection
Not Found
The requested URL /etc/passwd was not found on this server.
127.0.0.1 - - [13/Aug/2017:13:16:05 +0900] "HEAD /../../etc/passwd HTTP/1.0" 400 161 "-" "w3m/0.5.3+git20170102"
127.0.0.1 - - [13/Aug/2017:13:16:05 +0900] "GET /etc/passwd HTTP/1.1" 404 444 "-" "curl/7.52.1"
$ sudo strings /var/log/apache2/modsec_audit.log | \
awk 'BEGIN{flag=0} \
{if($1=="[13/Aug/2017:13:16:05"){flag=1;print} \
else{if($1=="Engine-Mode:" && flag==1){flag=0;print} \
else{if(flag==1){print}}}}' | sed -e 's/] /&\n\t/g'
[13/Aug/2017:13:16:05 +0900]
WY-ShX8AAQEAACLEEA0AAABJ 127.0.0.1 40148 127.0.0.1 80
--97663b14-B--
HEAD /../../etc/passwd HTTP/1.0
User-Agent: w3m/0.5.3+git20170102
Accept: text/html, text/*;q=0.5, image/*, application/*
Accept-Encoding: gzip, compress, bzip, bzip2, deflate
Accept-Language: ja;q=1.0, en;q=0.5
Host: localhost
--97663b14-F--
HTTP/1.1 400 Bad Request
Connection: close
Content-Type: text/html; charset=iso-8859-1
--97663b14-E--
--97663b14-H--
Apache-Error: [file "core.c"]
[line 4509]
[level 3]
AH00126: Invalid URI in request %s
Stopwatch: 1502597765775985 1032 (- - -)
Stopwatch2: 1502597765775985 1032; combined=628, p1=413, p2=0, p3=58, p4=110, p5=47, sr=42, sw=0, l=0, gc=0
Response-Body-Transformed: Dechunked
Producer: ModSecurity for Apache/2.9.1 (http://www.modsecurity.org/); OWASP_CRS/3.0.0.
Server: Apache/2.4.25 (Debian)
Engine-Mode: "DETECTION_ONLY"
■ディレクトリトラバーサルの書式があまりに単純過ぎたので引っかからなかった様子。
「../../etc/passwd」を「..../etc/passwd」に変更して再実施。
$ w3m -dump_head -no-proxy 'http://localhost/..../etc/passwd'; \
curl -v --noproxy localhost -s 'http://localhost/..../etc/passwd' | w3m -T text/html | head -3; \
sudo tail -2 /var/log/apache2/access.log
HTTP/1.1 404 Not Found
Date: Sun, 13 Aug 2017 04:24:10 GMT
Server: Apache/2.4.25 (Debian)
Connection: close
Content-Type: text/html; charset=iso-8859-1
* Trying ::1...
* TCP_NODELAY set
* connect to ::1 port 80 failed: 接続を拒否されました
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /..../etc/passwd HTTP/1.1
> Host: localhost
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Sun, 13 Aug 2017 04:24:10 GMT
< Server: Apache/2.4.25 (Debian)
< Content-Length: 288
< Content-Type: text/html; charset=iso-8859-1
<
{ [288 bytes data]
* Curl_http_done: called premature == 0
* Connection
Not Found
The requested URL /..../etc/passwd was not found on this server.
127.0.0.1 - - [13/Aug/2017:13:24:10 +0900] "HEAD /..../etc/passwd HTTP/1.0" 404 159 "-" "w3m/0.5.3+git20170102"
127.0.0.1 - - [13/Aug/2017:13:24:10 +0900] "GET /..../etc/passwd HTTP/1.1" 404 449 "-" "curl/7.52.1"
$ sudo strings /var/log/apache2/modsec_audit.log | \
awk 'BEGIN{flag=0} \
{if($1=="[13/Aug/2017:13:24:10"){flag=1;print} \
else{if($1=="Engine-Mode:" && flag==1){flag=0;print} \
else{if(flag==1){print}}}}' | grep ^Message | sed -e 's/] /&\n\t/g'
Message: Warning. Matched phrase "../" at REQUEST_URI. [file "/usr/share/modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf"]
[line "77"]
[id "930110"]
[rev "1"]
[msg "Path Traversal Attack (/../)"]
[data "Matched Data: ../ found within REQUEST_URI: /..../etc/passwd"]
[severity "CRITICAL"]
[ver "OWASP_CRS/3.0.0"]
[maturity "9"]
[accuracy "7"]
[tag "application-multi"]
[tag "language-multi"]
[tag "platform-multi"]
[tag "attack-lfi"]
[tag "OWASP_CRS/WEB_ATTACK/DIR_TRAVERSAL"]
Message: Warning. Matched phrase "../" at REQUEST_URI. [file "/usr/share/modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf"]
[line "77"]
[id "930110"]
[rev "1"]
[msg "Path Traversal Attack (/../)"]
[data "Matched Data: ../ found within REQUEST_URI: /..../etc/passwd"]
[severity "CRITICAL"]
[ver "OWASP_CRS/3.0.0"]
[maturity "9"]
[accuracy "7"]
[tag "application-multi"]
[tag "language-multi"]
[tag "platform-multi"]
[tag "attack-lfi"]
[tag "OWASP_CRS/WEB_ATTACK/DIR_TRAVERSAL"]
Message: Warning. Operator GE matched 5 at TX:anomaly_score. [file "/usr/share/modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"]
[line "57"]
[id "949110"]
[msg "Inbound Anomaly Score Exceeded (Total Score: 10)"]
[severity "CRITICAL"]
[tag "application-multi"]
[tag "language-multi"]
[tag "platform-multi"]
[tag "attack-generic"]
Message: Warning. Operator GE matched 5 at TX:inbound_anomaly_score. [file "/usr/share/modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf"]
[line "73"]
[id "980130"]
[msg "Inbound Anomaly Score Exceeded (Total Inbound Score: 10 - SQLI=0,XSS=0,RFI=0,LFI=10,RCE=0,PHPI=0,HTTP=0,SESS=0): Path Traversal Attack (/../)"]
[tag "event-correlation"]
Message: Warning. Matched phrase "../" at REQUEST_URI. [file "/usr/share/modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf"]
[line "77"]
[id "930110"]
[rev "1"]
[msg "Path Traversal Attack (/../)"]
[data "Matched Data: ../ found within REQUEST_URI: /..../etc/passwd"]
[severity "CRITICAL"]
[ver "OWASP_CRS/3.0.0"]
[maturity "9"]
[accuracy "7"]
[tag "application-multi"]
[tag "language-multi"]
[tag "platform-multi"]
[tag "attack-lfi"]
[tag "OWASP_CRS/WEB_ATTACK/DIR_TRAVERSAL"]
Message: Warning. Matched phrase "../" at REQUEST_URI. [file "/usr/share/modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf"]
[line "77"]
[id "930110"]
[rev "1"]
[msg "Path Traversal Attack (/../)"]
[data "Matched Data: ../ found within REQUEST_URI: /..../etc/passwd"]
[severity "CRITICAL"]
[ver "OWASP_CRS/3.0.0"]
[maturity "9"]
[accuracy "7"]
[tag "application-multi"]
[tag "language-multi"]
[tag "platform-multi"]
[tag "attack-lfi"]
[tag "OWASP_CRS/WEB_ATTACK/DIR_TRAVERSAL"]
Message: Warning. Operator GE matched 5 at TX:anomaly_score. [file "/usr/share/modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"]
[line "57"]
[id "949110"]
[msg "Inbound Anomaly Score Exceeded (Total Score: 10)"]
[severity "CRITICAL"]
[tag "application-multi"]
[tag "language-multi"]
[tag "platform-multi"]
[tag "attack-generic"]
Message: Warning. Operator GE matched 5 at TX:inbound_anomaly_score. [file "/usr/share/modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf"]
[line "73"]
[id "980130"]
[msg "Inbound Anomaly Score Exceeded (Total Inbound Score: 10 - SQLI=0,XSS=0,RFI=0,LFI=10,RCE=0,PHPI=0,HTTP=0,SESS=0): Path Traversal Attack (/../)"]
[tag "event-correlation"]
■「949110」は全体的なトランザクションでの異常の検出を数値化したものなので、
実質2種類のシグニチャにマッチしたことになる。
$ sudo strings /var/log/apache2/modsec_audit.log | awk 'BEGIN{flag=0} \
{if($1=="[13/Aug/2017:13:24:10"){flag=1;print} \
else{if($1=="Engine-Mode:" && flag==1){flag=0;print} \
else{if(flag==1){print}}}}' | grep ^Message | sed -e 's/] /&\n\t/g' | \
awk '/id/{gsub("]","",$NF);a[$NF]+=1}END{for(n in a){print a[n],n}}'
4 "930110"
2 "980130"
2 "949110"
$ sudo strings /var/log/apache2/modsec_audit.log | awk 'BEGIN{flag=0} \
{if($1=="[13/Aug/2017:13:24:10"){flag=1;print} \
else{if($1=="Engine-Mode:" && flag==1){flag=0;print} \
else{if(flag==1){print}}}}' | grep ^Message | sed -e 's/] /&\n\t/g' | \
awk '/id/{gsub("]","",$NF);a[$NF]+=1}END{for(n in a){print "grep -B 22 -A 26 "n" /usr/share/modsecurity-crs/rules/*" }}' | \
sh | grep '\[\|id:[0-9]*,\\'
/usr/share/modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf-
/usr/share/modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf: id:930110,\
/usr/share/modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf-
/usr/share/modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf- id:980120,\
/usr/share/modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf: id:980130,\
/usr/share/modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf- id:980140,\
/usr/share/modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf- id:949100,\
/usr/share/modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf-
/usr/share/modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf: id:949110,\
■IIS向けの場合は以下のようにすれば良いことが分かる。
$ w3m -dump_head -no-proxy 'http://localhost/..../cmd.exe' > /dev/null; \
curl -v --noproxy localhost -s 'http://localhost/..../cmd.exe' >/dev/null 2>&1 | w3m -T text/html | head -3 ; \
sudo tail -2 /var/log/apache2/access.log
127.0.0.1 - - [13/Aug/2017:13:41:49 +0900] "HEAD /..../cmd.exe HTTP/1.0" 404 159 "-" "w3m/0.5.3+git20170102"
127.0.0.1 - - [13/Aug/2017:13:41:49 +0900] "GET /..../cmd.exe HTTP/1.1" 404 446 "-" "curl/7.52.1"
$ sudo strings /var/log/apache2/modsec_audit.log | \
awk 'BEGIN{flag=0} \
{if($1=="[13/Aug/2017:13:41:49"){flag=1;print} \
else{if($1=="Engine-Mode:" && flag==1){flag=0;print} \
else{if(flag==1){print}}}}' | grep ^Message | sed -e 's/] /&\n\t/g' | \
awk '/id/{gsub("]","",$NF);a[$NF]+=1}END{for(n in a){print a[n],n}}'
4 "930110"
2 "980130"
2 "949110"
■SecRuleEngineをENABLE(ブロック)に変更する。
HTTPステータスコードが「404 Not Found」から「403 Forbidden」に変わった。
$ sudo sed -i -e 's/^\(SecRuleEngine\) DetectionOnly/\1 On/' /etc/modsecurity/modsecurity.conf
$ sudo systemctl reload apache2.service
$ w3m -dump_head -no-proxy 'http://localhost/..../etc/passwd'; \
> curl -v --noproxy localhost -s 'http://localhost/..../etc/passwd' | w3m -T text/html | head -3; \
> sudo tail -2 /var/log/apache2/access.log
HTTP/1.1 403 Forbidden
Date: Sun, 13 Aug 2017 05:05:15 GMT
Server: Apache/2.4.25 (Debian)
Connection: close
Content-Type: text/html; charset=iso-8859-1
* Trying ::1...
* TCP_NODELAY set
* connect to ::1 port 80 failed: 接続を拒否されました
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /..../etc/passwd HTTP/1.1
> Host: localhost
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Date: Sun, 13 Aug 2017 05:05:15 GMT
< Server: Apache/2.4.25 (Debian)
< Content-Length: 299
< Content-Type: text/html; charset=iso-8859-1
<
{ [299 bytes data]
* Curl_http_done: called premature == 0
* Connection
Forbidden
You don't have permission to access /..../etc/passwd on this server.
127.0.0.1 - - [13/Aug/2017:14:05:15 +0900] "HEAD /..../etc/passwd HTTP/1.0" 403 159 "-" "w3m/0.5.3+git20170102"
127.0.0.1 - - [13/Aug/2017:14:05:15 +0900] "GET /..../etc/passwd HTTP/1.1" 403 460 "-" "curl/7.52.1"
$ sudo strings /var/log/apache2/modsec_audit.log | awk 'BEGIN{flag=0} \
{if($1=="[13/Aug/2017:14:05:15"){flag=1;print} \
else{if($1=="Engine-Mode:" && flag==1){flag=0;print} \
else{if(flag==1){print}}}}' | grep ^Message | sed -e 's/] /&\n\t/g' | \
awk '/id/{gsub("]","",$NF);a[$NF]+=1}END{for(n in a){print a[n],n}}'
4 "930110"
2 "980130"
2 "949110"
$ sudo strings /var/log/apache2/modsec_audit.log | \
awk 'BEGIN{flag=0} \
{if($1=="[13/Aug/2017:14:05:15"){flag=1;print} \
else{if($1=="Engine-Mode:" && flag==1){flag=0;print} \
else{if(flag==1){print}}}}' | grep "^Message\|^Engine-Mode" | sed -e 's/] /&\n\t/g' | \
awk '/Engine-Mode|id|msg|data|severity|tag .[A-Z]/'
[id "930110"]
[msg "Path Traversal Attack (/../)"]
[data "Matched Data: ../ found within REQUEST_URI: /..../etc/passwd"]
[severity "CRITICAL"]
[tag "OWASP_CRS/WEB_ATTACK/DIR_TRAVERSAL"]
[id "930110"]
[msg "Path Traversal Attack (/../)"]
[data "Matched Data: ../ found within REQUEST_URI: /..../etc/passwd"]
[severity "CRITICAL"]
[tag "OWASP_CRS/WEB_ATTACK/DIR_TRAVERSAL"]
[id "949110"]
[msg "Inbound Anomaly Score Exceeded (Total Score: 10)"]
[severity "CRITICAL"]
[id "980130"]
[msg "Inbound Anomaly Score Exceeded (Total Inbound Score: 10 - SQLI=0,XSS=0,RFI=0,LFI=10,RCE=0,PHPI=0,HTTP=0,SESS=0): Path Traversal Attack (/../)"]
Engine-Mode: "ENABLED"
[id "930110"]
[msg "Path Traversal Attack (/../)"]
[data "Matched Data: ../ found within REQUEST_URI: /..../etc/passwd"]
[severity "CRITICAL"]
[tag "OWASP_CRS/WEB_ATTACK/DIR_TRAVERSAL"]
[id "930110"]
[msg "Path Traversal Attack (/../)"]
[data "Matched Data: ../ found within REQUEST_URI: /..../etc/passwd"]
[severity "CRITICAL"]
[tag "OWASP_CRS/WEB_ATTACK/DIR_TRAVERSAL"]
[id "949110"]
[msg "Inbound Anomaly Score Exceeded (Total Score: 10)"]
[severity "CRITICAL"]
[id "980130"]
[msg "Inbound Anomaly Score Exceeded (Total Inbound Score: 10 - SQLI=0,XSS=0,RFI=0,LFI=10,RCE=0,PHPI=0,HTTP=0,SESS=0): Path Traversal Attack (/../)"]
Engine-Mode: "ENABLED"
■検出のみに戻しておく。
$ sudo sed -i -e 's/^\(SecRuleEngine\) On/\1 DetectionOnly/' /etc/modsecurity/modsecurity.conf
$ sudo systemctl reload apache2.service