Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

Commit

Permalink
Grammar and text cleanup.
Browse files Browse the repository at this point in the history
Has anyone really been far even as decided to use even go want to do
look more like?
  • Loading branch information
Yvan Boily committed Sep 23, 2011
1 parent b514b2a commit 68371f6
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 47 deletions.
22 changes: 9 additions & 13 deletions README.md
@@ -1,24 +1,21 @@
# Garmr

Garmr is a checking that a site meets the basic requirements from a security point of view.
It checks what the correct HTTP calls are allowed and others are blocked. It is installable from PyPi.
Garmr is a tool to inspect the responses from websites for basic security requirements.

## Installation
Garmr includes a set of core test cases implemented in corechecks that are derived from
the Secure Coding Guidelines that can be found at [https://wiki.mozilla.org/WebAppSec/Secure_Coding_Guidelines]

This version of garmr :
## Installation

* does not support pip. grab the source from git
This version of Garmr :
* does not support pip. Grab the source from git
* requires Requests > 0.6.2-dev, which can be installed by following the instructions here:
** http://docs.python-requests.org/en/latest/user/install/#get-the-code



## Usage

usage: garmr.py [-h] [-u TARGETS] [-m MODULES] [-f TARGET_FILES] [-p] [-d]

Check urls for compliance with Secure Coding Guidelines

optional arguments:
-h, --help show this help message and exit
-u TARGETS, --url TARGETS
Expand All @@ -31,7 +28,6 @@ optional arguments:
-d, --dns Skip DNS resolution when registering a target.

## Tasks

* Implement a way to provide supply parameters and specify which http verb to use
* Implement sequences (i.e. a set of ActiveTests that once invoked, maintains a cookie jar)
* Implement a proper reporter; currently a range of data is accumulated, but never reported.
* Implement sequences (i.e. a series of ActiveTests that once invoked, maintains a cookie jar until the list of URLs is exhausted)
* Implement a proper detailed reporter; currently a range of data is accumulated, but never reported.
* Implement more checks
42 changes: 20 additions & 22 deletions corechecks.py
Expand Up @@ -3,8 +3,8 @@
from scanner import ActiveTest, PassiveTest, Scanner, get_url


class HttpOnlyPresent(PassiveTest):

class HttpOnlyAttributePresent(PassiveTest):
description = "Inspect the Set-Cookie: header and determine if the HttpOnly attribute is present."
def analyze(self, response):
cookieheader = "Set-Cookie"
has_cookie = cookieheader in response.headers
Expand All @@ -18,7 +18,7 @@ def analyze(self, response):
return result

class SecureAttributePresent(PassiveTest):

description = "Inspect the Set-Cookie: header and determine if the Secure attribute is present."
def analyze(self, response):
url = urlparse(response.url)
cookieheader = "Set-Cookie"
Expand All @@ -39,50 +39,48 @@ def analyze(self, response):
return result


class StsHeaderPresent(PassiveTest):

class StrictTransportSecurityPresent(PassiveTest):
secure_only = True

description = "Check if the Strict-Transport-Security header is present in TLS requests."
def analyze(self, response):
stsheader = "Strict-Transport-Security"
sts = stsheader in response.headers
if sts == False:
result = self.result("Fail", "STS header not found.", None)
result = self.result("Fail", "Strict-Transport-Security header not found.", None)
else:
result = self.result("Pass", "STS header present.", response.headers[stsheader])
result = self.result("Pass", "Strict-Transport-Security header present.", response.headers[stsheader])
return result

class XfoPresent(PassiveTest):

class XFrameOptionsPresent(PassiveTest):
description = "Check if X-Frame-Options header is present."

def analyze(self, response):
xfoheader = "x-frame-options"
xfoheader = "X-Frame-Options"
xfo = xfoheader in response.headers
if xfo == False:
result = self.result("Fail", "XFO header not found.", None)
result = self.result("Fail", "X-Frame-Options header not found.", None)
else:
result = self.result("Pass", "XFO header present.", response.headers[xfoheader])
result = self.result("Pass", "X-Frame-Options header present.", response.headers[xfoheader])
return result

class RobotsTest(ActiveTest):
run_passives = True
description = "Check for, and save the contents of robots.txt if it is present on the server."
description = "Check for the presence of a robots.txt file. If save_contents is true, the contents will be saved."
config = {"save_contents" : "False"}
def do_test(self, url):
u = urlparse(url)
roboturl="%s://%s/robots.txt" % (u.scheme, u.netloc)
response = requests.get(roboturl)
if response.status_code == 200:
result = self.result("Pass", "A robots.txt file is present on the server", response.content)
result = self.result("Pass", "A robots.txt file is present on the server",
response.content if self.config["save_contents"].lower() == "true" else None)
else:
result = self.result("Fail", "No robots.txt file was found.", None)
return (result, response);

class StsUpgradeCheck(ActiveTest):
insecure_only = True
run_passives = False
description = "Inspect the STS redirect process."
description = "Inspect the Strict-Transport-Security redirect process according to http://tools.ietf.org/html/draft-hodges-strict-transport-sec"

def do_test(self, url):
stsheader = "Strict-Transport-Security"
Expand All @@ -108,7 +106,7 @@ def do_test(self, url):
else:
message = "%s%s%s%s" % (
"The initial HTTP response included an STS header (RFC violation)." if invalid_header else "",
"" if is_redirect else "The initial HTTP response should be a 301 redirect (RFC violation).",
"" if is_redirect else "The initial HTTP response should be a 301 redirect (RFC violation see ).",
"" if correct_header else "The followup to the 301 redirect must include the STS header.",
"The 301 location must use the https scheme." if bad_redirect else ""
)
Expand All @@ -119,9 +117,9 @@ def do_test(self, url):
def configure(scanner):
if isinstance(scanner, Scanner) == False:
raise Exception("Cannot configure a non-scanner object!")
scanner.register_check(StsHeaderPresent())
scanner.register_check(XfoPresent())
scanner.register_check(StrictTransportSecurityPresent())
scanner.register_check(XFrameOptionsPresent())
scanner.register_check(RobotsTest())
scanner.register_check(StsUpgradeCheck())
scanner.register_check(HttpOnlyPresent())
scanner.register_check(HttpOnlyAttributePresent())
scanner.register_check(SecureAttributePresent())
16 changes: 9 additions & 7 deletions garmr.py
Expand Up @@ -6,18 +6,18 @@
import traceback

def main():
parser = argparse.ArgumentParser(description='Check urls for compliance with Secure Coding Guidelines')
parser.add_argument("-u", "--url", action="append", dest="targets", help="add a target to test")
parser.add_argument("-m", "--module", action="append", default = ["corechecks"], dest="modules", help="load a test suite")
parser.add_argument("-f", "--target-file", action="append", dest="target_files", help="File with urls to test")
parser = argparse.ArgumentParser("Runs a set of tests against the set of provided URLs")
parser.add_argument("-u", "--url", action="append", dest="targets", help="Add a target to test")
parser.add_argument("-f", "--target-file", action="append", dest="target_files", help="File with URLs to test")

parser.add_argument("-m", "--module", action="append", default = ["corechecks"], dest="modules", help="Load an extension module")
parser.add_argument("-p", "--force-passive", action="store_true", default=False, dest="force_passives", help ="Force passives to be run for each active test")
parser.add_argument("-d", "--dns", action="store_false", default=True, dest="resolve_target", help ="Skip DNS resolution when registering a target.")
parser.add_argument("-r", "--report", action="store", default="reporter.AntXmlReporter", dest="report",help="Load a reporter, format module.class, e.g. reporter.AntXmlReporter")
parser.add_argument("-d", "--dns", action="store_false", default=True, dest="resolve_target", help ="Skip DNS resolution when registering a target")
parser.add_argument("-r", "--report", action="store", default="reporter.AntXmlReporter", dest="report",help="Load a reporter e.g. -r reporter.AntXmlReporter")
parser.add_argument("-o", "--output", action="store", default="garmr-results.xml", dest="output", help="Default output is garmr-results.xml")
parser.add_argument("-c", "--check", action="append", dest="opts", help="Set a parameter for a check (check:opt=value)" )
parser.add_argument("-e", "--exclude", action="append", dest="exclusions", help="Prevent a check from being run/processed")
parser.add_argument("--save", action="store", dest="dump_path", help="Write out a configuration file based on parameters (won't run scan)")
#todo add option to influence DNS resolution before scanning.

args = parser.parse_args()
scanner = Scanner()
Expand All @@ -44,6 +44,8 @@ def main():
Scanner.logger.error("Unable to process the target list in: %s", targets)

# Configure modules.
# TODO: change the module loading to scan the list of classes in a module and automagically
# detect any tests defined.
if args.modules != None:
for module in args.modules:
try:
Expand Down
7 changes: 2 additions & 5 deletions reporter.py
@@ -1,10 +1,7 @@


class Reporter():

reporters = {}

# todo - implement me!
def start_report(self):
return None

Expand Down Expand Up @@ -39,9 +36,9 @@ def end_report(self):
return "This reporter is unimplemented!"

class DetailReporter(Reporter):
# TODO Implement me.
# TODO Implement detailed reporter
def end_report(self):
return "This reporter should emit an XML report that includes all of the the details for each test. including captured data"
return "This reporter should emit an XML report that includes all of the the details for each test, including captured data"

Reporter.reporters['detail'] = DetailReporter()

Expand Down

0 comments on commit 68371f6

Please sign in to comment.