浅谈Web应用指纹识别
浅谈Web应用指纹识别
Web应用指纹识别是指通过分析Web应用公开暴露的技术特征,识别出该应用所使用的技术栈、框架、服务器类型、版本信息等关键组件。这种技术在渗透测试中非常重要,因为它有助于安全测试人员选择最合适的攻击向量和漏洞利用方式,同时在实战中也有助我们寻找相关站点,扩大攻击面,增加攻击容错。
本文主要出于寻找同源/同框架站点的目的分析Web应用指纹,所以与常规红队行动信息收集侧重点有所不同。接下来将从两部分分析web应用指纹识别。
P1: 如何寻找网站特征?
提取Web应用指纹的思路非常清晰,找到关键特征即可。例如张三是一位长头发的男生,在茫茫人群中,我们要如何快速地跟别人描述,让他一眼就可以找到张三呢?显而易见,“长头发的男生”就是一个区别于其他人的明显特征。同理,对于网站,我们也可以使用这样的方法。例如一个wordpress站点
这是他的首页,我们对其进行目录扫描,就可以发现一些独特的目录,例如 wp-content , wp-admin 等…….
由此我们就可以判断这是一个wordpress站点,这是一个略微复杂的案例,针对不同的站点,我们可以选用不同的办法来帮助我们快速判断。
P2: 识别当前网站指纹
常见的指纹识别方法
在梳理识别方法之前,我们可以回忆一下对于一个网站,我们能得到什么信息,header,body…….这些我们能得到的信息都可以成为特征的出处。我们将介绍几个常见的特征思路,并且附上相应的搜索语法,本文主要以Fofa和Google语法为例,因为搜索语法的相关篇幅较长,详细介绍附在文末,同时出于学习目的,关于自动化识别的部分将会比较省略。
1. 网站图标
网站图标是一个重要的标志,大部分同源的网站,尤其是品牌、框架这一类比较有辨识度的都会选择使用同一个icon,在一些攻防演练中,网站中出现的icon也是判断靶标归属的重要规则之一。
- Fofa:
icon_hash=""
2. 网站标题
在实际运营中,标题往往是代表站点信息,这往往是不会改变的,我们只需要获得 title 的内容即可。
- Fofa:
title=""
3. 网站响应头信息
一些应用会在请求头/响应头中加入字段,这可以作为我们判断的依据。
| No.1 | X-Powered-By:Jboss | jboss的指纹 | | —- | ———————- | ———— | | No.2 | X-Drupal-Cache: | drupal的指纹 | | No.3 | Server:nginx | nginx的指纹 | | No.4 | Set-Cookie:PHPSESSID | php的指纹 |
- Fofa:
header=""
4. 特殊文件
因为开发或者开源需要,开发者往往会添加一些其他人可能想知道的信息,这些信息往往会存在特定文件中,比如 README.md,LICENCE等,顺着这个思路,我们也可以发现 robots.txt或者 sitemap.xml文件也会暴露网站的路径,帮助我们识别目标站点。
robots.txt
- Google:
inurl:""
6. 前端技术
- 最直接的方法就是查看网站源代码,查找明显的关键词,如:
React,Vue,Angular,Next.js,Bootstrap,Tailwind,jQuery等。 查找<script>标签引入的外部 JS 文件路径,比如:cdn.jsdelivr.net/npm/vue@3。 查找<link>标签中是否包含Bootstrap、Tailwind等常用 CSS 框架。 - 使用开发者工具 加载的 JavaScript 文件名称和路径(例如:
main.[hash].js是 Webpack 的典型产物)。React DevTools或Vue DevTools插件也能识别出目标页面是否用了对应框架。 观察 HTTP 响应头
某些框架或工具会在响应头中暴露线索,比如:
x-powered-by: Next.jsserver: Netlifyx-generator: WordPress.com
7. CDN信息
一些网站使用了CDN会在header字段里出现,可以查看是否使用CDN,如cloudflare、360cdn、365cyd、yunjiasu等
- Fofa:
header=""
8. WAF信息
是否使用waf,如Topsec、Jiasule、Yundun等;
9. IP及域名信息
ip与域名也是一种收集的思路,单个ip绑定多个域名,多个域名绑定单个ip,都是可以去思考的点。
- Fofa:
ip="",domain=""
10. 端口与服务信息
- 可以搜集网站开启的端口,例如tomcat默认端口8080,宝塔中间件默认端口888。
- 服务也是可以关注的点,同一个开发团队往往会选用同样的中间件或者技术栈
- Fofa:
port="",server=""
- Fofa:
11. 特定文件的MD5
一些网站的特定图片文件、js文件、CSS等静态文件,如 favicon.ico、 css、 logo.ico 、 js等文件一般不会修改,通过爬虫对这些文件进行抓取并比对md5值,如果和规则库中的Md5一致则说明是同一CMS。这种方式速度比较快,误报率相对低一些,但也不排除有些二次开发的CMS会修改这些文件。
- Fofa:
js_md5=""
12. 正常页面或错误网页中包含的内容
网页包含的特殊内容,比如一段特别的介绍文字
- Fofa:
body=""
13. URL包含的信息
- 许多应用有自己独特的路径命名,例如
wordpress的路径往往是wp-XXX,mybbcms的路径往往是bb-XXX。 - 部分国人自开发的应用会使用拼音命名路径,这也可以提取为特征。
- 前端项目的组件排列也可以作为判断,例如#home/home/index这样有明显特征的情况
- Google:
inurl:""
- Google:
14. 中间件信息
- 查看响应头
- 通过页面特征识别(默认页面/错误页面)
- Fofa:
header="",title="" - Google:
intitle:"Apache2 Ubuntu Default Page”,inurl:"/manager/html" intitle:"Apache Tomcat"
- Fofa:
15. 开发语言
url后缀判断
后缀 推测语言 .phpPHP .jsp,.jspx,.do,.actionJava .aspx,.ashxASP.NET .py,.cgiPython(Flask/Django) .rb,.erbRuby on Rails .js+ API 结构Node.js 可能 - 响应头判断Server 字段,X-Powered-By 字段
页面内容特征识别
|
jsessionid=| Java | | ———————– | —————- | |_VIEWSTATE=| ASP.NET | |.php?参数结构或报错页 | PHP | |csrfmiddlewaretoken| Django(Python) | |express-session| cookie → Node.js | - Google:查找 PHP 报错页面
intext:"Warning: include()" filetype:php查找 ASP.NET 报错页intitle:"Server Error in '/' Application"查找 Java 报错页intext:"java.lang.NullPointerException"查找 Flask 应用(Python)intext:"Werkzeug powered traceback"
16. COOKIE信息
| Cookie 名称 | 推测后端语言/框架 |
|---|---|
PHPSESSID | PHP |
JSESSIONID | Java (Tomcat, Spring) |
ASP.NET_SessionId | ASP.NET |
connect.sid | Node.js (Express/Connect) |
sessionid | Django(Python) |
_rails_session | Ruby on Rails |
laravel_session | Laravel (PHP框架) |
17. HTML源码信息
html源代码中包含注释、js、css等信息,通过访问这些信息来判断和确认cms系统框架。
在源代码中常常会包含 powered by 、bulit upon、 running等特征,可以判断特征以及版本号等信息。
HTML也会包含一些其他信息,例如 author 、 copyright 等
1
2
3
4
5
6
7
8
9
10
title
meta
- keyword
- description
- generator
- author
- copyright
script
html
real_url (真实跳转链接)
- Fofa:
body="",js_name=""
18. 操作系统信息
基于 TCP/IP 协议栈的指纹识别(TTL / Window Size)
操作系统 TTL 典型值 窗口大小(Window Size) Linux 64 5840/14600 Windows 128 8192/65535 FreeBSD 64 65535 Cisco / Router 255 4128 ping -c 1 [target.com](http://target.com/) traceroute [target.com](http://target.com/)分析 HTTP 响应头和页面内容
Server字段可能泄漏 OS 或 Web 服务平台.asp,.aspx→ Windows Server + IIS.php,.cgi,.pl→ 常见于 Linux + Apache/Nginx -port="445" && protocol="smb"
应用指纹识别自动化工具
参考这篇文章,给出了许多实用工具。
TideFinger/Web指纹识别技术研究与优化实现.md at master · TideSec/TideFinger
P3. 寻找同源站点
Google Hack
etc…
https://cloud.tencent.com/developer/article/2150789
FOFA
FOFA的资产是以IP和端口为单位,不是以IP为单位。所以存在同IP不同端口的数据。
主要分为检索字段以及运算符,所有的查询语句都是由这两种元素组成的。
| 逻辑运算符 | | | ———- | ———————————————– | | = | 匹配,=”“时,可查询不存在字段或者值为空的情况。 | | == | 完全匹配,==”“时,可查询存在且值为空的情况。 | | && | 与 | | != | 不匹配,!=”“时,可查询值不为空的情况。 | | *= | 确认查询优先级,括号内容优先级最高。 |
- 检索字段
基础类
基础类(General) 语法 例句 用途说明 = != *= ip ip=”1.1.1.1” 通过单一IPv4地址进行查询 ✓ ✓ - ip=”220.181.111.1/24” 通过IPv4 C段进行查询 ✓ ✓ - ip=”2600:9000:202a:2600:18:4ab7:f600:93a1” 通过单一Ipv6地址进行查询 ✓ ✓ - port port=”6379” 通过端口号进行查询 ✓ ✓ ✓ domain domain=”qq.com” 通过根域名进行查询 ✓ ✓ ✓ host host=”.fofa.info” 通过主机名进行查询 ✓ ✓ ✓ os os=”centos” 通过操作系统进行查询 ✓ ✓ ✓ server server=”Microsoft-IIS/10” 通过服务器进行查询 ✓ ✓ ✓ asn asn=”19551” 通过自治系统号进行搜索 ✓ ✓ ✓ org org=”LLC Baxet” 通过所属组织进行查询 ✓ ✓ ✓ is_domain is_domain=true 筛选拥有域名的资产 ✓ - - is_domain=false 筛选没有域名的资产 ✓ - - is_ipv6 is_ipv6=true 筛选是ipv6的资产 ✓ - - is_ipv6=false 筛选是ipv4的资产 ✓ - - 标记类
语法 例句 用途说明 = != *= app app=”Microsoft-Exchange” 通过FOFA整理的规则进行查询 ✓ - - fid fid=”sSXXGNUO2FefBTcCLIT/2Q==” 通过FOFA聚合的站点指纹进行查询 ✓ ✓ - product product=”NGINX” 通过FOFA标记的产品名进行查询 ✓ ✓ - category category=”服务” 通过FOFA标记的分类进行查询 ✓ ✓ - type type=”service” 筛选协议资产 ✓ - - type=”subdomain” 筛选服务(网站类)资产 ✓ - - cloud_name cloud_name=”Aliyundun” 通过云服务商进行查询 ✓ ✓ ✓ is_cloud is_cloud=true 筛选是云服务的资产 ✓ - - is_cloud=false 筛选不是云服务的资产 ✓ - - is_fraud is_fraud=true 筛选是仿冒垃圾站群的资产 (专业版及以上) ✓ - - is_fraud=false 筛选不是仿冒垃圾站群的资产(已默认筛选) ✓ - - is_honeypot is_honeypot=true 筛选是蜜罐的资产 (专业版及以上) ✓ - - is_honeypot=false 筛选不是蜜罐的资产(已默认筛选) ✓ - - 协议类
协议类 (type=service) 语法 例句 用途说明 = != *= protocol protocol=”quic” 通过协议名称进行查询 ✓ ✓ ✓ banner banner=”users” 通过协议返回信息进行查询 ✓ ✓ - banner_hash banner_hash=”8945471267541271602” 通过协议响应体计算的hash值进行查询 (个人版及以上) ✓ ✓ - banner_fid banner_fid=”zRpqmn0FXQRjZpH8MjMX55zpMy9SgsW8” 通过协议返回信息结构计算的指纹值进行查询。 (个人版及以上) ✓ ✓ - base_protocol base_protocol=”udp” 查询传输层为udp协议的资产 ✓ ✓ - base_protocol=”tcp” 查询传输层为tcp协议的资产 ✓ ✓ - 网站类
网站类(type=subdomain) 语法 例句 用途说明 = != *= title title=”beijing” 通过网站标题进行查询 ✓ ✓ ✓ header header=”elastic” 通过响应标头进行查询 ✓ ✓ - header_hash header_hash=”1258854265” 通过http/https响应头计算的hash值进行查询 (个人版及以上) ✓ ✓ ✓ body body=”网络空间测绘” 通过HTML正文进行查询 ✓ ✓ - body_hash body_hash=”-2090962452” 通过HTML正文计算的hash值进行查询 ✓ ✓ - js_name js_name=”js/jquery.js” 通过HTML正文包含的JS进行查询 ✓ ✓ ✓ js_md5 js_md5=”82ac3f14327a8b7ba49baa208d4eaa15” 通过JS源码进行查询 ✓ ✓ ✓ cname cname=”ap21.inst.siteforce.com” 通过别名记录进行查询 ✓ ✓ ✓ cname_domain cname_domain=”siteforce.com” 通过别名记录解析的主域名进行查询 ✓ ✓ ✓ icon_hash icon_hash=”-247388890” 通过网站图标的hash值进行查询 ✓ ✓ - status_code status_code=”402” 筛选服务状态为402的服务(网站)资产 ✓ ✓ - icp icp=”京ICP证030173号” 通过HTML正文包含的ICP备案号进行查询 ✓ ✓ ✓ sdk_hash sdk_hash==”Mkb4Ms4R96glv/T6TRzwPWh3UDatBqeF” 通过网站嵌入的第三方代码计算的hash值进行查询 (商业版及以上) ✓ ✓ - 地理位置
语法 例句 用途说明 = != *= country country=”CN” 通过国家的简称代码进行查询 ✓ ✓ - country=”中国” 通过国家中文名称进行查询 ✓ ✓ - region region=”Zhejiang” 通过省份/地区英文名称进行查询 ✓ ✓ - region=”浙江” 通过省份/地区中文名称进行查询(仅支持中国地区) ✓ ✓ - city city=”Hangzhou” 通过城市英文名称进行查询 ✓ ✓ - 证书类
语法 例句 用途说明 = != *= cert cert=”baidu” 通过证书进行查询 ✓ ✓ - cert.subject cert.subject=”Oracle Corporation” 通过证书的持有者进行查询 ✓ ✓ ✓ cert.issuer cert.issuer=”DigiCert” 通过证书的颁发者进行查询 ✓ ✓ ✓ cert.subject.org cert.subject.org=”Oracle Corporation” 通过证书持有者的组织进行查询 ✓ ✓ ✓ cert.subject.cn cert.subject.cn=”baidu.com” 通过证书持有者的通用名称进行查询 ✓ ✓ ✓ cert.issuer.org cert.issuer.org=”cPanel, Inc.” 通过证书颁发者的组织进行查询 ✓ ✓ ✓ cert.issuer.cn cert.issuer.cn=”Synology Inc. CA” 通过证书颁发者的通用名称进行查询 ✓ ✓ ✓ cert.domain cert.domain=”huawei.com” 通过证书持有者的根域名进行查询 ✓ ✓ ✓ cert.is_equal cert.is_equal=true 筛选证书颁发者和持有者匹配的资产 (个人版及以上) ✓ - - cert.is_equal=false 筛选证书颁发者和持有者不匹配的资产 (个人版及以上) ✓ - - cert.is_valid cert.is_valid=true 筛选证书是有效证书的资产 (个人版及以上) ✓ - - cert.is_valid=false 筛选证书是无效证书的资产 (个人版及以上) ✓ - - cert.is_match cert.is_match=true 筛选证书和域名匹配的资产 (个人版及以上) ✓ - - cert.is_match=false 筛选证书和域名不匹配的资产 (个人版及以上) ✓ - - cert.is_expired cert.is_expired=true 筛选证书已过期的资产 (个人版及以上) ✓ - - cert.is_expired=false 筛选证书未过期的资产 (个人版及以上) ✓ - - jarm jarm=”2ad2ad0002ad2ad22c2ad2ad2ad2ad2eac92ec34bcc0cf7520e97547f83e81” 通过JARM指纹进行查询 ✓ ✓ ✓ tls.version tls.version=”TLS 1.3” 通过tls的协议版本进行查询 ✓ ✓ - tls.ja3s tls.ja3s=”15af977ce25de452b96affa2addb1036” 通过tls的ja3s指纹进行查询 ✓ ✓ ✓ cert.sn cert.sn=”356078156165546797850343536942784588840297” 通过证书序列号进行查询 ✓ ✓ - cert.not_after.after cert.not_after.after=”2025-03-01” 筛选某证书到期日期后的证书 ✓ - - cert.not_after.before cert.not_after.before=”2025-03-01” 筛选某证书到期日期前的证书 ✓ - - cert.not_before.after cert.not_before.after=”2025-03-01” 筛选某证书生效日期后的证书 ✓ - - cert.not_before.before cert.not_before.before=”2025-03-01” 筛选某证书生效日期前的证书 ✓ - - 时间类型
语法 例句 用途说明 = != *= after after=”2023-01-01” 筛选某一时间之后有更新的资产 ✓ - - before before=”2023-12-01” 筛选某一时间之前有更新的资产 ✓ - - after&before after=”2023-01-01” && before=”2023-12-01” 筛选某一时间区间有更新的资产 ✓ - - 独立IP语法(不可叠加语法查询)
语法 例句 用途说明 = != *= port_size port_size=”6” 筛选开放端口数量等于6个的独立IP (个人版及以上) ✓ ✓ - port_size_gt port_size_gt=”6” 筛选开放端口数量大于6个的独立IP (个人版及以上) ✓ - - port_size_lt port_size_lt=”12” 筛选开放端口数量小于12个的独立IP (个人版及以上) ✓ - - ip_ports ip_ports=”80,161” 筛选同时开放不同端口的独立IP ✓ - - ip_country ip_country=”CN” 通过国家的简称代码进行查询独立IP ✓ - - ip_region ip_region=”Zhejiang” 通过省份/地区英文名称进行查询独立IP ✓ - - ip_city ip_city=”Hangzhou” 通过城市英文名称进行查询独立IP ✓ - - ip_after ip_after=”2021-03-18” 筛选某一时间之后有更新的独立IP ✓ - - ip_before ip_before=”2019-09-09” 筛选某一时间之前有更新的独立IP ✓ - -
P4. 实战演练
判断是wordpress站点
判断中间件为nginx
对iconhash进行搜索得到更多内容
对网站内容进行搜索,搜出来了其他的域名
可以发现,网站的结构,内容都有所不同,但是title都一样,所以可以利用这个title继续搜索
这里可以看到有很多证书绑定的域名是一致的,也可以反向查询证书绑定的域名。
cert=”www.0do.cn”
P5. 参考文章
- https://hackeyes.github.io/2021/04/17/fofa语法/
- https://www.freebuf.com/sectool/268246.html
- https://fofa.info/help_articles/list
- https://zhuanlan.zhihu.com/p/673765679
- https://github.com/TideSec/TideFinger/blob/master/Web指纹识别技术研究与优化实现.md
- https://cloud.tencent.com/developer/article/1429137
- https://cloud.tencent.com/developer/article/2150789
- https://www.ddosi.org/b94/












"](/../assets/img/2025-04-23-浅谈Web应用指纹识别/image%2012.png)