1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 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
|