对于WEB开发的工程师,需要具备一定的网络安全意识,才能编写出相对更安全的网站。而在前端安全中,XSS漏洞一直是被黑客利用最多的漏洞类型,主要的原因是XSS漏洞检测门槛高、攻击种类多、工程师意识不够强。
我的建议是,作为web开发人员,除了定制代码规范、xss检测体系外,我们还需要构造一些特定账号,这些账号的数据都是具有攻击性的。那么,工程师在项目开发中,一旦写出XSS漏洞,也能测试的时候发现,可以有一定概率避免XSS漏洞产生。
我在工作、生活中,访问一些网站时,本人习惯起的名字比较随意,诸如:
<script>alert(1)</script>
'<script>alert(1)</script>
'"><script>alert(1)</script>
<BODY ONLOAD=alert('XSS')>
由于名字都是具有XSS攻击的,偶尔我会发现某个网站有XSS漏洞。最近在使用公司产品时,就通过这种方法发现了一个漏洞,而这个漏洞点之前被很多人忽视了。
大概是这样的一段代码:
$name = "xiazhibingxue";
?>
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
var name="<?=str_replace('"', '"', $name)?>";
</script>
</head>
</html>
从代码中可以看出,主要是讲name变量赋值给js,而为了避免双引号导致XSS注入,在赋值时将$name进行了双引号转义:
str_replace('"', '\"', $name)
初步看下来,这个代码没有问题。我问了几个工程师,也都觉得没有问题。
那么,我抛出一行代码:
<script>var a="</script>";</script>
这段代码是给变量a赋值,值为"",实际浏览器效果,真的是这样的么?
将这行代码保存为html文件,浏览器打开,进入调试。你会发现js报错误了!!!
SyntaxError: unterminated string literal var a='
明明是一个简单的赋值,为何报错?这是因为,浏览器进行解析html时,会去找javascript代码块,而浏览器寻找这个代码块的工作方式是:
1. 从头遍历代码,找到<script>字符串,从<script>字符串之后,为js脚本的起始位置。
2. 继续遍历,直到找到</script>,为js脚本结束位置。
所以上面那一行代码,浏览器认为的js代码块实际上是:
<script>var a="</script>";</script>
浏览器是不会考虑双引号、字符串这些问题。因为浏览器需要先找js代码块,才能再解析js语法。而工程师先入为主的是语法正确,忽略了代码块切割的问题。
回到最初的项目demo代码,如果我的名字是:
</script><script>alert(1)</script>
攻击就产生了:
<script type="text/javascript">
var name="</script><script>alert(1)</script>";</script>
js被拆成了两个代码块(红色、绿色表示),第二个代码块会让浏览器弹出个警告1。
总结,工程师在xss漏洞防范中,忽视了内联js和外联js的区别。
Leave a Reply