Initial import WSF XSS protection.
Added an utility class to get safe query and form parameters. Added a new WSF_XSS_REQUEST to use safe parameters. Added a filter WSF_XSS_FILTER using WSF_XSS_REQUEST. Added test cases Signed-off-by: jvelilla <javier.hector@gmail.com>
This commit is contained in:
36
library/server/wsf/router/filter/wsf_xss_filter.e
Normal file
36
library/server/wsf/router/filter/wsf_xss_filter.e
Normal file
@@ -0,0 +1,36 @@
|
||||
note
|
||||
description: "[
|
||||
{WSF_XSS_FILTER}.
|
||||
Simple anti cross-site scripting (XSS) filter.
|
||||
Remove all suspicious strings from request parameters (query strings and form) before returning them to the application
|
||||
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_XSS_FILTER
|
||||
|
||||
inherit
|
||||
|
||||
WSF_FILTER
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute the filter.
|
||||
do
|
||||
execute_next (create {WSF_XSS_REQUEST}.make_from_request (req), res)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
51
library/server/wsf/src/support/wsf_xss_protection_patterns.e
Normal file
51
library/server/wsf/src/support/wsf_xss_protection_patterns.e
Normal file
@@ -0,0 +1,51 @@
|
||||
note
|
||||
description: "[
|
||||
{WSF_XSS_PROTECTION_PATTERNS}
|
||||
Provide application security parterns to assist in Cross Site Scripting
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
EIS: "name=OWASP XSS", "src=https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet", "protocol=uri"
|
||||
EIS: "name=Regular expression protection", "src=https://docs.apigee.com/api-services/reference/regular-expression-protection", "protocol=uri"
|
||||
|
||||
expanded class
|
||||
WSF_XSS_PROTECTION_PATTERNS
|
||||
|
||||
|
||||
feature -- xss PATTERNS
|
||||
|
||||
XSS_regular_expression: REGULAR_EXPRESSION
|
||||
note
|
||||
EIS: "name= XSS", "src=https://community.apigee.com/questions/27198/xss-threat-protection-patterns.html#answer-27465", "protocol=uri"
|
||||
local
|
||||
p: STRING_32
|
||||
once
|
||||
p := "((\%%3C)|<)[^\n]+((\%%3E)|>)"
|
||||
Result := compiled_regexp (p, True)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
compiled_regexp (p: STRING; caseless: BOOLEAN): REGULAR_EXPRESSION
|
||||
require
|
||||
p /= Void
|
||||
do
|
||||
create Result
|
||||
Result.set_caseless (caseless)
|
||||
Result.compile (p)
|
||||
ensure
|
||||
Result.is_compiled
|
||||
end
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
68
library/server/wsf/src/support/wsf_xss_utilities.e
Normal file
68
library/server/wsf/src/support/wsf_xss_utilities.e
Normal file
@@ -0,0 +1,68 @@
|
||||
note
|
||||
description: "Return safe (XSS protection) data for WSF_REQUEST query and form paramters."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_XSS_UTILITIES
|
||||
|
||||
|
||||
-- TODO add header protection.
|
||||
|
||||
feature -- Query parameters
|
||||
|
||||
safe_query_parameter (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
-- Safe Query parameter for name `a_name'.
|
||||
local
|
||||
l_wsf_xss: WSF_XSS_PROTECTION_PATTERNS
|
||||
r: REGULAR_EXPRESSION
|
||||
do
|
||||
r := l_wsf_xss.XSS_regular_expression
|
||||
Result := a_req.query_parameter (a_name)
|
||||
if Result /= Void then
|
||||
if
|
||||
attached {WSF_STRING} Result as str and then
|
||||
r.is_compiled
|
||||
then
|
||||
r.match (str.value)
|
||||
if r.has_matched then
|
||||
create {WSF_STRING} Result.make (str.name, " ")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Form Parameters
|
||||
|
||||
safe_form_parameter (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
-- Safe Form parameter for name `a_name'.
|
||||
local
|
||||
l_wsf_xss: WSF_XSS_PROTECTION_PATTERNS
|
||||
r: REGULAR_EXPRESSION
|
||||
do
|
||||
r := l_wsf_xss.XSS_regular_expression
|
||||
Result := a_req.form_parameter (a_name)
|
||||
if Result /= Void then
|
||||
if
|
||||
attached {WSF_STRING} Result as str and then
|
||||
r.is_compiled
|
||||
then
|
||||
r.match (str.value)
|
||||
if r.has_matched then
|
||||
create {WSF_STRING} Result.make (str.name, " ")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
59
library/server/wsf/src/wsf_xss_request.e
Normal file
59
library/server/wsf/src/wsf_xss_request.e
Normal file
@@ -0,0 +1,59 @@
|
||||
note
|
||||
description: "[
|
||||
XSS request, redefine query_parameter and form_parameters filtering the data (using XSS protection)
|
||||
before return the value.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_XSS_REQUEST
|
||||
|
||||
inherit
|
||||
WSF_REQUEST
|
||||
redefine
|
||||
query_parameter,
|
||||
form_parameter
|
||||
end
|
||||
|
||||
WSF_REQUEST_EXPORTER
|
||||
|
||||
WSF_XSS_UTILITIES
|
||||
|
||||
create
|
||||
make_from_request
|
||||
|
||||
feature {NONE} -- Creation
|
||||
|
||||
make_from_request (req: WSF_REQUEST)
|
||||
do
|
||||
make_from_wgi (req.wgi_request)
|
||||
end
|
||||
|
||||
feature -- Query parameters
|
||||
|
||||
query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
-- Query parameter for name `a_name'.
|
||||
do
|
||||
Result := safe_query_parameter (Current, a_name)
|
||||
end
|
||||
|
||||
feature -- Form Parameters
|
||||
|
||||
form_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
do
|
||||
Result := safe_form_parameter (Current, a_name)
|
||||
end
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
251
library/server/wsf/tests/src/test_xss_patterns.e
Normal file
251
library/server/wsf/tests/src/test_xss_patterns.e
Normal file
@@ -0,0 +1,251 @@
|
||||
note
|
||||
description: "Summary description for {TEST_XSS_PATTERNS}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
EIS: "name=XSS Filter Evasion Cheat Sheet", "src=https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet", "protocol=uri"
|
||||
|
||||
class
|
||||
TEST_XSS_PATTERNS
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
|
||||
feature -- Tests
|
||||
|
||||
test_xss_locator
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:= "[
|
||||
';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//";
|
||||
alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//--
|
||||
></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("XSS locator", r.has_matched)
|
||||
end
|
||||
|
||||
test_xss_locator_short
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
'';!--"<XSS>=&{()}
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("XSS locator short", r.has_matched)
|
||||
end
|
||||
|
||||
test_no_filter_evasion
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
<SCRIPT SRC=http://xss.rocks/xss.js></SCRIPT>
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("No filter evasion", r.has_matched)
|
||||
end
|
||||
|
||||
test_filter_bypass_based_polyglot
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
'">><marquee><img src=x onerror=confirm(1)></marquee>"></plaintext\></|\><plaintext/onmouseover=prompt(1)>
|
||||
<script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>'-->"></script>
|
||||
<script>alert(document.cookie)</script>">
|
||||
<img/id="confirm(1)"/alt="/"src="/"onerror=eval(id)>'">
|
||||
<img src="http://www.shellypalmer.com/wp-content/images/2015/07/hacked-compressor.jpg">
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("Filter bypass based polyglot", r.has_matched)
|
||||
end
|
||||
|
||||
|
||||
test_image_xss_js_directive
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
<IMG SRC="javascript:alert('XSS');">
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("Image XSS using the JavaScript directive", r.has_matched)
|
||||
end
|
||||
|
||||
|
||||
test_no_quotes_no_semicolon
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
<IMG SRC=javascript:alert('XSS')>
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("No quotes and no semicolon", r.has_matched)
|
||||
end
|
||||
|
||||
|
||||
test_case_insensitive_xss_vector
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
<IMG SRC=JaVaScRiPt:alert('XSS')>
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("Case insensitive XSS attack vector", r.has_matched)
|
||||
end
|
||||
|
||||
|
||||
test_html_entities
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
<IMG SRC=javascript:alert("XSS")>
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("HTML entities", r.has_matched)
|
||||
end
|
||||
|
||||
test_grave_accent_obfuscation
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
<IMG SRC=`javascript:alert("RSnake says, 'XSS'")`>
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("Grave accent obfuscation", r.has_matched)
|
||||
end
|
||||
|
||||
|
||||
test_malformed_a_tags
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
-- Skip the HREF attribute and get to the meat of the XXS... Submitted by David Cross ~ Verified on Chrome
|
||||
s:="[
|
||||
<a onmouseover="alert(document.cookie)">xxs link</a>
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("Malformed A tags", r.has_matched)
|
||||
end
|
||||
|
||||
test_malformed_a_tags_2
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
-- Chrome loves to replace missing quotes for you... if you ever get stuck just leave them off and Chrome will put them
|
||||
-- in the right place and fix your missing quotes on a URL or script.
|
||||
s:="[
|
||||
<a onmouseover=alert(document.cookie)>xxs link</a>
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("Malformed A tags", r.has_matched)
|
||||
end
|
||||
|
||||
|
||||
test_malformed_img
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
<IMG """><SCRIPT>alert("XSS")</SCRIPT>">
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("Malformed IMG tags", r.has_matched)
|
||||
end
|
||||
|
||||
|
||||
test_from_char_code
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("fromCharCode", r.has_matched)
|
||||
end
|
||||
|
||||
|
||||
test_default_src_tag
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
<IMG SRC=# onmouseover="alert('xxs')">
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("Default SRC tag to get past filters that check SRC domain", r.has_matched)
|
||||
end
|
||||
|
||||
|
||||
test_default_src_tag_2
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
<IMG SRC= onmouseover="alert('xxs')">
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("Default SRC tag by leaving it empty", r.has_matched)
|
||||
end
|
||||
|
||||
test_default_src_tag_3
|
||||
local
|
||||
r: REGULAR_EXPRESSION
|
||||
s: STRING
|
||||
do
|
||||
s:="[
|
||||
<IMG onmouseover="alert('xxs')">
|
||||
]"
|
||||
r:= xss_pattern.XSS_regular_expression
|
||||
r.match (s)
|
||||
assert ("Default SRC tag by leaving it out entirely", r.has_matched)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
xss_pattern: WSF_XSS_PROTECTION_PATTERNS
|
||||
|
||||
end
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" name="wsf_tests" uuid="C4FF9CDA-B4E4-4841-97E0-7F799B85B657">
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-17-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-17-0 http://www.eiffel.com/developers/xml/configuration-1-17-0.xsd" name="wsf_tests" uuid="C4FF9CDA-B4E4-4841-97E0-7F799B85B657">
|
||||
<target name="server">
|
||||
<root class="TEST" feature="make"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/\.git$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
<option debug="false" warning="true">
|
||||
<assertions precondition="true" postcondition="true" check="true" loop="true" supplier_precondition="true"/>
|
||||
@@ -21,6 +21,7 @@
|
||||
</library>
|
||||
<library name="http" location="..\..\..\network\protocol\http\http.ecf" readonly="false"/>
|
||||
<library name="http_client" location="..\..\..\network\http_client\net_http_client.ecf" readonly="false"/>
|
||||
<library name="pcre" location="$ISE_LIBRARY\unstable\library\text\regexp\pcre\pcre.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
|
||||
<library name="wsf" location="..\wsf.ecf" readonly="false">
|
||||
<option>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-16-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-16-0 http://www.eiffel.com/developers/xml/configuration-1-16-0.xsd" name="wsf" uuid="A37CE5AA-4D2A-4441-BC6A-0A1D7EC49647" library_target="wsf">
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-17-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-17-0 http://www.eiffel.com/developers/xml/configuration-1-17-0.xsd" name="wsf" uuid="A37CE5AA-4D2A-4441-BC6A-0A1D7EC49647" library_target="wsf">
|
||||
<target name="wsf">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/\.git$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true">
|
||||
</option>
|
||||
@@ -18,6 +18,7 @@
|
||||
<library name="error" location="..\..\utility\general\error\error.ecf"/>
|
||||
<library name="ewsgi" location="..\ewsgi\ewsgi.ecf"/>
|
||||
<library name="http" location="..\..\network\protocol\http\http.ecf"/>
|
||||
<library name="pcre" location="$ISE_LIBRARY\unstable\library\text\regexp\pcre\pcre.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
|
||||
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri.ecf"/>
|
||||
<library name="uri_template" location="..\..\text\parser\uri_template\uri_template.ecf"/>
|
||||
|
||||
Reference in New Issue
Block a user