文章目录结构:
0x00 选择whatweb的原因
0x01 简述whatweb打包EXE
0x02 改造whatweb请求头
0x03 Whatweb插件编写规则细节
0x04 实战开发spring-boot Whitelabel页面匹配
0x05 总结与下载
0x00 选择whatweb的原因
以前写过一篇文字,在windows上安装whatweb和ruby。为什么这么多指纹识别工具,我还要选择whatweb呢?随着工具的增多,我们需要对手上常用的渗透工具对比选择。我对比的主要方向是维护更新、扫描思路、批量支持、扩展修改性、阶段专业性等。PS:如果以后有机会做基础讲解的话,会分析下各阶段工具。
Whatweb指纹分析工具优缺点分析
优点:
1、综合指纹判断,输出信息全面,
2、插件结构完善,插件编写简单
3、CMD支持,GUI扩展,
4、多目标,IP地址范围支持,多线程,
5、代理支持,报头自定义
缺点:
1、由ruby开发,win下需要配置额外开发环境
2、结果输出复杂,需要额外进行结果解析。
3、国际化工具,需要适应国情的插件配置
缺点解决办法:
1、将whatweb打包成exe运行。【已实现】
2、编写脚本,对结果进行自定义解析。【已实现】
3、编写脚本,批量实现国内插件转whatweb插件格式
最终还是选择了Whatweb作为我的基础指纹识别工具。PS:文章末尾会附修改及打包好的whatweb0.5.5.1下载地址。
0x01 简述whatweb打包EXE
测试了一下kali下的ruby打包exe工具,发现打包whatweb失败,最终在github找到一个可行的新项目:ruby-packer其打包原理类似python,是将所有的文件打包成一个自解压可执行文件,支持windows、linux、macos平台安装。
pmq20/ruby-packer:
https://github.com/pmq20/ruby-packer
Windows下Ruby-packer安装:
首先安装预备环境:
1、Visual Studio,所有版本,包括社区版(记得在安装过程中选择"Common Tools for Visual C++"功能)。
2、SquashFS Tools::先百度安装巧克力(https://chocolatey.org/),然后执行choco install squashfs
3、Ruby:安装ruby环境(https://rubyinstaller.org/)。
4、perl:安装perl环境http://strawberryperl.com/。
5、Netwide Assembler:安装nasm,并将以上环境可执行文件加入环境变量。
6、测试rubyc.exe
下载rubyc(https://github.com/pmq20/ruby-packer#unstable-pre-release)
打开Visual Studio 的 "VS20XX x64 Native Tools Command Prompt"
最终执行:
\rubyc路径\rubyc.exe --help
建议:将以上环境可执行文件加入环境变量。
7、配置cacert.pem
下载cacert.pem放到任意目录下(如C:\cacert)
并新增SSL_CERT_FILE环境变量,值为C:\cacert\cacert.pem。
(如果没有证书,会显示gems https访问失败。)
(下载地址:http://curl.haxx.se/ca/cacert.pem)
8、最终打包
cd whatweb目录
rubyc.exe whatweb\whatweb
#亲测打包环境安装不是很复杂,但是比较费时#rubyc 将程序打包后可以通过upx等进行再次压缩。#WhatWeb初步打包为17M,upx压缩后为12M。#WhatWeb.exe启动时会有1s-2s延迟。#rubyc 打包的exe可以直接通过zip进行解压。如果找到一个可以原样编辑的EXE压缩包的程序,更新程序就不需要再次打包了。(坐等大家的推荐)
0x02 改造whatweb请求头
在内网用了一下whatweb扫描目标服务器,被防火墙直接拦截,分析流量发现其特征很明显。默认whatweb流量特征:
GET / HTTP/1.1
User-Agent: WhatWeb/0.5.5.1
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
#User-Agent 必需修改,否则会被防火墙标记
#Accept 建议修改,否则返回值可能是Json模式
#不同的请求头可能会造成不同的请求结果,建议使用Burp代理进行流量记录。
whatweb修改:添加动态refer和host 和其他默认头经过分析,发现在WhatWeb\lib\target.rb文件中动态修改是最通用的办法,且不会对其他的命令行参数进行影响。主要是修改refer、host、user-agent等请求头。
\WhatWeb\lib\target.rb 行267
############################################editor
@host = @uri.host #editor
@refer [email protected]_s #editor #puts @refer
############################################editor
\WhatWeb\lib\target.rb 行296
############################################editor
#根据输入参数动态设置host
$CUSTOM_HEADERS["HOST"] = "#@host"
#根据输入参数动态设置refer
$CUSTOM_HEADERS["Refer"] = "#@refer"
#增加随机user-agent列表
@user_agent_list = Array[
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36 Edg/89.0.774.48",
"Mozilla/5.0 (Android; Tablet; rv:14.0) Gecko/14.0 Firefox/14.0",
"..............",
"Mozilla/5.0 (iPhone; CPU iPhone OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A366 Safari/600.1.4",
"Mozilla/5.0 (iPod; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3",
]
#启用随机user-agent列表,未启用,感觉固定的就够
#@user_agent = @user_agent_list[rand(@user_agent_list.length)] #Open random user-agent
#增加固定user-agent列表
@user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36 Edg/89.0.774.48" #editor
#设置默认accept头
@accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
#设置默认accept-encodind 头
@accept_encodind = "gzip, deflate"
#设置默认accept-language 头
@accept_language = "zh-CN,zh;q=0.9"
#判断发送前报头中是否存在指定请求头,
#没有就新增报头,有就替换或者不处理。
if $CUSTOM_HEADERS["User-Agent"].downcase.include?"whatweb" then $CUSTOM_HEADERS["User-Agent"] = @user_agent end;
if $CUSTOM_HEADERS.has_key?("Accept") == false then $CUSTOM_HEADERS["Accept"] = @accept end;
if $CUSTOM_HEADERS.has_key?("Accept-Encoding") == false then $CUSTOM_HEADERS["Accept-Encoding"] = @accept_encoding end;
if $CUSTOM_HEADERS.has_key?("Accept-Language") == false then $CUSTOM_HEADERS["Accept-Language"] = @accept_language end;
#puts $CUSTOM_HEADERS
############################################editor
修改后的whatweb流量特征:
GET / HTTP/1.1
User_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36 Edg/89.0.774.48
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Connection: close
Host: XXXX
0x03 Whatweb插件编写规则
官方的插件示例在my-plugins/文件夹中,编写前可以进行参考
https://github.com/urbanadventurer/WhatWeb/wiki
在wiki有更多的开发思路和资源
基本匹配示例:
# 搜索一个文本字符串。
{ :text => "This page was generated by <b>Generic CMS</b>" },
# 搜索正则表达式。注意斜杠是转义。
{ :regexp => /This page was generated by <a href="http:\/\/www.genericcms.com\/en\/products\/generic-cms\/">Generic CMS<\/a>/ },
# #从Mega generator标签中提取通用CMS的版本。
{ :name => "Meta generator", :version => /<meta name="generator" content="Generic CMS version ([a-z0-9])+/ }
# HTTP服务器头信息
# 检测HTTP服务器报头中的文本“GenericServer”
{ :search => "headers[server]",:regexp => /^GenericServer / },
# HTTP服务器报头
# 从HTTP服务器报头中提取GenericServer的版本
{ :search => "headers[server]",:version => /^GenericServer V([^\s]+)/,},
#从Mega generator标签中提取通用CMS的版本。
{ :name => "Meta generator", :version => /<meta name="generator" content="Generic CMS version ([a-z0-9])+/ },
#检测通用CMS cookie。注意:search被设置为"headers[set-cookie]"
{ :search => "headers[set-cookie]", :regexp => /genericcms=[^;]+;/ },
#检测headers的CMScookie的__genericwafuid cookie #猜测作用
{ :search => "headers[set-cookie]", :regexp => /__genericwafuid/, :name=>"__genericwafuid cookie" },
# 检查图像的MD5sum哈希值来检测准确的版本
# 在野蛮模式3中,只有这个插件已经匹配,这些才会被检查
# 在侵略模式4,这些将被检查
# :model作用不知道干嘛的
{ :model => 'gsl2540b', :md5 => "d076eed06cafe1e4a74f83c7fdfe2e67", :url => '/generic/images/gsl2540b.jpg' },
{ :model => 'gsl2640b', :md5 => "01aa666a65a72bb4ab0deadbeef525f4", :url => '/generic/images/gsl2640b.jpg' },
#搜索引擎搜索关键字
dorks [
'"Generic CMS login"',
'Generic login register linkname',
]
细节匹配规则:
## 模式匹配##
# :regexp #Ruby格式的正则表达式
# :text #不分大小写的文本
# :ghdb #谷歌Hack数据库格式。这支持使用intitle:、inurl:和minus。
# :md5 #HTTP响应正文的MD5和哈希值
# :tagpattern #HTML标记名称列表。
##在哪里搜索##
# :search #可以是"body"(默认),"all","headers"或"headers[x]"为一个特定的HTTP头
#插件名称匹配##
# :name #您可以选择命名匹配。此名称将在详细输出中显示。
## 返回数据 ##
# 这些符号可以是一个正则表达式或文本。
#
# :version #版本
# :account #用户帐号名
# :module #一个模块名称
# :make #制造商,例如NetGear
# :model #模型,例如SpeedErr
# :firmware #固件,例如6.14.14
# :filepath 这些可以显示在错误消息中
# :string #这是为了返回上面的符号没有涵盖的数据。例如,电子邮件地址。
#
##模式确定性# #
# :certainty #这次匹配确定性。100是确定的(默认),75是可能的,25是可能的
##限制匹配到URL路径或HTTP状态##
# :url #您可以将其与其他变量结合使用,也可以单独使用
# :status #响应的HTTP状态
#你可以在插件中编写定制的Ruby代码来获得更多的控制
#支持有被动功能和主动功能。
#被动函数将始终执行
高级匹配示例:
Plugin.define do
name "Plugin-Tutorial-6" #插件名称
authors [ #插件作者
"Your preferred name <email@address>", # v0.1 # 2019-01-01 # Created plugin
]
version "0.1" #插件版本
description "Describe plugin" #插件描述
website "http://example.com/" #对应网站
#搜索引擎关键字
dorks [ '"Generic CMS login"','Generic login register linkname',]
#基本匹配列表
matches [
# 搜索一个文本字符
{ :text => "Generic CMS" },
]
#可以在插件中编写定制的Ruby代码来获得更多的控制匹配选项
#插件支持被动功能和主动功能。
#被动函数将始终执行
# 插件中可用的变量
# @body #响应体
# @headers #响应头
# @cookies #响应Cookie
# @status #响应状态码
# @base_uri #请求URI
# @md5sum #文件MD5值
# @tagpattern #标签匹配
# @ip #响应IP
#
#被动匹配
passive do
# 创建一个匹配数组
m = []
# 如果HTTP状态是302,重定向位置是/admin/genericcms.php,那么匹配
if @status.to_s =~ /^302$/ and @headers["location"] =~ /^\/admin\/genericcms\.php$/
m << { :name => "302 redirection to /admin/genericcms.php" }
end
#你可以添加调试和检查变量的值
# pp @status #输出status
# pp @headers #输出headers
# #返回匹配数组,即使它是空的
m
end
##
# 主动性函数只会有时执行
# 在主动级别3中,如果找到匹配,则执行主动函数
# #在主动级别4,主动函数总是执行
#主动匹配
aggressive do
@variables[:my_var] += 1
# 创建一个匹配数组。这将返回相当于上面的matches[]块的内容
m = []
# 返回匹配数组,即使它是空的
m
end
## 很少有插件需要启动和关闭功能
# 当插件第一次加载时执行
def startup
@variables = {my_var: 1}
end
# 当插件在web关闭时执行
def shutdown
# puts("my_var is #{@variables[:my_var]}")
end
end
其他参考:
网站指纹识别 whatweb - 知乎
https://zhuanlan.zhihu.com/p/28017554
#感觉好像也写的很模糊
0x04 实战开发spring-boot Whitelabel页面匹配
简单的规则只需要在matches[]数组中进行简单的添加即可实现。更复杂的匹配需要一些ruby语法基础,花半天看看就能够熟悉该语法。通过匹配返回报文中的Whitelabel Error Page来进行spring-boot框架的匹配。
Plugin.define do
name "Spring-Boot"
authors [
"WINEZER0",
]
version "0.1"
description "Spring is an open source application framework for the Java platform."
website "http://www.springsource.org/"
# Matches #匹配规则
matches [
#在响应包中查看Whitelabel Error Page匹配。
{ :text=>"Whitelabel Error Page" },
#扩展:通过主动访问错误url判断,需要攻击级别 == 4
#1级. 每个目标发送一个HTTP请求遵循重定向。
#3级. 如果一个1级插件匹配,附加URL请求将会被提出。
#4级. 对每个目标发送大量HTTP请求。将从所有插件尝试URL。
#通过访问指定URL,并通过正则匹配Whitelabel Error Page
{ :url => "/xxx/xxx/xxx/xxx", :text=>"Whitelabel Error Page"},
]
end
0x05 总结
目前whatweb最新版本是0.5.5 (20210530)获取修改版whatweb0.5.5.1及打包好的EXENOVASEC百度云盘共享地址
链接:https://pan.baidu.com/s/1YL0QTYaui-U1n2uGH8lGIg
提取码:bs7c WhatWeb的插件开发中文资料还是不够详细。很多关键字不知道具体含义,不过即使是这样也能够将常见的规则转换为whatweb内置规则了。等有时间会写一个PY脚本,进行批量的指纹的转换。如果需要更高级的定制,菜鸟教程支持ruby语法进行简单学习。PS:rubyc 打包的exe可以直接通过zip进行解压。如果找到一个可以原样编辑的EXE压缩包的程序,更新程序就不需要再次打包了。(坐等大家的推荐)
来源:freebuf.com 2021-05-31 10:47:02 by: WineCo
请登录后发表评论
注册