一个不小心自己留下了XSS漏洞
无论用户传递了何种参数到网页上, 都不要直接显示, 最好与服务端交互一次, 最次也要在js中全部转义, 永远不要直接渲染.
TL;DR
基本需求
我们在网页上查看商品时, 有可能只是看到一个名字, 而后我们想要点击详情, 在新的页面就可以看到详细信息.
我的偷懒
因为我在写程序时, 首页其实已经请求了详细信息, 只是显示一部分而已, 如果把这 一部分信息继续加载到详情页面, 就可以省一次到后端的请求. 也就是说, 当前页面中的 内容要传递到下一个页面中.
我参考了html页面跳转传递参数中的方式. 将页面中的内容编码, 传递到下一个 页面中, JS代码如下:
1 | // index.js |
点击按钮后, 请求的链接大概是这样的: http://127.0.0.1:8000/detail.html?info=eyJuYW1lIjoiYSBnb29kIiwicHJpY2UiOjIxLCJkZXNjIjoiYSBnb29kIG9ubHkgdXNlIHRvIHRlc3QifQ==
而后在detail.html
中, 设法将参数取出, 就像下面这样:
1 | // detail.js |
然后, 渲染到页面上只是很简单的一件事情了.
上述的代码放在Github仓库中, 可以自行查看.
我在示例代码中做了简化, 首页只显示某个商品名称, 点击detail按钮后, 跳转的页面 可以显示详细的信息.
假如用户分享了链接, 他就需要把那么长的一串url分享给别人, 别人也可以通过 点击链接获取的商品信息, 这是皆大欢喜的事情, 为什么为有漏洞呢?
如何注入
将信息编码之后传递, 的确是一件省事的事情, 但是假如有黑客将URL修改了呢. 我们根本无法分享链接的传播. 当我们知道了网页的渲染方式之后, 就可以简单的 进行注入了.
假如我们要传递的商品信息换成了下面这种.
1 | let xss_data = { |
编码之后, 把info的信息替换掉, 再次请求网页.
http://127.0.0.1:8000/detail.html?info=eyJkYXRhIjoiQ29tbWVudCM+PGltZyBzcmM9eCBvbmVycm9yPWFsZXJ0KDEpLy8+In0=
alert(1)
就开始工作了, 也就意味着, 你可以写任何形式的js代码在网页上工作了.
假如有心人篡改了url, 将其注入自己的脚本, 可以轻松的获取到cookie
(只要他带上cookie向自己的服务器发送一次请求就好).
有关XSS注入我并不是很精通, 参考了这个网站xss-bypass的注入方式.
总结
我们绝对不能贪图省事, 将URL中存在的信息直接渲染到HTML上, 即使你将自己真正的 信息加密了, 由于JavaScript的运行也是在用户一侧, 黑客可以有各种方式撩爆你的JS. 然后加入自己想要的任何脚本, 而你将会眼睁睁看着自己的用户点那些不该点的链接.