免责声明
本文发布的工具和脚本,仅用作测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。
如果任何单位或个人认为该项目的脚本可能涉嫌侵犯其权利,则应及时通知并提供身份证明,所有权证明,我们将在收到认证文件后删除相关内容。
文中所涉及的技术、思路及工具等相关知识仅供安全为目的的学习使用,任何人不得将其应用于非法用途及盈利等目的,间接使用文章中的任何工具、思路及技术,我方对于由此引起的法律后果概不负责。
漏洞描述:
Jenkins 是由Java编写的开源持续集成工具,Remoting 库用来实现控制端和 agent 端之间的通信。
受影响版本中,由于 ClassLoaderProxy#fetchJar 方法未对 agent 端的请求路径进行限制,具有Agent/Connect权限的攻击者可通过 Channel#preloadJar Api读取控制端上任意文件(包括配置文件、密码等)并接管后台,进而在目标服务器远程执行任意代码。
补丁版本限制 Channel#preloadJar 请求只能发送Jar文件,限制 agent 端从控制端主动请求文件修复此漏洞。
影响范围:
jenkins@[2.470, 2.471)
jenkins@[2.462, 2.462.1)
jenkins@[2.452, 2.452.4)
修复方案:
将组件 jenkins 升级至 2.471 及以上版本
将组件 jenkins 升级至 2.462.1 及以上版本
将组件 jenkins 升级至 2.452.4 及以上版本
实测如下:
代码如下:
import requests
import argparse
from packaging import version as packaging_version
def get_jenkins_version(url):
try:
response = requests.get(url)
if 'X-Jenkins' in response.headers:
return response.headers['X-Jenkins']
else:
return None
except requests.RequestException as e:
print(f"Error: {e}")
return None
def is_version_in_range(version, ranges):
v = packaging_version.parse(version)
for start, end in ranges:
if start and end:
if packaging_version.parse(start) <= v < packaging_version.parse(end):
return True
elif start:
if packaging_version.parse(start) <= v:
return True
elif end:
if v < packaging_version.parse(end):
return True
return False
def is_vulnerable(version):
# Define vulnerable version ranges
core_vulnerable_ranges = [
(None, "2.452.4"),
("2.460", "2.462.1"),
("2.470", "2.471")
]
remoting_vulnerable_ranges = [
(None, "3206.3208"),
("3248", "3248.3250"),
("3256", "3256.3258")
]
return is_version_in_range(version, core_vulnerable_ranges) or is_version_in_range(version, remoting_vulnerable_ranges)
def check_vulnerability(url):
version = get_jenkins_version(url)
if version:
if is_vulnerable(version):
return f"[+] {url} (Jenkins Version: {version}) is potentially vulnerable."
else:
return f"[-] {url} (Jenkins Version: {version}) is not in the list of known vulnerable versions."
else:
return f"[-] {url} - Failed to retrieve Jenkins version or Jenkins is not running."
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Check Jenkins instances for known vulnerabilities.")
parser.add_argument("urls", metavar="URL", type=str, nargs="*", help="Jenkins instance URL(s) to check")
parser.add_argument("-f", "--file", type=str, help="File containing Jenkins instance URLs to check")
args = parser.parse_args()
urls = args.urls
if args.file:
try:
with open(args.file, 'r') as file:
file_urls = [line.strip() for line in file if line.strip()]
urls.extend(file_urls)
except Exception as e:
print(f"Error reading file: {e}")
if not urls:
print("No URLs provided. Please provide URLs as arguments or in a file.")
else:
for url in urls:
print(check_vulnerability(url))