bgm
Nmap作为一款强大的网络扫描工具,其拥有的功能是非常多的。Nmap的插件也极其强大,目前大部分的人都在使用python,perl等语言调用Nmap,然后等待扫面完毕在读取结果进而下一步操作,不过如果我们使用Nmap的插件进行整改,可以急速优化我们的扫描器。这篇文章与大家分享如何利用Nmap和NSE脚本(有关于Nmap下NSE脚本的介绍请参考文章末尾的参考链接)来将Nmap的扫描结果导入Mysq数据库并进一步利用golang语言用web界面的方式显示出来。这篇文章主要是教大家如何实现。具体的技术细节不作详细解释,大家可以参考文章末尾的链接。
首先简单说一下我所用的系统及软件
Kali-Linux-2017.2-vm-amd64
Mysql 5.7.21-log(大家也可以用kali自带的mysql)
golang:go1.9.2 windows/amd64
Nmap以及其他所用到的已经在kali中集成,所以不需要安装。
由于nse脚本是基于lua的语法,所以我们还需要安装lua环境
安装lua下载lua安装包
[kbd]curl -R -O http://www.lua.org/ftp/lua-5.3.0.tar.gz[/kbd]
解压lua
[kbd]tar zxf lua-5.3.0.tar.gz[/kbd]
编译安装
[kbd]cd lua-5.3.0 && make linux test && make install[/kbd]
安装lua连接mysql相关组件
[kbd]apt-get install lua-sql-* [/kbd]
插件编写
在kali中的nmap脚本目录(/usr/share/nmap/scripts)下创建mysql-output.nse脚本
[kbd]cd /usr/share/nmap/scripts [/kbd]
[kbd]touch mysql-output.nse[/kbd]
脚本内容:
[infobox title=””]
— 调入初始化模块
local luasql = require “luasql.mysql”
local nmap = require “nmap”
description = [[
This script stores the following nmap output into a mysql database: Hostname, IP, port number, protocol (tcp/udp), service and version
]]
—
— you must have database
—
— mysql -uroot -p123456 -e “CREATE DATABASE IF NOT EXISTS NmapScan default character set utf8 COLLATE utf8_general_ci”;
—
— @usage
— nmap –script mysql-output <target>
—
— @example
— $ nmap -sS -A -F –script mysql-output 127.0.0.1
— $ mysql -uroot -p123456 -e “select * from NmapScan.scanData”;
—
— +———–+———–+——+———-+——-+———+—————+
— | hostname | ip | port | protocol | state | service | version |
— +———–+———–+——+———-+——-+———+—————+
— | localhost | 127.0.0.1 | 22 | tcp | open | ssh | OpenSSH6.6.1 |
— | localhost | 127.0.0.1 | 25 | tcp | open | smtp | Postfix smtpd |
— | localhost | 127.0.0.1 | 3306 | tcp | open | mysql | MySQL5.6.37 |
— | localhost | 127.0.0.1 | 80 | tcp | open | http | nginx1.10.2 |
— +———–+———–+——+———-+——-+———+—————+
—
—
—
author = “010sec”
license = “Same as Nmap–See http://nmap.org/book/man-legal.html”
categories = {“external”, “safe”}
prerule = function () return true end
portrule = function () return true end
postrule = function () return true end
—
— 调用MySQL
—
local env = luasql.mysql()
local conn = env:connect(“NmapScan”,”root”,”123456″,”192.168.2.155″,”3306″)
conn:execute”SET NAMES UTF8″
local cur,sql
—
— 在执行之前检测如果表不存在则创建
—
function preaction()
local cur = conn:execute(“CREATE TABLE IF NOT EXISTS scanData (hostname varchar(100), ip varchar(16), port integer(5), protocol varchar(3), state varchar(20), service varchar(100), version varchar(100))”)
if (cur~=nil) then
print(“Create tables success”)
else
print(“Crteat tables error”)
end
end
—
— 将端口信息存入数据库
—
function portaction (host, port)
local version = “”
if (port.version.product~=nil) then
version = port.version.product
end
if (port.version.version~=nil) then
version = version .. port.version.version
end
sql = string.format(“INSERT INTO scanData VALUES (‘%s’, ‘%s’, %d, ‘%s’, ‘%s’, ‘%s’, ‘%s’)” , conn:escape(host.name), conn:escape(host.ip), port.number, conn:escape(port.protocol), conn:escape(port.state), conn:escape(port.service), conn:escape(version))
cur = conn:execute(sql)
if (cur~=nil) then
print(“Insert success”)
else
print(“Insert error”)
end
end
—
— 关闭MySQL环境
—
function postaction ()
conn:close()
env:close()
end
local ActionsTable = {
prerule = preaction,
portrule = portaction,
postrule = postaction
}
— execute the action function corresponding to the current rule
action = function(…) return ActionsTable[SCRIPT_TYPE](…) end
[/infobox]
其中连接数据库信息根据自己情况修改。
测试
[kbd]nmap -sS -sA –script mysql-output 192.168.235.134 [/kbd]
此处我测试的目标是metasploit 2靶机。
查看数据库,结果如下:
使用golang编写web程序显示扫描结果
我是使用了一个现成的留言板web程序,然后做了修改,变成了一个简单的显示数据库内容的web界面,以后可以进一步完善。
原程序文章链接:http://bbs.csdn.net/topics/390485541
文件结构:
—–
|—-static
. |—-main.css
—-main.go
—-index.html
main.go代码
[infobox title=”main.go”]
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" //导入了第三方包 "html/template" "log" "net/http" ) type Message struct { Hostname string Ip string Port int Protocol string State string Service string Version string } func CheckErr(err error) { if err != nil { fmt.Println("") panic(err) } } func List(w http.ResponseWriter, r *http.Request) { var hostname string var ip string var port int var protocol string var state string var service string var version string db, err := sql.Open("mysql", "root:123456@tcp(192.168.2.155:3306)/nmapscan?charset=utf8") //设置连接数据库相关信息 CheckErr(err) rows, err := db.Query("select hostname, ip, port, protocol, state, service, version from scandata") CheckErr(err) var msgSlice []*Message for rows.Next() { err = rows.Scan(&hostname, &ip, &port, &protocol, &state, &service, &version) CheckErr(err) msg := new(Message) msg.Hostname = hostname msg.Ip = ip msg.Port = port msg.Protocol = protocol msg.State = state msg.Service = service msg.Version = version //fmt.Fprintf(w, id) msgSlice = append(msgSlice, msg) } t, err := template.ParseFiles("index.html") if err != nil { log.Println(err) } t.Execute(w, &msgSlice) } func main() { http.HandleFunc("/", List) http.HandleFunc("/list", List) http.Handle("/static/", http.FileServer(http.Dir("./"))) //http.HandleFunc("/", sayhelloName) //设置访问的路由 err := http.ListenAndServe(":9090", nil) //设置监听的端口 if err != nil { log.Fatal("ListenAndServe: ", err) } }
[/infobox]
index.html代码
[infobox title=”index.html”]
<!doctype html> <html> <header> <title>nmapscandata</title> <link type="text/css" rel="stylesheet" href="static/main.css"/> </header> <body> <h2>nmap扫描结果</h2> <table class="bordered"> <thead> <tr> <th>Hostname</th> <th>ip</th> <th>Port</th> <th>Protocol</th> <th>State</th> <th>Service</th> <th>Version</th> </tr> </thead> {{range .}} <tr> <td>{{.Hostname}}</td> <td>{{.Ip}}</td> <td>{{.Port}}</td> <td>{{.Protocol}}</td> <td>{{.State}}</td> <td>{{.Service}}</td> <td>{{.Version}}</td> </tr> {{end}} </table> <br><br> <br> </body> </html>
[/infobox]
mian.css代码
[infobox title=”main.css”]
body { width: 600px; margin: 40px auto; font-family: 'trebuchet MS', 'Lucida sans', Arial; font-size: 14px; color: #444; } table { *border-collapse: collapse; /* IE7 and lower */ border-spacing: 0; width: 100%; } .bordered { border: solid #ccc 1px; -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; -webkit-box-shadow: 0 1px 1px #ccc; -moz-box-shadow: 0 1px 1px #ccc; box-shadow: 0 1px 1px #ccc; } .bordered tr:hover { background: #fbf8e9; -o-transition: all 0.1s ease-in-out; -webkit-transition: all 0.1s ease-in-out; -moz-transition: all 0.1s ease-in-out; -ms-transition: all 0.1s ease-in-out; transition: all 0.1s ease-in-out; } .bordered td, .bordered th { border-left: 1px solid #ccc; border-top: 1px solid #ccc; padding: 10px; text-align: left; } .bordered th { background-color: #dce9f9; background-image: -webkit-gradient(linear, left top, left bottom, from(#ebf3fc), to(#dce9f9)); background-image: -webkit-linear-gradient(top, #ebf3fc, #dce9f9); background-image: -moz-linear-gradient(top, #ebf3fc, #dce9f9); background-image: -ms-linear-gradient(top, #ebf3fc, #dce9f9); background-image: -o-linear-gradient(top, #ebf3fc, #dce9f9); background-image: linear-gradient(top, #ebf3fc, #dce9f9); -webkit-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; -moz-box-shadow:0 1px 0 rgba(255,255,255,.8) inset; box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; border-top: none; text-shadow: 0 1px 0 rgba(255,255,255,.5); } .bordered td:first-child, .bordered th:first-child { border-left: none; } .bordered th:first-child { -moz-border-radius: 6px 0 0 0; -webkit-border-radius: 6px 0 0 0; border-radius: 6px 0 0 0; } .bordered th:last-child { -moz-border-radius: 0 6px 0 0; -webkit-border-radius: 0 6px 0 0; border-radius: 0 6px 0 0; } .bordered th:only-child{ -moz-border-radius: 6px 6px 0 0; -webkit-border-radius: 6px 6px 0 0; border-radius: 6px 6px 0 0; } .bordered tr:last-child td:first-child { -moz-border-radius: 0 0 0 6px; -webkit-border-radius: 0 0 0 6px; border-radius: 0 0 0 6px; } .bordered tr:last-child td:last-child { -moz-border-radius: 0 0 6px 0; -webkit-border-radius: 0 0 6px 0; border-radius: 0 0 6px 0; } /*----------------------*/ .zebra td, .zebra th { padding: 10px; border-bottom: 1px solid #f2f2f2; } .zebra tbody tr:nth-child(even) { background: #f5f5f5; -webkit-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; -moz-box-shadow:0 1px 0 rgba(255,255,255,.8) inset; box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; } .zebra th { text-align: left; text-shadow: 0 1px 0 rgba(255,255,255,.5); border-bottom: 1px solid #ccc; background-color: #eee; background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#eee)); background-image: -webkit-linear-gradient(top, #f5f5f5, #eee); background-image: -moz-linear-gradient(top, #f5f5f5, #eee); background-image: -ms-linear-gradient(top, #f5f5f5, #eee); background-image: -o-linear-gradient(top, #f5f5f5, #eee); background-image: linear-gradient(top, #f5f5f5, #eee); } .zebra th:first-child { -moz-border-radius: 6px 0 0 0; -webkit-border-radius: 6px 0 0 0; border-radius: 6px 0 0 0; } .zebra th:last-child { -moz-border-radius: 0 6px 0 0; -webkit-border-radius: 0 6px 0 0; border-radius: 0 6px 0 0; } .zebra th:only-child{ -moz-border-radius: 6px 6px 0 0; -webkit-border-radius: 6px 6px 0 0; border-radius: 6px 6px 0 0; } .zebra tfoot td { border-bottom: 0; border-top: 1px solid #fff; background-color: #f1f1f1; } .zebra tfoot td:first-child { -moz-border-radius: 0 0 0 6px; -webkit-border-radius: 0 0 0 6px; border-radius: 0 0 0 6px; } .zebra tfoot td:last-child { -moz-border-radius: 0 0 6px 0; -webkit-border-radius: 0 0 6px 0; border-radius: 0 0 6px 0; } .zebra tfoot td:only-child{ -moz-border-radius: 0 0 6px 6px; -webkit-border-radius: 0 0 6px 6px border-radius: 0 0 6px 6px }
[/infobox]
运行此项目后访问127.0.0.1:9090
运行web界面效果如图
参考链接
http://www.freebuf.com/articles/network/150613.html
https://nmap.org/book/nse-api.html
http://www.cnblogs.com/liun1994/p/7041373.html
http://blog.csdn.net/xumesang/article/details/51859344
https://zhuanlan.zhihu.com/p/27224457
https://github.com/Z-0ne/ScanS2-045-Nmap/blob/master/struts2-scan.nse
文章的固定链接,使用中文感觉不大舒服!
这个看你个人喜好了~