赞
踩
API 有很多分类,本文要讲述的甚至整个行业里面探讨的 API 安全 ,其实指的都是 Web 应用的 API,也就是前后端分离后的数据交互接口或者应用与第三方的数据交互接口。API 是现代 Web 编程主要的数据交互方式,API 安全已成绝大多数企业的严重问题,只有极少企业完全有能力解决 API 安全性问题。随着越来越多的企业通过 api 访问数据和服务,这些 API 成为数据盗窃和软件攻击的诱人目标!API 正在成为大多数现代应用程序的支柱,因此它们的安全性是现代信息安全的核心。保障 API 的安全性已成为当下 WEB 编程的首要目标。
对于企业而言,在生产经营中应提高数据安全意识,通过技术手段加强安全防范,定期修补安全漏洞,加强安全管理。对于公民个人而言,应当警惕个人信息数据泄露,同时自觉履行数据安全保护义务,不得窃取或以其他非法方式获取、使用数据,否则将触及法律红线。
API一般指应用程序编程接口。 API主要目的是提供应用程序与开发人员以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。是一种为客户提供服务的方式。
各种针对交互的 api,本质上相当于是应用层的一个前后端数据交互的协议
REST 是一种风格
REST 的作用是将我们查询(view),创建(create),编辑(edit)和删除(delete)直接映射到 HTTP 中已实现的GET,POST,PUT 和 DELETE方法
比如定义一个有关书的接口:demo.com/books ,然后使用不同的 http 方法来定义行为。GET 查询,POST 创建,PUT 编辑,DELETE 删除。这样改动之后 API 变得统一了,我们只需要改变请求方式就可以完成相关的操作,这样大大简化了我们接口的理解难度,变得易于调用。这就是 REST 风格的意义!
json 由于其轻量、易读的优点已经发展成了一种最常用的数据请求和响应格式。
一种用于 API 的查询语言
调用另一个系统的函数
是一个 XML 格式的、高度标准化的网络通讯协议
本文以 HTTP 接口为例讲解 API 安全
1.安全风险:包括跨站脚本攻击(XSS)、跨站请求伪造(CSRF)、SQL 注入等欺诈行为 2.性能风险:API 接口的性能可能受到访问量的影响,如果访问量过大,可能导致 API 接口响应变慢或者崩溃。甚至大流量本身就是由 DDOS 拒绝服务攻击引起的 3.数据风险:数据删除、数据丢失、数据损坏、数据篡改、意外修改、数据泄露 4.业务风险:越权,抵赖(否认做过的行为)
针对各种常见风险,都有对应的安全机制,认证机制、授权机制、加密机制、日志机制、流量控制机制
API 认证机制是保护 API 的首要方式,其目的是确定 API 请求的来源和合法性。常见的认证机制包括基于令牌(Token)的认证、OAuth 认证等。
访问控制机制是限制 API 访问权限的一种方式,它可以确保 API 的数据仅被授权的用户或应用程序访问。常见的访问控制机制包括角色基础的访问控制(RBAC)、属性基础的访问控制(ABAC)等。
加密机制是保护 API 数据传输和存储安全的一种方式,它可以保护 API 数据在传输过程中不被窃取或篡改。常见的加密机制包括 HTTPS 协议、TLS 协议等。
监控与日志机制是检测和记录 API 操作的一种方式,它可以帮助开发者发现和解决 API 存在的安全漏洞或攻击行为。常见的监控与日志机制包括 API 网关、日志分析工具等。
API 在面临大量合法或非合法请求时可能会耗尽 API 资源和带宽,从而使 API 系统瘫痪或无法正常工作。采用有效的 API 限流和防御机制,保证合法访问的可用性和避免非法的访问。
结合上面的图,我们可以更好的理解安全机制,最右面的是我们提供的 API,最左边是用户,在这之间就需要我们加入安全机制。
这些安全机制可以有效地保护 API 的安全,确保 API 的数据和功能不受到未经授权的访问和攻击。
撞库:通过收集互联网已泄露的用户和密码信息,生成对应的字典表,尝试批量登录其他网站后,得到一系列可以登录的用户。
拖库:来指网站遭到入侵后,黑客窃取其数据库文件,拖库的主要防护手段是数据库加密
洗库:对数据库中的资源进行层层利用,把里面的资源进行全方面的剥夺利用变现
三者结合使用,相辅相成,形成巨大的灰色产业链,进而为黑产提供服务。
指的是通过注册、登录或其他业务接口的返回值,如“账号已存在”或“账号不存在”,“您是老用户”或‘您是新用户’等来判断某个账号(用户名、邮箱、手机号等)是否在该平台注册过。
既可以为撞库提供初步的筛选,也可以作为一种数据爬取手段
根据业务接口的返回值获取到各种有用的信息。通常都是利用 API 缺陷越权获取不同用户的业务数据
针对业务做出的流量欺诈,从而非法获利。
黑客利用手机验证码的机制,将众多应用的短信 API 接口做成列表。而后通过程序调用大量企业的正常短信验证码接口,对指定手机号发起批量攻击,即批量发送验证码短信
对于企业而言,接口被利用,一方面损失了短信次数,更重要的是作为“骚扰者”,对企业有着严重的名誉损失
安全问题无法一蹴而就,针对不同的业务场景,分析可能出现的业务风险,逐步完成 API 安全体系的建设,形成一个良性循环机制、下面进行具体的安全实践,包括 https,加密解密,数据备份,流量限制等各种安全技术的实现
关于网络安全,付出的越多,收获的越多。潮水褪去,才知道谁在裸游
HTTPS是安全的HTTP,因为其是基于TLS协议的HTTP(HTTP over TLS)。SSL已经被TSL所取代,所以你现在真正用的是TLS协议,而非SSL协议。
TLS:传输层安全性协议 (Transport Layer Security),是一种加密通信协议,TLS工作在安全传输层,是建立在传输层TCP之上的协议,服务于应用层,它实现了将应用层的报文进行加密后再交由TCP进行传输的功能。
在当今,通过不安全的 HTTP 访问网站将不再被接受。目前,越来越多的网站开始使用HTTPS协议来保护用户的隐私和安全。如果您希望您的网站是安全的,使用HTTPS是绝对不可协商的决定!
HTTPS协议的主要优点包括:
客户端 | 服务端 |
---|---|
1.请求https连接 | |
2.返回证书(公钥) | |
3.判断证书是否合法-产生警告 | |
4.产生随机对称加密秘钥 | |
5.用公钥进行非对称加密后发送 | |
6.接收并用私钥解密得到对称加密秘钥 | |
7.通过对称秘钥加密的密文通信 |
使用的算法
算法 | 位数 |
---|---|
RSA非对称加密 | 2048位或更高 |
AES对称加密 | 128位或256位 |
需要注意的是,密钥长度越长,加解密的计算量就越大,可能会影响传输效率,因此需要在安全性和性能之间做出权衡。另外,在实际应用中,还需要考虑操作系统、硬件等方面的限制。不同机器不一定支持所有位数的加密算法。所以在HTTPS中,密钥长度是由服务器和客户端协商决定的。具体地说,在HTTPS握手阶段,服务器将其公钥发送给客户端,客户端使用该公钥加密一个随机生成的对称密钥,并将其发送回服务器。在这个过程中,服务器可以向客户端指定支持的加密算法以及对应的密钥长度,而客户端会选择其中最安全和最适合自己的加密算法与密钥长度,并将其发送给服务器。一般来说,服务器会提供多种加密算法和密钥长度供客户端选择,而客户端则会按照一定的优先级顺序选择最优的加密算法和密钥长度。这样做可以确保通信双方都能够支持最高水平的安全性,并且能够在实际应用中取得良好的性能表现。
TLS证书可以分为付费证书和免费证书两种类型。免费SSL证书通常只建议非单位类的个人测试使用。
付费证书 | 免费证书 | |
---|---|---|
颁发机构 | 专业CA机构 | 免费CA机构或社区组织 |
验证速度 | 人工身份验证和审核,下证慢 | 自动化验证,下证快 |
保障范围 | 财务赔偿和人工技术支持 | 论坛/官网 |
凭证类型 | 仅有域名型验证(DV)选项 | 域名型验证(DV),组织型验证(OV),扩展型验证(EV) |
证书有效期 | 1年,到期提醒 | 3个月左右 |
兼容性 | 99%的浏览器和客户端 | 主流浏览器 |
可选机构 | Sectigo、GeoTrust、Digicert、RapidSSL | Let’s Encrypt |
用户的信任度 | 极高 | 一般 |
多域名使用 | 支持 | 不支持 |
得益于 ACME 协议和 Let’s Encrypt 的存在,我们可以免费获取 TLS 证书并自动更新它们。Let’sEncrypt是一个完全免费的开源提供商,但不适合长期使用。
ACME协议:是一种自动化证书管理协议,可以自动化地申请、颁发、安装和更新TSL证书。因此,HTTPS协议使用TSL协议进行加密通信,并且需要使用ACME协议来进行证书的管理。
Let’s Encrypt是一个免费的、自动化的证书颁发机构(CA),它提供了一种简单的方式来获取TLS证书,帮助网站实现HTTPS加密连接。与传统的CA不同,Let’s Encrypt的证书是免费的,可以自动化地申请、颁发和更新。它的目标是使HTTPS加密成为互联网的标准,提高网站的安全性和隐私性
对于web api 来说,付费的和免费的在使用时区别不大,都具备加密通信的功能,仅仅是付费的有效期更长一点而已,还有付费的相当于购买了保险,如果是证书漏洞引起的泄露会理赔的,免费的其实也基本无法被攻破。
企业选择付费证书最主要的原因是基本任何企业都会有官网,还有很多的下属业务官网,使用https是必须的,但是免费的并不支持绑定多个域名,而付费的不管是绑定多个不同域名还是一个域名的多个子域名,都是支持的,而且EV SSL 还可以在浏览器显示对应的公司名(大多数浏览器支持),这对企业品牌形象的提升是非常重要的。
选择付费的证书目的在于如果是浏览器访问的话可以明确告知到用户证书和公私钥是没有被替换的,浏览器会在检查证书后在地址栏明确显示xxx官网,而不仅仅是一把绿色小锁子,这可以最大限度的保障用户不是正在访问钓鱼网站。黑客可以伪造任意域名的证书,但基本无法伪造权威CA证书
手动配置此处暂不过多描述,宝塔面板等都支持自动化申请和使用。
相较于HTTP协议的明文传输,HTTPS加密无疑让网站更加安全了,但我们并没有正确使用HTTPS,尤其是在做webapi开发的时候,大多数开发者只是简单用来加密传输了,对于网络传输过程中的中间人攻击,服务端做到证书的部署和校检环节的完整,客户端识别它的真实性和有效性等信息反馈给用户,https基本上是无法被攻击的(非付费证书客户端和用户无法判断其真假,有些不正规CA机构会不验证域名持有者信息,直接恶意颁发该域名的假证书),SSL中间人攻击就是一个不存在的伪命题。但是在客户端授权的情况下,可以组建中间人网络,而抓包工具便是作为中间人的代理。通常,HTTPS抓包工具会生成一个证书(类比的假证书),用户安装在客户端或添加信任。此时,客户端先与抓包工具通信,抓包工具再将请求转发到服务器,服务器返回的信息,抓包工具可进行处理或输出,然后再返回给客户端。这时候的https加密传输形同虚设,所以,HTTPS的安全性更多的体现在用户不知情的情况下进行的访问,如果用户已知情或主动授信,表明用户已经明确了风险,此时如果出现中间人攻击的问题,HTTPS还是不安全的,且这种不安全行为是服务端无法阻止甚至无法感知的。
真正的https是不存在SSL中间人攻击的,对于api开发,客户端是我们自己开发的,并不是浏览器。所以需要我们自己进行证书的验证,除了验证证书合法性(浏览器只能做到这一步了),我们的客户端更要检查证书中包含的信息是否与正在连接到的服务器相匹配,例如域名、IP地址等,但很遗憾的是绝大多数的站点并没有对证书进行任何验证,完全是在裸奔。使用webapp时,用户甚至都无法得知是否是https连接,客户端也不会给出警告告知用户是否是不安全的连接(开发时没考虑过这个问题),更不会去验证证书来源,这就造成了使用https做web api开发比在浏览器中危险系数高的多。
https可以保证网络传输中的安全,是一种大环境下的安全,防止所有数据被随意监听获取,但如果是碰到了已标准目标的黑客,意图通过篡改数据等行为欺诈服务器时,下载客户端,组件中间人网络将会是我们接下来要防御的重点。
针对这种安全场景,下面介绍一种技术用于解决上述问题
将服务器提供的SSL/TLS证书内置到移动端开发的APP客户端中,当客户端发起请求时,通过比对内置的证书和服务器端证书的内容,以确定这个连接的合法性。证书锁定本质还是是对抗用户非知情场景下的中间人攻击.并非用于对抗破解抓包的,
主要是针对以下几个场景,防止的依然是用户不知情场景下的中间人攻击
个人感受:证书锁定对抓包工具还是有一定影响的,比如服务端响应后,客户端查出是中间人(抓包工具)返回的响应,而不是锁定的证书,则客户端的程序逻辑可能会认定程序未运行在"可信环境"中,从而会不接受返回结果或者其他相对应的比如暂停服务等策略。对证书锁定的检查强度有些应用是每个响应都去检查,更多的是在应用初期访问时检查或者每隔一段时间检查一次。
实现
目前非常流行H5混合式开发APP,使用传统的HttpURLConnection类封装请求,客户端锁定操作需要实现X509TrustManager接口的checkServerTrusted方法,通过对比预埋证书信息与请求网站的的证书来判断。
在客户端锁定服务端证书的基础上(单向锁定),服务端对客户端的证书也进行锁定,需要客户端再做一次证书预埋.多见于金融业务
认证技术解决的是 “我是谁?”的问题
支持以下两种方式,写到请求头或者请求体中
Authorization: Bearer eyJhbGciOiJIUzI1NiI...
http://example.dev/me?token=eyJhbGciOiJIUzI1NiI...
根据HTTP 1.0 规范,Authorization 的格式是:
Authorization: <type> <authorization-parameters>
常见的授权类型还有:
Basic 用于 http-basic 认证;每次请求自动询问用户名密码
Bearer 常见于 OAuth 和 JWT 授权;
Digest MD5哈希的 http-basic 认证 (已弃用)
AWS4-HMAC-SHA256 AWS 授权
JWT认证实质是Bearer认证的一种,只不过JWT认证明确提到服务器加密的信息应该是JSON的
在客户端通过登录请求认证时,服务端返回一个token给到客户端,后续需要操作权限的接口都需要客户端携带token参数来证明自己的身份,完成认证。
该token本质是一段字符串,由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串。三段信息分别header(声明类型和加密算法),payload(七个默认字段+自定义私有字段),signature(header字符串+payload字符串+secret:自定义秘钥字符串/盐 salt )
将头部进行base64编码,构成了第一部分
{
'typ': 'JWT',
'alg': 'HS256'
}
将payload进行base64编码,构成了第二部分
{
"iss" => "jwt签发者", #非必须。issuer 请求实体,可以是发起请求的用户的信息,也可是jwt的签发者。
"iat" => jwt的签发时间, #非必须。issued at。 token创建时间,unix时间戳格式
"exp" => jwt的过期时间,这个过期时间必须要大于签发时间, #非必须。expire 指定token的生命周期。unix时间戳格式
"aud" => "接收jwt的一方", #非必须。接收该JWT的一方。
"sub" => "jwt所面向的用户", #非必须。该JWT所面向的用户
"nbf" => 定义在什么时间之前,该jwt都是不可用的, # 非必须。not before。如果当前时间在nbf里的时间之前,则Token不被接受;一般都会留一些余地,比如几分钟。
"jti" => "jwt的唯一身份标识(编号ID),主要用来作为一次性token,从而回避时序攻击", # 非必须。JWT ID。针对当前token的唯一标识
"GivenName" => "Jonny", # 自定义字段,非必须
"Surname" => "Rocket", # 自定义字段,非必须
"Email" => "jrocket@example.com", # 自定义字段,非必须
"Role" => ["Manager", "Project Administrator"] # 自定义字段,非必须
"Adimn" => true,
}
“header”:“base64编码后的header字符串”,
“payload”:“base64编码后的payload字符串”,
“secret”:“自定义的字符串”,
将上面三个字符串进行header中定义的alg散列算法进行摘要,生成signature字符串,构成了第三部分
将以上的三个部分的字符串 用 . 拼接后返回给客户端
xxxxxx.xxxxxx.xxxxx
jwt一般作为扩展包出现,有很多第三方提供的按以上规则去实现的扩展包,使用时只需要
简单的调用其提供的函数即可。
jwt解决的是认证问题。
最大的优点是无状态,有效使用jwt,可以降低服务器查询数据库的次数,比如在jwt中写入用户id等,就不用每次都去数据库查询token是否与存储的一致。在使用时最好携带不会变动的数据。
缺点:jwt是一次性的,想要变更jwt里的数据,就需要重新颁发证书,而即使签发了新的jwt,旧的仍然不会过期。而要解决这个问题,就需要把旧的jwt加入黑名单,存储在服务端;或者是通过给每个jwt设置独立的secret,签发新jwt时,直接删除旧的jwt-secret。其次jwt是有时效限制的,如果想要静默续签jwt,也是个比较大的问题,不像session。状态是保持在服务端的,随时可以续签,而jwt是要重新颁发的。
jwt的好处就是无状态,可以减少服务器资源占用和数据库查询。缺点就是其是一次性的,变更数据,续签都需要颁发新的jwt,需要中途过期的话甚至还需要引入新机制(黑名单机制或jwt-secret机制)
根据jwt的特性,可以看出jwt并不擅长变动,其实是特别不适合做单点登录和会话管理的,使用的场景可能也就只有 有效期短的一次性认证,比如激活类的邮件链接,这种场景就可以避开变更数据和续签的问题,也无需中途过期。仅仅使用其无状态的特性和认证信息不会被轻易篡改的特性
自动续期和指定失效(中途过期)这两2个方面无解,所以JWT的最佳使用场景就是给第三方应用开放数据的场景(临时认证),仅仅去解决“你是谁”的问题,并不太适用API系统,除此之外jwt还极其不安全,哪怕你使用了https依旧如此。
1.secret是存放在服务器端的,所以只要应用服务器不被攻破,理论上JWT是安全的。因此要保证服务器的安全。ps:这个有点难度!不是程序员可以完全解决了,还需要运维,甚至是网络大环境和政策的支持。
2.避免网络劫持,使用HTTPS传输 ps:HTTPS也不是绝对安全,有可能已经在更早之前已经存在中间人攻击了,甚至攻击者本身就是某个终端用户,而不是来自于网络
3.定期更换secret并且保证secret的复杂度,提高破解的代价,甚至可以针对每个用户或者每条jwt使用独立的secret,存入数据库/Redis,这样即使被破解,也危害不到整个应用。但这样就违背了初衷,不再是无状态的了。
jwt的header部分/payload/部分可以解析出来,signature无需解析,黑客也知道你所使用的加密算法,但是黑客想要篡改其中的内容,则必然会导致签名不正确,这里有两种方式可以达到欺诈服务器的效果
secret一旦丢失,所有用户都是不安全的。所以对于IT人员,更重要的是保护secret的安全。
总的来说,jwt能解决的问题还是很少的,好在有现成的扩展包可以使用,如果对API安全了解不深,对API安全也没有过高要求,也可以去使用。但如果是对API安全性要求较高,也可以去优化一下jwt,比如使用非对称加密rsa去加密签名。还有另外一个问题,jwt其实还是相当于明文传输,即便有https的保护,在网络上也不是特别安全,所以也可以用对称加密将信息加密,把加密解密的秘钥使用非对称加密进行传递。这样一来就有些复杂了,也不是jwt设计的初衷。
在前后端分离, 需要简单的(对安全要求不高)对后台API进行保护时,那就直接使用jwt扩展包;如果对安全有一定要求,那就自己重新设计一个自研的jwt,安全等级根据自身业务场景去指定,甚至是对客户端的零信任,甚至这个时候你要解决的不是认证问题,而是其他的API安全问题了,必然已脱离jwt无状态的范畴了
jwt的使用场景其实时很受限的,并不适合在API系统中使用,所以10年代,出现了一套广泛流行的认证授权协议OAuth2,我们常见的提供OAuth认证服务的厂商有支付宝,QQ,微信,微博等。
OAuth协议的1.0和2.0两个版本,相比较1.0版,2.0版整个授权验证流程更简单更安全,也是目前最主要的用户身份验证和授权方式。
其实JWT和OAuth2这两个协议是根本没有可比性的,jwt说白了只是提供了一个相对安全的token;OAuth2是先给你提供了个token,然后你拿着换取一个access_token,用access_token访问特定资源。说的再简单点就是jwt可以用于在OAuth2里作为一个生成token的小工具。
OAuth相关的三个URL:
- RequestToken URL:获取未授权的RequestToken服务地址;
- UserAuthorization URL:获取用户授权的RequestToken服务地址;
- AccessToken URL:用授权的RequestToken换取AccessToken的服务地址。
OAuth认证和授权过程
- 1、获得一个未授权的Request Token (比如显示新浪微博的授权登录界面) :客户端(第三方软件)向OAUTH服务提供商请求未授权的RequestToken。即访问RequestToken URL发起请求;
OAUTH服务提供商同意使用者的请求,并向其颁发未经用户授权的oauth_token与对应的oauth_token_secret,并返回给使用者;
- 2、获得一个用户授权的Request Token(比如登录之后显示的授权按钮,点击授权之后会返回一个授权过后的Request Token) :使用者向OAUTH服务提供商请求用户授权的RequestToken。即向UserAuthorization URL发起请求并在请求中携带上一步服务提供商颁发的未授权的token与其密钥;
- 3、换取AccessToken 用授权的Request Token向AccessToken URL发起请求,将上步授权RequestToken换取成AccessToken,OAUTH服务提供商同意使用者的请求,并向其颁发AccessToken与对应的密钥,并返回给使用者;
- 4、使用上步返回的AccessToken访问用户授权的资源。
OAuth2认证和授权过程
auth1.0与Oauth2.0是相互不兼容的。1.0协议每个token都有一个加密,2.0则不需要。这样来看1.0似乎更加安全,但是2.0要求使用https协议,安全性也更高一筹。
OAuth2有以下几种授权模式:
相比之下 1.0只有一个用户授权流程。
- 1.用户到授权服务器,请求授权,然后返回授权码(AuthorizationCode)
- 2.客户端由授权码到授权服务器换取访问令牌(access token)
- 3.用访问令牌去访问得到授权的资源
不同于认证解决“我是谁”的问题,授权技术是解决“我能做什么?”的问题
关于认证,授权,流量控制,监控与日志机制,应用层加密机制等共同组成了一个API安全防御体系,在此不多做赘述了,有机会我会通过完整的安全实践代码来演示
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。