5

怎么防止用户自己调用网站 API 发送 POST 请求篡改数据

 2 years ago
source link: https://www.v2ex.com/t/806211
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  程序员

怎么防止用户自己调用网站 API 发送 POST 请求篡改数据

  b00tyhunt3r · 19 小时 16 分钟前 · 3712 次点击

譬如我有一个 API 节点, 这个 API 接收包含 1 个参数 "address" 的 POST 请求

正常来说这个 address 是客户端在发送 POST 请求的时候程序自动获取的, 用户无法自己更改 但是如果用户自己用开发者工具之类的 call 这个 API, 在请求中传入自己有效的 Token 绕过鉴权, 和一个篡改的 address 参数, 那岂不是可以随意滥用这个 API 私自修改 address 了吗?

刚刚接触 web 开发不是很懂,请问该如何防止这个情况的发生?

45 条回复    2021-10-08 08:38:21 +08:00

DogeFlyKite

DogeFlyKite   19 小时 0 分钟前

搞一下 HTTPS 双向认证?

seakingii

seakingii   18 小时 59 分钟前

首先这个话题是"矛与盾",永恒的碰撞,难说能"防止"

其次可以加一些手段加大不合法调用的难度 ,方法也是老久的

百度: api 接口签名

zmxnv123

zmxnv123   18 小时 56 分钟前

token 根据 address 生成,服务端校验 token 和 address 是否匹配。

flyhaozi

flyhaozi   18 小时 51 分钟前

收藏了,学习下怎么绕过接口验证😁

xiaopc

xiaopc   18 小时 48 分钟前 via Android   ❤️ 2

首先,理论上用户端发来的任何信息都应视为不可信的,总有方法可以伪造,所以终极方法是「 address 」不应由客户端发
其次,如果做不到的话,就只能提高伪造难度,比如楼上说的对请求使用某种签名,然后混淆相关代码(攻击者获得签名方式;比如使用可信介质( U 盾等)客户端证书

zjsxwc

zjsxwc   18 小时 47 分钟前   ❤️ 2

用户主动行为你禁止不了。
但你可以做到不让用户之外的人恶意篡改,比如使用 https 。

mercury233

mercury233   18 小时 47 分钟前

默认你收到的都是篡改过的值,然后该怎么办就怎么办

xiaopc

xiaopc   18 小时 43 分钟前 via Android

(点错回复了)
比如楼上说的对请求使用某种签名,然后混淆相关代码(如果攻击者获得签名方式就没用了);比如使用可信介质( U 盾等)存储的客户端证书进行签名(但是怎么保证证书不会被攻击者拿到)

lmaq

lmaq   18 小时 40 分钟前

公钥加密+签名认证

coolrc

coolrc   18 小时 36 分钟前 via Android

如果是用户用私有 token 发的,那这个接口应该只能改这个用户的相关 address,如果被滥用了也是用户自己主动泄漏 token 的,只会影响这个用户。

如果是公用的 token,那你的 API 应该只能 get,而不能 put 。不能给修改数据的 API 用公共 token,不然怎么样加密都会被解析出来。

chanchan

chanchan   18 小时 36 分钟前

你觉得他不能用,他的 token 就不能有权限

Junzhou

Junzhou   18 小时 22 分钟前   ❤️ 2

他拥有他的合法 token,向接口发起请求,这样就是合法请求,为什么不能修改地址呢?

如果传递给你的地址是错误的(非法的),那你在后端对地址做校验就好了。 如果你用的是 https,把请求这个行为,和请求携带的参数是否合法,分成两个事儿来理解。 对请求内容加签只是为了保证内容在传输过程中防篡改。如果本身请求发起时携带的参数时错误的,加签并不能解决这个问题。

MintZX

MintZX   18 小时 21 分钟前 via iPhone

你是想要防止入侵还是什么? 如果是防止入侵 token 就行了。如果是防止有有效身份的用户自己改信息,那基本上是不太可能的。你整套前端的代码我都能改,你怎么防╮( ̄▽ ̄"")╭

Junzhou

Junzhou   18 小时 18 分钟前

@xiaopc 5# 说的我觉得不太对,其实应该拆开了看,客户端发起的请求是可以信任的(可以做到可信),但是客户端请求携带的参数(数据),必须要假设是不可信的。

markgor

markgor   17 小时 44 分钟前

第一、https 和这个没关系吧。装个 Fiddler,你就算是 https 还不一样能拦截篡改。
第二、address 生成是由客户端生成,那就不存在不能篡改,你要防止篡改的话只能由服务端生成。因为客户端生成的话你无法区分 address 是被篡改后的还是没被篡改,当然你可以对参数请求进行签名,但这样无疑只是增加破解的成本而已,别人只要反编译下或者多次对比,找出你加密的规则,那最后还不是一样照篡改你的数据。
最后:前端提交的一切内容都应该视为不可信内容。

qfdk

qfdk   17 小时 42 分钟前

这里需要后端校验用户的权限,如果用户没有更改权限,传来也没用。
首先 这个 token 要不是 jwt 的话 肯定会连着一个 previllage 的表,这里记录了一些可用的权限。正常要是 spring 的话 用 authority 来判断,默认是 访问 userinfo endpoint 来获取用户信息。 你可以用简单的 RWD 这样的三种权限来验证,看看有没有 W 权限。
当然了,还有个简单的法子,你 post 的时候, 后端通过 token,知道是谁来发送的,只要测试一下这个人是不是在白名单里面就好了 也就是

```js
if(allowEditAddress(token)){
doSomething();
}else{
// 没有权限
}
```

qfdk

qfdk   17 小时 40 分钟前

正常来说这个 address 是客户端在发送 POST 请求的时候程序自动获取的
> 这个获取流程,移到后端呗

Jooooooooo

Jooooooooo   17 小时 39 分钟前

jinliming2

jinliming2   17 小时 28 分钟前

没有 100% 的安全。你只能增加代码逻辑混淆,通过特定的方式生成校验参数,以此来提高破解门槛。如果破解者的破解成本大于破解后的收益,就表示你的混淆有价值。
如果不考虑破解收益,用户就是想不计成本的破解你的 API 混淆参数,那么你没办法,所有前端的校验逻辑理论上都是可以被破解的。

hronro

hronro   17 小时 14 分钟前

你在设计 API 的时候就应该想好,不应该信任客户端传过来的任何数据

seakingii

seakingii   17 小时 7 分钟前

@qfdk 你们忽略了一个场景,就是正常情况下,这个地址是由移动端 GPS 得到的, 所以不存在"由后端获取 address"的说法

seakingii

seakingii   17 小时 6 分钟前

这个场景应该是"正常情况下,这个地址是由移动端 GPS 得到"

楼主可能是为了防止用户随意更改 address,(有点像打卡 APP 防乱改地址)

pupboss

pupboss   16 小时 55 分钟前   ❤️ 1

可以做,但是意义很小就是了,因为 address 数据追根溯源是用户产生的,只要是用户产生的数据他无论如何都能篡改,就算你堵住了 address API,用户照样可以 root 越狱后改机器的 GPS

这也就是为什么说“任何用户输入都是不可信的”,后端简单做下过滤,避免用户传的数据对业务造成影响,避免不可靠的字段造成程序 crash,基本上就已经谢天谢地了

qfdk

qfdk   16 小时 42 分钟前

@seakingii #22 主要是楼主说的是 web 开发。没有万能的解决方案,只有一个针对于某个问题的一个方案。既然移动端来传输了,那就要考虑到移动那边了(估计楼主没到这么远呢), 你想的场景合理。要是 GPS 的情况可能要来个偏移算法,看看比如飘了多远,如果手机没电了各种情况了。 逃~~~

xiaopc

xiaopc   16 小时 21 分钟前 via Android

@Junzhou MITM 拿到请求,甚至直接在客户端做手脚,客户端请求也可以做

lscexpress

lscexpress   16 小时 5 分钟前

@zmxnv123 没关系啊,篡改数据的机器和获取 token 的机器在同一个地方

linhongye

linhongye   15 小时 58 分钟前

是的, 没有错...
用户有 token 就是可以去操作这个东西...
今天担心用户用 api 去操作 address, 明天就得担心用户虚拟 GPS 去操作 address.
想阻止这件事, 就得去结合多个不同传感器的信息去做验证.
回头来, 核心还是要考虑业务场景. 用户改了这个东西获得了什么好处, 你们损失了哪些东西?
如果损失不大, 甚至只是减少了一些利润, 其实可以不管...
一方面, 这种用户量不大, 等这种用户多了再去管.
另一方面, 如果刚接触 web, 那可能是个新项目, 这种项目有用户来用就是胜利, 还管他怎么用呢....

stevenhawking

stevenhawking   14 小时 56 分钟前

你参数都是放开给用户端 <input/> 控件的,你能给他 disabled 掉吗

ch2

ch2   14 小时 38 分钟前   ❤️ 1

一开始你就要考虑这种情况:
api 被逆向过,请求是用脚本发过来的
这种没办法防,但是你可以写一些规则惩罚乱搞太厉害的号

kinge

kinge   14 小时 22 分钟前

你不需要防止客户端请求。你只需要校验参数就行了

cs419

cs419   14 小时 13 分钟前

这个防不了
就类似爬虫一样 你可以加高对方的作弊成本
但无法做到绝对的阻止

如果你做到了绝对的阻止 那正常用户应该也被你拒之门外了

niubee1

niubee1   13 小时 40 分钟前

这是个设计问题吧,首先,如果一个不需要修改的值,为啥还要客户端原封不动传回去?

liuidetmks

liuidetmks   13 小时 9 分钟前 via iPhone

目前可用的办法就是 混淆 js 。目前混淆器好像可以做到类似于汇编了,到处跳转,属性都给你混淆了。
监控下 debugger
把运行环境,时间戳也当做参数。

但是这也只能增加对方难度,不能杜绝。

clf

clf   12 小时 55 分钟前 via Android

如果这个参数不应该由用户看到和生成,那么就完全把业务逻辑放在后端。

icyalala

icyalala   12 小时 24 分钟前   ❤️ 1

ssl pinning (也就是客户端内置证书) 来防止初级的抓包
参数签名+客户端防逆向
服务端风控,这是最主要的
根据我待过的几个公司的经验,就算大厂也基本就是这些了
整体来说就是增加成本降低风险,完全避免是不可能

zyxk

zyxk   11 小时 54 分钟前

客户自己调用 api ,在校验合法的范围内,他随便改都可以.
我也有个疑问,怎么防止客户不使用我的前台 /客户端 . 只用 api 或 第三方客户端调用 api
或者换个说法 比如 前后端分离的 V2EX 怎么防止第三方客户端呢 ?

@xiaopc @zjsxwc @coolrc @Junzhou
@MintZX @markgor @qfdk @ch2

ch2

ch2   11 小时 44 分钟前

@zyxk #36 答案是没法防,微信都做不到完全防止逆向
甚至后台都不一定能检测出来请求到底是不是自己客户端发的
无非是:
1. 用一些难以伪造的签名机制对请求进行签名,不要求请求必须被签名,不签名一样能用 api(可以很有效地对付懒省事的逆向者),但是服务器可以知道这个请求是第三方发过来的
2. 以封号为手段对使用非官方客户端的用户进行惩罚,或者强制踢掉这个第三方客户端的用户
使这个第三方客户端声誉受损没人敢用

leafre

leafre   11 小时 25 分钟前

签名+防逆向保护签名 token,只能尽可能提高篡改门槛

rekulas

rekulas   10 小时 31 分钟前

问题可以转换下,相当于淘宝用户都可以设置自己地址,然后问如何防止用户用工具模拟提交地址
答案当然是无法防止,只能通过各种手段提高逆向难度

毕竟对服务端来说,客户端都是“无状态”的,只要参数正确,无法识别是真客户端还是伪客户端

qfdk

qfdk   10 小时 6 分钟前

@zyxk 只能说加大难度,简单的是加了个 reCAPTCHA,为了防止计算机系学生,随便抓取 api 来进行开发第三方客户端(为了防止假设私人代码到他们的 vps 不行的 ddos 服务器来查询成绩,课程表等等)我们的方案是通过 gateway 来处理。gateway 与前端通讯是通过 session,每次前端请求,session 会续命 4h 。gateway 那边可以通过 sessionId 获取到用户的 token,token 我们不会保存在客户端(浏览器端)。这样所有的请求都通过我们 gateway 。如果第三方 学生需要搞的话,需要做到 keep-session,也就是不停的刷新浏览器或者发请求,超级麻烦。公共 API 都是 AES 加密参数的,秘钥我们知道,学生并不知道,这样公共 api 做到一人一个 token 不会重复,他们也没法穷举。

iPhone9

iPhone9   9 小时 31 分钟前

为什么你叫这个是篡改数据?

timpaik

timpaik   9 小时 28 分钟前 via Android

api 设计原则之一:客户端永远不可信

ganbuliao

ganbuliao   8 小时 26 分钟前

这种情况就 带一个 addressID 呗 后端通过 addressID 查出用户真实的 address 不就行了

js8510

js8510   2 小时 42 分钟前

我遇到过类似的。最后使用 presigned url 稍微增加了 手动 call api 的难度。

1. client request for address updates -> server
2. server return a presigned url for posing address chagnes and the url timeout in 200ms(一般是你 request response round trip 正常的时间范围)
3. client update address with presigned url.

因为 2. 返回的 presigned url 有 200ms timeout 而且只授权指定 ip. 所以,至少用户没办法手动操作直接 call api. 怎么着也要再搞个脚本 自动化一下。其实就拦截了不少特定场景下的用户了。

但是我觉得你的用户如果都是程序员,而且直接 call api 的动机很强,那基本上就没有用了。

xuanbg

xuanbg   6 分钟前

合法的用户,拥有合法的权限,使用合法的方式调用接口,怎么就成了篡改数据???

如果这行为不符合你的预期,那一定是你的接口数据校验没做到位。这就不是身份验证或令牌的问题,而是对数据的操作没有进行必要的限制的问题。譬如订单都发货了,你还允许修改发货地址之类。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK