Nessus安全測試插件編寫教程(2)

5.總結

  這是NASL Reference Guide的第一部分,主要介紹了NASL的各種函數。在下一部分我們將系統地介紹如何編寫Nessus安全測試插件。'
1.怎樣編寫一個高效的Nessus安全測試插件

  在Nessus安全測試系統中,所有的安全測試都是由nessusd進程發動的。在測試期間,一個好的測試插件必須能夠有效地利用其它測試插件的測試結果。例如:一個測試插件需要打開一個到FTP服務器的連接,而在這之前它應該首先檢查端口掃描測試插件的結果,確定FTP端口是否打開。在一般情況下,這樣只會節約一點點時間,但是如果被測試主機位於防火牆之後,這樣做會節省由於防火牆丟棄到21端口的TCP報文造成的漫長等待時間。


  1.1.確定端口是否打開

  get_port_state(〈portnum〉)函數用於獲得端口的狀態。如果端口爲開,這個函數就返回TRUE;反之,則返回FALSE;如果這個端口沒有被掃描過,也就是其狀態爲未知(unknown),函數也將返回TRUE。這個函數只消耗很少的CPU資源,因此你可以儘可能地使用它,來提高測試插件的效率。

  1.2.基礎信息(Knowledge Base,KB)

  在測試過程中,Nessus會爲每個主機維護一份由掃描測試插件獲得的基本信息(Knowledge Base,這個詞本來應該是基礎知識的意思,但是這裏似乎翻譯作基本信息更爲恰當^_^)。各種其它的測試插件應該儘可能地利用這些信息,以提高測試效率。實際上,端口的狀態就保存在這裏。

  KB被分爲好幾類。Service類包含每個已知的服務和爲其分配的端口號。例如,在大多數情況下,Server/smtp的值爲25。但是,如果遠程主機的SMTP服務被隱藏於2500端口,這個值就改爲2500。

  有關基本信息各個元素的細節請參考附錄B。

  在NASL中,有兩個有關節本信息(KB)的函數。使用get_kb_item(〈name〉)函數可以獲得基本信息的〈name〉項的值,這個函數是匿名函數;而函數set_kb_item(name:〈name〉,value:〈value〉)能夠把〈name〉項的值設置爲〈value〉。

  注意:你不能獲得剛剛加入的基本信息條目的值。例如,以下代碼將無法象你所期待的那樣執行:

   set_kb_item(name:"attack",value:TRUE);
   if(get_kb_item("attack"))
    {
     #這裏的代碼不可能執行
     #因爲attack基本信息項並沒有更新
    }

  之所以會這樣,是出於安全和代碼穩定性的考慮。在安全測試期間,Nessus服務器會爲每個安全測試插件維護一份基本信息(KB)拷貝,安全測試插件只是從自己的基本信息(KB)拷貝中獲得信息。而set_kb_item()函數只更新原始的基本信息(KB)拷貝,不對當前安全測試插件使用的拷貝進行更新操作。

2.NASL腳本結構

  每個安全測試插件需要向Nessus服務器進行註冊後,才能使用。註冊信息包括名字、描述、作者等。每個NASL腳本都需要有以下結構:

   #
   #NASL基本基本結構
   #
   if(description)
    {
     #這裏是註冊信息
     #
     #這裏可以叫做註冊部分(register section)
     #
     exit(0);
    }
   #
   #這裏是腳本代碼。我們可以稱爲***部分(attack section)
   #

  description是一個全局變量,值可以是TRUE或者FALSE,取決於腳本是否需要註冊。

  2.1.註冊部分

  在腳本的註冊部分,必須調用以下函數:

   script_name(language1:〈name〉,[...])

  設置在Nessus客戶程序窗口中顯示的名稱。

   script_description(language1:〈desc〉,[...])

  設置在Nessus客戶程序中顯示的描述信息。

   script_summary(language1:〈summary〉,[...])

  設置總結信息,必須在一行之內總結描述信息的內容。

   script_category(〈category〉)

  設置腳本的類別。必須是ACT_ATTACK、ACT_GATHER_INFO、ACT_DENIAL和ACT_SCANNER之一。

   ACT_GATHER_INFO

  信息採集類腳本。這種腳本率先啓動,不會對遠程主機造成傷害。

   ACT_ATTACK

  這類腳本會嘗試獲得遠程主機的某些權限,可能會危害遠程主機(例如,如果運行緩衝區溢出測試插件)

   ACT_DENIAL

  這種腳本會發起拒絕服務***,試圖造成遠程主機宕機。

   ACT_SCANNER

  端口掃描腳本。

   script_copyright(language1:〈copyright〉,[...])

  設置腳本的版權信息。

   script_family(language1:〈family〉,[...])

  設置腳本所屬的族(family)。NASL對此沒有明確的規定,你可以任意定義腳本所屬的族,例如:nixe0n's PowerTools",不過我不建議這樣做。當前使用的族名有:

   Backdoors
   CGI abuses
   Denial of Service
   FTP
   Finger abuses
   Firewalls
   Gain a shell remotely
   Gain root remotely
   Misc
   NIS
   RPC
   Remote file access
   SMTP problems
   Useless services

  你可能注意到了,以上所有的函數都有一個叫做language1的參數。這個參數用於提供多語言支持。使用NASL編寫的腳本都需要支持英語,因此這些函數的確切語法是:

   script_fuction(english:english_text,[francais:french_text,deutsch:german_text,...]);

  除了以上函數,還有一個用於解決安全測試插件依賴關係的函數script)dependencies()。它告訴nessusd服務器在某些腳本之後啓動當前腳本。如果當前腳本需要其它腳本獲得的結果,就需要使用這個函數。其原型爲:

   script_dependencies(filename1 [,filename2,...,filenameN]);

  filename參數是腳本文件名。

  2.2.***部分

  腳本的***部分可以包括所有用於***測試的代碼。一旦***完成,你可以使用security_warning()和security_hole()函數報告是否存在此類安全問題。這兩個函數的用途基本相同,security_warning()用於***成功,但是問題不大的情況。它們的原型如下:

   security_warning(〈port〉 [,protocol:〈proto〉]);
   security_hole(〈port〉 [,protocol:〈proto〉]);
   security_warning(port:〈port〉,data:〈data〉 [,protocol:〈proto〉]);
   security_hole(port:〈port〉,data:〈data〉 [,protocol:〈proto〉]);

  在上面的第一種情況下,客戶程序顯示的內容是腳本註冊時script_description()函數提供的。由於能夠支持多語言,因此非常方便。

  在第二種情況下,客戶程序將顯示data參數的內容。如果你需要顯示動態獲得的數據,就必須使用這種形式。

  2.3.CVE兼容性

  CVE是麻省理工學院維護的一個數據庫,主要是對安全相關的問題提供一個一般的描述。

  詳情請參考[url]http://cve.mitre.org[/url]。

  Nessus和CVE完全兼容,如果你要測試一個CVE定義過的安全問題,就可以在插件腳本的描述部分調用script_cve_id()函數。其原型如下:

   script_cve_id(string);

  例如:

   script_cve_id("CVE-1999-0991");

  如果使用了這個函數,Nessus客戶程序在生成報告時,會自動引用相關的CVE記錄。

  2.4.示例

  除了安全測試外,NASL也可以用來編寫一些用於維護的腳本。下面就是一個例子,用戶可以使用這個腳本檢查那些主機正在提供SSH服務。
   #
   #檢查SSH
   #
   if(description)
    {
     script_name(english:"Ensure the presence of ssh");
     script_description(english:"This script makes sure that ssh is running");
     script_summary(english:"connects ont remote tcp port 22");
     script_category(ACT_GATHER_INFO);
     script_family(english:"Admiminstration toolbox");
     script_copyright(english:"This script was Writtern by Joe U.");
     exit(0);
    }
   #
   #SSH服務可能隱藏在別的端口
   #因此我們需要依賴於find_service插件獲得的結果
   #
   port=get_kb_item("Services/ssh");
   if(!port)port=22;
   #首先聲明SSH沒有安裝
   ok=0;
   if(get_port_state(port))
    {
     soc=open_sock_tcp(port);
     if(soc)
      {
       #檢查端口是否是由TCP_Wrapper封裝的。
       data=recv(socket:soc,length:200);
       if("SSH"〉〈data)ok=1;
      }
     close(soc);
    }
   #
   #報告不提供SSH服務的主機
   #
   if(!ok)
   {
    report="SSH is not running on this host!";
    security_warning(port:22,data:report);
   }

3.腳本優化

  在安全測試期間,nessusd服務器將啓動200多個腳本。如果所有腳本編寫的都不好,這個測試就會浪費大量的時間。因此,你必須儘量提高腳本的效率。

  3.1.只在必要時運行

  對於優化腳本,最有效的方法是告訴nessusd服務器什麼時候不要啓動它。例如,假設你的腳本需要建立到遠程主機123/TCP端口的連接,如果nessusd知道這個端口已經被關閉,就沒有必要啓動你的腳本了。script_require_ports()、script_require_keys()和script_exclude_keys()就是用來實現上述目的。這些腳本需要在描述部分調用:

   script_require_ports(〈port1〉,〈port2〉,...)

  參數中的至少一個端口開放才啓動腳本。參數可以是數字,也可以是基本信息(KB)中定義的符號,例如:"Services/www"。注意:如果端口的狀態是未知的(例如:還沒有進行過端口掃描),這個腳本也會執行。

   script_require_keys(〈key1〉,〈key2〉,...)

  只有參數中的關鍵詞在基本信息(KB)都有定義時,才執行腳本。例如:

   script_require_keys("ftp/anonymous","ftp/writeable_dir");

  表示只有遠程FTP主機支持匿名用戶以及存在可以寫的目錄時,才啓動當前腳本。

   script_exclude_keys(〈key1〉,〈key2〉,...)

  參數表示的關鍵詞至少有一個在基本信息(KB)中有定義,才執行當前腳本。

  3.2.充分利用其它腳本的結果

  充分利用基本信息拷貝中的信息,可以使腳本更高效。例如,如果在調用open_sock_tcp()函數之前,先調用get_port_state()函數,就可以避免由於目標端口是關閉的帶來的時間上的浪費。

4.如何分享你的新腳本

  如果你想讓別人分享自己的成果,在編寫測試腳本時要遵循以下原則:

   你的腳本不能存在任何與用戶交互的操作
   NASL安全測試腳本是在服務器端運行的,因此用戶看不到任何的輸出信息。
   一個腳本只能測試一個漏洞
   如果你知道如何測試好幾個漏洞,那就爲每個漏洞都編寫自己的測試腳本。
   你的腳本最好歸入現有的種類
   如果你計劃分享自己的成果,最好避免建立Joe's Power Tools這樣的新插件種類,儘量把插件劃入已有的插件種類。
   查詢CVE中是否有相關漏洞的定義
   如果你能夠注意腳本的兼容性,可以節省Nessus維護者的很多時間。
   把成果發給Nessus維護者

   Nessus的維護者就是本文的作者。如果你不象獨享自己的成果,就把它發給Nessus維護者。如果你的腳本被採用,它就會被分配一個唯一的ID。

5.結論

  希望你能夠喜歡這個教程。學習這個語言不會佔用你太多的時間,你需要多多練習。在使用過程中,你會發現NASL解釋器的一些BUGS,希望你能夠及時把這些BUGS報告給我。

附錄A.基本信息(Knowledge base)

  所謂的基本信息是一些關鍵詞,裏面包含其它測試插件獲得的信息。使用script_dependencies()、get_kb_item()和set_kb_item()函數,可以幫助你避免沒有必要的重複測試。附錄A中將羅列出這些關鍵詞。

  在基本信息(KB)中,每個項可以有幾個值。例如,遠程主機運行兩個FTP服務:一個在端口21,另一個在端口2100。這樣關鍵詞Services/ftp就等於21和2100兩個端口。在這種情況下,測試腳本將執行兩次:第一次,get_kb_item("Services/ftp")函數將返回21,第二次這個函數將返回2100。不過,這是自動進行的,無須人工干預。對於腳本編寫者來說,相當於每個基本信息關鍵詞只有一個值。有些關鍵詞目前沒有多大用處,好多我就沒有用過,但是有備無患。

  Host/OS
  定義文件:queso.nasl、nmap_wrapper.nasl
  類型:字符串
  含義:遠程操作系統的類型

  Host/dead
  定義文件:ping_host.nasl和所有的DoS插件
  類型:boolean
  含義:遠程主機關閉。如果這個項被設置,nessusd將終止針對這個主機的所有測試。

  Services/www
  定義文件:find_service.nes
  類型:端口號
  含義:目標主機WEB服務器監聽的端口號。如果沒有發現WEB服務器,就返回0。

  Services/auth
  定義文件:find_service.nes
  類型:端口號
  含義:identd服務使用的端口。如果沒有這個服務,就返回0。

  Services/echo
  定義文件:find_service.nes
  類型:端口號
  含義:echo服務使用的端口。如果沒有這個服務,就返回0。

  Services/finger
  定義文件:find_service.nes
  類型:端口號
  含義:finger服務使用的端口。如果沒有這個服務,就返回0。

  Services/ftp
  定義文件:find_service.nes
  類型:端口號
  含義:ftp服務使用的端口。如果沒有這個服務,就返回0。

  Services/smtp
  定義文件:find_service.nes
  類型:端口號
  含義:smtp服務使用的端口。如果沒有這個服務,就返回0。

  Services/ssh
  定義文件:find_service.nes
  類型:端口號
  含義:ssh服務使用的端口。如果沒有這個服務,就返回0。

  Services/http_proxy
  定義文件:find_service.nes
  類型:端口號
  含義:HTTP代理服務使用的端口。如果沒有這個服務,就返回0。

  Services/imap
  定義文件:find_service.nes
  類型:端口號
  含義:imap服務使用的端口。如果沒有這個服務,就返回0。

  Services/pop1
  定義文件:find_service.nes
  類型:端口號
  含義:pop1服務使用的端口。如果沒有這個服務,就返回0。

  Services/pop2
  定義文件:find_service.nes
  類型:端口號
  含義:pop2服務使用的端口。如果沒有這個服務,就返回0。

  Services/pop3
  定義文件:find_service.nes
  類型:端口號
  含義:pop3服務使用的端口。如果沒有這個服務,就返回0。

  Services/nntp
  定義文件:find_service.nes
  類型:端口號
  含義:nntp服務使用的端口。如果沒有這個服務,就返回0。

  Services/linuxconf
  定義文件:find_service.nes
  類型:端口號
  含義:linuxconf服務使用的端口。如果沒有這個服務,就返回0。

  Services/swat
  定義文件:find_service.nes
  類型:端口號
  含義:SWAT服務使用的端口。如果沒有這個服務,就返回0。

  Services/wild_shell
  定義文件:find_service.nes
  類型:端口號
  含義:shell服務使用的端口。如果沒有這個服務,就返回0。

  Services/telnet
  定義文件:find_service.nes
  類型:端口號
  含義:telnet服務使用的端口。如果沒有這個服務,就返回0。

  Services/server
  定義文件:find_service.nes
  類型:端口號
  含義:realserver服務使用的端口。如果沒有這個服務,就返回0。

  Services/netbus
  定義文件:find_service.nes
  類型:端口號
  含義:NetBus服務使用的端口。如果沒有這個服務,就返回0。

  bind/version
  定義文件:bind_version.nasl
  類型:字符串
  含義:遠程BIND監控程序的版本

  rpc/bootparamd
  定義文件:bootparamd.nasl
  類型:字符串
  含義:bootparam RPC服務正在運行

  Windows compatible
  定義文件:ca_unicenter_file_transfer_service.nasl、ca_unicenter_transport_service.nasl、mssqlserver_detect.nasl和windows_detect.nasl
  類型:boolean
  含義:遠程主機好象運行一種Windows兼容操作系統(只有相關的端口開放才進行這個測試)

  finger/search.**@host
  定義文件:cfinger_search.nasl
  類型:boolean
  含義:使用**進行finger查詢能夠得到用戶列表。

  finger/0@host
  定義文件:finger_0.nasl
  類型:boolean
  含義:使用0進行finger查詢能夠得到用戶列表

  finger/.@host
  定義文件:finger_dot.nasl
  類型:boolean
  含義:使用.進行finger查詢能夠獲得用戶列表

  finger/user@host1@host2
  定義文件:finger_0.nasl
  類型:boolean
  含義:finger監控程序能夠用於重定向***

  www/frontpage
  定義文件:frontpage.nasl
  類型:boolean
  含義:遠程WEB服務器使用frontpage擴展

  ftp/anonymous
  定義文件:ftp_anonymous.nasl
  類型:boolean
  含義:遠程FTP服務器可以匿名登錄

  ftp/root_via_cmd
  定義文件:ftp_cwd_root.nasl
  類型:boolean
  含義:使用CWD命令可以獲得遠程FTP服務器的root權限。參看CVE-1999-0082

  ftp/microsoft
  定義文件:ftp_overflow.nasl
  類型:boolean
  含義:遠程主機是Micro$oft FTP服務器,不能處理太長的參數

  ftp/false_ftp
  定義文件:ftp_overflow.nasl
  類型:boolean
  含義:遠程主機經過TCP封裝,或者FTP端口開放而連接關閉。

附錄B.nasl工具

  libnasl軟件包中有一個單獨的解釋器nasl,可以用於腳本的調試。更多細節可以參考man nasl。
中國.Net俱樂部轉載此文。讓我們一起進步,共享人類技術資源。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章