diff --git a/nselib/url.lua b/nselib/url.lua
index 93b1b634f..15ebf65c6 100644
--- a/nselib/url.lua
+++ b/nselib/url.lua
@@ -319,7 +319,8 @@ end
-- This function takes a of the form
-- "name1=value1&name2=value2"
-- and returns a table containing the name-value pairs, with the name as the key
--- and the value as its associated value.
+-- and the value as its associated value. Both the name and the value are
+-- subject to URL decoding.
-- @param query Query string.
-- @return A table of name-value pairs following the pattern
-- table["name"] = value.
@@ -333,9 +334,11 @@ function parse_query(query)
query = string.gsub(query, ">", ">")
local function ginsert(qstr)
- local first, last = string.find(qstr, "=")
- if first then
- parsed[string.sub(qstr, 0, first-1)] = string.sub(qstr, first+1)
+ local pos = qstr:find("=", 1, true)
+ if pos then
+ parsed[unescape(qstr:sub(1, pos - 1))] = unescape(qstr:sub(pos + 1))
+ else
+ parsed[unescape(qstr)] = ""
end
end
@@ -355,18 +358,19 @@ end
---
-- Builds a query string from a table.
--
--- This is the inverse of parse_query.
+-- This is the inverse of parse_query. Both the parameter name
+-- and value are subject to URL encoding.
-- @param query A dictionary table where table['name'] =
-- value.
-- @return A query string (like "name=value2&name=value2").
-----------------------------------------------------------------------------
function build_query(query)
- local qstr = ""
+ local qstr = {}
for i,v in pairs(query) do
- qstr = qstr .. i .. '=' .. v .. '&'
+ qstr[#qstr+1] = escape(i) .. '=' .. escape(v)
end
- return string.sub(qstr, 0, #qstr-1)
+ return table.concat(qstr, '&')
end
return _ENV;
diff --git a/scripts/http-form-fuzzer.nse b/scripts/http-form-fuzzer.nse
index 69da08a0d..40d78ca82 100644
--- a/scripts/http-form-fuzzer.nse
+++ b/scripts/http-form-fuzzer.nse
@@ -97,14 +97,6 @@ local function generate_safe_postdata(form)
return postdata
end
-local function generate_get_string(data)
- local get_str = {"?"}
- for name,value in pairs(data) do
- get_str[#get_str+1]=url.escape(name).."="..url.escape(value).."&"
- end
- return table.concat(get_str)
-end
-
-- generate a charset of characters with ascii codes from 33 to 126
-- you can use http://www.asciitable.com/ to see which characters those actually are
local charset = generate_charset(33,126)
@@ -156,7 +148,7 @@ local function fuzz_form(form, minlen, maxlen, host, port, path)
if form["method"]=="post" then
sending_function = function(data) return http.post(host, port, form_submission_path, nil, nil, data) end
else
- sending_function = function(data) return http.get(host, port, form_submission_path..generate_get_string(data), {no_cache=true, bypass_cache=true}) end
+ sending_function = function(data) return http.get(host, port, form_submission_path.."?"..url.build_query(data), {no_cache=true, bypass_cache=true}) end
end
for _,field in ipairs(form["fields"]) do
diff --git a/scripts/http-open-redirect.nse b/scripts/http-open-redirect.nse
index 2fe4792ce..4acbb73b7 100644
--- a/scripts/http-open-redirect.nse
+++ b/scripts/http-open-redirect.nse
@@ -43,6 +43,8 @@ categories = {"discovery", "intrusive"}
portrule = shortport.http
+local redirect_canary = "http://scanme.nmap.org/"
+
local function dbg(str,...)
stdnse.debug2(str, ...)
end
@@ -74,10 +76,9 @@ local function checkLocationEcho(query, destination)
local q = url.parse_query(query);
-- Check the values (and keys) and see if they are reflected in the location header
for k,v in pairs(q) do
- local s,f = string.find(destination, v)
- if s == 1 then
+ if destination:sub(1, #v) == v then
-- Build a new URL
- q[k] = "http%3A%2f%2fscanme.nmap.org%2f";
+ q[k] = redirect_canary;
return url.build_query(q)
end
end
@@ -123,7 +124,7 @@ action = function(host, port)
dbg("Checking potential open redirect: %s:%s%s", host,port,url);
local testResponse = http.get(host, port, url);
--dbgt(testResponse)
- if isRedirect(testResponse.status) and testResponse.header.location == "http://scanme.nmap.org/" then
+ if isRedirect(testResponse.status) and testResponse.header.location == redirect_canary then
table.insert(results, ("%s://%s:%s%s"):format(parsed.scheme, host, port,url))
end
end
diff --git a/scripts/http-rfi-spider.nse b/scripts/http-rfi-spider.nse
index 767695c12..5254c2e94 100644
--- a/scripts/http-rfi-spider.nse
+++ b/scripts/http-rfi-spider.nse
@@ -69,14 +69,6 @@ local function generate_safe_postdata(form)
return postdata
end
-local function generate_get_string(data)
- local get_str = {"?"}
- for name,value in pairs(data) do
- get_str[#get_str+1]=url.escape(name).."="..url.escape(value).."&"
- end
- return table.concat(get_str)
-end
-
-- checks each field of a form to see if it's vulnerable to rfi
local function check_form(form, host, port, path)
local vulnerable_fields = {}
@@ -96,7 +88,7 @@ local function check_form(form, host, port, path)
if form["method"]=="post" then
sending_function = function(data) return http.post(host, port, form_submission_path, nil, nil, data) end
else
- sending_function = function(data) return http.get(host, port, form_submission_path..generate_get_string(data), nil) end
+ sending_function = function(data) return http.get(host, port, form_submission_path.."?"..url.build_query(data), nil) end
end
for _,field in ipairs(form["fields"]) do
@@ -208,7 +200,7 @@ function action(host, port)
end --for
end --if
- -- now try inclusion by parameters
+ -- now try inclusion by query parameters
local injectable = {}
-- search for injectable links (as in sql-injection.nse)
if r.response.status and r.response.body then
diff --git a/scripts/http-sql-injection.nse b/scripts/http-sql-injection.nse
index 41c4cfa18..dfd5275f1 100644
--- a/scripts/http-sql-injection.nse
+++ b/scripts/http-sql-injection.nse
@@ -102,7 +102,7 @@ local function build_injection_vector(urls)
for k, v in pairs(qtab) do
old_qtab = qtab[k];
- qtab[k] = qtab[k] .. "'%20OR%20sqlspider"
+ qtab[k] = qtab[k] .. "' OR sqlspider"
utab.query = url.build_query(qtab)
urlstr = url.build(utab)
diff --git a/scripts/http-unsafe-output-escaping.nse b/scripts/http-unsafe-output-escaping.nse
index c974d4f44..cdb373fcd 100644
--- a/scripts/http-unsafe-output-escaping.nse
+++ b/scripts/http-unsafe-output-escaping.nse
@@ -78,7 +78,7 @@ local function getReflected(parsed, r)
end
local function addPayload(v)
- return v.."ghz%3Ehzx%22zxc%27xcv"
+ return v.."ghz>hzx\"zxc'xcv"
end
local function createMinedLinks(reflected_values, all_values)