diff --git a/tests/integration/docker-compose.setup.yml b/tests/integration/docker-compose.setup.yml index e5050da8f..122966f36 100644 --- a/tests/integration/docker-compose.setup.yml +++ b/tests/integration/docker-compose.setup.yml @@ -371,6 +371,11 @@ services: MYSQL_DATABASE: ${WP_MYSQL_DATABASE} MYSQL_USER: ${WP_MYSQL_USER} MYSQL_PASSWORD: ${WP_MYSQL_PASSWORD} + # Apache container for the csrf module + csrf: + <<: [ *default_php_setup, *healthcheck_web ] + volumes: + - ./test_mod_csrf/php/src:/var/www/html/ # Wordpress container wordpress: @@ -463,6 +468,8 @@ services: condition: service_healthy http_headers: condition: service_healthy + csrf: + condition: service_healthy wordpress: condition: service_healthy backup: diff --git a/tests/integration/run.sh b/tests/integration/run.sh index 4d0d6f1a2..6cb2cf4df 100755 --- a/tests/integration/run.sh +++ b/tests/integration/run.sh @@ -9,6 +9,7 @@ test_mod_buster \ test_mod_cookieflags \ test_mod_crlf \ test_mod_csp \ +test_mod_csrf \ test_mod_drupal_enum \ test_mod_htaccess \ test_mod_http_headers \ diff --git a/tests/integration/test_mod_csrf/assertions/check.sh b/tests/integration/test_mod_csrf/assertions/check.sh new file mode 120000 index 000000000..aa85f6fcd --- /dev/null +++ b/tests/integration/test_mod_csrf/assertions/check.sh @@ -0,0 +1 @@ +../../check.sh \ No newline at end of file diff --git a/tests/integration/test_mod_csrf/assertions/csrf_fake_protected_form.php.json b/tests/integration/test_mod_csrf/assertions/csrf_fake_protected_form.php.json new file mode 100644 index 000000000..b83b352a3 --- /dev/null +++ b/tests/integration/test_mod_csrf/assertions/csrf_fake_protected_form.php.json @@ -0,0 +1,202 @@ +{ + "vulnerabilities": { + "Cross Site Request Forgery": [ + { + "method": "POST", + "path": "/fake_protected_form.php", + "info": "CSRF token 'csrf_token' might be easy to predict", + "parameter": "", + "module": "csrf", + "http_request": "POST /fake_protected_form.php HTTP/1.1\ncontent-type: application/x-www-form-urlencoded, application/x-www-form-urlencoded\nhost: csrf\nconnection: keep-alive\nuser-agent: Mozilla/5.0 (Windows NT 6.1; rv:45.0) Gecko/20100101 Firefox/45.0\naccept-language: en-US\naccept-encoding: gzip, deflate, br\naccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\nreferer: http://csrf/fake_protected_form.php\ncookie: PHPSESSID=1335df1b1b4a2149e8690c7ce5fc3932\ncontent-length: 39\nContent-Type: application/x-www-form-urlencoded\n\ncsrf_token=AAAAAAAAAAAAAAA&name=default", + "wstg": [ + "WSTG-SESS-05" + ] + } + ] + }, + "infos": { + "target": "http://csrf/fake_protected_form.php", + "crawled_pages": [ + { + "request": { + "url": "http://csrf/fake_protected_form.php", + "method": "GET", + "headers": [ + [ + "accept", + "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" + ], + [ + "accept-encoding", + "gzip, deflate, br" + ], + [ + "accept-language", + "en-US" + ], + [ + "connection", + "keep-alive" + ], + [ + "host", + "csrf" + ], + [ + "user-agent", + "Mozilla/5.0 (Windows NT 6.1; rv:45.0) Gecko/20100101 Firefox/45.0" + ] + ] + }, + "response": { + "status_code": 200, + "body": "\t\tCSRF protected test


", + "headers": [ + [ + "cache-control", + "no-store, no-cache, must-revalidate" + ], + [ + "connection", + "Keep-Alive" + ], + [ + "content-encoding", + "gzip" + ], + [ + "content-length", + "226" + ], + [ + "content-type", + "text/html; charset=UTF-8" + ], + [ + "expires", + "Thu, 19 Nov 1981 08:52:00 GMT" + ], + [ + "pragma", + "no-cache" + ], + [ + "server", + "Apache/2.4.56 (Debian)" + ], + [ + "set-cookie", + "PHPSESSID=1335df1b1b4a2149e8690c7ce5fc3932; path=/" + ], + [ + "vary", + "Accept-Encoding" + ], + [ + "x-powered-by", + "PHP/8.1.18" + ] + ] + } + }, + { + "request": { + "url": "http://csrf/fake_protected_form.php", + "method": "POST", + "headers": [ + [ + "accept", + "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" + ], + [ + "accept-encoding", + "gzip, deflate, br" + ], + [ + "accept-language", + "en-US" + ], + [ + "connection", + "keep-alive" + ], + [ + "content-length", + "39" + ], + [ + "content-type", + "application/x-www-form-urlencoded" + ], + [ + "cookie", + "PHPSESSID=1335df1b1b4a2149e8690c7ce5fc3932" + ], + [ + "host", + "csrf" + ], + [ + "referer", + "http://csrf/fake_protected_form.php" + ], + [ + "user-agent", + "Mozilla/5.0 (Windows NT 6.1; rv:45.0) Gecko/20100101 Firefox/45.0" + ] + ] + }, + "response": { + "status_code": 200, + "body": "\t\tCSRF protected test


form submitted !", + "headers": [ + [ + "cache-control", + "no-store, no-cache, must-revalidate" + ], + [ + "connection", + "Keep-Alive" + ], + [ + "content-encoding", + "gzip" + ], + [ + "content-length", + "232" + ], + [ + "content-type", + "text/html; charset=UTF-8" + ], + [ + "expires", + "Thu, 19 Nov 1981 08:52:00 GMT" + ], + [ + "pragma", + "no-cache" + ], + [ + "server", + "Apache/2.4.56 (Debian)" + ], + [ + "set-cookie", + "PHPSESSID=1335df1b1b4a2149e8690c7ce5fc3932; path=/" + ], + [ + "vary", + "Accept-Encoding" + ], + [ + "x-powered-by", + "PHP/8.1.18" + ] + ] + } + } + ] + } +} \ No newline at end of file diff --git a/tests/integration/test_mod_csrf/assertions/csrf_protected_form.php.json b/tests/integration/test_mod_csrf/assertions/csrf_protected_form.php.json new file mode 100644 index 000000000..146edeb2a --- /dev/null +++ b/tests/integration/test_mod_csrf/assertions/csrf_protected_form.php.json @@ -0,0 +1,190 @@ +{ + "vulnerabilities": { + "Cross Site Request Forgery": [] + }, + "infos": { + "target": "http://csrf/protected_form.php", + "crawled_pages": [ + { + "request": { + "url": "http://csrf/protected_form.php", + "method": "GET", + "headers": [ + [ + "accept", + "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" + ], + [ + "accept-encoding", + "gzip, deflate, br" + ], + [ + "accept-language", + "en-US" + ], + [ + "connection", + "keep-alive" + ], + [ + "host", + "csrf" + ], + [ + "user-agent", + "Mozilla/5.0 (Windows NT 6.1; rv:45.0) Gecko/20100101 Firefox/45.0" + ] + ] + }, + "response": { + "status_code": 200, + "body": "\t\tCSRF protected test


", + "headers": [ + [ + "cache-control", + "no-store, no-cache, must-revalidate" + ], + [ + "connection", + "Keep-Alive" + ], + [ + "content-encoding", + "gzip" + ], + [ + "content-length", + "273" + ], + [ + "content-type", + "text/html; charset=UTF-8" + ], + [ + "expires", + "Thu, 19 Nov 1981 08:52:00 GMT" + ], + [ + "pragma", + "no-cache" + ], + [ + "server", + "Apache/2.4.56 (Debian)" + ], + [ + "set-cookie", + "PHPSESSID=ldsu3ighl8der4ujghl3siur1fhgiu; path=/" + ], + [ + "vary", + "Accept-Encoding" + ], + [ + "x-powered-by", + "PHP/8.1.18" + ] + ] + } + }, + { + "request": { + "url": "http://csrf/protected_form.php", + "method": "POST", + "headers": [ + [ + "accept", + "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" + ], + [ + "accept-encoding", + "gzip, deflate, br" + ], + [ + "accept-language", + "en-US" + ], + [ + "connection", + "keep-alive" + ], + [ + "content-length", + "88" + ], + [ + "content-type", + "application/x-www-form-urlencoded" + ], + [ + "cookie", + "PHPSESSID=ldsu3ighl8der4ujghl3siur1fhgiu" + ], + [ + "host", + "csrf" + ], + [ + "referer", + "http://csrf/protected_form.php" + ], + [ + "user-agent", + "Mozilla/5.0 (Windows NT 6.1; rv:45.0) Gecko/20100101 Firefox/45.0" + ] + ] + }, + "response": { + "status_code": 200, + "body": "\t\tCSRF protected test


form submitted !", + "headers": [ + [ + "cache-control", + "no-store, no-cache, must-revalidate" + ], + [ + "connection", + "Keep-Alive" + ], + [ + "content-encoding", + "gzip" + ], + [ + "content-length", + "279" + ], + [ + "content-type", + "text/html; charset=UTF-8" + ], + [ + "expires", + "Thu, 19 Nov 1981 08:52:00 GMT" + ], + [ + "pragma", + "no-cache" + ], + [ + "server", + "Apache/2.4.56 (Debian)" + ], + [ + "set-cookie", + "PHPSESSID=ldsu3ighl8der4ujghl3siur1fhgiu; path=/" + ], + [ + "vary", + "Accept-Encoding" + ], + [ + "x-powered-by", + "PHP/8.1.18" + ] + ] + } + } + ] + } +} \ No newline at end of file diff --git a/tests/integration/test_mod_csrf/assertions/csrf_unprotected_form.php.json b/tests/integration/test_mod_csrf/assertions/csrf_unprotected_form.php.json new file mode 100644 index 000000000..3761839da --- /dev/null +++ b/tests/integration/test_mod_csrf/assertions/csrf_unprotected_form.php.json @@ -0,0 +1,202 @@ +{ + "vulnerabilities": { + "Cross Site Request Forgery": [ + { + "method": "POST", + "path": "/unprotected_form.php", + "info": "Lack of anti CSRF token", + "parameter": "", + "module": "csrf", + "http_request": "POST /unprotected_form.php HTTP/1.1\nhost: csrf\nconnection: keep-alive\nuser-agent: Mozilla/5.0 (Windows NT 6.1; rv:45.0) Gecko/20100101 Firefox/45.0\naccept-language: en-US\naccept-encoding: gzip, deflate, br\naccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\ncontent-type: application/x-www-form-urlencoded\nreferer: http://csrf/unprotected_form.php\ncookie: PHPSESSID=8f6s47ef68wse4f38esfsfew864fqdez\ncontent-length: 12\nContent-Type: application/x-www-form-urlencoded\n\nname=default", + "wstg": [ + "WSTG-SESS-05" + ] + } + ] + }, + "infos": { + "target": "http://csrf/unprotected_form.php", + "crawled_pages": [ + { + "request": { + "url": "http://csrf/unprotected_form.php", + "method": "GET", + "headers": [ + [ + "accept", + "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" + ], + [ + "accept-encoding", + "gzip, deflate, br" + ], + [ + "accept-language", + "en-US" + ], + [ + "connection", + "keep-alive" + ], + [ + "host", + "csrf" + ], + [ + "user-agent", + "Mozilla/5.0 (Windows NT 6.1; rv:45.0) Gecko/20100101 Firefox/45.0" + ] + ] + }, + "response": { + "status_code": 200, + "body": "\n\n\n\t\n\tCSRF unprotected test\n\n\n
\n \n

\n \n
\n\n\n\n", + "headers": [ + [ + "cache-control", + "no-store, no-cache, must-revalidate" + ], + [ + "connection", + "Keep-Alive" + ], + [ + "content-encoding", + "gzip" + ], + [ + "content-length", + "206" + ], + [ + "content-type", + "text/html; charset=UTF-8" + ], + [ + "expires", + "Thu, 19 Nov 1981 08:52:00 GMT" + ], + [ + "pragma", + "no-cache" + ], + [ + "server", + "Apache/2.4.56 (Debian)" + ], + [ + "set-cookie", + "PHPSESSID=8f6s47ef68wse4f38esfsfew864fqdez; path=/" + ], + [ + "vary", + "Accept-Encoding" + ], + [ + "x-powered-by", + "PHP/8.1.18" + ] + ] + } + }, + { + "request": { + "url": "http://csrf/unprotected_form.php", + "method": "POST", + "headers": [ + [ + "accept", + "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" + ], + [ + "accept-encoding", + "gzip, deflate, br" + ], + [ + "accept-language", + "en-US" + ], + [ + "connection", + "keep-alive" + ], + [ + "content-length", + "12" + ], + [ + "content-type", + "application/x-www-form-urlencoded" + ], + [ + "cookie", + "PHPSESSID=8f6s47ef68wse4f38esfsfew864fqdez" + ], + [ + "host", + "csrf" + ], + [ + "referer", + "http://csrf/unprotected_form.php" + ], + [ + "user-agent", + "Mozilla/5.0 (Windows NT 6.1; rv:45.0) Gecko/20100101 Firefox/45.0" + ] + ] + }, + "response": { + "status_code": 200, + "body": "form submitted !\n\n\n\t\n\tCSRF unprotected test\n\n\n
\n \n

\n \n
\n\n\n\n", + "headers": [ + [ + "cache-control", + "no-store, no-cache, must-revalidate" + ], + [ + "connection", + "Keep-Alive" + ], + [ + "content-encoding", + "gzip" + ], + [ + "content-length", + "215" + ], + [ + "content-type", + "text/html; charset=UTF-8" + ], + [ + "expires", + "Thu, 19 Nov 1981 08:52:00 GMT" + ], + [ + "pragma", + "no-cache" + ], + [ + "server", + "Apache/2.4.56 (Debian)" + ], + [ + "set-cookie", + "PHPSESSID=8f6s47ef68wse4f38esfsfew864fqdez; path=/" + ], + [ + "vary", + "Accept-Encoding" + ], + [ + "x-powered-by", + "PHP/8.1.18" + ] + ] + } + } + ] + } +} \ No newline at end of file diff --git a/tests/integration/test_mod_csrf/php/src/fake_protected_form.php b/tests/integration/test_mod_csrf/php/src/fake_protected_form.php new file mode 100644 index 000000000..a8cdc4a0b --- /dev/null +++ b/tests/integration/test_mod_csrf/php/src/fake_protected_form.php @@ -0,0 +1,44 @@ +'; +echo ''; +echo ''; +echo ' '; +echo ' CSRF protected test'; +echo ''; +echo ''; +echo '
'; +echo ' '; +echo ' '; +echo '

'; +echo ' '; +echo '
'; +echo ''; +echo ''; + +if ($_SERVER['REQUEST_METHOD'] === 'POST'){ + if(isset($_SESSION['csrf_token']) && isset($_POST['csrf_token'])){ + if ($_POST['csrf_token'] !== $_SESSION['csrf_token']){ + http_response_code(403); + die('CSRF token mismatch'); + } + else{ + http_response_code(200); + echo "form submitted !"; + } + } + else{ + http_response_code(403); + echo "CSRF token missing"; + } +} +?> diff --git a/tests/integration/test_mod_csrf/php/src/index.php b/tests/integration/test_mod_csrf/php/src/index.php new file mode 100644 index 000000000..c3a2a248b --- /dev/null +++ b/tests/integration/test_mod_csrf/php/src/index.php @@ -0,0 +1,15 @@ + + + + Index + + +

Index

+

This is a simple PHP web page.

+ + + diff --git a/tests/integration/test_mod_csrf/php/src/protected_form.php b/tests/integration/test_mod_csrf/php/src/protected_form.php new file mode 100644 index 000000000..2e761a792 --- /dev/null +++ b/tests/integration/test_mod_csrf/php/src/protected_form.php @@ -0,0 +1,43 @@ +'; +echo ''; +echo ''; +echo ' '; +echo ' CSRF protected test'; +echo ''; +echo ''; +echo '
'; +echo ' '; +echo ' '; +echo '

'; +echo ' '; +echo '
'; +echo ''; +echo ''; + +if ($_SERVER['REQUEST_METHOD'] === 'POST'){ + if(isset($_SESSION['csrf_token']) && isset($_POST['csrf_token'])){ + if ($_POST['csrf_token'] !== $_SESSION['csrf_token']){ + http_response_code(403); + die('CSRF token mismatch'); + } + else{ + http_response_code(200); + echo "form submitted !"; + } + } + else{ + http_response_code(403); + echo "CSRF token missing"; + } +} +?> diff --git a/tests/integration/test_mod_csrf/php/src/unprotected_form.php b/tests/integration/test_mod_csrf/php/src/unprotected_form.php new file mode 100644 index 000000000..f13b4408d --- /dev/null +++ b/tests/integration/test_mod_csrf/php/src/unprotected_form.php @@ -0,0 +1,23 @@ + + + + + + CSRF unprotected test + + +
+ +

+ +
+ + + diff --git a/tests/integration/wapiti/modules.json b/tests/integration/wapiti/modules.json index 064714694..ed9ec70b3 100644 --- a/tests/integration/wapiti/modules.json +++ b/tests/integration/wapiti/modules.json @@ -998,5 +998,52 @@ "erase_global_supplementary": false } ] + }, + "test_mod_csrf": { + "modules": "csrf", + "supplementary_argument": "", + "report_filter_tree": { + "vulnerabilities": { + "Cross Site Request Forgery": [ + { + "method": "", + "path": "", + "info": "", + "parameter": "", + "module": "", + "http_request": "", + "wstg": "" + } + ] + }, + "infos": { + "target": "", + "crawled_pages": [ + { + "request": { + "url": "", + "method": "", + "headers": [] + }, + "response": { + "status_code": 0, + "body": "", + "headers": [] + } + } + ] + } + }, + "targets": [ + { + "name": "http://csrf/protected_form.php" + }, + { + "name": "http://csrf/fake_protected_form.php" + }, + { + "name": "http://csrf/unprotected_form.php" + } + ] } } \ No newline at end of file