这是我参与「第四届青训营 」笔记创作活动的的第16天。
今天接着介绍几种关乎Web安全的问题。
感兴趣的可以看看我之前的文章:红包算法之如何助你抢到大红包 | 青训营笔记 - 掘金 (juejin.cn)
ReDoS
书写不恰当的正则表达式有可能造成redos攻击,攻击者可构造特殊的字符串,导致正则表达式运行会消耗大量的内存和cpu导致服务器资源被耗尽,无法继续响应。
正则表达式
不很懂得可以参考:正则表达式 – 教程 | 菜鸟教程 (runoob.com)
如何攻击
+是重复运算符,可代表某个字符或某个模式的重复。
ba+c //匹配 baaaac
此外,还有另一个重复运算符*。它和+之间唯一的区别是:+代表重复一次多次,*代表重复零次或多次。
ba*c // 将同时匹配 baaaac和bt ba+c // 将匹配baaaac 但不会匹配bc
贪婪匹配和非贪婪匹配
- 贪婪匹配
x.*y表达式如果对字符串axaayaaya进行处理,就会返回xaayaay。
- 非贪婪匹配
通过使用运算符?指定其进行非贪婪匹配,此时表达式为x.*?y
x.?*y表达式如果对字符串axaayaaya进行处理,就会返回xaay。
计算(回溯)
x*y表达式对字符串xxxxxxxxxxxxxx进行匹配,直接就可以看出匹配无结果。
但是计算机的正则表达式引擎会执行以下操作:
xxxxxxxxxxxxxx #不匹配
xxxxxxxxxxxxxx #回溯
xxxxxxxxxxxxx #不匹配
xxxxxxxxxxxxx #回溯
...
x #不匹配
x #回溯
但是这只是第一步!
接下来正则表达式引擎将从第二个x开始匹配,然后是第三个,然后是第四个,依此类推到第14个x。
最终总步骤数为256。
同样,如果你使用非贪婪匹配,x*?y表达式会从一个字母开始匹配,直到尝试过所有的可能,这和贪婪匹配一样愚蠢。
如果两个重复运算符相邻,那么也有可能很脆弱。
表达式: .*\d+.jpg\
Motive: 会匹配任意字符加上数字加上.jpg\
匹配字符串:1111111111111111111111111 (25 chars)\
计算步骤数: 9187
如果两个重复运算符较为相近,也有可能受到攻击。
表达式: .*\d+.*a\
Motive: 会匹配任意字符串加上数字加上任意字符串加上a字符\
匹配字符串: 1111111111111111111111111 (25 chars)\
计算步骤数: 77600
防范
-
降低正则表达式的复杂度, 尽量少用分组
-
严格限制用户输入的字符串长度(特定情况下)
-
使用单元测试、fuzzing 测试保证安全
CSRF
跨站域请求伪造(CSRF,Cross Site Request Forgery)是一种网络攻击方式,它在2007年曾被列为互联网20大安全隐患之一。
CSRF攻击是攻击者借助受害者的cookie骗取服务器的信任,但是攻击者并不能拿到cookie,也看不到cookie的内容。另外,攻击者也无法进行解析服务器返回的结果。
因此,攻击者无法从返回结果中得到任何信息,他只能够给服务器发送请求,执行请求中所包含的命令,在服务器端直接改变数据的值,而非窃取服务器数据。
GET型
如果一个网站某个地方的功能,比如用户修改邮箱是通过GET请求进行修改的。如:
/user.php?id=1&email=123@163.com ,这个链接的意思是用户id=1将邮箱修改为123@163.com。
当我们把这个链接修改为/user.php?id=1&email=abc@163.com,然后通过各种手段发送给被攻击者,诱使被攻击者点击我们的链接,当用户刚好在访问这个网站,他同时又点击了这个链接,那么悲剧发生了。这个用户的邮箱被修改为 abc@163.com 了
POST型
在普通用户的眼中,点击网页->打开试看视频->购买视频是一个很正常的一个流程。可是在攻击者的眼中可以算正常,但又不正常的,当然不正常的情况下,是在开发者安全意识不足所造成的。攻击者在购买处抓到购买时候网站处理购买(扣除)用户余额的地址。比如:/coures/user/handler/123/buy.php 。通过提交表单,buy.php处理购买的信息,这里的123为视频ID。那么攻击者现在构造一个链接,链接中包含以下内容
<form action=/coures/user/handler/25332/buy method=POST>
<input type="text" name="xx" value="xx" />
</form>
<script>
document.forms[0].submit();
</script>
当用户访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作,自动购买了id为25332的视频,从而导致受害者余额扣除。
防范
CSRF 的防御可以从服务端和客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的 CSRF 防御也都在服务端进行。
服务端防御:
- 遵循标准的GET动作
- 为页面增加随机数
- 在非GET请求中增加token并验证
- 验证HTTP Referer 字段
- 在HTTP头中自定义属性并验证
如有不对之处,欢迎指出~