diff --git a/cve/Java-SE/2022/CVE-2022-21449/README.md b/cve/Java-SE/2022/CVE-2022-21449/README.md new file mode 100644 index 0000000000000000000000000000000000000000..447b266dbc135e0d3365e5fc53a6c4742b33b6a2 --- /dev/null +++ b/cve/Java-SE/2022/CVE-2022-21449/README.md @@ -0,0 +1,37 @@ +# CVE-2022-21449 + +### Overview + +This tool allows to perform a quick scan of compiled code archives (.jar, .war etc) in order to check for vulnerability to CVE-2022-21449 by looking for the string indicating the use of ECDSA algorithm. The tool uses Python3 with no additional prerequisites. + +##### Usage + +``` +python cve_2022_21449.py root-folder [-quiet] [-exclude folder1 folder2 ..] +``` + +or + +``` +python cve_2022_21449.py root-archive [-quiet] [-exclude folder1 folder2 ..] +``` + +The tool will scan `root_folder` recursively for `.jar` and `.war` files; in each located archive the tool examines the `.class` files for appearances of `"withECDSA"` string. + +With `-quiet` flag, error messages (files not found/ archives failed to open/ password protected archives) are muted. + +Folders appearing after `-exclude` (optional) are skipped. + +##### Output example + + + +### Bash script + +Alternatively, one could use the `cve_2022_21449.sh` Bash script, which is somewhat slower, and requires installing zipgrep tool. + +Usage: + +``` +./cve_2022_21449.sh root-folder +``` diff --git a/cve/Java-SE/2022/CVE-2022-21449/cve_2022_21449.py b/cve/Java-SE/2022/CVE-2022-21449/cve_2022_21449.py new file mode 100644 index 0000000000000000000000000000000000000000..6bb1cff5a43e61abbc664e6764ca48082be41d96 --- /dev/null +++ b/cve/Java-SE/2022/CVE-2022-21449/cve_2022_21449.py @@ -0,0 +1,164 @@ +import os +import sys +from zipfile import BadZipFile, ZipFile +from tarfile import open as tar_open +from tarfile import CompressionError, ReadError +import zlib + + +ZIP_EXTENSIONS = {".jar", ".war", ".sar", ".ear", ".par", ".zip", ".apk"} +TAR_EXTENSIONS = {".tar.gz", ".tar"} + + +def examine_class(rel_path, file_name, content, silent_mode) -> bool: + if b"withECDSA" in content: + print ("In {}/{} potential use of ECDSA - may be vulnerable".format(rel_path, file_name)) + return True + + return False + + +def zip_file(file, rel_path: str, silent_mode: bool) -> bool: + problem_found = False + try: + with ZipFile(file) as jarfile: + for file_name in jarfile.namelist(): + if acceptable_filename(file_name): + with jarfile.open(file_name, "r") as next_file: + problem_found |= test_file( + next_file, os.path.join(rel_path, file_name), silent_mode + ) + continue + if file_name.endswith(".class") and not file_name.endswith( + "module-info.class" + ): + content = jarfile.read(file_name) + problem_found |= examine_class( + rel_path, file_name, content, silent_mode + ) + + # went over all the files in the current layer; draw conclusions + except (IOError, BadZipFile, UnicodeDecodeError, zlib.error, RuntimeError) as e: + if not silent_mode: + print(rel_path + ": " + str(e)) + return problem_found + + +def tar_file(file, rel_path: str, silent_mode: bool) -> bool: + problem_found = False + try: + with tar_open(fileobj=file) as tarfile: + for item in tarfile.getmembers(): + if "../" in item.name: + continue + if item.isfile() and acceptable_filename(item.name): + fileobj = tarfile.extractfile(item) + new_path = rel_path + "/" + item.name + problem_found |= test_file(fileobj, new_path, silent_mode) + + except ( + IOError, + FileExistsError, + CompressionError, + ReadError, + RuntimeError, + UnicodeDecodeError, + zlib.error, + ) as e: + if not silent_mode: + print(rel_path + ": " + str(e)) + return False + return problem_found + + +def test_file(file, rel_path: str, silent_mode: bool) -> bool: + if any(rel_path.endswith(ext) for ext in ZIP_EXTENSIONS): + return zip_file(file, rel_path, silent_mode) + + elif any(rel_path.endswith(ext) for ext in TAR_EXTENSIONS): + return tar_file(file, rel_path, silent_mode) + return False + + +def acceptable_filename(filename: str): + return any(filename.endswith(ext) for ext in ZIP_EXTENSIONS | TAR_EXTENSIONS) + + +def run_scanner(root_dir: str, exclude_dirs, silent_mode: bool) -> bool: + problem_found = False + if os.path.isdir(root_dir): + for directory, dirs, files in os.walk(root_dir, topdown=True): + [ + dirs.remove(excluded_dir) + for excluded_dir in list(dirs) + if os.path.join(directory, excluded_dir) in exclude_dirs + ] + + for filename in files: + if acceptable_filename(filename): + full_path = os.path.join(directory, filename) + rel_path = os.path.relpath(full_path, root_dir) + try: + with open(full_path, "rb") as file: + problem_found |= test_file(file, rel_path, silent_mode) + except FileNotFoundError as fnf_error: + if not silent_mode: + print(fnf_error) + elif os.path.isfile(root_dir): + if acceptable_filename(root_dir): + with open(root_dir, "rb") as file: + if any(root_dir.endswith(ext) for ext in ZIP_EXTENSIONS): + problem_found = zip_file(file, "", silent_mode) + + elif any(root_dir.endswith(ext) for ext in TAR_EXTENSIONS): + problem_found = tar_file(file, "", silent_mode) + return problem_found + + +def print_usage(): + print( + "Usage: " + + sys.argv[0] + + " [-quiet] [-exclude ...]" + ) + print("or: " + sys.argv[0] + " [-quiet]") + exit() + + +def parse_command_line(): + if len(sys.argv) < 2: + print_usage() + + root_dir = sys.argv[1] + exclude_folders = [] + + silent = len(sys.argv) > 2 and sys.argv[2] == "-quiet" + exclude_start = 3 if silent else 2 + if len(sys.argv) > exclude_start: + if not sys.argv[exclude_start] == "-exclude": + print_usage() + exclude_folders = sys.argv[exclude_start + 1 :] + + return root_dir, exclude_folders, silent + + +if __name__ == "__main__": + root_dir, exclude_dirs, silent_mode = parse_command_line() + + for dir_to_check in exclude_dirs: + if not os.path.isdir(dir_to_check): + print(dir_to_check + " is not a directory") + print_usage() + if not os.path.isdir(root_dir) and not ( + os.path.isfile(root_dir) and acceptable_filename(root_dir) + ): + print(root_dir + " is not a directory or an archive") + print_usage() + + print("Scanning " + root_dir) + if exclude_dirs: + print("Excluded: " + ", ".join(exclude_dirs)) + + problem_found = run_scanner(root_dir, set(exclude_dirs), silent_mode) + if problem_found: + sys.exit(1) diff --git a/cve/Java-SE/2022/yaml/CVE-2022-21449.yaml b/cve/Java-SE/2022/yaml/CVE-2022-21449.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b95ffd9b823c26b5f87a682f0d893248b7f496fc --- /dev/null +++ b/cve/Java-SE/2022/yaml/CVE-2022-21449.yaml @@ -0,0 +1,18 @@ +id: CVE-2022-21449 +source: https://github.com/jfrog/jfrog-CVE-2022-21449 +info: + name: Java SE(Java Standard Edition,Java 标准版)是Java技术的核心和基础,是Java ME和Java EE编程的基础。Java SE是Java程序设计语言和Java平台的总称。 + severity: high + description: Oracle Java SE(组件:库)中存在漏洞。易被利用的漏洞允许未经身份验证的攻击者通过多种协议进行网络访问,从而危害Oracle Java SE、Oracle GraalVM Enterprise Edition。成功攻击此漏洞会导致对关键数据或所有Oracle Java SE、Oracle GraalVM Enterprise Edition可访问数据进行未经授权的创建、删除或修改访问。 + scope-of-influence: Oracle Java SE:17.0.2和18;Oracle GraalVM企业版:21.3.1和22.0.0.2 + reference: + - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21449 + - https://security.netapp.com/advisory/ntap-20220429-0006/ + classification: + cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N + cvss-score: 7.5 + cve-id: CVE-2022-21449 + cwe-id: CWE-400 + cnvd-id: None + kve-id: None + tags: cve2022, Java SE, 未经身份验证的访问控制 diff --git a/openkylin_list.yaml b/openkylin_list.yaml index 76b55ee1523e39d3b21a2cffe91e095c91d41365..7fadea34108c06e0e63ac549a1951f6e432324f8 100644 --- a/openkylin_list.yaml +++ b/openkylin_list.yaml @@ -184,3 +184,5 @@ kve: - KVE-2022-0206 kylin-activation: - KVE-2022-0231 + Java-SE: + - CVE-2022-21449