网站漏洞验证代码
网站漏洞验证代码
去年秋天,网站我帮朋友看一个刚上线的漏洞电商站。后台登录框输入 ' or 验证1=1 --,页面直接跳进了管理面板。代码他没设任何过滤。网站我当时没说话,漏洞截了张图发过去,验证他回了一串省略号。代码这就是网站漏洞验证——不是搞破坏,是漏洞拿一段无害的代码,证明某个口子确实开着。验证
很多人把“验证”和“利用”混在一起。代码验证是网站你知道门没锁,伸手推一下,漏洞确认它能开。验证利用是你推开门进去搬东西。写验证代码的第一原则:只做最小化的证明,不碰数据,不留痕迹。 比如 SQL 注入,你只需要让页面返回一个数据库版本号,或者让 AND 1=1 和 AND 1=2 的响应产生差异,就足够了。别去 DROP TABLE。
拿一个常见的反射型 XSS 举例。假设搜索参数是 q,URL 是 https://target.com/search?q=test。你不需要写什么复杂的 payload。构造:
https://target.com/search?q=<script>alert(1)</script> 如果页面弹出一个对话框,漏洞就验证完了。但现实里往往弹不出来,因为浏览器有 XSS 过滤器,或者服务端做了转义。这时候别急着下结论说“没漏洞”。看源码,搜索 alert(1) 出现在 HTML 里的哪个位置。如果它出现在 <script> 标签内部,或者某个 onerror 属性里,说明转义不完整。我见过一个站,把 < 转成了 <,但没转 >,结果 <img src=x onerror=alert(1)> 照样执行。
SQL 注入的验证更微妙。盲注场景下,页面不返回错误,也不显示数据。你只能靠布尔条件或者时间延迟来判断。布尔盲注的验证代码长这样:
id=1 AND SUBSTRING((SELECT database()),1,1)='a' 如果页面正常返回,说明数据库名的第一个字母是 a。如果页面空白或报错,就不是。时间盲注更直接:
id=1; IF(SUBSTRING((SELECT database()),1,1)='a',SLEEP(5),0)-- 页面卡了五秒才响应,漏洞就坐实了。这里有个坑——很多 WAF 会拦截 SLEEP 关键字。你可以换成 BENCHMARK(5000000,MD5(1)),或者用 WAITFOR DELAY '0:0:5'(SQL Server)。验证代码要随机应变,不是背模板。
文件上传漏洞的验证最容易被忽略。你上传一个 .php 文件,如果服务器返回“上传成功”,但访问时被解析成文本,说明没漏洞。真正有漏洞的情况是:上传 shell.php.jpg,服务器只检查了扩展名,但 Apache 的 AddHandler 配置把 .jpg 当 PHP 解析。验证代码就是那个文件本身,内容写 <?php echo 'vuln'; ?>。访问后看到 vuln 三个字母,收工。
我自己的习惯是:每验证一个漏洞,都在本地笔记里记下三样东西——请求的原始报文、响应的关键差异、以及一个能复现的最小化 payload。别依赖截图,截图会丢。有一次我回头翻半年前的记录,发现当时验证的一个 SSRF 漏洞,payload 里有个参数名拼错了,但居然也通了。后来才明白,那个参数根本没被使用,漏洞在另一个参数上。验证代码写错却碰巧成功,这种事不罕见。
最后说一句。验证代码不要留在目标服务器上,不要用 alert(document.cookie) 去偷 cookie,不要用 sqlmap --dump 去拖库。你是在证明“这里有个洞”,不是在证明“我能把整个站端走”。前者叫安全测试,后者叫犯罪。区别就在那几行代码里。