从开发和对抗的角度思考web网页中的接口逆向

如何从开发和对抗的角度去思考web网页中的接口逆向。


文章目录

  • 前言
  • 1.从开发和对抗的角度思考接口逆向
    • [1.1 什么是接口逆向](#1.1 什么是接口逆向)
    • [1.2 开发的角度思考如何开发策略](#1.2 开发的角度思考如何开发策略)
    • [1.3 对抗的角度思考遇到的问题](#1.3 对抗的角度思考遇到的问题)
    • [1.4 正常情况下开发者如何防护](#1.4 正常情况下开发者如何防护)
    • [1.5 正常情况攻击者如何做?](#1.5 正常情况攻击者如何做?)
    • [1.6 对抗中的胜者](#1.6 对抗中的胜者)
  • 2.某个平台接口逆向案例

前言

今天突发奇想,做了一些web接口的逆向(用于信息聚合,带个人token,不做爬虫),于是在这里简单分享下,如何从开发和对抗的角度去思考web网页中的接口逆向。

  • 本文只做经验分享,不公开测试逆向的网站和逆向后的结果。
  • 本文只讲一下思路,并做一些简单测试。

1.从开发和对抗的角度思考接口逆向

开始本文前,先进行一个简单的科普,什么叫接口逆向?(针对B/S架构)

1.1 什么是接口逆向

现如今B/S架构的开发方式普遍是前后端分离,开发流程为:

  • 服务端提供能通过互联网访问的接口。
  • 前端使用Vue/React等框架进行开发,需要真实数据的时候从服务端提供的接口请求。
  • 开发完后使用webpack等工具编译JS代码。

对于一个前后端分离的网站来说,当我们随便打开一个网站,并使用F12去查看时,会发现:

  • 网络中会有真实数据的HTTP请求。
  • 前端源码一般看不懂。

这个时候,当我们去查看具体的请求,就能看到这个请求的构造,例如,我们可以查看下leetcode首页的一个接口:


你通过这种方式就能看到接口的url、请求体、返回体,一但获得了这三个信息,你就可以自己写一个程序去调用这些接口,获取他们的数据了,当然前提是你得搞定登录和授权。

你获得了这些接口,可以干很多事情:

  • 做爬虫爬取大网站的数据。
  • 写自动化脚本去进行某些获利的操作,比如抢购、自动签到等。
  • 从接口的返回体中发现没有在页面上显示出来的信息。
  • 发现接口的水平/垂直越权漏洞。

这些事情都是对网站所有者不利的,所以它自然不想你能这么简单的拿到接口的使用方式。

它就会有一些策略来对抗你:

  • 请求接口的时候,对参数进行某种方式的签名,一旦你得签名不对,就直接请求失败。
  • 接口返回的时候,对返回的结果加密,怎么解密只有前端知道。

例如:

这些策略其实就是隐藏接口的调用信息,防止你干坏事。

但是,所有这些加密、签名操作都会在前端运行一遍,也就是跑在你的电脑里面,理论上你是一定能分析出它的代码逻辑的,不过在真实场景往往会有各种各样的反制手段组织你去干这件事情,干这件事情的过程,就是逆向,在这个场景里叫接口逆向。接下来,我们可以从开发者的角度来思考下,怎么做这件事情以及如何防护。

1.2 开发的角度思考如何开发策略

假设我是一个全栈开发者,现在我想将我网站的接口的关键信息隐藏起来,让别人不能这么轻易的获得,我应该怎么办?

  • 制定一套加密/签名策略,对请求的参数、返回值,甚至是url中的关键内容,前端后端同时执行这套策略。
  • 这样只有服务端接受到指定前端发送的请求才知道怎么处理,而只有指定前端才能理解服务端接口返回的内容是什么含义。

这个时候,就会涉及到一些细节问题了,我使用什么样的加密策略,什么样的签名策略?

  • 自己去实现一个吗?这些密码学相关的算法非常的严谨,自己实现的很难做到相应的安全保障,且效率方面也会比成熟的库低不少。
  • 使用开源的一些密码算法库进行组合,多次套娃。密码算法库一般涉及的运算多,如果套娃过多,特别是使用到了公钥体系中的一些算法,可能会影响接口的性能。而且如果多个算法使用到的密钥不一样还难维护。

做为一个对安全知识有限的开发者来说,最简单的办法是:

  • 制定一套简单的规则将所有参数和url拼接起来签一个名,签名的私钥写死在前端,服务端收到请求后,先使用公钥验证签名是否正确再进行后续的处理。
  • 服务端对要返回的返回值使用AES进行加密,使用到的初始向量和私钥同样写死在前端。

简单总结就是:

  • 使用成熟的密码算法库。
  • 前端写死密码算法中会使用到的密钥。
  • 不做其他的安全防护。

假设这个版本是v1。

1.3 对抗的角度思考遇到的问题

现在我是一个攻击者,攻击的目标是上述的v1,想要得到这个的具体信息,我该怎么做?

  • 对前端请求的部分打上断点,调试参数生成签名的逻辑,返回数据的处理逻辑。
  • 搜索成熟的密码算法库的特征。
  • 搜索加解密、签名、密钥等关键字。
  • 分析请求和这些特征的交互逻辑。

对于v1版本来说,上这几种手段基本就能分析出前端具体的处理逻辑了,而且大概率能看到调用某种成熟算法库进行加解密、签名的操作,这个时候,如果想使用接口,直接使用这种算法其他语言的替代库即可。

这个时候,作为开发者的我有点不开心了,因为你如此简单的就获得了我的接口,导致我的防护措施没起到作用。我也该做出反制了:

  • 调试是吧?我直接无限debugger,让你无法正常的调试。
  • 搜索密码算法库的特征是吧?我自己实现一个高效率的库,让你没办法找特征。
  • 直接搜索密钥是吧?我自己写一个生成密钥的算法,让你根本看不到明文的密钥。
  • 分析代码逻辑是吧?我直接加混淆加vm,你面对一堆乱七八糟的js代码分析去吧。

我花费了大量的成本,此时做出了v2版本,这个版本对于99%的正常开发者来说,已经很难去逆向了。对于能逆向的人来说,需要花费大量的时间去分析,就算能逆出来,也不敢大规模的使用或公开,因为一旦被发现,我再把这些策略改一改,又是需要花费许多的时间在上面了。

如果不是拿到这个接口真的能获得巨大的利益,开发者也不会花费这么多成本去防护,攻击者也不会花费这么多成本去攻击。二者的对抗中,本质上就是资源的博弈。

1.4 正常情况下开发者如何防护

  • 不必对所有的接口都采用防护策略,有些接口可以放给有需要的人调用。
  • 可以在客户端侧的关键业务做一验证码防护,例如登录、签到等业务。
  • 可以在服务侧做一些防护的策略,比如限流、特定ip高频访问重点观察。
  • 做一些动态的防护策略,例如在做某种大抢购业务时,更换前端和服务端共享的密钥等。

1.5 正常情况攻击者如何做?

二者的对抗本质是资源的博弈,如果ROI够高,也是可以考虑如下策略的。

  • 多个逆向人员分工逆向特定的部分。
  • 使用不同账户,不同的代理节点进行访问。
  • 使用机器学习算法对抗人类验证。

1.6 对抗中的胜者

既然是资源的博弈,谁花的资源少,但是收获大,才是真正的胜者。

比如:

  • 开发者在客户端随意引用很多无用的加解密流程,导致攻击者花费了大量的时间去踩坑。
  • 攻击者很简单的就发现了防护策略的弱点。

2.某个平台接口逆向案例

接上面那个对返回结果加密的例子,尝试做一次简单的逆向。

先看接口:

纯get请求,没有请求参数,看返回体:

返回体一堆字符,看其特征像base64编码,尝试解码:

发现是乱码,说明是字节编码而来,考虑是明文进行某种加密后再使用base64编码,调试接口的请求部分:

单步调试:

发现接口中有加密相关的布尔值,说明这个接口的内容是加密的,同时指定了parseResponse中的解密算法为i.Decrypt。全局搜索Decrypt,找到Decrypt函数的定义。

仔细查看代码,其实解密函数就是一个AES的CBC模式,并且IV和密钥都是明文在源码中。只需要写个简单的python脚本就能解密返回体。

python 复制代码
from Crypto.Cipher import AES
import base64

# 将 JS 代码中 l 和 i 分别转换为 Python 对应的 key 和 iv
key = "63ca0d3f90f844928d236e132a1fee45".encode('utf-8')
iv = bytes.fromhex("00") * 16

# 假设密文为 Base64 编码的字符串,请替换为实际的加密数据
encrypted_base64 = "oUVOya5NG43FFSaV8gojbexUwU/RWNL7s/Ow***"
ciphertext = base64.b64decode(encrypted_base64)

# 创建 AES 解密器,注意这里使用 CBC 模式
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext_bytes = cipher.decrypt(ciphertext)

# 去除 PKCS7 填充
padding_length = plaintext_bytes[-1]
plaintext_bytes = plaintext_bytes[:-padding_length]

plaintext = plaintext_bytes.decode('utf-8')
print("解密后的明文:", plaintext)

结果为:

可以看到是一个标准的json格式,到底这个接口的防护策略就被我们突破了。


ATFWUS 2025-03-05

相关推荐
Lang-12109 小时前
Frida + Android Hook 完整指南
android·逆向·hook·frida
浩浩测试一下1 天前
汇编 标志位寄存器 (逆向分析 )
c语言·汇编·逆向·windows编程·标志寄存器
浩浩测试一下1 天前
汇编 数组与串指令(逆向分析)
汇编·逆向·二进制·免杀·串指令·汇编数组
程序0071 天前
.NET玩转爬虫 遇到反爬 jsl cookie
逆向
RSCompany1 天前
Frida 17 以后 Python API 跑旧版 JS 报 Java is not defined ?一行 import 直接恢复 Frida 16 体验
开发语言·python·逆向·hook·frida·android逆向·frida17
浩浩测试一下2 天前
汇编中的JCC指令 (逆向分析)
汇编·逆向·标志位·jcc指令·跳转指令·标志位寄存器
浩浩测试一下2 天前
汇编中的段与段寄存器(大小)段序 (逆向分析)
汇编·逆向·二进制·字节序·windows编程·内存地址排序
浩浩测试一下4 天前
汇编 位运算 (逆向分析)
汇编·逆向·位运算·asm·windows编程·二进制逆向
浩浩测试一下4 天前
汇编 高低八位寄存器数据存储方式(逆向分析)
汇编·网络安全·逆向·二进制·免杀·寄存器·windows编程
泡泡以安8 天前
Unidbg学习笔记(十三):固定随机干扰项
android·逆向