「!xxx%s%s%s%s%s%s%s%s」有什麼特別之處?

「!xxx%s%s%s%s%s%s%s%s」有什麼特別之處?

我被連結到Unix 仇恨者手冊並偶然發現(頁149):

主題:相關 Unix bug

1991 年 10 月 11 日

W4115x 同學們—

當我們討論啟動記錄、參數傳遞和呼叫約定時,您是否知道鍵入:

!xxx%s%s%s%s%s%s%s%s

任何 C-shell 都會導致它立即崩潰嗎?你知道為什麼嗎?

需要思考的問題:

  • 當你打字時 shell 會做什麼!xxx
  • 當你打字時它必須對你的輸入做什麼 !xxx%s%s%s%s%s%s%s%s
  • 為什麼這會使外殼崩潰?
  • 您如何(相當容易地)重寫 shell 的有問題的部分以避免出現此問題?

純粹出於好奇,誰能解釋一下問題是什麼?毫不奇怪,在 Google 上搜尋該字串並沒有幫助。搜尋訊息中的其他引用只給了我該訊息的其他副本,但沒有解釋。

答案1

我不想去挖掘25年前的貝殼的來源,但是

它可能是一個格式字串漏洞

如果 shell 包含如下程式碼

printf(str);

其中str是從使用者輸入中獲取的一些字串,該字串的內容將是printf使用的格式字串。告訴列印參數指向的字串%sprintf如果未給出參數(如上所述,只有格式字串),則函數將從堆疊中讀取一些其他數據,並將它們作為指標跟隨。可能存取未映射的記憶體並使進程崩潰。

在某種程度上,我認為該訊息的措辭也暗示了這樣的解決方案。如果您鍵入!xxx,shell 明顯會列印錯誤訊息,例如!xxx: event not found。從那裡開始,嘗試 print 並不是一個大的飛躍!xxx%s%s%s%s%s%s%s%s: event not found,這意味著格式字串漏洞。


我不應該這樣做,但我看了一眼源碼這裡4.3BSD-Tahoe/usr/src/bin/csh,日期自 1988 年起)。

findev(cp, anyarg)sh.lex.c看起來它可能是尋找符合歷史事件的函數:它遍歷被呼叫的連結struct Hist清單Histlist。如果沒有找到任何東西,它就會seterr2(cp, ": Event not found");呼叫noev().cp這裡看起來是在歷史記錄中搜尋的字串。

seterr2()將變數設定err為參數的串聯,並在, in 中的幾個地方err使用if (err) error(err);process()sh.c。最後,error()(在sh.err.c)包含一個經典的格式字串漏洞:if (s) printf(s, arg), printf(".\n");

在其他一些地方,error()是用參數呼叫的,例如error("Unknown user: %s", gpath + 1);,所以顯然這個想法是第一個參數error()可能是格式字串。

如果我說我完全理解歷史替換函數,那我是不誠實的。它幾乎是 C 中未註釋的手動字串%處理。!%findev()

相關內容