首頁 >後端開發 >php教程 >優化NFR之一 --MSSQL Hello Buffer Overflow_PHP教程

優化NFR之一 --MSSQL Hello Buffer Overflow_PHP教程

WBOY
WBOY原創
2016-07-21 16:07:53843瀏覽


1.  前言  3
2.  警報資訊  3
3.  NFR的偵測  4
4.  協定分析  小結  20


1.  前言
NFR(Network Flight Recorder)是一個老牌的商業網路IDS產品,最初由Firewall的牛人Marcus J. Ranum創建,是作為一個通用的網路流量分析和記錄軟體來實現的,為了最大限度地發揮分析工具的靈活性,NFR提供了完善強大的N-Code腳本語言,在許多的評測中表現出色。雖然L0pht為NFR提供過數百個簽名庫,但是缺乏一個可靠的簽名集一直是他的軟肋。

使用NFR有一段時間後,發現NFR有不少問題。且不說AI對中文的兼容性差而經常退出,也不說NFR版本升級而攻擊事件說明卻一直用舊版本的說明,單是IDS中最關鍵的攻擊簽名庫,卻讓我大跌眼鏡。除了升級緩慢以外,甚至還有不少錯誤的簽名。本系列文章針對其中我發現的部分問題進行分析和闡述,以便各位更好地利用NFR產品,同時也想和各位同仁討論IDS中攻擊簽名庫的編寫。由於知識與時間的限制,錯誤之處在所難免,也希望得到各位的指教,任何意見或建議請發至:benjurry@xfocus.org

SQL Server是微軟為對抗Oracle推出的資料庫, 佔領的市場份額已僅次於Oracle,居世界第二,但是其安全性也一直受到用戶的置疑。從1996年,Microsoft公司推出的SQL Server 6.5版本到1998年推出的SQL Server 7.0,以及2000年8月推出了SQL Server 2000,在版本和功能不斷升級的情況下,安全性問題卻沒有很好地改善,不斷發布針對SQL Server的安全性公告和修補程式。在2003年1月24日,針對SQL Server的「Slammer」蠕蟲在Internet上肆虐,導致網路流量激增,嚴重影響了世界各地的電腦和網路系統。 SQL Server的漏洞引起了各大安全公司和廠商的重視,因此NFR也立即發布了多個針對SQL Server的攻擊簽名,其中包括了2002年8月7日Immunity公司Dave Aitel發現的Hello Buffer Overflow漏洞。但是在使用過程中,我發現NFR針對該漏洞的警報非常多,於是我對此進行了分析,於是寫成了這篇文章,以做記錄。


2.  警報訊息
以下是NFR針對MS SQL Hello Buffer Overflow的警報訊息:

Severity:      Attack
Severity:    Jul-2003
Source File:    packages/mssql/sql2k.nfr
Line:        226
Host:        226
Host: k:buffered_hello
Source ID:     mssql_sql2k:source_me
Source:       mssql_sql2k:source_me
Source Description: Sqlserver 2k overflow detector
Source PID:     36531
Alert Message:         0.110 in 900 seconds
:          3
Source IP:     192.168.0.110
Destination IP:       --

其中包括了事件的嚴重等級、時間、NFR SensorIP、攻擊來源IP、目的名稱和一些其他警報訊息資訊。
在實際的使用中,一天產生了幾百條這種報警,看來這是個誤報,我們可以好好的分析一下了。


3.  NFR的偵測
我們先開啟NFR發布的簽章庫MSSQL.fp(或是也可以在AI的package中查看) 看看NFR的針對這個漏洞的攻擊簽章:


…..

變數定義等…



sqlserv_schema = library_schema:new(1, [ma:new(1, [ma:new(1, [ma:new(1) "time","ip","int","ip","int", "str"],
  scope());
sqlserv_rec = recorder("bin/list %c", "sqlserv_schema ");

HELLO_SIG = "x12x01x00x34x00x00x00x00x00x00x15";
MIN_LEN = strlen(HELLO_SIG);


…….

filter hello tcp ( client, dport: 1433) {
  declare $Blob inside tcp.connsym;
  if ($Blob == NULL) {
    Blob = cat($Blob, tcp.blob);
  }

  if (strlen($Blob)     return;
    if (COUNTHELLO[tcp.connsrc]) {
      COUNTHELLO[tcp.connsrc]   COUNTHELLO[tcp.connsrc] = 1;
    }
    if (do_alert(hello_overflow_alert, tcp.connsrc)) {
     .connsport, tcp.conndst, tcp.conndport,
        "--AlertDetails",
        "ALERT_ID", "40-8",
       "ALERT_SEVERITY", "medium",
        "ALERT_IMPACT", " unknown",
        "ALERT_EVENT_TYPE", "attack",
        "ALERT_ASSESSMENT", "unknown", <.>        "PORT_SRC", tcp.connsport,
"IP_ADDR_DST", tcp.conndst,
        "PORT_DST", tcp.conndport,
        .sec, tcp.conndst, tcp.conndport, tcp .connsrc,
      tcp.connsport, $Blob to sqlserv_rec;
    misc_attacks:rec(packet.sec ) , tcp.conndst);
  }
}

從上面的N-CODE我們可以看到,NFR在做這個檢測的時候步驟如下:

1、定義了一個攻擊特徵碼:
HELLO_SIG = "x12x01x00x34x00x00x00x00x00x00x15";
和攻擊特徵碼的長度:
MIN_LEN = strlen(HELLO_SIG);

MIN_LEN = strlen(HELLO_SIG);

長度和特徵碼長度比較,如果這個資料長度小於攻擊特徵碼的長度,那麼就不再進行下一步的偵測;

3、否則,把這個資料和特徵碼進行字串匹配,如果一致則認為是攻擊行為,然後進行阻止或報警。
接下來我們分析一下NFR IDS Record的數據,在AI中選擇package->Query->MSSQL->MSSQL Server 200,定好條件,按Table查到數據,隨便選取一條,copy出來得到如下內容:

Time:        15-Jul-2003 13:54:21
NFR:        benjurry-xfocus
Destination 15831219. 33
Source Address:   192.168. 0.110
Source Port:    1391
Payload:      
          x12x01xx
          x01x02x00x1cx00x0cx03x00(x00x04xffx08x00x00xc2x00
  🎜>
上面這條記錄包含了攻擊的時間,報告攻擊行為的NIDS sessor名字,目的IP、目的端口、源ip和源端口,而我們關心的是有效載荷Payload,因為它是NIDS用來和攻擊簽名庫比較的數據。 🎜>1.  會把payload中的能轉換成ASCII字符的16進制數轉換成ASCII碼;

2.  不能處理Unicode的字符,這個將在以後的分析中可以看到。

在這個例子中為了分析方便,我們把上面的payload中的字元特徵碼部分轉換成16進位數:
x12x01x00x34x00x00x00x00x00x00x15x00x06x01x00x 3x00x28x00x04xffx08x00x00
xc2x00x00x00MSSQLServerx00xx03x00x00


NFR抓到資料組包後,發現是SQL Server包,便把裡面的內容和SQL Server的攻擊庫進行比較,很明顯,上面所列的資料和攻擊庫是相符合的,因此一個警報便產生了,但是這真是攻擊行為嗎?我們繼續看下面的分析。


4.  協定分析

根據Xfocus的協定分析專案(將會在近期公佈專案成果),MS SQL 2000用的是TDS8.0,它的格式如下:
----------------------------------------------- --
| TDS包頭(8位元組) |  TDS負載資料       |
----------------------------- --------------------
其中MS SQL SERVER 2000 TDS的包頭結構如下:
------------- -------------------------------------------------- ----
| TOKEN | STATUS | LENGTH | SIGNED NUM | PACKET NUM | WINDOW SIZE |
------------------------ -------------------------------------------
其中TOKEN字段域1個字節,用來表示TDS操作請求種類。在這個漏洞中是0x12,也就是NFR記錄中的有效負載中的第一個位元組0x12, 0x12是預先登入驗證指令請求。其目的是取得目前MS SQL SERVER2000的一些設定值,例如SQL SERVER版本,是否支援加密等訊息,作為客戶端在建構TDS包的一個依據。 SQL Server在接受到該類型的套件的時候,將會由SSlibnet.dll中的對應函數做處理,在我的系統SQL Server 2000(沒有SP)的情況下,對應函數如下:


.text:42CF6DDD ; Attributes: bp-based frame
.text:42CF6DDD
.text:42CF6DDD        .
.text:42CF6DDD var_4      = dword ptr -4
.text:42CF6DDD arg_0      = dword ptr 8 .text:42CF6DDD arg 萬_8      = dword ptr 10h
. text:42CF6DDD arg_C      = dword ptr 14h
.text:42CF6DDD arg_10     = dword ptr 18h
.text:42CF6D18h  ebp
.text:42CF6DDE         mov   ebp, esp
.text:42CF6DE0         push  ecx
.text:42CF6DE1         mov   e [eax 94h]
.text:42CF6DEA         mov   [ebp var_4], ecx
.text:42CF6DED         cmp   [ebp var_4], 1
.text:42CF6DF1          cmp   [ebp var_4], 1
.text:42CF6DF7         jle   short loc_42CF6E3D
. text:42CF6DF9         cmp   [ebp var_4], 3



STATUS字段1個位元組,當它為0x01的時候表示此包為當前TDS包。
LENGTH字段域2個位元組,表示TDS包的總長度,包括TDS包頭的長度。
SIGNED NUM字段域2個位元組,目前保留未用。
PACKET NUM字段域1個字節,表示此TDS包在當前TDS操作請求中的序號
WINDOW SIZE字段域1個字節,目前保留未用。
MS SQL SERVER 0X12 TDS的套件主包格式如下:
-------------------------------- ----------------------
| TDS包頭(8位元組)| 欄位指示頭|    訊息      |
------- -----------------------------------------------
其中字段指示頭是一個可以變長的表,表的每一項代表了在一個字段在信息中的偏移地址和長度信息,在SQL2000中主要是4個字段,其對應的字段指示頭的結構如下:
{
  BYTE CNETLIBVERNO;
  WORD CNETLIBVEROFFSET;
  WORD CNETLIBVERLEN;   BYTE SINSTNAMENO;
  WORD SINSTNAMEOFFSET;
  WORD SINSTNAMELEN;
  BYTE CTHREADIDNO;
  WORD CTHREADIDOFFSET的結構如下:
{
  BYTE CNETLIBVER[CNETLIBVERLEN]
  BYTE CENYFLAG[CENYFLAGLEN];
 BYTE SINSTNAME[SINSTNAMELEN]
 >DWORD C​​DCU4S4S4P474 月(D455>T]]T5P]P]P]P]]PP版本]])> 🎜>CNETLIBVERNO欄位域
偏移:0
長度:1
意義:客戶端使用的網路連線庫(NETLIB)的版本號資訊的欄位編號。
說明:
備註:此值固定為0

CNETLIBVEROFFSET字段域
偏移:1
長度:2
意義:客戶端使用的網路連線庫( NETLIB)的版本號碼資訊的欄位偏移。
說明:欄位格式為網路位元組順序
備註:

CNETLIBVERLEN欄位域
偏移:3
長度:2
意義:客戶端使用的網路連線庫(NETLIB)的版本號資訊的欄位長度。
說明:欄位格式為網路位元組順序
備註:此值固定為6

CENYFLAGNO欄位域
偏移:5
長度:1
意義:客戶端使用強制加密標記欄位的欄位號碼。
說明:
備註:此值固定為1

CENYFLAGOFFSET欄位域
偏移:6
長度:2
意義:客戶端使用強制加密標記欄位的偏移。
說明:欄位格式為網路位元組順序
備註:

CENYFLAGLEN欄位域
偏移:8
長度:2
意義:客戶端使用強制加密標記欄位的長度。
說明:欄位格式為網路位元組順序
備註:數值固定為1

SINSTNAMENO欄位域
偏移:0XA
長度:1
意義:客戶端要求使用伺服器的實例名字段的字段號。
說明:
備註:此值固定為2

SINSTNAMEOFFSET字段域
偏移:0XB
長度:2
意義:客戶端要求使用伺服器的實例名字段的偏移。
說明:字段格式是網路位元組順序
備註:

SINSTNAMELEN字段域
偏移:0XD
長度:2
含義:客戶端要求使用伺服器的實例名字段的長度。
說明:欄位格式為網路位元組順序
備註:

CTHREADIDNO欄位
偏移:0XF
長度:1
意義:客戶端進程的執行緒ID字段的字段號。
說明:
備註:此值固定為3

CTHREADIDOFFSET欄位域
偏移:0X10
長度:2
意義:客戶端進程的執行緒ID欄位的的偏移。
說明:欄位格式是網路位元組順序
備註:

CTHREADIDLEN欄位域
偏移:0X12
長度:2
意義:客戶端進程的執行緒ID欄位的長度。
說明:欄位格式為網路位元組順序
備註:此值固定為4

FILEDEND欄位域
偏移:0X14
長度:1
意義:此字段標記字段指示頭已經結實,下面的就是字段的資訊。
說明:結束標記是0XFF
備註:

CNETLIBVER字段域
偏移:0X15
長度:6
含義:客戶端使用的網絡連接庫(NETLIB )的版本號。
說明:其版本號取的是DBNETLIB.DLL的版本
備註:其格式為網路位元組格式,如版本號為80.528.00,則為
  08 00 02 10 00 00
  08 00 02 10 00 00

CENYFLAG欄位
偏移:0X1B
長度:1
意義:客戶端強制加密標誌。
說明:0代表客戶端不強制加密,1代表客戶端使用強制加密
備註:

SINSTNAME字段域
偏移:0X1C
長度:SINSTNAMELEN
偏移:0X1C
長度:SINSTNAMELEN
意義:客戶端要求使用的實例名。
說明:單字節格式
備註:預設實例使用MSSQLserver這個名字

CTHREADID欄位域
偏移:0X1C SINSTNAMELEN
長度:4
意義:客戶端行程的執行緒ID。
說明:欄位格式是主機位元組順序
備註:

由上面的格式可以看出,一個用預設實例名MSSQLserver連接的SQL TDS套件格式將是如下的格式:
x12x01x00x34x00x00x00x00
x00x00x15x00x06x01x00x1b
x00x01x02x00x1cx00x1b
x00x01x02x00x1cx00x0cx00ffx 🎜>xc2x00x00x00MSSQ
LServerx00
x78x03x00x00

而NFR的攻擊簽章庫卻是
HELLO_SIGa>
而NFR的攻擊簽章庫卻是
HELLO_SIGx = "x12x10x"x00x
很明顯是正常TDS 0x12預登陸包的一部分,這就難怪會有這麼多警報了,那NFR的這個攻擊簽名是如何得到的呢?
我們還是從它的漏洞說明入手吧!


5.  漏洞說明
以下是NFR N-CODE中對這個漏洞的說明:
FALSE POSITIVES

False positives are unlikely of to the nature attack

REFERENCES
Bugtraq Post
  http://cert.uni-stuttgart.de/archive/bugtraq/2002/08/msg00125.html
Exploit
http www.scan-associates.net/papers/sql2kx2.txt
我們可以看到這個漏洞來自於http://www.immunitysec.com/ 的Dave Aitel,而從http://cert.uni-stuttgart. de/archive/bugtraq/2002/08/msg00125.html所列的MS SQL Server Hello Overflow NASL script中我們可以看到這個漏洞的關鍵就在於以下幾個語句:


pkt_hdr = raw_string(
0x12 ,0x01 ,0x00 ,0x34 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x15 ,0x00 00x,00,00x, 0 ,0x01 ,0x02 ,0x00 ,0x1c ,0x00 ,0x0c ,0x03 ,0x00 ,0x28 ,0x00 ,0x04 ,0xff ,0x08 ,0x00 ,0x02,
0x10 ,0x00,000x tail = raw_string (
0x00 ,0x24 ,0x01 ,0x00 ,0x00
);



…..
if(get_port_state(port))
{; 🎜>  soc = open_sock_tcp(port);

  if(soc)
  {

  attack_string=crap(560); ;
  send( socket:soc, data:sql_packet);

    r = recv(socket:soc, length:4096);
    close(soc);     if(!r)
    {
     display("Security Hole in MSSQLn");
   }

其中pkt_hdr是根據TDS協定構造的包,中間加了560個字元X,pkt_tail是構造的TDS包尾。

從這裡我們可以看到,可憐的NFR居然不負責任地把MS SQL Server Hello Overflow NASL script中的pkt_hdr取出11個字符,毅然決然地把它們作為其簽名。更可笑的是居然還寫著「False positives are unlikely due to the nature of the attack 」。
這就是在許多評測中遙遙領先的NFR?後來和stardust聊這個事情的時候,認為這個現象和很多評測機構在評測IDS產品的時候,重視對產品漏報的檢測而忽視對誤報的評測有關。因為在評測產品時,基本上都是大部分都是黑箱評測,要檢測漏報只要收集幾個Exploits就可以進行,但要檢測漏報卻要產生正常的包,有些系統比如這裡的Sql Server,如果不了解它的協定包格式,是很難產生的。因此有些IDS產生便鑽了這樣的空子,只要收集一些Exploits,把其中的攻擊代碼作為攻擊簽章直接發布,而不去分析漏洞產生的真正原因。

下面我們來分析這個漏洞產生的原因,然後我們就可以根據這個分析,寫出比較完善的攻擊簽章。


6.  漏洞分析
用IDA對SSlibnet.dll反彙編,我們可以看到:


.text:42CF6F49 loc_42

.text:42CF6F49 loc_42
.text:42CF6F49         mov   eax, [ebp 0xc]
.text:42CF6F4C            push  eax
.text:42CF6F53         lea   ecx, [ebp-0x214]
.text:42CF6F59         push  ecx
.text:42CF6F5A     all  add   esp, 8
.text:42CF6F62         push  offset unk_42D01104
.text: 42CF6F67         lea   edx, [ebp-0x214]
.text:42CF6F6D         push edx .text:42CF6F73         add   esp, 8


這個漏洞的原因就在這裡,當程式用strcpy拷貝的時候,如果來源字串超出0x214(也就是532)後,目標位址後的環境變數就會被覆寫導致溢位。由於這個漏洞很早,經歷了「Slammer」蠕蟲後,基本上所有的系統都補掉了這個漏洞,因此這裡就不在提供攻擊代碼了,有興趣的朋友可以自己分析和編寫。


另外需要在這裡說明的是,如果分析了TDS協定和這個漏洞的成因,完善的攻擊程序中的TDS包的長度是根據計算生成的,明顯不會是」x00x34 ”,以避過SQL Server中針對TDS包長度的校驗(當然在這個版本的SQL Server中還不包含這個校驗),或者攻擊程序把這攻擊代碼分成多個包,因此TDS格式中的status就不會是0x01,因此NFR是檢測不出完善的攻擊程序的的,也就是說針對這個漏洞,NFR 同時存在誤報和漏洞的情況。

在分析了這個漏洞的成因後,我們就可以針對這個問題寫出自己的NFR檢測程式碼:


sqlserv_schema = library_schema:new(1, ["time" ,"ip","int","ip","int", "str"],
  scope());
sqlserv_rec = recorder("bin/list %c", "sqlserv_schema");

HELLO_SIG = "x12 ";
#考慮了分包和長度不固定的因素,去除了後面不可靠的特徵串
MIN_LEN =29;
#包括TDS包頭和欄位指示頭的總長度

…….

filter hello tcp (client, dport: 1433) {
  declare $Blob inside tcp.connsym;
  declare $Blob inside tcp.connsym; ($Blob == NULL) {
    $Blob = tcp.blob;
  } else {
    $Blob = cat($Blob, tcp.blob)     return;

  if (prefix($Blob, HELLO_SIG) && strlen($Blob) > 295) {    超過255,因此這裡長度選擇了40(包頭) 255=295
#也可以增加一個Value,以便用戶自己根據事件情況進行調節
#警報
….

}


7.  小結
透過對NFR這個攻擊簽章的分析可以看出,發布完善的IDS攻擊簽章不是一個簡單的事情,它需要了解應用的協定格式和漏洞的成因。而不是簡單地收集網路上存在地exploits,然後截取其中的特徵碼。
目前很多人包括IDS開發人月都在討論IDS有沒有前途,需不需要。我想與其在那裡討論,不如靜下來好好分析漏洞,完善攻擊簽名,讓IDS做的更準確。
與其坐而論不如起而行! ! (來源:www.xfocus.net)

www.bkjia.comtruehttp: //www.bkjia.com/PHPjc/314964.htmlTechArticle1.前言3 2.警報訊息3 3.NFR的偵測4 4.協定分析8 5.漏洞說明15 6.漏洞分析18 7.小結20 1.前言NFR(Network Flight Recorder)是一個老牌的商業網絡IDS產品...

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn