404页面识别
字数 940 2025-08-26 22:11:28
404页面识别技术详解
前言
在网络安全和渗透测试中,子域名收集是资产信息收集的重要环节。然而,现有的子域名挖掘工具往往存在准确率不高的问题,返回的结果中包含大量无效的404页面。本文详细介绍如何通过技术手段识别和过滤404页面,提高子域名收集的效率和质量。
404页面的呈现方式
-
标准404页面:Web容器设置的404错误页面,服务端返回404状态码
- 示例:Freebuf网站访问不存在的页面时返回404状态码和404页面
-
重定向404页面:将404错误页面指向一个新的页面,页面上显示404信息,但状态码可能为301、302或200
- 示例:百度访问不存在的页面会返回200状态码并跳转到
https://www.baidu.com/search/error
- 示例:百度访问不存在的页面会返回200状态码并跳转到
404页面识别思路
- 基于状态码判断:直接检查HTTP响应状态码是否为404
- 基于页面相似度判断:
- 获取目标域名的404页面样本
- 比较请求页面与404样本页面的相似度
- 超过阈值则判定为404页面
关键技术实现
页面相似度计算
使用hashes.simhash算法计算页面内容的哈希值,并通过相似度比较判断页面是否相似:
from hashes.simhash import simhash
def is_similar_page(res1, res2, radio=0.85):
if res1 is None or res2 is None:
return False
body1 = res1.body
body2 = res2.body
url1 = res1.get_url()
url2 = res2.get_url()
simhash1 = simhash(body1.decode('utf-8'))
simhash2 = simhash(body2.decode('utf-8'))
calc_radio = simhash1.similarity(simhash2)
if calc_radio >= radio:
return True
else:
return False
404页面样本构造
通过访问随机生成的不存在页面来获取404页面样本:
def generate_404_kb(self, url):
domain = url.get_domain() # www.freebuf.com
domain_path = url.get_domain_path() # https://www.freebuf.com
rand_file = rand_letters(8) + '.html'
url_404 = domain_path.urljoin(rand_file)
resp_200 = requests.get(domain_path)
resp_404 = requests.get(url_404)
# 处理网站容错情况
if is_similar_page(resp_200, resp_404):
# 如果相似度等于1,证明domain页面本身就是404页面
if is_similar_page(resp_200, resp_404, 1):
self._404_already_domain.append(domain)
self._404_kb.append((domain, resp_200))
else:
self._404_already_domain.append(domain)
self._404_kb.append((domain, resp_404))
完整404识别类实现
class page_404:
_instance = None
def __init__(self):
self._404_already_domain = []
self._404_kb = []
# 可能返回404页面的状态码列表
self._404_code_list = [200, 301, 302]
def generate_404_kb(self, url):
# 同上
def set_check(self):
self._404_kb = []
self._404_checked = False
def is_404(self, http_response):
code = http_response.get_code()
url = http_response.get_url()
domain = url.get_domain()
if domain not in self._404_already_domain:
self.generate_404_kb(url)
# 如果状态码为404直接返回
if code == 404:
return True
if code in self._404_code_list:
for domain_404, resp_404 in self._404_kb:
# 判断域名是否一样
if domain == domain_404:
if is_similar_page(http_response, resp_404):
return True
return False
def is_404(http_response):
if page_404._instance is None:
page_404._instance = page_404()
return page_404._instance.is_404(http_response)
特殊案例处理
荒废域名的识别
当域名本身无效,访问主域名也会跳转到404页面时,需要特殊处理:
- 访问主域名(
domain_path)和随机生成的404页面(url_404)都返回相似内容 - 如果相似度达到1(完全一致),则判定该域名本身就是404页面
- 将这种情况也记录到404知识库中
技术要点总结
- 相似度阈值选择:通常设置为0.85,可根据实际情况调整
- 状态码处理:不仅关注404状态码,还需处理200、301、302等可能返回404页面的情况
- 随机页面生成:使用随机字符串构造不存在的URL获取404样本
- 容错处理:对网站可能存在的容错机制进行特殊处理
- 无效域名识别:识别整个域名都无效的情况
参考资源
- 《白帽子讲Web扫描》
- hashes.simhash库
- 实际渗透测试经验
通过以上技术实现,可以有效识别和过滤子域名收集结果中的404页面,提高后续渗透测试工作的效率。