Post-exploitation using Python Standard Libraries

Introduction

Mike LaRoe

Email: mlaroe.bitrot@gmail.com

Let’s go over some fundamental Python standard libraries and how, with those libraries alone, your toolbox during a CTF or red team (or blue!) situation will have many of the answers needed to point you on the path to success. These modules are important because they come naturally with Python installations and do not require any additional installations (which require privilege).

Very often you may only have access to a limited number of programs, and if Python is one of them, you might be golden. If the user group doesn’t allow installing software (hello netcat) you may be able to leverage some libraries to accomplish your goal. Enumeration, pivoting, and potentially privilege escalation are possible from a non-root user.

The Python standard libraries include a multitude of useful modules that can be leveraged to a security enthusiasts advantage. Some of my favorites are sockets, random, crypt, pipes, http, sys, and ctypes. Today we will be talking about the beefy, yet simple os module.

NOTE: This entire series will be based around Python 3 (as it should be, it’s 2018)

Setup

What you will need

A Windows or Linux environment, virtual or not.

Installing Python3 on Windows

Download Python3 for Windows

Installing Python3 on Linux

sudo apt-get install python3

So you have a python shell (Enumeration using the OS module):

Great. You see this:

>>>

Now we’re talking my language! To me that >>> can mean we have a foothold. Let’s play!

>>> import Scryp7k1dd13.py


traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    import Scryptk1dd13
ImportError: No module named 'Scryp7k1dd13'

Awww. Looks like we’ll have to do this ourselves. Personally, I love a good challenge! Let’s get some information about the operating system we are in. We’ll need to import the Python Standard Library that allows us to interact with our operating system for this. Let’s start real simple and go over the very basics of the os module.

>>> import os

The uname or name modules within the os library will identify and return the current operating system. We can call it by os.uname() in linux or os.name() in a windows environment. Try both when going blind.

LINUX

>>> print(os.uname())

The result should be something similar to:

posix.uname_result(sysname='Linux', nodename='potato', release='4.4.0-109-generic', version='#132-Ubuntu SMP Tue Jan 9 19:52:39 UTC 2018', machine='x86_64')

WINDOWS

>>> os.name()

The result should be something similar to:

'nt'

Super user friendly as you can see. But ‘nt’ means we are on a windows system. Let’s try os.system quick, and we’ll come back to it more in depth later. It’s really the heart of the power within the module.

>>> os.system('whoami')
ie8win7\testuser
0

We could also try and venture outside of the os module and use another standard library: platform

>>> import platform

>>> platform.win32_ver()
('7', '6.1.7601', 'SP1', u'Multiprocessor Free')

A good friend pointed out to me that os.name() does not print in Windows 10 and above. This can be worked around with another call from os.system():

>>> sysInfo = 'systeminfo | findstr /C:"OS"'
>>> os.system(sysInfo)

But I digress, back to Linux and the os module:

Linux User and Groups

We can find out what groups and user id are assigned to the current process by using os.getgid() and os.getuid(), respectively. Additionally, we can find the real process id of the current process by using os.getpid(). You can also use os.geteuid() to get the Effective user ID. This is usually irrelevant (until that one time it isn’t, and then it’s very important).

>>> print('gid = ' + str(os.getgid()) + ' uid = ' + str(os.getuid()))

Your result should be:

gid = 1000 uid = 1000

1000 is the first non-root user on the system. This is great! Very often the first non-root user is also an admin of the system! This means privileges (however limited)!

Windows User and Groups

With windows, we have to go straight to os.system and directly use the command line to get anything done with the os module. On the bright side, this returns a lot of useful information for us to have as we collect as data much as possible

>>> os.system('whoami/user')

USER INFORMATION


User Name      SID
============== ==============================================
ie8win7\ieuser S-1-5-21-3463664321-2923530833-3546627382-1000
0
>>> os.system('whoami/groups')

GROUP INFORMATION

group name                                                    type             s
ID                                            Attributes

​============================================================= ================ =
============================================= ==================================
================
​Everyone                                                      Well-known group S
-1-1-0                                        Mandatory group, Enabled by defaul
t, Enabled group
NT AUTHORITY\Local account and member of Administrators group Well-known group S
-1-5-114                                      Group used for deny only

​IE8Win7\HomeUsers                                             Alias            S
-1-5-21-3463664321-2923530833-3546627382-1001 Mandatory group, Enabled by defaul
t, Enabled group
BUILTIN\Administrators                                        Alias            S
-1-5-32-544                                   Group used for deny only

​BUILTIN\Users                                                 Alias            S
-1-5-32-545                                   Mandatory group, Enabled by defaul
t, Enabled group
​NT AUTHORITY\INTERACTIVE                                      Well-known group S
-1-5-4                                        Mandatory group, Enabled by defaul
t, Enabled group
​CONSOLE LOGON                                                 Well-known group S
-1-2-1                                        Mandatory group, Enabled by defaul
t, Enabled group
​NT AUTHORITY\Authenticated Users                              Well-known group S
-1-5-11                                       Mandatory group, Enabled by defaul
t, Enabled group
​NT AUTHORITY\This Organization                                Well-known group S
-1-5-15                                       Mandatory group, Enabled by defaul
t, Enabled group
​NT AUTHORITY\Local account                                    Well-known group S
-1-5-113                                      Mandatory group, Enabled by defaul
t, Enabled group
​LOCAL                                                         Well-known group S
-1-2-0                                        Mandatory group, Enabled by defaul
t, Enabled group
​NT AUTHORITY\NTLM Authentication                              Well-known group S
-1-5-64-10                                    Mandatory group, Enabled by defaul
t, Enabled group
​Mandatory Label\Medium Mandatory Level                        Label            S
-1-16-8192                                    Mandatory group, Enabled by defaul
t, Enabled group
​0
>>> os.system('whoami/priv')

PRIVILEGES INFORMATION

Privilege Name                Description                          State
============================= ==================================== ========
SeShutdownPrivilege           Shut down the system                 Disabled
SeChangeNotifyPrivilege       Bypass traverse checking             Enabled
SeUndockPrivilege             Remove computer from docking station Disabled
SeIncreaseWorkingSetPrivilege Increase a process working set       Disabled
SeTimeZonePrivilege           Change the time zone                 Disabled
0

Current Working Directory

Let’s look at what’s going on in the current working directory. Let’s write a short function using os.walk() and os.cwd() to return all files in the current directory and all files in each child directoy of the current working directory. This could provide some juicy information, or at the very least give us a rough idea of where we are within the system.

for a, b, c in os.walk(os.getcwd()):
    for file in c:
	       print(os.path.join(file, a))

On Linux:

... 
/home/testuser/Documents/Docker
/home/testuser/Documents/Docker
/home/testuser/Documents/Docker

On Windows:

...
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\Scripts
C:\Python27\Tools\versioncheck
C:\Python27\Tools\versioncheck
C:\Python27\Tools\versioncheck
C:\Python27\Tools\versioncheck
C:\Python27\Tools\webchecker
C:\Python27\Tools\webchecker
C:\Python27\Tools\webchecker
C:\Python27\Tools\webchecker
C:\Python27\Tools\webchecker
C:\Python27\Tools\webchecker
C:\Python27\Tools\webchecker

Now some of you more astute readers who practiced along at home may have noticed that the current working directory is determined by the directory you ran python.exe from. This can be influenced in ways that allow you to see a bit more. For instance if you ran Python from C:\Python3\ then you would only be privvy to the details of the Python3 directory, however if you ran Python as .\Python3\python from C:\ then you would have a scrape of the entirety of the C:\ drive. Good times.

Wonderful! On Linux we have been able to gather information about operating system, version, and user/group privilege of the python console, as well as an in-depth view of the Current working directory’s contents!. On Windows we have operating system information, version (as well as which service pack is installed) and the current working directory’s contents. Not bad for starting with only >>>! Now that we have learned some basics of how Python interacts with the operating system of a device, let’s explore using the terminal or command line in a Python shell.

os.system

Now here is where the real power is. This is how we interact with an operating system’s terminal in Python. Windows and Linux commands are used for their respective operating systems. For example, to list all the contents of the current working directory in Linux you would use ls, where as with windows you would use dir. But there are some intricacies to receive the proper feedback as you navigate the command line within a Python shell. Let’s create a blank .txt file in a Linux environment. It’s location will default to the directory you ran Python from.

>>> os.system('> ostest1.txt')

More Enumeration using os.system in a Linux environment

Let’s find out some more info about our Linux environment. Let’s take some common enumeration techniques and execute them in Python. Let’s look at the distribution and version of the system we are on.

$ os.system('cat /etc/issue')
Ubuntu 16.04.3 LTS \n \l

$ os.system('cat /etc/*-release')
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.3 LTS"
NAME="Ubuntu"
VERSION="16.04.3 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.3 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial

I hope you can see where I am going with this. If you can write it in the terminal, you can write it using os.system. As you experiment with this you may notice that some commands do not return any data or information that you would normally see in the terminal. It is true that you could solve this with os.popen(), however this has been deprecated, and since we are top notch men and women, we will do things the correct way, using the subprocess module which will be covered in the next lesson. Additionally, if you choose to play around with this and explore further you may find in Windows that UAC (User Access Control) will present a roadblock. We will cover this as well a little in the next lesson.

comments powered by Disqus