Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

Shell Shock

Bashの脆弱性

Dennis Gosnell

this presentation online

脆弱性

$ x='() { :;}; echo vulnerable' /bin/bash -c /bin/true
vulnerable

詳しい説明

bashでコマンドを実行

$ x='() { :;}; echo vulnerable' /bin/bash -c /bin/true
vulnerable
  • bashでコマンドを実行する
例:
$ /bin/bash -c "/bin/echo hello"
hello

環境変数

$ x='() { :;}; echo vulnerable' /bin/bash -c /bin/true
vulnerable
  • bashが実行されたとき、環境変数を評価して実行されているコマンド(/bin/true)に渡す
例:
$ x='foobar' /bin/bash -c "echo $foobar"
foobar

環境変数で関数を定義

  • 関数を定義して環境にエクスポート
$ my_func () { echo "hello"; }
$ my_func
hello
$ env | grep -i my_func
$ bash -c "my_func"
bash: my_func: command not found
$ export -f my_func
$ env | grep -i my_func
my_func=() { echo "hello"; }
$ bash -c "my_func"
hello

bashのnop

$ x='() { :;}; echo vulnerable' /bin/bash -c /bin/true
vulnerable
  • :はbashのnopオペレーター
  • 以下のコマンドと関数は何もしない
$ :
$ my_func () { : ;}
$ my_func
$

bashの挙動

  • 実行時に関数っぽい環境変数を探して、見つかったら評価する
$ my_func () { echo "hello"; }
$ export -f my_func
$ env | grep -i my_func
my_func=() { echo "hello"; }
$ bash -c "my_func"
hello

脆弱性

  • 環境に何もしない関数を作って、関数の定義の後で任意のコマンドを入れる
  • bashが起動するとき、関数を評価して、関数の定義の後の任意のコマンドも実行しちゃう
$ x='() { :;}; echo vulnerable' /bin/bash -c /bin/true
vulnerable

.git確認①

$ tree .git/
.git/ ├── HEAD ├── objects │   ├── 54 │   │   └── b450dd7d7c │   └── ac │      └── 0797189547 └── refs    └── heads       ├── master       └── newbranch
  • newbranchが作られた

.gitで確認②

$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
ac0797189547f3f0cdcf39cb170b16d2344aeaf3
  • HEADはmasterブランチを参照
  • masterはさきの子コミットを参照

.gitで確認③

$ cat .git/refs/heads/newbranch
ac0797189547f3f0cdcf39cb170b16d2344aeaf3
  • .git/refs/heads/newbranchが作られた
  • masterと同じコミットを参照している

$ tree .git/
.git/ ├── HEAD ( -> refs/heads/master ) ├── objects │   ├── 54 │   │   └── b450dd7d7c │   └── ac │      └── 0797189547 ( 親: -> objects/54/b450dd7d7c ) └── refs    └── heads       ├── master ( -> objects/ac/0797189547 )       └── newbranch ( -> objects/ac/0797189547 )

またコミットしてみよう

$ echo foobar >> README
$ git add README
$ git commit -m "Second child commit."
[master 22c3956] Second child commit.
 1 file changed, 1 insertion(+)

git log

$ git log --graph --decorate --all 
* commit 22c39561 (HEAD, master)
| Date:   Fri Jul 18 18:25:20 2014 +0900
|     Second child commit.
|
* commit ac079718 (newbranch)
| Date:   Fri Jul 11 14:51:49 2014 +0900
|     Child commit.
|
* commit 54b450dd
  Date:   Tue Jul 8 18:36:36 2014 +0900
      Initial commit.

.gitで確認④

$ cat .git/refs/heads/newbranch
ac0797189547f3f0cdcf39cb170b16d2344aeaf3
$ cat .git/refs/heads/master
22c395616a88b1e845057ad2775399a1853d4010
  • .git/refs/heads/newbranchが作られた
  • masterと同じコミットを参照している

新しいブランチを使ってみよう!

git checkout

$ git checkout newbranch
Switched to branch 'newbranch'
$ cat .git/HEAD
ref: refs/heads/newbranch
$ cat .git/refs/heads/newbranch
ac0797189547f3f0cdcf39cb170b16d2344aeaf3
$ cat .git/refs/heads/master
22c395616a88b1e845057ad2775399a1853d4010
  • HEADがnewbranchを参照するようになった
  • masterは特に変わっていない

newbranchにコミット

$ echo testtest >> README
$ git add README
$ git commit -m "Commit on newbranch."
[newbranch 163e533] Commit on newbranch.
 1 file changed, 1 insertion(+)

.git/で確認

$ cat .git/HEAD
ref: refs/heads/newbranch
$ cat .git/refs/heads/newbranch
163e533db99cf9c8bc1f30222e47975840ae2883
$ cat .git/refs/heads/master
22c395616a88b1e845057ad2775399a1853d4010
  • newbranchは新しいコミットを参照している
  • master、HEADは特に変わっていない

git checkout

  • HEADが参照しているブランチを変えられる

ちなみに

ブランチだけじゃなくて任意のコミットをcheckoutすることもできる

$ git checkout 54b450dd
Note: checking out '54b450dd'.

You are in 'detached HEAD' state.
...
$ cat .git/HEAD
54b450dd7d7c8280040569fc7b5e4637883e76c2

HEADだけじゃなくてブランチも移動しよう!

git reset

新しいブランチ作成

$ git branch test
$ cat .git/HEAD
ref: refs/heads/newbranch
$ cat .git/refs/heads/newbranch
ac0797189547f3f0cdcf39cb170b16d2344aeaf3
$ cat .git/refs/heads/master
22c395616a88b1e845057ad2775399a1853d4010
$ cat .git/refs/heads/test
ac0797189547f3f0cdcf39cb170b16d2344aeaf3

checkout

$ git checkout test
Switched to branch 'test'
$ cat .git/HEAD
ref: refs/heads/test
$ cat .git/refs/heads/newbranch
ac0797189547f3f0cdcf39cb170b16d2344aeaf3
$ cat .git/refs/heads/test
ac0797189547f3f0cdcf39cb170b16d2344aeaf3
  • HEADがtestを参照するようになった

masterが参照しているコミットに、testを参照させる

reset

$ git reset --hard master
HEAD is now at 22c3956 Second child commit.
$ cat .git/HEAD
ref: refs/heads/test
$ cat .git/refs/heads/test
22c395616a88b1e845057ad2775399a1853d4010
$ cat .git/refs/heads/master
22c395616a88b1e845057ad2775399a1853d4010
  • testも22c395616を参照している

resetのフラグ

  • --soft
  • --mixed
  • --hard
  • ...

git merge...

...の話はしません。

聞きたい人いますか?

今日の最後のコマンド

一番怖いと言われているコマンド

git rebase

まずレポジトリーを整理

$ git checkout master
Switched to branch 'master'
$ git branch -D newbranch
Deleted branch newbranch (was 163e533).
$ git branch -D test
Deleted branch test (was 22c3956).
  • newbranchとtestブランチを削除

ブランチ削除確認

$ tree .git/refs
.git/refs/ ├── heads │   └── master └── tags
  • newbranchとtestブランチは.git/refs/から消えている

test2ブランチ作成

$ git branch test2

masterにテストコミット

$ echo "hello1" >> master-test-file 
$ git add master-test-file
$ git commit -m 'master commit 1'
[master b27026d] master commit 1
 1 file changed, 1 insertion(+)
 create mode 100644 master-test-file
$ echo "hello2" >> master-test-file 
$ git add master-test-file
$ git commit -m 'master commit 2'
[master 55970ec] master commit 2
 1 file changed, 1 insertion(+)

test2にテストコミット

$ git checkout test2
Switched to branch 'test2'
$ echo "foo1" >> test2-test-file 
$ git add test2-test-file
$ git commit -m 'test2 commit 1'
[test2 491b512] test2 commit 1
 1 file changed, 1 insertion(+)
 create mode 100644 test2-test-file
$ echo "foo2" >> test2-test-file 
$ git add test2-test-file
$ git commit -m 'test2 commit 2'
[test2 e43ab74] test2 commit 2
 1 file changed, 1 insertion(+)

rebase

$ git rebase master
First, rewinding head...
Applying: test2 commit 1
Applying: test2 commit 2
$ ls
master-test-file  README  test2-test-file
$ git log --oneline
dc2421d test2 commit 2
910a5a7 test2 commit 1
55970ec master commit 2
b27026d master commit 1
22c3956 Second child commit.
ac07971 Child commit.
54b450d Initial commit.

コミットハッシュを注目

$ git log --oneline
dc2421d test2 commit 2
910a5a7 test2 commit 1
  • コミットが書き換えられている

rebase

  • 2つのブランチが分岐された時点から、現在のブランチを切り離して、もうひとつのブランチの最新のコミットに移動させる

レビュー

git branch
新しいブランチを作成
git checkout
HEADが参照しているブランチを変更
git reset
現在のブランチが参照しているコミットを変更
git rebase
ブランチごとを移住

fin

Use a spacebar or arrow keys to navigate