0x00 前言
承接上文,谈谈黑盒扫描器的需要的功能细节和一些设计细节
0x01 资产管控
首先要回答的是什么是资产,这个问题是偶尔在面试的时候会被问到的,其实每个公司的安全部,根据公司规模大小,涉及业务,小组分工和安全建设情况的不通,对资产的理解就不一样,很多时候面试被问到这个问题,感觉会答出多少,就知道跟进过哪些方面的安全,都建设过哪些安全系统,很快就可以看出一个安全人员的安全经历
对黑盒扫描器来说什么是资产
- PoC扫描器
- IP、域名对应的端口服务
- 服务基于的应用组件及版本
- 服务对应安全防御组件
- CGI扫描器
- HTTP服务
- 服务对应的CGI
- Web WAF规则
- 特用扫描器
- 服务资产扫描(包含未录入CMDB,员工自购的机器域名等部署的服务)
- 公共服务账号信息泄漏(如果公司开源包含github开源账号,官方微博账号等的信息泄漏扫描)
- 假冒应用(mobile app在应用商店中的假冒情况、小程序等同类)
下面根据资产来说明一些黑盒扫描器的演进历程
0x02 扫描中资产分布
首先建设服务资产扫描器
资产探测是第一必要的扫描,对公网来说,很多服务是直接不允许对公网暴露的,类似MySQL、Redis发现服务直接告警,内网则是需要确认存在漏洞的,强度不一样
所以仅有一个资产扫描就可以帮助我们抵挡住大部分的外网高风险漏洞
首先我们要明确,实际的资产必须在CMDB中有明确的适时变更,CMDB是惟一的标准,我们通过技术或者运营手段发现的资产首先是为了保证CMDB的正确,及时更新资产,其次才是为了发现漏洞
一般来讲,我们使用subdomain或者一些运营手段发现新资产,实际上,还有比如资产下架却未在CMDB中处理或者信息错误等问题
实际上在资产的监控中有以下措施
- 公司的子域名多为子系统名加上公司域名,subdomain的暴破中需要加上全量子系统名
- 开放端口需要和CMDB中申请记录相同,如申请的HTTP服务不可以放上ftp服务
- nmap有些服务识别不是很准确,需要自写PoC再访问一遍确认,无法确认的服务需要运营人工确定
- 小程序域名以及一些边角料的域名未必在CMDB中,subdomain暴破不出来,需要人工运营
实际上发现的问题有以下一些问题
- 未授权的端口发现可以追溯到防火墙策略的失效,以此整改和彻查防火墙策略
- 已申请的服务下架后新上服务,端口未回收,两次服务不同容易发现,但是相同比如都是HTTP就不容易发现,需要其他手段辅助
- 域名泛解析问题,泛解析的域名多为测试域名,变动快且因为测试用CMDB不及时更新,加上子系统名的自域名暴破对这种情况发现效果显著
- 员工因为流程问题自掏腰包购买域名服务器导致信息泄漏,多从github扫描获取,此种问题教育处理
不管怎么说,这种问题最后都是因为CMDB和流程导致的错误,以发现的问题督促CMDB和流程改进是更好的方法,实际上写这种扫描器的最终目的还是通过对流程的改进从根本上解决会导致安全问题出现的一些原因,才是闭环
然后建设PoC扫描器
当然PoC扫描器最重要的是PoC,收敛根据服务识别的结果来写PoC,实际上也没必要多写PoC,服务识别效果远比PoC更重要,毕竟很多漏洞可以知道版本,但不一定有可用的PoC
首先是要收敛类DB服务的未授权和弱口令的PoC,包含MySQL、Redis、Mongodb等,还有Solr、InfluxDB、Elasticsearch、RabbitMQ等诸多用HTTP服务提供的服务
然后是各类服务的PoC,类似Struts2、Weblogic,一些反序列化漏洞gadget等
然后讲一些写PoC的经验
我们首先要知道,类vulhub等环境中的PoC是不一定有用的,很多PoC只在特定的实验环境有效,实际上某种实验环境不可能复现,没必要发的PoC其实不需要加入
然后内部网络的网络环境复杂,我们多用DNS等方式发现的问题,因为机器在不同网络环境中可能会被隔绝外网,所以,写入shell甚至执行一些恶意命令让IDS等告警也是很好的解决方法,在各个网段搭建的dns服务器或者蜜罐确认PoC触发也是一种很好的方式
最后,有一些可以改变执行内容的PoC,我们要定期修改一下,比如命令执行,一段时间执行可以被检测出反弹shell的命令,一段时间通过DNSlog等检测,一段时间通过在/tmp
下写入文件,配合HIDS检测,偶尔会多处一点发现
实际上我们增加的这些手法未必能多发现几个,甚至忙了很久只多了一两个,但对增加扫描器的自信心很有帮助
此外,PoC扫描器还有很大的一个帮助,是为我们检验内网一些安全策略的有效性,我们收集的资产中也有服务对应的防御组件
- IP、域名对应的端口服务
- 服务基于的应用组件及版本
- 服务对应安全防御组件
比如弱口令在我们暴破的时候HIDS是否告警,结合HIDS的告警,不管PoC是否能检测漏洞,都能检测HIDS的有效性,流量检测等其他一些安全防护的检测也是一样,也是我一开始在PoC扫描器的资产中加入服务对应安全防御组件的原因
之后CGI扫描器
CGI扫描器比起上面这两者,如果要自研,会更难,原因自然是CGI和业务的关联更加紧密,且存在的通用漏洞类型更多,规则更加复杂
最开始,难的是目标划定和资产收集
- 我们如何确定HTTP服务,比如同一个端口,因为nginx的反代,可以在不同路径下有不同的服务
- 如何收集CGI,来源可以有WAF、流量检测和人工,但是CGI的登录态的时效性、一些时间戳、流水号参数的检查、CSRF Token等都容易让CGI失效
- 一些服务对成功率有要求,对脏数据不能容忍,尤其金融业务交易、开户等,如何让扫描和业务融洽
我公司的体量不算巨大,对外的服务大概400个HTTP服务,加上负载均衡,900多个端口,内网HTTP服务不让对CGI扫描
实际上对于这种体量,还是容易人工覆盖住的
CGI来源不用WAF、流量检测等,因为渗透做不到的服务,类似后门等就要让其他纵深防御处理,我们的目标其实是让CGI扫描器尽可能接近渗透的结果,而爬虫等搜索不到等CGI,用WAF等容易插入脏数据
我们仍然使用渗透的方式收集CGI,400个HTTP服务,每年要进行4轮全量渗透,对于公司内部人员使用系统需要暴露在公网的,确定权限鉴定没有问题,其实CGI不需要覆盖,至少当前还不需要,这样就能排掉大半的服务
因为本身就要周期渗透,人力的损耗就不大,我们通过渗透时候burp将流量导到统一收集的代理接口,就算是获取了流量,然后对每个服务进行渗透的渗透人员过滤好不能扫的影响业务的接口,提供对这个服务的权限获取脚本,包括如何获取登录态绕过CSRF Token等,时间戳流水号等能模拟则提供,不能则算了,放到扫描规则中处理
我们最开始说CGI扫描器的资产有3个
- HTTP服务(如果有复杂的情况,人工渗透运营统计)
- 服务对应的CGI(周期性渗透的时候收集)
- Web WAF规则(WAF是根据公司网络划分的,不同的WAF品牌在不同环境中,根据CMDB划分)
这里还有一个资产的Web WAF的规则,这里实际上有两个点
- Web WAF是否覆盖
- Web WAF的规则是否完整
实际运营中,我们的资产总是有很多服务没有覆盖Web WAF,然后覆盖了WAF了会因为插件没有对齐导致部分规则不生效,所以CGI扫描也要提供对WAF有效性的检测,所以Web WAF的资产也很重要
特用扫描器补齐
- 服务资产扫描(包含未录入CMDB,员工自购的机器域名等部署的服务)
- 公共服务账号信息泄漏(如果公司开源包含github开源账号,官方微博账号等的信息泄漏扫描)
- 假冒应用(mobile app在应用商店中的假冒情况、小程序等同类)
这些其实看名字就可以明白了,根据公司的具体情况进行扫描器编写即可
0x03 一些实现细节
资产和扫描任务的关系
首先还是划归我们的资产
- Domain
- IP
- Service
- HTTP
- CGI
资产主要是这几项,我们目标实现单资产+单PoC
的效果
但是以nmap为例,nmap扫描时候如果喂了一堆资产,就是用1-2-4-8-...-64
这样的个数为1组,进行扫描,一般来讲扫描的组内的个数越多,全部扫描完花的时间越少,所以我们不能用单资产+单PoC
,而只能多资产+单PoC
随之而来的,如果我们对IP这个资产按网段需要在扫描前做不同的处理prehandle
,以及扫描完成后需要通知SIEM等回调操作callback
,明显,单资产+单PoC
的原则如果因为某些像如上原因变成多资产+单PoC
,需要做的适配就不一样,也就是prehandle
和callback
需要特殊适配是十分烦人的事情,所以我们要分割这个过程
回顾一下我们常用的扫描任务,对资产适配以后,我们大概有这些任务
- 单CGI和单PoC,PoC对应的几十种Web通用漏洞,包含大量PoC(大量)
- 单服务(
ip:port
)和单PoC,含几十到上百中PoC(大量) - 单域名和单PoC,少数特殊需要只能通过域名(包含上面两种PoC)
- 单HTTP入口和单PoC,一些不需要PoC但和业务入口路径有关但PoC(少量)
- 单IP和单PoC,资产识别PoC扫描(极少)
- 多IP和单PoC,比如nmap(极少)
- 多CGI和单PoC,比如有上下文关系的扫描(极少)
我们基本上,IP,Domain,HTTP,CGI,Service五种主要资产,一般都是单资产对应单PoC,prehandle
和callback
相同,少数任务特殊,prehandle
和callback
不同
因此设计上,用celery做这样的处理
class BaseHandleTask(celery.Task, metaclass=abc.ABCMeta):
name = 'master_base'
@abc.abstractmethod
def get_target_list(self, target_option):
pass
@abc.abstractmethod
def get_plugin_list(self, plugin_option):
pass
def run(self, target_option, plugin_option):
target_list = self.get_target_list(target_option)
plugin_list = self.get_plugin_list(plugin_option)
tasks = []
for plugin in plugin_list:
for target in target_list:
tasks.append(handle.s(target, plugin, self.name))
chord(tasks)(self.get_success_callback().s().on_error(self.get_error_callback().s()))
@abc.abstractmethod
def get_success_callback(self):
pass
@abc.abstractmethod
def get_error_callback(self):
pass
这里将资产列表和PoC列表获取作为prehandle
分离,并分离任务成功和失败的callback
大部分的任务我们只需要写PoC,少数任务继承这个base类,做prehandle
和callback
的处理,这样结耦比之前脚本拉CMDB资产扫描的方式少了很多改代码的步骤
比如redis未授权PoC
import socket
def handle(target, option):
host = target.get('ip')
port = int(target.get('port'))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.settimeout(3)
s.connect((host, port))
s.send(b'INFO\r\n')
if b'redis_version' in s.recv(1024):
return True
except Exception as e:
return str(e)
finally:
s.close()
PoC写的简单点,不依赖任何框架写到类,只用target和option两个参数,方便别人看懂,或者把PoC迁移或者改写到他自己喜欢的框架中
减少多余扫描
sqlmap有一个响应相似度识别技术
实际上我们发送大量PoC,尤其是CGI的PoC都是无用的,因为确实没有漏洞,但是通用Web的Payload特别多,业务也会很受困扰
如果我们扫描了一次,业务一个月变更一次,实际上这个月扫描都是无意义的扫描
一个比较简单的改进这个方法就是对响应相似度进行识别,比如定一个0.98一下的相似度才扫描,实际上可以减少接近一半的CGI扫描
我们继续改进一下,比如json返回用户评论,用户评论每天增多,相似度变低,但是接口没变化,我们做一个适配,json格式识别key是否变化,然后json格式的相似度减少到0.6一下才扫描,又可以减少一大批无意义的扫描
其实这样扫描速度也快,对业务影响也少了
还有一些减少扫描,比如有些页面其实收集以后重放会返回错误,其实也没有办法模拟登录,都是无效扫描,其实都可以去掉,检测重放返回值是不是错误页面,尤其是公司的统一错误页面,也可以减少很多无意义扫描
漏报误报的发现
漏报
一者,我们在工作过程中,有很多乙方不断推销扫描器产品,二是比如上篇中我谈到历史上过渡的建设,这些都留着,时不时扫一扫,就可以发现不少问题,比如gif文件的Content-Type
错误会导致当脚本执行等问题,都是burp发现的我们的漏报,对增加发现漏报很有帮助
二者,全年众测,上报一些问题分析发现漏报
三者,自己渗透的时候发现
漏报其实比较难处理,很多问题我们也没有解决,尤其src上报的越权,没有好的自动化方法,但是留有完整日志对排查总归是好的
误报
比如json格式的API,用ajax的API不会造成反射型XSS,因此只需要检测DOM型XSS,用模拟浏览器来测试DOM型XSS比较好,用动态爬虫爬取CGI的时候,记录下API对应的页面,这个可以减少很多类似burp对XSS的误报
这个其实就比较好办的,扫描器发现漏洞在我们这里得人工确认才让业务修改,这个过程要认真,有些业务不懂漏洞,也不学习,你说什么就是什么,不要让别人做多余的事情
0x04 总结
说一下实践中的一些改进和问题
- 误报漏报
- 点击劫持,不仅检查
X-Frame-Option
,而且检查CSP和js不可绕过的标准代码 - CSRF,检查Token有效性,参数名过滤黑白名单,多因素验证排除
- XSS,Chrome Headless的DOM XSS和存储型XSS检测
- XXE,SSRF,反序列化漏洞内部DNSlog
- 页面相似度算法增加页面变化提醒,改进验证码暴破等问题
- 点击劫持,不仅检查
- 爬虫效果
- 动态爬虫增加身份证、测试商户信息等爬取CGI更多
- 白名单去除机制,页面相似度变化则白名单去除
- 应用的CSRF Token和登录态定制化
- 性能
- 页面相似度减少扫描次数
- json页面相似度算法改进减少扫描次数
- 部分金融业务返回码和流水号定制,减少开户、交易等问题的业务稳定性检查
- 不足
- 小程序等无法提取CGI和登录态
- 图片大小DoS等很多特殊漏洞没有处理
- 其他尝试(效果不好)
- 高斯分布测试各种漏洞类型,效果没有什么特殊
- RCE漏洞用时间函数的高斯分布,不如DNSLog效果好
time if [ $(whoami | cut -c 1 == r)]; then sleep 5; fi
这种