最近在写代码的时候发现的一些很容易被忽视的安全问题。
- 用户修改密码接口:当用户忘记密码然后更新自己得密码的时候,我们的服务端将验证用户和修改用户密码作为两个接口提供到前端,殊不知这样的操作可以直接影响到系统安全。
- 运维监测到公告系统(基于wordpress)经常多了很多来路不明的请求并直接返回了404。
- 短信服务被黑客刷到限额被用完。
下面我们来具体看看这几个漏洞形成的原因和解决方法。首先让我们来回顾一下网络安全的三要素。
- 机密性
- 完整性
- 可用性
1. 常见的攻击方式
- csrf攻击:跨站请求伪造。网站是通过
cookie
来实现登录功能的。而cookie
只要存在浏览器中,那么浏览器在访问这个cookie
的服务器的时候,就会自动的携带cookie
信息到服务器上去。那么这时候就存在一个漏洞了,如果你访问了一个别有用心或病毒网站,这个网站可以在网页源代码中插入js代码,使用js代码给其他服务器发送请求(比如ICBC的转账请求)。那么因为在发送请求的时候,浏览器会自动的把cookie
发送给对应的服务器,这时候相应的服务器(比如ICBC网站),就不知道这个请求是伪造的,就被欺骗过去了。从而达到在用户不知情的情况下,给某个服务器发送了一个请求(比如转账)- 总结:解决方法就是浏览器请求的时候带着一个参数:参数生成的规则和参数名字第三方钓鱼网站无法知道,所以可以隔绝大部分csrf攻击。
- 规范做法:后端通过一些字段(一般在cookie中)加密生成token,然后前端请求带着这个token,后端再验证这个token,这样可以防止百分百的csrf攻击。
- xss攻击:跨站脚本攻击,即CSS。利用网页开发时留下的漏洞(web应用程序对用户的输入过滤不足),巧妙的将恶意的代码注入到网页中,使用户浏览器加载并执行恶意制造的代码,以达到攻击的效果。这恶意的代码通常是JS代码,但实际上也可以是JAVA、VBS、ActiveX、Flash或者是普通的HTML。(浏览器不会判断,只要是符合解析,那么就会执行恶意的代码)。
- 可能存在XSS的地方:微博、留言板、聊天室等收集用户输入的地方都可能遭受XSS攻击的风险。只要你对用户的输入没有严格过滤。
- 攻击条件:1. 需要向WEB页面注入精心构造的恶意代码。2. 对用户的输入没有做过滤或者过滤不严谨,恶意代码能够被浏览器成功执行。
- 验证XSS漏洞存在的一般方法:可以使用script标签来手动检测
- 总结:解决方法就是将数据存到库里得时候,将一些会动态渲染成命令的语言格式化成字符串。
- 规范做法:后端通过一些字段(一般在cookie中)加密生成token,然后前端请求带着这个token,后端再验证这个token,这样可以防止百分百的csrf攻击。开启CSP网页安全政策防止XSS攻击。
- sql注入攻击:是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息
- 总结: 单一的策略并不是最可靠的,需要多种防御策略结合使用,多重防御,提升防御的坚固性
2.当然,文中最开始提到的安全问题都不是由以上三点造成的,具体形成原因出在业务实现层,如下。
- 登陆修改密码验证码的时候,将发送验证码,验证验证码。更改密码分为了三个步骤。
- 发送验证码>验证验证码>修改密码
- 验证验证码>修改密码 (黑客一直刷修改密码)
- 当用户验证完成后 ,黑客可以更改密码
- 解决方法:验证和修改一步进行操作,或者接口参数的上下游进行加密。
- wordpress的网站莫名增加大量的域名请求并报404
- 黑客利用模拟访问路径请求公告网站,如果我们在nginx层没有进行跳转,nginx会报404。
- 黑客通过返回的404可以推测出我们的项目目录结构,然后进行ddos攻击。
- 解决方法: 将这些不正常的请求全部重定向到主页。
- 短信大量被刷
- 用户ip如何获取,因为ip会经过多层代理,所以用请求头里的 remote_addr字段不能准确获取ip,我们利用x-forwarded-for,真实ip就是从外到里的最后一个。
- 获取用户ip代码
- 同一个机器注册大量的账号,然后登陆网站刷短信验证。
- 解决方法: 对用户ip进行限频操作。
/*
* 获取客户端ip
* @return mixed
*/
function get_client_ip(): string {
$client_ip = "";
if (getenv("HTTP_TRUE_CLIENT_IP")) {
$client_ip = getenv("HTTP_TRUE_CLIENT_IP");
} else if (getenv("HTTP_CDN_SRC_IP")) {
$client_ip = getenv("HTTP_CDN_SRC_IP");
} else if (getenv("HTTP_X_FORWARDED_FOR")) {
$client_ip = getenv("HTTP_X_FORWARDED_FOR");
} else if (getenv("REMOTE_ADDR")) {
$client_ip = getenv("REMOTE_ADDR");
}
$client_ip = str_replace(" ", "", $client_ip);
$client_ip_arr = explode(",", $client_ip);
return empty($client_ip_arr[0]) ? '' : $client_ip_arr[0];
}