做 Web 安全这一行手上没有趁手的扫描器就像拿着手电筒找水管漏水——不是找不到是效率太低。前阵子团队做了一次内部系统的安全基线检查需要在服务器资源有限的条件下对十几个测试环境逐个做漏洞探测和配置核查。试过的几款工具要么规则库没法按需裁剪要么报告生成出来还得人工二次整理总之就是各种不对味。后来用一个开源的 Web 安全扫描框架也就是这篇要说的 Lonkero为了叙事方便我给这个模拟项目起的代称把“装工具—配规则—跑扫描—出报告”整个流程完整跑通了一遍。这篇文章就是我从零安装到实战的全部记录重点不只是命令还包括每一步为什么这么做。如果你是需要做自建站点安全自查的开发者或者刚好接手了某个处于测试阶段的业务系统想快速摸清它有没有明显的 Web 漏洞这篇文章可以让你少走很多弯路。文章里的操作我都按实际执行时的样子写出来了你照着做就能复现哪怕之前没接触过扫描器也能顺利跑起来。1. 选型分析Web 安全扫描器那么多为什么最后用了 Lonkero1.1 扫描器到底是怎么工作的很多人第一次接触 Web 安全扫描器会觉得这玩意很高深其实原理拆开看并不复杂。一台扫描器本质上干三件事抓取目标站点的链接范围构造并发送带有试探性质的请求然后根据响应特征判断目标是否存在安全缺陷。把这个流程类比成服装质检就很好理解。扫描器先派出一只“爬虫”把站点上能访问到的页面、接口、参数都捞一遍相当于把货架上的衣服全部拿下来铺开然后针对每个有可能被攻击的入口批量发送预设好的测试用例这就相当于挨件检查线头、拉链、纽扣有没有问题最后把所有疑点整理成报告相当于质检员给你列了一张清单上面写着“这里可能有跳线那里扣子容易崩开”。所以扫描器并不是真的“攻击”目标而是在安全可控的范围内做验证式探测。Lonkero 在我这边的定位是一个偏主动能力的扫描框架。它既支持以爬虫为先导的主动扫描也支持配合浏览器流量转发的被动审计模式。主动模式能覆盖更多入口适合在受控环境中做全面体检被动模式噪音更小适合先低调地摸清底细再决定要不要上强度。两种模式结合使用比单用一种要务实得多。1.2 和其他方案的对比优势到底在哪我简单列过一张对比表把市面上常见的几类扫描方案跟 Lonkero 放在一起比过这里分享出来。对比维度商业扫描器传统开源扫描工具Lonkero模拟项目规则库更新厂商统一维护更新较及时依赖社区贡献更新频率参差模块化规则包可自行裁剪部署方式多数需要云端账号或独立硬件本地部署本地部署离线可跑报告形式报告精美但导出格式有限一般是 HTML/文本支持 HTML/JSON/Markdown可对接平台扩展性插件体系较封闭脚本扩展但需要从头开发提供规则模板和插件接口成本费用较高免费但维护成本需自己扛免费学习成本适中误报率相对较低偏高中等需人工确认我并不是说商业扫描器不好。在大型企业里商业产品提供的统一管理、集中审计、合规报表确实很省事。但像我们这次的需求场景条件很具体测试环境在内网不能在扫描过程中依赖任何外部服务规则库要能针对项目现场情况做裁剪报告要能自动化对接内部存档最好还能把原始 JSON 留下来做二次分析。这几条筛下来很多商业产品和传统开源工具就不太合适了。Lonkero 恰好踩在这些需求点上。它的核心规则包覆盖了注入、跨站脚本、命令执行、文件读取、敏感信息泄露等常见类型基本对应行业里公认的基础风险清单又因为规则本身就是模块化的遇到特殊场景可以直接调整匹配条件不用为了一个小需求去改扫描器的主逻辑。再加上它能完全离线跑这一点在隔离网络里简直就是救命稻草。1.3 什么人适合用它我自己的感受是这工具不是只给专门做安全的工程师准备的。个人开发者可以拿它来快速自查自己的个人站点尤其是那些部署了开源建站程序、平时没怎么管过安全配置的小项目扫一遍就能发现很多之前完全没注意到的问题。小型团队的用处更大。团队里没有专职安全人员的话可以在发布前用扫描器跑一轮快速基线把明显的高危项先拦住。这个工具报告结构还算清晰不熟悉安全的人看结论也能大致明白哪些该优先处理。至于专业安全测试人员可以把 Lonkero 当前置筛查工具来用。扫描结果能帮你在人工测试之前圈定重点方向节约真正花在深挖上的时间。当然扫描器只是工具最终判断它报出来的东西是不是真漏洞、危害多大、怎么修复仍然需要人来完成。这一点后面我会专门展开讲。2. 安装部署实测从零到能跑的完整流程2.1 安装前的环境准备我这边用的是一台用于测试环境的低配云主机操作系统是 Ubuntu 22.04配置大概 2 核 4G 内存。这个配置跑单目标的扫描任务完全够用如果你要同时扫十几个目标建议至少把内存加到 8G不然任务排队时内存容易吃紧。Lonkero 本身需要几个外部组件。运行环境要求 Python 3.9 或更高版本任务调度依赖 Redis数据存储默认用 SQLite也可以切换成 PostgreSQL。Redis 主要承担扫描任务的排队和调度因为扫描不是单线程能搞定的事——多个目标、多组规则并发执行时没有消息队列很容易把机器资源打满而且任务中途断了也没法接续。SQLite 适合小规模使用读写简单不需要额外维护等到任务量大、需要多人同时访问结果的时候再迁移到 PostgreSQL 比较稳妥。先把基础依赖装上sudo apt update sudo apt install -y python3-pip python3-venv redis-server sqlite3 git这里有个容易被忽略的步骤别忘了确认 Redis 服务已经启动。安装完成后跑一下systemctl status redis-server看到 activerunning再继续。如果是在容器里部署没有 systemd 的话就用redis-server --daemonize yes把 Redis 作为后台进程拉起来。2.2 获取项目源码并创建独立虚拟环境源码拉下来之后我强烈建议用 Python 虚拟环境做隔离而不是直接把依赖装进系统环境。我自己十次有八次会把系统 Python 环境搞乱原因都是图省事直接 pip install。用虚拟环境的好处是所有依赖都在这一个沙盒里微信万一装坏了删掉目录重新建一个就行不会影响系统本身。git clone https://example.com/lonkero.git cd lonkero python3 -m venv venv source venv/bin/activate pip install -r requirements.txt依赖安装过程中如果出现网络波动或者某一两个包迟迟装不上可以给 pip 加国内镜像源加速比如pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple镜像源的选择按你所在网络环境来就行目的只是让安装过程更顺。装完之后用pip list | grep -i lonkero看一眼核心依赖是否齐全确认没有遗漏再进入下一步。2.3 初始化数据库并启动 Web 控制台依赖装好后要做数据库初始化。Lonkero 本身带了一套后台管理界面通过它配置扫描目标、查看报告、管理规则包所以需要有账号体系和操作日志初始化迁移这步不能省。python manage.py migrate迁移过程如果输出一堆OK就说明数据库结构已经建好。然后创建一个管理员账号python manage.py createsuperuser按提示输入用户名、邮箱、密码。注意密码要求有大小写字母和数字如果被拒绝了换成强一点的组合就行。接下来启动控制台python manage.py runserver 0.0.0.0:8000服务起来之后浏览器访问http://127.0.0.1:8000就能看到登录页面。如果是在局域网服务器上部署记得在安全组里放行 8000 端口但不要直接暴露到公网不然控制台本身就成了一个攻击面。这个细节很多人会忽略我见过不止一次因为调试方便把控制台裸奔到公网的案例后果很严重的。启动后可以用管理员账号登录后台先做一次冒烟自检。在后台新建一个“自检目标”地址填自己本机的某个测试页面比如http://127.0.0.1:8080/test随便创建一个简单的 HTML 文件让 HTTP 服务托管起来然后跑一条最小规则。如果能顺利出结果说明整套链路已经通了。这一步虽然看起来多余但能帮你区分问题是出在“工具没装好”还是“目标配置不对”后面排查起来少走很多弯路。2.4 安装过程中最容易翻车的几个点我把实际安装过程中踩过、以及在群里看到别人踩过的坑整理成了一张速查表遇到类似报错直接对号入座。现象可能原因处理办法pip 安装到一半报错 ModuleNotFoundError依赖包版本冲突或遗漏重新执行 pip install -r requirements.txt必要时用--upgrade强制更新Redis 连接被拒绝Redis 服务没有真正启动执行redis-cli ping返回 PONG 表示正常数据库迁移失败SQLite 文件权限不对检查当前用户是否对项目目录有写权限用chmod -R urw授权8000 端口被占用有其他服务占用了端口换成其他端口python manage.py runserver 0.0.0.0:8081后台界面能进但扫描任务一直排队Redis 任务队列没被消费检查 worker 进程执行python manage.py worker启动消费注意不要把整个项目丢在 root 用户的 home 目录下运行也别拿 root 直接跑 Web 控制台。我用普通用户跑权限上也更可控。3. 核心功能与关键参数配置3.1 目标配置开始扫描前你要想清楚的事工具装好之后第一件要面对的事就是告诉它“扫什么”。这个过程比想象中需要多花点心思。你可以在控制台里手动填目标地址也可以从文件批量导入目标列表或者把其他工具的抓包导出文件转成目标列表。但我更想聊的是怎么界定扫描范围。先说说地址本身。目标地址建议带具体的协议和路径前缀比如http://192.168.1.10:8080/app/。为什么因为一个站点往往同时存在多个业务模块比如后台管理系统、用户前端、接口网关。如果你只填一个根域名扫描器会把所有能爬到的路径全扫一遍耗时太长还会产出大量跟本次排查无关的告警。把路径精确到模块级别让扫描集中在真正关心的业务范围内效率和准确性都会高很多。然后是认证问题。很多站点把核心功能藏在登录后比如订单查询、个人信息修改、后台管理这些功能恰恰是最容易被攻击的地方。如果扫描器不带会话它只会看到游客能看到的页面等于只做了半个扫描。我习惯先把测试账号登录后的会话信息保存下来在目标配置里指定“使用已获取的会话”然后粘贴进去。有些接口支持 HTTP 基本认证就直接填账号密码。还有一类系统需要先调用一个登录接口换取 tokenLonkero 支持在扫描前执行一次预请求把返回的 token 提取出来拼到后续请求头里这个功能对前后端分离的项目特别实用。3.2 规则包怎么选别一次全上Lonkero 的规则包分得很细常见的有以下几类SQL 注入检测规则跨站脚本XSS检测规则命令注入检测规则路径遍历与文件读取检测规则文件上传与包含检测规则敏感数据泄露检测规则不安全配置HTTP 头缺失、弱加密算法等检测规则第一次使用的人往往会有一个误区把规则全选上觉得“扫得越全面越好”。实际上全选意味着扫描时间翻倍、误报翻倍而且很多规则之间会有重叠会给报告分析带来很大干扰。我更推荐先根据目标类型做筛选。如果是 PHP 写的传统业务系统重点看 SQL 注入、文件包含、命令注入这几类。如果是前后端分离的 Web 应用SQL 注入还是要保留但 XSS 规则和接口鉴权相关的检查要更细致。如果这次就是一次安全基线核查那再加上不安全配置和敏感数据泄露的规则。自定义规则这块也想提一下。规则本质上是一个匹配器定义了“往参数里放什么内容看到什么响应就算命中”。比如你想探测某个接口是否对异常输入做了参数长度限制可以写一条规则向目标参数发送超长字符串如果响应状态码变成了 500 或者返回了堆栈信息就标记为异常。这种自定义规则没有多难写但能让扫描器更贴近你的业务场景。3.3 扫描速率与资源限制慢才是快扫描速度参数是我最想强调的一环。很多人第一次跑扫描看着控制台上的并发数很兴奋直接把并发拉满结果目标扛不住不仅扫描结果失真还把目标服务搞到宕机。这件事在测试环境发生还好万一手滑点在生产环境上画面不敢想。我常用的几个参数配置如下参数默认值建议初始值理由最大并发任务数101~2并发太高会撑爆目标服务也让结果更难分析单请求超时5 秒10 秒目标响应慢时容易产生大量误报超时给长一点更稳每秒请求数上限无限制10 次以内Web 扫描不是压测慢速能有效降低误报率扫描深度32太深会把大量无关页面纳入扫描范围拿“每秒请求数”举个例子。假设你扫一个没有 CDN 保护的小型业务站点目标服务器也就是个 2 核 4G 的实例。扫描器以 100 个请求每秒的速率打过去对方数据库连接池瞬间被占满首页请求都可能超时。这时候扫描器会把超时当成“服务异常”记录还有可能把正常页面当成异常页面报告里堆满了无用告警。反过来你限制到每秒 10 个请求虽然整体扫描时长拉长了但每个请求都得到了有效的响应扫出来的结论更接近真相。我这里跟大家分享一个原则扫描之前确认这台扫描器所在机器到目标网络的带宽情况量力而行永远不要用扫描器去做压测该干的事。3.4 报告导出与通知配置扫描结果默认在控制台里看也可以用命令导出成 HTML、JSON、Markdown 三种格式。HTML 报告适合给没有技术背景的同事看图表和分级都比较直观JSON 报告适合程序处理可以直接对接内部的问题跟踪系统自动创建工单Markdown 报告适合直接贴到内部文档站。我建议每次扫描完成后把原生 JSON 报告保存起来。原因有两个一是便于做历史对比下次扫描后能自动 diff 出新增的风险项二是当规则库升级导致结果有差异时能够追溯当时的判断依据。只保留 HTML 报告的话这些后续工作都做不了。通知这块Lonkero 支持在扫描结束后触发回调把结果摘要推送到企业微信/钉钉这类 IM 机器人的 Webhook也可以发邮件。配置不算复杂按文档把 Webhook 地址填进去再设置触发条件比如“仅高危以上告警时通知”。集成好之后团队不用天天盯着扫描任务进度跑完自然有人通知。4. 实战演练一次完整的安全扫描全流程4.1 场景描述这次实战的目标是我称之为“某跨平台系统”的测试环境实际是一个模拟电商教学站点部署在内网服务器上地址示意为http://192.168.1.10:8080/。这个环境的作用是验证前端页面与后端接口的联动数据库里灌了一批测试商品和测试用户数据。我们的任务很直接在它上线生产之前用 Lonkero 做一次完整的安全体检重点确认三个问题——能不能被拖库、能不能被拿到管理后台权限、敏感数据会不会泄露。如果是真实的生产系统这种完整扫描必须在低峰期做并且要先经过系统负责人同意。这里我用的是内网测试环境授权边界很明确可以放心跑。4.2 第一步采集会话先拿到登录后的状态这个模拟站点的大部分核心功能都需要登录包括商品查询、订单管理、个人信息中心。如果不带会话扫描Lonkero 只能爬到登录页、注册页和首页漏掉的问题会非常严重。我从测试账号列表里选了一个具有普通用户权限的账号在浏览器里手动登录打开开发者工具从请求头里复制 Cookie。然后在 Lonkero 控制台的目标配置界面选择“使用已有会话”把 Cookie 粘贴进去。这一步对应的实际意义是让扫描器以“登录用户”的身份去访问整个页面。订单列表、个人资料修改这类功能都会在扫描范围内出现“参数带入”的接口后续规则才有机会检测出存储型 XSS、越权访问、SQL 注入这类问题。不登录扫一遍相当于把大门钥匙丢在家里只绕着院子转了一圈。4.3 第二步配置扫描规则与速率我这次选的是“完整体检”策略把所有规则包全部选上因为这是面向生产前的一次全量摸底宁可慢一点也要尽可能把问题找全。但如果是对已经改版后的某个模块做快速回归我反而建议只选变化模块相关的规则跑一次快速基线就够了。速率配置上我把并发任务数设为 2每秒请求数限制在 5 到 8 之间。因为这是内网环境网络带宽不是瓶颈限速是为了不给目标服务造成额外压力。测试机上还跑着数据库和其他辅助服务如果扫描直接把目标打挂了后续的问题复现和验证工作全都得中断。同时我做了路径排除。静态文件目录/static/、/images/和第三方字体库这些内容不需要探测直接排除掉可以省掉大量无意义的请求。4.4 第三步启动扫描实时观察现场情况配置完成后在后台点击启动。这里用命令行的形式更直观lonkero scan --config scan_config.yml启动后终端会持续输出运行日志。日志字段包括当前正在爬取的 URL、已发现的接口数量、每条规则的命中情况、请求失败的数量以及失败原因。我不会只看最后结果中间会盯着日志观察因为这个阶段能发现很多有用的信息。扫到一半的时候日志里有一个请求引起了我的注意。某个商品查询接口的响应时间明显高于其他请求而且日志里出现了两次 500 状态码。正常来说不带攻击参数的普通访问不应该返回 500这往往意味着该接口对某些输入处理不够健壮。我把这个接口的位置记了下来准备在扫描结束后手工验证。我这里多说一句看到 500 不直接等于漏洞但它是值得你去确认的信号。真实的漏洞发现流程里很多问题正是从这些“非预期响应”开始追查的。4.5 第四步报告解析与手工复现扫描跑完我导出了一份 HTML 报告和一份 JSON 报告。报告按风险等级分类统计如下风险等级数量代表问题严重1商品查询接口存在 SQL 注入高危2留言功能存在存储型 XSS管理后台缺少登录失败限制中危3备份文件可访问、目录列表开启、弱密码策略低危若干版本指纹暴露、部分 HTTP 安全头缺失看到“SQL 注入”这一类结果我的第一反应不是马上写修复方案而是先手工复现一遍确认这不是规则包的误报。复现手段很简单用 curl 往可疑参数上丢一个特殊字符观察响应curl -s http://192.168.1.10:8080/shop/product?pid1 | grep -i error\|sql\|exception如果响应里出现了 SQL 语法错误、数据库异常关键词或者底层异常堆栈信息基本可以判定注入存在。如果返回的是一个统一的错误页面没有任何敏感信息泄露那就要打个问号可能只是参数校验写的不好并没有达到“注入可利用”的程度。我这边的情况是响应里直接把 SQL 查询片段带出来了确认是原样拼接导致的注入。与之对应的修复方案并不难底层 SQL 改成参数化查询不信任任何客户端传入的拼串另外把数据库账号的权限降到最低即使遇到注入也拿不到太多数据。存储型 XSS 的复现步骤更直白在留言板提交一段带script标签的测试内容切换到其他用户视角查看页面如果脚本被执行问题就实锤了。修复上需要做输出编码页面渲染时对用户提交的内容转义处理尤其是script、img onerror这类高风险标签建议直接过滤掉。4.6 为什么不能直接相信报告扫描结果里也掺了误报。比如有两条“疑似命令注入”的告警我手工验证后发现目标接口只是把用户输入的参数拼到了日志里并没有进入系统命令触发的只是规则包的关键字匹配。在报告里它们被标记成中危但实际风险可以忽略。这类经验表明扫描器的价值在于“广撒网”它能够用相对低的成本把问题定位到具体位置但最终判断还是要靠人工复核。我一般会在报告末尾追加一栏“人工复核结果”逐条确认后再决定把哪些问题同步给开发团队修复。这个习惯能避免狼来了喊太多次造成团队对安全报告麻木。5. 高频问题排查与避坑笔记5.1 常见问题速查表问题现象可能的诱因解决思路扫描执行一半后突然停止任务队列积压或扫描进程被系统杀掉查看日志定位退出原因重启 worker 进程用--resume续跑同一目标大量请求超时目标本身性能不足或扫描速率太高降低并发数增大请求超时时间必要时让目标扩容或避开业务高峰报告里高危告警占比异常高规则选择不合理或者目标存在大量安全基线问题先按“严重/高危/中危”维度分级处理把误报剔除后重新评估一键导出 PDF 报告失败系统中缺少中文字体或报告组件不兼容检查依赖库版本确认导出环境里的字体包已安装批量导入目标后任务排队缓慢Redis 性能瓶颈或者 worker 数量不足增加 worker 进程数量重启调度服务实际使用中出现频率最高的其实是第二类“请求超时”。很多时候不是目标真的有问题而是你的扫描配置太激进。我见过有同事为了追求扫描效率把并发开到 50结果目标数据库连接池被打爆最后连扫描器本身都连不上目标了。遇到这种情况把并发降下来让目标缓一缓再重新跑一遍问题往往就消失了。5.2 几个容易被忽略的细节第一扫描前务必备份目标数据。即便扫描器的测试用例设计得再温和对某些不健全的接口来说特殊参数还是可能触发数据写入异常甚至把业务数据污染掉。我在模拟站点上遇到过扫描器往商品表里插入了测试数据的情况好在只是测试环境如果是生产环境这就是事故了。所以扫描前对目标数据库做快照是最不亏的保险。第二要关注磁盘空间。扫描报告、原始日志、截图证据都会占用存储。如果扫描几百个 URL报告还好但如果你开了响应快照功能一个目标就能产出几百 MB 的数据。任务开始前用df -h看看磁盘剩余空间别让日志写满磁盘否则连扫描器的数据库都可能损坏。第三在同一台机器上不要同时跑多个全量扫描。虽然 Lonkero 有调度能力但多个任务并发执行会让调度器和目标两边的资源都吃紧尤其是目标之间如果有共用数据库的情况反而会产生大量假告警。我习惯的方式是“一个目标一个任务队列”扫完一个再开下一个看起来慢实际数据和报告质量都要高很多。第四扫描完成后把原始日志保留下来不要只看最终报告。报告中只体现最后结论但判断“这个问题是怎么被发现的”“漏洞长的什么样子”还是要回看原始请求和响应。保留日志还有个好处后续做整改效果复核时可以拿着同一批 payload 重新验证修复是否生效。5.3 我实践下来最受用的几个原则扫描这件事我自己总结下来就几句话。先被动后主动。遇到不熟悉的系统先用被动审计模式收集一段时间的流量搞清楚业务接口的分布和参数结构再有针对性地开主动扫描。这样能大幅减少无用请求也能让主动扫描的精准度上一个台阶。先不带认证扫一次再带认证扫一次。这两次的结果要分开看。不带认证扫出来的问题和登录后扫出来的问题暴露面和利用难度完全不同混在一个报告里会让修复排期变得混乱。扫描器负责广撒网人负责精准捕捞。这个观点我前面反复说过这里的要害是不要拿扫描器报告直接作为漏洞修复的最终依据务必把高风险的条目全部人工验证一遍。验证成本不高但能避免折腾开发团队去修一个根本不存在的漏洞。有条件的话把扫描动作集成到发布流程里。每次发版后在测试环境自动跑一次快速基线把 SQL 注入、XSS、敏感信息泄露这三大类高危项作为红线发现问题直接卡住发布。这件事看起来是增加了一次额外检查实际上会省掉很多上线后出事再去排查的时间。我们团队把这一步做成流水线里的固定环节之后线上环境爆出低级安全问题的概率显著降低开发和运维的焦虑也跟着降下来了。我再分享一个个人习惯。每次扫描跑完后我会把 JSON 报告保存到以日期为名的目录里同时随手写一个一句话摘要记录这次扫描的目标背景、当时的系统版本、主要发现。过两三个月后当需要对比新版本是否引入新的风险时这些记录就是最直接的参考依据。别小看这个习惯我的很多回溯分析都靠它救急。最后说一句心里话。Web 安全扫描器永远只是辅助工具它帮你把“可能有问题的地方”摆到你面前但真正的安全工作大头还是那些枯燥的查阅代码、梳理接口、验证边界、修复加固的细活。用熟 Lonkero 这类工具之后你会发现它最大的价值不是每天帮你找出几十个漏洞而是在你做安全复查的时候少惦记一点“我是不是漏了某个角落”让你能把精力放到更需要判断力和经验的地方去。