作者:leveryd
本文為作者投稿,Seebug Paper 期待你的分享,凡經采用即有禮品相送!
投稿郵箱:paper@seebug.org

背景

看過從shiro-550漏洞品阿里云waf規則引擎文章的,應該知道阿里云是怎么防護shiro反序列化漏洞的利用,那么我們有辦法繞過防護么?

先把上面的問題放一放,看看幾個base64解碼相關的case吧。

base64解碼時,不同語言的接口實現有略微區別,目前知道有兩種"邊界情況":

  • 字符串中包含 . % 等符號時,是選擇忽略這些符號,還是報錯
  • 字符串中包含 = 符號,解析到=時,是認為解析完成了,還是忽略"等號"繼續解析

比如: Python base64解碼時,會忽略"="號后面的字符串

import binascii
binascii.a2b_base64(b'aGVsbG8=')       # b'hello' (valid)
binascii.a2b_base64(b'aGVsbG8==')      # b'hello' (ignoring data)
binascii.a2b_base64(b'aGVsbG8=python') # b'hello' (ignoring data)

PHP base64解碼時,支持編碼中有. % 等符號,會忽略這些符號

P.HNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==
P%HNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==

我也是從別人給Python提交的這個bug 學到的一些姿勢。

所以,我想研究以下問題:

  • 哪些語言受影響?
  • 會有什么影響?
  • 什么時候會產生繞過?
  • 哪些waf可以繞過?

哪些語言受影響?

  • 測試思路

有兩個兩個測試目標:

  1. 看看"不同語言 對 == 后面是否忽略"
  2. 看看"不同語言 對 . 號是否忽略"

因此,對hellobase64編碼并做點變形,得到下面三個測試paylaod

  aGVsbG8=test
  aGVs.bG8
  aGVs.bG8=

另外額外測一下shiro中base64的解碼

  • 測試的語言、版本、解碼接口如下
  php(7.3.11): base64_decode

  python(3.7): binascii.a2b_base64、base64.b64decode

  openresty(1.19): ngx.base64.decode_base64url

  java(jshell 14.0.1): Base64.getDecoder().decode

  shiro(1.5.1): org.apache.shiro.codec.Base64.decode
  • 測試結果
payload php python openresty java shiro
aGVsbG8=test hello-z? hello hello 拋異常 hello-z?
aGVs.bG8 hello 解碼失敗 解碼失敗 拋異常 hel
aGVs.bG8= hello hello 解碼失敗 拋異常 hello
aGVsbG8= hello hello hello hello hello
  • 結論

  • php、python、openresty、shiro 都不同程度地受變形payload影響

會有什么影響?

  • 什么時候適用這種繞過方式?

以下情況下會存在繞過:

  1. waf不能解碼,后端可以解碼
  2. waf解碼后,只檢測解碼后的數據,不檢測原始payload

第一種情況的例子:比如發送 PHN.jcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==,如果waf不能解碼,就會放行。

第二種情況的例子:發送a=aGVsbG8=' union select 1 and ',有可能waf解碼成 "hello",認為沒有危害,也會放行

第一種情況很常見,第二種情況目前還沒有遇到案例。

  • 哪些waf可以繞過?

只測試了我心中的"最強王者"(阿里云waf和長亭云waf),都存在第一種情況的繞過。

規范

  • 規范中是怎么定義"base64解碼時對非字母如何處理"?

rfc規范 中說的是,"沒有特殊情況下,遇到非字母就應該報錯并拒絕繼續解碼"。

官方文檔 shiro 是根據另外一個郵件相關的規范來做的base64編解碼。

最后

所以,現在你清楚怎么繞過shiro漏洞的防護了么?

另外,如果讀者有第二種情況繞過的案例,歡迎公眾號后臺私信我。


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1600/