diff options
Diffstat (limited to 'scripts/http-cookie-flags.nse')
-rw-r--r-- | scripts/http-cookie-flags.nse | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/scripts/http-cookie-flags.nse b/scripts/http-cookie-flags.nse new file mode 100644 index 0000000..84872fd --- /dev/null +++ b/scripts/http-cookie-flags.nse @@ -0,0 +1,173 @@ +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + +description = [[ +Examines cookies set by HTTP services. Reports any session cookies set +without the httponly flag. Reports any session cookies set over SSL without +the secure flag. If http-enum.nse is also run, any interesting paths found +by it will be checked in addition to the root. +]] + +--- +-- @usage +-- nmap -p 443 --script http-cookie-flags <target> +-- +-- @output +-- 443/tcp open https +-- | http-cookie-flags: +-- | /: +-- | PHPSESSID: +-- | secure flag not set and HTTPS in use +-- | /admin/: +-- | session_id: +-- | secure flag not set and HTTPS in use +-- | httponly flag not set +-- | /mail/: +-- | ASPSESSIONIDASDF: +-- | httponly flag not set +-- | ASP.NET_SessionId: +-- |_ secure flag not set and HTTPS in use +-- +-- @args path Specific URL path to check for session cookie flags. Default: / and those found by http-enum. +-- @args cookie Specific cookie name to check flags on. Default: A variety of commonly used session cookie names and patterns. +-- +-- @xmloutput +-- <table key="/"> +-- <table key="PHPSESSID"> +-- <elem>secure flag not set and HTTPS in use</elem> +-- </table> +-- </table> +-- <table key="/admin/"> +-- <table key="session_id"> +-- <elem>secure flag not set and HTTPS in use</elem> +-- <elem>httponly flag not set</elem> +-- </table> +-- </table> +-- <table key="/mail/"> +-- <table key="ASPSESSIONIDASDF"> +-- <elem>httponly flag not set</elem> +-- </table> +-- <table key="ASP.NET_SessionId"> +-- <elem>secure flag not set and HTTPS in use</elem> +-- </table> +-- </table> +-- +-- @see http-enum.nse +-- @see http-security-headers.nse + +categories = { "default", "safe", "vuln" } +author = "Steve Benson" +license = "Same as Nmap--See https://nmap.org/book/man-legal.html" +dependencies = {"http-enum"} + +portrule = shortport.http + +-- a list of patterns indicating cookies which are likely session cookies +local session_cookie_patterns = { + '^PHPSESSID$', + '^CFID$', + '^CFTOKEN$', + '^VOXSQSESS$', + '^CAKEPHP$', + '^FedAuth$', + '^ASPXAUTH$', + '^session$', + '[Ss][Ee][Ss][Ss][Ii][Oo][Nn][^%a]*[Ii][Dd]' +} + +-- check cookies set on a particular URL path. returns a table with problem +-- cookie names mapped to a table listing each problem found. +local check_path = function(is_session_cookie, host, port, path) + stdnse.debug1("start check of %s", path) + local path_issues = stdnse.output_table() + local resp = http.get(host, port, path) + if not resp.status then + stdnse.debug1("Error retrieving %s: %s", path, resp["status-line"]) + return nil + end + + if not resp.cookies then + stdnse.debug2("No cookies on %s", path) + return nil + end + + for _,cookie in ipairs(resp.cookies) do + stdnse.debug2(' cookie: %s', cookie.name) + local issues = stdnse.output_table() + if is_session_cookie(cookie.name) then + stdnse.debug2(' IS a session cookie') + if port.service=='https' and not cookie.secure then + stdnse.debug2(' * no secure flag and https') + issues[#issues+1] = 'secure flag not set and HTTPS in use' + end + if not cookie.httponly then + stdnse.debug2(' * no httponly') + issues[#issues+1] = 'httponly flag not set' + end + end + + if #issues>0 then + path_issues[cookie.name] = issues + end + + end + + stdnse.debug1("end check of %s : %d issues found", path, #path_issues) + if #path_issues>0 then + return path_issues + else + return nil + end +end + +action = function(host, port) + local all_issues = stdnse.output_table() + local specified_path = stdnse.get_script_args(SCRIPT_NAME..".path") + local specified_cookie = stdnse.get_script_args(SCRIPT_NAME..".cookie") + + -- create a function, is_session_cookie, which accepts a cookie name and + -- returns true if it is likely a session cookie, based on script-args + local is_session_cookie + if specified_cookie == nil then + is_session_cookie = function(cookie_name) + for _, pattern in ipairs(session_cookie_patterns) do + if string.find(cookie_name, pattern) then + return true + end + end + return false + end + else + is_session_cookie = function(cookie_name) + return cookie_name==specified_cookie + end + end + + -- build a list of URL paths to check cookies for based on script-args and + -- http-enum results. + local paths_to_check = {} + if specified_path == nil then + stdnse.debug2('path script-arg is nil; checking / and anything from http-enum') + paths_to_check[#paths_to_check+1] = '/' + for _,path in ipairs( stdnse.registry_get({host.ip, 'www', port.number, 'all_pages'}) or {}) do + paths_to_check[#paths_to_check+1] = path + end + else + stdnse.verbose1('path script-arg is %s; checking only that path', specified_path) + paths_to_check[#paths_to_check+1] = specified_path + end + + -- check desired cookies on all desired paths + for _,path in ipairs(paths_to_check) do + all_issues[path] = check_path(is_session_cookie, host, port, path) + end + + if #all_issues>0 then + return all_issues + else + return nil + end + +end |