张文盛,章红琴
(1.安徽广播电视大学 信息技术与网络管理中心,安徽 合肥 230022;2.合肥恒卓科技有限公司 营销二部,安徽 合肥 230022)
URL是Web应用的入口,URL安全是Web应用安全的重要组成部分。URL存在的安全问题主要包括信息泄露和信息篡改。信息泄露包括两种情况:一种是给攻击者一些有用的信息,攻击者据此推断内部实现细节,进而找到漏洞[1];另一种是URL本身包含一些敏感信息,例如密码或SESSION ID,可直接为攻击者所用[2]。信息篡改也包括两种情况:一种是攻击者修改URL中的参数,通过提交精心构造的数据,完成结构化查询语言(Structured Query Language,SQL)注入、跨站脚本攻击(Cross Site Scripting,XSS)注入等攻击[3];另一种是通过分析URL中参数存在的规律,进而枚举所有有效的参数,获取非授权信息[4]。URL保护是针对上述安全问题提出的解决方案。URL保护目标包括信息完整性和信息保密性,完整性解决信息篡改问题,保密性解决信息泄露问题。
目前主流的URL保护方案是设计URL保护算法。URL保护算法采用密码学提供的加密、解密、散列等工具,将这些工具进行一定的组合,形成算法后对URL进行保护。这些密码学工具的构造有很坚实的理论基础,也经过实践检验,因此可靠性很高,能够达到保护URL的目的。URL保护算法的缺点是需要保护密钥,如果密钥泄露,保护算法就形同虚设。此外保护算法在生成URL和检验URL时都要进行大量运算,增加系统开销。针对这些缺点,本文选择从另一个角度出发,设计基于短链接的URL保护模型,完成保护URL完整性和保密性的目的。
目前URL保护算法包括三种:保护完整性(I型)[5]、保护机密性(II型)[6]、同时保护完整性和机密性(III型)[7]。这三种算法中,使用散列函数保证完整性,使用对称加密算法保证机密性。
以III型为例介绍URL保护算法的工作原理。假设该法采用消息摘要算法第5版(Message-Digest Algorithm Version 5,MD5)和高级加密标准(Advanced Encryption Standard,AES)共同保护URL。规定单引号为字符串定界符,单引号之间的字符为字符串内容,加号为字符串拼接运算符,则算法的具体执行过程如下。
(1)将请求参数s1和密钥key1按规定顺序装配成字符串s2=key1+s1;
(2)计算s2的MD5检验和v=MD5(s2);
(3)将检验和v嵌入s1成为新的请求字符串s3=′v=′+v+′&′+s1;
(4)对s3使用密钥key2执行AES加密得到字符串s4=AES(s3,key2);
(5)对s4使用改进base64编码为字符串s5=base64_encode(s4),得到最终URL;
(6)解析过程逆向操作,期间验证检验和,丢弃无效请求。
其工作原理如图1和图2所示。
图1 III型保护算法生成URL过程
图2 III型保护算法解析URL过程
短链接也是一种URL,只是长度非常短,只有几个字符,优点是节省流量,方便生成二维码,移动应用上使用很普遍[8]。本模型使用了短链接,工作原理如图3所示。
图3 基于短链接URL保护模型工作原理
图3中,系统先生成URL,再根据URL在键-键(Key-Key,KK)缓存中查询对应的短链接,如果没有,则使用短链接生成算法,生成一个短链接,建立URL和短链接的映射关系,存入KK缓存,然后将短链接返回给用户。用户访问短链接,系统在KK缓存中查询该短链接对应的URL,如果没有则报错,否则再将URL传给后端业务进一步处理。
根据工作原理,KK缓存是模型核心,实现将URL映射成短链接和将短链接映射成URL的双重功能,要求URL唯一和短链接唯一,属于Key-Key缓存,区别于普通的键值(Key-Value,KV)缓存。KK缓存支持三个操作:存入URL和短链接的映射关系,根据URL获取映射的短链接,根据短链接获取映射的URL。
本模型中,URL和短链接之间的映射关系需要长期维持,避免用户过一段时间再访问短链接就报错,因此这种映射关系需要持久化,例如写入硬盘。随着系统的持续访问,映射关系会越来越多,但其实经常用到的不多,为了在映射数量和可用性之间找到平衡,需要定期清理映射关系,例如采用过期策略,超过一段时间没有访问的映射关系,可以销毁。
短链接使用短链接算法生成。该算法应该基于URL生成短链接。为了保证系统安全,根据短链接很难推测出对应的URL,需要设计安全高效的短链接生成算法,散列函数具有较好的单向性,可以用在生成算法中。为了保密,可以设置密钥,密钥泄漏了也没有关系,可以换一个,对模型的执行和安全性没有任何影响。短链接很短,碰撞概率很高,因此算法需要加盐,例如随机数,万一发生碰撞,可以再生成一个。
短链接只有几个随机字符,不包含任何敏感信息。短链接是随机字符串,假设长度为6,采用26个大小写英文字符和10个数字,则短链接空间大小是626=56 800 235 584≈568亿。合法的短链接最多也就十几万个,只有总空间的万分之一不到,也就是枚举1万个短链接,才有一个可能是合法的。完全遍历短链接空间进行攻击,需要花费很长时间和代价。即使遍历整个空间,由于所有的URL都是合法生成的,造成攻击的的可能性几乎不存在。
本模型和普通的URL保护算法属于两种不同的方案,称采用URL保护算法的方案为基于加密保护URL的算法模型,简称算法模型,称本模型为基于短链接保护URL的映射模型,简称映射模型。映射模型仅在URL和短链接之间进行高速的映射操作,不涉及复杂的加解密算法,理论上性能高于算法模型。算法模型需要保护密钥,一旦密钥泄漏,保护就失效了。映射模型可以设置密钥,但密钥泄漏不影响模型的安全性,安全性要高于算法模型。此外使用短链接也节省传输流量,适合移动互联网应用。
算法模型中,服务器根据URL进行编码和解码,不依赖于其他状态。映射模型中,服务器根据KK缓存中的数据进行编码和解码,依赖于KK缓存。因此本质上,算法模型是无状态模型,映射模型是有状态模型。
KK缓存有多种选型,例如关系型数据库MySQL;非关系型数据库MongoDB;KV数据库Memcache和Redis等。MySQL和MongoDB等数据库可以建立唯一索引,并且本身已具备持久化能力,完全满足KK缓存的要求,唯一的缺点是性能不如KV数据库。Memcache属于纯内存数据库,不具备持久化能力,Memcache基于内存,速度最快,但无法满足KK的唯一性要求,需要改造。Redis的MSETNX命令可以一次设置多个KV,使用MSETNX
表1 KK缓存选型对比
纯内存KK缓存中的数据只保存在内存中,因此速度最快,属于高速缓存,但缺点也明显,一但系统重启或崩溃数据便会丢失,还需从其他地方重新加载,例如和其他可持久型数据库进行合作。纯内存KK缓存重启后,要重新初始化,从后端数据库中加载所有映射关系。系统运行中有新的映射关系建立,KK缓存中存一份,数据库也要存一份。
为了测试各种选型的性能差异,改造Memcache实现纯内存KK缓存。Memcache的add操作在key存在的时候出错返回,该操作最接近KK需求。修改add操作的逻辑,实现Redis MSETNX相同功能,执行两次set,一次是set(key=url,value=短链接),一次是set(key=短链接,value=url),并且任何key存在的时候,都出错返回。后端再配合MySQL数据库,就可以满足KK缓存需求。
短链接生成算法有很多种实现方法,为了测试方便,选用的短链接生成算法伪代码如下:
function ShortText(url,key,rand){
用a-z,0-9,A-Z共62个字符构建字符表chars;
str=md5(rand+key+url);
//字符串连接,输出为128位二进制数据
取str前4个字节,作为32位无符号整数赋值给变量a;
b=0x3fffffff&a;
//将最高2位抹掉,变成30位数
ret=〃;
for(i=0;i<6;i++){
//循环6次
c=b&0x3d;
//限制c在0-62之间
ret=ret+chars[c];
//字符串连接
b=b>>5;
}
return ret;
//返回一个长度为6的字符串
}
由于KK缓存选型和短链接生成算法实现有很多种,为了兼容各种选择,映射模型采用接口的方式实现,这样不管采用什么系统,都可以无缝使用。接口定义如下:
interface Iurlmap
{
public function createShortLink($url);
//根据URL生成短链接
public function createMap($url);
//获取URL映射短链接
public function resolvMap($shortlink);
//获取短链接映射的URL
}
比较算法模型(选用III算法,实现同参考文献[7])和映射模型的性能开销,映射模型中的KK缓存选型包括MySQL、MongoDB、改进Memcache和Redis。在PHP中单机(不经过交换机和路由器)测试,配置是AMD EPYC 7281 16-Core Processor,内存128 GB,操作系统Ubuntu 18.04.3 LTS,PHP 7.2.19-0ubuntu0.18.04.1 (cli,NTS),MySQL 5.7.27-0ubuntu0.18.04.1,MongoDB 3.6.3,Redis 4.0.9,改进Memcached基于1.4.5版本修改。Memcache等服务采用C/S模式访问,网络通信很慢,作为对比,本测试还使用PHP的数组模拟纯内存KK缓存,简称mem。测试项目包括生成URL和解析URL,采用两组不同长度的URL作为输入或输出,分别是25字符和250字符。每组包括2种耗时测试:运行100万次和运行1 000万次,每种测试5次,取耗时均值,耗时单位为秒,测试结果如表2所示。
表2中,L*表示URL长度,例如L25表示URL长度为25字符;R*表示运行次数,例如R100表示运行100万次,T*表示该列测试类型所需的平均时间,例如T1表示URL长度25字符运行100万次所需的平均时间;P1=(T4-T2)×100/T2,统计URL长度增加10倍,耗时增加多少;P2=1 000/T2,统计每秒执行操作次数(Query Per Second,QPS),单位为万/s。从表2可以看出,运行次数增加10倍,所有操作的耗时也增加10倍,耗时与运行次数为线性关系;URL长度增加10倍,算法模型耗时增加50%,而映射模型耗时变化很小,说明算法模型耗时与输入强相关,映射模型耗时与输入弱相关;QPS比较,mem > III型> Memcache > Redis > MySQL > MongoDB,纯内存KK缓存速度比III保护算法快20倍,但C/S模式因为涉及网络通信等IO操作,导致Memcache比III型保护算法慢将近20倍。
表2 算法模型和映射模型的性能测试
保护URL能提高Web应用的安全性,传统基于加密保护URL的算法模型存在处理慢和密钥泄漏问题,本文设计一种基于短链接保护URL的映射模型,详细描述模型的工作原理,通过KK缓存实现URL和短链接的高速转换,保证了安全性和可用性。在探讨了系统实现关键技术后,测试了算法模型和映射模型的性能,结果表明映射模型理论性能比算法模型要高一些,但由于实现的原因,实际性能要低一些。此外映射模型的结构比算法模型复杂,稳定性也要差一点。总体上,映射模型无密钥泄漏问题,节省流量,处理速度也不慢,可以满足大多数Web应用的需求。