Seppure la sintassi di PHP non preveda strette condizioni sull'indentazione e sullo stile in cui il codice deve essere scritto, questo non toglie che una impostazione il più possibile chiara e sistematica della modalità di scrittura, di naming delle variabili e in generale la definizione "interna" di alcune semplici regole e convenzioni possano agevolare, soprattutto quando diversi sviluppatori lavorano sullo stesso progetto.
Può sembrare banale, soprattutto a chi abbia già famigliarità con altri linguaggi di programmazione, ma l'indicazione principale è commentare e documentare il codice, questo spesso può sembrare fastidioso e inutile soprattutto ai programmatori "esperti", ma questo atteggiamento cambia immediatamente quando si debba riprendere codice scritto da altri o scritto da noi stessi alcuni mesi addietro.
Cercare di mostrare un codice chiaro utilizzando spazi, tab e lasciando una sola istruzione per linea, oltre che utilizzare i separatori di blocco {...}
anche quando non strettamente necessari non influisce sull'esecuzione del nostro programma ma rende la vita più semplice...
if ($questo==$quello)foreach($cio as $questo)echo $cio."
";
risulta sicuramente piu bello e sicuramente più manutenibile se scritto in questo modo:
if ($arr_questo==$arr_quello)
{
# output dei valori contenuti nell'array $arr_questo
foreach ($cio as $arr_questo)
{
echo $cio."
";
}
}
Cerchiamo sempre di ridurre al minimo l'utilizzo di if
nidificati, spesso è possibile avere un codice molto più leggibile e "risparmiare" indentazione separando i vari controlli condizionali, consideriamo questo esempio:
if ($autenticato)
{
if ($amministratore)
{
if ($nome == "Mario")
{
print "Bentornato Padrone $nome";
}
else
{
print "Questa area è riservata";
}
}
else
{
return false;
}
}
else
{
return false;
}
che può essere invece molto più lineare se scritto in questo modo
if (!$autenticato)
{
return false;
}
if (!$amministratore)
{
return false;
}
if ($nome == "Mario")
{
print "Bentornato Padrone $nome";
}
else
{
print "Questa area è riservata a Mario";
}
Buona cosa è anche sfruttare la flessibilità della sintassi di PHP che non costringe a scrivere un comando tutto su una sola riga, se ben utilizzata questa caratteristica ci fornisce un'ulteriore incremento a livello di leggibilità e quindi (prima o poi...) di risparmio di tempo e incremento di produttività:
$sql = "
SELECT nome, cognome, indirizzo, provincia,
telefono, data_nascita
FROM utenti
WHERE cognome LIKE 'P%'
AND provincia = 'VC'
";
la stringa contenente la query SQL potrà essere passata tranquillamente come parametro ad esempio alla funzione mysql_query()
permettendo a chi legge il codice di focalizzare immediatamente dove tale stringa viene impostata.
Il dovere lavorare con dati inseriti da un utente e soprattutto il fatto che questi dati verranno spesso utilizzati
all'interno di query che verranno eseguite sulla base dati, comporta la necessità di dovere prevenire i danni derivabili
da dati inseriti da utenti maliziosi.
Un caso di particolare interesse è l'attacco conosciuto come SQL Injection
Per SQL Injection si intende la possibilità che un visitatore ha, a meno che l'applicazione abbia accorgimenti speciali,
di inviare, ad esempio tramite i campi di una form da cui ci si aspetta tutt'altro, al database server delle query che non
fanno esattamente quello che ci si aspetta.
Vediamo un classico esempio per capire meglio, supponiamo di dovere autenticare tramite una form i nostri utenti:
<form action="login.php" method="POST">
Username: <input name="user">
<br>
Password: <input type="password" name="pwd">
<br>
<input type="submit" value=" Login ">
</form>
la pagina $login.php conterrà al suo interno una query che va a verificare che i dati inseriti corrispondano
effetivamente ad un utente registrato nel nostro sistema:
$query = "SELECT * FROM clienti WHERE username='".$_POST['user']."' AND password='".$_POST['pwd']."'";
Tutto bene fino a che i nostri clienti accedono inserendo quello che ci aspettiamo cioè delle stringhe con il loro utente e
la loro password, ma cosa succede se nel campo user viene inserita la stringa
administrator' OR 1=1 --
e nel campo password
qualsiasicosa
la nostra query diventa
$query = "SELECT * FROM clienti WHERE username='administrator' OR 1=1 --' AND password='qualsiasicosa'";
cioè l'utente verrà riconosciuto come accreditato come 'administrator' qualsiasi sia la password inserita.
Fortunamente il proteggersi da questo tipo di attacco in PHP è relativamente semplice, lapèrima barriera che si può impostare
è sicuramente il verificare che sia attiva la direttiva magic_quotes_gpc
(fra l'altro l'impostazione di default lo prevede),
successivamente si può utilizzare odelle funzioni di escape specifiche per il tipo di database che stiamo utlizzando, ad esempio
mysql_escape_string($stringa_di_input)
o in definitiva applicare indistintamente la funzione addslashes($stringa_di_input)
a tutti quei dati che andranno a formare le nostre query.
Dato che spesso non si ha accesso diretto al file di configurazione php.ini, rifacendosi all'esempio precedente
può essere utile un costrutto del genere:
if (!get_magic_quotes_gpc())
$_POST['user'] = addslashes($_POST['user']);
$_POST['pwd'] = addslashes($_POST['pwd']);
in questo modo la nostra query attaccata diventerà
$query = "SELECT * FROM clienti WHERE username='administrator\' OR 1=1 --' AND password='qualsiasicosa'";
in questo modo l'apice inserito dall'utente viene interpretato nella query come il carattere apice e non come un terminatore
di una stringa.
Questo tipo di attacco prevede l'inserimento di codice arbitrario, sia esso HTML o comandi di scripting (JavaScript, VbScript o ActiveX), come input di una applicazione web oppure di una e-mail in formato HTML. Il codice maligno verrà quindi eseguito del browser del visitatore della pagina in cui è stato pubblicato.
Un esempio classico di vulnerabilità può essere considerata una applicazione che previa autenticazione premetta di pubblicare del contenuto che sarò visibile ai successivi visitatori, un Blog ad esempio, senza estrapolare dai contenuti le istruzioni e i comandi eseguibili.
La caratteristica che rende molto pericoloso questo tipo di attacco è che la responsabilità del rilascio del codice maligno viene delegata all'hosting, inconsapevole, che mantiene l'applicazione vulnerabile, il responsabile dell'attacco accederà al server per ottenere le informazioni che l'utente sta fornendo.
Vediamo un semplice esempio di XSS:
che apre una browser dell'utente verso un sito esterno.
Oppure, per ottenere i cookie del visitatore ignaro:
getCookie.php, presente sul mio sito, può ad esempio caricare una pagina dove un frame nascosto si occupa di archiviare/inviare a qualche altra applicazione il coookie "rubato" e la parte visibile è invece la pagina di provenienza. In genere viene effettuato anchel'encoding della URL remota in modo da nasconderla ulteriormente.
L'attacco può essere prevenuto attuando la regola base "non fidarsi mai dell'input" e quindi validando lato server ciò che i nostri utenti inviano, questo significa ad esemio utilizzare funzioni come
strip_tag()
per rimuovere gli evenentuali tag HTML da ciò che l'utente sta inserendo.
Inoltre un'altra operazione efficace per evitare gli XSS è di eseguire in output la funzione htmlentities() che trasforma in entità HTML i caratteri come etc...
Spesso è utile se non necessario utilizzare un file di configurazione (ad esempio: config.php) in cui ad esempio verrà inizializzata la sessione, verranno definiti i parametri di connessione al database e altro.
Si consiglia di utilizzare sempre un estensione che preveda il parsing da parte del web server anche per i file i configurazione, questo per evitare che utenti maliziosi possano effettuare il download del file e ottenere così le password e i dati che vi sono contenuti. Ad esempio non è difficile imbattersi in siri in cui sono presenti file del tipo:
config.ini
connessione.ini
start.ini
o altro ...