Detecting CUPS Vulnerabilities: CVE-2024–47076, CVE-2024–47175, CVE-2024–47176 CVE-2024–47177

vsociety
4 min readOct 9, 2024

--

by@alchemist

CVE-2024–47177 9 Critical Severity

  1. import subprocess
  2. import re
  3. def check_package_version(package_name):
  4. try:
  5. result = subprocess.run([‘dpkg-query’, ‘-W’, ‘-f=${Version}’, package_name],stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  6. version = result.stdout.decode(‘utf-8’).strip()
  7. if result.returncode == 0:
  8. return version
  9. else:
  10. return None
  11. except Exception as e:
  12. print(f”Error checking {package_name}: {e}”)
  13. return None
  14. def check_service_status(service_name):
  15. try:
  16. result = subprocess.run([‘systemctl’, ‘is-active’, service_name],stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  17. status = result.stdout.decode(‘utf-8’).strip()
  18. return status == ‘active’
  19. except Exception as e:
  20. print(f”Error checking {service_name}: {e}”)
  21. return False
  22. def check_udp_port_631():
  23. try:
  24. result = subprocess.run([‘ss’, ‘-uln’], stdout=subprocess.PIPE)
  25. output = result.stdout.decode(‘utf-8’)
  26. return ‘631’ in output
  27. except Exception as e:
  28. print(f”Error checking UDP port 631: {e}”)
  29. return False
  30. vulnerable_versions = {
  31. ‘libcupsfilters’: ‘2.1b1’,
  32. ‘libppd’: ‘2.1b1’,
  33. ‘cups-filters’: ‘2.0.1’,
  34. }
  35. def compare_versions(installed_version, vulnerable_version):
  36. installed_parts = list(map(int, re.split(r’[.-]’, installed_version)))
  37. vulnerable_parts = list(map(int, re.split(r’[.-]’, vulnerable_version)))
  38. return installed_parts <= vulnerable_parts
  39. def check_vulnerabilities():
  40. libcupsfilters_version = check_package_version(‘libcupsfilters’)
  41. if libcupsfilters_version and compare_versions(libcupsfilters_version,
  42. vulnerable_versions[‘libcupsfilters’]):
  43. print(f”Vulnerable libcupsfilters version detected: {libcupsfilters_version}”)
  44. else:
  45. print(“libcupsfilters is not vulnerable or not installed.”)
  46. libppd_version = check_package_version(‘libppd’)
  47. if libppd_version and compare_versions(libppd_version,vulnerable_versions[‘libppd’]):
  48. print(f”Vulnerable libppd version detected: {libppd_version}”)
  49. else:
  50. print(“libppd is not vulnerable or not installed.”)
  51. cups_filters_version = check_package_version(‘cups-filters’)
  52. if cups_filters_version and compare_versions(cups_filters_version,
  53. vulnerable_versions[‘cups-filters’]):
  54. print(f”Vulnerable cups-filters version detected: {cups_filters_version}”)
  55. else:
  56. print(“cups-filters is not vulnerable or not installed.”)
  57. if check_service_status(‘cups-browsed’):
  58. print(“cups-browsed service is running, system may be vulnerable.”)
  59. else:
  60. print(“cups-browsed service is not running, system is less likely to be vulnerable.”)
  61. if check_udp_port_631():
  62. print(“UDP port 631 is exposed, system may be vulnerable.”)
  63. else:
  64. print(“UDP port 631 is not exposed, system is less likely to be vulnerable.”)
  65. if __name__ == “__main__”:
  66. check_vulnerabilities()

Detecting CUPS Vulnerabilities: CVE-2024–47076, CVE-2024–47175, CVE-2024–47176 CVE-2024–47177

  1. import subprocess
  2. import re
  3. def check_package_version(package_name):
  4. try:
  5. result = subprocess.run([‘dpkg-query’, ‘-W’, ‘-f=${Version}’, package_name],stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  6. version = result.stdout.decode(‘utf-8’).strip()
  7. if result.returncode == 0:
  8. return version
  9. else:
  10. return None
  11. except Exception as e:
  12. print(f”Error checking {package_name}: {e}”)
  13. return None
  14. def check_service_status(service_name):
  15. try:
  16. result = subprocess.run([‘systemctl’, ‘is-active’, service_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  17. status = result.stdout.decode(‘utf-8’).strip()
  18. return status == ‘active’
  19. except Exception as e:
  20. print(f”Error checking {service_name}: {e}”)
  21. return False
  22. def check_udp_port_631():
  23. try:
  24. result = subprocess.run([‘ss’, ‘-uln’], stdout=subprocess.PIPE)
  25. output = result.stdout.decode(‘utf-8’)
  26. return ‘631’ in output
  27. except Exception as e:
  28. print(f”Error checking UDP port 631: {e}”)
  29. return False
  30. vulnerable_versions = {
  31. ‘libcupsfilters’: ‘2.1b1’,
  32. ‘libppd’: ‘2.1b1’,
  33. ‘cups-filters’: ‘2.0.1’,
  34. }
  35. def compare_versions(installed_version, vulnerable_version):
  36. installed_parts = list(map(int, re.split(r’[.-]’, installed_version)))
  37. vulnerable_parts = list(map(int, re.split(r’[.-]’, vulnerable_version)))
  38. return installed_parts <= vulnerable_parts
  39. def check_vulnerabilities():
  40. libcupsfilters_version = check_package_version(‘libcupsfilters’)
  41. if libcupsfilters_version and compare_versions(libcupsfilters_version, vulnerable_versions[‘libcupsfilters’]):
  42. print(f”Vulnerable libcupsfilters version detected: {libcupsfilters_version}”)
  43. else:
  44. print(“libcupsfilters is not vulnerable or not installed.”)
  45. libppd_version = check_package_version(‘libppd’)
  46. if libppd_version and compare_versions(libppd_version, vulnerable_versions[‘libppd’]):
  47. print(f”Vulnerable libppd version detected: {libppd_version}”)
  48. else:
  49. print(“libppd is not vulnerable or not installed.”)
  50. cups_filters_version = check_package_version(‘cups-filters’)
  51. if cups_filters_version and compare_versions(cups_filters_version, vulnerable_versions[‘cups-filters’]):
  52. print(f”Vulnerable cups-filters version detected: {cups_filters_version}”)
  53. else:
  54. print(“cups-filters is not vulnerable or not installed.”)
  55. if check_service_status(‘cups-browsed’):
  56. print(“cups-browsed service is running, system may be vulnerable.”)
  57. else:
  58. print(“cups-browsed service is not running, system is less likely to be vulnerable.”)
  59. if check_udp_port_631():
  60. print(“UDP port 631 is exposed, system may be vulnerable.”)
  61. else:
  62. print(“UDP port 631 is not exposed, system is less likely to be vulnerable.”)
  63. if __name__ == “__main__”:
  64. check_vulnerabilities()
  65. python3 CVE-2024–47177-xdetection.py

Introduction

In September 2024, several critical vulnerabilities were discovered in the Common UNIX Printing System (CUPS), affecting nearly all UNIX-like operating systems, including Linux distributions. These vulnerabilities, tracked as CVE-2024–47076, CVE-2024–47175, CVE-2024–47176, and CVE-2024–47177, expose systems to potential Remote Code Execution (RCE) attacks, enabling attackers to gain unauthorized access and execute malicious code remotely.

Brief Overview of the CVEs

  1. CVE-2024–47076: This vulnerability resides in the libcupsfilters library, where IPP attributes from an IPP server are not properly sanitized. This can result in attacker-controlled data being injected into the CUPS system, enabling remote exploitation.
  2. CVE-2024–47175: In the libppd library, improper validation and sanitization of IPP data can lead to malicious data being injected into PostScript Printer Description (PPD) files, opening the system to attacks.
  3. CVE-2024–47176: The cups-browsed service binds to the unrestricted IP address INADDR_ANY on UDP port 631. This flaw allows any packet from any source to trigger an attacker-controlled IPP request, leading to potential exploitation.
  4. CVE-2024–47177: Found in the cups-filters component, this vulnerability allows arbitrary command execution through the FoomaticRIPCommandLine PPD parameter, leading to remote code execution when a print job is initiated.

The Detection Script:

To help system administrators detect if their systems are vulnerable, I’ve created a Python-based detection script. This script checks for vulnerable versions of libraries like libcupsfilters, libppd, and cups-filters, as well as the status of the cups-browsed service and whether the vulnerable port (UDP 631) is exposed.

How the Detection Script Works:

  • Library Version Checks: It queries the system to check if vulnerable versions of libcupsfilters, libppd, and cups-filters are installed.
  • Service Status Check: It verifies if the cups-browsed service is running, which is necessary for some vulnerabilities to be exploited.
  • Port Exposure: It checks if UDP port 631 is open, which could allow an attacker to communicate with the service remotely.

Running the Script

  • Prerequisites: This script is designed for Debian-based Linux distributions (like Ubuntu). It uses dpkg-query to check package versions. Modify it for Red Hat-based systems by using rpm or dnf.
  • Execution: Save the script as detection.py and run it with Python 3 (sudo python3 detection.py).

Conclusion

By using this detection script, system administrators can identify whether their systems are vulnerable to these recent CUPS exploits. While the vulnerabilities are serious, mitigations such as disabling the cups-browsed service and blocking UDP port 631 can significantly reduce the attack surface until patches are available. It’s essential to stay informed and apply patches as soon as vendors release them to ensure system security.

--

--

vsociety
vsociety

Written by vsociety

vsociety is a community centered around vulnerability research

No responses yet