diff --git a/tests/checks/CheckTestBase.php b/tests/checks/CheckTestBase.php index 442283a..9844dc4 100644 --- a/tests/checks/CheckTestBase.php +++ b/tests/checks/CheckTestBase.php @@ -13,7 +13,10 @@ public function setUp() { } public function runCheck( $file_contents ) { - $input = array( 'php' => array( 'test.php' => $file_contents ) ); + $input = array( + 'php' => array('test.php' => $file_contents ), + 'css' => array('test.css' => $file_contents ), + ); $result = $this->check->check( $input ); $errors = $this->check->get_errors(); diff --git a/tests/checks/test-XSSVectorsCheck.php b/tests/checks/test-XSSVectorsCheck.php new file mode 100644 index 0000000..36d8501 --- /dev/null +++ b/tests/checks/test-XSSVectorsCheck.php @@ -0,0 +1,529 @@ + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-in-link-tag-href', $error_slugs ); + } + + public function test_obfuscated_xss_in_link_tag_href() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-in-link-tag-href', $error_slugs ); + } + + public function test_xss_not_in_link_tag_href() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-in-link-tag-href', $error_slugs ); + } + + /* + * XSS javascript in base href tag + */ + public function test_xss_in_base_tag_href() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-in-base-tag-href', $error_slugs ); + } + + public function test_xss_not_in_base_tag_href() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-in-base-tag-href', $error_slugs ); + } + + /* + * XSS javascript in meta tag content attribute + */ + public function test_xss_in_meta_tag_content() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-in-meta-tag-content', $error_slugs ); + } + + public function test_xss_not_meta_tag_content() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-in-meta-tag-content', $error_slugs ); + } + + /* + * XSS javascript in any src attribute + */ + public function test_xss_in_any_tag_src() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-javascript-in-any-tag-src', $error_slugs ); + } + + public function test_xss_not_in_any_tag_src() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-javascript-in-any-tag-src', $error_slugs ); + } + + /* + * XSS javascript in style attribute and style tag + */ + public function test_xss_in_tag_style_attr() { + $file_contents = <<<'EOT' +
+EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-javascript-in-style-attribute', $error_slugs ); + } + + public function test_xss_not_in_tag_style_attr() { + $file_contents = <<<'EOT' +
+EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-javascript-in-style-attribute', $error_slugs ); + } + + public function test_xss_unicode_obfuscated_javascript_in_tag_style_attr() { + $file_contents = <<<'EOT' +
+EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-unicode-obfuscated-javascript-in-style-attribute', $error_slugs ); + } + + public function test_xss_unicode_obfuscated_javascript_not_in_tag_style_attr() { + $file_contents = <<<'EOT' +
+EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-unicode-obfuscated-javascript-in-style-attribute', $error_slugs ); + } + + public function test_xss_in_style_tag() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-javascript-in-style-tag', $error_slugs ); + } + + public function test_xss_not_in_style_tag() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-javascript-in-style-tag', $error_slugs ); + } + + /* + * XSS -moz-binding in style attributes and style tag + */ + public function test_moz_binding_in_tag_style_attr() { + $file_contents = <<<'EOT' +
+EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'moz-binding-xss-in-style-attribute', $error_slugs ); + } + + public function test_moz_binding_not_in_tag_style_attr() { + $file_contents = <<<'EOT' +
+EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'moz-binding-xss-in-style-attribute', $error_slugs ); + } + + public function test_moz_binding_in_tag_style() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'moz-binding-xss-in-style-tag', $error_slugs ); + } + + public function test_moz_binding_not_in_tag_style() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'moz-binding-xss-in-style-tag', $error_slugs ); + } + + /* + * XSS CSS expression property in style attribute and style tag + */ + public function test_css_expression_xss_in_style_tag() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'css-expression-xss-in-style-tag', $error_slugs ); + } + + public function test_css_expression_xss_not_in_style_tag() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'css-expression-xss-in-style-tag', $error_slugs ); + } + + public function test_css_expression_xss_in_style_attribute() { + $file_contents = <<<'EOT' +
> +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'css-expression-xss-in-style-attribute', $error_slugs ); + } + + public function test_obfuscated_css_expression_xss_in_style_attribute() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'css-expression-xss-in-style-attribute', $error_slugs ); + } + + public function test_css_expression_xss_not_in_style_attribute() { + $file_contents = <<<'EOT' +
+EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'css-expression-xss-in-style-attribute', $error_slugs ); + } + + /* + * XSS CSS behavior property in style attribute and style tag + */ + public function test_css_behavior_xss_in_style_tag() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'css-behavior-xss-in-style-tag', $error_slugs ); + } + + public function test_css_behavior_xss_not_in_style_tag() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'css-behavior-xss-in-style-attribute', $error_slugs ); + } + + public function test_css_behavior_xss_in_style_attribute() { + $file_contents = <<<'EOT' +
+EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'css-behavior-xss-in-style-attribute', $error_slugs ); + } + + public function test_css_behavior_xss_not_in_style_attribute() { + $file_contents = <<<'EOT' +
+EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'css-behavior-xss-in-style-attribute', $error_slugs ); + } + + /* + * XSS Script tag in malformed img tag + */ + public function test_script_tag_in_malformed_img_tag() { + $file_contents = <<<'EOT' + "> +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'malformed-img-tag-xss-script', $error_slugs ); + } + + public function test_script_tag_not_in_malformed_img_tag() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'malformed-img-tag-xss-script', $error_slugs ); + } + + /* + * Malformed whitespace, embedded characters, and comment abuse + */ + public function test_comment_obfuscated_javascript_in_src_attr() { + $file_contents = <<<'EOT' + + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-html-comment-obfuscated-javascript-in-any-tag-src', $error_slugs ); + } + + public function test_space_before_javascript_in_src_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-whitespace-and-javascript-in-any-tag-src', $error_slugs ); + } + + public function test_space_and_metachar_before_javascript_in_src_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-whitespace-and-javascript-in-any-tag-src', $error_slugs ); + } + + public function test_tab_javascript_in_src_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-whitespace-obfuscated-javascript-in-any-tag-src', $error_slugs ); + } + + public function test_encoded_tab_javascript_in_src_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-javascript-in-any-tag-src', $error_slugs ); + } + + public function test_encoded_newline_javascript_in_src_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-javascript-in-any-tag-src', $error_slugs ); + } + + public function test_encoded_carriage_return_javascript_in_src_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-javascript-in-any-tag-src', $error_slugs ); + } + + public function test_null_character_javascript_in_src_attr() { + $file_contents = ""; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-javascript-in-any-tag-src', $error_slugs ); + } + + /* + * XSS javascript declaration in tag background attribute + */ + public function test_javascript_in_body_tag_background_attribute() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-in-background-attribute', $error_slugs ); + } + + public function test_javascript_not_in_body_tag_background_attribute() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-in-background-attribute', $error_slugs ); + } + + /* + * XSS javascript in img tag rarely used attributes + */ + public function test_xss_in_img_dynsrc_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-in-img-dynsrc-attr', $error_slugs ); + } + + public function test_xss_not_in_img_dynsrc_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-in-img-dynsrc-attr', $error_slugs ); + } + + public function test_xss_in_img_lowsrc_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-in-img-lowsrc-attr', $error_slugs ); + } + + public function test_xss_not_in_img_lowsrc_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-in-img-lowsrc-attr', $error_slugs ); + } + + /* + * XSS less used scripting languages in any tag src attributes + */ + public function test_xss_vbscript_in_src_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-vbscript-in-any-tag-src', $error_slugs ); + } + + public function test_xss_vbscript_not_in_src_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-vbscript-in-any-tag-src', $error_slugs ); + } + + public function test_xss_livescript_in_src_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-livescript-in-any-tag-src', $error_slugs ); + } + + public function test_xss_livescript_not_in_src_attr() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-livescript-in-any-tag-src', $error_slugs ); + } + + /* + * XSS Object type x-scriptlet + */ + public function test_xscript_in_object_tag() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'xss-object-type-x-scriptlet', $error_slugs ); + } + + public function test_xscript_not_in_object_tag() { + $file_contents = <<<'EOT' + +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'xss-object-type-x-scriptlet', $error_slugs ); + } + + /* + * XSS in CSS + */ + public function test_xss_javascript_in_css() { + $file_contents = <<<'EOT' + body { + background-image:url("javascript:alert('XSS')"); + } +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'javascript-in-css', $error_slugs ); + } + + public function test_xss_javascript_not_in_css() { + $file_contents = <<<'EOT' + body { + background-image:url("background.gif"); + } +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'javascript-in-css', $error_slugs ); + } + + public function test_xss_behavior_in_css() { + $file_contents = <<<'EOT' + body { + behavior: url(xss.htc); + } +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'behavior-in-css', $error_slugs ); + } + + public function test_xss_behavior_not_in_css() { + $file_contents = <<<'EOT' + body { + background-image:url("background.gif"); + } +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'behavior-in-css', $error_slugs ); + } + + public function test_xss_moz_binding_in_css() { + $file_contents = <<<'EOT' + body { + -moz-binding:url("http://ha.ckers.org/xssmoz.xml#xss") + } +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'moz-binding-in-css', $error_slugs ); + } + + public function test_xss_moz_binding_not_in_css() { + $file_contents = <<<'EOT' + body { + background-image:url("background.gif"); + } +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'moz-binding-in-css', $error_slugs ); + } + + public function test_xss_expression_in_css() { + $file_contents = <<<'EOT' + body { + width: expression(alert('XSS')); + } +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertContains( 'expression-in-css', $error_slugs ); + } + + public function test_xss_expression_not_in_css() { + $file_contents = <<<'EOT' + body { + width: 100%; + } +EOT; + $error_slugs = $this->runCheck( $file_contents ); + $this->assertNotContains( 'expression-in-css', $error_slugs ); + } + +} \ No newline at end of file diff --git a/vip-scanner/checks/XSSVectorsCheck.php b/vip-scanner/checks/XSSVectorsCheck.php new file mode 100644 index 0000000..bcb359f --- /dev/null +++ b/vip-scanner/checks/XSSVectorsCheck.php @@ -0,0 +1,269 @@ +)/misU', '', $string ); + + /** + * Removes slashes + */ + $string = str_replace( array( '/', '\\' ), '', $string ); + + /** + * Removes encoded tabs ( ), newlines ( ), and carriage returns ( ) + */ + $string = str_replace( array( ' ', ' ', ' ' ), '', $string ); + + /** + * Removes null characters + */ + $string = str_replace( "\0", "", $string ); + + /** + * Removes all whitespace + */ + $string = preg_replace( '/(\s)/misU', '', $string ); + + return $string; + } + + function check( $files ) { + $result = true; + + /* + * PHP and HTML Checks + */ + $checks = array( + 'xss-in-base-tag-href' => array( + 'expression' => '/<[\s]*?base(?:[^\>]*?)href(?:\s)*?=[\s]*?(?.*)(?=\s|=|>)/imsU', + 'match-text' => 'javascript:', + 'level' => 'Warning', + 'note' => esc_html( 'XSS Attack Vector found in tag href attribute (javascript:)' ), + ), + 'xss-in-link-tag-href' => array( + 'expression' => '/<[\s]*?link(?:[^\>]*?)href(?:\s)*?=[\s]*?(?.*)(?=\s|=|>)/imsU', + 'match-text' => 'javascript:', + 'level' => 'Warning', + 'note' => esc_html( 'XSS Attack Vector found in tag href attribute (javascript:)' ), + ), + 'xss-in-meta-tag-content' => array( + 'expression' => '/<[\s]*?meta(?:[^\>]*?)content(?:\s)*?=[\s]*?(?.*)(?=>)/imsU', + 'match-text' => 'javascript:', + 'level' => 'Warning', + 'note' => esc_html( 'XSS Attack Vector found in tag content attribute (javascript:)' ), + ), + 'xss-javascript-in-any-tag-src' => array( + 'expression' => '/<[\s]*?[a-z]*(?:[^\>]*?)src(?:\s)*?=[\s]*?(?.*)(?=\s|=|>)/imsU', + 'match-text' => 'javascript:', + 'level' => 'Warning', + 'note' => 'XSS Attack Vector found in HTML tag src attribute (javascript:)', + ), + 'xss-html-comment-obfuscated-javascript-in-any-tag-src' => array( + 'expression' => '/<[\s]*?[a-z]*(?:[^\>]*?)src(?:\s)*?=[\s]*?(?(?:.*)(?:<--)?(?:.*)(?:-->)(?:.*))(?=\s|=|>)/imsU', + 'match-text' => 'javascript:', + 'level' => 'Warning', + 'note' => 'XSS Attack Vector found in HTML tag src attribute (javascript:)', + ), + 'xss-whitespace-and-javascript-in-any-tag-src' => array( + 'expression' => '/<[\s]*?[a-z]*(?:[^\>]*?)src(?:\s)*?=[\s]*?(?(?:[\s]*)?.*(?:[\s]*)?)(?=\=|>)/imsU', + 'match-text' => 'javascript:', + 'level' => 'Warning', + 'note' => 'XSS Attack Vector found in HTML tag src attribute (javascript:)', + ), + 'xss-whitespace-obfuscated-javascript-in-any-tag-src' => array( + 'expression' => '/<[\s]*?[a-z]*(?:[^\>]*?)src(?:\s)*?=[\s]*?(?(?:[\s]*)?(?:.*)j(?:[\s]*)?a(?:[\s]*)?v(?:[\s]*)?a(?:[\s]*)?s(?:[\s]*)?c(?:[\s]*)?r(?:[\s]*)?i(?:[\s]*)?p(?:[\s]*)?t(?:[\s]*)?:(?:.*)(?:[\s]*)?)(?=\=|>)/imsU', + 'match-text' => 'javascript:', + 'level' => 'Warning', + 'note' => 'XSS Attack Vector found in HTML tag src attribute (javascript:)', + ), + 'xss-vbscript-in-any-tag-src' => array( + 'expression' => '/<[\s]*?[a-z]*(?:[^\>]*?)src(?:\s)*?=[\s]*?(?.*)(?=\s|=|>)/imsU', + 'match-text' => 'vbscript:', + 'level' => 'Warning', + 'note' => 'XSS Attack Vector found in HTML tag src attribute (vbscript:)', + ), + 'xss-livescript-in-any-tag-src' => array( + 'expression' => '/<[\s]*?[a-z]*(?:[^\>]*?)src(?:\s)*?=[\s]*?(?.*)(?=\s|=|>)/imsU', + 'match-text' => 'livescript:', + 'level' => 'Warning', + 'note' => 'XSS Attack Vector found in HTML tag src attribute (livescript:)', + ), + 'xss-javascript-in-style-tag' => array( + 'expression' => '/<[\s]*?style(?:.*?)?>(?.*?)<[\s]*?\/[\s]*?[a-z]*?[\s]*?>/imsU', + 'match-text' => 'javascript:', + 'level' => 'Warning', + 'note' => esc_html( 'XSS Attack Vector found in