NetVision-Technik

Zur?ck   NetVision-Technik > Forum > Server > Webserver > Security

Security Hier kommen alle Fragen und Lösungen zur Sicherheit und zu Fixes am Serversystem rein

Antwort
 
Themen-Optionen Ansicht
Alt 20.04.2011, 22:43  
PHP, SQL & Server Optimierungs~/Securityguide
bl0bb bl0bb ist offline 20.04.2011, 22:43

Hola,

da ich Lastschwächen und Sicherheitslücken immer wieder auf diversen Trackern und auch hier bei vielen Userskripten sehe, habe ich mal einen "kurzen" Optimierungs~ und Securityguide verfasst. Ob das Thema in dieser Section richtig ist, weiß ich nicht

Ich hoffe es wird einigen Leuten helfen und ihr lernt noch was, denn man lernt ja bekanntlich nie aus

Und für die Leute die sich fragen wozu:
Die Antwort ist ganz einfach -> ihr vermeidet mögliche SQL Injections, XSFR- & XSS Attacken, LFI's, RFI's, Directory Traversals usw. und könnt auch noch das System massiv entlasten. Und das alles nur, wenn ein paar Dinge beachtet werden. Wer mit den Abkürzungen nichts anfangen kann, sollte Tante Google fragen.

Da ich mich schon lange nicht mehr mit den einzelnen Ablegern der verschiedenen Sourcen auseinandersetze (hab meine eigene ), werden entsprechende Codebeispiele allgemein gehalten.


Optimierung von PHP Code

Ich fange mal mit PHP an, da eine Webapp, zumindest hier, größenteils in PHP geschrieben ist.
- Spart euch eure "Selfmade" Funktionen und nutzt PHP-eigene Funktionen. Für 90% aller Fälle gibt es schon welche und diese laufen immer schneller als die eigenen.

- Initialisiert Variablen bevor ihr diese nutzt. Damit vermeidet ihr mögliche Falsewerte und ihr wisst immer genau welchen Typ eine Variable hat.

- Vermeidet eine Zeilenweise Ausgabe per echo oder print. Sammelt diese stattdessen in einer Variable und gebt diese am Ende einmalig aus.
PHP-Code:
// falsch
echo 'Zeile 1';
// irgendwelche Logik
echo 'Zeile 2';

// richtig
$output 'Zeile 1';
// irgenwelche Logik
$output .= 'Zeile 2';
echo 
$output
- Verwendet ihr Variablen in Strings dann nur mittels Konkatenierung.
PHP-Code:
// falsch
"Ausgabe $var";

//richtig
'Ausgabe' $var
- Strings ohne Variablen immer in einfache Hochkommata setzen ('), das spart dem Parser einen Zweitdurchlauf.

- Lasst ihr eine Schleife über die Länge eines Arrays laufen, dann bestimmt die Länge vorher und nicht in der Schleife.
PHP-Code:
// falsch
for($i=0$i<count($array); $i++) {...}

//richtig
$size count($array);
for(
$i=0$i<$size$i++) {...} 
- Nutzt bei einfachen if/else Bedingungen den Konditionaloperator, denn der ist schneller.
PHP-Code:
//falsch
if(true) {
$var 1;
} else {
$var 0;
}

//richtig
$var true 0
- Ordnet bei Kontrollstrukturen (if/else, switch) vom Wahrscheinlichstem zum Unwahrscheinlichstem. Also Bedingungen die fast immer wahr sind, kommen nach ganz oben.

- Besitzt eine if-Anweisung mehrere durch OR getrennte Bedingungen, dann kommt das Schnellste nach Links.
PHP-Code:
//falsch
if($var+== || $var === 3) {...}

//richtig
if($var === || $var+== 5) {...} 
- Bettet das (Main)Skript in ob_start und ob_end_flush ein. Die Puffernutzung ist wesentlich schneller als eine partielle Ausgabe. Zudem kann man so geziehlt Fehler schon im Anfangsstadium breaken.

- Prüft "unbekannte" Variablen vor der Nutzung oder in Bedingungen mit isset, das zielt insbesondere auf $_GET und $_POST ab.
PHP-Code:
//falsch
if($var) {...}

//richtig
if(isset($var)) {...} 
- Nutzt wenn möglich Referenzen (&) auf Variablen. Damit muss von dieser keine Kopie vor der Veränderung erstellt werden und man spart RAM.
PHP-Code:
$array = array('.''..''...');

//falsch
function do($array) {
...
return 
$array;
}

// richtig
function do(&$array) {
...

- Finger weg von array_push, nehmt stattdessen lieber die normale Zuweisung ($array[] = 'Wert').

- file oder file_get_contents sind schneller als fopen bzw. fget

- mysql_fetch_assoc ist immer schneller als mysql_fetch_array

- echo ist schneller als print

- array_map ist schneller als eine foreach Schleife, zumindest bei einfachen Operationen (z.B. trim)

- strtr ist schneller als str_replace

- str_replace ist schneller als preg_replace

- htmlspecialchars ist schneller als htmlentities

- Ein Cast ist schneller als das entsprechende PHP-Äquivalent [(int) vs. intval].

- Gleichheit ist immer schneller als Vergleich (=== vs. ==)

- "kleiner gleich" ist schneller als "kleiner als" (<= vs. <)

- "größer als" ist schneller als "größer gleich" (> vs. >=)

- Inkrementierung/Dekrementierung ist schneller als das mathematische Äquivalent (++ vs. +1). Wobei der Präoperator schneller ist als der Postoperator (++$var vs. $var++)

- Bei der Ausgabe von mehrere Variablen ist eine Argumentliste schneller als eine Konkatenierung.
PHP-Code:
//falsch
echo $var1 $var2;

//richtig
echo $var1$var2
- Belegt die Argumente einer eigenen Funktion, wenn möglich, immer mit Defaultwerten vor, da so der Funktionsaufruf beschleunigt wird.
PHP-Code:
//falsch
function do($a$b) {...}

//richtig
function do($a=1$b=2) {...} 
- Den (String)Index eines Arrays immer in Hochkommata setzen, sonst denkt der Parser das es sich um eine Konstante handelt.
PHP-Code:
//falsch
$array[index]

//richtig
$array['index'
- Vermeidet Fehler/Warnungsunterdrückung (@) in den Skripten. Fangt eventuelle Meldungen vorher durch ein if-Konstrukt ab.
PHP-Code:
//falsch
@unlink($file);

//richtig
if(file_exists($file)) {
unlink($file);

- Vermeidet ereg-Funktionen und nutzt stattdessen preg-Funktionen.

- PHP-eigene Konstanten (true, false, null) immer klein schreiben, Großschreibung verhindert das Entdecken beim Erstdurchlauf.

- Vermeidet zuviele includes/requires. Ein Codesplit ist zwar sinnvoll, jedoch muss nicht jeder Schnipsel in eine eigene Datei.

- Fasst Codewiederholungen in eigene Funktionen zusammen, das spart dem Parser eine Menge Zeit.
Beachtet man diese Sachen, kann man das Parsen der Skripte bei größeren Projekten um Sekunden drücken.


Optimierung der Datenbank und SQL Queries

Ein wesentlicher Bestandteil sind SQL Anfragen. Sind diese suboptimal kann die Ladezeit eine Seite schnell in die Höhe schießen. Daher sollte man auch hier ein paar Sachen beachten. Die Beispiele sind für MySQL, bei anderen Servern kann die Syntax abweichen.
- Die Datenbankstruktur sollte gut geplant sein. Lohnt es sich zusammengehörige Informationen nur in einer Table zu speichern, oder kommt man besser, wenn man diese Informationen gruppiert und über mehrere Tables verteilt. Mehrere Tables haben den Vorteil das diese weniger Speicher belegen und schneller durchsucht werden können.
Bsp: Userdaten einer NV-Source
Per Default sind alle Informationen eines Users in nur einer Table gespeichert. Und diese wächst auch recht schnell an, wenn man immer und immer wieder Columns hinzufügt. Besser wäre es wichtige Userinfos in eine Table abzulegen (ID, Username, Enabled, etc.) und zusätzliche (weniger oft benötigte) Infos in eine Weitere (AllowDownload, AllowUpload, etc.). Dies spart bei grundlegenden Abfragen, bei denen man z.B. nur wissen möchte welche Klasse der User hat und ob dieser aktiviert ist, eine Menge Zeit, da die ganzen weniger relevanten Infos in einer anderen Table liegen.
- Der Typ einer Column sollte an die zu speichernden Werte angepasst werden. Es ist absolute Verschwendung einem Usernamen den Typ VARCHAR(255) zuzuordnen, wenn der Username z.B. auf 20 Zeichen begrenzt ist.

- Jede Column sollte einen Defaultwert haben. Columns mit Stringwerten (CHAR, TEXT, DATE, ...) kann man per Default auf NULL setzen. Zahlenwerte hingegen auf 0, 0.0 usw. Dies erleichtert einen INSERT ungemein, wenn man nicht alle Columns durchschleppen muss.

- Ein TINYINT(1) ist einem ENUM(0,1) oder ENUM('no', 'yes') vorzuziehen. Ein TINYINT belegt weniger Ressourcen und ein Vergleich mit Integern ist schneller als ein Stringvergleich. Und da das so ist, sollte man IP's auch immer als Integer speichern (ip2long oder INET_ATON).

- Die Vergleichsoperatoren und die Art des Vergleichs sind natürlich auch ausschlaggebend wie schnell Bedingungen abgearbeitet werden können.
- Sortierung der Operatoren von schnell zu langsam: = , > , >= , < , <= , LIKE , <> .
Man sollte also darauf bedacht sein immer den schnellsten Operator zu wählen, auch wenn die Bedingung dafür umgeformt werden muss.

- Wenn Columns miteinander verglichen werden, sollten sie denselben Typ und Länge haben, denn sonst muss intern erst eine Typumwandlung vorgenommen werden.
sql Code:
#falsch
`char_col_length_10`=`varchar_col_length_20`

#richtig
`char_col_length_10`=`char_col_length_10`

- Ein Vergleich mit Literalen geht immer am schnellsten und sollte somit vorgezogen werden.
sql Code:
#falsch
`col2`=`col3` AND `col1`=5

#richtig
`col1`=5 AND `col2`=`col3`

- Vermeiden von NOT
sql Code:
#falsch
NOT `col`>5

#richtig
`col`<=5

- Ein Literal sollte beim Vergleich denselben Typ haben wie die Column, d.h. Char zu Char, Int zu Int.
sql Code:
#falsch
`tinyint_col`='5'

#richtig
`tinyint_col`=5

- Nutzt IN anstelle von OR.
sql Code:
#falsch
`col`=5 OR `col`=7

#richtig
`col` IN (5,7)

- Bei fast vollständigen Sequenzen geht es schneller die Range zu ermitteln und bestimmte Elemente auszuschließen, anstatt sich IN zu bedienen.
sql Code:
#falsch
`col` IN (1,2,3,5,6,7)

#richtig
`col` BETWEEN 1 AND 7 AND `col`<>4

- Bedingungen können mit den De Morgan'schen Gesetzen umgeformt werden, um so langsame Operatoren zu eliminieren.
sql Code:
#falsch
 NOT (`col1`>5 OR `col2`=7)
 
 #richtig
 `col1`<=5  AND `col2`<>7
- Die Bedingungen einer WHERE Klausel sind zu sortieren:
- Bei OR Bedingungen kommt das Wahrscheinlichste ganz nach links, denn sobald die Bedingung erfüllt wurde, wird der Rest übersprungen.

- Bei AND Bedingungen kommt das Unwahrscheinlichste ganz nach links.

- Beim Verbund von mehreren AND und OR kommt die einfachste Bedingung nach links und die verschachteltste Bedingung nach rechts.

- Bei Oracle DBs ist es genau anders herum, aber die verwendet hier sicherlich eh keiner
Mit Wahrscheinlichkeit ist der Wert einer Column gemeint der wohl am ehesten (nicht) zutrifft.
Bsp. 1: Hole alle User die aktiviert sind oder bl0bb heißen. Man weiß das der Großteil der User aktiviert ist und wohl nur ein einziger bl0bb heißt. Daher filtert man zuerst nach dem enabled Attribut, da die WHERE Klausel nach Erfüllung beendet wird.
sql Code:
#falsch
SELECT * FROM `users` WHERE `username`='bl0bb' OR `enabled`=1

#richtig
SELECT * FROM `users` WHERE `enabled`=1 OR `username`='bl0bb'

Bsp. 2: Hole alle User die aktiviert und verwarnt sind. Die wenigsten User sind verwarnt, daher ist dies die unwahrscheinlichste Bedingung. Sobald diese eintrifft wird die AND Verknüpfung false und die Ausführung wird beendet.
sql Code:
#falsch
SELECT * FROM `users` WHERE `enabled`=1 AND `warned`=1

#richtig
SELECT * FROM `users` WHERE `warned`=1 AND `enabled`=1
- Bei einem SELECT immer die Expressions einzeln angeben und den Universalselektor (*) vermeiden.

- Erstellt Indizes für häufig benutzte WHERE Klauseln. Ein INDEX ist eine interne Sortierung einer/mehrerer Column(s). Liegt ein INDEX an, so wird direkt in diesem gesucht statt einmal komplett die Table zu durchsuchen. Ein INDEX lohnt sich aber wirklich nur für häufige Abfragen. Nicht für jede WHERE Klausel einen INDEX erstellen! Damit erreicht man nur das Gegenteil und die Anwendung wird langsamer. Ein INDEX nimmt natürlich auch Speicher in Anspruch und wird jedesmal neu erstellt, wenn Werte der indexierten Column hinzugefügt, verändert oder gelöscht werden. Daher muss man vorher abwegen, ob ein INDEX auf Columns mit einer hohen Änderungsquote sinnvoll ist.
Bsp: Bei einem Userlogin wird überprüft ob dieser auch aktiviert ist. Daher lohnt sich hier ein INDEX auf der Column enabled.
sql Code:
CREATE INDEX `idx_enabled` ON `users`(`enabled`)
Und um sicherzugehen das dieser auch genutzt wird bindet man USE/FORCE INDEX in die Abfrage ein.
sql Code:
SELECT * FROM `users` USE `idx_enabled` WHERE `username`='...' AND `enabled`=1
Weitere Informationen über Indizes findet ihr hier.

- Überprüft eure Queries mit EXPLAIN. Damit kann man mögliche Bremsen gleich von Anfang an beseitigen und sieht ob es angebracht wäre den Query umzustrukturieren oder Indizes zu erstellen.

- Fasst mehrere Queries mittels JOIN zusammen oder nutzt einen Subquery.
Bsp: Öfters möchte man den Usernamen des Uploaders eines Torrents haben. Und immer wieder wird das ganze in zwei Queries aufgesplittet.
PHP-Code:
$id mysql_fetch_assoc(mysql_query("SELECT owner FROM torrents WHERE id=1"));
$username mysql_fetch_assoc(mysql_query("SELECT username FROM users WHERE id=" $id['owner'])); 
Das ganze mit einem JOIN:
sql Code:
SELECT `u`.`username` FROM `torrents` AS `t` LEFT JOIN `users` AS `u` ON `t`.`owner`=`u`.`id`  WHERE `t`.`id`=1
Oder mit einem Subquery:
sql Code:
SELECT (SELECT `u`.`username` FROM `users` AS `u` WHERE `u`.`id`=`t`.`owner`) AS `username` FROM `torrents` AS `t` WHERE `t`.`id`=1
Ob man nun einen JOIN oder Subquery verwenden sollte, hängt von Fall zu Fall ab. Da heißt es einfach testen. In der Regel ist ein Subquery in einer WHERE Klausel schneller als ein entsprechender JOIN.

- Wenn nicht benötigt sollte man auf ORDER BY verzichten. Unter bestimmten Bedingungen kann man dies auch weglassen, wenn man einen INDEX für die WHERE Klausel angelegt hat.
Um ein optimales Ergebnis zu erzielen, müssen dem SQL Server auch entsprechende Ressourcen zugewiesen werden. Dafür gibt es das schicke kleine Skript Tuning-Primer welches Änderungsvorschläge unterbreitet. Was welcher Eintrag bewirkt ist hier nachzulesen.


Optimierung des Zusammespiels von PHP und SQL

Die oben genannten Optimierungen bringen schon eine Menge, wenn man PHP Logik und SQL Logik jedoch falsch miteinander verbindet, nutzt das alles nichts
- Nutzt immer nur ein Charset und mischt diese nicht. Ansonsten laufen im Hintergrund immer Konvertierungen, welche unangenehm bremsen und auch die Daten beschädigen können.
Speichert die Skripte in einem bestimmten Charset ab, und passt die SQL-, PHP- und Serverkonfig an dieses Charset an.
Beispiele:
php.ini
default_charset = "UTF-8"

my.cnf / my.ini
[mysqld]
default-character-set = utf8
default-collation = utf8_general_ci
character-set-server = utf8
collation-server = utf8_general_ci
init-connect = 'SET NAMES utf8'

nginx.conf
server {
...
charset utf-8;
...
}

httpd.conf
AddDefaultCharset UTF-8
Ändert die Collation der einzelnen Columns entsprechend und gebt dem Header das Charset mit.
PHP-Code:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
header('Content-type: text/html; charset=UTF-8'); 
- Vermeidet eine Queryausführung innerhalb von Schleifen. Sammelt stattdessen die Parameter und führt nach der Schleife einen Query aus.
PHP-Code:
//falsch
while($i<10) {
...
mysql_query("...");
...

Statt vieler einzelner INSERT-Anweisungen kann man auch einen Multiple-Insert ausführen.
PHP-Code:
$values '';
while(
$i<10) {
...
$values .= ($values != '' ',' '') . '(' $val1 ', ' $val2 ')';
...
}
mysql_query("INSERT INTO `xy` (`col1`, `col2`) VALUES " $values); 
Analog kann man auch einen DELETE entsprechend anpassen.
PHP-Code:
$ids = array();
while(
$i<10) {
...
$ids[] = $id;
...
}
mysql_query("DELETE FROM `xy` WHERE `id` IN (" implode(','$ids) . ")"); 
- Nutzt SQL-eigene Funktionen anstelle von PHP-Funktionen um Parameter zu validieren bzw. die Ergebnismenge zu manipulieren.
PHP-Code:
//falsch
$a mysql_query("SELECT `firstname`, `lastname` FROM `users`");
while(
$b mysql_fetch_assoc($a)) {
...
$name $b['firstname'] . ' ' $b['lastname'];
...
}

//richtig
$a mysql_query("SELECT CONCAT(`firstname`, ' ', `lastname`) AS `name` FROM `users`");
while(
$b mysql_fetch_assoc($a)) {
...
$name $b['name'];
...


Optimierung der Webapp


Es gibt auch einige Sachen, welche jetzt nicht speziell PHP oder SQL zugeordnet werden können, auf die man dennoch achten sollte
- Parameter eines AJAX Requests sollten vorm Abschicken validiert werden.

- Nur soviele includes / requires / link-meta-tags (also zusätzlicher Code) wie unbedingt nötig. Was mir immer wieder auffällt, ist das die bittorrent.php in die Announce inkludiert wird. Was da allerdings an unnötigem Overhead hinten ran kommt -.- Besser ist es die paar CONFIG Konstanten und Funktionen entsprechend auszulagern und diese PHP-Datei zu inkludieren.

- Haltet den HTML/CSS/Javascript Code valide. Nur so ist eine fehlerfreie Darstellung und korrekte Datenübertragung immer gewährleistet. Gibt ja genug Addons für den Firefox, IE oder Chrome die dabei helfen können.

- Lagert soviel Javascript und CSS Code wie möglich in externe Dateien aus. Diese werden wie auch Bilder in den Cache gelegt und müssen beim nächsten Mal nicht neu geladen werden. Das spart Traffic Und um sicherzustellen das der User Stylesheet- oder Javascript-Änderungen auch sofort mitbekommt, hängt man an die Datei einfach einen Stamp an.
PHP-Code:
<link href="style.css?update=<?=filemtime('style.css')?>" type="text/css" rel="stylesheet">
- Cached aufwendige Konstrukte (Navigation, Need-Seed-Liste, Torrentübersicht, Shoutbox, ...) und regelmäßig ausgeführte Queries (z.B. die PM-Queries die bei jedem Seitenaufruf gemacht werden). Dafür kann memcached genutzt werden, oder wenn ihr damit nicht klar kommt, schreibt es in eine separate Datei oder die Session des Users. Ein Fileread geht allemal schneller als ein Query. Der SQL-Server wird es euch danken.

- Auf einem Tracker sollte die Announce über einen anderen Port geleitet werden. Das entlastet den Webserver ein wenig, wenn auch nicht viel. Aber Kleinvieh macht ja bekanntlich auch Mist.

- Der Cleanup sollte in einen cron ausgelagert werden. Damit spart man sich wieder unnötige Queries in der Anwendung.

Sicherheit der Webapp

Jetzt zu ein paar Grundregeln um mögliche Sicherheitslücken zu eliminieren.
- Vermeiden von SQL Injections:
Alle Daten die vom User manipuliert werden können ($_GET, $_POST, $_REQUEST, $_COOKIE, Formdata) müssen validiert (z.B. is_int) und escaped (z.B. mysql_real_escape_string) werden, bevor diese in die Datenbank wandern.

- Vermeiden von XSS Lücken:
Alle Daten aus der Datenbank oder einem Request müssen vor der Ausgabe konvertiert werden (z.B. htmlspecialchars).
Und wer richtig paranoid sein möchte kann es auch gerne so machen:
PHP-Code:
htmlspecialchars(html_entity_decode(urldecode($data))); 
- Vermeiden von XSFR:
Um diesen Attacken entgegen zu wirken, wird bei jeder Aktion (z.B. ein Submit) ein eindeutiges Token, als Parameter, mitgeschickt, welches den User identifiziert. Ist dieses Token nicht gesetzt, falsch oder abgelaufen, wird die Aktion nicht ausgeführt.

Bsp: Mit diesem Code in der Shoutbox, ist es in ungeschützten NV Sourcen möglich, dass alle User automatisch ausgeloggt werden. Und solange diese beim Login auf die Seite mit der Shoutbox geleitet werden, bleibt das auch so.
Code:
[img ]code entfernt muss nicht jeder kennen solche sachen sonst wird wieder rumgespielt[/img] // Leerzeichen beim ersten img Tag entfernen
Um diese Lücke zu beheben wird vor der Logout Routine folgendes in die logout.php eingefügt:
PHP-Code:
...
check_xsfr_token($_GET['xsrf']);
... 
Die Funktion check_xsrf_token könnte folgendermaßen aussehen:
PHP-Code:
function check_xsrf_token($token) {
if(
$token === $_SESSION['userdata']['xsrf']) {
return;
} else {
die();

Wie das Token generiert und gespeichert wird, ist jedem selbst überlassen.
Ein erfolgreicher Logout ist jedenfalls nur noch auf diese Art möglich:
Code:
http://SERVER_URL/logout.php?xsrf=12345
Wobei das noch eine harmlose Variante einer XSRF Attacke ist. Man kann sich genauso gut befördern oder sich Upload schenken lassen.

- Cookie Grabbing:
Wenn es keine XSS Schwachstellen mehr gibt, fällt es Angreifern wesentlich schwerer Cookies zu stehlen. Um dennoch auf Nummer sicher zu gehen, sollten klickbare URLs validiert werden. So etwas wie ein script-Tag hat darin nichts zu suchen. Damit ein erfolgreicher Angriff nicht permanent zum Erfolg führt, sollte die Lebensdauer eines Cookies so kurz wie möglich gehalten werden. Zusätzlich kann man den User Agent und die IP in die Cookiedaten einbinden und diese dann mit einem eigenen Algorithmus verschlüsseln (dafür bietet sich Mcrypt an). So hat der Angreifer zwar das Cookie, kann damit aber nichts anfangen

- Session Hijacking:
Hier gilt ähnliches wie beim Cookie Grabbing. Gültigkeitsdauer so gering wie möglich halten. Nach einem erfolgreichen Login am besten die Session ID wechseln (session_regenerate_id). Zusätzlich den User Agent und die IP prüfen, und wenn diese abweichen, einen erneuten Login fordern.

- Vermeiden von Directory Traversal, RFI und LFI:
Eigentlich ist es ganz simpel diese Arten von Angriffen zu vermeiden. Niemals vom User manipulierbare Daten ohne Validierung verwenden. Und schon gar nicht, wenn diese genutzt werden um Dateien einzubinden. Dazu kann man sich eine Regex bauen, um Dateinamen des Projektes zu spezifizieren und diese dann entsprechend zu prüfen. Oder man legt sich eine Art Whitelist für zulässige Seiten an. Der Fantasie sind da keine Grenzen gesetzt.
Falls man einen Bilderupload oder ähnliches hat, mit dem der User ermächtigt wird, quasi potentiellen Schadcode auf die Seite zu laden, sollte man bei jedem Upload den MIME Type überprüfen (finfo_file). Da dies allerdings noch nicht reicht, kann man bei Bildern die Funktion getimagesize anwenden und schaun ob das Bild auch valide ist. Aber auch das bietet noch keinen 100%igen Schutz. Besser ist es die Datei mit diversen Funktionen zu dekodieren (html_entity_decode, base64_decode, urldecode) dann einmal ein strip_tags auf den Content laufen lassen und die alte mit der neuen Filegröße zu vergleichen. Weicht diese ab, kann man davon ausgehen, dass mit dem Bild etwas nicht stimmt.

- Fehlermeldungen:
Diese sollten niemals ausgegeben werden, da man so Rückschlüsse auf die Struktur ziehen kann. Lieber alles loggen oder sich eine Mail mit der Meldung schicken lassen.

- Weg vom mass-market product:
Da offene Sourcen ja dafür gedacht sind, dass diese von sovielen Betreibern wie möglich genutzt werden, sollte man sensible Strukturen ändern. Dabei ist es egal ob es sich um eine NV-Source, Wordpress, XTCommerce usw. handelt.
Wege dahin ist z.B. die Änderung der Datenbankstruktur. In vielen Fällen reicht schon ein Präfix für die einzelnen Tables aus, um so z.B. SQL Injections zu erschweren. Auch anfällige Funktionen, wie die mksecret der NV-Source, sollten verändert werden. Denn sonst werden potentielle Brutforce Attacken nur gefördert. Auch eine Änderung der Ordnerstruktur ist nicht verkehrt.

- Verzeichnisschutz:
Generel sollten alle Verzeichnisse vor unbefugtem Zugriff geschützt werden.

Bsp nginx.conf
server {
...
location /PathToFolder/ {
deny all;
allow 127.0.0.1;
}
...
}

Bsp. sites-enabled
<Directory /PathToFolder/>
Options Indexes MultiViews FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
Allow from 127.0.0.0/255.0.0.0 ::1/128
</Directory>

- Hotlinking:
Um Traffic zu sparen, sollten alle Images, Stylesheets, Skripte etc auf einen lokalen Zugriff begrenzt werden. Ich habe schon desöfteren gesehen, dass ein User sein Avatar auf Tracker A im Bitbucket von Tracker B liegen hat -.-

Bsp nginx.conf
server {
...
location ~* \.(jpg|jpe?g|png|gif|swf|nfo|torrent|css|js)$ {
valid_referers blocked none server_names;
if ($invalid_referer) {
return 404;
}
}

root /PathToRoot;
...
}

Bsp. .htaccess
RewriteEngine on
RewriteCond %{HTTP_REFERER} .
RewriteCond %{HTTP_REFERER} !^SITE_URL [NC]
RewriteRule \\.(jpg|jpe?g|png|gif|swf|nfo|torrent|css|js)$ - [NC,F]

- Aktivierung der SSL Verschlüsselung:
Ob das Zertifkat gültig ist oder nicht, spielt auf Trackern eher eine untergeordnete Rolle. Hauptsache die Kommunikation wird verschlüsselt. Bei seriösen Webanwendungen sollte man sich da jedoch nicht lumpen lassen.

Sicherheit des Servers

Jetzt noch ein kurzer Abriss wie man seinen Server sicherer gestalten kann.
- Festplatten verschlüsseln bzw. einzelne Partitionen in welche man Logs, DBs und den WWW Kram getrennt unterbringen kann.
- Logs sollten regelmäßig gelöscht werden. Eine lange Vorhaltedauer erschwert nur das reagieren auf aktuelle Ereignisse.
- Firewall installieren und alle Ports dicht machen, welche nicht unbedingt benötigt werden.
- Weg von den Standartports (SSH, FTP usw.), denn da erfolgt zuerst ein Scan auf mögliche Lücken.
- Für die einzelnen Server/Applikationen immer einen einzelnen User mit beschränkten Rechten anlegen. Somit wird bei Kompromittierung wenigstens der Rootzugriff vermieden. Gleiches gilt für Anwendungen welche auf den SQL Server zugreifen. Niemals per mysql-root an die Datenbank lassen.
- Passwörter regelmäßig wechseln.
- Installation von Suhosin. Dies ist wesentlich effektiver als das CrackerTracker Skript.
- Nutzen von offiziellen Sourcelisten.
- Datenbanken, phpmyadmin und Useruploads außerhalb des WWW Roots aufbewahren.
- Die URL von phpmyadmin ändern und nicht auf dem Defaultwert lassen.
- Tools alá fail2ban, ipcop etc. installieren um Angriffen nicht vollkommen schutzlos ausgeliefert zu sein.
So das wars auch schon - mehr fällt mir gerade nicht ein. Es fehlen bestimmt noch einige Dinge, aber die können ja ergänzt werden

Ge?ndert von bl0bb (21.04.2011 um 01:05 Uhr).

 
Benutzerbild von bl0bb
bl0bb
Erfahrener Benutzer
Punkte: 12.526, Level: 73 Punkte: 12.526, Level: 73 Punkte: 12.526, Level: 73
Levelaufstieg: 19% Levelaufstieg: 19% Levelaufstieg: 19%
Aktivität: 0% Aktivität: 0% Aktivität: 0%
Letzte Erfolge
Registriert seit: 04.04.2011
Beitr?ge: 247
Abgegebene Danke: 6
Erhielt 94 Danke für 7 Beiträge
Downloads: 2
Uploads: 0
Nachrichten: 34
Hits: 57264
Mit Zitat antworten
Folgende 20 Benutzer sagen Danke zu bl0bb für den nützlichen Beitrag:
bejay (21.04.2011), BiGPoWeR (21.04.2011), Bluesteel (21.04.2011), bolzen (21.04.2011), D@rk-€vil™ (21.04.2011), destination (21.04.2011), Deto® (21.04.2011), DIABLO (21.04.2011), DoLo (21.04.2011), gotthummer (20.04.2011), june (21.04.2011), Lex (21.04.2011), max56 (23.05.2011), Schwamm (21.04.2011), Sponge (21.04.2011), Stifler (21.04.2011), Thunder™ (20.04.2011), vaio03 (21.04.2011), x3n (21.04.2011), Zero111 (21.04.2011)
Alt 21.04.2011, 10:33   #11
Stifler
König
Punkte: 39.887, Level: 100 Punkte: 39.887, Level: 100 Punkte: 39.887, Level: 100
Levelaufstieg: 0% Levelaufstieg: 0% Levelaufstieg: 0%
Aktivität: 0% Aktivität: 0% Aktivität: 0%
Letzte Erfolge
Auszeichnungen
 
Benutzerbild von Stifler
 
Registriert seit: 14.02.2011
Ort: Graz
Alter: 39
Beitr?ge: 1.495
Abgegebene Danke: 82
Erhielt 200 Danke für 37 Beiträge
Downloads: 11
Uploads: 0
Nachrichten: 6230
Renommee-Modifikator:
3168 Stifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes Ansehen
Standard

Eher so!
PHP-Code:
$output .= "\n<table cellspacing='1' cellpadding='4' border='0' class='tableinborder' style='width: 100%;'>
    <tbody>
        <tr>
            <td align='left' class='tablea'><font color='red'><b>Nickname:</b></font> </td>
            <td align='left' class='tablea'><b> "
.$nickname." </b></td>
        </tr>
        <tr>
            <td align='left' class='tablea'><font color='red'><b>Email:</b></font> </td>
            <td align='left' class='tablea'><b> "
.$email." </b></td>
        </tr>
        <tr>
            <td align='left' class='tablea'><font color='red'><b>Grund:</b></font> </td>
            <td align='left' class='tablea'><b> "
.$grund." </b></td>
        </tr>
    </tbody>
</table><br />\n"

__________________
Stifler ist offline   Mit Zitat antworten Nach oben
Alt 21.04.2011, 10:35   #12
ike
Erfahrener Benutzer
Punkte: 2.915, Level: 33 Punkte: 2.915, Level: 33 Punkte: 2.915, Level: 33
Levelaufstieg: 10% Levelaufstieg: 10% Levelaufstieg: 10%
Aktivität: 0% Aktivität: 0% Aktivität: 0%
Letzte Erfolge
Artikel Benutzer besitzt 1x Badboy Benutzer besitzt 1x Profi Benutzer besitzt 1x Angel Benutzer besitzt 1x Hilfe Level 1 Benutzer besitzt 1x Hilfe Level 2
 
Benutzerbild von ike
 
Registriert seit: 07.03.2010
Beitr?ge: 436
Abgegebene Danke: 12
Erhielt 38 Danke für 2 Beiträge
Downloads: 15
Uploads: 0
Nachrichten: 309
Renommee-Modifikator:
1821 ike genießt hohes Ansehenike genießt hohes Ansehenike genießt hohes Ansehenike genießt hohes Ansehenike genießt hohes Ansehenike genießt hohes Ansehenike genießt hohes Ansehenike genießt hohes Ansehenike genießt hohes Ansehenike genießt hohes Ansehenike genießt hohes Ansehen
Standard

Mit dem Code würde er dir <br /> ausgeben, da du die Variablen immer wieder überschreibst.


Du kannst die Variable genauso wie dein echo behandeln sprich

PHP-Code:
$output 
'<table>
  <tr>
    <td>Hallo</td>
  </tr>
</table>'
;

echo 
$output
ike ist offline   Mit Zitat antworten Nach oben
Alt 21.04.2011, 11:00   #13
D@rk-€vil™
König
Punkte: 90.825, Level: 100 Punkte: 90.825, Level: 100 Punkte: 90.825, Level: 100
Levelaufstieg: 0% Levelaufstieg: 0% Levelaufstieg: 0%
Aktivität: 0% Aktivität: 0% Aktivität: 0%
Letzte Erfolge
Auszeichnungen
 
Benutzerbild von D@rk-€vil™
 
Registriert seit: 06.09.2008
Ort: Da wo der Himmel neun schlägt...
Beitr?ge: 1.630
Abgegebene Danke: 253
Erhielt 1.103 Danke für 139 Beiträge
Downloads: 89
Uploads: 3
Nachrichten: 3824
Renommee-Modifikator:
3461 D@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes Ansehen
Standard

ok....danke dir ike
__________________

Chaosqueen: Gegen unseren DDos Schutz hat keiner ne Chance.
Ich: Träum mal schön weiter du Naive Person.
D@rk-€vil™ ist offline   Mit Zitat antworten Nach oben
Alt 21.04.2011, 11:44   #14
pullermann
Gesperrt
Punkte: 10.511, Level: 68 Punkte: 10.511, Level: 68 Punkte: 10.511, Level: 68
Levelaufstieg: 16% Levelaufstieg: 16% Levelaufstieg: 16%
Aktivität: 0% Aktivität: 0% Aktivität: 0%
Letzte Erfolge
 
Benutzerbild von pullermann
 
Registriert seit: 31.05.2009
Beitr?ge: 363
Abgegebene Danke: 8
Erhielt 37 Danke für 5 Beiträge
Downloads: 45
Uploads: 0
Nachrichten: 142
Renommee-Modifikator:
0 pullermann hat eine strahlende Zukunftpullermann hat eine strahlende Zukunftpullermann hat eine strahlende Zukunftpullermann hat eine strahlende Zukunftpullermann hat eine strahlende Zukunftpullermann hat eine strahlende Zukunftpullermann hat eine strahlende Zukunftpullermann hat eine strahlende Zukunftpullermann hat eine strahlende Zukunftpullermann hat eine strahlende Zukunftpullermann hat eine strahlende Zukunft
Standard

Danke für die Arbeit sowas ist immer gut und kommt hier immer gut an
pullermann ist offline   Mit Zitat antworten Nach oben
Alt 21.04.2011, 13:49   #15
Zero111
Ausbilder Schmidt
Letzte Erfolge
 
Benutzerbild von Zero111
 
Registriert seit: 30.10.2008
Ort: Essen (Ruhr) Ruhrpott4Ever :D
Alter: 36
Beitr?ge: 2.665
Abgegebene Danke: 107
Erhielt 1.644 Danke für 154 Beiträge
Downloads: 43
Uploads: 1
Nachrichten: 3942
Renommee-Modifikator:
10 Zero111 genießt hohes AnsehenZero111 genießt hohes AnsehenZero111 genießt hohes AnsehenZero111 genießt hohes AnsehenZero111 genießt hohes AnsehenZero111 genießt hohes AnsehenZero111 genießt hohes AnsehenZero111 genießt hohes AnsehenZero111 genießt hohes AnsehenZero111 genießt hohes AnsehenZero111 genießt hohes Ansehen
Standard

so gehts auch
PHP-Code:
$output "
<table cellspacing='1' cellpadding='4' border='0' class='tableinborder' style='width: 100%;'>
    <tbody>
        <tr>
            <td align='left' class='tablea'><font color='red'><b>Nickname:</b></font> </td>
            <td align='left' class='tablea'><b> "
.$nickname." </b></td>
        </tr>
        <tr>
            <td align='left' class='tablea'><font color='red'><b>Email:</b></font> </td>
            <td align='left' class='tablea'><b> "
.$email." </b></td>
        </tr>
        <tr>
            <td align='left' class='tablea'><font color='red'><b>Grund:</b></font> </td>
            <td align='left' class='tablea'><b> "
.$grund." </b></td>
        </tr>
    </tbody>
</table><br />"
;

echo 
$output
__________________
Zero111 ist offline   Mit Zitat antworten Nach oben
Alt 21.04.2011, 14:25   #16
bl0bb
Erfahrener Benutzer
Punkte: 12.526, Level: 73 Punkte: 12.526, Level: 73 Punkte: 12.526, Level: 73
Levelaufstieg: 19% Levelaufstieg: 19% Levelaufstieg: 19%
Aktivität: 0% Aktivität: 0% Aktivität: 0%
Letzte Erfolge
 
Benutzerbild von bl0bb
 
Registriert seit: 04.04.2011
Beitr?ge: 247
Abgegebene Danke: 6
Erhielt 94 Danke für 7 Beiträge
Themenstarter Themenstarter
Downloads: 2
Uploads: 0
Nachrichten: 34
Renommee-Modifikator:
1013 bl0bb genießt hohes Ansehenbl0bb genießt hohes Ansehenbl0bb genießt hohes Ansehenbl0bb genießt hohes Ansehenbl0bb genießt hohes Ansehenbl0bb genießt hohes Ansehenbl0bb genießt hohes Ansehenbl0bb genießt hohes Ansehenbl0bb genießt hohes Ansehenbl0bb genießt hohes Ansehenbl0bb genießt hohes Ansehen
Standard

Zitat:
Zitat von D@rk-€vil™ Beitrag anzeigen
nur ich frage mich, warum wurde in meiner letzten php weiterbildung gesagt.....das...

echo besser sei als output
Jo, eigentlich stimmt es fast. Es kommt immer auf die Kombination an. Sobald man den Ausgabepuffer nutzt ist echo schneller, ohne Pufferung $output. Da aber die wenigsten schon mal was von ob_start gehört haben... Aber auch mit Puffer sind beide Varianten annähernd gleich. Daher würde ich die $output Varaiante einer Masse von echos immer vorziehen.

Testskript $output
PHP-Code:
<?
ob_start();
$scriptstart = microtime(true);
$output = '';
for($i = 0; $i < 500000; ++$i) {
    $output .= 'Zahl' . $i;
}
echo $output;
unset($output);
echo '<br/><br/>Laufzeit: ' . (microtime(true) - $scriptstart) . 's<br/>benutzter Speicher: ' . memory_get_usage() . 'bytes';
ob_end_flush();
?>
Testskript echo
PHP-Code:
<?
ob_start();
$scriptstart = microtime(true);
for($i = 0; $i < 500000; ++$i) {
    echo 'Zahl' . $i;
}
echo '<br/><br/>Laufzeit: ' . (microtime(true) - $scriptstart) . 's<br/>benutzter Speicher: ' . memory_get_usage() . 'bytes';
ob_end_flush();
?>
Durchlauf 1 mit Puffer
$output
Laufzeit: 0.63549590110779ms
benutzter Speicher: 5235576bytes

echo
Laufzeit: 0.62462306022644s
benutzter Speicher: 5235488bytes

Durchlauf 2 mit Puffer
$output
Laufzeit: 0.63504791259766ms
benutzter Speicher: 5235576bytes

echo
Laufzeit: 0.62371683120728s
benutzter Speicher: 5235488bytes

Durchlauf 3 mit Puffer
$output
Laufzeit: 0.64082717895508ms
benutzter Speicher: 5235576bytes

echo
Laufzeit: 0.63638401031494s
benutzter Speicher: 5235488bytes


Durchlauf 1 ohne Puffer
$output
Laufzeit: 0.62938117980957ms
benutzter Speicher: 5224840bytes

echo
Laufzeit: 3.9060130119324s
benutzter Speicher: 340272bytes

Durchlauf 2 ohne Puffer
$output
Laufzeit: 0.68935108184814ms
benutzter Speicher: 5224840bytes

echo
Laufzeit: 2.9526829719543s
benutzter Speicher: 340272bytes

Durchlauf 3 ohne Puffer
$output
Laufzeit: 0.65321207046509ms
benutzter Speicher: 5224840bytes

echo
Laufzeit: 3.556214094162ms
benutzter Speicher: 340272bytes
bl0bb ist offline   Mit Zitat antworten Nach oben
Alt 21.04.2011, 17:46   #17
D@rk-€vil™
König
Punkte: 90.825, Level: 100 Punkte: 90.825, Level: 100 Punkte: 90.825, Level: 100
Levelaufstieg: 0% Levelaufstieg: 0% Levelaufstieg: 0%
Aktivität: 0% Aktivität: 0% Aktivität: 0%
Letzte Erfolge
Auszeichnungen
 
Benutzerbild von D@rk-€vil™
 
Registriert seit: 06.09.2008
Ort: Da wo der Himmel neun schlägt...
Beitr?ge: 1.630
Abgegebene Danke: 253
Erhielt 1.103 Danke für 139 Beiträge
Downloads: 89
Uploads: 3
Nachrichten: 3824
Renommee-Modifikator:
3461 D@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes AnsehenD@rk-€vil™ genießt hohes Ansehen
Standard

jut....danke dir...mehr wollte ich nicht wissen
__________________

Chaosqueen: Gegen unseren DDos Schutz hat keiner ne Chance.
Ich: Träum mal schön weiter du Naive Person.
D@rk-€vil™ ist offline   Mit Zitat antworten Nach oben
Alt 21.04.2011, 17:58   #18
Stifler
König
Punkte: 39.887, Level: 100 Punkte: 39.887, Level: 100 Punkte: 39.887, Level: 100
Levelaufstieg: 0% Levelaufstieg: 0% Levelaufstieg: 0%
Aktivität: 0% Aktivität: 0% Aktivität: 0%
Letzte Erfolge
Auszeichnungen
 
Benutzerbild von Stifler
 
Registriert seit: 14.02.2011
Ort: Graz
Alter: 39
Beitr?ge: 1.495
Abgegebene Danke: 82
Erhielt 200 Danke für 37 Beiträge
Downloads: 11
Uploads: 0
Nachrichten: 6230
Renommee-Modifikator:
3168 Stifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes AnsehenStifler genießt hohes Ansehen
Standard

ob_implicit_flush ist auch eine interessante Sache! Da erspart man sich das ob_flush() und flush().

Nütze ich bei meinem Chatsystem, bzw war vor Ajax die einzige Möglichkeit einen "Realtimechat" (kein Reload sondern Stream) mit einer Endlosschleife + sleep() reibungslos zu verwirklichen!
__________________
Stifler ist offline   Mit Zitat antworten Nach oben
Antwort

Stichworte
optimierung, php, sicherheit, sql


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, G?ste: 1)
 

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 +1. Es ist jetzt 08:34 Uhr.


Powered by vBulletin® Version 3.8.9 (Deutsch)
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Template-Modifikationen durch TMS