1- <?php if ( ! defined ('BASEPATH ' )) exit ('No direct script access allowed ' );
1+ <?php if ( ! defined ('BASEPATH ' )) exit ('No direct script access allowed ' );
22/**
33 * CodeIgniter
44 *
@@ -69,16 +69,16 @@ class CI_Security {
6969 * @access protected
7070 */
7171 protected $ _never_allowed_str = array (
72- 'document.cookie ' => '[removed] ' ,
73- 'document.write ' => '[removed] ' ,
74- '.parentNode ' => '[removed] ' ,
75- '.innerHTML ' => '[removed] ' ,
76- 'window.location ' => '[removed] ' ,
77- '-moz-binding ' => '[removed] ' ,
78- '<!-- ' => '<!-- ' ,
79- '--> ' => '--> ' ,
80- '<![CDATA[ ' => '<![CDATA[ ' ,
81- '<comment> ' => '<comment> '
72+ 'document.cookie ' => '[removed] ' ,
73+ 'document.write ' => '[removed] ' ,
74+ '.parentNode ' => '[removed] ' ,
75+ '.innerHTML ' => '[removed] ' ,
76+ 'window.location ' => '[removed] ' ,
77+ '-moz-binding ' => '[removed] ' ,
78+ '<!-- ' => '<!-- ' ,
79+ '--> ' => '--> ' ,
80+ '<![CDATA[ ' => '<![CDATA[ ' ,
81+ '<comment> ' => '<comment> '
8282 );
8383
8484 /* never allowed, regex replacement */
@@ -89,10 +89,11 @@ class CI_Security {
8989 * @access protected
9090 */
9191 protected $ _never_allowed_regex = array (
92- "javascript\s*: " => '[removed] ' ,
93- "expression\s*(\(|&\#40;) " => '[removed] ' , // CSS and IE
94- "vbscript\s*: " => '[removed] ' , // IE, surprise!
95- "Redirect\s+302 " => '[removed] '
92+ 'javascript\s*: ' ,
93+ 'expression\s*(\(|&\#40;) ' , // CSS and IE
94+ 'vbscript\s*: ' , // IE, surprise!
95+ 'Redirect\s+302 ' ,
96+ "([ \"'])?data\s*:[^ \\1]*?base64[^ \\1]*?,[^ \\1]*? \\1? "
9697 );
9798
9899 /**
@@ -364,9 +365,9 @@ public function xss_clean($str, $is_image = FALSE)
364365 * These words are compacted back to their correct state.
365366 */
366367 $ words = array (
367- 'javascript ' , 'expression ' , 'vbscript ' , 'script ' ,
368- 'applet ' , 'alert ' , 'document ' , 'write ' , 'cookie ' , 'window '
369- );
368+ 'javascript ' , 'expression ' , 'vbscript ' , 'script ' , ' base64 ' ,
369+ 'applet ' , 'alert ' , 'document ' , 'write ' , 'cookie ' , 'window '
370+ );
370371
371372 foreach ($ words as $ word )
372373 {
@@ -524,38 +525,38 @@ public function entity_decode($str, $charset='UTF-8')
524525 public function sanitize_filename ($ str , $ relative_path = FALSE )
525526 {
526527 $ bad = array (
527- "../ " ,
528- "<!-- " ,
529- "--> " ,
530- "< " ,
531- "> " ,
532- "' " ,
533- '" ' ,
534- '& ' ,
535- '$ ' ,
536- '# ' ,
537- '{ ' ,
538- '} ' ,
539- '[ ' ,
540- '] ' ,
541- '= ' ,
542- '; ' ,
543- '? ' ,
544- "%20 " ,
545- "%22 " ,
546- "%3c " , // <
547- "%253c " , // <
548- "%3e " , // >
549- "%0e " , // >
550- "%28 " , // (
551- "%29 " , // )
552- "%2528 " , // (
553- "%26 " , // &
554- "%24 " , // $
555- "%3f " , // ?
556- "%3b " , // ;
557- "%3d " // =
558- );
528+ "../ " ,
529+ "<!-- " ,
530+ "--> " ,
531+ "< " ,
532+ "> " ,
533+ "' " ,
534+ '" ' ,
535+ '& ' ,
536+ '$ ' ,
537+ '# ' ,
538+ '{ ' ,
539+ '} ' ,
540+ '[ ' ,
541+ '] ' ,
542+ '= ' ,
543+ '; ' ,
544+ '? ' ,
545+ "%20 " ,
546+ "%22 " ,
547+ "%3c " , // <
548+ "%253c " , // <
549+ "%3e " , // >
550+ "%0e " , // >
551+ "%28 " , // (
552+ "%29 " , // )
553+ "%2528 " , // (
554+ "%26 " , // &
555+ "%24 " , // $
556+ "%3f " , // ?
557+ "%3b " , // ;
558+ "%3d " // =
559+ );
559560
560561 if ( ! $ relative_path )
561562 {
@@ -613,19 +614,20 @@ protected function _remove_evil_attributes($str, $is_image)
613614 */
614615 unset($ evil_attributes [array_search ('xmlns ' , $ evil_attributes )]);
615616 }
616-
617+
617618 do {
618619 $ count = 0 ;
619620 $ attribs = array ();
620-
621+
621622 // find occurrences of illegal attribute strings without quotes
622- preg_match_all (" /( " .implode ('| ' , $ evil_attributes )." )\s*=\s*([^\s]*)/is " , $ str , $ matches , PREG_SET_ORDER );
623-
623+ preg_match_all (' /( ' .implode ('| ' , $ evil_attributes ).' )\s*=\s*([^\s> ]*)/is ' , $ str , $ matches , PREG_SET_ORDER );
624+
624625 foreach ($ matches as $ attr )
625626 {
627+
626628 $ attribs [] = preg_quote ($ attr [0 ], '/ ' );
627629 }
628-
630+
629631 // find occurrences of illegal attribute strings with quotes (042 and 047 are octal quotes)
630632 preg_match_all ("/( " .implode ('| ' , $ evil_attributes ).")\s*=\s*( \042| \047)([^ \\2]*?)( \\2)/is " , $ str , $ matches , PREG_SET_ORDER );
631633
@@ -637,11 +639,11 @@ protected function _remove_evil_attributes($str, $is_image)
637639 // replace illegal attribute strings that are inside an html tag
638640 if (count ($ attribs ) > 0 )
639641 {
640- $ str = preg_replace ("/<(\/?[^><]+?)([^A-Za-z\-])( " .implode ('| ' , $ attribs ).")([\s><])([><]*)/i " , '<$1$2$4$5 ' , $ str , -1 , $ count );
642+ $ str = preg_replace ("/<(\/?[^><]+?)([^A-Za-z<> \-])(.*?)( " .implode ('| ' , $ attribs ).")(.*?)( [\s><])([><]*)/i " , '<$1 $3$5$6$7 ' , $ str , -1 , $ count );
641643 }
642-
644+
643645 } while ($ count );
644-
646+
645647 return $ str ;
646648 }
647649
@@ -682,9 +684,15 @@ protected function _sanitize_naughty_html($matches)
682684 */
683685 protected function _js_link_removal ($ match )
684686 {
685- $ attributes = $ this ->_filter_attributes (str_replace (array ('< ' , '> ' ), '' , $ match [1 ]));
686-
687- return str_replace ($ match [1 ], preg_replace ("#href=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si " , "" , $ attributes ), $ match [0 ]);
687+ return str_replace (
688+ $ match [1 ],
689+ preg_replace (
690+ '#href=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si ' ,
691+ '' ,
692+ $ this ->_filter_attributes (str_replace (array ('< ' , '> ' ), '' , $ match [1 ]))
693+ ),
694+ $ match [0 ]
695+ );
688696 }
689697
690698 // --------------------------------------------------------------------
@@ -702,9 +710,15 @@ protected function _js_link_removal($match)
702710 */
703711 protected function _js_img_removal ($ match )
704712 {
705- $ attributes = $ this ->_filter_attributes (str_replace (array ('< ' , '> ' ), '' , $ match [1 ]));
706-
707- return str_replace ($ match [1 ], preg_replace ("#src=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si " , "" , $ attributes ), $ match [0 ]);
713+ return str_replace (
714+ $ match [1 ],
715+ preg_replace (
716+ '#src=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si ' ,
717+ '' ,
718+ $ this ->_filter_attributes (str_replace (array ('< ' , '> ' ), '' , $ match [1 ]))
719+ ),
720+ $ match [0 ]
721+ );
708722 }
709723
710724 // --------------------------------------------------------------------
@@ -819,14 +833,11 @@ protected function _validate_entities($str)
819833 */
820834 protected function _do_never_allowed ($ str )
821835 {
822- foreach ($ this ->_never_allowed_str as $ key => $ val )
823- {
824- $ str = str_replace ($ key , $ val , $ str );
825- }
836+ $ str = str_replace (array_keys ($ this ->_never_allowed_str ), $ this ->_never_allowed_str , $ str );
826837
827- foreach ($ this ->_never_allowed_regex as $ key => $ val )
838+ foreach ($ this ->_never_allowed_regex as $ regex )
828839 {
829- $ str = preg_replace (" # " . $ key . " #i " , $ val , $ str );
840+ $ str = preg_replace (' # ' . $ regex . ' #is ' , ' [removed] ' , $ str );
830841 }
831842
832843 return $ str ;
0 commit comments