Hvor og hvordan skal man beskytte sig mod SQL-injections og XSS?
Hvor og hvordan skal man beskytte sig mod SQL-injections og XSS?Jeg har lavet en hjemmeside som fungerer som et mini-CMS. Siden er lavet med HTML, CSS, JavaScript og til database er der gjort brug af MySQL samt PHP.
Det hele går ud på en at en superbruger kan logge ind på hjemmesiden, og derefter bliver der vist en 'admin' side. Her kan en bruger oprette nyheder og nye brugere (men disse nyoprettede kan ikke selv oprette brugere - det er kun superbrugeren). Det er muligt for alle besøgende at kommentere disse nyheder (altså uden at være logget ind). Derudover er det også muligt for alle brugerne at slette kommentar, nyheder og opdatere nyhederne.
Hvad jeg så kan forstå er at man skal beskytte sig mod SQL-injections, fordi med disse SQL-injections kan man 'indskyde' SQL-kode ved et SQL-kald. Fx ved en login-side med en HTML form (som min side), her kan der opnås uautoriseret adgang som superbruger. Bør jeg så kun bruge prepared statements ved login-siden?
Jeg har forstået at man kan beskytte sig mod SQL-injections ved at bruge prepared statements, hvor der indgår bruger-input i SQL-sætningen. Det kan gøres med PDO fordi det er den nemmeste metode og den fungerer til mange forskellige database typer. Jeg har så gjort brug af prepared statements ved login, se nedenstående:
<?php
session_start();
//Tjekker om email og password er sat
if(isset($_POST['userid']) && isset($_POST['password']))
{
$userid = $_POST['userid'];
$password = $_POST['password'];
require_once('connect.inc.php');
$conn = dbConnect('pdo') or die('no connection');
//Henter data hvor email er lig med userid
$stmt = $conn->prepare("SELECT * FROM users_tbl WHERE email = ? AND password = ?");
$stmt->bindParam(1, $userid, PDO::PARAM_STR);
$stmt->bindParam (2, sha1($password), PDO::PARAM_INT);
$stmt->execute();
if($stmt->fetch())
{
$_SESSION['valid_user'] = $userid;
}
$stmt = null;
//Hvis okay gå til prefs, ellers udskriv fejl
if(isset($_SESSION['valid_user'])){
header("location:prefs.php");
//Udskriv fejl her
}else{
?>
Men er så ikke helt sikker på jeg forstår hvad det er der egentlig sker og hvorfor?
Er det korrekt at:
1.
'prepare' metoden sender queryen til serveren og bruger en placeholder i form af et ?-tegn som argument i stedet for variablerne. Derefter bruges 'execute' metoden til at erstatte placeholderen i SQL med det rigtige. Fordi queryen og variablerne sendes separat er der på ingen måde noget SQL der vil blive kunne 'executed' hvis det befandt sig i variablerne?
2.
Det er bedst og bruge bindParam - fremfor bindValue eller gøre det i selve execute sætningen, fordi variablen så ikke nødvendigvis behøver at være defineret endnu? Men kan ikke helt se hvornår det er interessant?
3.
Man SKAL altid lukke sin database forbindelse efter man har kørt alle sine queries på hver PHP script? Ved fx at sige $stmt = null;. Og hvorfor skal man det?
Foruden prepared statements bør man så satinere alt input og output for at undgå HTML i databasen og her kan man bruge htmlspecialchars?
Bør man også checke om input eller output har det rigtige format og her kan man bruge regex?
Se nedenstående eksempel på begge:
//Bruger
$username = htmlspecialchars($_POST['username']);
$email = htmlspecialchars($_POST['email']);
$password = htmlspecialchars($_POST['password']);
$usertype = htmlspecialchars($_POST['usertype']);
//Indsæt bruger i databasen
if (isset($_POST['email'])){
if (preg_match(if (preg_match("/^[\w\d]$/", $username) && preg_match("#.*^(?=.{8,20})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).*$#", $password) && preg_match("/([^@]+)@(.+)/", $email))
{
//Opret bruger
$query = "INSERT INTO users_tbl(username, email, password, usertype) VALUES (?,?,?, 1)";
$stmt = $conn->prepare($query);
$stmt->bindParam(1, $username, PDO::PARAM_STR);
$stmt->bindParam(2, $email, PDO::PARAM_STR);
$stmt->bindParam(3, sha1($password), PDO::PARAM_STR);
$stmt->execute();
header("location:prefs.php");
}
else
{
Udover SQL-injections findes der også XSS, som er hvad helt præcist? Og hvordan beskytter man sig mod det? Kan man sikrer sig mod XSS ved at sørge for at en bruger aldrig nogensinde kan komme til at skrive egentlig HTML - ved at konvertere de specielle tegn (<, >, & og ") til HTML-entiteter inden de udskrives?
Jeg bruger fx en JavaScript funktioner som alertbox. Når en bruger er logget ind og vil slette nyhederne, bruges den til at spørge om man 'vil slette denne nyhed?' og her sender jeg så id'et på nyheden videre gennem URL'en for at slette den. Kan forstå at når man bruger alert() funktioner er man XSS vulnerabel? I hvilke andre tilfælde er man også det?
Kan man bruge htmlspecialchars for at beskytte sig mod XSS når man udtrækker data fra databasen? Det er hvad jeg kunne læse mig frem til på en tråd fra stackoverflow:
http://stackoverflow.com/questions/14148937/is-using-htmlspecialchars-for-input-output-html-sanitization-for-mysql-databa
Jeg finder dette spørgsmål meget interessant og håber nogen kan hjælpe mig med det, da jeg også tror det kan hjælpe andre med at forstå hvad XSS og SQL-injections er for en størrelse og hvordan man kan beskytte sig mod det.
På forhånd mange tak.