2.Javascript伪协议
where
href:
<a href=javascript:alert(1)>Link</a>
iframe:
<iframe src=javascript:alert(1)></iframe>
form的action
button的formaction
windows.location
例子1:插入youtube视频
如果網站上有個功能可以讓使用者在發文時填入 YouTube 影片網址,並且在文章中自動嵌入
javascript:alert(1);
绕过对youtube.com的检查:
javascript:alert(1);console.log('youtube.com')
防御:正確方式是檢查網址是否為 YouTube 影片的格式,並且要確保網址是以
https://
開頭
例子2:profile 頁面填入自己的 blog
后端代码
儘管把 <>";
都做了編碼,沒辦法新增標籤,也沒辦法跳脫雙引號新增屬性,但攻擊者依舊可以插入 javascript:alert(1)
,因為這裡面完全沒有任何不合法的字元。
例3:
<a href="<?php echo htmlspecialchars($data) ?>">link</a>
React
現在的前端框架基本上都會自動幫你做好跳脫,沒有在 React 裡面使用 dangerouslySetInnerHTML
或是在 Vue 裡面使用 v-html
的話,基本上都是沒什麼問題的,但是 href
就不同了,理由同上,它的內容是沒問題的。
\ React 在 v16.9 的時候有針對這個行為新增警告,在文件裡面也有說明:Deprecating javascript: URLs,警告的內容是:
Warning: A future version of React will block javascript: URLs as a security precaution. Use event handlers instead if you can. If you need to generate unsafe HTML try using dangerouslySetInnerHTML instead.
在 React GitHub 的 issue 裡面也有更多的討論:
Vue
URL Injection 如果要在前端處理的話,有提到可以用 sanitize-url 這一套 library。
页面跳转
payload:
例子:
在拿到 target 之後直接使用了:window.location.href = decodeURIComponent(target)
來做重新導向。而 getTarget
其實就是去 query string 把 target 的值拿出來。所以如果登入的網址是:https://matters.news/login?target=javascript:alert(1)
,在使用者按下登入並且成功之後,就會跳出一個 alert,觸發 XSS!
javascript
过滤
javascript
过滤HTML 裡面的屬性內容是可以經過編碼的 <a href="javascript:alert(1)">click me</a>
<a href=JavaScript:alert(1)>clickme</a>
http://
验证
http://
验证javascript:alert(http://)
防御
只允許
http://
跟https://
開頭的字串利用 JavaScript 去解析 URL,根据 protocol 判斷是否為合法的協議,來阻擋名單之外的內容
target="_blank"
在Chrome 当你点了连结时,会新开一个网址为的about:blank#blocked
分页,在Firefox 会新开一个没有网址的分页,在Safari 则是什么事情都不会发生,在这三个桌面浏览器上都不会执行JavaScript。
补充
而有个常见的错误判断方式一样会利用URL 来解析,但却是看hostname 或是origin 等等:
当hostname
或是host
为空的时候,就代表是不合法的网址。这样的方式虽然乍看之下没问题,但我们可以利用//
在JavaScript 中是注解的特性,搭配换行字元来做出一个看起来像网址,但其实是javascript: 伪协议的字串:
虽然看起来很像网址,但是在Chrome 上面没有问题,不会误判,可是Safari 就不同了,同样的程式码在Safari 16.3 上面执行,输出结果是:
链接
The curious case of XSS and the mouse middle button. Anchor Tag XSS Exploitation in Firefox with Target=”_blank”
Last updated