凌晨两点,云端一条来自云WAF的洞手告警在钉钉群里弹出来:某业务接口出现大量500响应码,请求参数里夹着union select。工监值班同事看了一眼,测分丢进“误报”文件夹就睡了。云端第二天上午,洞手数据库里三个表的工监数据挂在某论坛上叫卖。事后复盘,测分WAF规则确实拦了标准SQL注入,云端但攻击者用的洞手是分块传输加注释混淆,把union/**/select拆成三个chunk发过去,工监WAF的测分解析引擎没拼回来。
这事说明一个挺尴尬的云端现实:云WAF不是保险箱,它更像一个反应永远慢半拍的洞手保安。厂商规则库更新要时间,工监而攻击者改payload只要几分钟。所以手工监测这件事,在云端环境下反而比过去更重要——不是替代WAF,是补它的盲区。
先搞清楚“云”给漏洞监测加了什么变量
传统IDC里,你抓包、看日志、比对文件哈希,路径是清晰的。上了云之后,流量经过SLB、CDN、WAF、API网关,每一层都可能改写请求。比如CDN会归一化URL编码,WAF会截断超长参数,到源站时你看到的payload已经跟攻击者发的不一样了。手工监测的第一步,是拿到“未被篡改的原始请求”。
我一般会做三件事:在WAF上开全量日志投递到SLS,在SLB上开tcpdump做镜像抓包,在应用层用OpenResty的ngx.req.get_body_data()落一份原始body。三份数据交叉比对,才能还原攻击者真正发了什么。
# 一个简单的分块传输还原脚本片段 def reassemble_chunked(raw): chunks = raw.split(b'\r\n') body = b'' for c in chunks: if c and not c.startswith(b'0'): try: size = int(c, 16) body += chunks[chunks.index(c)+1][:size] except: pass return body 手工监测查什么,不查什么
别去追每一个告警。云上每天几万条WAF日志,人工看是自杀。我的筛选逻辑很粗暴:只看响应码200且请求里带危险字符的。因为500可能是误报,403是被拦了,只有200意味着攻击可能已经穿透到业务逻辑层。
具体看三类东西。一是参数污染,比如id=1&id=2,WAF可能只检查第一个值。二是JSON嵌套里的注入,{ "user":{ "name":"admin'--"}}这种,很多WAF的JSON解析器直接跳过。三是文件上传的content-type伪造,把application/x-php写成image/jpeg,云存储的MIME检测不一定认。
有个案例我印象很深。某电商的优惠券接口,攻击者传了coupon_id=1%00,WAF没拦,后端Java把%00当字符串截断,结果领了一堆本不该领的券。这种漏洞扫描器扫不出来,WAF规则也覆盖不到,只能靠人盯着日志里那些“看起来正常但就是不对劲”的请求。
工具是辅助,判断靠人
我常用的是jq加grep的组合,从SLS拉日志到本地,写个shell脚本过滤。有时候也用Burp的Repeater手动重放,把WAF绕过的payload一个个试。但工具只能帮你缩小范围,真正判断“这个请求是不是攻击”,靠的是对业务的理解。比如一个查询接口突然出现order by 100,正常人不会这么干,那大概率就是在测列数。
云环境还有个坑:多租户。你看到的源IP可能是另一个租户的NAT出口,封IP会误伤。所以手工监测的结论不能直接给WAF下封禁策略,得结合session、设备指纹、请求频率一起看。我一般会先加一条临时规则观察24小时,确认是恶意流量再升级处置。
说到底,云端web漏洞手工监测是个脏活累活。没有一键解决方案,也没有银弹。它要求你既懂HTTP协议细节,又熟悉云产品的流量路径,还得有耐心从海量日志里捞针。但正是这种“笨功夫”,往往能在WAF漏掉的地方,把攻击者挡在数据泄露之前。