labunix's blog

labunixのラボUnix

第1回危険シェル芸勉強会を安全に実行してみる。(shellshock.sh)

■第1回危険シェル芸勉強会を安全に実行してみる。

 20141019 OSC Tokyo/Fall LT 【危険シェル芸】
 http://www.slideshare.net/ryuichiueda/20141019-osc-tokyofall-lt

■まずはchroot環境にログイン。
 以降、すべてchroot上のwheezyで実行しているものとする。

 Wheezy上にchroot環境のWheezyを構築
 http://labunix.hateblo.jp/entry/20130819/1376924059

 CentOS6上にchrootのdebian wheezyを構築
 http://labunix.hateblo.jp/entry/20130820/1377007672

$ ssh -p 8022 localhost

■Fork爆弾

 Fork爆弾
 http://ja.wikipedia.org/wiki/Fork%E7%88%86%E5%BC%BE

■準備
 起動したコンソール内で起動できるプロセス数を制限する。
 自身のPIDを取得して、いつでもkill出来るようにしておく。

$ ulimit -a | grep proc
max user processes              (-u) 62513

$ ulimit -u 511 &&  ulimit -a | grep proc
max user processes              (-u) 511

$ echo $$
12983

■確認用に別シェルで以下のどちらかで監視する。

$ echo $$;ulimit -a | grep proc
13037
max user processes              (-u) 62513

$ watch -d -n 1 'echo $$;ps l | wc -l'
Every 1.0s: echo $$;ps l | wc -l                        Sun Oct 19 21:15:20 2014

18541
10

$ watch -d -n 1 'echo $$;ps U `whoami` | wc -l'
Every 1.0s: echo $$;ps U `whoami` | wc -l               Sun Oct 19 21:22:16 2014

21393
46

■Fork爆弾実行、10秒待機し、
 Fork爆弾で定義された「:」を同じコンソールから上書きで強制終了
 監視中の「ps -l」の行数は406で打ち止めとなった。

$ :(){ :|:& };: ; sleep 10; :(){ . & };
bash: fork: リソースが一時的に利用できません
bash: fork: retry: リソースが一時的に利用できません
...

■間違ったコメントの実行
 「rm」コマンドだから危険なだけで、
 先に「echo」や「ls」等で確認するクセを付けていれば問題無い。

#  touch temp && echo temp /* テン ポラリを削除 */
temp /bin /boot /dev /etc /home /initrd.img /lib /lib64 /media /mnt /opt /proc
 /root /run /sbin /selinux /srv /sys /tmp /usr /var /vmlinuz テンポラリを削除
 CASL2/ Desktop/ firefox/ hinemos/

$ touch temp && echo temp # テンポラリを削 除
temp

■迷惑なwall。
 「-n」オプションはrootのみ使える。
 引数だとファイル名指定になる。
 日本語は見事にエスケープされる。
 「write」はユーザやTTYにピンポイントで送れる。
 それなら、「echo」コマンドの方がはるかに優秀。

# wall -V
wall from util-linux 2.20.1

# wall '我はroot。神だ'
wall: cannot open file 我はroot。神だ: そのようなファイルやディレクトリはありません

# echo '我はroot。神だ' | wall -n

\346\210\221\343\201\257root\343\200\202\347\245\236\343\201\240                

# echo '我はroot。神だ' | write labunix
Message from root@chroot-debian on pts/4 at 22:02 ...
M-fM-^HM-^QM-cM-^AM-/rootM-cM-^@M-^BM-gM-%M-^^M-cM-^AM- 
EOF

■とりあえず日本語は止めましょう。

$ echo $(echo "this is `whoami` message" | sed s/`whoami`/god/g) | wall
                                                                               
Broadcast Message from labunix@vmx-deb                                        
        (/dev/pts/3) at 21:47 ...                                              
                                                                               
this is god message                                                            

$ echo $(echo "this is `whoami` message" | sed s/`whoami`/god/g) | write `whoami`

Message from labunix@vmx-deb on pts/3 at 22:06 ...
this is god message
EOF

■echo の方が優秀というのは、ユーザが日本語以外のロケールを使用しても、
 変換されずにそのまま表示されるというところ。

$ export LANG=C;echo $LANG
C

# TARGETTTY=`ps au | head -1 | awk '{i = 0;while (i<NF){if($i == "TTY"){print i};i++}}'`; \
  ps au  | grep ^labunix | \
    awk '{print $'${TARGETTTY}'}' | sort -u | \
    for list in `xargs`;do echo "我はroot 。神だ" > "/dev/${list}";done
我はroot。神だ
              我はroot。神だ


■TTYが既に分かっているなら、以下で十分です。
 ちなみにrootで無くでもなりすませるので、こちらの方が危険かも。

# yes "我はroot。神だ" > /dev/pts/1 
$ yes "我はroot。神だ" > /dev/pts/1

■ShellShockについては以下で少し書いた。

 「CVE-2014-6271」、「CVE-2014-7169」について調べてみた(Debian Wheezy)
 http://labunix.hateblo.jp/entry/20140926/1411734893

$ w3m -dump "https://raw.githubusercontent.com/SaltwaterC/sploit-tools/master/shellshock.sh" | \
  tee shellshock.sh >/dev/null; \
  chmod +x shellshock.sh

$ ./shellshock.sh 
Testing /bin/sh for CVE-2014-6271
Testing /bin/sh for CVE-2014-7169
Testing /bin/sh for CVE-2014-7186
VULNERABLE
Testing /bin/sh for CVE-2014-7187
Test not reliable without bash being built with -fsanitize=address

Testing /bin/bash for CVE-2014-6271
Testing /bin/bash for CVE-2014-7169
Testing /bin/bash for CVE-2014-7186
VULNERABLE
Testing /bin/bash for CVE-2014-7187
Test not reliable without bash being built with -fsanitize=address

■「CVE-2014-7186」で脆弱という判定だが、公式は修正済みとしている。

 CVE-2014-7186(Dedebian)
 https://security-tracker.debian.org/tracker/CVE-2014-7186

$ apt-cache show bash | grep ^Ver
Version: 4.2+dfsg-0.1+deb7u3

$ dpkg -L bash | grep change | xargs zcat | grep "CVE-2014\|^bash\|DSA" | head -10
bash (4.2+dfsg-0.1+deb7u3) wheezy-security; urgency=high
bash (4.2+dfsg-0.1+deb7u2) wheezy-security; urgency=high
  * Add CVE-2014-7169.diff diff.
    CVE-2014-7169: Incomplete fix for CVE-2014-6271. (Closes: #762760, #762761)
bash (4.2+dfsg-0.1+deb7u1) wheezy-security; urgency=high
  * Apply patch from Chet Ramey to fix CVE-2014-6271.
bash (4.2+dfsg-0.1) unstable; urgency=low
bash (4.2-5.1) unstable; urgency=low
bash (4.2-5) unstable; urgency=low
bash (4.2-4) unstable; urgency=high

■該当のコードは以下。

$ grep -A 5 CVE-2014-7186 ./shellshock.sh 
	echo "${bold}Testing $1 for CVE-2014-7186${normal}"
	{bash -c "true $(printf '<<EOF %.0s' {1..79})"} > /dev/null 2>&1
	if [ $? -ne 0 ]
	then
		echo "VULNERABLE"
	fi

■単体で実行すると、戻り値は0となるので、構文自体がおかしいことが分かる。

$ bash -c "true $(printf '<<EOF %.0s' {1..79})" >/dev/null 2>&1;echo $?
0
$ bash -c "$(printf '<<EOF %.0s' {1..79})" >/dev/null 2>&1;echo $?
0

$ bash -c "true $(printf '<<EOF %.0s' {1..79})" 2>&1 | uniq -c
     79 bash: 警告: ヒアドキュメントの 0 行目でファイル終了 (EOF) に達しました ('EOF' が必要)

■別の情報も参考にしてみるが出力は同じ。

 bashの脆弱性CVE-2014-7186, CVE-2014-7187について
 http://d.hatena.ne.jp/entree/20140930/1412071602

$ bash -c "true `yes '<<EOF' | head -20 | xargs echo`" 2>&1 | uniq -c
     20 bash: 警告: ヒアドキュメントの 0 行目でファイル終了 (EOF) に達しました ('EOF' が必要)

■オリジナルソースはハードコートされているまま。

$ sudo apt-get source --download-only bash
$ tar zxvf bash_4.2+dfsg.orig.tar.gz
$ cd bash-4.2+dfsg/
$ tar Jtvf bash-4.2dfsg.tar.xz  | grep parse.y | awk '{print $NF}'
bash-4.2/parse.y
$ tar Jxvf bash-4.2dfsg.tar.xz bash-4.2/parse.y
bash-4.2/parse.y
$ grep "REDIRECT.*redir_stack" bash-4.2/parse.y 
static REDIRECT *redir_stack[10];

$ gunzip bash_4.2+dfsg-0.1+deb7u3.diff.gz

■debianのパッチでハードコートに対応している。
 ハードコートされた「*redir_stack[10]」によって、11以上ネストした場合に
 コア・ダンプしたり、フレーム・ポインターが書き換えられたりする可能性があるというもの。
 パッチで配列をポインタに置き換えていることが分かる。
 実行時の警告も11以上のネストで結果が変わらなかったことから、問題無いと思われる。

$ gunzip bash_4.2+dfsg-0.1+deb7u3.diff.gz
$ grep "REDIRECT.*redir_stack" bash_4.2+dfsg-0.1+deb7u3.diff 
+-static REDIRECT *redir_stack[10];
++static REDIRECT **redir_stack;

■上記から、「shellshock.sh」を以下のように修正。

$ grep -A 5 CVE-2014-7186 ./shellshock.sh
	echo "${bold}Testing $1 for CVE-2014-7186${normal}"
	bash -c "true $(printf '<<EOF %.0s' {1..79})" > /dev/null 2>&1
	if [ $? -ne 0 ]
	then
		echo "VULNERABLE"
	fi

$ ./shellshock.sh 
Testing /bin/sh for CVE-2014-6271
Testing /bin/sh for CVE-2014-7169
Testing /bin/sh for CVE-2014-7186
Testing /bin/sh for CVE-2014-7187
Test not reliable without bash being built with -fsanitize=address

Testing /bin/bash for CVE-2014-6271
Testing /bin/bash for CVE-2014-7169
Testing /bin/bash for CVE-2014-7186
Testing /bin/bash for CVE-2014-7187
Test not reliable without bash being built with -fsanitize=address