debt-simulator HSCTF

debt-simulator HSCTF

Wederom een prachtige ctf challenge die wordt besproken.

Na het klikken op de url die bij de challenge behoorden was er een soort van spel te zien.

wie heeft er zin om zijn bankrekening te verhogen? psss of juist te verlagen want dat kan natuurlijk ook nog. maar goed FOCUSSSSS op de challenge. Ik begon met het analyseren van de code die achter deze applicatie verstopt zat.

De code was een enkele lijn met tekst, niet echt duidelijk om te lezen dus ik ben toen naar de volgende website gegaan:

https://www.freeformatter.com/html-formatter.html#ad-output

Met behulp van deze website kreeg ik de code op een overzichtelijke manier te zien, dat is toch prettiger om te analyseren.

Helaas was er niet echt veel te vinden in de code, dus toen ben ik met behulp van de browser debugger verder gaan zoeken naar belangrijke hints of tips voor de challenge.

De browser debugger kan worden opgeroepen door met je rechtermuisknop op de website te klikken en vervolgens naar ‘inspect element’ te gaan waarna er het als volgt uit komt te zien

Met dit venster voor mijn neus ben ik naar de tab gegaan genaamd “Debugger”.

Eenmaal in dedebugger vondt ik iets interessants aan, een url.

De url was als volgt:

https://debt-simulator-login-backend.web.hsctf.com/yolo_0000000000001

Op deze pagina waren een aantal functies te zien, waarvan 1 functie bestond genaamd ‘getgetgetgetgetgetgetgetgetFlag’. Toen heb ik de hoofd applicatie met behulp van BurpSuite onderschept en zag tot mijn verbazing het volgende:

Zoals je ziet in de afbeelding hierboven zie je een parameter genaamd function, toen heb ik geprobeerd deze parameter aan te passen met de functie die wij eerder hadden gevonden genaamd ‘getgetgetgetgetgetgetgetgetFlag’. Het resultaat was als volgt:

Op deze manier had ik de vlag gevonden die behoort bij deze challenge.

Code analyse

Nu gaan wij de code bestuderen.

import React, { useState, useEffect } from 'react';
import Header from "./Header";
import Main from './Main';
import Message from './Message';
import Button from "./Button";
import "./App.css";

function App() {
  const [message, setMessage] = useState("Ready to Play?");
  const [runningTotal, setRunningTotal] = useState(0);
  const [buttonText, setButtonText] = useState("Start Game");


  useEffect(() => {
    if (runningTotal < -1000) {
      setMessage("You lost. You have less than $-1000. Better luck next time.");
      setButtonText("Play Again");
    } else if (runningTotal > 2000) {
      setMessage("You won. You have more than $2000. Try your luck again?");
      setButtonText("Play Again");
    } else if (runningTotal !== 0 && buttonText !== "Next Round") {
      setButtonText("Next Round");
    }
  });

  const onClick = () => {
    const isGetCost = Math.random() > 0.4 ? true : false;
    const func = isGetCost ? 'getCost' : 'getPay';
    const requestOptions = {
      method: 'POST',
      body: 'function=' + func,
      headers: { 'Content-type': 'application/x-www-form-urlencoded' }
    }

    fetch("https://debt-simulator-login-backend.web.hsctf.com/yolo_0000000000001", requestOptions)
    .then(res => res.json())
    .then(data => {
      data = data.response;
      if (buttonText === "Play Again" || buttonText === "Start Game") {
        setButtonText("Next Round");
        setRunningTotal(0);
      }
      setMessage("You have " + (isGetCost ? "paid me " : "received ") + "$" + data + ".");
      setRunningTotal(runningTotal => isGetCost ? runningTotal - data : runningTotal + data);
    });
  }

  return <div className="App">
    <Header />
    <Message message={message}/>
    <Main content={runningTotal}/>
    <Button onClick={onClick} text={buttonText}/>
  </div>;
}

export default App;

Ik zal het nu in stukken gaan knippen.

function App() {
  const [message, setMessage] = useState("Ready to Play?");
  const [runningTotal, setRunningTotal] = useState(0);
  const [buttonText, setButtonText] = useState("Start Game");

Bovenstaande code maakt een functie genaamd App aan. Vervolgens een variable message die gelijk wordt gezet aan een useState genaamd “Ready to play?”. Wat doet de useState precies?

De useState zorgt voor de interactie, als ik op de knop start game druk verdwijnt de ready to play message van het scherm. Vervolgens wordt het huidige bedrag op 0 gezet en de laatste regel zorgt ervoor dat op de knop de zin ‘Start game’ staat.

 useEffect(() => {
    if (runningTotal < -1000) {
      setMessage("You lost. You have less than $-1000. Better luck next time.");
      setButtonText("Play Again");
    } else if (runningTotal > 2000) {
      setMessage("You won. You have more than $2000. Try your luck again?");
      setButtonText("Play Again");
    } else if (runningTotal !== 0 && buttonText !== "Next Round") {
      setButtonText("Next Round");
    }
  });

Bovenstaande code doet het volgende, het is simpel gezegt een if else situatie. Als de runningTotal variable kleiner is dan -1000 dan komt er een bericht genaamd You lost. You have less then -1000. Better luck next time. En de knop wordt op ‘play again’ gezet.

de tweede statement zegt als runningTotal groter is dan 2000 er de bericht you won tevoorschijn komt. De laatste controleert of runningTotal niet gelijk is aan 0 en buttonText niet gelijk is aan next round, als dit dus true (waar) is dan wordt de tekst van de knop op Next round gezet.

const onClick = () => {
    const isGetCost = Math.random() > 0.4 ? true : false;
    const func = isGetCost ? 'getCost' : 'getPay';
    const requestOptions = {
      method: 'POST',
      body: 'function=' + func,
      headers: { 'Content-type': 'application/x-www-form-urlencoded' }
    }

Bovenstaande maakt een functie genaamd onClick vervolgens maakt de functie een aantal hooks. Hooks worden beschreven als volgt:

Hooks zijn functies waarmee u kunt "haken" in reactiestatus en levenscyclusfuncties van functiecomponenten. Hooks werken niet binnen klassen - ze laten je React zonder lessen gebruiken. 
React biedt een paar ingebouwde Hooks zoals useState. U kunt ook uw eigen Hooks maken om stateful gedrag tussen verschillende componenten te hergebruiken. 

De functie onClick maakt dus een aantal hooks aan genaamd isGetCost. Deze hook berekent een random waarde die groter moet zijn dan 0.4 en daarna kijkt die of het waar of vals is.

Vervolgens de tweede hook genaamd isGetCost voert dus of de getCost of getPay uit, simpel gezegt of je moet betalen of je krijgt geld. De laatste hook vertelt welke request opties wij hebben. In dit geval een POST met in de body dus de functie en de bijbehorende waarde. Zoals te zien was tijdens de challenge in de BurpSuite reqeust.

    fetch("https://debt-simulator-login-backend.web.hsctf.com/yolo_0000000000001", requestOptions)
    .then(res => res.json())
    .then(data => {
      data = data.response;
      if (buttonText === "Play Again" || buttonText === "Start Game") {
        setButtonText("Next Round");
        setRunningTotal(0);
      }
      setMessage("You have " + (isGetCost ? "paid me " : "received ") + "$" + data + ".");
      setRunningTotal(runningTotal => isGetCost ? runningTotal - data : runningTotal + data);
    });
  }

Dit gedeelte is het belangrijkst want hier hebben wij de vreemde url gevonden. De fetch haalt de pagina op die tussen de quotes staan en dit geval dus de vreemde pagina. Hij doet dit met behulp van de eerder gemaakte hook genaamd requestOptions dus hij voert een POST reqeust uit en roept de bijbehorende functie van die pagina.

daarna komt er weer een if statement die weer een vergelijking doet, dit spreekt eigenlijk voor zichzelf want het is een beetje hetzelfde als de vorige keer dat wij een if statement hadden. Het controleert simpel gezegd gewoon of buttonText gelijk is aan play again of buttonText is gelijk aan start game, zo ja dan wordt de text op de knop naar Next round gezet en de het geld weer op 0.

setMessage is een bericht dat tevoorschijn komt tijdens het spelen nadat er op de knop wordt gedrukt. dan staat er bijvoorbeeld dit:

You have paid me $180.

of

You have received $19.

De setRunningTotal bepaalt het bedrag dat de speler nog heeft, een simpel reken som wordt hier uitgevoerd.

  return <div className="App">
    <Header />
    <Message message={message}/>
    <Main content={runningTotal}/>
    <Button onClick={onClick} text={buttonText}/>
  </div>;
}

export default App;

Het laatste stukje code doet eigenlijk niks bijzonders, het geeft een div terug met daarin een header en daarin dan de message dus de tekst. De main content is de runningTotal het bedrag en een knop waar de speler op kan klikken.

De aller laatste code zorgt ervoor dat de applicatie start en gespeeld kan worden.

Dit was het weer voor deze week, tot de volgende keer! en bedankt voor het lezen.

Please share and spread
5 2 stemmen
Artikelbeoordeling
Abonneer
Laat het weten als er
guest
0 Reacties
Inline feedbacks
Bekijk alle reacties
NederlandsEnglish
0
Zou graag je gedachten willen weten, s.v.p. laat een reactie achter.x
()
x