2009-06-28 15 views
38

Ho un semplice script mailer PHP che prende i valori da un formulario presentato tramite POST e li poste a me:Come sanitizzare l'input dell'utente in PHP prima della spedizione?

<?php 
$to = "[email protected]"; 

$name = $_POST['name']; 
$message = $_POST['message']; 
$email = $_POST['email']; 

$body = "Person $name submitted a message: $message"; 
$subject = "A message has been submitted"; 

$headers = 'From: ' . $email; 

mail($to, $subject, $body, $headers); 

header("Location: http://example.com/thanks"); 
?> 

Come posso sterilizzare l'input?

+1

Se si utilizza un campo di testo diretto, non ci dovrebbero essere htmlentities nei dati $ _POST. Se utilizzi una sorta di editor di testo RTF che genera html, utilizza html_entity_decode(). Assicurati di togliere i caratteri di controllo dall'oggetto - i caratteri di nuova riga nell'oggetto possono rovinare le intestazioni delle tue email –

+16

@Frank Farmer: stai suggerendo che dovrebbe fidarsi che nessun codice offensivo raggiunga il suo codice solo perché ha usato un "straight-up" campo di testo"? Questo è un consiglio terribile. –

+9

Heh, campo di testo orizzontale. Ho appena fatto un test XSS su qualcuno che l'ha fatto. A loro non piaceva la divertente immagine inviata tramite un link img inserito nel "campo di testo straight-up". –

risposta

44

Sanitizza la variabile di post con filter_var().

Example here. Come:

echo filter_var($_POST['email'], FILTER_SANITIZE_EMAIL); 
+0

Mi piace filter_var per questo, purtroppo, non tutti i setup di hosting hanno ancora il 5.2, ma sembra essere una funzione ben pensata. – artlung

+0

php 5 è ​​abbastanza buono filter_var (PHP 5> = 5.2.0) –

+2

Non tutte le configurazioni di hosting hanno ancora 5.2, hehe, è così 2009. Ora è più come se fossero ancora in esecuzione 5.4 sono pesci. – markus

10

Dal momento che non sta costruendo una query SQL o qualsiasi cosa qui, l'unica validazione rilevante che posso vedere di quegli input è una convalida e-mail per $ _POST [ "email"], e forse un'alfanumerica filtra negli altri campi se vuoi veramente limitare l'ambito di ciò che il messaggio può contenere.

Per filtrare l'indirizzo e-mail, è sufficiente utilizzare filter_var:

$email = filter_var($email, FILTER_SANITIZE_EMAIL); 

Come da suggerimento di Frank Farmer, è anche possibile filtrare a capo in oggetto dell'e-mail:

$subject = str_replace(array("\r","\n"),array(" "," "),$subject); 
+2

Newline caratteri in le linee dell'oggetto dell'email sono in qualche modo problematiche. –

+0

Ciao Frank, ho modificato la mia risposta per riflettere il tuo suggerimento. –

+7

A seconda del modo in cui viene costruita l'email, i caratteri di nuova riga possono essere inseriti in qualsiasi intestazione di e-mail che consente all'utente malintenzionato di aggiungere eventuali intestazioni di e-mail nuove o sostitutive che gli piacciono. Oltre a ciò, l'iniezione di un'intera riga vuota (due newline) consente quindi all'utente malintenzionato di inserire un corpo di posta elettronica di sua scelta, ignorando completamente l'e-mail generata. – Cheekysoft

4

Come altri hanno notato, è fantastico. Se non è disponibile, aggiungilo al tuo toolchest.

La variabile $headers è particolarmente pericolosa per la sicurezza. Può essere aggiunto e causare l'aggiunta di intestazioni spoofed. Questo post chiamato Email Injection discute abbastanza bene.

filter_var i s ottimo, ma un altro modo per assicurare che qualcosa sia un indirizzo di posta elettronica e non qualcosa di brutto è utilizzare una funzione isMail(). Eccone uno:

function isEmail($email) { 
    return preg_match('|^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]{2,})+$|i', $email); 
}; 

Quindi, per utilizzare questo, si potrebbe fare:

if (isset($_POST['email']) && isEmail($_POST['email'])) { 
    $email = $_POST['email'] ; 
} else { 
    // you could halt execution here, set $email to a default email address 
    // display an error, redirect, or some combination here, 
} 

In termini di convalida manuale, limitando la durata usando substr(), in esecuzione strip_tags() e comunque limitare ciò che può essere messo in

.
+1

Parlando di filter_var, ha anche un filtro per convalidare le e-mail in modo che la funzione 'isEmail' sia cattiva e inutile (per non parlare del fatto che le espressioni regolari non possono validare correttamente le e-mail). –

4

È necessario rimuovere qualsiasi newline dall'input fornito dagli utenti nelle intestazioni $, che viene passato a mail() ($ email nel tuo caso)! Vedi Email injection.

PHP dovrebbe prendersi cura di sanificazione $ a $ e soggetto, ma ci sono versioni di PHP con gli insetti (colpite sono PHP 4 < = 4.4.6 e PHP 5 < = 5.2.1, vedi MOPB-34-2007).

0

È possibile utilizzare il codice da artlung intestazione 's risposta s sopra per convalidare e-mail ..

io uso questo tipo di codice per evitare l'iniezione di testa ..

// define some mail() header's parts and commonly used spam code to filter using preg_match 
$match = "/(from\:|to\:|bcc\:|cc\:|content\-type\:|mime\-version\:|subject\:|x\-mailer\:|reply\-to\:|\%0a|\%0b)/i"; 

// check if any field's value containing the one or more of the code above 
if (preg_match($match, $name) || preg_match($match, $message) || preg_match($match, $email)) { 

// I use ajax, so I call the string below and send it to js file to check whether the email is failed to send or not 
echo "failed"; 

// If you are not using ajax, then you can redirect it with php header function i.e: header("Location: http://example.com/anypage/"); 

// stop the script before it reach or executing the mail function 
die(); 

} 

Il mail()' filtraggio sopra è troppo severo, dal momento che alcuni utenti potrebbero utilizzare le stringhe filtrate nel loro messaggio senza alcuna intenzione di dirottare il tuo modulo di posta elettronica, quindi reindirizzare a una pagina che spiega quale tipo di stringhe non è consentito nel modulo o spiegarlo sul tuo pagina del modulo.