Recently I discovered yet another malicious package in the PyPI repository. The py-terminal-banner package does a couple of interesting things but most notably it creates a reverse shell.
Details of the py-terminal-banner Package
The py-terminal-banner may be attempting to typo-squat the terminal-banner package hoping that somebody would mistakenly install it instead.
This package have been in the PyPI repository since Nov 8, 2019 and according to pypistats.org, the package was downloaded almost 150 times in the last 6 months but not all those downloads may have resulted in an installation or usage. This package has been reported to the PyPI administrators.
If you have the py-terminal-banner package installed make sure to uninstall it. If you used the generate_banner function of this package there is a change that a reverse shell was opened to your machine (see detailed analysis below). It is impossible to know what was done through the reverse shell, so assume the machine was comprised in some way.
Analysis of the py-terminal-banner Source Code
The py-terminal-banner package contains only 2 python source code files. A ‘banner/__init__.py’ file which doesn’t contain much code and the ‘banner/banner.py’ file which contains the following code.
There is a couple of interesting aspects regarding this package and the source code. The malicious code in the generate_banner function does not seem to get executed automatically (it has to be called explicitly). Since this PyPI package is in the wheel format there is no setup.py file that is executed during installation. While there is no attempt made to obfuscate the malicious code in the generate_banner function. The function does provide some “value” to the user by printing a Chuck Norris joke retrieved from chucknorris.io.
The malicious code starts on line 15 where a sub process is started which opens a socket to an IP address based in Brazil. It then duplicates the necessary file descriptors and start /bin/sh to complete the establishment of a reverse shell.
On line 18 and 20 the code author outputs the ~/.aws/credentials file. The author’s intent may have been to send the content of this file over the reverse shell to the attacker’s server. Regardless, it seems like however wrote this code, might be interested in stealing AWS credentials.
Lastly the code does a HTTPS POST to the same IP address (but different port) that was used for the reverse shell. This POST doesn’t contain data, but the purpose may be to capture the IP address of the victim in a web server log. The POST is using HTTPS and the PyPI package ships its own cert.pem file.
Backend (C&C) Infrastructure
At the time of this analysis the IP address used in the code refused connection attempts on both the reverse shell port as well as the port for the HTTPS POST. This may indicate that this malicious package and the server infrastructure is abandoned, the server side infrastructure may be temporarily offline or incoming connections for some reason are only accepted from specific IP addresses.