格式化字串漏

2022-09-23 13:39:08 字數 2463 閱讀 1202

當printf系列函式的格式化串裡包含使用者提交的資料時,就有可能出現格式化串漏洞。 函式包括:

snprintf

vfprintf

vprintf

vsprintf

vsnprintf

除了這呰函式外,其他接受c風格格式符的函式也可能存在類似風險,例如wind0ws上的wprintf函式。攻擊者可能提交許多格式符(而不提供對應的變數),這樣的話,棧上就沒有和格式符相對應的引數,因此,系統就會用棧上的其他資料代替這些引數,從而導致資訊洩漏和執行任意**。

如前文所述,必須以格式化串的形式傳遞printf函式,好讓printf函式確定用什麼變數代替相應的格式化串,以及用什麼形式輸出變數。

然而,如果我們不給格式化串(格式符)提供相應的變最,將會出現奇怪的事情。例如下面這個程式,它將用命令列的引數呼叫printf。

按如下所示編譯**: cc fmc.c -o fmt 用如下的形式執行:

./fmt "%x %x %x %x"

將等同於在程式裡用如下的形式呼叫printf:

printf( '%x %x %x %x");

上面的語句透露出乙個重要的資訊:我們提交了格式化串,卻沒有提供相應的代替字串的 4個數字變最。有趣的是printf並沒有報錯,而是輸出如下內容:

4015c98c 4001s26c bffff944 bffffse8

口printf不知從什麼地方找來了4個引數充數!事實上,這些資料來自棧。

乍看上去這似乎不是什麼問題,然而,攻擊者卻可能利用它來獲取棧上的資料。對棧本身來說這可能洩露棧上的敏感資訊,如使用者名稱、密碼等。

n% 這個引數被視為指向整數的指標(或者整數變數,例如short,在這個引數之前輸出 的宇符的數量將被儲存到這個引數指向的位址裡

如果滿足下列條件,就可以利用格式化串漏洞執行任意**。

我們能控制引數,並可以把輸出的字元的數量寫入記憶體的任意區域^

寬度格式符允許我們用任意的長度(當然可以為255個字元)填充輸出因此,可以用選擇的值改寫單個位元組.

重複上面步騵4次的話,就能改寫記憶體中的任意48,也就是說,攻擊者可以利用這個 方法改寫記憶體位址。但是,如果把00寫到記憶體位址中,可能會出問題,因為在c語言裡00是終止符。然而,如果可以在它前面的位址寫入28,那就冇可能規避這個問題。 

通常來說,我們可以猜測函式指標的位址(儲存的返回位址、二進位制檔案的匯入表、c++ vtable),因此,我們可以促成系統把提交的字串當作**來執行。

關於格式化串攻擊,有幾個常見的誤區需要澄清^

它們不僅僅影響*nix。

它們不必非要以棧為基礎。

棧保護機制對它們通常不起作用。

用靜態**分析工具通常可以檢測它們。

在絕大多數*nix平台上,可以用直接引數訪問來幫忙。 注意上面的輸出,從找上彈出的第三個值。

試一下下面這條命令:"%3\$x"

但是如果列印很久的資料會出錯%hn能夠解決這個閼題. 它只寫半個整型,兩個位元組,那麼就可以把shellcode位址分成兩個部分.依次寫入到 要覆蓋的位址以及這個位址加2的位置.這樣要列印的長度將減少很多.

報據上面調整的結果,可以構造乙個所示的結構的格式串來實現攻擊.,

| retloc+2 |retloc | % shaddrh-8 x| % flag $hn丨% shaddrl-shaddrh x丨 %flag+1 $hn丨

構造攻擊格式串

由用shellcode的位址的半字構造列印長度來寫入返回位址,那麼必須注意要把小一些 的半字放在前曲,這樣才能順利覆蓋返回位址。用於構建這種格式串的函式流程大致如下

void mkfmt(char *fmtstr, u_long retloc, u_long shaddr, int align, int flag)

*/    /* let's build */

if (valh < vall) else

//*    for (i = 0; i < align; i++)

//*/

}示例的程式有些特別,由於格式串並不是複製過去的,所以對齊字串要放在格式串的後面。格式串漏洞利用的要素是以下幾點:

• 覆蓋獲得控制的位址

• printf引數位址到自定義的格式串資料位址直接的距離

• 格式串資料沒有4位元組對齊的偏移

• shellcode 位址

可以用來覆蓋獲得控制的位址有以下幾種:

全域性偏移表(got)(動態重定位對函式,如果某些人使用的二進位制檔案與你的一樣,那 就太好了,比如rpm:

析構函式(dtors)表(函式在退出前將呼叫析構函式);

c函式庫鉤子,

atexit結構;

所有其他的函式指標,例如c ++ vtable、冋調函式等;

windows裡預設未處理的異常處理程式,它幾乎總是在同一位址

堆疊中的函式返回位址

覆蓋 dl_lookup_versioned_symbol

其實搏蓋dl_lookup_versioned_symbol也是覆蓋got技術.只不過是ld的got。   

字串格式化

sprintf snprintf snprintf std stringstream std strstream boost lexical cast boost format cstring format 1 sprintf 使用 sprintf 不安全,輕則破壞資料的準確性,重則程式崩潰。請看下...

格式化字串

通常在使用字串的時候,會對字串進行格式化,然後輸出或呼叫 一般我們使用替換標記對字串進行格式化 string str1 string.format add is 1,2,3 而且在c 中的替換標記可以以任意順序和次數出現在格式化字串中,但替換值是按順序排的,而且替換標記不能超出索引範圍 string...

字串格式化

例如 string s hello map.put target world string res format s,map 有什麼用呢?比如在some.properties中配置模板字串,但是如果用 這種方式,在配置了spring讀取properties注入變數的時候,這個變數就找不到會報錯。這個...