黑盒漏洞扫描(三)

前言

甲方扫描器其中一个很重要的功能重点,就是无害化,目的是尽量降低业务影响到可接受程度。

做过甲方扫描器,基本上对于反馈都有所熟悉。

"我们的服务有大量报错,请问和你们有关么"

"我们的接口昨晚请求量飙升,这是扫描器造成的么"

扫描,应该尽量无感知。

无害化,是扫描器不同于SAST/IAST的一个难点(当然IAST有部署上的性能问题,偶尔的OOM、过高的资源占用也是大问题),是生存下去的必须考虑的一个点。扫描要有产出、要有效率,而业务侧更注重安全、有无业务影响,尤为重要,毕竟谁也不想业务一出问题先来问问是不是安全部门的扫描器。

业务影响的大体场景分类,个人还是分成针对web接口扫描和主机端口扫描造成的业务影响。

web接口扫描无害化

2.1 QPS

2.1.1 为什么要控制qps

QPS(Queries-per-second),指扫描器每秒针对业务发出的请求量。

QPS不控制好,很容易随时导致业务反馈,业务经过一番辛苦排查,发现是扫描器,自然会带着情绪进行反馈;更严重者甚至会导致占用过多服务资源,导致影响正常业务(可能升级到事务报告,虽然没收到过)

常见的反馈场景分为几种:

a. 在nginx层的公司级监控中,扫描器发送的请求超过了某个接口设置的QPS阈值

b. 在web框架的监控中,请求QPS超过阈值

c. 业务自行设置的监控中,请求超过阈值

d. 业务接口本身没有超过阈值,但是后端的二次调用或多次调用(RPC或其他http服务)超过了阈值

怎么解决?

2.1.2 聚合方式控制qps的关键点

QPS控制需要确定两个点:

1 聚合方式:通过什么方式把不同的URL聚合到一个key中

为什么需要聚合?我们要控制的是对业务的接口的请求量,而不是我们看到的URL的访问量。

a 同一个path,但是参数不同,大多数情况下还是同一个接口同一个函数在处理;

b 而现在动态参数已经很普遍了,比如百度贴吧的帖子

https://tieba.baidu.com/p/1000000001

最后的十位数字不位于参数,而是位于路径中,后端读取这段路径的值来作为变量,不管数字怎么变都是同一个接口处理。

c 甚至于子域名也可能对应同一个接口

https://bj.meituan.com/meishi/

https://sh.meituan.com/meishi/

长这样多数情况下,不同的城市 北京bj、上海sh、广州gz等,都是对应到同一个美食列表页服务

如果不聚合,针对每个长得一模一样的url设置最低的1的qps,当同时对帖子进行扫描时,即使每个url每秒只发送一个请求,在同一段时间内url数量多时,对这个处理的接口发起的访问量也会变得极大。特别是在业务高峰期(早8点到晚10点业务请求量较大),接口压力本来就挺大,基于流量镜像模式的,接收到的url也很多,再做一次扫描,容易把业务打的叫苦不迭。

所以聚合理论上是将表面不一的url收束在属于它们自己的范围内,当然越接近接口越精准。

2 QPS值:对应的key能使用多少QPS、每秒能发送多少请求

QPS值,取决于这个接口的承接能力、设置报警的阈值。

值设置的高了,容易打爆业务接口;值设置的低了,扫描速率会较慢,流量大时可能消费不完。

最适合的值上限,是业务正常情况下的请求量均值或上限。

有的业务会按照一分钟请求总量来设置告警,一分钟 100-1000,也就对应着 1-17的QPS。平时访问量较低的接口,QPS为1就足以打报警。

2.1.3 不同的实现方式

a 域名聚合

同一个域名或子域名的请求不超过N(5-10)。

一刀切方式,优点是成本低、效果也挺好。

缺点是绝对平等,不管流量大小都使用同一个QPS,流量大时可能扫描不完。

和任务绑定起来适用于扫描任务多但每个任务流量不多的情况,比如多用户多任务的情况。

b 集群聚合

每一个url,根据nginx解析结果,获取url最终归属的业务集群。

结合内部监控数据,获取每个集群实时访问量,计算出每个集群的访问峰值;

使用峰值减去实时访问量(前n分钟),得到空余的可用访问量

缺点:

1 依赖于内部基建的资源

2 同一个集群下的接口,可用的访问量是基于整个集群的。比如A可用300、B可用300、C可用300,集群整体可用900,但A本身承受量只有500。这样就会出现QPS倾斜,访问都打到A,会把A打爆。

c 去重聚合

镜像模式下基本都会有一套去重程序、流量清洗服务,在去重的时候记录下每个key的实时访问量。

用去重的key作为聚合的值,QPS计算的方式和之前一样,计算每个key的峰值,再减去前n分钟(在可控范围内尽可能少)的qps,得到这个key在这一分钟的可用量。

结合路径相似度与页面相似度的去重,去重key接近于接口,效果比较理想。

2.1.4 QPS超限后的限制方式

如果插件最小任务单位已经拆分到请求级别,那么可以将请求任务丢到队列里,根据可用量来读取请求任务运行。

但插件有很多情况需要上下文关联,比如需要第一个请求获取登录凭证token、第二个请求使用该token进行后端RCE等。

这时当扫描规则发送请求时,该请求已经没有可用QPS了,怎么做限制

方法1

直接sleep,等待可用了再发送,但会导致任务hang住、占用节点。资源多无所谓。

方法2

超限后扔回重试队列中

但是下次扫描并不从头开始,而是从中断处开始继续扫描

不进行断点重扫,会有部分插件一定扫描不完,比如有的规则扫描时没有限制,1秒10个请求,无法成功;而QPS控制业务边缘归属于引擎,不应该影响规则本身的检测效果

记录每个扫描任务的每个请求hash (url + header + postBody),给插件分类(有无上下文关键);

对于没有上下文的规则,下次任务已经请求过的hash直接跳过;对于有上下文关联的规则,存储每个hash的返回,重试时已经请求过的hash,直接读取上一次的返回。

2.2 业务错误码报错

业务线会监控服务稳定性可用性,最简单的就是404/504等错误码的每分钟占比。

可用性有的会直接影响到业务的KPI与指标。

这里应该收集每一次的反馈,和内部监控平台沟通谈需求,识别到内部扫描时把这部分请求摘掉;如果是单个业务自身做的报错收集,只能靠他们自己去解决这些问题了。

这里注意扫描时要让业务溯源简单,自定义的header / ua / 出口IP等,否则溯源老半天才发现是内部扫描,业务会更生气。

2.3 脏数据

脏数据是一个无法避开不谈的问题。

镜像模式下,只过滤掉header与post,只扫描get,仍然可能会存在脏数据问题。

get理论上应该是做查询,select操作,但是业务想用来做增删改操作也无可厚非。

get中可能存在用户凭证,业务不把token放在cookie中了,而是放在get参数中、平时保存在localstorage中。这种情况带着get参数值去扫描,等于拿着用户的身份去扫描,有个信息增删改操作,就会导致用户脏数据。

再比如,业务写接口,登录界面获取手机验证码,getCode?phone=xxx&type=1,拿到这条流量进行扫描,在对type进行扫描的时候,重复发送给用户验证码,用户还以为账号是被黑了。

又或者,没有增删改等,只是单纯的查询,但因为带着用户信息,频繁访问,被反扒处置了,用户被封禁了。

方法1 清洗与打标

在2.1中,说过接口;在我们有了所有接口数据后,借用其他安全产品的能力(SAST/IAST),给接口打上标签,判断是增删改或者是查;增删改操作就小心跳过,可避免掉大部分脏数据业务影响情况。再设置参数名黑名单,过滤掉形如phone/token/tele等明显带有用户特性的参数名的值。

这种做法相对安全,覆盖率取决于SAST/IAST的能力,但也会导致这些接口的漏报

方法2 爬虫

通过爬虫,第一篇1.2.4,采用自身测试账号抓取的流量,通常脏数据问题会比较少,因为这些请求都是正常用户可以访问到发出的,也是外部扫描器会收集到的。

用户能访问到的接口,造成脏数据,说明外部的用户也可以造成,特别是外部的白帽子/黑客也会进行扫描。并不是不扫描问题就不存在,只是没暴露。

方法3 影子环境

直接将现有的DB环境、服务环境复制一份,通过nginx层转发扫描请求/压测请求到影子环境,风险极低,但成本极大(成本*2)。

或者单纯的复制DB环境,在数据库连接函数中作hook,把扫描请求的数据库链接改为影子库。但是操作起来很麻烦,开发维护成本较大,多层调用最后再到DB,和最初的请求关联起来判断是不是扫描的就很难。

而且除了常规DB mysql/mongo/redis/MQ/kafka等,还有其他的数据库甚至是本地log等,转了一部分但另一些操作没转,业务数据层方面就不一致了,只能通过反馈不断维护,比较麻烦,不太推荐。

方法4 测试环境

第一篇 1.2.6中,测试环境进行扫描。

把扫描作为一个能力开放给业务线,在业务可控的情况下,可以带cookie扫描、也不需要过滤各种参数,QA在明白风险的情况下进行扫描。

甚至可以进行流量打标,让业务自行选择是否对涉及增删改的接口进行扫描。

PS:

有的收购业务一扫系统就出问题,没有统一测试环境,没有统一上线流程可以获取代码进行接口打标,脆弱至到处都是未授权,这种情况无能为力。

2.4 扫描时间段

有的业务允许扫描,但希望扫描的时间段放在半夜,因为半夜业务访问量较低,出了脏数据或者QPS等问题,影响会比白天高峰期时小,到业务 "开门" 也有一定的缓冲时间。

2.5 限制带宽

虽然都是过滤就可以的,但是和静态文件影响扫描性能不同,这个会造成成本问题。

扫描时可能会遇到下载文件的接口,请求一次后,接口会把几十上百兆的文件内容返回给客户端。这QPS一上来,带宽蹭蹭蹭就起飞了。私有云场景可能是和云服务买带宽套餐,可能是阶梯式收费,也可能是按使用量收费。一旦超量,可能就要多花费个几百万,足以发个严重事故了。

所以流量过滤时,也要过滤掉content-length过长的、content-type属于下载类型的。

主机端口扫描无害化

3.1 内网HTTP服务报错

内网中有很多HTTP服务,对内网进行框架漏洞扫描时,可能会引起报错,影响与处理方法同2.2

3.2 指纹匹配过滤不符合端口的数据

内网有很多端口服务,端口服务有自己的报错姿势。

有业务自己写的socket服务,但是没有做数据校验,当接收到不符合格式的数据时,抛异常导致进程中断。

这样的业务,其实也算存在DOS漏洞,可以提交安全工单敦促业务修复。

也存在部分常规业务,打个比方,redis协议扫描mysql导致mysql处理时间过长hang住(可能不是这两个服务,时间长忘记了)。

这种可以通过端口指纹方式避免掉,通过给每个端口打上所属服务/框架的标签,规则设置一级指纹(URL/HOST等数据类型)、二级指纹(URL数据的框架、HOST端口的服务/框架),在任务处过滤掉不匹配不对应的,可避免数据不匹配导致的服务报错或者挂掉

3.3 业务方给定指纹

内网可能有RPC框架,接收到不符合端口的数据会报错,但是框架层面无法作数据校验、来直接过滤掉不符合的数据,因为使用方需要这些报错来判断服务是否有异常。也无法在框架层面直接判断来源IP和集群过滤掉扫描请求,这不符合框架的设计。

可以由框架提供探测指纹,端口连接后返回特定数据,标识本身服务。

3.4 限制服务同一时间的链接数

内网扫描出现的比较多的情况,是一个IP端口的服务被链接过多,导致服务异常。

一个要做的是限制同一个 IP+端口 单位的链接数,同一时间只能链接N个。

另一个,可能存在规则socket.connect后,没有close,即使任务关闭,但远程连接方没有收到关闭请求,还在等待接收数据。即使本身已经限制了链接数,还是会打爆。所以规则检测,需要判断connect后是否有close。

PS:

当然还可能会有层出不穷的报错,比如扫描弱口令 比如ssh/mysql/mssql/redis时,引起的大量报错信息与不停告警。遇到过业务方写个了mssql代理,扫描时导致DBA mssql各种报错,但是DBA不知道是哪个机器发送的请求,业务方也不知道自己的代理启动在哪里,只知道有扫描器弱口令规则的paylaod,也无法加白名单。最后把IP写进username里才定位出来。

也可能有内部业务与其他公司有服务对接,在自家内网开了个代理服务器,可映射到其他内网。扫描时检测到各种端口,其实是其他公司的内网各IP与端口。这种情况十分危险,有反馈最好先加白过滤。代理服务器可能链接到其他传统的、脆弱老旧内网,一扫过去可能就挂了,事故报告就来了。

规则无害化

4.1 场景

规则无害化由上述方式并不能很好控制。

有的友商扫描SMB (MS17-010)等漏洞的时候,没有把控好规则的危害程度...直接上了把业务打蓝屏的规则;

log4J常规payload,链接到dns,会导致log4J等待、hang住,qps过高可能会打挂服务。

4.2 靶场验证

规则扫描线上服务之前,需要设置靶场链接,经过验证后才能上线,不仅是验证规则是否有效,也是验证规则是否会对环境造成影响

4.3 插件审核机制

自动化检测一些常规规范,比如调用socket.connect后是否有close()等

对个人而言,代码得或多或少符合PEP8规范吧,杂乱无章的缩进、不明所以的换行、奇怪的dict有换行没换行交替,实在是看了有些尴尬

再是人工审核,审核时需要审核员(可以是固定资深人员、也可以是自选另外一个同事),迭代更新的规则展示更新的部分。审核主要是依靠经验判断有无不可控的风险。

相关推荐
运维行者_1 小时前
企业无线网络监控的挑战与智能化演进趋势
大数据·运维·服务器·网络·数据库
国强_dev2 小时前
技术探讨:使用 stunnel 加密转发数据库连接时,如何获取客户端真实 IP?
数据库·网络协议·tcp/ip
@insist1232 小时前
系统规划与管理师-信息系统规划核心工作要点解析
数据库·软考·系统规划与管理师·软件水平考试·系统规划与管理工程师
超级数据查看器2 小时前
超级数据查看器 v10.0 发布
java·大数据·数据库·sqlite·安卓
数安3000天2 小时前
增量数据如何自动分类分级,避免目录“过期“?
大数据·数据库
桌面运维家3 小时前
如何用半缓存云桌面将服务器硬盘容量扩展至本地终端?
运维·服务器·缓存
南墙上的石头3 小时前
麒麟 V10 重装人大金仓 V8R6 踩坑实录(含 MySQL 兼容模式)
数据库·mysql
画中有画4 小时前
论向量数据库在项目中的应用
数据库
spider_xcxc5 小时前
Redis 数据库高质量实践指南(一)
运维·数据库·redis·oracle·云计算
l1t5 小时前
在linux和windows中解决duckdb 1.6dev版本输出执行计划报错问题
linux·运维·数据库·windows·duckdb