• nmap之nse脚本简单学习


    nmap之nse脚本简单学习

    环境:centos8

    nmap安装

    yum -y install nmap

    -- 版本
    [root@qingchen /]# nmap -version
    Nmap version 7.70 ( https://nmap.org )
    
    • 1
    • 2
    • 3

    脚本入门学习

    cd /usr/share/nmap

    [root@qingchen nmap]# ls
    nmap.dtd  nmap-mac-prefixes  nmap-os-db  nmap-payloads  nmap-protocols  nmap-rpc  nmap-service-probes  nmap-services  nmap.xsl  nselib  nse_main.lua  scripts
    
    -- nselib scripts是脚本库和脚本都是lua语言编写的
    
    • 1
    • 2
    • 3
    • 4

    cd /usr/share/nmap/scripts

    nmap的脚本存放路径,自己写的脚本放进去就可以使用了,脚本语言lua

    lua学习参考菜鸟或者https://blog.csdn.net/qq_40893942/article/details/127986572

    NSE脚本基本格式

    一个完整的NSE脚本通常都有这么几个部分的代码字段:

    • description 字段:本脚本的说明介绍。

    • categories 字段:本脚本的分类。Nmap执行脚本除了指定单个脚本外,还可以指定某一类脚本,比如default类,我们没有使用–script参数时,默认会加载这一类的脚本。

    • rule 字段:本脚本的执行规则,也即触发脚本执行的条件会在rule字段定义。一般执行规则是一个lua函数,返回值只有true和false两种。

    • action字段:脚本执行的具体内容。rule字段返回true时会执行action字段定义的函数。

    local shortport = require "shortport"
    description = [[demo]]
    author = "qingchen"
    license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
    categories = {"default"}
    
    portrule = function( host, port )
       return true
    end
    
    action = function(host, port)
    
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Demo中rule字段是portrule,NSE脚本的执行规则是和nmap的扫描相结合的,两者执行的先后顺序目前有如下4种。

    1. prerule():规则早于nmap的扫描,执行的顺序是先执行脚本,后nmap扫描。
    2. hostrule():nmap完成了主机发现之后运行脚本。
    3. portrule():nmap执行了端口扫描后运行脚本。
    4. postrule():nmap完成所有的扫描后才执行脚本。

    编写脚本

    在前面脚本demo代码的基础上,只需修改portrule函数的代码和让action函数来输出。

    栗子:

    编写文件名为qingchen-simple-test.nse的脚本放在/usr/share/nmap/scripts,判断80端口是不是tcp协议。内容如下:

    -- 引用shortport脚本库
    local shortport = require "shortport"
    -- 描述
    description = [[qingchen port simple test]]
    -- 作者
    author = "qingchen"
    -- license
    license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
    -- 类别
    categories = {"default"}
    
    portrule = function(host,port)
        return port.protocol == "tcp" and port.number == 80
    end
    
    action = function(host, port)
    print(host.ip)
    return "qingchen-script-test"
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    nmap --script-updatedb命令用来更新脚本库(貌似不更新也是可以直接在scripts文件夹下识别到自定义脚本的)

    nmap -p 80 127.0.0.1 --script qingchen-simple-test.nse 运行脚本

    [root@qingchen scripts]# vim qingchen-simple-test.nse 
    [root@qingchen scripts]# nmap --script-updatedb
    [root@qingchen scripts]# nmap -p 80 127.0.0.1 --script qingchen-simple-test.nse 
    Starting Nmap 7.70 ( https://nmap.org ) at 2022-11-24 13:41 CST
    127.0.0.1
    Nmap scan report for VM-4-3-centos (127.0.0.1)
    Host is up (0.000052s latency).
    
    PORT   STATE SERVICE
    80/tcp open  http
    |_qingchen-simple-test: qingchen-script-test
    
    Nmap done: 1 IP address (1 host up) scanned in 0.45
    
    -- 换8080试试
    
    [root@qingchen scripts]# nmap -p 8080 127.0.0.1 --script qingchen-simple-test.nse 
    Starting Nmap 7.70 ( https://nmap.org ) at 2022-11-24 13:44 CST
    Nmap scan report for VM-4-3-centos (127.0.0.1)
    Host is up (0.000046s latency).
    
    PORT     STATE  SERVICE
    8080/tcp closed http-proxy
    
    Nmap done: 1 IP address (1 host up) scanned in 0.44 seconds
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    编写脚本库文件

    /nselib/文件夹下新建一个名为qingchenlib.lua的文件,填入如下内容:

    function Porttest(port)
        return string.format("The port '%s' is open",port)
    end
    
    • 1
    • 2
    • 3

    作用是查看哪些端口是开放的

    使用脚本库

    编写脚本 qingchen-lib-test.nse

    local shortport = require "shortport"
    local qingchenlib = require "qingchenlib"
    
    description = [[引用库文件测试]]
    
    author = "qingchen"
    license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
    categories = {"default"}
    
    portrule = function( host, port )
        return true
    end
    
    action = function(host,port)
        return Porttest(port.number)
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    引用库文件使用local,格式一般为: local 库文件名 = require “库文件名”,引用后可直接使用库里面的方法和属性值

    Nmap 命令:nmap -Pn 127.0.0.1 --script qingchen-lib-test.nse(可以不带后缀)

    [root@qingchen nselib]# nmap -Pn 127.0.0.1 --script qingchen-lib-test
    Starting Nmap 7.70 ( https://nmap.org ) at 2022-11-24 13:58 CST
    Nmap scan report for VM-4-3-centos (127.0.0.1)
    Host is up (0.0000050s latency).
    Not shown: 996 closed ports
    PORT     STATE SERVICE
    22/tcp   open  ssh
    |_qingchen-lib-test: The port '22' is open
    80/tcp   open  http
    |_qingchen-lib-test: The port '80' is open
    3306/tcp open  mysql
    |_qingchen-lib-test: The port '3306' is open
    9000/tcp open  cslistener
    |_qingchen-lib-test: The port '9000' is open
    
    Nmap done: 1 IP address (1 host up) scanned in 1.80 seconds
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    自定义脚本对mysql数据库操作

    涉及库文件
    • mysql:用来进行数据库操作。
    • nmap:通过nmap建立socket连接mysql。
    • shortport:基本的port规则库。
    创建数据库和存放结果的表

    在你的MySql中建一个名为nmap的数据库,然后建立表和字段:

    CREATE TABLE IF NOT EXISTS nmap.scanData (
        date varchar(40),
        hostos varchar(256),
        hostname varchar(100), 
        ip varchar(16), 
        port integer(5), 
        protocol varchar(3), 
        state varchar(20), 
        service varchar(256), 
        version varchar(256)
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    脚本

    mysql-test.nse

    local mysql = require "mysql"
    local nmap = require "nmap"
    local shortport = require "shortport"
    
    -- 登陆mysql
    local function mysqlLogin(socket, username, password)
        local status, response = mysql.receiveGreeting( socket )
        if ( not(status) ) then
            return response
        end
        return mysql.loginRequest( socket, { authversion = "post41", charset = response.charset }, username, password, response.salt )
    end
    
    description = [[mysql test]]
    author = "qingchen"
    license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
    categories = {"default"}
    portrule = function () return true end
    
    function portaction (host,port)
        local host_local="127.0.0.1"
        local port_local="3306"
        local username="root"
        local password="1234"
        local hostos_str= host.os
        local version = port.version
    
        if (port.version.product~=nil) then
            version = port.version.product
        end
        if (port.version.version~=nil) then
            version = version .. port.version.version
        end
    
        local date=os.date("%Y-%m-%d %H:%M:%S")
        local sql = string.format("INSERT INTO nmap.scanData (date,hostos,hostname,ip, port,protocol,state,service,version) VALUES ('%s','%s','%s', '%s', %d, '%s', '%s', '%s', '%s');select 1",date,hostos_str,host.name,host.ip, port.number,port.protocol,port.state,port.service,version)
    
        local socket = nmap.new_socket()
    
        if ( not(socket:connect(host_local, port_local)) ) then
            return fail("Failed to connect to server")
        end
        local status, response = mysqlLogin(socket, username, password)
        if ( status ) then
            local status, rs = mysql.sqlQuery( socket, sql )
            socket:close()
        else
            socket:close()
        end
    end
    local ActionsTable = {
      portrule = portaction
    }
    -- execute the action function corresponding to the current rule
    action = function(...) return ActionsTable[SCRIPT_TYPE](...) end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    执行 nmap -O 127.0.0.1 --script mysql-test

    [root@qingchen nselib]# nmap -O 127.0.0.1 --script mysql-test
    Starting Nmap 7.70 ( https://nmap.org ) at 2022-11-24 14:08 CST
    Nmap scan report for VM-4-3-centos (127.0.0.1)
    Host is up (0.0000050s latency).
    Not shown: 996 closed ports
    PORT     STATE SERVICE
    22/tcp   open  ssh
    80/tcp   open  http
    3306/tcp open  mysql
    9000/tcp open  cslistener
    Device type: general purpose
    Running: Linux 3.X
    OS CPE: cpe:/o:linux:linux_kernel:3
    OS details: Linux 3.7 - 3.10
    Network Distance: 0 hops
    
    OS detection performed. Please report any incorrect results at https://nmap.org/submit/ .
    Nmap done: 1 IP address (1 host up) scanned in 4.11 seconds
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    查看数据库已经写入数据了

    在这里插入图片描述

    但是其中hostos和version是lua中table格式的数据这里没有转成string所以看不到具体数据

    可以写一个lua库文件作用是:把table转成string

    table2string.lua

    放入nselib库中

    function ToStringEx(value)
        if type(value)=='table' then
            return TableToStr(value)
        elseif type(value)=='string' then
            return "\\'"..value.."\\'"
        else
            return tostring(value)
        end
    end
    
    function TableToStr(t)
        if t == nil then return "" end
        local retstr= "{"
    
        local i = 1
        for key,value in pairs(t) do
            local signal = ","
            if i==1 then
                signal = ""
            end
    
            if key == i then
                retstr = retstr..signal..ToStringEx(value)
            else
                if type(key)=='number' or type(key) == 'string' then
                    retstr = retstr..signal..'['..ToStringEx(key).."]="..ToStringEx(value)
                else
                    if type(key)=='userdata' then
                        retstr = retstr..signal.."*s"..TableToStr(getmetatable(key)).."*e".."="..ToStringEx(value)
                    else
                        retstr = retstr..signal..key.."="..ToStringEx(value)
                    end
                end
            end
    
            i = i+1
        end
    
        retstr = retstr.."}"
        return retstr
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    注意return "\\'"..value.."\\'"这里要加两个转义字符不然就会报错 like this

    connect sucess
    INSERT INTO nmap.scanData (date,hostos,hostname,ip, port,protocol,state,service,version) VALUES ('2022-11-24 14:51:45','nil','VM-4-3-centos', '127.0.0.1', 9000, 'tcp', 'open', 'cslistener', '{['cpe']={},['service_tunnel']='none',['service_dtype']='table',['name']='cslistener',['name_confidence']=3.0}');
    false
    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'cpe']={},['service_tunnel']='none',['service_dtype']='table',['name']='http',['n' at line 1
    false
    -- 插入数据库时也需要对单引号转义否则插入失败
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    写完库文件后,我们只需要引用一下我们写的库调用一下table2string

    完整代码如下:

    local mysql = require "mysql"
    local nmap = require "nmap"
    local shortport = require "shortport"
    local table2string = require "table2string"
    
    local function mysqlLogin(socket, username, password)
        local status, response = mysql.receiveGreeting( socket )
        if ( not(status) ) then
            return response
        end
        return mysql.loginRequest( socket, { authversion = "post41", charset = response.charset }, username, password, response.salt )
    end
    description = [[mysql save test]]
    author = "qingchen"
    license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
    categories = {"default"}
    portrule = function () return true end
    function portaction (host,port)
        local host_local="127.0.0.1"
        local port_local="3306"
        local username="root"
        local password="1234"
        local hostos_str = ToStringEx(host.os)
        local version = ToStringEx(port.version)
    
        if (port.version.product~=nil) then
            version = port.version.product
        end
        if (port.version.version~=nil) then
            version = version .. port.version.version
        end
    
        local date=os.date("%Y-%m-%d %H:%M:%S")
        local sql = string.format("INSERT INTO nmap.scanData (date,hostos,hostname,ip, port,protocol,state,service,version) VALUES ('%s','%s','%s', '%s', %d, '%s', '%s', '%s', '%s');",date,hostos_str,host.name,host.ip, port.number,port.protocol,port.state,port.service,version)
    
        local socket = nmap.new_socket()
    
        if ( not(socket:connect(host_local, port_local)) ) then
            return fail("Failed to connect to server")
        end
        local status, response = mysqlLogin(socket, username, password)
        -- 这里我打印了连接状态和sql语句,方便查看定位错误
        if ( status ) then
            print("connect sucess")
            print(sql)
            local status, rs = mysql.sqlQuery( socket, sql )
            print(status)
            print(rs)
            socket:close()
        else
            socket:close()
        end
    end
    local ActionsTable = {
      portrule = portaction
    }
    -- execute the action function corresponding to the current rule
    action = function(...) return ActionsTable[SCRIPT_TYPE](...) end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    执行命令:nmap -O 127.0.0.1 --script mysql-save-test

    在这里插入图片描述

    可以看到打印出数据了

    end

    到此就是完成对nmap脚本nse的简单学习了

  • 相关阅读:
    图神经网络 | Python实现基于时空图卷积GNN + LSTM 模型预测(多变量方法)
    Mysql 面试题总结
    Kyligence Cloud 集成 Amazon Glue 实现数据目录统一管理
    超详细SpringBoot+Vue项目部署(两个Vue项目)
    肖sir__linux讲解vim命令(3.1)
    安装与配置FTP服务器
    剑指Offer面试题解总结61~70
    PostgreSql linux 常用命令
    电气元器件的型号,符号,接线认识(一)
    Linux fork和vfork函数用法
  • 原文地址:https://blog.csdn.net/qq_40893942/article/details/128019728