Simplified imports and added constants
Issues, Constants, and Results are now imported in the __init__.py of the module Change-Id: I805c9df4f8b838d63e2a7d04f5998718a7bf4ecb
This commit is contained in:
parent
08a84a78dd
commit
445e12362e
|
@ -0,0 +1,16 @@
|
|||
# Copyright 2016 Rackspace
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from syntribos.issue import Issue # flake8: noqa
|
||||
from syntribos.constants import *
|
||||
from syntribos.result import IssueTestResult # flake8: noqa
|
|
@ -0,0 +1,19 @@
|
|||
# Copyright 2016 Rackspace
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
LOW = 1
|
||||
MEDIUM = 2
|
||||
HIGH = 3
|
||||
|
||||
RANKING = ['Undefined', 'Low', 'Medium', 'High']
|
|
@ -13,6 +13,8 @@
|
|||
# limitations under the License.
|
||||
import json
|
||||
|
||||
import syntribos
|
||||
|
||||
|
||||
class JSONFormatter(object):
|
||||
|
||||
|
@ -48,11 +50,12 @@ class JSONFormatter(object):
|
|||
defect_type = issue.defect_type
|
||||
|
||||
if defect_type not in issues_by_url:
|
||||
sev_rating = syntribos.RANKING[issue.severity]
|
||||
issues_by_url[defect_type] = {
|
||||
'description': issue.text,
|
||||
'severity': issue.severity
|
||||
'severity': sev_rating
|
||||
}
|
||||
machine_output['stats'][issue.severity] += 1
|
||||
machine_output['stats'][sev_rating] += 1
|
||||
|
||||
issues_by_defect = issues_by_url[defect_type]
|
||||
if issue.impacted_parameter:
|
||||
|
@ -62,6 +65,7 @@ class JSONFormatter(object):
|
|||
name = issue.impacted_parameter.name
|
||||
content_type = issue.content_type
|
||||
payload_string = issue.impacted_parameter.trunc_fuzz_string
|
||||
conf_rating = syntribos.RANKING[issue.confidence]
|
||||
param = {
|
||||
'method': method,
|
||||
'location': loc,
|
||||
|
@ -73,7 +77,7 @@ class JSONFormatter(object):
|
|||
payload_obj = {
|
||||
'strings': [payload_string],
|
||||
'param': param,
|
||||
'confidence': issue.confidence
|
||||
'confidence': conf_rating
|
||||
}
|
||||
if 'payloads' not in issues_by_defect:
|
||||
issues_by_defect['payloads'] = [payload_obj]
|
||||
|
@ -97,7 +101,7 @@ class JSONFormatter(object):
|
|||
issues_by_defect['payloads'].append(payload_obj)
|
||||
|
||||
else:
|
||||
issues_by_defect['confidence'] = issue.confidence
|
||||
issues_by_defect['confidence'] = conf_rating
|
||||
|
||||
output = json.dumps(machine_output, sort_keys=True,
|
||||
indent=2, separators=(',', ': '))
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
# limitations under the License.
|
||||
import os
|
||||
|
||||
import syntribos
|
||||
from syntribos.clients.http import client
|
||||
from syntribos.issue import Issue
|
||||
import syntribos.tests.auth.datagen
|
||||
from syntribos.tests import base
|
||||
|
||||
|
@ -67,10 +67,11 @@ class BaseAuthTestCase(base.BaseTestCase):
|
|||
" therefore it indicates that authentication with"
|
||||
" another user's token was successful.")
|
||||
self.register_issue(
|
||||
Issue(test="try_alt_user_token",
|
||||
severity="High",
|
||||
text=text,
|
||||
assertions=[(self.assertTrue, self.resp.status_code == 404)])
|
||||
syntribos.Issue(
|
||||
test="try_alt_user_token",
|
||||
severity=syntribos.HIGH,
|
||||
text=text,
|
||||
assertions=[(self.assertTrue, self.resp.status_code == 404)])
|
||||
)
|
||||
self.test_issues()
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ import os
|
|||
|
||||
from six.moves.urllib.parse import urlparse
|
||||
|
||||
import syntribos
|
||||
from syntribos.clients.http import client
|
||||
from syntribos.issue import Issue
|
||||
from syntribos.tests import base
|
||||
import syntribos.tests.fuzz.config
|
||||
import syntribos.tests.fuzz.datagen
|
||||
|
@ -137,29 +137,28 @@ class BaseFuzzTestCase(base.BaseTestCase):
|
|||
|
||||
if self.resp.status_code >= 500:
|
||||
self.register_issue(
|
||||
Issue(test="500_errors",
|
||||
severity="Low",
|
||||
confidence="High",
|
||||
text=("This request returns an error with status code "
|
||||
"{0}, which might indicate some server-side fault "
|
||||
"that could lead to further vulnerabilities"
|
||||
).format(self.resp.status_code)
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="500_errors",
|
||||
severity=syntribos.LOW,
|
||||
confidence=syntribos.HIGH,
|
||||
text=("This request returns an error with status code "
|
||||
"{0}, which might indicate some server-side fault "
|
||||
"that could lead to further vulnerabilities"
|
||||
).format(self.resp.status_code))
|
||||
)
|
||||
|
||||
if (not self.validate_length() and
|
||||
self.resp.status_code == self.init_response.status_code):
|
||||
self.register_issue(
|
||||
Issue(test="length_diff",
|
||||
severity="Low",
|
||||
confidence="Low",
|
||||
text=("The difference in length between the response to "
|
||||
"the baseline request and the request returned "
|
||||
"when sending an attack string exceeds {0} "
|
||||
"percent, which could indicate a vulnerability "
|
||||
"to injection attacks")
|
||||
.format(self.config.percent)
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="length_diff",
|
||||
severity=syntribos.LOW,
|
||||
confidence=syntribos.LOW,
|
||||
text=("The difference in length between the response to "
|
||||
"the baseline request and the request returned "
|
||||
"when sending an attack string exceeds {0} "
|
||||
"percent, which could indicate a vulnerability "
|
||||
"to injection attacks").format(self.config.percent))
|
||||
)
|
||||
|
||||
def test_case(self):
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from syntribos.issue import Issue
|
||||
import syntribos
|
||||
from syntribos.tests.fuzz import base_fuzz
|
||||
|
||||
|
||||
|
@ -40,28 +40,28 @@ class BufferOverflowBody(base_fuzz.BaseFuzzTestCase):
|
|||
failed_strings = self.data_driven_failure_cases()
|
||||
if failed_strings:
|
||||
self.register_issue(
|
||||
Issue(test="bof_strings",
|
||||
severity="Medium",
|
||||
confidence="Low",
|
||||
text=("The string(s): \'{0}\', known to be commonly "
|
||||
"returned after a successful buffer overflow "
|
||||
"attack, have been found in the response. This "
|
||||
"could indicate a vulnerability to buffer "
|
||||
"overflow attacks.").format(failed_strings)
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="bof_strings",
|
||||
severity=syntribos.MEDIUM,
|
||||
confidence=syntribos.LOW,
|
||||
text=("The string(s): \'{0}\', known to be commonly "
|
||||
"returned after a successful buffer overflow "
|
||||
"attack, have been found in the response. This "
|
||||
"could indicate a vulnerability to buffer "
|
||||
"overflow attacks.").format(failed_strings))
|
||||
)
|
||||
time_diff = self.config.time_difference_percent / 100
|
||||
if (self.resp.elapsed.total_seconds() >
|
||||
time_diff * self.init_response.elapsed.total_seconds()):
|
||||
self.register_issue(
|
||||
Issue(test="bof_timing",
|
||||
severity="Medium",
|
||||
confidence="Medium",
|
||||
text=("The time it took to resolve a request with a "
|
||||
"long string was too long compared to the "
|
||||
"baseline request. This could indicate a "
|
||||
"vulnerability to buffer overflow attacks")
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="bof_timing",
|
||||
severity=syntribos.MEDIUM,
|
||||
confidence=syntribos.MEDIUM,
|
||||
text=("The time it took to resolve a request with a "
|
||||
"long string was too long compared to the "
|
||||
"baseline request. This could indicate a "
|
||||
"vulnerability to buffer overflow attacks"))
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from syntribos.issue import Issue
|
||||
import syntribos
|
||||
from syntribos.tests.fuzz import base_fuzz
|
||||
|
||||
|
||||
|
@ -31,29 +31,29 @@ class CommandInjectionBody(base_fuzz.BaseFuzzTestCase):
|
|||
failed_strings = self.data_driven_failure_cases()
|
||||
if failed_strings:
|
||||
self.register_issue(
|
||||
Issue(test="command_injection",
|
||||
severity="High",
|
||||
confidence="Medium",
|
||||
text=("A string known to be commonly returned after a "
|
||||
"successful command injection attack was "
|
||||
"included in the response. This could indicate "
|
||||
"a vulnerability to command injection "
|
||||
"attacks.").format(failed_strings)
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="command_injection",
|
||||
severity=syntribos.HIGH,
|
||||
confidence=syntribos.MEDIUM,
|
||||
text=("A string known to be commonly returned after a "
|
||||
"successful command injection attack was "
|
||||
"included in the response. This could indicate "
|
||||
"a vulnerability to command injection "
|
||||
"attacks.").format(failed_strings))
|
||||
)
|
||||
time_diff = self.config.time_difference_percent / 100
|
||||
if (self.resp.elapsed.total_seconds() >
|
||||
time_diff * self.init_response.elapsed.total_seconds()):
|
||||
self.register_issue(
|
||||
Issue(test="command_injection",
|
||||
severity="High",
|
||||
confidence="Medium",
|
||||
text=("The time elapsed between the sending of "
|
||||
"the request and the arrival of the res"
|
||||
"ponse exceeds the expected amount of time, "
|
||||
"suggesting a vulnerability to command "
|
||||
"injection attacks.").format(self.resp.elapsed)
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="command_injection",
|
||||
severity=syntribos.HIGH,
|
||||
confidence=syntribos.MEDIUM,
|
||||
text=("The time elapsed between the sending of "
|
||||
"the request and the arrival of the res"
|
||||
"ponse exceeds the expected amount of time, "
|
||||
"suggesting a vulnerability to command "
|
||||
"injection attacks.").format(self.resp.elapsed))
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from syntribos.issue import Issue
|
||||
import syntribos
|
||||
from syntribos.tests.fuzz import base_fuzz
|
||||
|
||||
|
||||
|
@ -25,14 +25,14 @@ class IntOverflowBody(base_fuzz.BaseFuzzTestCase):
|
|||
if (self.resp.elapsed.total_seconds() >
|
||||
time_diff * self.init_response.elapsed.total_seconds()):
|
||||
self.register_issue(
|
||||
Issue(test="int_timing",
|
||||
severity="Medium",
|
||||
confidence="Medium",
|
||||
text=("The time it took to resolve a request with an "
|
||||
"invalid integer was too long compared to the "
|
||||
"baseline request. This could indicate a "
|
||||
"vulnerability to buffer overflow attacks")
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="int_timing",
|
||||
severity=syntribos.MEDIUM,
|
||||
confidence=syntribos.MEDIUM,
|
||||
text=("The time it took to resolve a request with an "
|
||||
"invalid integer was too long compared to the "
|
||||
"baseline request. This could indicate a "
|
||||
"vulnerability to buffer overflow attacks"))
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from syntribos.issue import Issue
|
||||
import syntribos
|
||||
from syntribos.tests.fuzz import base_fuzz
|
||||
|
||||
|
||||
|
@ -44,27 +44,27 @@ class SQLInjectionBody(base_fuzz.BaseFuzzTestCase):
|
|||
failed_strings = self.data_driven_failure_cases()
|
||||
if failed_strings:
|
||||
self.register_issue(
|
||||
Issue(test="sql_strings",
|
||||
severity="Medium",
|
||||
confidence="Low",
|
||||
text=("The string(s): \'{0}\', known to be commonly "
|
||||
"returned after a successful SQL injection attack"
|
||||
", have been found in the response. This could "
|
||||
"indicate a vulnerability to SQL injection "
|
||||
"attacks."
|
||||
).format(failed_strings)
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="sql_strings",
|
||||
severity=syntribos.MEDIUM,
|
||||
confidence=syntribos.LOW,
|
||||
text=("The string(s): \'{0}\', known to be commonly "
|
||||
"returned after a successful SQL injection attack"
|
||||
", have been found in the response. This could "
|
||||
"indicate a vulnerability to SQL injection "
|
||||
"attacks."
|
||||
).format(failed_strings))
|
||||
)
|
||||
|
||||
time_diff = self.config.time_difference_percent / 100
|
||||
if (self.resp.elapsed.total_seconds() >
|
||||
time_diff * self.init_response.elapsed.total_seconds()):
|
||||
self.register_issue(
|
||||
Issue(test="sql_timing",
|
||||
severity="Medium",
|
||||
confidence="Medium",
|
||||
text=(
|
||||
"A response to one of our payload requests has "
|
||||
syntribos.Issue(
|
||||
test="sql_timing",
|
||||
severity=syntribos.MEDIUM,
|
||||
confidence=syntribos.MEDIUM,
|
||||
text=("A response to one of our payload requests has "
|
||||
"taken too long compared to the baseline request. "
|
||||
"This could indicate a vulnerability to time-based "
|
||||
"SQL injection attacks"))
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
# limitations under the License.
|
||||
import os
|
||||
|
||||
from syntribos.issue import Issue
|
||||
import syntribos
|
||||
from syntribos.tests.fuzz import base_fuzz
|
||||
import syntribos.tests.fuzz.datagen
|
||||
|
||||
|
@ -84,15 +84,15 @@ class XMLExternalEntityBody(base_fuzz.BaseFuzzTestCase):
|
|||
failed_strings = self.data_driven_failure_cases()
|
||||
if failed_strings:
|
||||
self.register_issue(
|
||||
Issue(test="xml_strings",
|
||||
severity="Medium",
|
||||
confidence="Low",
|
||||
text=("The string(s): \'{0}\', known to be commonly "
|
||||
"returned after a successful XML external entity "
|
||||
"attack, have been found in the response. This "
|
||||
"could indicate a vulnerability to XML external "
|
||||
"entity attacks.").format(failed_strings)
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="xml_strings",
|
||||
severity=syntribos.MEDIUM,
|
||||
confidence=syntribos.LOW,
|
||||
text=("The string(s): \'{0}\', known to be commonly "
|
||||
"returned after a successful XML external entity "
|
||||
"attack, have been found in the response. This "
|
||||
"could indicate a vulnerability to XML external "
|
||||
"entity attacks.").format(failed_strings))
|
||||
)
|
||||
|
||||
time_diff = self.config.time_difference_percent / 100
|
||||
|
@ -100,11 +100,12 @@ class XMLExternalEntityBody(base_fuzz.BaseFuzzTestCase):
|
|||
if (self.resp.elapsed.total_seconds() >
|
||||
time_diff * self.init_response.elapsed.total_seconds()):
|
||||
self.register_issue(
|
||||
Issue(test="xml_timing",
|
||||
severity="Medium",
|
||||
confidence="Medium",
|
||||
text=("The time it took to resolve a request with an "
|
||||
"invalid URL in the DTD takes too long compared "
|
||||
"to the baseline request. This could reflect a "
|
||||
"vulnerability to an XML external entity attack."))
|
||||
syntribos.Issue(
|
||||
test="xml_timing",
|
||||
severity=syntribos.MEDIUM,
|
||||
confidence=syntribos.MEDIUM,
|
||||
text=("The time it took to resolve a request with an "
|
||||
"invalid URL in the DTD takes too long compared "
|
||||
"to the baseline request. This could reflect a "
|
||||
"vulnerability to an XML external entity attack."))
|
||||
)
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from syntribos.issue import Issue
|
||||
import syntribos
|
||||
from syntribos.tests.fuzz import base_fuzz
|
||||
|
||||
|
||||
|
@ -27,20 +27,20 @@ class XSSBody(base_fuzz.BaseFuzzTestCase):
|
|||
if 'content-type' in self.init_request.headers:
|
||||
content_type = self.init_request.headers['content-type']
|
||||
if 'html' in content_type:
|
||||
sev = "Medium"
|
||||
sev = syntribos.MEDIUM
|
||||
else:
|
||||
sev = "Low"
|
||||
sev = syntribos.LOW
|
||||
else:
|
||||
sev = "Low"
|
||||
sev = syntribos.LOW
|
||||
if failed_strings:
|
||||
self.register_issue(
|
||||
Issue(test="xss_strings",
|
||||
severity=sev,
|
||||
confidence="Low",
|
||||
text=("The string(s): \'{0}\', known to be commonly "
|
||||
"returned after a successful XSS "
|
||||
"attack, have been found in the response. This "
|
||||
"could indicate a vulnerability to XSS "
|
||||
"attacks.").format(failed_strings)
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="xss_strings",
|
||||
severity=sev,
|
||||
confidence=syntribos.LOW,
|
||||
text=("The string(s): \'{0}\', known to be commonly "
|
||||
"returned after a successful XSS "
|
||||
"attack, have been found in the response. This "
|
||||
"could indicate a vulnerability to XSS "
|
||||
"attacks.").format(failed_strings))
|
||||
)
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
# limitations under the License.
|
||||
import os
|
||||
|
||||
import syntribos
|
||||
from syntribos.clients.http import client
|
||||
from syntribos.clients.http import parser
|
||||
from syntribos.issue import Issue
|
||||
from syntribos.tests import base
|
||||
|
||||
|
||||
|
@ -43,40 +43,37 @@ class CorsHeader(base.BaseTestCase):
|
|||
if 'Access-Control-Allow-Origin' in self.resp.headers:
|
||||
if self.resp.headers['Access-Control-Allow-Origin'] == "*":
|
||||
self.register_issue(
|
||||
Issue(test="CORS_HEADER",
|
||||
severity="Medium",
|
||||
confidence="High",
|
||||
text=("CORS header `Access-Control-Allow-Origin` set"
|
||||
" to a wild character, this header should"
|
||||
" always be set to a white listed set of URIs"
|
||||
)
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="CORS_HEADER",
|
||||
severity=syntribos.MEDIUM,
|
||||
confidence=syntribos.HIGH,
|
||||
text=("CORS header `Access-Control-Allow-Origin` set"
|
||||
" to a wild character, this header should"
|
||||
" always be set to a white listed set of URIs"))
|
||||
)
|
||||
|
||||
if 'Access-Control-Allow-Methods' in self.resp.headers:
|
||||
if self.resp.headers['Access-Control-Allow-Methods'] == "*":
|
||||
self.register_issue(
|
||||
Issue(test="CORS_HEADER",
|
||||
severity="Low",
|
||||
confidence="High",
|
||||
text=("CORS header `Access-Control-Allow-Methods`"
|
||||
" set to a wild character,it is a good"
|
||||
" practice to give a white list of allowed"
|
||||
" methods."
|
||||
)
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="CORS_HEADER",
|
||||
severity=syntribos.LOW,
|
||||
confidence=syntribos.HIGH,
|
||||
text=("CORS header `Access-Control-Allow-Methods`"
|
||||
" set to a wild character,it is a good"
|
||||
" practice to give a white list of allowed"
|
||||
" methods."))
|
||||
)
|
||||
|
||||
if 'Access-Control-Allow-Headers' in self.resp.headers:
|
||||
if self.resp.headers['Access-Control-Allow-Headers'] == "*":
|
||||
self.register_issue(
|
||||
Issue(test="CORS_HEADER",
|
||||
severity="Low",
|
||||
confidence="High",
|
||||
text=("CORS header `Access-Control-Allow-Headers`"
|
||||
" set to a wild character,it is a good"
|
||||
" practice to give a white list of allowed"
|
||||
" headers"
|
||||
)
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="CORS_HEADER",
|
||||
severity=syntribos.LOW,
|
||||
confidence=syntribos.HIGH,
|
||||
text=("CORS header `Access-Control-Allow-Headers`"
|
||||
" set to a wild character,it is a good"
|
||||
" practice to give a white list of allowed"
|
||||
" headers"))
|
||||
)
|
||||
|
|
|
@ -16,9 +16,9 @@ import re
|
|||
|
||||
from six.moves.urllib.parse import urlparse
|
||||
|
||||
import syntribos
|
||||
from syntribos.clients.http import client
|
||||
from syntribos.clients.http import parser
|
||||
from syntribos.issue import Issue
|
||||
from syntribos.tests import base
|
||||
|
||||
|
||||
|
@ -47,11 +47,10 @@ class SSLTestCase(base.BaseTestCase):
|
|||
|
||||
if re.search(regex, response_text):
|
||||
self.register_issue(
|
||||
Issue(test="SSL_ERROR",
|
||||
severity="Medium",
|
||||
confidence="High",
|
||||
text=("Make sure that all the returned endpoint URIs"
|
||||
" use 'https://' and not 'http://'"
|
||||
)
|
||||
)
|
||||
syntribos.Issue(
|
||||
test="SSL_ERROR",
|
||||
severity=syntribos.MEDIUM,
|
||||
confidence=syntribos.HIGH,
|
||||
text=("Make sure that all the returned endpoint URIs"
|
||||
" use 'https://' and not 'http://'"))
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue