返回资讯中心
外部精选
软件工程
#开发者实时流

InfinityFree 的 "?I=1

来源标题:InfinityFree's "?I=1"

文章以作者2026年11月8日与大学老友重逢为引子,讲述对方请其开发一个计算两坐标中点的小工具,用于与网友约定公平的见面地点。作者回家后随即完成应用并发送链接,约一周后(11月14日)出现转折。

Hacker News 最新altilunium2026/11/14 · 今天22 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

分享

2026年11月8日,我和一位大学时代的老朋友见了面。我们大概有八年多没联系了,直到有一天我突发奇想,在Instagram上搜索老同学的踪迹。

事实证明,Facebook Inc.(现为Meta)在“重新找回旧日熟人”这件事上依然相当擅长。我很快就和朋友重新联系上了。按下关注按钮,查看对方的关注列表,再关注几个人,没多久,关注链就引出了私信。经过大量交流后,我们约了线下见面。

见面时,朋友让我做一个简单的应用:一个计算两个坐标之间中点的工具。

他心里有个具体的用途。有时他需要和网上认识的人见面,在双方各自住处之间找到一个合适的碰面地点,对让安排尽可能公平很重要。以地理中点作为会合点,理论上双方就能走相同的距离。

所以,见面一回到家,我立刻就把应用做好,把链接发给了他。

大约一周后,2026年11月14日,我又收到了他的消息。显然,这个应用第一次在真实场景中成功派上了用场!

他还提了一个功能需求:用户不应该只能手动输入坐标,还应该能直接输入地名来搜索位置。

今晚,我打算实现这个功能。

我最初的策略很直接:集成Photon地理编码器,把位置查询解析成坐标。不过,这里有个问题。

我预计Photon会解析不了某些查询,尤其是当底层的OpenStreetMap数据不完整时。我不想让这些失败的查询就这么消失。相反,我想把它们收集到某个地方,这样就能用积累的数据来发现数据缺口,并有可能改进地理编码体验。

我希望每当有人提交位置查询时,我的手机都能收到即时通知。为此,我设计了一套方案,涉及service worker和推送通知。然后我把整套东西部署到了我免费的InfinityFree托管账户上。

不幸的是,service worker拒绝工作。

我开始用Chrome DevTools调试问题。我切换到移动设备模拟,检查了控制台。果然,有一条错误信息:manifest.json中存在语法错误,据说是在第1行。

不可能,我心想。我的manifest.json看起来完全合法。到底能有什么问题?

我决定通过DevTools直接访问manifest.json,查看它的实际内容。结果发现:InfinityFree把我manifest.json的全部内容替换成了完全不同的东西。

<html>
 <body>
 <script type="text/javascript" src="/aes.js"></script>
 <script>
 function toNumbers(d) {
 var e = [];
 d.replace(/(..)/g, function(d) {
 e.push(parseInt(d, 16))
 });
 return e
 function toHex() {
 for (var d = [], d = 1 == arguments.length && arguments[0].constructor == Array ? arguments[0] : arguments, e = "", f = 0; f < d.length; f++)
 e += (16 > d[f] ? "0" : "") + d[f].toString(16);
 return e.toLowerCase()
 var a = toNumbers("f655ba9d09a112d4968c63579db590b4")
 , b = toNumbers("98344c2eee86c3994890592585b49f80")
 , c = toNumbers("4445f8d155088fc9ff58f3c4b5f04d8d");
 document.cookie = "__test=" + toHex(slowAES.decrypt(c, 2, a, b)) + "; max-age=21600; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/";
 location.href = "manifest.json?i=1";
 </script>
 <noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support</noscript>
 </body>
</html>

其实,早在这次事件之前很久,我就怀疑幕后有类似的事情在发生。有一个细节一直让我耿耿于怀:每当我访问自己的域名时,URL里总会稳定出现那个可疑的?i=1参数。

但这是我第一次偶然发现那个看似无害的URL参数背后实际发生的事情。

这是一段由InfinityFree托管基础设施注入的反机器人/浏览器验证脚本。它的目的是验证访问者能够执行JavaScript、解密一些数据并存储一个cookie,然后才允许访问所请求的资源。

toNumbers(d):把十六进制转换为字节

这个函数接收一个十六进制字符串,并将其转换为数字数组。

function toNumbers(d) {
 var e = [];
 d.replace(/(..)/g, function(d) {
 e.push(parseInt(d, 16))
 });
 return e
// toNumbers("f655ba9d") -> [246, 85, 186, 157]

toHex():把字节转换回十六进制

这个函数做的是前一个函数的逆操作。它接收一个数字数组,把每个数字转换成两个字符的十六进制表示。

function toHex() {
 for (var d = [], d = 1 == arguments.length && arguments[0].constructor == Array ? arguments[0] : arguments, e = "", f = 0; f < d.length; f++)
 e += (16 > d[f] ? "0" : "") + d[f].toString(16);
 return e.toLowerCase()
// toHex([246, 85, 186, 157]) -> f655ba9d

AES

这是三段密码学数据。每个十六进制字符串包含32个字符,代表16字节(128位)。

var a = toNumbers("f655ba9d09a112d4968c63579db590b4")
 , b = toNumbers("98344c2eee86c3994890592585b49f80")
 , c = toNumbers("4445f8d155088fc9ff58f3c4b5f04d8d");
// a : AES加密密钥
// b : 初始化向量(IV)
// c : 加密数据(密文)

AES(高级加密标准)是一种对称加密算法。加密和解密使用同一个密钥。

slowAES是AES算法的一个JavaScript实现。

通常,现代浏览器提供原生的密码学API:crypto.subtle.decrypt(...),但独立的JavaScript实现可以在不依赖Web Crypto API的情况下工作。

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →