Suchen
Inside Wiki
Nützliche Links




 
phpforum.de bei Facebook
 
phpforum.de bei Twitter
 

Zurück   PHP Forum: phpforum.de > phpforum.de Wiki > phpforum.de Wiki

PHP Wiki Dieses Wiki sammelt Lösungen, zu Problemen, welche immer wieder im Forum auftauchen.

 
 
Artikel-Optionen Ansicht
  #1  

Standard XSS

 

 

Sicherheit - Inhalte

Allgemein


Man spricht von XSS (Cross-Site Scripting), wenn ein Code in einen anderen Code eingeschleust wird. Hacker verwenden XSS, um z. B. an Logindaten zu kommen.

Beispiel XSS JavaScript


Angenommen, man hat eine Partnerbörse. User können sich registrieren, einloggen und ein Profil anlegen.

Sieht man sich ein Profil an, bekommt man zu sehen:

- Das Login-Formular, wo sich die User einloggen können, um ihr Profil zu ändern.
- Das Profil selbst.

Für den User Isabella schaut es z. B. folgendermaßen aus:



Der Code, den der Browser zu sehen bekommt, ist noch unspektakulär. Es sind nur 2 Tabelle und 1 Login-Formular. Der hier vielleicht schon etwas interessante Teil ist der letzte td, wo der Partnerwunsch steht. Dieser Text stammt aus einem textarea.

HTML Quellcode:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
      <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
      <title>XSS</title>
      <link rel="stylesheet" type="text/css" href="formate.css" />
   </head>
   <body>
      <h1>XSS</h1>
      <form method="post" action="index.php">
         <table>
            <tr>
               <th class="trLoginTitle">Nick:</th>
               <td><input name="username" type="text" /></td>
            </tr>
            <tr>
               <th class="trLoginTitle">Passwort:</th>
               <td><input name="password" type="password" /></td>
            </tr>
            <tr>
               <td colspan="2" class="trSubmit"><input value="Login" type="submit" /></td>
            </tr>
         </table>
      </form>
      <h2>Profil: Isabella</h2>
      <table>
         <tr>
            <th class="trProfileTitle">Geschlecht:</th>
            <td>weiblich</td>
         </tr>
         <tr>
            <th class="trProfileTitle">Größe:</th>
            <td>170 cm</td>
         </tr>
         <tr>
            <th class="trProfileTitle">Haarfarbe:</th>
            <td>blond</td>
         </tr>
         <tr>
            <th class="trProfileTitle">Augenfarbe:</th>
            <td>blau</td>
         </tr>
         <tr>
            <th class="trProfileTitle">Partnerwunsch:</th>
            <td><div id="tdPartnerTextarea"><pre>Mag große Männer :)</pre></div></td><!-- dieser Text stammt ursprünglich aus einem textarea -->
         </tr>
      </table>
   </body>
</html>

Die zugehörige CSS-Datei siehe Anhang.

Angenommen, Isabella ist ein Hacker. Sie hat nicht „Mag große Männer “ eingegeben, sondern genau diesen Text in das textarea des Profil-Formulars eingetragen:

Code:
<script type="text/javascript">
   this.onload = function()
   {
      this.document.forms[0].onsubmit = xss;
   }
   function xss()
   {
      var form = this.document.forms[0];
      var username = form.username.value;
      var password = form.password.value;
      alert(username + "/" + password);

      return true;
   }
</script>

Das hier ist JavaScript-Code. Was er bewirkt, erkläre ich etwas später.

Isabella schickt das Profil-Formular ab. Zuerst werden alle Formulardaten erfasst:

PHP Quellcode:
// Voraussetzungen:
//  - session musste gestartet werden können
//  - User korrekt eingeloggt
//  - $_POST-Daten müssen vorhanden sein

$sexIds  = array('', 'weiblich', 'männlich');
$hairIds = array('', 'blond', 'braun', 'schwarz', 'rot');
$eyesIds = array('', 'blau', 'grün', 'braun');

$errors = array(); // Fehlersammlung für Feedback an User

$sexId  = abs($_POST['sex_id']);  // 0 ... keine Angabe, 1 ... weiblich, 2 ... männlich
$hairId = abs($_POST['hair_id']); // 0 ... keine Angabe, 1 ... blond, 2 ... braun, 3 ... schwarz, 4 ... rot
$eyesId = abs($_POST['eyes_id']); // 0 ... keine Angabe, 1 ... blau, 2 ... grün, 3 ... braun
if
(
   $sexId  != $_POST['sex_id']  || $sexId  >= count($sexIds) ||
   $hairId != $_POST['hair_id'] || $hairId >= count($hairIds) ||
   $eyesId != $_POST['eyes_id'] || $eyesId >= count($eyesIds)
)
   exit;
$size = (int)$_POST['size'];                            // Angabe in cm
if ($size != $_POST['size'] || $size < 20)
   $errors[] = 0;                                       // User muss Größe nochmals eingeben
$partner = rtrim($_POST['partner']);                    // Text aus einem textarea
if (mb_strlen($partner) > 255)
{
   $errors[] = 1;                                       // Hinweis darauf, dass Text zu lang war
   $partner = rtrim(mb_substr($partner, 0, 255));
}

Sofern das Formular korrekt ausgefüllt wurde, werden die Daten danach in einer Datenbank abgespeichert:

PHP Quellcode:
// Voraussetzung: $_SESSION['id'] muss gesetzt sein

$id = (int)$_SESSION['id']; // in der Session ist die eigene DB-ID gespeichert
if ($id != $_SESSION['id'] || $id < 1)
   exit;
$ini = parse_ini_file('ini/config.txt');

$handle = mysql_connect($ini['host'], $ini['username'], $ini['password']);
if (!is_resource($handle))
   throw new Exception('mysql connect');
if (!mysql_select_db($ini['db'], $handle))
   throw new Exception('mysql select db');

$sql =
   'REPLACE INTO profile
   (  
      id,
      sex_id,
      size,
      hair_id,
      eyes_id,
      partner
   )
   VALUES
   (  
      '
, $id, ',
      '
, $sexId ,',
      '
, $size ,',
      '
, $hairId ,',
      '
, $eyesId ,',
      "'
, mysql_real_escape_string($partner), '"
   );'
;
if (!mysql_query($sql, $handle))
   throw new Exception('mysql: ' . print_r($sql, true));

Schaut man sich ein Profil an, werden die Daten aus der DB gelesen:

PHP Quellcode:
// Voraussetzung: $_GET['id'] muss gesetzt sein

$id = (int)$_GET['id']; // welches Profil man sehen möchte wird in der URL angegeben
if ($id != $_GET['id'] || $id < 1)
   exit;
$ini = parse_ini_file('ini/config.txt');

$handle = mysql_connect($ini['host'], $ini['username'], $ini['password']);
if (!is_resource($handle))
   throw new Exception('mysql connect');
if (!mysql_select_db($ini['db'], $handle))
   throw new Exception('mysql select db');

$sql = 'SELECT * FROM profile WHERE id = ', $id, ';';
$result = mysql_query($sql, $handle);
if (!is_resource($result))
   throw new Exception('mysql: ' . print_r($sql, true));
$data = mysql_fetch_assoc($result);

Nun sei angenommen, dass das PHP-Script XSS erlaubt. Der Partnerwunsch wird nun direkt ausgegeben (siehe letzter td):

PHP Quellcode:
<table>
   <tr>
      <th class="trProfileTitle">Geschlecht:</th>
      <td><?php echo $sexIds[$data['sex_id']]; ?></td>
   </tr>
   <tr>
      <th class="trProfileTitle">Größe:</th>
      <td><?php echo $data['size']; ?> cm</td>
   </tr>
   <tr>
      <th class="trProfileTitle">Haarfarbe:</th>
      <td><?php echo $hairIds[$data['hair_id']]; ?></td>
   </tr>
   <tr>
      <th class="trProfileTitle">Augenfarbe:</th>
      <td><?php echo $eyesIds[$data['eyes_id']]; ?></td>
   </tr>
   <tr>
      <th class="trProfileTitle">Partnerwunsch:</th>
      <td><div id="tdPartnerTextarea"><pre><?php echo $data['partner']; ?></pre></div></td>
   </tr>
</table>

Es kommt nun Karli aus Hannover auf das Profil von Isabella. Sein Browser sieht folgenden Quelltext:

HTML Quellcode:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
      <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
      <title>XSS</title>
      <link rel="stylesheet" type="text/css" href="formate.css" />
   </head>
   <body>
      <h1>XSS</h1>
      <form method="post" action="index.php">
         <table>
            <tr>
               <th class="trLoginTitle">Nick:</th>
               <td><input name="username" type="text" /></td>
            </tr>
            <tr>
               <th class="trLoginTitle">Passwort:</th>
               <td><input name="password" type="password" /></td>
            </tr>
            <tr>
               <td colspan="2" class="trSubmit"><input value="Login" type="submit" /></td>
            </tr>
         </table>
      </form>
      <h2>Profil: Isabella</h2>
      <table>
         <tr>
            <th class="trProfileTitle">Geschlecht:</th>
            <td>weiblich</td>
         </tr>
         <tr>
            <th class="trProfileTitle">Größe:</th>
            <td>170 cm</td>
         </tr>
         <tr>
            <th class="trProfileTitle">Haarfarbe:</th>
            <td>blond</td>
         </tr>
         <tr>
            <th class="trProfileTitle">Augenfarbe:</th>
            <td>blau</td>
         </tr>
         <tr>
            <th class="trProfileTitle">Partnerwunsch:</th>
            <td><div id="tdPartnerTextarea"><pre><script type="text/javascript">
   this.onload = function()
   {
      this.document.forms[0].onsubmit = xss;
   }
   function xss()
   {
      var form = this.document.forms[0];
      var username = form.username.value;
      var password = form.password.value;
      alert(username + "/" + password);
 
      return true;
   }
</script></pre></div></td>
         </tr>
      </table>
   </body>
</html>

Die Ausgabe sieht folgendermaßen aus:



Von dem JavaScript-Code ist hier nichts zu sehen.

Karli ist natürlich begeistert und möchte mit Isabella Kontakt aufnehmen. Er steht auf blauäugige Blondinen. Darum gibt er schnell seine Logindaten ein und klickt den Submit-Button.

Und jetzt wird der JavaScript-Code aktiv.

Sobald nämlich Karli auf den Submit-Button klickt, führt der Browser folgende Zeile aus:

Code:
this.document.forms[0].onsubmit = xss;

Daraufhin wird die Funktion xss aufgerufen. Darin wird ermittelt, was in dem Login-Formular eingegeben wurde:

Code:
var form = this.document.forms[0];
var username = form.username.value;
var password = form.password.value;

username und password könnten nun an einen beliebigen Server übertragen werden. Hierzu bräuchte man nur noch ein kleines AJAX-Script. Der Datenfluss würde dann folgendermaßen aussehen:



Im vorliegenden Script erweist sich Isabella jedoch als gnädig. Die Daten werden nicht auf ihren eigenen Server übertragen, sondern nur in einem Alert-Fenster ausgegeben:

Code:
alert(username + "/" + password);

Ohne diesem Alert hätte Karli nichts von dieser XSS-Attacke mitbekommen. Denn danach werden die login-Daten ganz normal weiterverarbeitet:

Code:
return true;

Karli ist dann ganz normal eingeloggt.

Wie hätte man diese XSS-Attacke verhindern können? Durch den PHP-Befehl htmlentities:

PHP Quellcode:
<table>
   <tr>
      <th class="trProfileTitle">Geschlecht:</th>
      <td><?php echo $sexIds[$data['sex_id']]; ?></td>
   </tr>
   <tr>
      <th class="trProfileTitle">Größe:</th>
      <td><?php echo $data['size']; ?> cm</td>
   </tr>
   <tr>
      <th class="trProfileTitle">Haarfarbe:</th>
      <td><?php echo $hairIds[$data['hair_id']]; ?></td>
   </tr>
   <tr>
      <th class="trProfileTitle">Augenfarbe:</th>
      <td><?php echo $eyesIds[$data['eyes_id']]; ?></td>
   </tr>
   <tr>
      <th class="trProfileTitle">Partnerwunsch:</th>
      <td><div id="tdPartnerTextarea"><pre><?php echo htmlentities($data['partner'], ENT_QUOTES, 'UTF-8'); ?></pre></div></td>
   </tr>
</table>

Denn nun bekommt der Browser folgenden Quellcode vorgesetzt:

HTML Quellcode:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
      <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
      <title>XSS</title>
      <link rel="stylesheet" type="text/css" href="formate.css" />
   </head>
   <body>
      <h1>XSS</h1>
      <form method="post" action="index.php">
         <table>
            <tr>
               <th class="trLoginTitle">Nick:</th>
               <td><input name="username" type="text" /></td>
            </tr>
            <tr>
               <th class="trLoginTitle">Passwort:</th>
               <td><input name="password" type="password" /></td>
            </tr>
            <tr>
               <td colspan="2" class="trSubmit"><input value="Login" type="submit" /></td>
            </tr>
         </table>
      </form>
      <h2>Profil: Isabella</h2>
      <table>
         <tr>
            <th class="trProfileTitle">Geschlecht:</th>
            <td>weiblich</td>
         </tr>
         <tr>
            <th class="trProfileTitle">Größe:</th>
            <td>170 cm</td>
         </tr>
         <tr>
            <th class="trProfileTitle">Haarfarbe:</th>
            <td>blond</td>
         </tr>
         <tr>
            <th class="trProfileTitle">Augenfarbe:</th>
            <td>blau</td>
         </tr>
         <tr>
            <th class="trProfileTitle">Partnerwunsch:</th>
            <td><div id="tdPartnerTextarea"><pre>&lt;script type=&quot;text/javascript&quot;&gt;
   this.onload = function()
   {
      this.document.forms[0].onsubmit = xss;
   }
   function xss()
   {
      var form = this.document.forms[0];
      var username = form.username.value;
      var password = form.password.value;
      alert(username + &quot;/&quot; + password);
 
      return true;
   }
&lt;/script&gt;</pre></div></td>
         </tr>
      </table>
   </body>
</html>

Der von Isabella ursprünglich eingegebene Text ist nun kein JavaScript mehr, sondern nur noch normaler Text, der auch auf dem Bildschirm ausgegeben wird:



Anhang CSS-Datei


Code:
body
{
   font-family: Verdana;
   font-size: 12px;
}
h1, h2
{
   font-size: 16px;
}
table
{
   border-collapse: collapse;
}
.trLoginTitle
{
   text-align: left;
   border: 1px solid #aaaaaa;
   padding: 3px;
}
.trProfileTitle
{
   text-align: left;
   border: 1px solid #aaaaaa;
   padding: 3px;
   vertical-align: top;
}
td
{
   border: 1px solid #aaaaaa;
   padding: 3px;
   vertical-align: top;
}
#tdPartnerTextarea
{
   width: 200px;
   overflow: auto;
}
.trSubmit
{
   text-align: right;
}
pre
{
   margin: 0px;
   font-family: Verdana;
   font-size: 12px;
}

« Vorheriges Kapitel   Sicherheit

Mitwirkende: combie
Erstellt von keksi__, 24.11.2010 am 23:15
Zuletzt bearbeitet von keksi__, 27.11.2010 am 20:57
16 Kommentare , 12094 Betrachtungen

Dieser Text steht unter der GNU-Lizenz für freie Dokumentation


 

Lesezeichen

Artikel-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.

Gehe zu

Alle Zeitangaben in WEZ +2. Es ist jetzt 19:29 Uhr.


Powered by vBulletin® Version 3.8.8 (Deutsch)
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Powered by NuWiki v1.3 RC1 Copyright ©2006-2007, NuHit, LLC