javascript伪协议解析

2024-02-21 17:16:59 浏览数 (1)

前言

首先来介绍一下这个伪协议,JavaScript伪协议最重要的,其实就是可以用来执行js的代码,哪些地方可以用呢,

a标签的href里面,iframe标签的src里面,甚至form标签的action和button的formaction也是可以的

代码语言:javascript复制
<a href=javascript:alert(1)>LLLL</a>
代码语言:javascript复制
<iframe src=javascript:alert(1)></iframe>
代码语言:javascript复制
<form action=javascript:alert(1)>
  <button>submit</button>
</form>

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

危害方式

这里可能会产生这种危害的地方,比如一个网站需要发布一个文章,发文的时候在文中会自动填入一个网址进行嵌入,然后这个功能可能没什么过滤,那么就可以尝试插入javascript伪协议进行xss

代码语言:javascript复制
<iframe src="<?= $youtube_url ?>" width="500" height="300"></iframe>

当然也有可能会进行网址内是否包含正常网站的检查,我们也可以绕过,这里比如会对网址内是否包含youtube.com进行检测,就可以使用javascript:alert(1);console.log('youtube.com')绕过。

正确的方式是检测网址是否为上网址的格式,并且确保是https开头

这里有一个后端存在这种漏洞案列

代码语言:javascript复制
<a href="<?php echo htmlspecialchars($data) ?>">link</a>`

这里虽然将<>";做了编码,但是没办法新增标签,也没办法跳脱引号新增属性,但是攻击者可以插入javascript伪协议

vue中案例:

代码语言:javascript复制
<script setup>
  import { ref } from 'vue'

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

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

如果是跳转登录的话,也会产生这种类型的漏洞

页面重定向一般来说使用

代码语言:javascript复制
const searchParams = new URLSearchParams(location.search)
window.location = searchParams.get('redirect')

问题在于window.location的值也可以是javascript伪协议

这里举一个案例:

这是一个登录页面,

点击登入之后,会出现一个redirectToTarget 的 function ,而这个的源代码是这样

代码语言:javascript复制
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)
}

简单阅读下,就是使用了window.location.href机型重定向,如果登录的网址是https://xxxx/login?target=javascript:alert(1)

那么攻击者就会触发xss,这样如果攻击者抓取input的值,也就是账号密码就会泄露。

防御手法

针对这种类型的攻击,仅仅是将javascript过滤是不行的,因为href的内容是可以进行编码的

比如:

代码语言:javascript复制
<a href="&#106avascript&colon;alert(1)">click me</a>

比较好的判断方式就是只允许http和https开头的字段,而且利用JavaScript去解析url,比如:

代码语言:javascript复制
console.log(new URL('javascript:alert(1)'))
/*
  {
    // ...
    href: "javascript:alert(1)",
    origin: "null",
    pathname: "alert(1)",
    protocol: "javascript:",
  }
*/

这样就可以根据protocol普安段是否合法

这里也会有一个错误的写法

代码语言:javascript复制
console.log(new URL('javascript:alert(1)'))
/*
  {
    // ...
    hostname: "",
    host: "",
    origin: null
  }
*/

当hostname或者host为空,就代表不合法,但是我们可以利用//在JavaScript中注解方式,搭配一个元素看起来像网址,比如:

代码语言:javascript复制
console.log(new URL('javascript://huli.tw/
alert(1)'))

这个在谷歌上没有问题,但是有一些浏览器就会存在问题。

上述这些问题,其实加一个target="_blank"就可以解决大部分问题,只需要重启一个新页面,浏览器会处理好很多问题。

实际案例

这里是一个23年6月telegram的漏洞,网页版中,有一个ensureProtocol函数,负责确认url有没有://,没有的话就加上,

代码语言:javascript复制
export function ensureProtocol(url?: string) {
  if (!url) {
    return undefined;
  }
  return url.includes('://') ? url : `http://${url}`;
}

要绕过就很简单,我们只要加上javascript:alert('://')

但是这里浏览器解析也会分析url是不是合法的网址,而url本来最前面就可以带上账号和木马,中间就是使用:进行分割。像这样:

https://username:password@www.example.com/

因此攻击者发现可以用这样的字符串来绕过

代码语言:javascript复制
javascript:alert@github.com/#://

这里javascript伪装成账号,而alert是密码,后面的hostname是github,后面://进行绕过,虽然前面没有http或者https,但是仍认为合法.

最后搭配url,进行编码,产生出一个密码只有合法的网址

代码语言:javascript复制
javascript:alert('Slonser was here!');//@github.com#;alert(10);://eow5kas78d0wlv0.m.pipedream.net'

解码之后就是

代码语言:javascript复制
javascript:alert('Slonser was here!');//@github.com#;alert(10);://eow5kas78d0wlv0.m.pipedream.net'

这里字符串会被服务器判断为一个链接类型,同时://也逃过检测,攻击者点击就会触发。

0 人点赞