XSS全称Cross Site Scripting(跨站脚本),为了与“CSS”区别,就使用XSS作为简称。 XSS攻击指恶意用户在html中注入含恶意的JavaScript代码或者恶意的HTML代码。在其他用户浏览该页面时,浏览器会直接编译处理所有代码包括恶意代码,从而作出损害用户利益的攻击。 下面通过一个简单的前后端数据交互例子进行叙述,先贴上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 //页面代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>存储型XSS测试</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.0/dist/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous"> <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.0/dist/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script> <style type="text/css"> .demo{ width: 450px; padding: 1.5rem; margin-right: 0; margin-left: 0; } </style> </head> <body> <div class="container"> <div class="demo"> <div class="d-flex justify-content-around mb-3"> <input type="text" class="form-control mr-3" placeholder="输入添加信息"> <button type="button" class="btn btn-primary flex-shrink-0" onclick="addMessage()">添加</button> </div> <div> <table class="table table-bordered"> <thead> <tr> <th>信息</th> </tr> </thead> <tbody></tbody> </table> </div> </div> </div> <script type="text/javascript"> const input=document.querySelector('input') const tbody=document.querySelector('tbody') function getMessage(){ fetch('http://127.0.0.1:9500/message',{mode:'cors'}) .then(res=>res.json()) .then(res=>{ let html=res.reduce((cur,el)=>{ cur+=` <tr> <td>${el}</td> </tr> ` return cur },'') tbody.innerHTML=html }) } getMessage() function addMessage(){ fetch('http://127.0.0.1:9500/message',{ mode:'cors', method:'POST', body:JSON.stringify({message:input.value}), headers: { 'content-type': 'application/json' }, }) .then(()=>getMessage()) } </script> </body> </html>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 //后端代码node.js const express=require('express') const bodyParser = require("body-parser") const app=express() const router=express.Router() const jsonParser = bodyParser.json() let message=['John'] router.get('/',function(req,res){ res.status(200).json(message) }) router.post('/',jsonParser,function(req,res){ message.push(req.body.message) res.status(200).end() }) //中间件解决跨域问题 function cors(req,res,next){ res.header('Access-Control-Allow-Origin','*') res.header('Access-Control-Allow-Headers','Content-Type') res.header('Access-Control-Allow-Methods','PUT,POST,GET,DELETE,OPTIONS') next() } app.use(cors) app.use('/message',router) app.use(function(req,res){ res.status(404).end() }) app.listen(9500,function(){})
交互效果如下: 此时,如果我们插入带恶意的html片段,如:
1 <img src="whatever" onerror=alert('attack')>
因为src中是一个无效链接,加载失败必然会执行onerror中的回调函数,因此则会出现以下效果: 这就是其中一种XSS攻击的原理的呈现。一般恶意用户会通过onerror回调函数插入script如下:
1 <img src="whatever" onerror="javascript:window.el=document.createElement('script'),window.el.src='wrong.js',document.head.appendChild(window.el)">
通过引入来自外部的恶意脚本,在恶意脚本里就可以进行恶意操作,例如:
窃取用户Cookie:document.cookie收集用户cookie或者sessionStorage然后发送到别的服务器里
监听用户行为:通过登陆的键入字符串窃取用户信息
插入恶意广告:插入恶意iframe或者监听鼠标点击跳转页面
**拓展:**有人会问为什么onerror函数中不这么写
1 javascript:document.head.innerHTML+="<script src='wrong.js'></script>"
那是因为HTML5中指定不执行由innerHTML插入的script标签。
2.XSS攻击的分类
1.存储型XSS攻击
开头的例子就是存储型XSS攻击,存储型的攻击主要步骤是:
恶意用户把恶意代码片段提交到服务器的数据库中
普通用户请求网站,网站把包含恶意代码的数据加载从页面中加载出来
恶意代码开始运行
2.反射型XSS攻击
有些页面交互中存在用户输入数据后,页面响应时会原封不动地返回这个数据到页面上。例如…还是先贴代码吧:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 //后端node.js代码 const express=require('express') const app=express() app.get('/main/:keyword',function(req,res){ res.send(`搜索内容:${req.params.keyword}`) }) app.use(function(req,res){ res.status(404).end() }) app.listen(9501)
正常交互效果: 带XSS攻击的交互效果:
3.DOM型XSS攻击
DOM型XSS攻击与反射型XSS攻击类似,都是通过把恶意代码作为参数纳入到url中,诱发用户点击。不过区别在于反射型XSS攻击的页面是通过后端的模板引擎渲染的,而DOM型XSS攻击中的页面是通过前端取出URL中的参数里的恶意代码后,然后通过document.write或者innerHTML等方法渲染到页面上的。
3.XSS攻击预防措施
总结说,一般XSS攻击中注入的恶意代码有两种类型:
在img或者iframe等标签中,后面接着代码,可能以javascript:开头,。
以