Tags: web command_injection php 

Rating: 5.0

# HPNY

**Info**: Get some lucky word or number for your new year! *(http://challenge/?roll=getluckyword)*

La frustración hecha reto. Clickando en el link, solamente se puede ver un mensaje deseando *Feliz Año Nuevo* en algún idioma aleatorio, pero en el caso de acceder sin especificar ningún parámetro, se muestra el código fuente de la página:

```php
50) {
die("bumbadum badum");
}
eval("echo ".$_GET["roll"]."();");
}

?>
```

Como se puede ver, hay dos funciones definidas: `get_lucky_word` y `get_lucky_number`. No parece que haya nada realmente interesante en ninguna, así que las obviaremos. Por otro lado, el código comprueba la existencia del parámetro `roll` y si éste contiene solamente valores alfabéticos y algunos símbolos admitidos. Además, también valida que la longitud del valor sea menor o igual que 50 caracteres.

La parte interesante viene después:

```php
eval( "echo " . $_GET["roll"] . "();" );
```

Claramente aquí se encuentra la vulnerabilidad.

Vemos que lo que le pasemos como valor al parámetro *roll* se va a evaluar como una función. Es por eso que si escribimos `get_lucky_word` nos devuelve una felicitación aleatoria.
Para probar si existe la vulnerabilidad, se puede escribir la función `phpinfo` y esperar que devuelva un resultado:

![phpinfo](https://miro.medium.com/max/700/1*Ql6HRKT9qkWF73YdK_WDJg.png)

*Voilà!* Muestra exactamente lo que se esperaba. La idea ahora es buscar dónde puede estar la flag escondida...

El primer paso es listar el directorio en el que nos encontramos, pero no va a ser posible usar `scandir(".")`, dado que las comillas no están permitidas. Aún así, la solución es simple: podemos usar variables globales como `__DIR__` o funciones como `getcwd` para resolver el problema. Pero también sucede que `scandir` devuelve un Array, y no es posible renderizarlo en el navegador, así que lo suyo será englobar todo dentro de funciones como `var_dump` o `print_r`:

![scandir](https://miro.medium.com/max/620/1*88fOQv1IMv7hMo0D2RCODA.png)
> Comando: *?roll=print_r(scandir(getcwd()))*

La frustración y los problemas comienzan al intentar leer el archivo. Para utilizar comandos como `readfile` o `show_source` es necesario especificar el nombre del fichero, pero habría que usar comillas y además éste contiene un número (caracter que no tenemos permitido).

Entonces, ¿cómo lo resolvemos?

Una solución, y posiblemente la más sencilla, es aprovechar el resultado del script anterior para concatenarlo con una lectura de archivos. Podemos darle la vuelta al array con `array_reverse` y obtener al segundo índice con `next`.

![flag](https://miro.medium.com/max/700/1*XWwWuzftQao_5DTU5U023g.png)

**¡Ahí está la flag!**

_

Para ser sinceros, esta no es la solución a la que yo llegué. Mi aproximación fue algo diferente.

Ya que existen funciones como `getallheaders`, pasé como cabecera el nombre del archivo y lo obtuve usando `array_pop`. Distinta solución al mismo reto:

![curl](https://miro.medium.com/max/700/1*tQEQTsuM_Q3695ewxB7hCQ.png)

Original writeup (https://kikefontan.medium.com/tetctf-2021-1430c27c1143).