SQL Injektion und Cross Site Scripting verhindern?
Wie würde ich das hier in sicher machen ?
Es ist der Php Code von einem Unsicheren Chat aber es geht mir um XSS oder SQL Injectons, nicht um Verschlüsselungen etc.
<?php
$host = 'localhost';
$user = 'root';
$pw = '';
$database = 'Chat';
$db = mysqli_connect($host, $user, $pw, $database);
if ($db) {
} else {
exit("Error" . mysqli_connect_error());
}
if (isset($_GET['message']) && $_GET["message"] != "") {
$username = "Alice";
$message = $_GET['message'];
$sql_insert = 'INSERT INTO messages SET
user = "' . $username . '",
message = "' . $message . '"';
$sql = "SELECT * FROM messages";
$res = $db->query($sql);
$insert = mysqli_query($db, $sql_insert);
echo "Sucessfull";
}
else {
echo '<script> alert("Bitte Trage etwas ein")';
}
4 Antworten
nutz gleich PDO und prepare statements und übergibt die variablen seperat mit platzhaltern und assoziativen arrays . das modul macht das nötige für dich .
fals du davon was nciht verstehst einfach mit google mal suchen nach den begriffen .
Hier ien gutes tutorial was es erklärt (ist deutsch)
zum thema XSS musst du dich einlesen , da fällt mir pauschal nix zu ein , den da gibts vieles zu breachten .
hier
so macht man es richtig
<?php
//Datenbank Informationen
$server = 'localhost';
$user = 'root';
$psw = null;
$dbName = 'Test';
//Verbinden mit Datenbank ($server $user $psw $dbName )
try {
$conn = new PDO('mysql:host='.$server.';dbname='.$dbName.';charset=utf8', $user, $psw);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
// In Datenbank lesen
$sql = "SELECT * FROM messages";
//Prepared Statement
$Abfrage = $conn->prepare($sql);
//Abfrage lesen auführen
$Abfrage -> execute();
$result = $Abfrage->fetchAll(PDO::FETCH_ASSOC);
//Antwort von der Datenbank in das Objekt result
//Nacheinander anzeigen
foreach ($result as $i) {
echo "<p class='". $i["user"]."'>".
$i["message"] ." <br>".
$i["date"] . "</p>";
}
// In Datenbank Schreiben
$username = "Alice";
$message = $_GET['message'];
// platzhalter mit doppelpunkt vorran für folgende namen im array , siehe $sqlvars
$sql = "INSERT INTO messages (user,message) VALUES (:username,:message) ";
// variablen für platzhalter als array mit "namen"
$sqlvars = array("username" => $username,
"message" => $message );
//Prepared Statement
$Abfrage = $conn->prepare($sql);
//Abfrage Schreiben ausführen , $variablenarray übergeben , maskiert automatisch alle werte .
$Abfrage->execute($sqlvars);
}catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
exit;
}
zu dein angriffmöglichkeiten gehört natürlich dann das XSS , weil wenn die $message javascript enthält wird das bei anzeige ausgeführt . also muss du noch mal nachgucken im netz wie man sowas entfernt aus der message .
Danke , Also ist das was du bearbeitet hast dann auch wirklich SQL Injection sicher oder könnte man selbst das noch irgendwie knacken ?
Und für das XSS müsste doch das hier ausreichen ?
echo htmlspecialchars(stripslashes(trial($_[GET["message"])));
Oder ist nur oberflächlich/grob
ausserdem brauchst du noch session , da du nur message empfangen solltest was auch von deinem php gesendet wurde und nicht irgendwer mit GET an die url hängt . den dann spämmt dich irgendwer voll
also z.b.
in der form.php
<?php
session_start();
$_SESSION["message"] = "ok";
.
.
?>
und in deinem INSERT dann
<?php
session_start();
if (!isset($_SESSION['message'])) {exit;}
.
.
?>
echo htmlspecialchars(stripslashes(trial($_[GET["message"])));
ja geht , kannst dir auch eine funktion daraus machen wie hier beschrieben
https://www.php-einfach.de/experte/php-sicherheit/cross-site-scripting-xss-in-php/
aber das strip slashes brauchste dann eigentlich nicht mehr .
Danke aber ich glaube das mit dem spammen über die URL funktioniert hier nicht da ich das mit Ajax mache.
Der vordere Teil sieht so aus, sieht vielleicht für dich ein wenig dumm programmiert (Im Html Dokument mit Script Tags) aus aber das ist kein Ernst gemeintes Projekt und kann man schnell bearbeiten.
<script>
$('#absendeFormular').submit(function(event){
event.preventDefault();
$.ajax({
type:"GET",
url:"assets/PHP/sendMessage.php",
data: $(this).serialize(),
success: function (data) {
console.log(data)
}
});
$('#absendeFormular')[0].reset();
});
</script>
<script>
setInterval(() => {
$(document).ready(function(event){
$.ajax({
type:"GET",
url:"assets/PHP/aktualisieren.php",
data: $(this).serialize(),
success: function (data) {
$('#ChatBereich').html(data)
}
});
});
}, 500);
</script>
das ist egal , ich kann ein GET auch selber mit AJAX von irgendwo machen , mach ich mir meine eigene webseite .
solltest eh lieber per POST machen . und wie gesagt , nur das $_SESSION verhindert das andere seiten das ausnutzen .
deswegen auch deine anderen seiten immer als php mit session_start() damit du weisst welcher user da von deinem server kommt . also auch wenn du dort javascript lädst zum verschicken, wichtig, der user soll schon eine session haben , die wird dann im header mitgeschickt auch beim ajax.
Achso, dann nehme ich lieber POST.
GET soll ein kleines bisschen Performanter sein und es hat nicht in der URL gestört wie normalerweise deswegen hab ich mich schnell dafür entschieden.
..../&message=......................................
würde nicht schön aussehen
kannst auch get machen , das ist nicht schlimm , aber halt doof weil alte browser bei urls mit 255 zeichen früher aufgehört haben .
moment, bei ajax ist get ok , das taucht ja nicht in der history auf .
echo htmlspecialchars(stripslashes(trial($_[GET["message"])));
Hab mich verschrieben, meinte *trim
ja geht , kannst dir auch eine funktion daraus machen wie hier beschrieben
function xss($string) {
return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
}
also so und dann
$message = xss($_POST['message']);
Das ist dann aufjedenfall übersichtlicher
ah wenn du gelesen hast , ist das immer kompliziert wenn man das bei der eingabe schon macht .
bei der ausgabe wäre fast leichter , oder eben einen wirklichen filter bauen .
musst du gucken , den wenn etwas erstmal merkwürdig in einer datenbank steht kann das auch nerfen :) da eben alle zeichen dann umgeformt werden und die daten schlecht anders genutzt werden können .
ggf ein filter bauen der ['message'] mit script tags nicht erlaubt . und dann nur die tags maskieren .
z.b. hier ganz nett gemacht
https://gist.github.com/mbijon/1098477/4e245ab3844ddbd0e7c6f9fdf360501517e121cf
SQL Injektion und Cross Site Scripting verhindern?
Verwende PDO mit prepared Statements. Damit bist Du auf der sicheren Seite.
Alex
Kannst du mir vielleicht sagen welche Angriffsmöglichkeiten du hier hättest ?
Also ich habe dasselbe wie oben mit PDO gemacht und Prepared Statements.
Ein Teil ist um Etwas Auszulesen mit SELECT * FROM ... und der zweite Teil um in die Datenbank einzufügen.
<?php
//Datenbank Informationen
$server = 'localhost';
$user = 'root';
$psw = null;
$dbName = 'Test';
//Verbinden mit Datenbank ($server $user $psw $dbName )
try {
$conn = new PDO('mysql:host='.$server.';dbname='.$dbName.'', $user, $psw);
}catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
// In Datenbank lesen
$sql = "SELECT * FROM messages";
//Prepared Statement
$Abfrage = $conn -> prepare($sql);
//Abfrage lesen auführen
$Abfrage -> execute();
$result = $Abfrage -> fetchAll();
//Antwort von der Datenbank in das Objekt result
//Nacheinander anzeigen
foreach ($result as $i) {
echo "<p class='". $i["user"]."'>".
$i["message"] ." <br>".
$i["date"] . "</p>";
}
// In Datenbank Schreiben
$username = "Alice";
$message = $_GET['message'];
$sql = 'INSERT INTO messages SET
user = "' . $username . '",
message = "' . $message . '"';
//Prepared Statement
$Abfrage = $conn -> prepare($sql);
//Abfrage Schreiben auführen
$Abfrage -> execute();
//Verbindung mit Datenbank beenden
$conn = null;
$message = $_GET['message'];
Usereingaben sollten nicht ungefiltert ineinander Datenbank übernommen werden. Besser ist
$message = htmlspecialchars($_GET['message']);
der insert lautet dann
$sql = 'INSERT INTO messages SET
user = :user,
message = :message";
//Prepared Statement
$Abfrage = $conn -> prepare($sql);
//Abfrage Schreiben auführen
$Abfrage -> execute(array(user => $user, message => $message));
Danke, und mehr Schwachstellen fallen dir nicht auf du dir den überarbeiteten Code Anschaust ?
<?php
//Datenbank Informationen
$server = 'localhost';
$user = 'root';
$psw = null;
$dbName = 'Test';
//Verbinden mit Datenbank ($server $user $psw $dbName )
try {
$conn = new PDO('mysql:host='.$server.';dbname='.$dbName.';charset=utf8', $user, $psw);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
// In Datenbank lesen
$sql = "SELECT * FROM messages";
//Prepared Statement
$Abfrage = $conn->prepare($sql);
//Abfrage lesen auführen
$Abfrage -> execute();
$result = $Abfrage->fetchAll(PDO::FETCH_ASSOC);
//Antwort von der Datenbank in das Objekt result
//Nacheinander anzeigen
foreach ($result as $i) {
echo "<p class='". $i["user"]."'>".
$i["message"] ." <br>".
$i["date"] . "</p>";
}
// In Datenbank Schreiben
$username = "Alice";
//cross site scripting filtern
$message = htmlspecialchars(stripslashes(trim($_POST['message'])));
// platzhalter mit doppelpunkt vorran für folgende namen im array , siehe $sqlvars
$sql = "INSERT INTO messages (user,message) VALUES (:username,:message) ";
// variablen für platzhalter als array mit "namen"
$sqlvars = array("username" => $username,
"message" => $message );
//Prepared Statement
$Abfrage = $conn->prepare($sql);
//Abfrage Schreiben ausführen , $variablenarray übergeben , maskiert automatisch alle werte .
$Abfrage->execute($sqlvars);
}catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
exit;
}
1. Der DB ordentliche Zugangsdaten geben.
2. Wenn möglich keinen root-Zugang benutzen.
3. Prepared Statements für das SQL benutzen.
4. Input validieren.
5. Input escapen.
Kurzum: Alles.
Der DB ordentliche Zugangsdaten geben.
Ja klar, das ist nur Lokal mit Xampp
4. Input validieren.
5. Input escapen.
Das hab ich nicht so genau verstanden, hast du vielleicht ein Beispiel ?
Und ist es dann 100% sicher vor SQL INJ. und XSS wenn ich diese 5 Punkte erledige oder gibt es da noch mehr ?
Aktuell darf da jeder alles reinwerfen.. Aich HTML, JavaScript oder sonstwas.. das ist nicht so gut.
Wenn ich mir deinen Code so ansehe nein, du wirst wahrscheinlich in jeder Datei Sicherheitslücken einbauen. Aber zum üben am Anfang ist das i.O.
Kannst du mir vielleicht sagen welche Angriffsmöglichkeiten du hier hättest ?
Also ich habe dasselbe wie oben mit PDO gemacht und Prepared Statements.
Ein Teil ist um Etwas Auszulesen mit SELECT * FROM ... und der zweite Teil um in die Datenbank einzufügen.
<?php
//Datenbank Informationen
$server = 'localhost';
$user = 'root';
$psw = null;
$dbName = 'Test';
//Verbinden mit Datenbank ($server $user $psw $dbName )
try {
$conn = new PDO('mysql:host='.$server.';dbname='.$dbName.'', $user, $psw);
}catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
// In Datenbank lesen
$sql = "SELECT * FROM messages";
//Prepared Statement
$Abfrage = $conn -> prepare($sql);
//Abfrage lesen auführen
$Abfrage -> execute();
$result = $Abfrage -> fetchAll();
//Antwort von der Datenbank in das Objekt result
//Nacheinander anzeigen
foreach ($result as $i) {
echo "<p class='". $i["user"]."'>".
$i["message"] ." <br>".
$i["date"] . "</p>";
}
// In Datenbank Schreiben
$username = "Alice";
$message = $_GET['message'];
$sql = 'INSERT INTO messages SET
user = "' . $username . '",
message = "' . $message . '"';
//Prepared Statement
$Abfrage = $conn -> prepare($sql);
//Abfrage Schreiben auführen
$Abfrage -> execute();
//Verbindung mit Datenbank beenden
$conn = null;
Du benutzt keine prepared Statements. Du hast 1-zu-1 die selben Probleme wie in der ursprünglichen Frage. Alle davon sind noch da.
Ok danke, wie sieht es deiner Meinung nach jetzt überarbeitet aus ?
Könnte man so veröffentlichen oder immernoch Angreifbar ?
<?php
//Datenbank Informationen
$server = 'localhost';
$user = 'root';
$psw = null;
$dbName = 'Test';
//Verbinden mit Datenbank ($server $user $psw $dbName )
try {
$conn = new PDO('mysql:host='.$server.';dbname='.$dbName.';charset=utf8', $user, $psw);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
// In Datenbank lesen
$sql = "SELECT * FROM messages";
//Prepared Statement
$Abfrage = $conn->prepare($sql);
//Abfrage lesen auführen
$Abfrage -> execute();
$result = $Abfrage->fetchAll(PDO::FETCH_ASSOC);
//Antwort von der Datenbank in das Objekt result
//Nacheinander anzeigen
foreach ($result as $i) {
echo "<p class='". $i["user"]."'>".
$i["message"] ." <br>".
$i["date"] . "</p>";
}
// In Datenbank Schreiben
$username = "Alice";
//cross site scripting filtern
$message = htmlspecialchars(stripslashes(trim($_POST['message'])));
// platzhalter mit doppelpunkt vorran für folgende namen im array , siehe $sqlvars
$sql = "INSERT INTO messages (user,message) VALUES (:username,:message) ";
// variablen für platzhalter als array mit "namen"
$sqlvars = array("username" => $username,
"message" => $message );
//Prepared Statement
$Abfrage = $conn->prepare($sql);
//Abfrage Schreiben ausführen , $variablenarray übergeben , maskiert automatisch alle werte .
$Abfrage->execute($sqlvars);
}catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
exit;
}
Ich würde eher ein Framework nehmen, welches bereits SQL Injections verhindern kann. Z.B. ein ORM Framework.
Aber anscheinend soll das nicht 100% Sicher sein.
Oder ist ORM nicht PDO ?
Klingt ähnlich
Kannst du mir vielleicht sagen welche Angriffsmöglichkeiten du hier hättest ?
Also ich habe dasselbe wie oben mit PDO gemacht und Prepared Statements.
Ein Teil ist um Etwas Auszulesen mit SELECT * FROM ... und der zweite Teil um in die Datenbank einzufügen.