前不久,开发的任务告一段落。后来得知项目中bug比较多,须要去逐一检查修复,苦于没有专业的测试工程师,只好硬着头皮上(以为能学到不少东西),也学会了一些安全测试经常使用软件基本操做,好比Burpsuite、sqlmap等。今天作一些总结吧,以此提醒往后的开发过程当中不只要考虑代码的质量规范等问题,还要注意尽可能减小安全问题的出现,以往只是埋头开发,并不太关注安全问题。因此此次对我来讲收获不小!html
Sql注入(SQL injection)是指攻击者在服务器端构造数据库执行代码能够在服务器中数据库获得执行。因为攻击代码在数据库中执行,根据链接用户的权限,能够读、修改数据库资料甚至执行数据库外部命令,典型的攻击方法为窃取数据库资料、控制操做系统等。前端
使用sqlmap可对url进行SQL注入扫描,进而能攻破DB,获取表信息等,是十分须要咱们开发者关注的问题,可是已经有不少手段能防止SQL注入,最简单的就是使用Mybatis持久框架,同时摒弃声明式注解SQL拼接:好比@Select等注解中的SQL语句可能须要拼接,推荐使用XML编写SQL,尽可能使用#{}参数传入,而不是${}传入nginx
一、增长全局防注入功能,从客户端获取到的参数都必须经过安全校验,防范如下常见攻击字符:web
'|"|>|..|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|script|frame|;|or|-|+|,|)|etc|style|expressionsql
注:对获取的参数进行安全检测以前应首先统一字符编码和大小写,避免攻击者经过编码和大小写混用绕过安全检查。数据库
二、摒弃SQL动态拼接的查询方式,使用参数化查询express
三、采用Mybatis等持久化框架官方推荐的SQL方式进行SQL编写查询后端
与SQL注入相似,SQL注入是注入可执行的SQL代码到数据库服务端,而XSS简单来讲就是注入可执行的具备危害的脚本代码,具体来讲:跨站脚本(Cross-site Scripting简称XSS)是指攻击者输入攻击代码到服务器端,代码在其它用户的浏览器中获得执行。因为攻击代码在受害者的浏览器中执行,能够读、修改和传输任何浏览器能够读取的资料,典型的攻击方法为窃取Cookie、网页重定向等。跨域
每每在页面的一些输入框:浏览器
或者Url中增长后缀或者改写参数为xss脚本代码,如:xxx/name=Lijian&id=123"()%26%25<acx><ScRiPt%20>alert('xss')</ScRiPt>
xxx/serviceid=1%22%3e%3cscript%3ealert(1)%3c%2fscript%3e
采起措施:
一、增长全局防御功能,从客户端获取到的参数都必须经过安全校验,防范常见攻击字符:注:对获取的参数进行安全检测以前应首先统一字符编码和大小写,避免攻击者经过编码和大小写混用绕过安全检查。
二、将获取到的数据进行HTML转码再存入数据库或输出。
三、经过提升Seesion、Cookie等安全(设置HttpOnly,Secure等属性)
1) 加密会话(SSL)缺乏HttpOnly属性
有效防止客户端脚本,好比JS脚本获取Cookie信息而且发送到指定站点提供黑客使用。准确来讲是防止非HTTP协议程序接口获取Cookie(Java后端能够获取Cookies,前端经过Ajax获取)
Java语言设置httpOnly
response.setHeader("Set-Cookie", "cookiename=value;Path=/;Domain=domainvalue;Max-Age=seconds;HTTPOnly");
2) 加密会话(SSL)缺乏Secure属性
若是设置了Secure=true,那么这个cookie只能依靠https协议发送,不能使用http协议。即此时的Cookie是在https时被建立的,若是改成http页面则没法使用Cookie,一般结合httpOnly一块儿配置使用提升Cookie安全
3) 防Cookie伪造
传统的Cookie(name, value)形式,网上流传的是将value值加上保存时间savaTime、自定义密钥、签名等方式
4) 尽可能不要存放敏感信息
不要在Cookie中放userInf等信息,好比手机号码,邮箱等,即便放也要加密!
除了规定高强度的复杂性外,还不能只是简单的MD5加密,网上有不少的MD5解密网站可进行破解
众所周知,前端代码不存在加密,大部分都是可见的,因此在前端开发过程当中尽可能不要留一些隐私敏感信息,好比测试时候用来测试预留的银行卡号等信息应该删除
至少在前端展现的时候用“●●●●”或者“****”代替,而不是直接显示在前端!
如敏感信息App Secret Key
前端中:
而不是:
固然像一些手机号码也须要加解密,好比替换中间的几位数,对中间几位数进行加密隐藏等!
对Session的key值尽可能不要使用简单的userId等,能够再加UUID,或者SessionId
常见登陆页面,当输入用户名以后(还未输入密码进行登陆)可能会返回“用户名不存在”的提示,这样的提示可能会让黑客进行大量的用户枚举破解用户名。咱们应该统一返回“用户名或密码错误”的提示,混淆防止黑客对用户名进行暴力破解。
如常见的密码输入,用户输入的次数超过必定数量后对用户进行暂时锁定或者强制修改密码等;手机验证码输入次数达到上限后,一样进行锁定(时间锁定/操做锁定)
固然登陆页面还会密码还有验证码等的校验,好比注册/登陆页面中每每最后有个输入(手机)验证码的文本框,
像我这样的新手每次都会行云流水,忘情地写代码,自我感受棒棒哒:嗯…..用户输入验证码以后咱们后端要验证验证码是否正确,我要开发一个checkVeriCode验证验证码是否正确的接口,emmmm……..正确就返回true,错误就返回false。而后返回true以后,就能够继续调咱们的/login登陆接口,或者注册/register接口,So easy!超简单(无比膨胀)。
面对本身的ignorance,我只想说:千万不要单独开发验证验证码是否正确的接口,进行调用!千万不要单独开发验证验证码是否正确的接口,进行调用!千万不要单独开发验证验证码是否正确的接口,进行调用!最好就使用一个接口(login接口或者register接口中)将验证验证码环节放到其中,点击注册/登陆按钮以后调用登陆/注册接口,先进行验证码的校验,正确则直接进入登陆/注册保存,错误则提示验证码失败。简单来讲咱们打开F12开发者模式,只能看到一个接口,而不会出现checkVeriCode接口与/login(/register)两个接口,前一个接口影响后一个接口。
总结起来就是咱们在开发埋头苦干忘我地编写代码的时候,尽量减小“多接口强耦合”开发,即后一个接口会受前一个接口返回包影响(这种影响每每是比较重要的),而前一个接口返回包每每很容易被篡改(你说还有比true/fasle更容易被篡改的嘛?)
Request:输入错误的验证码----->调用checkVeriCode--------请求我不拦截你放你走
Response:checkVeriCode接口返回false----->站住你别走,我要拦截你,把你打(改)成true---->好了,你能够走了--->验证码输入正确---->成功破解登陆/注册。
咱们使用Burpsuite中咱们截取校验验证码接口,输入错误的验证码123456
返回false数据包,没有任何问题。这是正确的
下面咱们篡改false为true以后返回到客户端,便可绕过验证码环节
这种邮件/短信轰炸是比较好理解的,黑客获取到相关的接口以后进行返回调用,进而对指定手机号码/邮箱进行轰炸,严重的话邮箱服务器等困难会崩溃。
那么此时咱们简单的就认为那还不简单,对同一个手机号码/邮件进行次数限定不就完了?真的是这样就能够了吗?当时我一开始的时候也是这么想的!当时我想的最简单的作法就是:在规定T时间内每次对同一个手机号码发送验证码后,存入Redis中的次数(有效期T)加1,达到必定数目后,进行“操做频繁提示”。
但其实咱们还忽略了另一个问题,若是攻击者使用同一IP不一样手机号码进行攻击,他的目标再也不是轰炸手机,而是让服务器崩溃,那么咱们仍然要对同一个IP进行次数限制。须要注意的是对方可能使用的是代理IP,咱们还须要检测真实IP,网上有不少检测是不是代理IP,获取真实IP的方法,简单的判断:HTTP头部X-Forward-For第一个IP就是咱们的真实IP。
这个咱们一般负载均衡使用Nginx服务器,有时候错误输入URL可能会跳转到Nginx的错误页面显示404,此时会显示一个Nginx的版本号,或者欢迎页面
1)去除欢迎页面
找到index.html欢迎页面,注释html代码便可。
[open@dcspap01 ~]$ cd /usr/local/nginx/html
2)去除版本号:
第一步:修改nginx.conf,http中增长:server_tokens off
[open@dcspap01 ~]$ cd /home/open [open@dcspap01 ~]$ vi nginx.conf
第二步:编辑fastcgi.conf文件,找到fastcgi_param SERVER SOFTWARE 去掉后面的参数$nginx_version,即隐藏nginx版本号
[open@dcspap01 ~]$ cd /usr/local/nginx [open@dcspap01 ~]$ vi fastcgi.conf
第三步:重启nginx,须要root用户登陆
[open@dcspap01 ~]$ cd /usr/local/nginx/ [open@dcspap01 ~]$ ./nginx -s reload
HTTP 响应头信息中的X-Frame-Options,能够指示浏览器是否应该加载一个 iframe 中的页面。若是服务器响应头信息中没有X-Frame-Options,则该网站存在点击劫持攻击风险。
修改web服务器配置,添加X-Frame-Options响应头。赋值有以下三种:
Java代码:
response.addHeader("x-frame-options","SAMEORIGIN");
Nginx配置:(添加到 'http', 'server' 或者 'location' 的配置中:)
add_header X-Frame-Options SAMEORIGIN
Apache配置:
Header always append X-Frame-Options SAMEORIGIN
OPTIONS方法请求web服务器告知其支持的各类功能。能够询问服务器一般支持哪些方法,或者对某些特殊资源支持哪些方法。若是单独再详细了解OPTIONS的话估计又得一大篇了,搜因此这么简单的总结下:
OPTIONS一般存在于先后端分离的跨域请求中:浏览器自发起一次preflight request(预检请求),以检测实际请求是否安全,这也是黑客一般针对的点,那么咱们后端须要作什么呢,就须要作一些简单的跨域设置,容许部分的HTTP METHOD
response.addHeader("Access-Control-Allow-Origin", "*"); response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS"); response.setHeader("Access-Control-Allow-Headers", "x-requested-with"); response.addHeader("Access-Control-Max-Age", "1800");
启用OPTIONS请求后,返回Allow头,代表后端服务器支持的HTTP方法,有些方法DELETE、HEAD等方法是不必或者不安全的,须要禁止,同时若是服务器不须要支持WebDAV,请务必禁用它,或禁止没必要要的HTTP方法!
1)我不是专业的安全测试,因此提到的问题可能不是很完善,解决办法也可能不是很好,我相信确定有不少的更好的解决办法;
2)在这里我只是想提醒做为菜鸟开发的话不只要关注代码质量,对代码负责。还要对安全问题负责,我认为这才是好的(秃头)程序猿应该全方位考虑到的;
3)“不光还要懂开发懂代码,还要全局掌握一些知识”这是我对本身的要求,这些问题看似简单但据我经从来看,不少开发者都会忽视(我为何还要懂安全问题,我又不是测试)。