漏洞技巧
漏洞技巧
2017年夏天,我蹲在出租屋的漏洞技巧折叠桌前,盯着一个登录框发呆。漏洞技巧目标网站用的漏洞技巧是某开源CMS,版本号明晃晃挂在页脚。漏洞技巧我试了默认口令、漏洞技巧试了注入、漏洞技巧试了上传,漏洞技巧全被拦。漏洞技巧最后翻到它一个不起眼的漏洞技巧“找回密码”接口,参数里有个user_id,漏洞技巧改成别人的漏洞技巧数字,密码重置链接直接发到了我邮箱。漏洞技巧整个过程没用一个0day,漏洞技巧没写一行exp。漏洞技巧那是我第一次意识到,漏洞利用的胜负手,往往不在漏洞本身,而在你对“正常功能”的理解有多深。
很多人把漏洞挖掘当成找宝藏,拿着扫描器到处跑,等一个红色警告。扫描器能告诉你哪里可能有洞,但它永远不知道这个洞能不能用、怎么用、用了之后会发生什么。真正的技巧藏在业务逻辑的缝隙里。比如一个电商网站,优惠券只能领一次,但如果你在领券请求发出后、服务器返回前,把coupon_id参数改成另一个,有时候能同时领两张。这不是代码漏洞,是状态机没锁死。扫描器不会报这个,因为它不“异常”。
我见过最漂亮的漏洞利用,是一个支付逻辑的绕过。目标平台允许用户充值,充值金额是整数,最小1元。有人发现,在提交订单时把金额改成0.01,前端会拦截,但直接改HTTP包,后端居然接受。更妙的是,支付网关那边只校验总额是否匹配,不校验单笔金额下限。于是充1分钱,到账1元。这个洞存在了三个月,直到有人充了十万次。修复方式也简单:加一行if (amount < 1) reject。但发现它的人,靠的不是fuzzing,是盯着“1元”这个数字想:为什么是1?能不能是0.99?
另一个我反复用的技巧,是参数污染。这词听着玄,其实就是同一个参数名传两次。比如?id=1&id=2。不同语言、不同框架对这种情况的处理不一样。PHP取最后一个,ASP取第一个,Node的querystring会变成数组。有一次我测一个越权接口,?user_id=123&user_id=456,后端校验用了第一个值,业务逻辑用了第二个值。于是我用123的身份,读了456的数据。这种洞,扫描器基本瞎。你得手动试,试不同的组合,试%00截断,试大小写混写,试URL编码两次。
“漏洞不是被找到的,是被构造出来的。”——这话我忘了谁说的,但每次挖到逻辑洞都会想起来。
还有一类技巧,我管它叫“时间差”。比如密码重置令牌,理论上应该一次性使用,但很多系统在用户提交新密码前不失效旧令牌。你申请重置,拿到链接,别点。再申请一次,拿到第二个链接。然后用第一个链接改密码,第二个链接居然还能用。这中间的时间窗口,就是你的机会。有些系统更懒,令牌根本不过期。我见过一个,2015年生成的令牌,2018年还能用。这种洞不需要任何技术,只需要耐心和一点恶意。
写这些不是教人使坏。我自己做安全测试,拿授权,写报告。但技巧本身是中性的。你理解了这些,才能在设计系统时避开它们。比如状态机要加锁,参数要严格解析,令牌要一次性且带TTL。这些事,扫描器不会替你干。你得自己盯着代码,盯着请求,盯着那些“看起来正常”的地方。漏洞往往就藏在你觉得“这还用测?”的瞬间。
最后说个小事。有次我测一个后台,登录后有个“导出CSV”按钮。点了,下载一个文件。我抓包看请求,发现它把查询条件全放在URL里,包括table_name。改成users,下载了用户表。改成admin_logs,下载了管理员操作记录。这个洞的利用,只花了十秒。但发现它,花了我两个小时翻JS源码。技巧这东西,说到底就是:比别人多看一眼,多想一步。没了。
(责任编辑:休闲)













