romano-pavan/sitecheck

GitHub: romano-pavan/sitecheck

一个零依赖的在线商店合法性启发式检查工具,通过分离欺诈信号与技术卫生状况并纳入正面信任证据,为消费者提供可解释的风险评分。

Stars: 0 | Forks: 0

# sitecheck ![status](https://img.shields.io/badge/status-work%20in%20progress-yellow) ![python](https://img.shields.io/badge/python-3.8%2B-blue) ![deps](https://img.shields.io/badge/dependencies-none-green) ![license](https://img.shields.io/badge/license-MIT-lightgrey) ![AI](https://img.shields.io/badge/code-AI--generated-8a2be2) **针对在线商店的启发式合法性检查工具。** 它旨在回答一个实际问题:*在这个网站下单安全吗?* 将其指向一个域名,它会检查你本需手动核验的内容:域名年龄、TLS、DNS、商户身份、支付条款、退货政策和信誉反馈。它会在 30 到 90 秒内以通俗易懂的语言返回一个评分结论。

Telegram bot report

核心扫描器具有**零运行时依赖**。仅使用 Python 3.8+ 标准库。 ## 为什么会有这个项目 一家保健品商店开始出现在我的搜索结果中,价格比所有竞争对手都低 40% 左右。感觉不太对劲,但仅凭“感觉不对”并不是理由。我需要证据,而且我需要在输入信用卡号*之前*而不是之后获得证据。 手动完成这些检查需要在 8 个浏览器标签页之间花费 15 分钟:WHOIS、版本说明、退货页面、Trustpilot、证书和支付选项。而本工具只需一条命令,在手机上不到一分钟就能完成。 它是一个分诊工具,而非神谕。它告诉你该看哪里,而不是告诉你该相信什么。 ## 检查内容 | 领域 | 检查项 | |---|---| | **域名** | 通过 RDAP 查询年龄,然后是 `whois`,接着是 Wayback Machine 的首次快照(三种后备方案,因为像 `.hr` 这样的 ccTLD 注册局会隐藏注册数据)、注册时长、所有权变更 | | **DNS** | A/AAAA 解析、MX、SPF、DMARC | | **TLS** | 证书有效性、颁发者、年龄、过期时间、协议版本 | | **HTTP** | HTTPS 重定向、安全标头、跨域重定向 | | **身份** | 使用 ISO 7064 MOD 11,10 校验和验证克罗地亚 OIB;通过官方 **VIES** 注册表验证欧盟 VAT(免费,无需 API key);实体地址;电话;使用自有域名的电子邮件 | | **商业** | 支付方式、快递、配送成本、免邮门槛、货到付款费用、配送时间窗口、退货政策。支持检测**克罗地亚语和英语**,支持 EUR/GBP/USD | | **危险信号** | 仅限银行电汇支付、加密货币、人为制造的紧迫感、虚高的锚定折扣、作为保健品出售的未经批准的物质(SARMs、prohormones、research chemicals) | | **信誉** | URLhaus 恶意软件数据源、urlscan.io、Google Safe Browsing(可选,需要 key) | 一次典型的扫描会针对网站的 7 到 9 个页面运行大约 30 项检查。

Findings detail

## 评分机制的工作原理 大多数网站检查器会将一堆信号缩减为一个数字。那个数字通常是错误的,更糟糕的是,它无法被证伪。本工具做出了三个重要的区分。

HTML report

### 1. 欺诈信号不等于技术卫生状况 缺少 HSTS 标头是一种配置选择。缺少 DMARC 记录也是。这两者都不是欺诈的证据。许多诚实的本地商店两者皆无,而托管平台上的许多诈骗店面却拥有完美的 TLS 并在每个标头扫描器中获得 A+ 评级。 因此,卫生状况的检查结果会单独报告,并且**计为零风险分**。只有那些确实与欺诈相关的信号(匿名商户、三周大的域名、仅限电汇)才会影响得分。

Hygiene findings reported separately with no points

截图中的所有内容都被标记为 `hygiene`,对风险得分没有任何贡献。它是信息,而不是指控。 ### 2. 正面证据同样重要 商店可以**赚取**结论,而不仅仅是扣分。系统会追踪八种信任信号: - 域名运营 3 年以上 - 已识别商户(经过验证的 OIB 或欧盟 VAT 号码) - 存在实体地址 - 存在联系电话 - 使用商店自有域名的电子邮件 - 明确说明的支付方式 - 完善的配送条款(指定的快递、价格、时间范围) - 存在退货政策 **拥有 5 个以上的信任信号且无欺诈信号即判定为 `VERIFIED`**,无论卫生状况的细节如何。 一个只计算负面因素的模型永远无法为诚实的商店洗白,这使其变得毫无用处。一个总是“狼来了”的工具会被忽视,而被忽视的工具保护不了任何人。 完善的配送条款本身就是证据。诈骗店面不会有承运商合同、智能包裹柜集成,以及在购物车中计算出的 1 欧元货到付款费用。这些都是没有人会为一个打算存活三周的域名去构建的基础设施。 ### 3. 未能确认不等于欺诈的证据 这是本代码库中最深刻的教训。VIES 确认 VAT 号码是强有力的证据。VIES *未能确认* VAT 号码不能作为任何证据。关于这个 bug 是如何产生的,请参阅[设计说明](#design-notes)。 ### 评分区间 风险得分范围从 0 到 100(设有上限),具有公开的评分区间: ``` 0–15 LOW 16–35 MODERATE 36–60 HIGH 61–100 CRITICAL ``` 任何 `RISK` 级别的发现都会将结论限制在 `MODERATE` 或更差,无论有多少信任信号。出现两个或以上的该级别发现,或得分超过 60 分,将直接判定为 `CRITICAL`。 ## 快速开始 ``` git clone https://github.com/romano-pavan/sitecheck.git cd sitecheck python3 sitecheck.py example.com ``` 无需安装,无需 virtualenv,无需 `pip`。扫描器仅使用标准库。 ``` # 机器可读 python3 sitecheck.py example.com --json report.json # 人类可读报告,可在任何手机浏览器上渲染 python3 sitecheck.py example.com --html report.html # 跳过外部声誉 API python3 sitecheck.py example.com --no-reputation ``` **可选:** `pip install dnspython` 可支持 MX/SPF/DMARC 检查。如果没有它,扫描器将回退到系统自带的 `dig`/`nslookup`。如果这两者都不存在,它将跳过这些检查并明确告知。 **可选:** 设置 `GSB_API_KEY` 以进行 Google Safe Browsing 查询。 ## 三种接口 ### CLI 带有彩色编码的终端输出,可通过 `--json` 进行脚本化控制。 ### Web UI ``` docker compose up -d --build # http://localhost:8080 ``` 请将其保留在局域网或私有覆盖网络中。默认情况下没有身份验证。如果需要,你可以设置 `SITECHECK_TOKEN` 作为共享密钥防护。 ### Telegram 机器人 这是我实际上最常使用的接口,也就是本页顶部截图中的那个。你可以从任何地方发送一个域名给它,它会回复一个结论,然后将完整的报告以 HTML 格式作为附件发送。 它基于**长轮询(long polling)**运行,因此它只会向 `api.telegram.org` 发出出站 HTTPS 调用,仅此而已。没有开放端口,没有 webhook,没有公网 IP,也无需端口转发。它可以在住宅连接的 CGNAT 背后运行,这正是家庭服务器的典型网络环境。 ``` cp .env.example .env # add TG_TOKEN from @BotFather docker compose up -d --build # 向你的 bot 发送 /id,将数字填入 TG_ALLOWED_IDS,重启 ``` **白名单是强制性的。** Telegram 机器人是公开可发现的。如果不设置 `TG_ALLOWED_IDS`,任何找到该机器人的人都可能通过你的家庭网络连接运行扫描。未列出的用户将被拒绝,并且其 ID 会被记录在日志中。 ## 局限性 请阅读本节。一个隐藏自身盲点的工具比没有工具更糟糕。 - **仅限静态 HTML。** 通过 JavaScript 渲染内容的商店对它是不可见的。当它找不到某项内容时,它会报告“未找到,请手动检查”,而不是断言其不存在。 - **启发式判断,而非确凿证据。** `VERIFIED` 意味着未检测到已知的欺诈模式。这并不意味着该商店诚实、有偿付能力,或者你的包裹一定会送达。 - **它无法读取图像。** 就此工具而言,位于 JPEG 页脚中的地址是不存在的。 - **信誉数据源是不完整的。** URLhaus 的干净结果只意味着“尚未被编目”,而不是“安全”。 - **反机器人措施会使其失效。** 位于激进 WAF 背后的站点可能无法返回任何有用的信息。 - **内容检测是双语的(克罗地亚语和英语)。** 域名、TLS、DNS、VIES、OIB、信誉和重定向等层面的检测与语言无关,可针对全球任何域名运行。页面内容层可识别克罗地亚语和英语的表述,并处理 EUR、GBP 和 USD,不论符号顺序如何(`50 €` 或 `£50`)。身份验证在欧盟内部最为敏锐,因为 OIB 和 VIES 是欧盟特有的。其他语言的商店仍然会获得完整的、与语言无关的分析,只是内容读取会比较有限。 无论得分如何,长期有效的建议不会改变。第一次在未知商户购物时,请控制金额,并使用信用卡或货到付款支付。绝不要提前进行银行电汇。 这些盲点中有几个已经有了候选的修复方案。请参阅[路线图](#roadmap)。 ## 设计说明 下面记录的每一个 bug,都是在阅读了与现实相矛盾的输出结果并拒绝妥协后发现的。这些修复方案才是本代码库中最有价值的部分。 ### 评分模型惩罚了合法的跨境贸易 一家老牌的欧盟零售商被评为了 `MODERATE RISK`(中度风险)。调查显示它得了 24 分,但报告中只显示了其中的 10 分。其余分数来自于界面从未展示过的 `INFO` 级别的检查结果。**一个你无法看到其依据的分数,比没有分数还要糟糕。** 而具体内容比呈现方式更糟糕。该零售商是斯洛伐克企业,因此: - 地址的正则表达式只能匹配克罗地亚的城市和邮政编码,从而因为“未找到地址”加了 10 分 - 持有斯洛伐克 VAT 号码而不是克罗地亚 OIB 被扣了 **5 分**,理由竟然是作为一家遵守本国税法的外国公司 - 从 CDN 和其自身的 `.at`/`.de`/`.cz` 店面加载资源,因为“未知的外部域名”被扣了 4 分 该模型将欺诈信号与配置卫生状况混为一谈,并且只计算负面扣分,导致诚实的商店永远无法洗白。这个问题通过拆分评估维度并加入信任信号得到了修复。 ### 未能确认不等于不存在 随后,VIES 集成功能标记了同一家零售商:*“在欧盟 VIES 注册表中找不到该 VAT 号码(+12 分)”*。 VIES 并不是一个公司注册表。它是用于欧盟内部贸易 VAT 零税率的 B2B 交易对手核查工具,它只包含为共同体内部交易激活的号码。通过 OSS 方案向消费者销售商品的 B2C 零售商,完全没有理由进行这种激活。德国、意大利和西班牙要求进行单独的激活步骤,这使得该问题成为导致出现“无效”误报的最常见原因。欧盟委员会自己的指南也明确指出,无效的结果并不意味着该企业存在欺诈行为。 所以,工具正确地查询了一个真实的注册表,试图回答该注册表根本不打算回答的问题,然后将这种无结果视作欺诈的罪证。 现在 VIES 有三种而不是两种结果:`valid`(有效,视为信任信号)、`invalid`(无效,得零分,并附带解释说明为什么这是正常的),以及 `unavailable`(不可用,得零分,因为某个国家数据库宕机并不能构成任何判决)。 ### 发现链接,不要猜测路径 扫描器以前会猜测可能的路径:`/terms`、`/shipping`、`/payment`。而上面提到的那家零售商将条款放在了 `/content/dostava-i-placanje`。猜测永远找不到它,因此工具针对一个用表格列出了四种支付方式的页面报告称“未说明支付方式”。 现在,它会从页面中解析 `` 链接,根据锚文本和 URL 关键字对它们进行评分,并跟踪匹配度最高的链接。路径猜测仅作为没有页脚链接站点的后备方案保留。 ### 单词 PLACEHOLDER 是一个有效的波兰 VAT 号码 在一份实际的报告中发现了这个问题,报告标记道:*“VAT 号码 PLACEHOLDER 未通过 VIES 确认”*。 之前的匹配模式是由 `[A-Z]{2}[A-Z0-9]{8,12}` 经过欧盟国家前缀过滤而成。`PLACEHOLDER` 被解析为 `PL`(波兰)加上九个字母数字字符。完美契合。 修复方法是要求至少包含六位数字,因为真实的 VAT 号码主要由数字组成。这里的教训更具普遍性:一个匹配事物形状的模式,也会愉快地匹配任何其他具有相同形状的东西。`BACKGROUND`、`DESCRIPTION` 和 `SEPARATELY` 距离成为税务身份,仅仅只差一次前缀表查询。 ### 7 里面的 8 一份报告显示 `8 / 7 trust signals`(8/7 信任信号),这不是一个可能存在的得分。之前的最大值是一个硬编码的文字常量,在添加了第八个信号而没有更新该常量的那一刻起,它就脱离了实际情况。 现在,最大值是直接根据扫描器实际能授予的信号列表派生而来的,因此这两不会再产生偏差。在你还在别处枚举某些事物的同时,硬编码它们的数量,这就是一颗带有延时引信的 bug。 ## 路线图 **这项工作正在进行中。** 以下检查项均为候选方案,大致按单位投入的产出价值排序。欢迎贡献代码和提出建议。请开启一个 issue。 ### 免费,无需 key | 想法 | 增加的价值 | |---|---| | **证书透明度日志 (crt.sh)** | 曾经为某个域名及其子域颁发的每一张证书。能揭示真实的 HTTPS 年龄、被遗忘的预发布主机,以及最有价值的部分:**克隆网络**。一张同时覆盖 `shop1`、`shop2`、`shop3` 的证书是诈骗农场的典型特征。这可能是本列表中价值最高的一项。 | | **schema.org / JSON-LD 解析** | 许多商店会发布包含法人名称、地址和 VAT 的 `Organization` 结构化数据。免费,除了已经获取的页面之外不需要额外的请求,并且它绕过了“地址在图片中”这个盲点。 | | **反向 IP / ASN 查询** | 共享主机是正常的。但在同一个 IP 上运行相同模板的两百家 storefronts 就不正常了。此外还能标记出防弹主机提供商。 | | **Favicon 哈希** | 诈骗网络会跨店面重用 favicons。将哈希与已知的恶意特征集进行匹配,成本低廉且有效。 | | **Wayback 内容差异对比** | 这个域名在半年前是不是完全作为另一个用途存在?利用继承的 SEO 回收域名是一种已知手段。 | | **robots.txt / sitemap.xml** | 揭示页脚链接永远不会暴露的网站结构和预发布页面。 | | **注册商信誉** | 某些域名注册商在滥用数据中占比极高。 | ### 免费但需要 key | 想法 | 备注 | |---|---| | **URLhaus 认证 key** | abuse.ch 现在需要身份验证。该项检查代码已经编写完毕且支持优雅降级。只需将 key 作为环境变量配置进去即可。 | | **VirusTotal** | 免费层,限制为 4 次请求/分钟。通过大约 90 个引擎获取域名信誉。 | | **urlscan.io key** | 目前已经在无需认证的情况下进行查询。拥有 key 可以提高限制并返回更多信息。 | | **克罗地亚法院注册表 (sudreg-api.pravosudje.hr)** | 需要免费注册。对于 `.hr` 商店来说,这绝对比 VIES 更好,因为它是一个真正的公司注册表:它返回成立日期、状态(活跃、破产、清算)以及注册业务范围。它能够回答 VIES 从未打算回答的问题。 | | **OpenCorporates** | 带有免费层的公司注册表聚合器。在克罗地亚以外的地区很有用。 | ### 付费 | 想法 | 备注 | |---|---| | **Trustpilot API** | 最显而易见的一个,也是最令人失望的一个。它需要商业合作,而抓取其内容违反了其服务条款。值得坦白地说:反正评论也是本页中最弱的证据。它们都是被大规模购买、刷出来的、被操纵的,而国家公司注册表中的一项记录则不是。如果它能实现,它也只能作为一个弱信号,而不是强信号。 | | **SecurityTrails / WHOISXML** | 历史记录 DNS 和 WHOIS。能够展示当前状态查询所遗漏的所有权变更和托管服务商流失情况。 | | **IPQualityScore / ScamAdviser API** | 现成的风险评分。很方便,但这意味着将本工具旨在做出的判断外包了出去。 | ### AI 辅助检查 这确实很有趣,因为它们能够触及正则表达式无法覆盖的领域: - **条款文本的连贯性分析。** 诈骗商店会从毫不相干的模板中复制粘贴条款。语言模型能够发现自相矛盾的退货政策、指明了与页脚版权信息不同的公司名称,或者在欧盟消费者法律下存在法律逻辑不连贯的条款。正则表达式无法做到这一点。 - **机器翻译检测。** 克隆的店面通常是从其他市场机器翻译而来的。其破绽在于文体,而非词汇。 - **对截图应用视觉模型。** 可以读取刻录在图片中的地址,并检测虚假的信任徽章:比如背后没有任何链接的纯静态 PNG 格式的“Norton Secured”徽标。 - **跨字段一致性校验。** 版本说明中的公司名称是否与 VAT 注册信息、电子邮件域名以及银行账户所在国家/地区相匹配?模型可以对这几点进行逻辑推理。而正则表达式不能。 显而易见的危险在于:模型的结论是不可复现的,并且无法像规则那样接受审计。如果这项功能得以构建,其输出将保持仅供参考并明确标注,绝不会在暗地里影响得分。一个你无法检查其推理逻辑的工具,正是本项目极力避免成为的那种东西。 ### 这种爬取行为合法吗? 这不是法律建议。我是一名系统管理员,不是律师。但坦诚地讲: 在你准备购物的商店抓取少数几个公开页面,本来就是你的浏览器所做的事情。该工具在用户的明确请求下,使用正常的 user agent,每次扫描大约读取 9 个页面,并且不存储任何有关第三方的内容。这是一个站得住脚的立场,并且与系统化的大规模数据收割有本质区别。 真正需要注意的是: - **服务条款。** 有些站点禁止自动化访问。这是一个合同问题而非刑事问题,但它是切实存在的,这也正是为什么抓取 Trustpilot 不在本路线图之中的原因。 - **`robots.txt`。** 虽然没有法律约束力,但无视它是极其不礼貌的,且观感不佳。遵守它是我们后续计划要做的。 - **速率限制。** 猛烈请求某台主机极有可能触及滥用计算机的法律红线。扫描被限制在 9 个页面,正是因为这个原因。 - **GDPR。** 该工具刻意不收集任何个人数据。公司注册数据不属于个人数据,并且不保留任何用户数据。 - **欧盟 DSM 指令第 4 条。** 提供了文本和数据挖掘的例外情况,除非权利人以机器可读的方式保留了该权利,这又绕回到了遵守 `robots.txt` 的问题上。 ### 明确不计划做的功能 - **一个简单的“安全/不安全”布尔值判断。** 不确定性正是本工具的核心。一个隐藏其置信区间的工具就是在撒谎。 - **自动购买或填写表单。** 这超出了本工具的范围,且会带来责任风险。 - **一个公开的托管实例。** 这将需要防滥用控制、速率限制和它自己的服务条款,并且会将每一次扫描背后承担责任的网络连接转移给其他人。 ## 出处 **本代码库中的代码由 Claude (Anthropic) 编写。我没有编写它,我也不会声称是我写的。** 我没有能力编写这种水平的 Python 代码。我所做的是:定义问题、规范行为、针对真实的商店测试每次发布,并找出其中的失败案例。[设计说明](#design-notes) 中记录的每一个 bug,都是因为我阅读了与现实相矛盾的输出结果,并对其进行了深入排查才浮出水面的。商业信息提取功能是我的主意。我负责部署、运营并决定最终发布哪些功能。 这种分工是最坦诚的描述,我宁愿将其公之于众,也不愿假装这是我亲手敲出来的。 机器可读的出处:[`AI_DISCLOSURE.md`](AI_DISCLOSURE.md),遵循 [ai-disclosure 规范](https://github.com/ggfevans/ai-disclosure)。 ## 许可证 MIT。详见 [LICENSE](LICENSE)。 ## 作者 **Romano Pavan**,IT 系统管理员,克罗地亚,克尔克 (Krk) [github.com/romano-pavan](https://github.com/romano-pavan)
标签:Python, Telegram机器人, 反欺诈, 安全合规, 无后门, 网站可信度检测, 网络代理, 请求拦截, 逆向工具