前回の記事では、私が個人的にテストしたデモについて書きました。前回、これは xss で成功するために知っておく必要がある非常に重要な知識です。 。 HTML 文字エンティティだけでなく、xss の学習を続けるために理解する必要がある非常に重要な知識はエンコーディングです。そうしないと、特殊文字用のさまざまなフィルターに遭遇したときに、何もできないことがよくあります。この記事は、「答えは b 、質問 2 の答えは c と d」のさまざまなエンコーディングの知識を学ぶことを目的としています。
これら 2 つの質問を読んで、誰もが簡単に正しく答えられ、その理由がわかったら、すぐにこの記事を参照するか、直接閉じてください~~
上記の質問に答えるために、まず次のコーディング関連の知識を勉強しましょう~ ~
よく使われるコーディング
よく使われるコーディングカテゴリーの紹介は他の方のまとめから拝借しました おそらく以下の3種類があり、CSS表現は今はほとんど使われていないのでもちろんCSSコーディングなどもあります。 . これ以上の紹介はありません。
HTML エンティティ エンコーディング、10 進数、16 進数の ASCII コードまたは Unicode 文字エンコーディング。スタイルは「numeric;」です。たとえば、「<」は < としてエンコードできます。
js コーディングには 4 つのカテゴリがあります:
(a) 3 つの 8 進数、足りない場合は前に 0 を追加します。たとえば、「e」は「145」としてエンコードされます
url エンコード、パーセント記号、および 2 桁の 16 進数文字数字の ASCII エンコード。たとえば、「/」の URL エンコードは %2F です。通常 encodeURIComponent と呼ばれるものは、URL エンコーディングです。
上記の紹介を読んで、理解できる人はおそらくそれが何をするのかを知っているでしょうし、理解していない人はおそらく役に立たないと思うでしょう。
簡単なデモを見てみましょう~~
HTMLタグ属性の値では、文字エンティティ相対文字に変換されます。これは、次の 2 つが同等であることを意味します:
<button onclick="javascipt:alert(1);">xss</button><button onclick="javascipt:alert(1);">xss</button>
これは何に使われますか?たとえば、一重引用符や二重引用符などの一部の特殊文字はフィルタリングされますが、 はフィルタリングされません。実際、そのような文字エンティティがあることを知っていれば、あまり注意する必要はありません。は js コーディングですが、それぞれを使用した場合の効果は基本的に同じです。
var body = document.getElementsByTagName('body')[0]; body = '<a href="location.href=\'http://www.baidu.com\'">test</a>'; // 等同于上面那句 body = '<a href="location.href=\'http\u003a//www.baidu.com\'">test</a>';
ここで使用されているのは 3 番目のタイプの js エンコーディング、js の Unicode エンコーディングであり、その他の使用方法は同じです。 : を u003a にエンコードしました。js 実行可能環境に入ると、エンコードされた u003a は : に再解析されます。
xss アプリケーションでフィルタリングをバイパスするためにも使用されます。
URL エンコーディング
複合エンコーディング
ここで説明する複合エンコーディングは、前述のエンコーディングの組み合わせを指し、実際のシナリオで最もよく使用される可能性があります。
簡単なデモを見てみましょう。
var body = document.getElementsByTagName('body')[0]; // test1 // url编码 body = '<a href="location.href=\'http%3A%2F%2Fwww.baidu.com\'">test1</a>'; // test2 // url编码 -> js unicode编码 body = '<a href="location.href=\'http\u00253A\u00252F\u00252Fwww.baidu.com\'">test2</a>'; // test3 // url编码 -> html字符实体编码 body = '<a href="location.href=\'http%3A%2F%2Fwww.baidu.com\'">test3</a>'; // test4 // url编码 -> html字符实体编码 -> js unicode编码 body = '<a href="location.href=\'http\u0026#37;3A%2F%2Fwww.baidu.com\'">test4</a>'; // test5 // url编码 -> js unicode编码 -> html字符实体编码 body = '<a href="location.href=\'http\u00253A\u00252F\u00252Fwww.baidu.com\'">test5</a>'; // test6 // url编码 -> js unicode编码 body = '<a href="location.href=\'http%3A%2F%2Fwww.baidu\u002ecom\'">test6</a>'; // test7 // url编码 -> js unicode编码 -> html字符实体编码 body = '<a href="location.href=\'http%3A%2F%2Fwww.baidu\u002ecom\'">test7</a>';
test1 は URL エンコードのみを実行しました。URL には URL エンコードが存在し、正常にジャンプできることは間違いありません。
test3 では、% を % にエンコードしましたが、それでもスムーズにジャンプできることがわかりました。これはなぜでしょうか。理由も非常に単純で、bodyにaタグを挿入すると、属性にHTMLの文字エンティティが入ったシーンになります。 HTML エンティティのエンコーディングについて説明したときにすでに述べましたが、属性内の HTML エンティティのエンコーディングは dom ツリーのレンダリング中に解析されます。 Chrome デバッガーを開くと、表示される内容は test1 と変わりません。
test4我们在test3的基础上把第一个 & 通过js unicode编码编程 \u0026 ,发现居然还可以跳转!聪明的读者可能一下子就反应过来了,因为在赋值 的这条语句的时候先经过了js可执行环境,然后到dom中,在js可执行环境里 \u0026 被解码出来了,在渲染a标签的时候解码出来的 & 和后面的 #37 拼接起来,被html实体解码成 % ,url跳转的时候被url解码成特定的字符。也就是说整个过程其实经过了 js unicode解码 -> html字符实体解码 -> url解码。
好吧,你告诉我是先经过js环境,再到html,反过来编码肯定挂了吧。看看我们的test5,我们在test2的基础上把第一个 \ 编码成 \ ,果然挂了!!没有正确跳转。然而仔细一看,之所以没有正确跳转是因为这个url被当成相对路径了,跳转出来的路径是 http://192.168.1.100:8848/http%3A//www.baidu.com , 前面那一串ip端口忽略,后面的地址是对的!只不过被当成了相对路径而已。看来test5这种编码顺序也是可以的?
为了验证上面这个疑问,我测试了一下test1 -> test6 -> test7这个编码顺序,不出意外,正常跳转了。
这时候有些读者可能有点凌乱。先html编码和先js编码看来也没啥区别,瞎逼编就好了。
重新理清下思路,其实我举的这个例子非常特殊,不仅用到了三种编码,编码处理的环境也在不断变化。整个解码过程其实分4步,是这样子的:
inner/*防过滤*/HTML 的js可执行环境时候的js解码 ->
dom渲染时的html字符实体解码 ->
location.href 的js可执行环境时候的js解码 ->
url跳转时候的url解码
看完这个解码顺序大家应该都了解为什么先html编码还是先js编码都可以了吧,并不是瞎逼编的= =
回头来看这个题目,如果大家对上面都理解了,估计对这道题目也没有什么疑问。
b为什么是错误的呢,我们来hack它吧~~
看demo:
<div id="test"></div><script type="text/javascript"> var t = document.getElementById('test'); var hash = location.hash.substr(1); t = '<a href="#" id="test" onclick="func('+ hash +')">test</a>'; function func () {}</script>
我们模拟了一个这样的例子,从hash里面作为输入点,然后输出到页面上。首先上面这个没有任何过滤。
我们写了个这样的hash - "onmouseover="alert(1)" 轻松破解
我们简单过滤一下,对单双引号html编码
<div id="test"></div><script type="text/javascript"> var t = document.getElementById('test'); var hash = location.hash.substr(1); hash = hash.replace(/\"/g, '"') .replace(/\'/g, '''); t = '<a href="#" id="test" onclick="func('+ hash +')">test</a>'; function func () {}</script>
刚才的破解方法失效了,那答案b不是对的吗?
那怎么破解?我当时被这个先入为主的思维困扰了好久,其实这边并不一定要老想着去闭合html里面的标签,可以闭合js啊!
我们提交这样一个hash - '+alert(1)+'
成功弹窗!结合html字符实体编码 + onclick里面的js可执行环境,是可以被xss的~
其他选项和题目就留给大家自己思考一下,就不一一解释了,应该并没有太大问题。
好吧,这篇就先到这里了~~
下个月继续安全方面的知识分享。大家清明快乐。。。