私有认证算法 - 网络安全

6
我正在开发一个从文本生成音频(TTS)并提供速度/音高控制的播放器项目。我的问题与请求安全有关。用户在我的网站注册时获得 widget_id,他在自己的网站中放置一些 js,并且 api 在他的网站上工作。当用户点击发送按钮时,api.js 文件会将 widget_id 数据作为 ajax POST 请求发送到我的网站。然后在我的网站上,我获取了 widget_id 和引用源(referer): $referer = isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : '';
我从数据库中获取与 widget_id 相关的站点值,并将其与 $referer 进行比较。
... if($website_url == $referer) { $website_checked = true; } ...
所以我的问题是: 攻击者是否可以使用一些库(例如 Curl)更改 $_SERVER["HTTP_REFERER"] 的值,从而破坏我的安全性?
例如,如果他使用 curl 和以下代码:
curl_setopt($ch, CURLOPT_REFERER, 'https://anysite.io/');
谢谢。
因此,我更新了问题,因为我意识到这是不可信任的。所以请给出私有身份验证算法的基本步骤...
更新3: 我开始设置赏金,因为我需要了解在我的场景中私有身份验证算法的运作方式。

3
易受欺骗,因此不可靠。 - Abbas
1
任何允许您进行网络请求并指定任意标头的程序或插件都会使其不安全。 - Taplar
1
如果API像您的演示页面一样是公开可访问的,那么您实际上无法防止滥用。解决这个问题的方法是只允许每个选项使用预定义的文本(从Google Text-to-Speech下载/缓存已解析的.mp3文件,并仅从您的服务器提供它们),或者完全删除演示并要求用户首先登录(SSO等快速且简便),然后给他们密钥和密钥配额,可以在演示中使用。或者您可以接受它,因为您的价格远远超过您支付1M字符的成本。 - Lawrence Cherone
我认为你需要澄清一个问题:你关心什么?你想要防止什么?你担心有人复制JS并在未经授权的网站上使用它吗? - Will
不,正如我所说的,我需要验证widget_id来自正确的位置! - Simon
显示剩余2条评论
5个回答

4
  • 保护 Js

    1. 当客户端浏览器尝试访问 js 库时,您的服务器应该能够保存客户端的信息,如完整的浏览器名称、操作系统、IP、设备等。服务器应该为该客户端生成一个唯一的 ID。
    2. 您的 Js 应该根据生成的唯一 ID 在客户端浏览器中设置 cookie。
    3. 当用户点击发送按钮时,从 cookie 中传递唯一 ID。在服务器端,根据唯一 ID 验证客户端的详细信息。这是为了确保 POST 请求来自已请求 JS 文件的客户端,限制直接调用 POST API 而不初始化 JS 文件。
  • 验证 POST 请求

    1. 添加令牌过期日期
    2. 始终检查唯一 ID 生成时间和发送按钮单击时间,并基于此阻止可疑的 API 调用。(例如,在 ID 生成和发送按钮单击/在服务器上接收 POST 请求之间的时间段太短)
    3. 一旦服务器接收到 POST 调用,销毁/禁用唯一密钥。
    4. 监控您接收请求的 IP,这将帮助您识别机器人并禁用针对它们的服务器请求。一个小程序就能做到。

3
不,它不可靠。用户可以伪造它们,例如使用Referer ControlRefControl - 尽管这样的事情是由用户修改自己的浏览器完成的。大多数引荐者是正确的(仅仅因为会费力伪造的人不多),但如果安全是一个问题,你不应该依赖它们。要使其安全,发出请求的人应包括私有认证,以证明他们是真实的身份。

@CertainThanks提供的Referer Control链接非常感谢, 你能用两个词来描述私有认证算法吗? 我正在考虑从客户端向我的服务器发送带有15分钟值的秘密令牌,然后使用该值进行检查...这可信吗? - Simon
要完全保证安全,我认为这是不可能的,除非使用您的API的站点拥有自己的服务器端编程。否则,无论该站点运行哪个JS进行身份验证,任何反向工程代码的人都能够运行。 - CertainPerformance
1
如果代码只在客户端运行,您无法确定仅有被允许使用 API 的客户端在使用它,因为客户端代码是公开可见的。混淆可以防止反向工程,但这并不是一个保证。完全安全需要服务器端代码。你必须决定权衡是否值得。在我看来,除非剥削是一个真正昂贵的问题,否则混淆就足够了。 - CertainPerformance
那么谷歌是如何做到的呢?仅提供JS代码?例如,Google翻译小部件... - Simon
我失去了我们聊天的链接。 - Simon
显示剩余4条评论

0

所以我在这里没有看到任何活动。

我认为,如果我在客户端生成随机令牌,然后向我的服务器发出ajax请求并存储用户随机令牌与其小部件ID相关联,然后使用相同的令牌进行另一个请求,并将其与保存的值进行比较,就可以解决我的问题!


0

你的问题的答案就像其他人写的那样:不行。Referer 不能信任并且容易被篡改,甚至可以被浏览器阻止。

但是:

这是真正的问题吗?安全性始终是可用性和风险之间的权衡,因此您必须衡量风险。例如,Google 地图微件安全依赖于 referer。这表明两件事:

  • Google 没有找到/没有更好的方法来检查微件集成是否来自正确的位置
  • 即使 referer 可以被篡改...他们也不在乎。这很不可能发生,但更重要的是:如果发生了,问题不大(至少对于 Google 来说,那些 Google 地图微件被“盗用”的客户不会感到高兴)。

再次强调,真正的问题是:您的微件和数据有多敏感?如果您确实需要安全性,您将不得不实施一些私有身份验证(这只是另一种方式来说登录),管理凭据以及存储它们的地方(数据库?),处理令牌交换, 用户每次都要登录...

所以,是的,可能拥有一个真正安全的微件,但正如我所说,这总是一种权衡,没有免费的午餐。


0

为了进行安全调用,您可以使用JWT加密请求,您可以在此处阅读有关JWT安全性的更多信息如果您可以解码JWT,它们如何安全?

有一个非常可靠的库可以在PHP中生成此令牌,您可以在任何客户端语言(例如JavaScript)中使用生成的令牌。

https://github.com/firebase/php-jwt

例如,下面的示例将包括私有/公共身份验证密钥以及其他数据,您可以在服务器端验证,即您的widget_id。
use \Firebase\JWT\JWT;

$key = "example_key";
$payload = array(
    "iss" => "http://example.org",
    "aud" => "http://example.com",
    "iat" => 1356999524,
    "nbf" => 1357000000,
    "widget_id" => 123
);

$jwt_public_key = JWT::encode($payload, $key); 

您可以使用负载中的各种参数验证REQUEST,并查看库中刷新令牌方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接