CodeIgniter: rimuovere il tag iframe dal filtro xss
CodeIgniter integra un filtro per la protezione di attacchi xss (http://it.wikipedia.org/wiki/Cross-site_scripting). Questa funzione è attivabile manualmente in fase di validazione dei form oppure è possibile attivarla per l'intero sistema impostando nel file di configurazione:
$config['global_xss_filtering'] = TRUE;
In questo modo, oltre ad altri controlli, vengono disabilitati una serie di tags potenzialmente dannosi:
$naughty = 'alert|applet|audio|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|isindex|layer|link|meta|object|plaintext|style|script|textarea|title|video|xml|xss';
Per abilitare il tag iframe ci sono 3 soluzioni: 1) Il modo più veloce (e meno sicuro) per abilitare il tag iframe sarebbe modificare la stringa dei tags nel file Security.php (all'interno della cartella core di CodeIgniter) rimuovendo il testo "|iframe". 2) Se non si vuole modificare il file originale è possibile estendere la classe riscrivendo la funzione xss_clean con la variabile $naughty modificata. 3) Per mantenere un buon livello di sicurezza è poi possibile estendere la classe Security modificando la funzione clean_xss in modo meno drastico (questo è il metodo consigliato), controllando l'url degli iframe in modo da abilitare solo quelli desiderati (ad esempio per youtube, vimeo o altri portali sicuri) rimuovendo tutti quelli potenzialmente dannosi. Nella funzione si sostituisce:
$str = preg_replace_callback('#<(/*\s*)(' . $naughty . ')([^><]*)([><]*)#is', array($this, '_sanitize_naughty_html'), $str);
Con questo codice:
// START MOD - ALLOW IFRAME
// BY Emanuele Fantin
// Allow iframe tags
$re_replace = array();
if (defined('ALLOWED_IFRAME_URL_XSS'))
{
preg_match_all('/<iframe.*src=\"(.*)\".*><\/iframe>/isU', $str, $matches, PREG_SET_ORDER);
$allowed_url_sources = unserialize(ALLOWED_IFRAME_URL_XSS);
// if there are iframes in string
if (!empty($matches))
{
foreach ($matches as $k => $iframe)
{
$iframe_code = $iframe[0];
$iframe_url = trim(strtolower($iframe[1]));
foreach ($allowed_url_sources as $allowed_url)
{
//check if the iframe url is allowed
if (strncmp($iframe_url, $allowed_url, strlen($allowed_url)) == 0)
{
//create a temporary placeholder
$tmp_placeholder = '##' . time() . '_' . rand() . '##';
$str = str_replace($iframe_code, $tmp_placeholder, $str);
//add an item for reverse replace (used later)
$re_replace[] = array(
'placeholder' => $tmp_placeholder,
'original_tag' => $iframe_code
);
}
}
}
}
}
$str = preg_replace_callback('#<(/*\s*)(' . $naughty . ')([^><]*)([><]*)#is', array($this, '_sanitize_naughty_html'), $str);
//reverse replace of each placeholder
foreach ($re_replace as $item)
{
$str = str_replace($item['placeholder'], $item['original_tag'], $str);
}
//END MOD
Il codice funziona in questo modo:
- controlla se nella stringa ci sono tags di tipo iframe
- se l'url dell'iframe è tra quelli permessi (definiti in una costante globale) sostituisce ogni tag iframe e il suo contenuto con una stringa temporanea (placeholder) prima che venga richiamata la funzione_sanitize_naughty_html()
- dopo la pulizia della stringa da parte di codeigniter i placeholder vengono sostituiti con il codice iframe originale che in questo modo non viene modificato
Nella costante globale si definiscono gli url in questo modo:
define('ALLOWED_IFRAME_URL_XSS', serialize(array( 'http://player.vimeo.com', 'https://player.vimeo.com', '//www.youtube.com',//youtube utilizza anche questa notazione senza http: 'http://www.youtube.com', 'https://www.youtube.com', )));
Con lo stesso metodo (tag -> placeholder temporaneo -> tag originale) si possono abilitare anche altri tipi di tag (ad esempio object o embed) scrivendo il codice apposito per gestirli in base alle proprie esigenze. Anche il controllo degli url permessi può essere migliorato utilizzando le espressioni regolari.
Commenti