Seguridad

Level_Up!: El WriteUp del reto «Origin» y un nuevo reto «Guess my number»

En el equipo de IdeasLocas seguimos con el objetivo de publicar un nuevo reto en nuestra plataforma de retos de Web3 llamada Level_Up!. Por esta razón, hoy traemos dos cosas, un nuevo WriteUp para el reto número 5, el reto Origin, y un nuevo reto, el cual será el 14 denominado «Guess my number». Es decir, hoy traemos dos cosas en un sólo artículo.

Figura 1: Level_Up!: El WriteUp del reto «Origin»
y un nuevo reto «Guess my number»

Comenzaremos hablando sobre el reto «Origin«, el cual tiene una dificultad de 3 sobre 5. Aunque la dificultad, podemos decir que es media, veremos que hay que utilizar algunos conceptos para la solución que puede ser no tan sencillo de primeras, sobretodo si no hemos visto estos conceptos a priori.


El reto Origin, el cual trataremos en el writeup, permite al usuario trabajar el concepto de vulnerabilidades asociadas a phishing o engaños, así como vulnerabilidades que nos penalizan los controles de autorización incorrectos o utilizar mecanismos no recomendables. Ya hemos hablado sobre estos conceptos en este artículo del blog sobre tx.origin y ataques de phishing.


WriteUp del Reto «Origin»

El reto como siempre muestra una serie de pasos y tiene como objetivo trabajar sobre una vulnerabilidad que tiene el contrato. En uno de los pasos se nos dice que nos fijemos en la función transfer. Esta función recibe una dirección a la que se puede enviar fondos o se quiere enviar fondos y una cantidad de fondos a transferir.

Revisando la función de transfer podemos ver que el require solicita que el tx.origin sea igual al owner del contrato. Esto quiere decir que el que origina la transacción debe ser igual al owner. Si pasamos ese require la variable winner pasaría a valer el valor del msg.sender.

Figura 3: Función «transfer»

Aquí hay dos cosas, diferencia entre msg.sender y tx.origin y por qué importa colocarse cómo winner. Vamos a empezar viendo la variable winner. Si se revisa la función getFlag() se puede ver que el contrato del reto Origin debe tener el balance a 0 y el winner debe ser igual al que invoca la función.

Figura 4: Función getFlag()

Entonces, tenemos que dar solución a dos cosas: primero, comprobar que el balance del contrato Origin no es 0 y conseguir extraer los fondos, así como conseguir ser el winner. Si revisamos la función Transfer comentada anteriormente, nos damos cuenta de que se puede conseguir las dos cosas en la misma función. Si conseguimos que tx.origin sea igual al owner del contrato conseguiremos ser el winner y conseguiremos extraer los fondos del balance, enviándose estos al msg.sender. Antes de avanzar, vamos a analizar cómo funciona msg.sender:

  • Tenemos un usuario A, un contrato A y un contrato B. El usuario A invoca una función del contrato A y éste invoca una función del contrato B.
  • El msg.sender en el contrato A será el usuario A, mientras que el msg.sender en el contrato B será el contrato A.

Como se puede ver el msg.sender es justo quién te invoca cómo función de un contrato. No ocurre lo mismo con el tx.origin:

  • Tenemos un usuario A, un contrato A y un contrato B. El usuario A invoca una función del contrato A y éste invoca una función del contrato B.
  • El tx.origin en el contrato A será el usuario A. En el contrato B el tx.origin (cuando es invocado por el contrato A) seguirá siendo el usuario A.

La variable tx.origin almacena la dirección que origina la posible pila de llamadas que puedan surgir. Esto es un problema de seguridad como se trató en el artículo sobre tx.origin. Cuando desplegamos el reto, nos damos cuenta que en la propia página del reto nos aparece lo siguiente:

Figura 5: Formulario en la página del reto

Esto es un formulario para indicar la dirección de un contrato y una caja de texto dónde incluir el ABI del contrato ‘a pelo’. Esto ya es una pista de que necesitaremos un contrato para poder solucionar el reto. Se entiende que el botón Verify Contract hará que el backend de Level_Up! se conecte contra la dirección del contrato e invoque una función denominada attack. Al invocar esa función la dirección pública del backend de Level_Up! lo está haciendo el owner del contrato Origin (que es quién desplegó el reto). Entonces ocurriría lo siguiente:

  • Backend level_up! (dirección pública) invoca contrato ataque (función attack). En este punto el tx.origin es la dirección pública de level_up!
  • El contrato ataque invoca la función transfer del contrato Origin. En el contrato Origin el valor tx.origin sería la dirección pública de level_up! por lo que se bypassea el valor del require que comprueba si tx.origin es igual al owner.
  • Se actualiza el valor de winner por la dirección del contrato de ataque.
  • Se envían los fondos del contrato Origin al contrato de ataque.
  • El usuario puede conseguir la flag a través de una función getFlag() que se dispone en el contrato de ataque, ya que el owner es el contrato de ataque y no el usuario.

Parece un poco enrevesado, pero entendiendo bien el concepto de tx.origin se puede ver el peligro de utilizarlo en procesos de autorización. A continuación, se dejan las funciones del contrato de ataque desplegado sobre la blockchain de Level_Up!

    function attack() public{
        scontract.transfer(owner,scontract.balanceTotal());
    }

    function getFlag() public view returns(string memory){
        return scontract.getFlag();
    }
El despliegue del contrato se puede hacer con Remix para este reto. Solo tenemos que sacar la dirección del contrato Origin, eso se puede hacer a través de las ‘dev tools’ en la página del reto con contract.address.

Figura 6: Despliegue del reto con Remix

Ahora, hay que quedarse con la dirección del contrato de ataque y el ABI. Son valores que se pueden obtener en Remix y pasárselo al formulario en la página del reto.

Figura 7: Verificando la dirección del contrato del ataque

Tras verificar que todo va bien, fijaros el mensaje que nos devuelve el reto.

Figura 8: Transacción hecha

Ahora, podemos intentar recoger la flag desde el propio Remix o conectándonos al contrato de ataque desde la consola de Javascript

Figura 9: Recogemos el flag

Recogemos el flag y lo podemos validar en la plataforma a través de la instrucción base.validateFlag(contract.address).

Nuevo reto: Guess my number

Tenemos nuevo reto. El reto «Guess my number» nos trae una nueva experiencia Web3 en el que el usuario debe trabajar con datos a bajo nivel en temas de transacciones. Poder entenderlas mejor y quizá usar un poco de fuerza bruta para poder ayudarse en algún momento. Este reto es una evolución de snippet_delegated, el cual será resuelto, en principio en un par de meses.

Figura 10: Disponible el reto «Guess_my_number»

Ya tenemos un total de 14 retos y esperemos seguir publicando un reto mensualmente para que podáis seguir avanzando en conocimientos en la Web3 y en la parte de seguridad. Os animo a que probéis Level_UP! y os forméis en estas tecnologías, que van a ser parte de nuestro ecosistema tecnológico durante mucho tiempo, y hay que entender bien su funcionamiento, la piezas tecnológicas, la infraestructura y los riesgos de seguridad.


Recuerda que si quieres aprender de estas tecnologías, tienes Bit2Me Academy, que es una plataforma online para aprender de Web3, BitCoin, Tokenomics o Ethereum con cursos gratuitos además del libro dedicado a «Bitcoin: La tecnología Blockchain y su investigación» de Yaiza Rubio y Félix Brezo que seguro que te ayudan a ponerte las pilas.


Más artículos de Web3, Blockchain & SmartContracts
Saludos,

Autor: Pablo González Pérezescritor de los libros «Metasploit para Pentesters«, «Hacking con Metasploit: Advanced Pentesting» «Hacking Windows«, «Ethical Hacking«, «Got Root«,  “Pentesting con Powershell” y de «Empire: Hacking Avanzado en el Red Team«, Microsoft MVP en Seguridad y Security Researcher en el equipo de «Ideas Locas» de la unidad CDCO de Telefónica.  Para consultas puedes usar el Buzón Público para contactar con Pablo González

Contactar con Pablo González

Powered by WPeMatico

Gustavo Genez

Informático de corazón y apasionado por la tecnología. La misión de este blog es llegar a los usuarios y profesionales con información y trucos acerca de la Seguridad Informática.