Forum: PC-Programmierung Ordnung und Struktur in PHP Projekten


von PHP-Noob (Gast)


Lesenswert?

Hallo,

ich würde gerne wissen, ob und wenn ja wie man in PHP möglichst "sauber" 
programmieren kann. Ich nenne hierfür ein einfaches Beispiel, bei dem 
ich keine wirklich zufriedenstellende Lösung gefunden habe:

Ich möchte in einer PHP-Datei das HTML-Header Gedöns reinschreiben, 
diese Datei soll von allen einzelnen PHP-Seiten eingebunden werden. 
Außerdem gibt es eine CSS-Datei, die bereits innerhalb der header-Datei 
eingebunden werden soll / muss.

Wenn ich nun einen Unterordner habe, und die header.php mittels
1
include '../header.php'
 einbinde, dann funktioniert das nicht, weil nach dem einbinden die CSS 
Datei mit z.B.
1
href ="main.css"
 nicht mehr gefunden wird, da diese sich ja ebenfalls in einem höher 
liegenden Ordner befindet. Wird die header-Datei im Unterordner 
eingebunden, so ist der angegebene Pfad jetzt falsch.


Nun habe ich es so gelöst, dass ich für jeden Unterordner wiederum eine 
Header-Datei habe. In dieser wird definiert wo sich der Hauptpfad 
befindet, anschließend wird die übergeordnete Header Datei eingebunden. 
In dieser Header Datei wird dann der Hauptpfad benötigt um die CSS Datei 
richtig zu finden. Ein bisschen Quellcode sagt mehr als 1000 Worte:

Hauptheader:
1
<!DOCTYPE html>
2
<html lang="de">
3
<head>
4
  <title><?php echo $title; ?></title>
5
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6
  <link rel="stylesheet" type="text/css" href ="<?php echo $mainpath; ?>main.css"> 
7
</head>
8
9
<?php
10
date_default_timezone_set("Europe/Berlin");
11
 ?>


Untergeordnete Header:
1
<?php
2
$mainpath = '../';
3
include $mainpath.'header.php';
4
 ?>


Somit funktioniert alles, ich finde es dennoch sehr unsauber, dass 
Variablen in einer Datei "global" definiert werden und von anderen 
Dateien einfach genutzt werden. Anders ausgedrückt: In der 
Hauptheaderdatei wird auf die Variable "$mainpath" zugegriffen, die 
dieser Datei alleine vollkommen unbekannt ist. Erst dadurch, dass diese 
Datei von einer anderen Datei eingebunden wird, bekommt diese Variable 
erst ihre Definition.

Gibt es da andere Wege um sowas ordentlich zu machen?

von Sheeva P. (sheevaplug)


Lesenswert?

PHP-Noob schrieb:
> [...]
> Hauptheader:<!DOCTYPE html>
> <html lang="de">
> <head>
>   <title><?php echo $title; ?></title>
>   <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
>   <link rel="stylesheet" type="text/css" href ="<?php echo $mainpath;
> ?>main.css">
> </head>
>
> [...]
> Gibt es da andere Wege um sowas ordentlich zu machen?

CSS wird nicht von PHP eingebettet, sondern von HTML. Das in dem href 
="" hat daher erst einmal nichts mit dem Pfad der PHP-Datei im 
Dateisystem zu tun -- sondern mit dem URL, unter dem der Webbrowser die 
Datei main.css anrufen kann. Dieser URL hat aber vor allem mit der 
Konfiguration Deines Webservers und weniger mit dem Ablageort im 
Dateisystem zu tun.

Außerdem bist Du leider dabei, Dir einen schlechten Stil anzugewöhnen. 
Auch wenn es war einmal die Grundidee von PHP gewesen ist, PHP-Code ins 
HTML einzubetten, war und ist das einer der größten Kritikpunkte an PHP 
und einer der wichtigsten Gründe dafür, warum Richtige Entwickler(tm) 
der Sprache und ihren Benutzern mit einer gewisse Skepsis begegnen... 
Profis schreiben lieber HTML-Templates, die dann mit einer 
Templateengine wie Smarty verarbeitet werden, so daß HTML und PHP-Code 
in unterschiedlichen Ordnern liegen und damit sauber voneinander 
getrennt sind.

Auch CSS-Dateien haben nichts in Verzeichnissen zu suchen, in denen auch 
Dein PHP-Code untergebracht ist. CSS-Dateien gehören, eventuell 
vielleicht noch zusammen mit JavaScript-Dateien, in ein separates 
Verzeichnis, das oft "static/" genannt wird. Der Webserver ist dann 
dafür verantwortlich, daß der URL "http://www.example.com/static/"; 
korrekt auf das Verzeichnis "/var/www/example.com/static/" gemappt wird, 
so daß Dein HTML-Code für das Stylesheet nur den absoluten URL-Pfad 
"/static/main.css" einbinden muß.

HTH, YMMV.

von Dirk D. (dicky_d)


Lesenswert?

ICh sehe, und betreibe das genauso,
such dir deine Lieblings-Template-Engine und benutze diese, da wirst du 
auf dauer wesentlich glücklicher mit!

Guck dich einfach mal Hier um:

https://github.com/ziadoz/awesome-php

In dem speziellen Fall ist der Absatz Templating interesant:

https://github.com/ziadoz/awesome-php#templating

Ausser das dir das hilft den Überblick zu bewahren führt das auch dazu 
das du alles was du brauchst Sammelst und das dann anzeigt statt dein 
Markup zu schreiben und immer wieder Dinge einzusammeln und 
Entscheidungen zu treffen.
Grüße, Dirk

von Bernd K. (prof7bit)


Lesenswert?

Dirk D. schrieb:
> ICh sehe, und betreibe das genauso,
> such dir deine Lieblings-Template-Engine und benutze diese

PHP IST eine Template Engine, eine sehr mächtige sogar. Es ist 
technologischer Unfug höchsten Grades da noch eine zweite obendrüber zu 
stülpen.

: Bearbeitet durch User
von Sheeva P. (sheevaplug)


Lesenswert?

Bernd K. schrieb:
> Dirk D. schrieb:
>> ICh sehe, und betreibe das genauso,
>> such dir deine Lieblings-Template-Engine und benutze diese
>
> PHP IST eine Template Engine, eine sehr mächtige sogar. Es ist
> technologischer Unfug höchsten Grades da noch eine zweite obendrüber zu
> stülpen.

Vor allem ist es jedenfalls technologischer Unfug, die Programmlogik in 
den Darstellungslayer einzubetten.

Andererseits hast Du nicht völlig unrecht: man kann PHP innerhalb von 
PHP als Templateengine benutzen, aber das ist eher etwas für 
Fortgeschrittene. Für Einsteiger ist sowas sehr verwirrend und führt sie 
in Versuchung, doch wieder mit dem Unfug anzufangen.

Deswegen ist Smarty an dieser Stelle der bessere Einstieg, weil es zu 
einer Trennung von Logik und Darstellung führt und recht leicht zu 
lernen ist. So gewöhnt sich der künftige Entwickler gleich ein 
ordentliches Softwaredesign an, was beim Einstieg zweifellos wichtiger 
ist, als die Einsparung einiger Sekundenbruchteile Laufzeit auf einem 
massiv beharkten Server.

von PHP-Noob (Gast)


Lesenswert?

Guten morgen, vielen Dank für eure Antworten!

Ich habe mir mal smarty konfiguriert und mich ein bisschen eingelesen 
und denke nicht, dass es das richtige für mich ist. Ich werde vermutlich 
niemals beruflich PHP programmieren und auf meiner Seite werde ich wohl 
für immer der Programmierer und Designer bleiben, ich bin also auf eine 
so starke Trennung nicht angewiesen.

Sheeva P. schrieb:
> Auch CSS-Dateien haben nichts in Verzeichnissen zu suchen, in denen auch
> Dein PHP-Code untergebracht ist. CSS-Dateien gehören, eventuell
> vielleicht noch zusammen mit JavaScript-Dateien, in ein separates
> Verzeichnis, das oft "static/" genannt wird. Der Webserver ist dann
> dafür verantwortlich, daß der URL "http://www.example.com/static/";
> korrekt auf das Verzeichnis "/var/www/example.com/static/" gemappt wird,
> so daß Dein HTML-Code für das Stylesheet nur den absoluten URL-Pfad
> "/static/main.css" einbinden muß.

Ich weiß nicht, ob ich dich richtig verstanden habe... muss ich den 
Server umkonfigurieren, damit er mit dem absoluten URL-Pfad klarkommt? 
Ich habe einen Standard-billigen 0815 Server bei 1&1 und bei einem 
absoluten Pfad findet er die CSS Datei nicht, wenn die PHP- bzw. HTML 
Datei in einem Unterordner liegt.


Wie hätte man mein Beispiel denn vor der smarty Zeit gelöst? Gibt es da 
noch andere Tricks?

von Planlos (Gast)


Lesenswert?

PHP-Noob schrieb:
> Wie hätte man mein Beispiel denn vor der smarty Zeit gelöst?

Ein Ordner "static" am Webserver (oder auch mehrere, "styles", 
"images","scripts").

Im HTML mit src="/static/abc.png" arbeiten.

Hat alles mit PHP nix zu tun, ist reines HTML.

Vorteile:
- Kannst direkt für die statischen Verzeichnisse mit .htaccess 
mod_expires konfigurieren, für viel schnelleren Seitenaufbau
- Kannst in den statischen Ordnern das Ausführen von PHP verbieten 
lassen. (Mehr Sicherheit, falls durch irgendeinen Fehler woanders ein 
User-Upload in diese Ordner erlaubt ist.
- Funktioniert unabhängig von der Lage deiner PHP-Dateien, und auch wenn 
du per mod_rewite "schönere" URLs erzeugen willst.
(z.B. http://meine.seite/artikel/2016/thema_abc statt 
http://meine.seite/artikel.php?Jahr=2015&thema=abc)

von Dirk D. (dicky_d)


Lesenswert?

Bernd K. schrieb:
> PHP IST eine Template Engine, eine sehr mächtige sogar. Es ist
> technologischer Unfug höchsten Grades da noch eine zweite obendrüber zu
> stülpen.

Dann machen sehr viele Leute wohl sehr viel falsch.

Wann immer ich denke das Viele Leute grundsätzlich was falsch machen, 
aber ich nicht, versuche ich mal mein Weltbild zurecht zu rücken, 
probier das doch auch mal :)

von S R (Gast)


Lesenswert?

Dirk D. schrieb:
> Dann machen sehr viele Leute wohl sehr viel falsch.

Bernd K. hat schon recht, ich sehe das genauso. Und nur weil es viele 
falsch machen ist es noch lange nicht richtig oder gut.

Natürlich gehören Views (=Templates) getrennt von der restlichen Logik. 
Aber eben in PHP geschrieben und nicht in irgendeiner Template-Sprache 
wie Smarty oder Blade die am Ende wieder in PHP übersetzt wird.

von Sheeva P. (sheevaplug)


Lesenswert?

PHP-Noob schrieb:
> Ich habe mir mal smarty konfiguriert und mich ein bisschen eingelesen
> und denke nicht, dass es das richtige für mich ist. Ich werde vermutlich
> niemals beruflich PHP programmieren und auf meiner Seite werde ich wohl
> für immer der Programmierer und Designer bleiben, ich bin also auf eine
> so starke Trennung nicht angewiesen.

Da habe ich mich vielleicht mißverständlich ausgedrückt: wenn ich von 
Design rede, meine ich nicht das grafische Design und Layout Deiner 
Website, sondern das Softwaredesign bzw. die Architektur. Das hat wenig 
damit zu tun, ob Du PHP beruflich oder privat benutzen willst, sondern 
vielmehr damit, wie Deine Software aufgebaut ist; zum Beispiel gehören 
HTML-Templatedateien, Dateien mit PHP-Code und statische Dateien in 
unterschiedliche Verzeichnisse, und Programmlogik (PHP-Code) sollte 
nicht in HTML-Code eingebettet werden.

> Sheeva P. schrieb:
>> Auch CSS-Dateien haben nichts in Verzeichnissen zu suchen, in denen auch
>> Dein PHP-Code untergebracht ist. CSS-Dateien gehören, eventuell
>> vielleicht noch zusammen mit JavaScript-Dateien, in ein separates
>> Verzeichnis, das oft "static/" genannt wird. Der Webserver ist dann
>> dafür verantwortlich, daß der URL "http://www.example.com/static/";
>> korrekt auf das Verzeichnis "/var/www/example.com/static/" gemappt wird,
>> so daß Dein HTML-Code für das Stylesheet nur den absoluten URL-Pfad
>> "/static/main.css" einbinden muß.
>
> Ich weiß nicht, ob ich dich richtig verstanden habe... muss ich den
> Server umkonfigurieren, damit er mit dem absoluten URL-Pfad klarkommt?
> Ich habe einen Standard-billigen 0815 Server bei 1&1 und bei einem
> absoluten Pfad findet er die CSS Datei nicht, wenn die PHP- bzw. HTML
> Datei in einem Unterordner liegt.

Der Webserver hat die Aufgabe, URLs auf Dateisystempfade zu mappen, also 
für eine angeforderte URL die richtige Datei zu finden. In der 
klassischen Apache-Konfiguration gibt es dazu unter anderem die 
Direktive "Alias". Zum Beispiel könnte in einer Apache-Konfiguration die 
folgende Zeile zu finden sein:
1
Alias /static /var/www/example.com/static

Dies weist den Apache-Webserver an, bei einem Request nach URLs, die mit 
"/static" beginnen, ins Verzeichnis "/var/www/example.com/static" zu 
suchen. Wenn Deine Website also
1
<link rel="stylesheet" type="text/css" href ="/static/main.css" />

einbindet, wird der Webbrowser den Webserver nach der Datei 
"/static/main.css" fragen, und der Webserver liefert dann die Datei 
"/var/www/example.com/static/main.css" an den Webbrowser zurück (oder, 
wenn er diese Datei in angegebenen Pfad nicht findet, einen HTTP-Fehler 
404).

Wie der Gast Planlos ebenso dankenswerter- wie richtigerweise anmerkt, 
hat das aber nichts mit PHP zu tun, sondern ist eine Sache der 
Konfiguration des Webservers, und bei statischen HTML-Seiten genauso 
gilt.

Wie man das auf einem "Standard-billgen 0815 Server bei 1&1" 
konfiguriert, kann Dir vielleicht jemand anders hier sagen; ich bin in 
verschiedenerlei Dingen eher traditionell orientiert und konfiguriere 
meinen Apachen daher noch ganz klassisch von Hand. ;-)

von Dirk D. (dicky_d)


Lesenswert?

S R schrieb:

> Natürlich gehören Views (=Templates) getrennt von der restlichen Logik.
> Aber eben in PHP geschrieben und nicht in irgendeiner Template-Sprache
> wie Smarty oder Blade die am Ende wieder in PHP übersetzt wird.

Was spricht den dagegen?

von S R (Gast)


Lesenswert?

Dirk D. schrieb:
> Was spricht den dagegen?

- Man muss völlig sinnbefreit "noch eine Sprache" lernen, und zwar alle 
die eventuell mitwirken (z.Bsp. auch der Frontend-Entwickler).
- Man muss eine IDE finden die das Syntax-Highlighting unterstützt damit 
es Spaß macht
- Performance MUSS schlechter sein
...

Was ist denn der Unterschied ob ich nun {$var} oder <?= $var; ?> 
schreibe? Oder in Blade halt {{ $var }}

von Dirk D. (dicky_d)


Lesenswert?

S R schrieb:
> Dirk D. schrieb:
>> Was spricht den dagegen?
>
> - Man muss völlig sinnbefreit "noch eine Sprache" lernen, und zwar alle
> die eventuell mitwirken (z.Bsp. auch der Frontend-Entwickler).
Je nach Projektkontext hat man dann aber nur EINE Templatesprache, 
sowohl für dinge die auf dem Server gerendert werden als auch für dinge 
die nachträglich im Browser gerendert werden.

> - Man muss eine IDE finden die das Syntax-Highlighting unterstützt damit
> es Spaß macht
Das ist dann wohl ein Nachteil JEDER sprache :(

> - Performance MUSS schlechter sein ...
Nein.
wenn du das richtig machst wird in Produktion keine Template 
interpretiert, dann hast nur die zu php kompilierten templates auf dem 
Server.


> Was ist denn der Unterschied ob ich nun {$var} oder <?= $var; ?>
> schreibe? Oder in Blade halt {{ $var }}

Das wirst du lernen wenn in $var z.b. "<script>alert('this could be a 
xss-attack');</script>" steht :)

: Bearbeitet durch User
von Stefan R. (1994rstefan)


Lesenswert?

> - Man muss völlig sinnbefreit "noch eine Sprache" lernen, und zwar alle
> die eventuell mitwirken (z.Bsp. auch der Frontend-Entwickler).
Gerade Frontend-Entwickler sollten diese "Sprachen" bereits können.

> - Man muss eine IDE finden die das Syntax-Highlighting unterstützt damit
> es Spaß macht
Was, zumindest für Smarty, heutzutage so gut wie jede IDE tut.

> - Performance MUSS schlechter sein
Nicht wirklich, das Template wird in PHP-Code umgewandelt und 
gespeichert. Beim Aufruf der Seite wird dann direkt der PHP-Code 
ausgeführt.

> Was ist denn der Unterschied ob ich nun {$var} oder <?= $var; ?>
> schreibe? Oder in Blade halt {{ $var }}
Zumindest bis PHP 5.4 war das schlechter Stil, "<?=" konnte nur 
verwendet werden wenn auch die Short-Open-Tags aktiviert waren.

Bei deinem einfachen Beispiel erspart man sich natürlich noch nicht sehr 
viel Tipparbeit, bei folgenden Beispielen sieht das aber schon anders 
aus:
1
<?= strtoupper($var); ?>
2
3
{$var|upper}
1
<?= empty($var) ? 'keine Angabe' : $var; ?>
2
3
{$var|default:'keineAngabe'}
1
<?php if(empty($var)) :
2
    echo 'keine Einträge vorhanden';
3
else:
4
    foreach($var as $item) :
5
        echo $item;
6
    endforeach;
7
endif; ?>
8
9
{foreach from=$var item=$item}
10
    {$item}
11
{foreachelse}
12
    keine Einträge vorhanden
13
{/foreach}

Des weiteren werden bei Smarty Variablen escaped, die von dir genannten 
Beispiele haben also sogar einen sehr großen Unterschied.
Richtig wäre <?= htmlspecialchars($var, ENT_QUOTES); ?> vs {var}.

: Bearbeitet durch User
von Stefan R. (1994rstefan)


Lesenswert?

Wie wär es wenn du den Pfad zum Stylesheet einfach relativ zum 
Document-Root angibst? Dazu musst du am Anfang des Dateipfades einfach 
nur einen / einfügen, also wie folgt:
1
<link rel="stylesheet" type="text/css" href ="/assets/css/main.css">
Dadurch wird dann unabhängig davon ob du gerade [URI]/, [URI]/foo, 
[URI]/foo/bar aufrufst immer [URI]/assets/css/main.css geladen.
Alternativ könntest den Stylesheet auch wirklich komplett absolut 
angeben, also inklusive http://[URI]

von D. I. (Gast)


Lesenswert?

Würdest du Rails mit Trailblazer und HAML als Templateengine verwenden 
hättest du die Probleme wo was hingehört nicht :P

shots fired

von S R (Gast)


Lesenswert?

Leute, ich dachte nicht dass man hier noch erklären muss, dass Variablen 
escaped gehören...

Das erledigen gängige Template Helper wie e($str);


<?= ist nach PSR Standard gängig, vor-PHP 5.4 ist bitte keine Referenz 
mehr.


Ich benutze <?php dennoch nicht, weil es mir egal ist ob ich <?php echo 
oder <?= tippe.
1
<?php if(empty($var)) :
2
    echo 'keine Einträge vorhanden';
3
else:
4
    foreach($var as $item) :
5
        echo $item;
6
    endforeach;
7
endif; ?>

Würde ich so machen:
1
<?php if (empty($var)): ?>
2
    Keine Einträge vorhanden.
3
<?php else: ?>
4
    <?php foreach ($var as $item): ?>
5
        <?php echo e($item); ?>
6
    <?php endforeach; ?>
7
<?php endif; ?>


Die Mehrarbeit beim Tippen übernimmt die IDE.


> - Performance MUSS schlechter sein
Nicht wirklich, das Template wird in PHP-Code umgewandelt und
gespeichert. Beim Aufruf der Seite wird dann direkt der PHP-Code
ausgeführt.

Genau, aber beim ersten Aufruf muss auch das erstmal umgewandelt werden.

von S R (Gast)


Lesenswert?

Noch kurz zu meinem Beispiel oben; klar überwiegen da im Moment die 
<?php Tags; aber da im Realfall auch noch ein Haufen HTML dazwischen 
hängen wird, ist es so IMHO deutlich übersichtlicher.

von Daniel A. (daniel-a)


Lesenswert?

Es gibt in html auchnoch den "base" tag, welcher ändern kann wozu 
relative URLs relativ sind. Von der verwendung des "base" tags rate ich 
jedoch ab.

Ich habe mal eine Templateingengine zusammengehackt, die ich 
gelegentlich bei Schulaufgaben verwende. Ich mache das gewönlich so, 
dass ich bei jeder unterseite nur das Templateingscript einbinde. Dann 
lade ich das Haupttemplate und defineire alle Ordner, wo der Inhalt zu 
finden ist (Current Working Directory und ein anderes Verzeichnis, und 
ein Array). Dann Suche ich die zu ersetzenden teile mit preg_match (ich 
markiere die mit #var#, %var%, und !!!var!!!), suche den passenden 
content und ersetze den Platzhalter mit str_replace, und je nach 
Markierung escape ich alles mit htmlentities, oder evaluire php code, 
oder mache die Ersetzung vor jeglicher PHP code evaluation. Die 
Ersetzung ist dabei Rekursiv.

Dabei habe ich das Problem mit den Pfaden folgendermassen gelöst: 
(funktioniert nur wenn der Pfad keine Symlinks enthält)
1
$rootdir        = dirname(__FILE__);
2
$urlroot        = '/'.substr(realpath($rootdir),strlen(realpath($_SERVER['DOCUMENT_ROOT']))+1);
Und füge vor allen Pfaden htmlentities($urlroot) ein (ausser in den css 
files, dort sind die pfade relativ zum css file).
Eine bessere alternative zum Code oben wäre wohl:
1
$urlroot = str_repeat('../',substr_count($_SERVER['REQUEST_URI'],'/'));

Ausserdem ist __autoload ausserst praktisch um nicht alle mehrfach 
verwendeten klassen manuell einbinden zu müssen.

http://php.net/__autoload

von Planlos (Gast)


Lesenswert?

Daniel A. schrieb:
> Eine bessere alternative zum Code oben wäre wohl:$urlroot =
> str_repeat('../',substr_count($_SERVER['REQUEST_URI'],'/'));

Warum willst du das unbedingt relativ angeben? Damit sich der Webbrowser 
mit dem cachen schwerer tut?

Und beachte: REQUEST_URI kann je nach Server-Config (Reverse-Proxy usw.) 
auch gerne ein 'http://hostname/...'; enhalten. Dann zählst du zwei '/' 
zuviel. Und ein Query-String mit weiteren '/' kann auch noch dabei sein.

und sobald mod_rewrite für (Buzzword) SEO-Friendly URLs im Einsatz ist, 
versagt die Methode völlig, dann können es auch zuwenige sein.

von PHP-Noob (Gast)


Lesenswert?

Hallo,

nochmals vielen Dank für eure Hilfe!

Sheeva P. schrieb:
> Da habe ich mich vielleicht mißverständlich ausgedrückt: wenn ich von
> Design rede, meine ich nicht das grafische Design und Layout Deiner
> Website, sondern das Softwaredesign bzw. die Architektur.

Ich bezog mich beim "Programmierer" und "Designer" auf die Einleitung 
der Spezifikation von smarty. Dort wird DER Vorteil von Smarty dadurch 
beschrieben, dass der Programmierer und der Designer unabhängig 
voneinander und gleichzeitig an einem Projekt arbeiten können. Diese 
Anforderung habe ich aber ja nicht für meine Seite.


Ein gutes Design in der Software ist für mich sehr wichtig, deshalb 
frage ich ja auch hier nochmal nach. Und ich denke, dass ich smarty 
dafür nicht brauche, da ich der einzige Programmierer bin.

Wie hier einige Leute richtig geschrieben haben: Die Lösung im Falle der 
CSS-Datei ist ein einfacher Schrägstrich vor dem Pfad. Damit wird die 
CSS Datei immer gefunden, egal von wo aus sie gebraucht wird.

Wie im Beispiel ganz oben brauche ich für den HTML-Header noch den Titel 
der jeweiligen Seite. Dies habe ich jetzt durch eine Funktion 
GetHeader($title) im der PHP-Header Datei gelöst und denke, dass dies 
"die Richtige" Lösung sein sollte.
1
function GetHeader($title)
2
{
3
  return
4
    '<!DOCTYPE html>
5
    <html lang="de">
6
    <head>
7
      <title>'.$title.'</title>
8
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
9
      <link rel="stylesheet" type="text/css" href ="/static/main.css"> 
10
    </head>';
11
}

Ich werde bestimmt nochmal eine Frage zur konzeptionellen Struktur haben 
und werde mich dann nochmal melden.


Vielen Dank nochmal an alle!

von Smarter (Gast)


Lesenswert?

PHP-Noob schrieb:
> Und ich denke, dass ich smarty
> dafür nicht brauche, da ich der einzige Programmierer bin.

Falsche Herangehensweise. Damit gewöhnst Du Dir nur was Dummes an. Wenn 
mal ein zweiter/dritter dazukommt, willst Du dann umstellen? Ich sage ja 
auch nicht "Ich nehm grün/gelb für die Phase, bin ja der einzige 
Elektriker im Haus".

Ich nutze auch für private Projekte die strikte Trennung mittels Smarty. 
Hatte das vorher auch anders, aber der enstehende Verhau ist einfach nur 
hässlich. Außerdem kann so auch jemand an den Templates arbeiten ohne 
Dir die Programmierung oder mehr zu zerschiessen.

Bei deiner GetHeader() Lösung allerdings...
Kopierst du mal HTML Source mit einem ' rein haste nen Fehler und mußt 
suchen und escapen. Selbiges wenn Du " statt ' nutzt. Außerdem wird dann 
PHP noch alles mit einem $ als Variable betrachten.

Am Ende packt man auch noch CSS und JS mit rein, weil extra Dateien sind 
ja so uncool. Bei solchen Projekten gibt es bei mir nur eine Lösung:
rm -rf

von D. I. (Gast)


Lesenswert?

Smarter schrieb:
> Bei solchen Projekten gibt es bei mir nur eine Lösung:
> rm -rf

qft

von PHP-Noob (Gast)


Lesenswert?

Smarter schrieb:
> Ich sage ja
> auch nicht "Ich nehm grün/gelb für die Phase, bin ja der einzige
> Elektriker im Haus".

Naja, dieser Vergleich ist aus mehreren Gründen unpassend:

In deinem Fall
- besteht Lebensgefahr
- ist (spätestens beim Unfall) illegal
- ist die Wahrscheinlichkeit, dass eine andere Person da irgendwann 
rangehen wird nahezu 100% (z.B. nach einem Verkauf, einer Vermietung 
oder meinem Tod). Die Wahrscheinlichkeit, dass jemand an meinen 
Webseitenqullcode rangeht ist nahezu 0%.

Aber...

ich habe jetzt ein bisschen weiterprogrammiert, und merke, dass die 
Programmierung "unsauber wirkt" und ich werde wohl doch auf Smarty 
umstellen. (Noch ist es ja nicht zu spät)

Eine Frage hätt ich trotzdem nochmal vorab:

Ist die Prgrammierung mit Smarty was die Angreifbarkeit von Außen angeht 
sicherer oder vielleicht sogar unsicherer?

Als Beispiel nenne ich ein HTML-Formular, in dem einfach jemand ganz 
frech irgendeinen JavaScript Code reinschreibt? Oder ist das ein 
vollkommen unabhängiges Thema?

von K. J. (Gast)


Lesenswert?

PHP-Noob schrieb:
> Als Beispiel nenne ich ein HTML-Formular, in dem einfach jemand ganz
> frech irgendeinen JavaScript Code reinschreibt? Oder ist das ein
> vollkommen unabhängiges Thema?

Das ist wieder was anderes, Solche Felder prüfst du mit PHP auf 
Plausibilität, du würdest so ein Feld ja auch nicht direkt an eine DB 
übergeben weil da ja auch "blabla;drop table...." drinstehen könnte.

von PHP-Noob (Gast)


Lesenswert?

OK, danke.

von Bernd K. (prof7bit)


Lesenswert?

Warum willst Du eigentlich im Jahre 2016 noch ein neues Projekt mit PHP 
anfangen oder gar Lebenszeit mit der Einarbeitung in diese sterbende 
Museumstechnologie verbrauchen?

Wenn ich heute ein neues Web-Projekt anfangen wollte würde ich Go 
verwenden.

von lol (Gast)


Lesenswert?

Bernd K. schrieb:
> PHP
> anfangen oder gar Lebenszeit mit der Einarbeitung in diese sterbende
> Museumstechnologie verbrauchen?

lol, ymmd :'D

totgesagte leben länger, sieht man sehr gut an c.

von Sheeva P. (sheevaplug)


Lesenswert?

Bernd K. schrieb:
> Wenn ich heute ein neues Web-Projekt anfangen wollte würde ich Go
> verwenden.

Ich nicht.

von Bernd K. (prof7bit)


Lesenswert?

lol schrieb:
> totgesagte leben länger, sieht man sehr gut an c.

Naja, der Vergleich hinkt. Für C(++) hat sich noch kein Nachfolger 
etabliert der es in allen denkbaren Einsatzgebieten ersetzt und in 
jeder Hinsicht übertrifft. Das wird der Grund sein für sein 
hartnäckiges Nichtverschwinden

Aber bei PHP verhält es sich genau umgekehrt: Kannst Du zum Beispiel 
irgendeine aktuelle Alternative zu PHP nennen die in irgendeiner 
Kategorie noch schlechter abschneidet als PHP? Serverside-Brainfuck 
vielleicht, aber sonst noch welche? Da muss man schon angestrengt 
nachdenken.

: Bearbeitet durch User
von Sheeva P. (sheevaplug)


Lesenswert?

PHP-Noob schrieb:
> ich habe jetzt ein bisschen weiterprogrammiert, und merke, dass die
> Programmierung "unsauber wirkt" und ich werde wohl doch auf Smarty
> umstellen. (Noch ist es ja nicht zu spät)

;-)

> Ist die Prgrammierung mit Smarty was die Angreifbarkeit von Außen angeht
> sicherer oder vielleicht sogar unsicherer?

Smarty ist nur eine Templateengine und setzt die Daten, die Du ihm 
gibst, in Deine Templates ein. Wenn Deine Daten ordentlich validiert 
worden sind, hat Smarty überhaupt keine Auswirkungen auf das 
Sicherheitsniveau.

Nur wenn Du Deine Daten nicht ordentlich validierst, bietet Smarty eine 
kleine Verbesserung der Sicherheit: normalerweise maskiert Smarty die 
Ausgabedaten, ersetzt also zum Beispiel "<" und ">" durch die passenden 
HTML-Entities "&lt;" und "&gt;". Wo es gewünscht ist, kannst Du das mit 
einem Smarty-Filter (|safe) ausschalten, dann ist Deine Applikation an 
dieser einen Stelle genauso unsicher wie ohne Smarty. Trotzdem ist die 
einzige Möglichkeit, die Sicherheit Deiner Applikation zu gewährleisten, 
die korrekte und vollständige Validierung aller Eingabedaten, die aus 
nicht-vertrauenswürdigen Quellen kommen.

> Als Beispiel nenne ich ein HTML-Formular, in dem einfach jemand ganz
> frech irgendeinen JavaScript Code reinschreibt? Oder ist das ein
> vollkommen unabhängiges Thema?

Der kluge PHP-Entwickler benutzt für so etwas HTML_QuickForm2. Damit 
kann man nicht nur Formulare erstellen, sondern auch Funktionen zur 
Validierung der Eingaben definieren und ausführen -- die Sicherheit 
Deiner Applikation steht und fällt mit der Qualität Deiner Validierung. 
Ein Beispiel findest Du hier: [1].

HTML_QuickForm2 bietet Dir außerdem die Möglichkeit, Deine Eingabedaten 
bereits clientseitig vor dem Absenden mit JavaScript zu überprüfen. Das 
hat den Vorteil, daß invalide Daten normalerweise gar nicht erst auf dem 
Server ankommen, was Deinen Server schont, und die Benutzer eine 
deutlich schnellere Rückmeldung bekommen, was Deine Benutzer schont. 
Wichtig ist allerdings, daß eine clientseitige Validierung die 
serverseitige höchstens unterstützen, aber niemals ersetzen kann, da die 
clientseitige Validierung bei böswilligen Benutzern und solchen, die 
JavaScript deaktiviert haben, natürlich nicht funktioniert.

Insofern: immer serverseitig validieren -- und zwar wirklich ALLES, auch 
einen simplen Radiobutton, eine Checkbox oder eine Selectbox. Den Schutz 
gegen CSRF nicht vergessen!


[1] 
https://pear.php.net/manual/en/package.html.html-quickform2.tutorial.php

von Dirk D. (dicky_d)


Lesenswert?

Sheeva P. schrieb:

> Smarty ist nur eine Templateengine und setzt die Daten, die Du ihm
> gibst, in Deine Templates ein. Wenn Deine Daten ordentlich validiert
> worden sind, hat Smarty überhaupt keine Auswirkungen auf das
> Sicherheitsniveau.

Das ist  nur die halbe Wahrheit, valide Daten müssen ggf. noch Escaped 
werden, und zwar passend zur Ausgabemethode.
Du musst z.B. ein Freitextfeld anders Escapen, je nach dem ob es als 
Text im HTML, in einem Attribut, oder als teil eines Links verwendest.
da du ja vorher nicht weißt wo du die Daten im Template benötigst, und 
diese evtl sogar mehrfach nutzt muss das Escapen im Template selbst 
passieren.

Beispiel:

deine Daten:

  Er sagte: "Meine Mama ist die Beste!"

das Kannst du innerhalb eines Textbereiches in HTML einfach so 
durchgehen lassen.

Wenn das aber ein Attribut eines Elements werden soll, z.b. Der Text 
eines Buttons musst du die Anführungszeichen durch &quot; ersetzen.

Soll der Text als Get-Parameter an einen Link angehängt werden sind 
wieder andere dinge zu tun...



An sonnsten kann ich mich dir da nur anschließen.

von Sheeva P. (sheevaplug)


Lesenswert?

Bernd K. schrieb:
> lol schrieb:
>> totgesagte leben länger, sieht man sehr gut an c.
>
> Naja, der Vergleich hinkt. Für C(++) hat sich noch kein Nachfolger
> etabliert der es in allen denkbaren Einsatzgebieten ersetzt und in
> jeder Hinsicht übertrifft. Das wird der Grund sein für sein
> hartnäckiges Nichtverschwinden
>
> Aber bei PHP verhält es sich genau umgekehrt: Kannst Du zum Beispiel
> irgendeine aktuelle Alternative zu PHP nennen die in *irgendeiner*
> Kategorie noch schlechter abschneidet als PHP? Serverside-Brainfuck
> vielleicht, aber sonst noch welche? Da muss man schon angestrengt
> nachdenken.

Naja, "aktuell"... Server-Side Includes existieren. ;-)

von Sheeva P. (sheevaplug)


Lesenswert?

Dirk D. schrieb:
> Sheeva P. schrieb:
>
>> Smarty ist nur eine Templateengine und setzt die Daten, die Du ihm
>> gibst, in Deine Templates ein. Wenn Deine Daten ordentlich validiert
>> worden sind, hat Smarty überhaupt keine Auswirkungen auf das
>> Sicherheitsniveau.
>
> Das ist  nur die halbe Wahrheit, valide Daten müssen ggf. noch Escaped
> werden, und zwar passend zur Ausgabemethode.

Nein, das war die ganze Wahrheit. Die Daten werden auf der Eingabeseite 
validiert, Smarty macht hingegen nur die Ausgabe. Die Darstellung, um 
die sich Smarty kümmert, ist allerdings nicht sicherheitsrelevant, da 
die Daten ja bereits auf der Eingangsseite validiert worden sind.

von Dirk D. (dicky_d)


Lesenswert?

Sheeva P. schrieb:
> Dirk D. schrieb:
>> Sheeva P. schrieb:
>>
>>> Smarty ist nur eine Templateengine und setzt die Daten, die Du ihm
>>> gibst, in Deine Templates ein. Wenn Deine Daten ordentlich validiert
>>> worden sind, hat Smarty überhaupt keine Auswirkungen auf das
>>> Sicherheitsniveau.
>>
>> Das ist  nur die halbe Wahrheit, valide Daten müssen ggf. noch Escaped
>> werden, und zwar passend zur Ausgabemethode.
>
> Nein, das war die ganze Wahrheit. Die Daten werden auf der Eingabeseite
> validiert, Smarty macht hingegen nur die Ausgabe. Die Darstellung, um
> die sich Smarty kümmert, ist allerdings nicht sicherheitsrelevant, da
> die Daten ja bereits auf der Eingangsseite validiert worden sind.


ich hab dir dafür doch grade schon ein beispiel geliefert.

was valide ist oder nicht bestimmt einzig und alleine dein Datenmodell.

Und wenn dein Datenmodell vorsieht das Doppelte Anführungszeichen oder 
Leerzeichen valide sind dann ist das so.

Trotzdem musst du das je nach Ausgabemethode Escapen.

von Daniel A. (daniel-a)


Lesenswert?

Sheeva P. schrieb:
> Die Darstellung, um
> die sich Smarty kümmert, ist allerdings nicht sicherheitsrelevant, da
> die Daten ja bereits auf der Eingangsseite validiert worden sind.

Das ist nicht immer der richtige Ort für sowas. Nehmen wier z.B. die 
Postform dieses Forums. Hier kann man wegen der Validation keinen 
HTML-Code mit einem Link-Tag posten. Das ist absolut bescheuert, weil 
dass, wenn es immer korrekt escaped wird, vollkomen unbedenklich und 
manchmal sogar notwendig ist.

von Planlos (Gast)


Lesenswert?

Daniel A. schrieb:
> Hier kann man wegen der Validation keinen
> HTML-Code mit einem Link-Tag posten.

Falsche Baustelle. Das filtern von “hre f“ dient hier nur der 
SPAM-Abwehr.

von Sheeva P. (sheevaplug)


Lesenswert?

Dirk D. schrieb:
>> Nein, das war die ganze Wahrheit. Die Daten werden auf der Eingabeseite
>> validiert, Smarty macht hingegen nur die Ausgabe. Die Darstellung, um
>> die sich Smarty kümmert, ist allerdings nicht sicherheitsrelevant, da
>> die Daten ja bereits auf der Eingangsseite validiert worden sind.
>
>
> ich hab dir dafür doch grade schon ein beispiel geliefert.
>
> was valide ist oder nicht bestimmt einzig und alleine dein Datenmodell.
>
> Und wenn dein Datenmodell vorsieht das Doppelte Anführungszeichen oder
> Leerzeichen valide sind dann ist das so.
>
> Trotzdem musst du das je nach Ausgabemethode Escapen.

Ok, nochmal langsam: die Validierung stellt sicher, daß die 
Eingangsdaten dem Datenmodell entsprechen. Wenn sie das nicht tun, nehme 
ich die Daten nicht entgegen und weise sie zurück. Auf diese Weise 
kommen erst gar keine Daten in mein System, die meinem Datenmodell nicht 
entsprechen würden. Anders gesagt: nach einer korrekten Validierung auf 
der Eingabeseite sind die Daten in meinem Systems per se 
vertrauenswürdig. Das ist ja der ganze Sinn einer Eingabevalidierung: 
aus nichtvertrauenswürdigen Eingabedaten vertrauenswürdige Eingabedaten 
zu machen.

Die Ausgabe validierter, mithin: vertrauenswürdiger Daten hat, egal, ob 
mit Escaping oder ohne, zwar etwas mit meinem Datenmodell zu tun, aber 
nichts mehr mit der Sicherheit. Denn meine Daten sind ja eingangs schon 
geprüft worden, jetzt geht es nur noch um die Darstellung valider Daten.

Richtig ist, daß die Darstellung und das Escaping der Daten von meinem 
Datenmodell abhängen. Aber mit der Sicherheit von Smarty -- und die war 
gefragt -- hat das nichts mehr zu tun.

von Sheeva P. (sheevaplug)


Lesenswert?

Daniel A. schrieb:
> Sheeva P. schrieb:
>> Die Darstellung, um
>> die sich Smarty kümmert, ist allerdings nicht sicherheitsrelevant, da
>> die Daten ja bereits auf der Eingangsseite validiert worden sind.
>
> Das ist nicht immer der richtige Ort für sowas.

Aber natürlich ist das der richtige Ort für sowas. Wo sollte der denn 
sonst sein? Bevor ein Programm mit Eingabedaten arbeiten kann, muß 
sichergestellt sein, daß diese valide sind. Und das kann natürlich nur 
dort geschehen, wo das Programm die Daten annimmt.

> Nehmen wier z.B. die
> Postform dieses Forums. Hier kann man wegen der Validation keinen
> HTML-Code mit einem Link-Tag posten. Das ist absolut bescheuert, weil
> dass, wenn es immer korrekt escaped wird, vollkomen unbedenklich und
> manchmal sogar notwendig ist.

Mir ist leider nicht ganz klar, was Du mir mit diesem Beispiel sagen 
möchtest. Daß die Forensoftware HTML-Links zulassen sollte?

von Dirk D. (dicky_d)


Lesenswert?

Sheeva P. schrieb:

>> Trotzdem musst du das je nach Ausgabemethode Escapen.
>
> Ok, nochmal langsam: die Validierung stellt sicher, daß die
> Eingangsdaten dem Datenmodell entsprechen. Wenn sie das nicht tun, nehme
> ich die Daten nicht entgegen und weise sie zurück. Auf diese Weise
> kommen erst gar keine Daten in mein System, die meinem Datenmodell nicht
> entsprechen würden. Anders gesagt: nach einer korrekten Validierung auf
> der Eingabeseite sind die Daten in meinem Systems per se
> vertrauenswürdig. Das ist ja der ganze Sinn einer Eingabevalidierung:
> aus nichtvertrauenswürdigen Eingabedaten vertrauenswürdige Eingabedaten
> zu machen.
>
> Die Ausgabe validierter, mithin: vertrauenswürdiger Daten hat, egal, ob
> mit Escaping oder ohne, zwar etwas mit meinem Datenmodell zu tun, aber
> nichts mehr mit der Sicherheit. Denn meine Daten sind ja eingangs schon
> geprüft worden, jetzt geht es nur noch um die Darstellung valider Daten.
>
> Richtig ist, daß die Darstellung und das Escaping der Daten von meinem
> Datenmodell abhängen. Aber mit der Sicherheit von Smarty -- und die war
> gefragt -- hat das nichts mehr zu tun.

Okay, noch viel langsamer, extra für dich:

Stell dir vor: Du willst sowas wie pastebin.com, oder ein Forum 
implementieren.

Plötzlich besteht dein Datenmodell darauf das HTML und JavaScript valide 
Daten sind.

Das Daten vertrauenswürdig sind heißt ja nur das da nichts drin ist was 
du da nicht drin erwartest, das heißt nicht das die Daten nicht ggf. 
doch gefährlich sind.


Beispiele:
 - du erwartest einen Integer, du bekommst '1a'. das Validiert nicht, 
alles okay.
 - du erwartest einen Integer, du bekommst '11'. Das Validiert, alles 
okay.
 - du erwartest ein Forumspost, du bekommst "Hallo, ich habe ein Problem 
mit folgendem Javascript. " onclick="alert("test");', das wird 
validieren.
wenn du letzes Beispiel aber mit Hilfe von Smarty als value für ein 
Eingabefeld setzen willst und smarty nicht mitteilst das du das 
gesondert escaped haben willst ist das gefährlich.

Smarty versteht die Syntax der zu erzeugenden Sprache nicht und geht, 
wenn du ihm nichts anderes sagst, davon aus das du in html-text 
schreiben willst.


Du kannst dich natürlich auf den Standpunkt stellen das valide Daten so 
simple Typen sind wie: Integer, oder string der nur aus Klein- und 
Großbuchstaben sowie Leerzeichen bestehen.
Damit wirst du aber nicht sonderlich weit kommen...

von Dirk D. (dicky_d)


Lesenswert?

Sheeva P. schrieb:
> Daniel A. schrieb:
>> Sheeva P. schrieb:
>>> Die Darstellung, um
>>> die sich Smarty kümmert, ist allerdings nicht sicherheitsrelevant, da
>>> die Daten ja bereits auf der Eingangsseite validiert worden sind.
>>
>> Das ist nicht immer der richtige Ort für sowas.
>
> Aber natürlich ist das der richtige Ort für sowas. Wo sollte der denn
> sonst sein? Bevor ein Programm mit Eingabedaten arbeiten kann, muß
> sichergestellt sein, daß diese valide sind. Und das kann natürlich nur
> dort geschehen, wo das Programm die Daten annimmt.
>
>> Nehmen wier z.B. die
>> Postform dieses Forums. Hier kann man wegen der Validation keinen
>> HTML-Code mit einem Link-Tag posten. Das ist absolut bescheuert, weil
>> dass, wenn es immer korrekt escaped wird, vollkomen unbedenklich und
>> manchmal sogar notwendig ist.
>
> Mir ist leider nicht ganz klar, was Du mir mit diesem Beispiel sagen
> möchtest. Daß die Forensoftware HTML-Links zulassen sollte?


Genau da schient dein Problem zu sein.

in diesem Forum kann und soll ich ja quellcode posten dürfen.
Warum dann nicht auch Quellcode mit einem link in html.
der Clue ist, das in der Ausgabe der link nicht 1 zu 1 ausgegeben wird, 
sondern so escaped wird das der Benutzer das sieht was ich eingebe,

wenn ich <b>fett</b> tippe siehst du ja auch nicht fett sonder 
<b>fett</b>.

Das ist der unterschied zwischen Validierung und escaping.

von Sheeva P. (sheevaplug)


Lesenswert?

Dirk D. schrieb:
> Okay, noch viel langsamer, extra für dich:

Bald sind wir hier in Zeitlupe unterwegs. ;-)

> Stell dir vor: Du willst sowas wie pastebin.com, oder ein Forum
> implementieren.
>
> Plötzlich besteht dein Datenmodell darauf das HTML und JavaScript valide
> Daten sind.

Ok, stelle ich mir vor.

>  - du erwartest ein Forumspost, du bekommst "Hallo, ich habe ein Problem
> mit folgendem Javascript. " onclick="alert("test");', das wird
> validieren.
> wenn du letzes Beispiel aber mit Hilfe von Smarty als value für ein
> Eingabefeld setzen willst und smarty nicht mitteilst das du das
> gesondert escaped haben willst ist das gefährlich.

Nö. In meiner Eingangsschnittstelle werden die Daten natürlich vor der 
Weiterverarbeitung in etwas Ungefährliches konvertiert. Das erst am 
Ausgang zu machen, halte ich für grob fahrlässig.

Das, was Du dort oben als Beispiel heranziehst, würde ich nicht weiter 
verarbeiten wollen, schon wegen der Double- und Singlequotes. Mit sowas 
kann man sich ziemlich fiese SQL-Injections einfangen. Deswegen möchte 
ich das JavaScript aus Deinem Beispiel auch nicht in meiner Loganalyse 
oder sonstwo sehen. Darum gehe ich in solchen Fällen den Umweg, die 
Daten entweder zu konvertieren oder, wo das nicht möglich ist, 
wenigstens in Base64 zu enkodieren.

von Bernd K. (prof7bit)


Lesenswert?

Sheeva P. schrieb:
> Nö. In meiner Eingangsschnittstelle werden die Daten natürlich vor der
> Weiterverarbeitung in etwas Ungefährliches konvertiert. Das erst am
> Ausgang zu machen, halte ich für grob fahrlässig.

Das könnte man auch in den Griff bekommen wenn man eine Sprache hat bei 
der man zwei verschiedene String-Typen deklarieren kann die NICHT 
zuweisungskompatibel sind und es dann so arrangiert daß Benutzereingaben 
grundsätzlich als der eine Typ reinkommen und Ausgaben zum HTML-Template 
oder zur Datenbank grundsätzlich nur den anderen Typ akzeptieren und der 
einzige Weg zur Umwandlung von Typ A nach Typ B eine Funktion ist die 
das Escapen erledigt, die Typ A als Parameter akzeptiert und Typ B 
zurückliefert.

So kann man übriges auch unbeabsichtigte Abstürze von NASA Marssonden 
verhindern indem man unterschiedliche Datentypen für metrische und 
imperiale Einheiten definiert die nicht zuweisungskompatibel sind und 
einen zwingen über eine Konvertierungsfunktion zu gehen. So ein Fehler 
würde dann schon zuhause im Compiler knallen und nicht erst Monate 
später auf der Planetenoberfläche.

: Bearbeitet durch User
von smarter (Gast)


Lesenswert?

Dirk D. schrieb:
> wenn du letzes Beispiel aber mit Hilfe von Smarty als value für ein
> Eingabefeld setzen willst und smarty nicht mitteilst das du das
> gesondert escaped haben willst ist das gefährlich.

Und wo ist der Unterschied dazu, wenn Du das nun direkt in PHP via echo 
ausgibst? Du teilst PHP mit "Hey, das mußt Du aber escaped echo'en"? 
Wenn du das mit htmlentities() machst, kannst Du den Wert auch einfach 
der Smarty Variablen zuweisen.

> Smarty versteht die Syntax der zu erzeugenden Sprache nicht und geht,
> wenn du ihm nichts anderes sagst, davon aus das du in html-text
> schreiben willst.

Korrigiere mich, aber wo sagst Du bitteschön Smarty was für eine Sprache 
die Ausgabe hat? Du definierst Templates, und was die nun sind ist 
schnurzegal. Das ist einfach Text, und darin werden Daten ausgegeben. 
Was soll es Smarty kümmern daß das nun meist eben HTML ist? Du kannst 
auch einfach C oder Assembler, Esperanto oder sonstwas schreiben. Den 
Inhalt liefert ja PHP.


> Du kannst dich natürlich auf den Standpunkt stellen das valide Daten so
> simple Typen sind wie: Integer, oder string der nur aus Klein- und
> Großbuchstaben sowie Leerzeichen bestehen.
> Damit wirst du aber nicht sonderlich weit kommen...
Alle Daten die von Userseite kommen haben immer auf den kleinstmöglichen 
Nenner gebracht zu werden. Wenn Du zB via Browser einen Shop 
durchblätterst, dann versuche nur INT für die IDs zu verwenden; das 
vereinfacht die Prüfung. Klar, Text muß man leider auch annehmen.

von smarter (Gast)


Lesenswert?

Bernd K. schrieb:
> oder zur Datenbank grundsätzlich nur den anderen Typ akzeptieren

Kann es sein daß Du noch nicht mit Prepared Statements arbeitest?

von Daniel A. (daniel-a)


Lesenswert?

@sheevaplug

Du machst es einfach falsch, genau mit deinem Ansatz fängt man sich SQL 
Injection und co. nämlich ein, und Leute wie die Nulls haben darunter zu 
leiden:
http://www.wired.com/2015/11/null/
http://thenextweb.com/insider/2016/03/27/last-name-null-is-tough-for-computers/#gref

Wenn man nur die Eingabe auf Validität prüft, wird man zwangslaufig 
vergessen auf irgendein Keyword zu prüfen. Nur in Base64 zu Encodieren 
ist auch keine lösung, denn das macht den text um ca. 1/4 grösser, 
verhindert das Durchsuchen der Datenbank und vor der Ausgabe beim 
Benutzer muss man es wieder dekodieren, weil dieser kein Base64 
versteht. Man sollte auch nicht vor sämtlichen Verarbeitungen die Daten 
escapen, denn bei unterschiedlichen Ausgabeformaten muss anders escapt 
werden, und es darf auch nichts doppelt escapt werden. Wenn du z.B. alle 
'<' mit '&gt;' und '&' mit '&amp;' escapst, direkt nach dem Empfangen, 
und du es dann in eine Datenbank schreiben würdest, dann hast du 
folgende Probleme:
 1) Du kannst die Daten vor der Ausgabe nichtmehr escapen, da dann aus 
'&gt;' '&amp;gt;' würde
 2) Wen jemand manuell in die DB reingeschrieben hat, ist das bei der 
Ausgabe nichtmehr validiert & escapt
 3) Wenn du aus den Daten dann ein PDF erstellen wills, steht überall 
statt '<' nur '&gt;'
 4) Du kannst immernoch Keywords übersehen

Wenn man es Richtig machen will, sollte man folgendes tun:
 * Alle Daten müssen mindestens auf der Serverseite und optional 
ebenfalls auf der Clientseite direkt nach dem Versenden auf Plausiblität 
geprüft werden, ohne dabei zu restriktiv zu sein (z.B. name null und 
sonderzeichen erlauben)
 * Die Daten werden erst direkt vor der Ausgabe für die Ausgabe escapt 
(bei PHP und HTML kann man mit htmlentities nicht viel falsch machen 
(ausser man nutzt es in einem script tag)) (1)
 * Man nutzt geprüfte verfahren um SQL injections zu verhindern, und 
lässt sich SQL Queries mittels Prepared statements escapen. (In PHP 
verwende ich PDO) (2)
 * Jede Funktion überprüft nocheinmal die übergebenen Werte und wirft 
gegebenenfaqlls eine Exception
 * Alle Exceptions werden korrekt behandelt, alles muss mit 
automatisierten Tests getestet sein
 * Benutzereingaben dürfen keinen Einfluss auf Pfade, Dateinamen oder 
URLs haben. Sollte dies dennoch notwendig werden empfehle ich nur wenige 
Zeichen zuzulassen ( Beispielsweise mit dem Regex /^[a-zA-Z0-9_-]+$/ )
 * Alle Funktionen müssen korrekt mit Nullbytes in Strings umgehen 
können
 * Benutzereingaben dürfen nicht in Scripttags, Eval-Statements oder 
Vergleichbarem auftauchen.

1) http://php.net/htmlentities
2) http://php.net/manual/de/pdo.prepared-statements.php

von Sheeva P. (sheevaplug)


Lesenswert?

Daniel A. schrieb:
> Du machst es einfach falsch, genau mit deinem Ansatz fängt man sich SQL
> Injection und co. nämlich ein, und Leute wie die Nulls haben darunter zu
> leiden:
> http://www.wired.com/2015/11/null/
> 
http://thenextweb.com/insider/2016/03/27/last-name-null-is-tough-for-computers/#gref

Nö, nö, nö, und nö. Bei mir sind die Nulls sicher.

> Wenn man nur die Eingabe auf Validität prüft, wird man zwangslaufig
> vergessen auf irgendein Keyword zu prüfen.

Da hast Du wohl etwas flashc verstanden. Ich prüfe nicht auf Keywords, 
wie kommst Du auf das schmale Brett? Die armen Nulls haben vor mir 
überhaupt nichts zu befürchten, denn nach PHPs htmlentities() oder 
Pythons encode() Funktionen sind Frau und Herr Null immer noch Frau und 
Herr Null. Huch!

Ehrlich jetzt, ich weiß gar nicht, was und woher Du Deine komischen 
Ideen hast, wie ich meine Eingabedaten behandle. Ich werfe gar keine 
Daten weg; ich konvertiere sie nur so, daß sie keine "bösen Zeichen" 
mehr enthalten, aber ansonsten noch genau dieselben Informationsgehalt 
haben wie vor der Konvertierung. Der Unterschied zwischen "'1'" und "1" 
ist 48, sonst nix.

> Nur in Base64 zu Encodieren ist auch keine lösung, denn das macht den
> text um ca. 1/4 grösser,

Schlimmer: um mindestens ein Drittel. Na und? Speicher ist billiger als 
Sicherheit UND als Entwicklungszeit. Aber, wie gesagt, das ist wirklich 
nur was für ganz besondere Ausnahmefälle.

> verhindert das Durchsuchen der Datenbank und

In Deiner Datenbank vielleicht. In meiner nicht:
1
SELECT ... WHERE decode(posting, 'base64') ILIKE ...;

Und bevor Du jetzt auf den Gedanken kommst, daß das auf der DB ja 
ziemlich teuer wäre: ja, aber da hat meine Datenbank einige feine 
Möglichikeiten in petto, aber darum kümmere ich mich, wenn die 
Performance nicht reicht oder degradiert.

> vor der Ausgabe beim Benutzer muss man es wieder dekodieren, weil dieser
> kein Base64 versteht.

Was hast denn Du für komische User, die kein Base64 verstehen? ;-)

> Man sollte auch nicht vor sämtlichen Verarbeitungen die Daten
> escapen, denn bei unterschiedlichen Ausgabeformaten muss anders escapt
> werden, und es darf auch nichts doppelt escapt werden.

Ach, weißt Du, das Schöne an einer möglichst frühzeitigen Konvertierung 
der Daten auf der Eingangsschnittstelle ist, daß ich im ganzen Programm 
nur halbwegs sichere Daten habe und mir um deren Escaping nur noch dann 
Gedanken machen muß, wenn ich wirklich einmal an die Rohdaten kommen 
muß. Und in diesem speziellen Fall gibt es zu "htmlspecialchars()" in 
PHP die wunderbare Funktion namens "htmlspecialchars_decode()", welche 
das Ganze problemlos wieder rückgängig macht, aber eben nur gezielt und 
ganz genau dort, wo ich Rohdaten brauche.

Wenn ich eine Forensoftware entwickle, die Codelistings ermöglichen 
soll, spielt es für den Programmlauf gar keine Rolle, ob ich die Daten 
auf der Eingangs- oder der Ausgangsschnittstelle konvertiere. Aber wenn 
ich drei oder mehr Subsysteme (für eine sehr einfache Webaplikation etwa 
Ausgabe, Datenbank und Logging) mit den Daten bedienen muß, fühle ich 
mich einfach viel wohler, wenn ich nicht mehr darauf achten muß, ob da 
Quotes und/oder Doublequotes oä. drin vorkommen. Billiger in Bezug auf 
Ressourcen ist es auch: meine CPU muß nämlich nicht in jedem Subsystem 
eine speicher- und rechenintensive Verarbeitung meiner Eingabedaten 
durchrödeln, damit die Daten ins Subsystem passen.

Schau, ich mache es halt anders als Du. Dabei würde ich im Gegensatz zu 
Dir aber nie auf die Idee kommen, zu behaupten, daß Du es flahcs machst. 
Aber während Du bei jedem Zugriff auf Deine unsicheren Variableninhalte 
jedesmal darüber nachdenken mußt, ob diese Bibliothek, jenes Subsystem, 
oder der nächste Softwarelayer mit dem klarkommt, was potentiell in den 
Variablen stehen könnte, bin ich da vollkommen entspannt, weil ich weiß, 
daß es mit meiner Datenbank, meinem OR-Mapper, mit MongoDB, Redis, dem 
Logging oder LaTeX oder sonstwas keine Probleme geben kann. Und da ich 
bevorzugt WTForms benutze, kann ich die Konvertierfunktionen für meine 
Eingaben gänzlich entspannt an meine Formularelemente klemmen. Für URLs 
hat Flask, mein Lieblings-Microframework für Python, sogar einen ganz 
eigenen Mechanismus für die einfache Validierung und Konvertierung:
1
@app.route('/showCustomer/<id:int>')
2
def showCustomer():
3
    id += 1000
4
    return render_template('showUser.html', user=Customer.get(id))

Ansonsten muß ich PHP zum Glück schon lange nicht mehr benutzen. Aber 
wenn ich noch müßte, würde ich den Teufel tun und so etwas Primitives 
wie PDO (oder, in meiner Sprache: dbapi2) verwenden. Das führt nämlich 
früher oder später dazu, daß der SQL-Code immer abhängiger von der 
konkreten Datenbank wird. Deswegen greife ich, wann immer es die 
Performance zuläßt, zu einem OR-Mapper; für PHP wäre das bei mir 
Doctrine, in meiner Sprach gibt es da Werkzeuge wie SQLAlchemy und 
SQLObject, die sich um die ganzen hirnlosen Nickeligkeiten kümmern und 
im Gegensatz zu primitiven DB-APIs wie PDO und dbapi2 eine echte 
Abstraktion des Datenbanklayers bieten. Jeilomat, wa?

von Daniel A. (daniel-a)


Lesenswert?

Sheeva P. schrieb:
> Wenn man nur die Eingabe auf Validität prüft, wird man zwangslaufig
>> vergessen auf irgendein Keyword zu prüfen.
>
> Da hast Du wohl etwas flashc verstanden. Ich prüfe nicht auf Keywords,
> wie kommst Du auf das schmale Brett?

...

> Ehrlich jetzt, ich weiß gar nicht, was und woher Du Deine komischen
> Ideen hast, wie ich meine Eingabedaten behandle. Ich werfe gar keine
> Daten weg; ich konvertiere sie nur so, daß sie keine "bösen Zeichen"
> mehr enthalten, aber ansonsten noch genau dieselben Informationsgehalt
> haben wie vor der Konvertierung.

Das ist dann aber keine Validation mehr, sondern etwas ähnliches wie 
Escapen. In deinen ersten beiden Posts redest du nur von Validieren. Du 
hast sogar folgendes geschrieben:

Sheeva P. schrieb:
> Nein, das war die ganze Wahrheit. Die Daten werden auf der Eingabeseite
> validiert, Smarty macht hingegen nur die Ausgabe. Die Darstellung, um
> die sich Smarty kümmert, ist allerdings nicht sicherheitsrelevant, da
> die Daten ja bereits auf der Eingangsseite validiert worden sind.

Dies impliziert das du nur eine Validation durchfürst. Das ist ein wenig 
als würde man sagen: "Hey, ich prüfe die Daten nur einmal auf 
Korrektheit, danach ist alles sicher", und dann auf Einwände Antwortet: 
"Ich konvertiere es hier und hier, so überprüfe ich die Eingaben, wie 
bist du auf andere Ideen gekommen?". Validieren beinhaltet nunmal nicht 
Escapen. Es geht um die Terminologie.

Sheeva P. schrieb:
> SELECT ... WHERE decode(posting, 'base64') ILIKE ...;

Perfekt, schon habe ich meinen ersten Angriffsvektor. Hier kann ich dir 
beliebige MySQL Keywords unterjubeln, z.B. "\x9Eée" für null. Mich hält 
soetwas nicht von von SQL Injection ab.

PS: Wenn du mir die URL zu deiner Homepage gibst könnte ich dort für 
dich nach Sicherheitslücken suchen.

von Dirk D. (dicky_d)


Lesenswert?

Sheeva P. schrieb:
> Dirk D. schrieb:
>> Okay, noch viel langsamer, extra für dich:
>
> Bald sind wir hier in Zeitlupe unterwegs. ;-)

--- Wenn das Nötig ist das du die Sachlage verstehst :)
>
>> Stell dir vor: Du willst sowas wie pastebin.com, oder ein Forum
>> implementieren.
>>
>> Plötzlich besteht dein Datenmodell darauf das HTML und JavaScript valide
>> Daten sind.
>
> Ok, stelle ich mir vor.
>
>>  - du erwartest ein Forumspost, du bekommst "Hallo, ich habe ein Problem
>> mit folgendem Javascript. " onclick="alert("test");', das wird
>> validieren.
>> wenn du letzes Beispiel aber mit Hilfe von Smarty als value für ein
>> Eingabefeld setzen willst und smarty nicht mitteilst das du das
>> gesondert escaped haben willst ist das gefährlich.
>
> Nö. In meiner Eingangsschnittstelle werden die Daten natürlich vor der
> Weiterverarbeitung in etwas Ungefährliches konvertiert. Das erst am
> Ausgang zu machen, halte ich für grob fahrlässig.

Und du weißt am Eingang schon welche Subsysteme mit deinen Daten in 
Berührung kommen und kennst alle Fallstricke aller Subsysteme?


>
> Das, was Du dort oben als Beispiel heranziehst, würde ich nicht weiter
> verarbeiten wollen, schon wegen der Double- und Singlequotes.

Du fühlst dich also nicht dazu in der Lage in Forum zu Programmieren in 
dem man Code-Snipets posten darf, willst aber Ratschläge genen wie man 
richtig Programmiert?

> Mit sowas
> kann man sich ziemlich fiese SQL-Injections einfangen.
Aber nur wenn man Fahrlässig genug ist die Existens von Prepared 
Statements zu ignorieren.

> Deswegen möchte
> ich das JavaScript aus Deinem Beispiel auch nicht in meiner Loganalyse
> oder sonstwo sehen.
Ist die auch von dir geschrieben?

> Darum gehe ich in solchen Fällen den Umweg, die
> Daten entweder zu konvertieren oder, wo das nicht möglich ist,
> wenigstens in Base64 zu enkodieren.

Oh das klingt total clever, und das löst auch nicht das 
Ursprungs-Problem, nämlich das du die Daten ne nach Ausgabe-situation 
anders Escapen musst.

von Dirk D. (dicky_d)


Lesenswert?

smarter schrieb:
> Dirk D. schrieb:
>> wenn du letzes Beispiel aber mit Hilfe von Smarty als value für ein
>> Eingabefeld setzen willst und smarty nicht mitteilst das du das
>> gesondert escaped haben willst ist das gefährlich.
>
> Und wo ist der Unterschied dazu, wenn Du das nun direkt in PHP via echo
> ausgibst?
Nirgendwo. die Ursprungsfrage vom OP war ja ob Smarty an der Stelle 
hinreichend viel für in tut um solche Probleme abzuwenden.
Nein, ist es nicht, warum hab ich beschrieben.

> Du teilst PHP mit "Hey, das mußt Du aber escaped echo'en"?
> Wenn du das mit htmlentities() machst, kannst Du den Wert auch einfach
> der Smarty Variablen zuweisen.
htmlentities() ist eben nicht das Allheilmittel, aber ja, du kannst das 
machen, da spricht auch erstmal nichts gegen.
>
>> Smarty versteht die Syntax der zu erzeugenden Sprache nicht und geht,
>> wenn du ihm nichts anderes sagst, davon aus das du in html-text
>> schreiben willst.
>
> Korrigiere mich, aber wo sagst Du bitteschön Smarty was für eine Sprache
> die Ausgabe hat? Du definierst Templates, und was die nun sind ist
> schnurzegal. Das ist einfach Text, und darin werden Daten ausgegeben.
> Was soll es Smarty kümmern daß das nun meist eben HTML ist? Du kannst
> auch einfach C oder Assembler, Esperanto oder sonstwas schreiben. Den
> Inhalt liefert ja PHP.
Per Default schiebt smarty alle Eingabewerte durch htmlentities(), weil 
es davon ausgeht das du Ja html-text schreiben willst und nicht C 
Assembler, Esperanto oder sonnstwas.
Wenn du etwas anderes willst musst du smarty das mitteilen, durch 
{$var|json_decode} als beispiel für json, du musst den filter natürlich 
vorher registrieren.

>
>
>> Du kannst dich natürlich auf den Standpunkt stellen das valide Daten so
>> simple Typen sind wie: Integer, oder string der nur aus Klein- und
>> Großbuchstaben sowie Leerzeichen bestehen.
>> Damit wirst du aber nicht sonderlich weit kommen...
> Alle Daten die von Userseite kommen haben immer auf den kleinstmöglichen
> Nenner gebracht zu werden.
Natürlich, aber der Kleinstmögliche Nenner ist nun mal in dem Beispiel 
Freitext der unter anderem Javascript und Html enthalten darf.
> Wenn Du zB via Browser einen Shop
> durchblätterst, dann versuche nur INT für die IDs zu verwenden; das
> vereinfacht die Prüfung. Klar, Text muß man leider auch annehmen.

von smarter (Gast)


Lesenswert?

Dirk D. schrieb:
> Nirgendwo. die Ursprungsfrage vom OP war ja ob Smarty an der Stelle
> hinreichend viel für in tut um solche Probleme abzuwenden.

Zur Erinnerung, denn Du schrubest:
> Smarty versteht die Syntax der zu erzeugenden Sprache nicht und geht,
> wenn du ihm nichts anderes sagst, davon aus das du in html-text
> schreiben willst.

Deine Aussage war also, daß Du Smarty sagen mußt was Du für Ausgabe 
erzeugst (per Default HTML), was schlichtweg falsch ist.


> Per Default schiebt smarty alle Eingabewerte durch htmlentities(), weil
> es davon ausgeht das du Ja html-text schreiben willst und nicht C
> Assembler, Esperanto oder sonnstwas.
> Wenn du etwas anderes willst musst du smarty das mitteilen, durch
> {$var|json_decode} als beispiel für json, du musst den filter natürlich
> vorher registrieren.

Hast Du vielleicht noch nie mit Smarty gearbeitet? Wenn ich in meinem 
PHP eine Variable für Smarty mit assign('doublequote', '"') belege, dann 
habe ich im Quelltext nachher was? Ja, ein " und kein &quot;. Wie kommst 
Du also bitte auf das schmale Brett das alles automatisch durch 
htmlentities() gehen sollte? Das wäre der absolute Blödsinn.

Dein Beispiel ist übrigens auch etwas daneben, denn damit rufst Du 
keinen Smarty Modifikator auf, sondern die PHP Funktion json_decode. 
Hättest Du wenigstens |lower als Beispiel für einen Modifikator 
genommen... Könnte es sein daß Du stattdessen registerFilter() meinst? 
Aber andererseits nutzt man Filter nicht in Templates, sondern vorher.

Also nochmal, schon jemals Smarty benutzt, oder trollst Du hier nur? 
Weil, was Du schreibst ist so hanebüchen falsch, das tut richtig weh 
beim lesen und lässt Dich entsprechend dastehen.


> Natürlich, aber der Kleinstmögliche Nenner ist nun mal in dem Beispiel
> Freitext der unter anderem Javascript und Html enthalten darf.

Ja und? Ich habe hier privat eine MySQL DB in der via Browser viel 
Japanisch reingeschrieben wird. Auf Arbeit habe ich ein paar 
selbstgeschriebene Seiten die Chinesisch enthalten, aber auch massig 
Quellcodes aus C, HTML, JS, Perl, PHP, Python, usw. Damit hat die DB 
jetzt seit Jahren noch nie Probleme gehabt. PDO eben, kein blödsinniges 
Geschwurbsel mit zur Laufzeit gebastelten Queries. Da nutze ich noch 
nicht mal htmlentities() beim Import.


>> SELECT ... WHERE decode(posting, 'base64') ILIKE ...;
> Perfekt, schon habe ich meinen ersten Angriffsvektor. Hier kann ich dir
> beliebige MySQL Keywords unterjubeln

Zeig doch bitte mal eine MySQL Injektion für diesen Postgres Query, bei 
dem Du noch nicht mal siehst ob es evtl PDO ist...

von Dirk D. (dicky_d)


Lesenswert?

smarter schrieb:
> Dirk D. schrieb:
>> Nirgendwo. die Ursprungsfrage vom OP war ja ob Smarty an der Stelle
>> hinreichend viel für in tut um solche Probleme abzuwenden.
>
> Zur Erinnerung, denn Du schrubest:
>> Smarty versteht die Syntax der zu erzeugenden Sprache nicht und geht,
>> wenn du ihm nichts anderes sagst, davon aus das du in html-text
>> schreiben willst.
>
> Deine Aussage war also, daß Du Smarty sagen mußt was Du für Ausgabe
> erzeugst (per Default HTML), was schlichtweg falsch ist.

Da hab ich mich zum Teil geirrt.
twig hat per default htmlenteties als escaping, smarty nicht, zumindest 
nicht bevor du das einschaltest.
Trotzdem kannst du Smarty sagen wie es escapen soll:

Aus der Smarty-Doku 
(http://www.smarty.net/docsv2/de/language.modifier.escape.tpl):
{$artikelTitel}
{$artikelTitel|escape}
{$artikelTitel|escape:"html"}    {* maskiert &amp; &quot; &#039; &lt; 
&gt; *}
{$artikelTitel|escape:"htmlall"} {* maskiert ALLE html Entit&auml;ten *}
{$artikelTitel|escape:"url"}
{$artikelTitel|escape:"quotes"}
>
>
>> Per Default schiebt smarty alle Eingabewerte durch htmlentities(), weil
>> es davon ausgeht das du Ja html-text schreiben willst und nicht C
>> Assembler, Esperanto oder sonnstwas.
>> Wenn du etwas anderes willst musst du smarty das mitteilen, durch
>> {$var|json_decode} als beispiel für json, du musst den filter natürlich
>> vorher registrieren.
>
> Hast Du vielleicht noch nie mit Smarty gearbeitet?
Dock, hab ich, ist aber schon einige Jahre her, zu letzt eher mit Twig, 
wie gesagt, habs verwechselt, sorry.
> Wenn ich in meinem
> PHP eine Variable für Smarty mit assign('doublequote', '"') belege, dann
> habe ich im Quelltext nachher was? Ja, ein " und kein &quot;. Wie kommst
> Du also bitte auf das schmale Brett das alles automatisch durch
> htmlentities() gehen sollte? Das wäre der absolute Blödsinn.
>
> Dein Beispiel ist übrigens auch etwas daneben, denn damit rufst Du
> keinen Smarty Modifikator auf, sondern die PHP Funktion json_decode.
> Hättest Du wenigstens |lower als Beispiel für einen Modifikator
> genommen... Könnte es sein daß Du stattdessen registerFilter() meinst?
> Aber andererseits nutzt man Filter nicht in Templates, sondern vorher.

Auch hier war ich wohl halb bei twig, da heißen die smarty-modifier 
filter, und da gibt es einen json_encode filter.
Wenn du also Statt Filter Modifier Liest passts wieder.
json_decode hab ich in der stelle absichtlich gewählt um auf die 
escape-problematik zu zeigen.

>
> Also nochmal, schon jemals Smarty benutzt, oder trollst Du hier nur?
Wie gesagt, ja, habe ich, und ich hab Dinge aus der Twig-welt 
verwechselt, dafür möchte ich mich auch ausdrücklich entschuldigen.

> Weil, was Du schreibst ist so hanebüchen falsch, das tut richtig weh
> beim lesen und lässt Dich entsprechend dastehen.
>
>
>> Natürlich, aber der Kleinstmögliche Nenner ist nun mal in dem Beispiel
>> Freitext der unter anderem Javascript und Html enthalten darf.
>
> Ja und? Ich habe hier privat eine MySQL DB in der via Browser viel
> Japanisch reingeschrieben wird. Auf Arbeit habe ich ein paar
> selbstgeschriebene Seiten die Chinesisch enthalten, aber auch massig
> Quellcodes aus C, HTML, JS, Perl, PHP, Python, usw. Damit hat die DB
> jetzt seit Jahren noch nie Probleme gehabt. PDO eben, kein blödsinniges
> Geschwurbsel mit zur Laufzeit gebastelten Queries. Da nutze ich noch
> nicht mal htmlentities() beim Import.
Mein reden, Sheeva Plug ist der Meinung das Daten grundsätzlich 
gefährlich sind, Ich, und wenn ich dich richtig verstehe, auch du bist 
der Meinung das Daten nur dann gefährlich sind wenn man sie ohne 
escaping ins falsche Format abkippt.


>
>
>>> SELECT ... WHERE decode(posting, 'base64') ILIKE ...;
>> Perfekt, schon habe ich meinen ersten Angriffsvektor. Hier kann ich dir
>> beliebige MySQL Keywords unterjubeln
>
> Zeig doch bitte mal eine MySQL Injektion für diesen Postgres Query, bei
> dem Du noch nicht mal siehst ob es evtl PDO ist...
Das ist auch nicht von mir :)

von smarter (Gast)


Lesenswert?

Dirk D. schrieb:
> Da hab ich mich zum Teil geirrt.

Respekt. Sieht man heute selten daß jemand Fehler einräumt :)

> Trotzdem kannst du Smarty sagen wie es escapen soll:
Jo, hat es, aber mMn muß sowas bereits PHP seitig passieren. Das sollte 
so nur eine Notlösung sein wenn zB der Webmaster eine Variable als 
Buttontext mißbraucht und Quotes sauber haben will.

> json_decode hab ich in der stelle absichtlich gewählt um auf die
> escape-problematik zu zeigen.

Vielleicht stehe ich nun auf dem Schlauch, aber wieso sollte man 
json_decode() in Smarty nutzen? Ich nutze JSON primär in AJAX, und da 
wird alles entweder clientseiting via JS, oder backendseitig via PHP 
gemacht. Smarty hatte ich da noch nie involviert.

> Mein reden, Sheeva Plug ist der Meinung das Daten grundsätzlich
> gefährlich sind, Ich, und wenn ich dich richtig verstehe, auch du bist
> der Meinung das Daten nur dann gefährlich sind wenn man sie ohne
> escaping ins falsche Format abkippt.

Nunja, auch ich traue keinen Daten die von einem Client kommen. Eine 
Prüfung auf der Seite kann nur zur Benutzerfreundlichkeit beitragen 
(zB "Das ist keine Emailadresse"), aber Input muß immer serverseitig 
geprüft werden. Lieber ein die() zuviel als Probleme. Alles kann man 
nicht prüfen (Freitext), sondern sich nur so gut wie möglich absichern. 
PDO, keine ungeprüfte Übernahme aus GET/POST, usw.

Es muß halt beim entwickeln klar sein, wo die Daten auftauchen. Wenn man 
Freitext bei zB einem Forum einfach so in ein <div></div> packt wie es 
reinkam, kein Wunder wenn man Ärger bekommt. Oder, was auch passiert, 
Pfade zu include Files per GET zu übertragen.

>> Zeig doch bitte mal eine MySQL Injektion für diesen Postgres Query, bei
>> dem Du noch nicht mal siehst ob es evtl PDO ist...
> Das ist auch nicht von mir :)
Hier muß nun ich mich entschuldigen :) Hab glatt die Zeile mit dem 
Urheber mitgelöscht.

von Dirk D. (dicky_d)


Lesenswert?

smarter schrieb:
> Dirk D. schrieb:
>> Da hab ich mich zum Teil geirrt.
>
> Respekt. Sieht man heute selten daß jemand Fehler einräumt :)
>
>> Trotzdem kannst du Smarty sagen wie es escapen soll:
> Jo, hat es, aber mMn muß sowas bereits PHP seitig passieren. Das sollte
> so nur eine Notlösung sein wenn zB der Webmaster eine Variable als
> Buttontext mißbraucht und Quotes sauber haben will.

Was machst du den wenn du im Temlate z.B. den Usernamen an mehren 
Stellen brauchst, im Fliestext, als Attribut an nem Icon, oder so.
Gibst du dann für jede mögliche Art der Verwendung eine Version der 
Daten mit? oder Entscheidest du über das escaping genau da wo du es 
brauchst?
>
>> json_decode hab ich in der stelle absichtlich gewählt um auf die
>> escape-problematik zu zeigen.
>
> Vielleicht stehe ich nun auf dem Schlauch, aber wieso sollte man
> json_decode() in Smarty nutzen? Ich nutze JSON primär in AJAX, und da
> wird alles entweder clientseiting via JS, oder backendseitig via PHP
> gemacht. Smarty hatte ich da noch nie involviert.
Ich hatte z.B. mal nen Slideshow-System, der Kunde wollte genau das. das 
hat Metadaten über das bild in json an nem data-attribut erwartet.

>
>> Mein reden, Sheeva Plug ist der Meinung das Daten grundsätzlich
>> gefährlich sind, Ich, und wenn ich dich richtig verstehe, auch du bist
>> der Meinung das Daten nur dann gefährlich sind wenn man sie ohne
>> escaping ins falsche Format abkippt.
>
> Nunja, auch ich traue keinen Daten die von einem Client kommen. Eine
> Prüfung auf der Seite kann nur zur Benutzerfreundlichkeit beitragen
> (zB "Das ist keine Emailadresse"), aber Input muß immer serverseitig
> geprüft werden. Lieber ein die() zuviel als Probleme. Alles kann man
> nicht prüfen (Freitext), sondern sich nur so gut wie möglich absichern.
> PDO, keine ungeprüfte Übernahme aus GET/POST, usw.
>
> Es muß halt beim entwickeln klar sein, wo die Daten auftauchen. Wenn man
> Freitext bei zB einem Forum einfach so in ein <div></div> packt wie es
> reinkam, kein Wunder wenn man Ärger bekommt. Oder, was auch passiert,
> Pfade zu include Files per GET zu übertragen.

Klar, wenn ich weiß das in dem Datenfeld nur Integer, Boolsche, oder 
texte die ich per regex auf was "einfaches" prüfen kann, weil die nicht 
anders sein dürfen dann mach ich das, schon alleine um keine Daten zu 
haben die invalide sind.
Trotzdem behandele ich Daten wenn ich sie Einbette, in SQL, HTML, 
Javascript, css, was auch immer,  immer so als könnten die Potentiell 
Böse sein, auch wenn ich davon ausgehe das da nen Benutzername kommt der 
nur aus Alphanumerischen bestehen sollte.
Im besten Fall passiert dann nichts anderes als wenn ich es ignoriert 
hätte. im schlimmsten Fall, z.B. wenn jemand eine andere Lücke genutzt 
hat um mir Daten unterzuschieben die nicht so sind wie ich sie erwarte 
bin ich halt auf der sicheren Seite.

Da zeig ich lieber den Benutzername passend escaped an, und der User 
liest Javascript das durch htmlentities() gerutscht ist, als das 
Javascript was jetzt da ist, obwohl es nicht da sein sollte dem client 
zum ausführen hin zu werfen.

Viel mehr Spaß machen an der Stelle aber Template-Systeme die die zu 
erzeugende Sprache verstehen und solche Probleme selbst lösen.
Beruflich Arbeite ich Häufig mit nem System das HTML mit xslt aus 
XML-Eingabedaten erzeugt.
Da ist xss Praktisch ausgeschlossen.
Ähnlich sied es mit Jade / Pug /Haml aus.

von smarter (Gast)


Lesenswert?

Dirk D. schrieb:
> Was machst du den wenn du im Temlate z.B. den Usernamen an mehren
> Stellen brauchst, im Fliestext, als Attribut an nem Icon, oder so.
> Gibst du dann für jede mögliche Art der Verwendung eine Version der
> Daten mit? oder Entscheidest du über das escaping genau da wo du es
> brauchst?

Ein Username ist sicher, denn der kann nach der Eingangsprüfung nix 
schlechtes enthalten.

> Ich hatte z.B. mal nen Slideshow-System, der Kunde wollte genau das. das
> hat Metadaten über das bild in json an nem data-attribut erwartet.

Aber dann steht JSON im data Attrib, und das wertet man mit JS aus. 
Sobald JSON an PHP geht, würde ich es dort in eine Variable konvertieren 
und per assign() an Smarty zuweisen.

von Mark B. (markbrandis)


Lesenswert?

Bernd K. schrieb:
> Wenn ich heute ein neues Web-Projekt anfangen wollte würde ich Go
> verwenden.

Ich würde Scala nehmen.

von Sicherer " Username <b> (Gast)


Lesenswert?

smarter schrieb:
> Ein Username ist sicher, denn der kann nach der Eingangsprüfung nix
> schlechtes enthalten.

Das kommt ganz drauf an wie restriktiv der Username zu sein hat...

von Sheeva P. (sheevaplug)


Lesenswert?

Daniel A. schrieb:
> Das ist dann aber keine Validation mehr, sondern etwas ähnliches wie
> Escapen.

Ok, da hast Du Recht.

> Sheeva P. schrieb:
>> SELECT ... WHERE decode(posting, 'base64') ILIKE ...;
>
> Perfekt, schon habe ich meinen ersten Angriffsvektor. Hier kann ich dir
> beliebige MySQL Keywords unterjubeln, z.B. "\x9Eée" für null.

Bei meiner Datenbank kommst Du mit MySQL-Keywords nicht weit. ;-)

> Mich hält soetwas nicht von von SQL Injection ab.

Ich glaube schon:
1
luke=# SELECT decode('\x9Eée', 'base64');
2
ERROR:  invalid symbol

von Daniel A. (daniel-a)


Lesenswert?

Sheeva P. schrieb:
>> Mich hält soetwas nicht von von SQL Injection ab.
>
> Ich glaube schon:
> luke=# SELECT decode('\x9Eée', 'base64');
> ERROR:  invalid symbol

Nunja, ich geb ja zu das es nicht geht, jedoch hast du nicht ganz 
erfasst was ich meinte:
1
php > echo base64_encode("\x9E\xE9e");
2
null
Natürlich nützt mir das nicht viel, weil es dann zwischen zwei '\'' 
Zeichen wäre, aber ich denke man sieht die Idee dahinter.

von Dirk D. (dicky_d)


Lesenswert?

Man kann halt in codierten Daten auch nicht wirklich suchen.
Also natürlich kann man sowas machen wie

SELECT * FROM foo WHERE BASE64_DECODE(data) LIKE :suchmuster

aber dann durchwühlt die Datenbank bei jeder anfrage alle Daten und 
Indizierung ist auch unmöglich.

Mir ist fraglich wie man sowas für eine gute Idee halten kann.
Dann kann ich meine Daten auch direkt in Dateien schreiben.
Da kann ich auch nicht wirklich suchen...

von Sheeva P. (sheevaplug)


Lesenswert?

Daniel A. schrieb:
> Sheeva P. schrieb:
>> SELECT ... WHERE decode(posting, 'base64') ILIKE ...;
>
> Perfekt, schon habe ich meinen ersten Angriffsvektor. Hier kann ich dir
> beliebige MySQL Keywords unterjubeln, z.B. "\x9Eée" für null. Mich hält
> soetwas nicht von von SQL Injection ab.

Da erlaube ich mir mal, das anders zu sehen:
1
sheeva=# SELECT decode('\x9Eée', 'base64');
2
ERROR:  invalid symbol

Tipp: ich habe kein MySQL. Aus Gründen. ;-)

von Sheeva P. (sheevaplug)


Lesenswert?

Dirk D. schrieb:
> Mein reden, Sheeva Plug ist der Meinung das Daten grundsätzlich
> gefährlich sind,

Richtig. Jedwede Daten aus nicht vertrauenswürdigen Quellen sind nicht 
vertrauenswürdig und daher grundsätzlich als gefährlich zu betrachten.

> Ich, und wenn ich dich richtig verstehe, auch du bist
> der Meinung das Daten nur dann gefährlich sind wenn man sie ohne
> escaping ins falsche Format abkippt.

Auch richtig. Bei einer Webapplikation werden die Daten in 99% aller 
Fälle -- ganz gleichgültig, wo sie zwischendrin landen -- auch wieder 
als HTML ausgegeben. Also kann ich sie gleich auf der Eingangsseite 
gleich nach der Validierung in ein HTML-kompatibles Format konvertieren 
und muß dann nicht mehr darüber denken. Das ist auch dann sinnvoll, wenn 
mehrere Entwickler gemeinsam an einem Projekt arbeiten, oder wenn die 
Templates von Designern und Layoutern bearbeitet werden, die das 
Escaping gern vergessen.

von PHP-Dödel in der Kaffeepause (Gast)


Lesenswert?

Oh Mann Leute es ist doch so einfach:
Oberste Regel die niemals gebrochen wird: ALLES WAS REINKOMMT GEHT DURCH 
FILTER, AUSNAHMSLOS! Clientseitige Checks via Javascript dienen nur der 
Anwenderergonomie und sind NIEMALS Ersatz für serverseitige Checks.

Mit was ich das mache (von Hand, per Framework,...) ist erst mal egal 
solange ich weiss was der jeweilige Filter eines Frameworks macht und 
ausreicht ist das ok. Da man sich da immer auf Dritte verlässt und evt. 
in der nächsten Release anders arbeitet,... SCHREIBT MAN sich entspr. 
FILTER BESSER SELBST. NUR ICH weiss was durchkommen darf und draussen 
bleiben soll. Da kann man sich nicht auf andere verlassen.
PHP bringt entspr. Basisfilterfunktionen mit auf die man aufbauen kann:
http://php.net/manual/en/book.filter.php

PS: Ja ich LIEBE Grossbuchstaben.

von Mark B. (markbrandis)


Lesenswert?

PHP-Dödel in der Kaffeepause schrieb:
> Oh Mann Leute es ist doch so einfach:
> Oberste Regel die niemals gebrochen wird: ALLES WAS REINKOMMT GEHT DURCH
> FILTER, AUSNAHMSLOS!

Oft genug braucht nichts zur Laufzeit dynamisch in ein SQL-Statement 
reinzugehen, wenn man sich an gewisse Regeln hält.

How to Write Injection-Proof SQL (PDF):
http://www.oracle.com/technetwork/database/features/plsql/overview/how-to-write-injection-proof-plsql-1-129572.pdf

von Daniel A. (daniel-a)


Lesenswert?

PHP-Dödel in der Kaffeepause schrieb:
> Oberste Regel die niemals gebrochen wird: ALLES WAS REINKOMMT GEHT DURCH
> FILTER, AUSNAHMSLOS! Clientseitige Checks via Javascript dienen nur der
> Anwenderergonomie und sind NIEMALS Ersatz für serverseitige Checks.

Das hat doch noch gar keiner bestritten.

PHP-Dödel in der Kaffeepause schrieb:
> Mit was ich das mache (von Hand, per Framework,...) ist erst mal egal
> solange ich weiss was der jeweilige Filter eines Frameworks macht und
> ausreicht ist das ok.
...
> PHP bringt entspr. Basisfilterfunktionen mit auf die man aufbauen kann:

Man darf sich nicht nur auf Filter Bzw. Validation verlassen. Send mir 
doch eine Mail an: &|~-'/*@danielabrecht.ch (wer weiss, was ich da sonst 
noch so reinpacken könnte)

Natürlich geht es Problemlos durch den Filter:
1
php > echo filter_var("&|~-'/*@danielabrecht.ch", FILTER_VALIDATE_EMAIL) ? "ok" : "nope";
2
ok

von Dirk D. (dicky_d)


Lesenswert?

Sheeva P. schrieb:

> Auch richtig. Bei einer Webapplikation werden die Daten in 99% aller
> Fälle -- ganz gleichgültig, wo sie zwischendrin landen -- auch wieder
> als HTML ausgegeben. Also kann ich sie gleich auf der Eingangsseite
> gleich nach der Validierung in ein HTML-kompatibles Format konvertieren
> und muß dann nicht mehr darüber denken.

Und was machst du wenn du in deinen Daten suchen willst?
Deine Daten per Json an den Client übertragen willst?
Du logs schreiben willst?
Du Emails schreiben willst?
Du vieleicht pdf's erzeugen willst?
du nen Sitemap-file generieren willst?
Jedes mal wieder zurück Konvertieren? das klingt nach ner Spitzen idee.

In ne Datenbank gehören die Daten, nicht eine Representaiton der Taten 
für ein Bestimmtes Ausgabeformat.

Was machst du wenn du dich entschließt deine Seite Jetzt per Angular 
o.Ä. neu zu gestalten.
Konvertierst du dann deine Daten in der Datenbank dammit das wieder 
klappt?

von php-dödel (Gast)


Lesenswert?

Daniel A. schrieb:

>> PHP bringt entspr. Basisfilterfunktionen mit auf die man aufbauen kann:
>
> Man darf sich nicht nur auf Filter Bzw. Validation verlassen. Send mir
> doch eine Mail an: &|~-'/*@danielabrecht.ch (wer weiss, was ich da sonst
> noch so reinpacken könnte)
>
> Natürlich geht es Problemlos durch den Filter:php > echo
> filter_var("&|~-'/*@danielabrecht.ch", FILTER_VALIDATE_EMAIL) ? "ok" :
> "nope";
> ok
Wieder echt PHP-Schrott: Bug schon lange bekannt und bis heute nicht
gefixed (7.0.6).
Deshalb selber schreiben und fleissig Tests schreiben.

von Daniel A. (daniel-a)


Lesenswert?

php-dödel schrieb:
> Wieder echt PHP-Schrott: Bug schon lange bekannt und bis heute nicht
> gefixed (7.0.6).
> Deshalb selber schreiben und fleissig Tests schreiben.

Das ist kein PHP Bug. Diese Mail Adresse ist echt und Funktionsfähig. Es 
wäre ein Bug, wenn diese nicht durch die Validation käme.

von php-dödel (Gast)


Lesenswert?

Daniel A. schrieb:
> Das ist kein PHP Bug. Diese Mail Adresse ist echt und Funktionsfähig. Es
> wäre ein Bug, wenn diese nicht durch die Validation käme.
Ups stimmt. Wusste gar nicht was für kranke Adressen möglich sind:
http://stackoverflow.com/questions/19220158/php-filter-validate-email-does-not-work-correctly

Standard hin oder her, solche Adressen würde ich trotzdem nicht 
akzeptieren weil kein Mensch solche Addressen hat.

von Sheeva P. (sheevaplug)


Lesenswert?

Dirk D. schrieb:
> Sheeva P. schrieb:
>
>> Auch richtig. Bei einer Webapplikation werden die Daten in 99% aller
>> Fälle -- ganz gleichgültig, wo sie zwischendrin landen -- auch wieder
>> als HTML ausgegeben. Also kann ich sie gleich auf der Eingangsseite
>> gleich nach der Validierung in ein HTML-kompatibles Format konvertieren
>> und muß dann nicht mehr darüber denken.
>
> Und was machst du wenn du in deinen Daten suchen willst?
> Deine Daten per Json an den Client übertragen willst?
> Du logs schreiben willst?
> Du Emails schreiben willst?
> Du vieleicht pdf's erzeugen willst?
> du nen Sitemap-file generieren willst?
> Jedes mal wieder zurück Konvertieren? das klingt nach ner Spitzen idee.

Hast Du das, was ich oben geschrieben habe, nicht gelesen oder hast Du 
es vielleicht nicht verstanden? Ich wähle und validiere sehr genau, wie 
ich Daten aus nichtvertrauenswürdigen Quellen handhabe und was dann am 
Ende in meinen Datenfeldern stehen darf. Und wenn der Anwendungsfall es 
vorgibt, potentiell gefährliche Inhalte verarbeiten zu müssen, 
konvertiere ich sie an der Eingangsschnittstelle in ein Format, das 
meinen Subsystemen soweit möglich keine Probleme bereiten kann. Mit 
dieser Vorgehensweise habe ich erfolgreich mehrere professionelle 
Penetration Tests, Sicherheits- und tatsächlich auch Codeaudits 
absolviert.

Also laß' jetzt bitte die Luft 'raus, Dirk, und gewöhn' Dich einfach mal 
an den Gedanken, daß andere Menschen einige Dinge vielleicht anders 
machen als Du, und das trotzdem nicht unbedingt falsch sein muß. Ich 
jedenfalls fahre mit meiner Technik, alles, was 'reinkommt, so früh und 
so weit wie möglich zu entschärfen, bislang ziemlich gut.

> In ne Datenbank gehören die Daten, nicht eine Representaiton der Taten
> für ein Bestimmtes Ausgabeformat.
>
> Was machst du wenn du dich entschließt deine Seite Jetzt per Angular
> o.Ä. neu zu gestalten.
> Konvertierst du dann deine Daten in der Datenbank dammit das wieder
> klappt?

Ach, laß' das doch einfach mal meine Sorge sein, ja? Bisher habe ich 
noch immer einen Weg gefunden, ob Du das nun wahrhaben willst oder 
meinetwegen auch nicht. :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.