OSCP Preperation 3


There were a few awesome tips and tricks I learned over the last week, primarily dealing with Python and sudo access. Full disclosure, I don’t write Python 2. The reason is that Python 3 has been out for 10 years and Python 2’s EOL is in 2020. It’s still important to understand the Python’isms but, I prefer 3. The examples below should work for both Python2 and 3. The topics we’re going to touch on today are:

  1. Pip Install – Arbitrary Code Execution
  2. Python Library Manipulation Local Code Execution


Pip Arbitrary Code Execution:

Okay, the hypothetical situation here is that you have sudo access to pip install as a standard user. This assumes that if sudo requires the user’s password you have it, or that sudo does not require a password at all.  The question is, how can we abuse this to obtain information otherwise inaccessible.

There’s no way to issue commands via the pip CLI tool itself like other common Linux tools. However, if we put our dev hats on for a bit, we know that python packages are more complex and require a setup of sorts for a proper install. In our case, we can generate our own “Fake” python package using python setuptools along with the command.develop class.

First, create a directory for your package. I’m calling mine fake_package.

Second, generate setup.py as seen below:

This code will reside within a python file called setup.py and is required for any python package as it is one of the first things pip will look for once you run the pip install command.

We can then compile the package with the following command:

After the successful build, we can then attempt to install it using sudo pip install:

We were able to pull the shadow file with no issues. How about a reverse shell?

Pip Install Reverse Shell

And there we have it. A full root reverse shell via Pip Arbitrary Code Execution.


Python Library Manipulation for Local Code Execution:

Okay, another fun and hypothetical situation. You have access to a python script and such access requires you to have sudo permissions to the script. You’re unable to edit the script but you can sure as hell execute and read it. Where does this leave you as far as privilege escalation is concerned?

Well, to answer that question you need to figure out what is the script doing and how is it doing it. Let’s take a look at an example program I wrote:

In this simple program, we’ve defined a hello function that does two things. First, it prints Hello Internet and secondly, it prints the path of the urllib python library. Let’s take a look at the script’s output:

Python 2:

Python 3:

The output successfully prints the Hello Internet string and the path of the urllib library. The locations of the library are different subject to the python version, which is to be expected. For more on how Python looks up its libraries, read this awesome post by Lee On Coding.

One thing people overlook but, most of us who have programmed Python for a living have experienced, is that Python will look in the current working directory (most times) before running to the default library path. What does this mean? Well, we could possibly load a malicious library by adding in our own “Fake Library” within the current working directory.

Let’s take a look at how this all works (Works for both Python2 and Python3).

  1. Taking a look at the file permissions. We can see root owns the Python Program and we are unable to edit the file.
  2. Looking at our sudo permissions, we can see we have sudo access to the file and any python version to run it.
  3. When we run the program with sudo rights we obtain the same information as before:
  4. We know the program is importing the urllib library. Let’s see if we can manipulate it by adding our own urllib.py to the current working directory.

    And when we run the program again we get the following output:

    Evil urllib

Two things have changed in the output. First, we were able to print a message via an echo system command through our fake urllib.py. Second, the path for the urllib.py has changed to our current working directory. So, what if we wanted to pop a reverse root shell? Easy, we change the script to the following and re-run the python program while we have a netcat lister up and running:

run the program and we get a root shell:

Root Shell


I do have a bunch more that was learned over the last week but that would make this post a bit lengthy. I’ll hold off and maybe do a second post this week regard MySQL one liners for DB enumeration and using wget with HTTP’s Post.

No Comments

Post a Comment