Merge branch 'master' of https://github.com/radicallyopensecurity/pentext into development

# Conflicts:
#	.gitignore
#	xml/dtd/invoice.xsd
#	xml/source/quickscope.xml
#	xml/xslt/generate_invoice.xsl
This commit is contained in:
skyanth
2016-10-04 17:02:36 +02:00
59 changed files with 3467 additions and 628 deletions

7
.gitignore vendored
View File

@@ -1,4 +1,9 @@
xml/PenText.xpr
# (Emacs) (temporary) files
.#*
\#*#
.projectile
# Compiled Python stuff
*.pyc
.DS_Store

View File

@@ -1,2 +1,49 @@
# pentext
PenText system
# Pentext
The PenText XML documentation project is a collection of XML templates, XML schemas and XSLT code, which combined provide an easy way to generate IT security documents including test reports (for penetration tests, load tests, code audits, etc), offers (to companies requesting these tests) and invoices.
### How it Works
The OWASP PenText project is based on XML. A PenText Report, Quote, Invoice or Generic Document is in fact a (modular) XML document, conforming to an XML Schema. The XML Schema ensures that the documents are structured correctly, so that they can then be transformed into other formats using XSLT and the SAXON XSLT processor. Currently there is only one target format: PDF. To produce the PDF document, the report, offer, invoice or generic document XML is first transformed into XSL-FO (XSL Formatting Objects), which is then converted to PDF using Apache FOP.
### The Structure
The directories are used as follows:
- chatops: contains bash and Python scripts that can be used with Hubot (chatOps), handy for automation while getting started or for checking document validity or spellchecking.
- xml:
- contains the PenText XML system and templates in directories *dtd*, *source* and *xslt*
- your report or quote will go into *source*
- contains a *graphics* map for your company logo
- the *findings* and *non-findings* directories are for findings and non-findings
## Getting Started
What do you need ?
1. Clone this repository
2. Install the toolchain
3. Edit the content
Listo! That's all you need. Now you can build PDF reports using the content.
### Toolchain
To convert the XML content into PDF files the tools the *Apache FOP* library and the *Java* library *Saxon* will be used
It is easiest to install the toolchain using Ansible: check out the role PeterMosmans.docbuilder (https://galaxy.ansible.com/PeterMosmans/docbuilder/)
To edit (and view) the content you'll need a XML editor - which could be any text editor like *JEdit*, to a full IDE- for editing of course ;). Preferably something that can check XML file validity. To view the resulting PDF files a PDF viewer is necessary.
### Building PDF's
Manually compiling a quotation, report or other document can be done using `java -jar path-to-Saxon-jar -s:name-of-xml-file -xsl:name-of-xsl-file-in-xsl-directory -o:name-for-pdf-output`
But why do it manually when the [ChatOps](https://github.com/radicallyopensecurity/pentext/tree/master/chatops) directory contains so much nice scripts to do just that ?
See for more detailed information the [tools manual](https://github.com/radicallyopensecurity/pentext/blob/master/xml/doc/Tools%20manual.md)
## Adding and Modifying Content
### Guidelines
- There is a guide for [report writing](xml/doc/report/Report%20Writing%20-%20Procedure.md)
- There is also a guide for [quotation writing](xml/doc/offerte/Offerte%20Writing%20Procedure.md)
### Example documents
Besides the reports and quotations, generic documents can also be created.
Those can be found [here](xml/doc/examples)

123
chatops/README.md Normal file
View File

@@ -0,0 +1,123 @@
# Introduction
This directory contains the ChatOps scripts, based on Hubot. It uses RocketChat and gitlab as the underlying framework (but can be modified to fit any other framework).
This document describes the goal of the scripts, as well as installation instructions and their basic usage.
## Workflow
Scripts are ordered by workflow, not alphabetically.
The workflow consists of
1. setting up a repository for a quote with the PenText framework
2. (optional: converting quickscope input to a quote)
3. building a PDF quote
4. setting up a repository for a pentest with the PenText framework, based on a quote
5. (optional: converting gitlab issues to XML findings and non-findings)
6. (optional: validating a PenText report)
7. building a PDF report
8. building a PDF invoice
## Naming
The scripts either take the **project name** as input, or the **repository name** (and optional namespace and branch). The project name is leading, repository names are derived from the project names: the quotation repository has `off-` as prefix, and the pentest repository will have `pen-` as prefix.
As a rule of thumb, the handlers that are prefixed with `start` (startquote, startpentest) will take the **project name** as input. All other handlers take the **repository name** as input.
Example: when the project's name is ros, then the corresponding quote repository and RocketChat channel's name will be `off-ros`.
If this quote will result in a pentest project, then the corresponding repository and RocketChat channel will be named `pen-ros`.
Note that git repository names are _lowercase_.
# Scripts
The scripts use multiple environment variables, that can be set by the user under which rosbot is running. These are
+ `GITLABCLI` :: the location of the python-gitlab command line interface (defaults to `gitlab`)
+ `GITSERVER` :: the name of the gitlab server (defaults to `gitlab.local`)
+ `GITWEB` :: the URL of the gitlab webinterface (defaults to `https://$GITSERVER`)
+ `NAMESPACE` :: the namespace of the user which is used to set up gitlab repositories (defaults to `ros`)
+ `PENTEXTREPO` :: the location of the PenText repository (defaults to `https://github.com/radicallyopensecurity/pentext`)
## Prerequisites
The Bash scripts use the python-gitlab command-line interface to talk to the gitlab instance. This interface can be installed using `sudo pip install git+https://github.com/gpocentek/python-gitlab`. Obviously, Python needs to be installed as well.
This command line interface expects a configuration file `.python-gitlab.cfg` for the user under which rosbot is running, which it uses to connect to gitlab. Make sure it contains the correct details so that you can connect to gitlab.
If you want to convert and build documents, the pentext toolchain is necessary. Use the ansible playbook https://galaxy.ansible.com/PeterMosmans/docbuilder/ or install the tools (Java, Saxon and Apache FOP) by hand, see https://github.com/radicallyopensecurity/pentext/blob/master/xml/doc/Tools%20manual.md for more information.
## Test the configuration
Test out whether the configuration is successful by manually executing the Bash script [bash/test_pentext](bash/test_pentext) - this should return an OK.
## CoffeeScript
### rosbot.coffee
[scripts/rosbot.coffee](scripts/rosbot.coffee) - contains the various keywords and redirects to the proper handlers. All RocketChat-specific actions (e.g. the creation of rooms) is being handled by this script.
The scripts contains an array of users that will be added to the newly created rooms by default.
Example:
`admins = ['admin']`
## Bash
### startquote
Start the quotation process by setting up a repository with the PenText framework, and creating a RocketChat channel.
Handled by [bash/handler_quote](bash/handler_quote)
Sets up a pentest RocketChat channel named `off-PROJECT_NAME`, a gitlab repo named `off-PROJECT_NAME`, and installs the latest version of the Pentext framework. Note that this uses the `PROJECT_NAME` as input, so it will automatically append the `off-` prefix.
Usage: `startquote PROJECT_NAME`
### quickscope
Converts a quickscope (`source/quickscope.xml`) into a full-blown XML quote.
Handled by [bash/handler_quickscope](bash/handler_quickscope)
Usage: `quickscope REPO_NAME [NAMESPACE [BRANCH]]]`
### build
Builds PDF files from XML quotes and reports.
Handled by [bash/handler_build](bash/handler_build)
Usage: `build quote|report REPO_NAME [NAMESPACE [[BRANCH]] [-PARAMETERS]`
### startpentest
Start the pentesting process by setting up a repository with the PenText framework, adding standard gitlab labels and issues, and creating a RocketChat channel.
Handled by [bash/handler_pentest](bash/handler_pentest)
Sets up a pentest RocketChat channel named `pen-PROJECT_NAME`, and a gitlab repo named `pen-PROJECT_NAME`. Will use the quotation found in the corresponding `off-PROJECT_NAME` as base. Note that the prefix `pen-` is set by the `rosbot.coffee` script.
Usage: `startpentest PROJECT_NAME`
### convert
Converts gitlab issues labeled with `finding` and `non-finding` into XML files, and adds those to the repository
Handled by [bash/handler_convert](bash/hander_convert)
Converts gitlab items to XML findings
Usage: `convert REPO_NAME`
### validate
Validates quotes and reports.
Handled by [bash/handler_validate](bash/handler_validate)
Validates quotes and reports using the `validate_report.py` script (proper casing, spell checking, long lines, cross-checks)
Usage: `validate [OPTIONAL PARAMETERS]`
### invoice
Builds PDF invoices from quotes.
Handled by [bash/handler_invoice](bash/handler_invoice)
Usage: `invoice REPO_NAME INVOICE_NO [NAMESPACE [[BRANCH]] [-PARAMETERS]`

126
chatops/bash/handler_build Normal file
View File

@@ -0,0 +1,126 @@
#!/bin/bash
# handler_build - builds PDF quotes and reports from XML files
#
# This script is part of the PenText framework
# https://pentext.org
#
# Copyright (C) 2016 Radically Open Security
# https://www.radicallyopensecurity.com
#
# Author(s): Peter Mosmans
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
VERSION=0.11
DOCBUILDER=/usr/local/bin/docbuilder.py
TEMPLOC=$(mktemp -d)
# These variables should be set environment-specific
[ -z $GITSERVER ] && GITSERVER=gitlab.local
[ -z $GITWEB ] && GITWEB=https://${GITSERVER}
[ -z $NAMESPACE ] && NAMESPACE=ros
BRANCH=master
# Read standard 'command line' variables
[[ ! -z $1 ]] && TARGET=$1
[[ ! -z $2 ]] && REPO=$2
# Reading positional parms is a bit ugly, shifting parms or getopt would be nicer
if [[ ! -z $3 ]]; then
if [[ ! $3 == -* ]]; then
NAMESPACE=$3
else
PARMS=$3
fi
fi
if [[ ! -z $4 ]]; then
if [[ ! $3 == -* ]]; then
BRANCH=$4
else
PARMS="$PARMS $4"
fi
fi
if [[ $# -ge 5 ]]; then
shift 4
PARMS="$PARMS $@"
fi
trap cleanup EXIT QUIT
# Make sure that the temporary files are always removed
cleanup() {
trap '' EXIT INT QUIT
[ -d $TEMPLOC ] && rm -rf $TEMPLOC &>/dev/null
exit
}
# As quote used to be called offer or even offer,
# this function retains backward compatibility - v0.1
backwards_compatible() {
if [[ $TARGET == "quote" ]] && [ ! -f $TARGET.xml ]; then
TARGET="offerte"
fi
}
# Clones repo using global (!) variables - v0.2
clone_repo() {
pushd $TEMPLOC 1>/dev/null
git clone -b $BRANCH --depth=1 -q ssh://git@${GITSERVER}/${NAMESPACE}/${REPO}.git &>/dev/null
if [ ! -d $TEMPLOC/$REPO ]; then
echo "[-] could not clone repo ${NAMESPACE}/${REPO}"
exit 1
else
cd $REPO
fi
}
# Preflight checks using global (!) variables - v0.2
preflight_checks() {
if ([[ $TARGET != "quote" ]] && [[ $TARGET != "report" ]]) || [ -z $REPO ]; then
echo "Usage: build quote|report REPOSITORY [NAMESPACE [BRANCH] [-v]"
exit
fi
if [ ! -f $DOCBUILDER ]; then
echo "[-] this script needs docbuilder.py ($DOCBUILDER)"
fi
}
build() {
if [ ! -d source ]; then
echo "[-] missing necessary pentext framework files"
exit 1
fi
pushd source &>/dev/null
backwards_compatible
targetpdf=target/$TARGET-latest.pdf
$DOCBUILDER -c -i $TARGET.xml -o ../$targetpdf -x ../xslt/generate_$TARGET.xsl $PARMS
if [[ $? -ne 0 ]]; then
echo "[-] Sorry, failed to parse $TARGET. Use \`builder $TARGET $REPO $NAMESPACE $BRANCH -v\` for more information."
exit 1
fi
popd &>/dev/null
if [ ! -f $targetpdf ]; then
echo "[-] hmmm... failed to build PDF file (could not find $targetpdf)"
exit 1
fi
}
add_to_repo() {
git add target/$TARGET-latest.pdf
git add target/waiver_?*.pdf &>/dev/null
git commit -q -m "$targetpdf proudly manufactured using ChatOps" &>/dev/null
git push -q >/dev/null
}
preflight_checks
echo "builder v$VERSION - Rocking your world, one build at a time..."
clone_repo
build
add_to_repo
echo "[+] listo! Check out $GITWEB/$NAMESPACE/$REPO/raw/$BRANCH/$targetpdf"
exit 0

View File

@@ -0,0 +1,131 @@
#!/bin/bash
# handler_convert - converts gitlab issues into XML files
#
# This script is part of the PenText framework
# https://pentext.org
#
# Copyright (C) 2016 Radically Open Security
# https://www.radicallyopensecurity.com
#
# Author(s): Peter Mosmans
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
VERSION=0.2
CONVERTER=/usr/local/bin/gitlab-to-pentext.py
TEMPLOC=$(mktemp -d)
# These variables should be set environment-specific
[ -z $GITLABCLI ] && GITLABCLI=gitlab
[ -z $GITSERVER ] && GITSERVER=gitlab.local
[ -z $NAMESPACE ] && NAMESPACE=ros
BRANCH=master
# Read standard 'command line' variables
[[ ! -z $1 ]] && REPO=$1
# Reading parms is a bit ugly, shifting parms or actually using getopt would be nicer
if [[ ! -z $2 ]]; then
if [[ ! $2 == -* ]]; then
NAMESPACE=$2
else
PARMS=$2
fi
fi
if [[ ! -z $3 ]]; then
if [[ ! $3 == -* ]]; then
BRANCH=$3
else
PARMS="$PARMS $3"
fi
fi
if [[ $# -ge 4 ]]; then
shift 3
PARMS="$PARMS $@"
fi
trap cleanup EXIT QUIT
# Make sure that the temporary files are always removed
cleanup() {
trap '' EXIT INT QUIT
[ -d $TEMPLOC ] && rm -rf $TEMPLOC &>/dev/null
exit
}
# As quote used to be called offerte or offer,
# this function retains backward compatibility - v0.2
backwards_compatible() {
if [[ $TARGET == "quote" ]] && [ ! -f $TARGET.xml ]; then
TARGET="offerte"
fi
}
# Clones repo using global (!) variables - v0.2
clone_repo() {
pushd $TEMPLOC 1>/dev/null
git clone -b $BRANCH --depth=1 -q ssh://git@${GITSERVER}/${NAMESPACE}/${REPO}.git &>/dev/null
if [ ! -d $TEMPLOC/$REPO ]; then
echo "[-] could not clone repo ${NAMESPACE}/${REPO}"
exit 1
else
cd $REPO
fi
}
# Preflight checks using global (!) variables - v0.2
preflight_checks() {
if [ -z $REPO ]; then
echo "[-] repository name needed"
exit
fi
if [ ! -f $CONVERTER ]; then
echo "[-] this script needs gitlab-to-pentext.py ($CONVERTER)"
exit
fi
}
get_id() {
project_id=$($GITLABCLI project search --query $REPO|awk '/id:/{print $2}')
if [ -z $project_id ]; then
echo "[-] could not find $REPO in gitlab"
exit
fi
return $project_id
}
convert() {
$CONVERTER --issues $project_id -y
}
add_to_repo() {
git add * &>/dev/null
git commit -q -m "Converted gitlab (non) findings to XML using ChatOps" &>/dev/null
git push -q >/dev/null
}
validate() {
if [ ! -d source ]; then
echo "[-] missing necessary pentext framework files"
exit 1
fi
$VALIDATOR $PARMS
if [[ -f project-vocabulary.pws ]]; then
git add project-vocabulary.pws
git commit -q -m 'Added spellcheck vocabulary using ChatOps' >/dev/null
git push -q >/dev/null
fi
}
preflight_checks
echo "convert v$VERSION - Convert all the things!"
get_id
clone_repo
convert
add_to_repo
echo "[+] Listo!"

View File

@@ -0,0 +1,126 @@
#!/bin/bash
# handler_invoice - builds PDF invoices from quotes
#
# This script is part of the PenText framework
# https://pentext.org
#
# Copyright (C) 2016 Radically Open Security
# https://www.radicallyopensecurity.com
#
# Author(s): Peter Mosmans
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
VERSION=0.5
DOCBUILDER=/usr/local/bin/docbuilder.py
TEMPLOC=$(mktemp -d)
DATESTAMP=$(date +"%Y-%m-%d")
INVOICE="00/000"
# These variables should be set environment-specific
[ -z $GITSERVER ] && GITSERVER=gitlab.local
[ -z $GITWEB ] && GITWEB=https://${GITSERVER}
[ -z $NAMESPACE ] && NAMESPACE=ros
BRANCH=master
TARGET=quote
# Read standard 'command line' variables
[[ ! -z $1 ]] && REPO=$1
[[ ! -z $2 ]] && INVOICE=$2
# Reading positional parms is a bit ugly, shifting parms or getopt would be nicer
if [[ ! -z $3 ]]; then
if [[ ! $3 == -* ]]; then
NAMESPACE=$3
else
PARMS=$3
fi
fi
if [[ ! -z $4 ]]; then
if [[ ! $3 == -* ]]; then
BRANCH=$4
else
PARMS="$PARMS $4"
fi
fi
if [[ $# -ge 5 ]]; then
shift 4
PARMS="$PARMS $@"
fi
trap cleanup EXIT QUIT
# Make sure that the temporary files are always removed
cleanup() {
trap '' EXIT INT QUIT
[ -d $TEMPLOC ] && rm -rf $TEMPLOC &>/dev/null
exit
}
# As quote used to be called offerte or offer,
# this function retains backward compatibility - v0.2
backwards_compatible() {
if [[ $TARGET == "quote" ]] && [ ! -f $TARGET.xml ]; then
TARGET="offerte"
fi
}
# Clones repo using global (!) variables - v0.2
clone_repo() {
pushd $TEMPLOC 1>/dev/null
git clone -b $BRANCH --depth=1 -q ssh://git@${GITSERVER}/${NAMESPACE}/${REPO}.git &>/dev/null
if [ ! -d $TEMPLOC/$REPO ]; then
echo "[-] could not clone repo ${NAMESPACE}/${REPO}"
exit 1
else
cd $REPO
fi
}
# Preflight checks using global (!) variables - v0.2
preflight_checks() {
if [ -z $REPO ]; then
echo "Usage: invoice REPOSITORY [INVOICE_NUMBER [NAMESPACE [BRANCH]]] [-v]"
exit
fi
if [ ! -f $DOCBUILDER ]; then
echo "[-] this script needs docbuilder.py ($DOCBUILDER)"
fi
}
build() {
if [ ! -d source ]; then
echo "[-] missing necessary pentext framework files"
exit 1
fi
pushd source &>/dev/null
backwards_compatible
targetpdf=target/invoice-latest.pdf
$DOCBUILDER -c -i $TARGET.xml -o ../$targetpdf -x ../xslt/generate_invoice.xsl -invoice "$INVOICE" -date $DATESTAMP --fop ../target/invoice.fo $PARMS
if [[ $? -ne 0 ]]; then
echo "[-] Sorry, failed to generate $targetpdf"
exit 1
fi
popd &>/dev/null
if [ ! -f target/invoice-latest.pdf ]; then
echo "[-] hmmm... failed to build PDF file (could not find $targetpdf)"
exit 1
fi
}
add_to_repo() {
git add target/invoice-latest.pdf
git commit -q -m "Invoice $INVOICE automatically generated using ChatOps" &>/dev/null
git push -q >/dev/null
}
preflight_checks
echo "invoice v$VERSION - Congrats, another project from conception to ka-CHING"
clone_repo
build
add_to_repo
echo "[+] listo! Check out $GITWEB/$NAMESPACE/$REPO/raw/$BRANCH/$targetpdf"

View File

@@ -0,0 +1,163 @@
#!/bin/bash
# handler_pentest - sets up a pentest repo with PenText based on a quote repo
#
# This script is part of the PenText framework
# https://pentext.org
#
# Copyright (C) 2016 Radically Open Security
# https://www.radicallyopensecurity.com
#
# Author(s): Peter Mosmans
# John Sinteur
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
VERSION=0.9
SAXON=/usr/local/bin/saxon/saxon9he.jar
TEMPLATEREPO=ssh://git@gitlab.local/peter/templates
# These variables should be set environment-specific
[ -z $GITLABCLI ] && GITLABCLI=gitlab
[ -z $GITSERVER ] && GITSERVER=gitlab.local
[ -z $NAMESPACE ] && NAMESPACE=ros
[ -z $NAMESPACEID ] && NAMESPACEID=1
[ -z $PENTEXTREPO ] && PENTEXTREPO=https://github.com/radicallyopensecurity/pentext
TEMPLOC=$(mktemp -d)
pentext=$(echo $PENTEXTREPO|awk -F '/' '{print $5}')
# Read standard 'command line' variables
[[ ! -z $1 ]] && REPO=$1
[[ ! -z $2 ]] && NAMESPACE=$2
[[ ! -z $3 ]] && PREVIOUS=$3
BRANCH=master
TARGET=quote
trap cleanup EXIT QUIT
# Make sure that the temporary files are always removed
cleanup() {
trap '' EXIT INT QUIT
# remove repo if not finished successfully
if [ -z $finished ] && [ ! -z $project_id ]; then
$GITLABCLI project delete --id $project_id
echo "[-] deleted project $project_id"
fi
[ -d $TEMPLOC ] && rm -rf $TEMPLOC &>/dev/null
exit
}
# As quote used to be called offerte or offer,
# this function retains backward compatibility - v0.2
backwards_compatible() {
if [[ $TARGET == "quote" ]] && [ ! -f $TARGET.xml ]; then
TARGET="offerte"
fi
}
# Clones repo using global (!) variables - v0.3
clone_repo() {
pushd $TEMPLOC 1>/dev/null
git clone --depth=1 -q ssh://git@${GITSERVER}/${NAMESPACE}/${REPO}.git &>/dev/null
if [ ! -d $TEMPLOC/$REPO ]; then
echo "[-] could not clone repo ${NAMESPACE}/${REPO}"
exit 1
else
cd $REPO
fi
}
# Preflight checks using global (!) variables
preflight_checks() {
if [ -z $REPO ]; then
echo "[-] repository name needed (without leading pen- or off-)"
exit
fi
if [ ! -f $SAXON ]; then
echo "[-] this script needs saxon ($SAXON)"
fi
}
setup_repo() {
project_id=$($GITLABCLI project create --name $REPO --namespace $NAMESPACEID --issues-enabled true --wiki-enabled true --snippets-enabled true --wall-enabled true --merge-requests-enabled true 2>/dev/null| awk '/id:/{print $2}')
if [ ! -z $project_id ]; then
echo "[+] successfully created gitlab project $REPO with id ${project_id}"
$GITLABCLI project-label create --project-id ${project_id} --name documentation --color "#0000FF" &>/dev/null
$GITLABCLI project-label create --project-id ${project_id} --name finding --color "#00c800" &>/dev/null
$GITLABCLI project-label create --project-id ${project_id} --name lead --color "#e4d700" &>/dev/null
$GITLABCLI project-label create --project-id ${project_id} --name non-finding --color "#c80000" &>/dev/null
$GITLABCLI project-label create --project-id ${project_id} --name future-work --color "#f8b7b2" &>/dev/null
$GITLABCLI project-issue create --project-id ${project_id} --description "Please drop all your positive/negative comments here, so that we can keep on improving our processes. It is important that we learn from <b>what</b>. No need for namecalling, <b>who</b> is unimportant <br /> <h2>Thumbs up</h2> <h2>Improvement</h2><h2>Not project related</h2><h2>Project related</h2>" --title "Retrospective: add your feedback HERE" &> /dev/null
else
echo "[-] could not create repo $NAMESPACE/$REPO"
exit 1
fi
}
# Add standard templates using global (!) variables - v0.2
add_templates() {
[ -d $TEMPLOC/$pentext ] && rm -rf $TEMPLOC/$pentext &>/dev/null
pushd $TEMPLOC 1>/dev/null && git clone --depth=1 $PENTEXTREPO &>/dev/null && popd 1>/dev/null
if [ ! -d $TEMPLOC/$pentext ]; then
echo "[-] could not clone (and therefore add) pentext repo $TEMPLATEREPO"
exit 1
else
clone_repo
# copy the framework
cp -r $TEMPLOC/$pentext/xml/* .
# remove the docs
rm -r doc &>/dev/null
fi
}
grab_offer() {
pushd source &>/dev/null
backwards_compatible
if [ ! -f $TARGET.xml ]; then
echo "[-] could not find $TARGET.xml"
exit
fi
cp client_info.xml $TEMPLOC/client_info.xml &> /dev/null
cp $TARGET.xml $TEMPLOC/quote.xml &> /dev/null
}
convert_report() {
cp $TEMPLOC/quote.xml source/quote.xml &> /dev/null
cp $TEMPLOC/client_info.xml source/client_info.xml &> /dev/null
pushd source &>/dev/null
java -jar $SAXON -s:quote.xml -xsl:../xslt/off2rep.xsl -o:report.xml
if [ ! -f report.xml ]; then
echo "[-] hmmm... failed to convert quote into report.xml"
exit 1
fi
popd &>/dev/null
mkdir -p findings/ &>/dev/null
mkdir -p non-findings/ &>/dev/null
}
add_to_repo() {
git add * &>/dev/null
git commit -q -m "Initialized pentest repository with PenText using ChatOps" &> /dev/null
git push -q > /dev/null
}
preflight_checks
echo "startpentest v${VERSION} - Ready for some ACTION?"
ORIGREPO=$REPO
REPO=off-$ORIGREPO
[[ ! -z $PREVIOUS ]] && $REPO=$PREVIOUS
clone_repo
grab_offer
REPO=pen-${ORIGREPO}
setup_repo
add_templates
convert_report
add_to_repo
echo "[+] listo!"
finished=true

View File

@@ -0,0 +1,90 @@
#!/bin/bash
# handler_quickscope - converts a quickscope into a quotation
#
# This script is part of the PenText framework
# https://pentext.org
#
# Copyright (C) 2016 Radically Open Security
# https://www.radicallyopensecurity.com
#
# Author(s): Peter Mosmans
# John Sinteur
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
VERSION=0.3
SAXON=/usr/local/bin/saxon/saxon9he.jar
TEMPLOC=$(mktemp -d)
# These variables should be set environment-specific
[ -z $GITSERVER ] && GITSERVER=gitlab.local
[ -z $NAMESPACE ] && NAMESPACE=ros
# Read standard 'command line' variables
[[ ! -z $1 ]] && REPO=$1
[[ ! -z $2 ]] && NAMESPACE=$2
[[ ! -z $3 ]] && BRANCH=$3 || BRANCH=master
trap cleanup EXIT QUIT
# Make sure that the temporary files are always removed
cleanup() {
trap '' EXIT INT QUIT
[ -d $TEMPLOC ] && rm -rf $TEMPLOC &>/dev/null
exit
}
# Clones repo using global (!) variables - v0.2
clone_repo() {
pushd $TEMPLOC 1>/dev/null
git clone --depth=1 -q ssh://git@${GITSERVER}/${NAMESPACE}/${REPO}.git &>/dev/null
if [ ! -d $TEMPLOC/$REPO ]; then
echo "[-] could not clone repo ${NAMESPACE}/${REPO}"
exit 1
else
cd $REPO
fi
}
# Preflight checks using global (!) variables
preflight_checks() {
if [ -z $REPO ]; then
echo "Usage: quickscope REPOSITORY [NAMESPACE]"
exit
fi
if [ ! -f $SAXON ]; then
echo "[-] this script needs saxon ($SAXON)"
fi
}
convert_quickscope() {
if [ ! -f $TEMPLOC/$REPO/source/quickscope.xml ] || [ ! -f $TEMPLOC/$REPO/xslt/qs2offerte.xsl ]; then
echo "[-] missing necessary pentext framework files"
exit 1
fi
java -jar $SAXON -s:$TEMPLOC/$REPO/source/quickscope.xml -xsl:$TEMPLOC/$REPO/xslt/qs2offerte.xsl -o:$TEMPLOC/$REPO/source/offerte.xml
if [ ! -f $TEMPLOC/$REPO/source/offerte.xml ]; then
echo "[-] failed to parse quote"
exit
fi
}
add_to_repo() {
git add source/offerte.xml &>/dev/null
git commit -q -m "Created quickscope using ChatOps" &>/dev/null
git push -q >/dev/null
}
preflight_checks
echo "quickscope v${VERSION} - Rockin' and scoping'..."
clone_repo
convert_quickscope
add_to_repo
echo "[+] listo!"
exit 0

113
chatops/bash/handler_quote Normal file
View File

@@ -0,0 +1,113 @@
#!/bin/bash
# handler_quote - sets up a quote gitlab repository using PenText
#
# This script is part of the PenText framework
# https://pentext.org
#
# Copyright (C) 2016 Radically Open Security
# https://www.radicallyopensecurity.com
#
# Author(s): Peter Mosmans
# John Sinteur
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
VERSION=0.7
# These variables should be set environment-specific
[ -z $GITLABCLI ] && GITLABCLI=gitlab
[ -z $GITSERVER ] && GITSERVER=gitlab.local
[ -z $NAMESPACE ] && NAMESPACE=ros
[ -z $NAMESPACEID ] && NAMESPACEID=1
[ -z $PENTEXTREPO ] && PENTEXTREPO=https://github.com/radicallyopensecurity/pentext
PREFIX="off-"
pentext=$(echo $PENTEXTREPO|awk -F '/' '{print $5}')
TEMPLOC=$(mktemp -d)
# Read standard 'command line' variables
[[ ! -z $1 ]] && REPO=$PREFIX$1
REPO=${REPO,,} # follow git specs: lowercase
[[ ! -z $2 ]] && NAMESPACE=$2
trap cleanup EXIT QUIT
# Make sure that the temporary files are always removed
cleanup() {
trap '' EXIT INT QUIT
# remove repo if not finished successfully
if [ -z $finished ] && [ ! -z $project_id ]; then
$GITLABCLI project delete --id $project_id
echo "[-] deleted project $project_id"
fi
[ -d $TEMPLOC ] && rm -rf $TEMPLOC &>/dev/null
exit
}
# Clones repo using global (!) variables - v0.3
clone_repo() {
pushd $TEMPLOC 1>/dev/null
git clone --depth=1 -q ssh://git@${GITSERVER}/${NAMESPACE}/${REPO}.git &>/dev/null
if [ ! -d $TEMPLOC/$REPO ]; then
echo "[-] could not clone repo ${NAMESPACE}/${REPO}"
exit 1
else
cd $REPO
fi
}
# Preflight checks using global (!) variables
preflight_checks() {
if [ -z $REPO ]; then
echo "Usage: startquote PROJECT_NAME"
exit
fi
if ! which $GITLABCLI &>/dev/null; then
echo "[-] this script needs the gitlab command line interface (python-gitlab)"
fi
}
setup_repo() {
project_id=$($GITLABCLI project create --name $REPO --namespace $NAMESPACEID --issues-enabled true --wiki-enabled true --snippets-enabled true --wall-enabled true --merge-requests-enabled true 2>/dev/null| awk '/id:/{print $2}')
if [ ! -z $project_id ]; then
echo "[+] successfully created gitlab project $REPO with id ${project_id}"
else
echo "[-] could not create repo $NAMESPACE/$REPO"
exit 1
fi
}
# Add standard templates using global (!) variables - v0.2
add_templates() {
[ -d $TEMPLOC/$pentext ] && rm -rf $TEMPLOC/$pentext &>/dev/null
pushd $TEMPLOC 1>/dev/null && git clone --depth=1 $PENTEXTREPO &>/dev/null && popd 1>/dev/null
if [ ! -d $TEMPLOC/$pentext ]; then
echo "[-] could not clone (and therefore add) pentext repo $TEMPLATEREPO"
exit 1
else
clone_repo
# copy the framework
cp -r $TEMPLOC/$pentext/xml/* .
# remove the docs
rm -r doc &>/dev/null
fi
}
add_to_repo() {
git add * &>/dev/null
git commit -q -m "Initialized quote repository with PenText using ChatOps" &>/dev/null
git push -q > /dev/null
}
preflight_checks
echo "startquote v${VERSION} - Humbly setting up your quote framework..."
setup_repo
add_templates
add_to_repo
echo "[+] listo!"
finished=true

View File

@@ -0,0 +1,113 @@
#!/bin/bash
# handler_validate - validates quotes and reports
#
# This script is part of the PenText framework
# https://pentext.org
#
# Copyright (C) 2016 Radically Open Security
# https://www.radicallyopensecurity.com
#
# Author(s): Peter Mosmans
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
VERSION=0.3
VALIDATOR=/usr/local/bin/validate_report.py
TEMPLOC=$(mktemp -d)
# These variables should be set environment-specific
[ -z $GITSERVER ] && GITSERVER=gitlab.local
[ -z $NAMESPACE ] && NAMESPACE=ros
BRANCH=master
# Read standard 'command line' variables
[[ ! -z $1 ]] && REPO=$1
# Reading parms is a bit ugly, shifting parms or actually using getopt would be nicer
if [[ ! -z $2 ]]; then
if [[ ! $2 == -* ]]; then
NAMESPACE=$2
else
PARMS=$2
fi
fi
if [[ ! -z $3 ]]; then
if [[ ! $3 == -* ]]; then
BRANCH=$3
else
PARMS="$PARMS $3"
fi
fi
if [[ $# -ge 4 ]]; then
shift 3
PARMS="$PARMS $@"
fi
trap cleanup EXIT QUIT
# Make sure that the temporary files are always removed
cleanup() {
trap '' EXIT INT QUIT
[ -d $TEMPLOC ] && rm -rf $TEMPLOC &>/dev/null
exit
}
# As quote used to be called offerte or offer,
# this function retains backward compatibility - v0.2
backwards_compatible() {
if [[ $TARGET == "quote" ]] && [ ! -f $TARGET.xml ]; then
TARGET="offerte"
fi
}
# Clones repo using global (!) variables - v0.3
clone_repo() {
pushd $TEMPLOC 1>/dev/null
git clone --depth=1 -q ssh://git@${GITSERVER}/${NAMESPACE}/${REPO}.git &>/dev/null
if [ ! -d $TEMPLOC/$REPO ]; then
echo "[-] could not clone repo ${NAMESPACE}/${REPO}"
exit 1
else
cd $REPO
fi
}
# Preflight checks using global (!) variables - v0.2
preflight_checks() {
if [ -z $REPO ]; then
echo "[-] repository name needed"
exit
fi
if [ ! -f $VALIDATOR ]; then
echo "[-] this script needs validate_report.py ($VALIDATOR)"
exit
fi
}
validate() {
if [ ! -d source ]; then
echo "[-] missing necessary pentext framework files"
exit 1
fi
$VALIDATOR $PARMS
}
# Add changed files to the repository
add_to_repo() {
git add * &>/dev/null
git commit -q -m "validate fixed some files using ChatOps" &>/dev/null
git push -q > /dev/null
}
preflight_checks
echo "validate v$VERSION - Validating all of your needs..."
clone_repo
validate
add_to_repo
# Don't Listo! here, as the validate script tells the user that

50
chatops/bash/releaser.sh Normal file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# releaser - renames (and encrypts) pentest reports for release
#
# This script is part of the PenText framework
# https://pentext.org
#
# Copyright (C) 2016 Radically Open Security
# https://www.radicallyopensecurity.com
#
# Author(s): Peter Mosmans
# Marcus Bointon
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
source=target/report-latest.pdf
name=$1
targetdir=target
type=REP
version=1.0
if [ -z ${name} ]; then
echo "Usage: releaser NAME [version [TYPE]]"
echo "Names files TYPE-YYYYMMDD-vVERSION-NAME"
echo "Expects source to be ${source}, and the target directory is ${targetdir}"
echo "defaults are version=1.0 and TYPE=REP"
exit 1
fi
[ ! -z $2 ] && version=$2
[ ! -z $3 ] && type=$3
fullname="${targetdir}/${type}-$(date +'%Y%m%d')-v${version}-${name}.pdf"
if [ -f ${source} ]; then
if [ -f ${fullname} ]; then
echo "${fullname} already exists. Exiting..."
exit 1
else
cp -v ${source} ${fullname}
PASS=$(head -c 25 /dev/random | base64 | head -c 25)
zip --password ${PASS} "${fullname}.zip" ${fullname} 2>/dev/null && echo "Zip file encrypted with password '${PASS}'"
fi
else
echo "Could not find source ${source}"
exit 1
fi

169
chatops/bash/test_pentext Normal file
View File

@@ -0,0 +1,169 @@
#!/bin/bash
# test_pentext - tests the PenText toolchain
#
# This script is part of the PenText framework
# https://pentext.org
#
# Copyright (C) 2016 Radically Open Security
# https://www.radicallyopensecurity.com
#
# Author(s): Peter Mosmans
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
VERSION=0.6
DOCBUILDER=/usr/local/bin/docbuilder.py
VALIDATOR=/usr/local/bin/validate_report.py
SAXON=/usr/local/bin/saxon/saxon9he.jar
# These variables should be set environment-specific
[ -z $GITLABCLI ] && GITLABCLI=gitlab
[ -z $GITSERVER ] && GITSERVER=gitlab.local
[ -z $GITWEB ] && GITWEB=https://$GITSERVER
[ -z $NAMESPACE ] && NAMESPACE=ros
[ -z $NAMESPACEID ] && NAMESPACEID=1
[ -z $PENTEXTREPO ] && PENTEXTREPO=https://github.com/radicallyopensecurity/pentext
TEMPLOC=$(mktemp -d)
BRANCH=master
reponame=test-pentext-$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 10 | head -n 1)
pentext=$(echo $PENTEXTREPO|awk -F '/' '{print $5}')
# Read standard 'command line' variables
[[ ! -z $1 ]] && REPO=$1
# Reading parms is a bit ugly, shifting parms or actually using getopt would be nicer
if [[ ! -z $2 ]]; then
if [[ ! $2 == -* ]]; then
NAMESPACE=$2
else
PARMS=$2
fi
fi
if [[ ! -z $3 ]]; then
if [[ ! $3 == -* ]]; then
BRANCH=$3
else
PARMS="$PARMS $3"
fi
fi
if [[ $# -ge 4 ]]; then
shift 3
PARMS="$PARMS $@"
fi
trap cleanup EXIT QUIT
# Make sure that the temporary files are always removed
cleanup() {
trap '' EXIT INT QUIT
[ -d $TEMPLOC ] && rm -rf $TEMPLOC &>/dev/null
exit
}
# As quote used to be called offerte or offer,
# this function retains backward compatibility - v0.2
backwards_compatible() {
if [[ $TARGET == "quote" ]] && [ ! -f $TARGET.xml ]; then
TARGET="offerte"
fi
}
setup_repo() {
echo "[*] testing gitlab command line interface..."
REPO=${reponame,,} # lowercase, but of course
project_id=$($GITLABCLI project create --name $REPO --namespace $NAMESPACEID --issues-enabled true --wiki-enabled true --snippets-enabled true --wall-enabled true --merge-requests-enabled true| awk '/id:/{print $2}')
if [ ! -z $project_id ]; then
echo "[+] successfully created test gitlab project with id ${project_id}"
else
echo "[-] could not create repo $reponame - is the .python-gitlab.cfg configuration corrent ?"
exit 1
fi
}
# Clones repo using global (!) variables - v0.3
clone_repo() {
echo "[*] testing gitlab SSH access using ssh://git@${GITSERVER}/${NAMESPACE}..."
pushd $TEMPLOC 1>/dev/null
git clone --depth=1 -q ssh://git@${GITSERVER}/${NAMESPACE}/$REPO.git &>/dev/null
if [ ! -d $TEMPLOC/$REPO ]; then
echo "[-] could not clone repo ${NAMESPACE}/$reponame - is the namespace correct ?"
exit 1
else
echo "[+] successfully cloned repo using namespace ${NAMESPACE}"
fi
cd $TEMPLOC/$REPO
}
# Preflight checks
preflight_checks() {
echo "The following variables will be used: "
echo "DOCBUILDER=$DOCBUILDER (location of docbuilder.py)"
echo "GITLABCLI=$GITLABCLI (command line gitlab interface)"
echo "GITSERVER=$GITSERVER (git server)"
echo "GITWEB=$GITWEB (webinterface of git server)"
echo "NAMESPACE=$NAMESPACE (namespace of repositories)"
echo "NAMESPACEID=$NAMESPACEID (namespace ID of repositories)"
echo "PENTEXTREPO=$PENTEXTREPO (location of pentext repo)"
echo "SAXON=$SAXON (saxon binary)"
echo "VALIDATOR=$VALIDATOR (location of validate_report.py)"
echo "[*] testing binaries..."
[ ! -f $VALIDATOR ] && echo "[-] validate_report.py ($VALIDATOR) is missing (necessary for validate)"
[ ! -f $DOCBUILDER ] && echo "[-] docbuilder.py ($DOCBUILDER) is missing (necessary for build)"
[ ! -f $SAXON ] && echo "[-] saxon ($SAXON) is missing (necessary for invoice)"
which java &> /dev/null || echo "[-] java is missing (necessary for saxon)"
if ! which $GITLABCLI &>/dev/null && [ ! -f $GITLABCLI ]; then
echo "[-] gitlab ($GITLABCLI) is missing, required for startquote and startpentest"
exit 1
fi
}
add_to_repo() {
echo "[*] testing add to repo"
echo "commit test" > testcommit
git add testcommit
git commit -q -m "test_pentext testcommit"
git push -q
if [ $? -ne 0 ]; then
echo "[-] failed adding stuff to repo"
fi
}
delete_repo() {
if [ ! -z $project_id ]; then
$GITLABCLI project delete --id $project_id &>/dev/null
if [ $? -eq 0 ]; then
echo "[+] successfully deleted testproject $project_id"
else
echo "[-] hmmm... failed deleting testproject $project_id"
exit 1
fi
fi
}
clone_pentext() {
echo "[*] testing access to PenText repo $PENTEXTREPO..."
pushd $TEMPLOC 1>/dev/null
git clone --depth=1 $PENTEXTREPO &>/dev/null
popd 1>/dev/null
if [ ! -d $TEMPLOC/$pentext ]; then
echo "[-] could not clone repo $TEMPLATEREPO..."
exit 1
fi
}
# preflight_checks
echo "test_pentext v$VERSION - Testing the PenText toolchain"
preflight_checks
setup_repo
clone_repo
add_to_repo
delete_repo
clone_pentext
echo "[+] all tests successful. Good to go!"

View File

@@ -0,0 +1,234 @@
#!/usr/bin/env python
"""
Builds PDF files from (intermediate fo and) XML files.
This script is part of the PenText framework
https://pentext.org
Copyright (C) 2015-2016 Radically Open Security
https://www.radicallyopensecurity.com
Author(s): Peter Mosmans
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
"""
from __future__ import absolute_import
from __future__ import print_function
import argparse
import os
import subprocess
from subprocess import PIPE
import sys
import textwrap
GITREV = 'GITREV' # Magic tag which gets replaced by the git short commit hash
OFFERTE = 'generate_offerte.xsl' # XSL for generating waivers
WAIVER = 'waiver_' # prefix for waivers
def parse_arguments():
"""
Parses command line arguments.
"""
global verboseprint
global verboseerror
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=textwrap.dedent('''\
Builds PDF files from (intermediate fo and) XML files.
Copyright (C) 2015-2016 Radically Open Security (Peter Mosmans)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.'''))
parser.add_argument('-c', '--clobber', action='store_true',
help='overwrite output file if it already exists')
parser.add_argument('-date', action='store',
help='the invoice date')
parser.add_argument('--fop-config', action='store',
default='/etc/docbuilder/rosfop.xconf',
help="""fop configuration file (default
/etc/docbuilder/rosfop.xconf""")
parser.add_argument('-f', '--fop', action='store',
default='../target/report.fo',
help="""intermediate fop output file (default:
../target/report.fo)""")
parser.add_argument('--fop-binary', action='store',
default='/usr/local/bin/fop',
help='fop binary (default /usr/local/bin/fop')
parser.add_argument('-i', '--input', action='store',
default='report.xml',
help="""input file (default: report.xml)""")
parser.add_argument('-invoice', action='store',
help="""invoice number""")
parser.add_argument('--saxon', action='store',
default='/usr/local/bin/saxon/saxon9he.jar',
help="""saxon JAR file (default
/usr/local/bin/saxon/saxon9he.jar)""")
parser.add_argument('-x', '--xslt', action='store',
default='../xslt/generate_report.xsl',
help='input file (default: ../xslt/generate_report.xsl)')
parser.add_argument('-o', '--output', action='store',
default='../target/report-latest.pdf',
help="""output file name (default:
../target/report-latest.pdf""")
parser.add_argument('-v', '--verbose', action='store_true',
help='increase output verbosity')
parser.add_argument('-w', '--warnings', action='store_true',
help='show warnings')
args = parser.parse_args()
if args.verbose:
def verboseprint(*args): # pylint: disable=missing-docstring
for arg in args:
print(arg, end="")
print()
def verboseerror(*args): # pylint: disable=missing-docstring
for arg in args:
print(arg, end="", file=sys.stderr)
print(file=sys.stderr)
else:
verboseprint = lambda *a: None
verboseerror = lambda *a: None
return vars(parser.parse_args())
def print_output(stdout, stderr):
"""
Prints out standard out and standard err using the verboseprint function.
"""
if stdout:
verboseprint('[+] stdout: {0}'.format(stdout))
if stderr:
verboseerror('[-] stderr: {0}'.format(stderr))
def change_tag(fop):
"""
Replaces GITREV in document by git commit shorttag.
"""
cmd = ['git', 'log', '--pretty=format:%h', '-n', '1']
process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
shorttag, _stderr = process.communicate()
if not process.returncode:
fop_file = open(fop).read()
if GITREV in fop_file:
fop_file = fop_file.replace(GITREV, shorttag)
with open(fop, 'w') as new_file:
new_file.write(fop_file)
print('[+] Embedding git version information into document')
def to_fo(options):
"""
Creates a fo output file based on a XML file.
Returns True if successful
"""
cmd = ['java', '-jar', options['saxon'],
'-s:' + options['input'], '-xsl:' + options['xslt'],
'-o:' + options['fop'], '-xi']
if options['invoice']:
cmd.append('INVOICE_NO=' + options['invoice'])
if options['date']:
cmd.append('DATE=' + options['date'])
process = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
print_output(stdout, stderr)
if process.returncode:
print_exit('[-] Error creating fo file from XML input',
process.returncode)
else:
change_tag(options['fop'])
return True
def to_pdf(options):
"""
Creates a PDF file based on a fo file.
Returns True if successful
"""
cmd = [options['fop_binary'], '-c', options['fop_config'], options['fop'],
options['output']]
try:
verboseprint('Converting {0} to {1}'.format(options['fop'],
options['output']))
process = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
result = process.returncode
print_output(stdout, stderr)
if result == 0:
print('[+] Succesfully built ' + options['output'])
except OSError as exception:
print_exit('[-] ERR: {0}'.format(exception.strerror), exception.errno)
return result == 0
def print_exit(text, result):
"""
Prints error message and exits with result code.
"""
print(text, file=sys.stderr)
sys.exit(result)
def main():
"""
The main program.
"""
global verboseerror
global verboseprint
result = False
options = parse_arguments()
if not os.path.isfile(options['input']):
print_exit('[-] Cannot find input file {0}'.
format(options['input']), result)
try:
if os.path.isfile(options['output']):
if not options['clobber']:
print_exit('[-] Output file {0} already exists. '.
format(options['output']) +
'Use -c (clobber) to overwrite',
result)
os.remove(options['output'])
except OSError as exception:
print_exit('[-] Could not remove/overwrite file {0} ({1})'.
format(options['output'], exception.strerror), result)
result = to_fo(options)
if result:
if OFFERTE in options['xslt']: # an offerte can generate multiple fo's
report_output = options['output']
verboseprint('generating separate waivers detected')
output_dir = os.path.dirname(options['output'])
fop_dir = os.path.dirname(options['fop'])
try:
for fop in [os.path.splitext(x)[0] for x in
os.listdir(fop_dir) if x.endswith('fo')]:
if WAIVER in fop:
options['output'] = output_dir + os.sep + fop + '.pdf'
else:
options['output'] = report_output
options['fop'] = fop_dir + os.sep + fop + '.fo'
result = to_pdf(options) and result
except OSError as exception:
print_exit('[-] ERR: {0}'.format(exception.strerror),
exception.errno)
else:
result = to_pdf(options)
else:
print_exit('[-] Unsuccessful (error {0})'.format(result), result)
sys.exit(not result)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,275 @@
#!/usr/bin/env python
"""
Gitlab bridge for PenText: imports and updates gitlab issues into PenText
(XML) format
This script is part of the PenText framework
https://pentext.org
Copyright (C) 2016 Radically Open Security
https://www.radicallyopensecurity.com
Author(s): Peter Mosmans
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
"""
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import argparse
import collections
import os
import sys
import textwrap
try:
import gitlab
import jxmlease
# Path of this script. The validate_report module is on the same path.
sys.path.append(os.path.dirname(__file__))
import validate_report
except ImportError as exception:
print('[-] This script needs python-gitlab, jxmlease and validate_report library',
file=sys.stderr)
print("validate_report is part of the pentext framework", file=sys.stderr)
print("Install python-gitlab with: sudo pip install python-gitlab", file=sys.stderr)
print("Install jxmlease with: sudo pip install jxmlease", file=sys.stderr)
print("", file=sys.stderr)
print("Currently missing: " + exception.message, file=sys.stderr)
sys.exit(-1)
def add_finding(issue, options):
"""
Writes issue as XML finding to file.
"""
title = validate_report.capitalize(issue.title.strip())
print_status('{0} - {1} - {2}'.format(issue.state, issue.labels,
title), options)
threat_level = 'Moderate'
finding_type = 'TODO'
finding_id = '{0}-{1}'.format(issue.iid, valid_filename(title))
filename = 'findings/{0}.xml'.format(finding_id)
finding = collections.OrderedDict()
finding['title'] = title
finding['description'] = unicode.replace(issue.description,
'\r\n', '\n')
finding['technicaldescription'] = ''
for note in [x for x in issue.notes.list() if not x.system]:
finding['technicaldescription'] += unicode.replace(note.body,
'\r\n', '\n')
finding['impact'] = {}
finding['impact']['p'] = 'TODO'
finding['recommendation'] = {}
finding['recommendation']['ul'] = {}
finding['recommendation']['ul']['li'] = 'TODO'
finding_xml = jxmlease.XMLDictNode(finding, tag='finding',
xml_attrs={'id': finding_id,
'threatLevel': threat_level,
'type': finding_type})
if options['dry_run']:
print_line('[+] {0}'.format(filename))
print(finding_xml.emit_xml())
else:
if os.path.isfile(filename) and not options['overwrite']:
print_line('Finding {0} already exists (use --overwrite to overwrite)'.
format(filename))
else:
if options['y'] or ask_permission('Create file ' + filename):
with open(filename, 'w') as xmlfile:
xmlfile.write(finding_xml.emit_xml().encode('utf-8'))
print_line('[+] Created {0}'.format(filename))
def add_non_finding(issue, options):
"""
Adds a non-finding.
"""
title = validate_report.capitalize(issue.title.strip())
print_status('{0} - {1} - {2}'.format(issue.state, issue.labels,
title), options)
non_finding_id = '{0}-{1}'.format(issue.iid, valid_filename(title))
filename = 'non-findings/{0}.xml'.format(non_finding_id)
non_finding = collections.OrderedDict()
non_finding['title'] = title
non_finding['p'] = unicode.replace(issue.description,
'\r\n', '\n')
for note in [x for x in issue.notes.list() if not x.system]:
non_finding['p'] += unicode.replace(note.body,
'\r\n', '\n')
non_finding_xml = jxmlease.XMLDictNode(non_finding, tag='non-finding',
xml_attrs={'id': non_finding_id})
if options['dry_run']:
print_line('[+] {0}'.format(filename))
print(non_finding_xml.emit_xml())
else:
if os.path.isfile(filename) and not options['overwrite']:
print_line('Non-finding {0} already exists (use --overwrite to overwrite)'.
format(filename))
else:
if options['y'] or ask_permission('Create file ' + filename):
with open(filename, 'w') as xmlfile:
xmlfile.write(non_finding_xml.emit_xml().encode('utf-8'))
print_line('[+] Created {0}'.format(filename))
def ask_permission(question):
"""
Ask question and return True if user answered with y.
"""
print_line('{0} ? [y/N]'.format(question))
return raw_input().lower() == 'y'
def convert_markdown(text):
"""
Replace markdown monospace with monospace tags
"""
result = text
return result
# print('EXAMINING ' + text + ' END')
# monospace = re.findall("\`\`\`(.*?)\`\`\`", text, re.DOTALL)
# if len(monospace):
# result = {}
# result['monospace'] = ''.join(monospace)
def list_issues(gitserver, options):
"""
Lists all issues for options['issues']
"""
try:
for issue in gitserver.project_issues.list(project_id=options['issues']):
if issue.state == 'closed' and not options['closed']:
continue
if 'finding' in issue.labels:
add_finding(issue, options)
if 'non-finding' in issue.labels:
add_non_finding(issue, options)
except Exception as exception:
print_error('could not find any issues ({0})'.format(exception), -1)
def list_projects(gitserver):
"""
Lists all available projects.
"""
for project in gitserver.projects.list(all=True):
print_line('{0} - {1}'.format(project.as_dict()['id'],
project.as_dict()['path']))
def parse_arguments():
"""
Parses command line arguments.
"""
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=textwrap.dedent('''\
gitlab-to-pentext - imports and updates gitlab issues into PenText (XML) format
Copyright (C) 2015-2016 Radically Open Security (Peter Mosmans)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.'''))
parser.add_argument('--closed', action='store',
help='take closed issues into account')
parser.add_argument('--dry-run', action='store_true',
help='do not write anything, only output on screen')
parser.add_argument('--issues', action='store',
help='list issues for a given project')
parser.add_argument('--overwrite', action='store_true',
help='overwrite existing issues')
parser.add_argument('--projects', action='store_true',
help='list gitlab projects')
parser.add_argument('-v', '--verbose', action='store_true',
help='increase output verbosity')
parser.add_argument('-y', action='store_true',
help='assume yes on all questions, write findings')
if len(sys.argv) == 1:
parser.print_help()
return vars(parser.parse_args())
def preflight_checks():
"""
Checks if all tools are there.
Exits with 0 if everything went okilydokily.
"""
try:
gitserver = gitlab.Gitlab.from_config('remote')
gitserver.auth()
except gitlab.config.GitlabDataError as exception:
print_error('could not connect {0}'.format(exception), -1)
return gitserver
def print_error(text, result=False):
"""
Prints error message.
When @result, exits with result.
"""
if len(text):
print_line('[-] ' + text, True)
if result:
sys.exit(result)
def print_line(text, error=False):
"""
Prints text, and flushes stdout and stdin.
When @error, prints text to stderr instead of stdout.
"""
if not error:
print(text)
else:
print(text, file=sys.stderr)
sys.stdout.flush()
sys.stderr.flush()
def print_status(text, options=False):
"""
Prints status message if options array is given and contains 'verbose'.
"""
if options and options['verbose']:
print_line('[*] ' + str(text))
def valid_filename(filename):
"""
Return a valid filename.
"""
result = ''
for char in filename.strip():
if char in [':', '/', '.', '\\', ' ', '[', ']', '(', ')', '\'']:
if len(char) and not result.endswith('-'):
result += '-'
else:
result += char
return result.lower()
def main():
"""
The main program.
"""
options = parse_arguments()
gitserver = preflight_checks()
if options['projects']:
list_projects(gitserver)
if options['issues']:
list_issues(gitserver, options)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,551 @@
#!/usr/bin/env python
"""
Cross-checks findings, validates XML files, offerte and report files.
This script is part of the PenText framework
https://pentext.org
Copyright (C) 2015-2016 Radically Open Security
https://www.radicallyopensecurity.com
Author(s): Peter Mosmans
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
"""
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import argparse
import mmap
import os
import re
import subprocess
import sys
import textwrap
import xml.sax
try:
from lxml import etree as ElementTree
except ImportError as exception:
print('[-] This script needs lxml',
file=sys.stderr)
print("Install lxml with: sudo pip install lxml", file=sys.stderr)
sys.exit(-1)
# When set to True, the report will be validated using docbuilder
DOCBUILDER = False
VOCABULARY = 'project-vocabulary.pws'
# Snippets may contain XML fragments without the proper entities
EXAMPLEDIR = 'examples/'
NOT_CAPITALIZED = ['a', 'an', 'and', 'as', 'at', 'but', 'by', 'for', 'in',
'nor', 'of', 'on', 'or', 'the', 'to', 'up']
SNIPPETDIR = 'snippets/'
TEMPLATEDIR = 'templates/'
OFFERTE = '/offerte.xml'
REPORT = '/report.xml'
WARN_LINE = 80 # There should be a separation character after x characters...
MAX_LINE = 86 # ... and before y
if DOCBUILDER:
import docbuilder_proxy
import proxy_vagrant
try:
import aspell
except:
print('[-] aspell not installed: spelling not available')
def parse_arguments():
"""
Parses command line arguments.
"""
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description=textwrap.dedent('''\
validate_report - validates offer letters and reports
Copyright (C) 2015-2016 Radically Open Security (Peter Mosmans)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.'''))
parser.add_argument('-a', '--all', action='store_true',
help='Perform all checks')
parser.add_argument('--auto-fix', action='store_true',
help='Try to automatically correct issues')
parser.add_argument('-c', '--capitalization', action='store_true',
help='Check capitalization')
parser.add_argument('--debug', action='store_true',
help='Show debug information')
parser.add_argument('--edit', action='store_true',
help='Open files with issues using an editor')
parser.add_argument('--learn', action='store_true',
help='Store all unknown words in dictionary file')
parser.add_argument('--long', action='store_true',
help='Check for long lines')
parser.add_argument('--offer', action='store_true',
help='Validate offer master file')
parser.add_argument('--spelling', action='store_true',
help='Check spelling')
parser.add_argument('-v', '--verbose', action='store_true',
help='increase output verbosity')
parser.add_argument('--no-report', action='store_true',
help='Do not validate report master file')
parser.add_argument('--quiet', action='store_true',
help='Don\'t output status messages')
return vars(parser.parse_args())
def validate_spelling(tree, filename, options):
"""
Checks spelling of text within tags.
If options['learn'], then unknown words will be added to the dictionary.
"""
result = True
try:
speller = aspell.Speller(('lang', 'en'),
('personal-dir', '.'),
('personal', VOCABULARY))
except: # some versions of aspell use a different path
speller = aspell.Speller(('lang', 'en'),
('personal-path', './' + VOCABULARY))
if options['debug']:
[print(i[0] + ' ' + str(i[2]) + '\n') for i in speller.ConfigKeys()]
try:
root = tree.getroot()
for section in root.iter():
if section.text and isinstance(section.tag, basestring) and \
section.tag not in ('a', 'code', 'monospace', 'pre'):
for word in re.findall('([a-zA-Z]+\'?[a-zA-Z]+)', section.text):
if not speller.check(word):
if options['learn']:
speller.addtoPersonal(word)
else:
result = False
print('[-] Misspelled (unknown) word {0} in {1}'.
format(word.encode('utf-8'), filename))
if options['learn']:
speller.saveAllwords()
except aspell.AspellSpellerError as exception:
print('[-] Spelling disabled ({0})'.format(exception))
return result
def all_files():
"""
Returns a list of all files contained in the git repository.
"""
cmd = ['git', 'ls-files']
process = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
return process.stdout.read().splitlines()
def open_editor(filename):
if sys.platform in ('linux', 'linux2'):
editor = os.getenv('EDITOR')
if editor:
print('{0} {1}'.format(editor, filename))
sys.stdout.flush()
subprocess.call([editor, '"{0}"'.format(filename)], shell=True)
else:
subprocess.call('xdg-open', filename)
elif sys.platform == "darwin":
subprocess.call(['open', filename])
elif sys.platform == "win32":
os.system('"{0}"'.format(filename.replace('/', os.path.sep)))
def validate_files(filenames, options):
"""
Checks file extensions and calls appropriate validator function.
Returns True if all files validated succesfully.
"""
result = True
masters = []
findings = []
non_findings = []
scans = []
for filename in filenames:
if (filename.lower().endswith('.xml') or
filename.lower().endswith('xml"')):
if SNIPPETDIR not in filename and TEMPLATEDIR not in filename:
if (OFFERTE in filename and options['offer']) or \
(REPORT in filename and not options['no_report']):
masters.append(filename)
# try:
type_result, xml_type = validate_xml(filename, options)
result = result and type_result
if 'non-finding' in xml_type:
non_findings.append(filename)
else:
if 'finding' in xml_type:
findings.append(filename)
else:
if 'scans' in xml_type:
scans.append(filename)
if len(masters):
for master in masters:
result = validate_master(master, findings, non_findings, scans, options) and result
return result
def print_output(options, stdout, stderr=None):
"""
Prints out standard out and standard err using the verboseprint function.
"""
if stdout and options['verbose']:
print('[+] {0}'.format(stdout))
if stderr and options['verbose']:
print('[-] {0}'.format(stderr))
def validate_report():
"""
Validates XML report file by trying to build it.
Returns True if the report was built successful.
"""
host, command = docbuilder_proxy.read_config(docbuilder_proxy.CONFIG_FILE)
command = command + ' -c'
return proxy_vagrant.execute_command(host, command)
def validate_xml(filename, options):
"""
Validates XML file by trying to parse it.
Returns True if the file validated successfully.
"""
result = True
xml_type = ''
# crude check whether the file is outside the pentext framework
if 'notes' in filename:
return result, xml_type
print_output(options, 'Validating XML file: {0}'.format(filename))
try:
with open(filename, 'rb') as xml_file:
xml.sax.parse(xml_file, xml.sax.ContentHandler())
tree = ElementTree.parse(filename, ElementTree.XMLParser(strip_cdata=False))
type_result, xml_type = validate_type(tree, filename, options)
result = validate_long_lines(tree, filename, options) and result and type_result
if options['edit'] and not result:
open_editor(filename)
except (xml.sax.SAXException, ElementTree.ParseError) as exception:
print('[-] validating {0} failed ({1})'.format(filename, exception))
result = False
except IOError as exception:
print('[-] validating {0} failed ({1})'.format(filename, exception))
result = False
return result, xml_type
def get_all_text(node):
"""
Retrieves all text within tags.
"""
text_string = node.text or ''
for element in node:
text_string += get_all_text(element)
if node.tail:
text_string += node.tail
return text_string.strip()
def is_capitalized(line):
"""
Checks whether all words in @line start with a capital.
Returns True if that's the case.
"""
return not line or line.strip() == capitalize(line)
def capitalize(line):
"""
Returns a capitalized version of @line, where the first word and all other
words not in NOT_CAPITALIZED are capitalized.
"""
capitalized = ''
for word in line.strip().split():
if word not in NOT_CAPITALIZED or not len(capitalized):
word = word[0].upper() + word[1:]
capitalized += word + ' '
return capitalized.strip()
def validate_type(tree, filename, options):
"""
Performs specific checks based on type.
Currently only finding and non-finding are supported.
"""
result = True
fix = False
root = tree.getroot()
xml_type = root.tag
attributes = []
tags = []
if options['spelling']:
result = validate_spelling(tree, filename, options)
if xml_type == 'pentest_report':
attributes = ['findingCode']
if xml_type == 'finding':
attributes = ['threatLevel', 'type', 'id']
tags = ['title', 'description', 'technicaldescription', 'impact',
'recommendation']
if xml_type == 'non-finding':
attributes = ['id']
tags = ['title']
if not len(attributes):
return result, xml_type
for attribute in attributes:
if attribute not in root.attrib:
print('[A] Missing obligatory attribute in {0}: {1}'.
format(filename, attribute))
if attribute == 'id':
root.set(attribute, filename)
fix = True
else:
result = False
else:
if attribute == 'threatLevel' and root.attrib[attribute] not in \
('Low', 'Moderate', 'Elevated', 'High', 'Extreme'):
print('[-] threatLevel is not Low, Moderate, High, Elevated or Extreme: {0}'.
format(root.attrib[attribute]))
result = False
if attribute == 'type' and (options['capitalization'] and not \
is_capitalized(root.attrib[attribute])):
print('[A] Type missing capitalization (expected {0}, read {1})'.
format(capitalize(root.attrib[attribute]),
root.attrib[attribute]))
root.attrib[attribute] = capitalize(root.attrib[attribute])
fix = True
for tag in tags:
if root.find(tag) is None:
print('[-] Missing tag in {0}: {1}'.format(filename, tag))
result = False
continue
if not get_all_text(root.find(tag)):
print('[-] Empty tag in {0}: {1}'.format(filename, tag))
result = False
continue
if tag == 'title' and (options['capitalization'] and \
not is_capitalized(root.find(tag).text)):
print('[A] Title missing capitalization in {0} (expected {1}, read {2})'.
format(filename, capitalize(root.find(tag).text),
root.find(tag).text))
root.find(tag).text = capitalize(root.find(tag).text)
fix = True
all_text = get_all_text(root.find(tag))
if tag == 'description' and all_text.strip()[-1] != '.':
print('[A] Description missing final dot in {0}: {1}'.format(filename, all_text))
root.find(tag).text = all_text.strip() + '.'
fix = True
if fix:
if options['auto_fix']:
print('[+] Automatically fixed {0}'.format(filename))
tree.write(filename)
else:
print('[+] NOTE: Items with [A] can be fixed automatically, use --auto-fix')
return (result and not fix), xml_type
def validate_long_lines(tree, filename, options):
"""
Checks whether pre or code section contains lines longer than MAX_LINE characters
Returns True if the file validated successfully.
"""
if not options['long']:
return True
result = True
fix = False
root = tree.getroot()
for pre_section in [j for section in ('pre', 'code') for j in root.iter(section)]:
if pre_section.text:
fixed_text = ''
for line in pre_section.text.splitlines():
while len(line) > MAX_LINE:
result = False
print('[-] {0} Line inside {1} too long: {2}'.
format(filename, section, line.encode('utf-8')[MAX_LINE:]))
cutpoint = MAX_LINE
for split in [' ', '"', '\'', '=', '-', ';']:
if split in line.encode('utf-8')[WARN_LINE:MAX_LINE]:
cutpoint = line.find(split, WARN_LINE, MAX_LINE)
fix = True
fixed_line = line[:cutpoint] + '\n'
print('cutted line {0}'.format(line))
line = line[cutpoint:]
fixed_text += fixed_line.encode('utf-8')
print('[A] can be fixed (breaking at {0}): {1}'.format(cutpoint, fixed_line))
fixed_text += line + '\n'
if fix and options['auto_fix']:
print('[+] Automatically fixed {0}'.format(filename))
pre_section.text = fixed_text
print(fixed_text)
tree.write(filename)
close_file(filename)
return result
def validate_master(filename, findings, non_findings, scans, options):
"""
Validates master file.
"""
result = True
include_findings = []
include_nonfindings = []
print_output(options, 'Validating master file {0}'.format(filename))
try:
xmltree = ElementTree.parse(filename,
ElementTree.XMLParser(strip_cdata=False))
if not find_keyword(xmltree, 'TODO', filename):
print('[-] Keyword checks failed for {0}'.format(filename))
result = False
print_output(options, 'Performing cross check on findings, non-findings and scans...')
for finding in findings:
if not cross_check_file(filename, finding):
print('[A] Cross check failed for finding {0}'.
format(finding))
include_findings.append(finding)
result = False
for non_finding in non_findings:
if not cross_check_file(filename, non_finding):
print('[A] Cross check failed for non-finding {0}'.
format(non_finding))
include_nonfindings.append(non_finding)
result = False
if result:
print_output(options, 'Cross checks successful')
except (ElementTree.ParseError, IOError) as exception:
print('[-] validating {0} failed ({1})'.format(filename, exception))
result = False
if not result:
if options['auto_fix']:
add_include(filename, 'findings', include_findings)
add_include(filename, 'nonFindings', include_nonfindings)
close_file(filename)
print('[+] Automatically fixed {0}'.format(filename))
else:
print('[+] NOTE: Items with [A] can be fixed automatically, use --auto-fix')
return result
def report_string(report_file):
"""
Return the report_file into a big memory mapped string.
"""
try:
report = open(report_file)
return mmap.mmap(report.fileno(), 0, access=mmap.ACCESS_READ)
except IOError as exception:
print('[-] Could not open {0} ({1})'.format(report_file, exception))
sys.exit(-1)
def cross_check_file(filename, external):
"""
Checks whether filename contains a cross-check to the file external.
"""
result = True
report_text = report_string(filename)
if report_text.find(external) == -1:
print('[-] could not find a reference in {0} to {1}'.format(filename, external))
result = False
return result
def add_include(filename, identifier, findings):
"""
Adds XML include based on the identifier ('findings' or 'nonFindings').
"""
tree = ElementTree.parse(filename, ElementTree.XMLParser(strip_cdata=False))
root = tree.getroot()
for section in tree.iter('section'):
if section.attrib['id'] == identifier:
finding_section = section
if finding_section is not None:
for finding in findings:
new_finding = ElementTree.XML('<placeholderinclude href="../{0}"/>'.format(finding))
finding_section.append(new_finding)
tree.write(filename, encoding="utf-8", xml_declaration=True, pretty_print=True)
def close_file(filename):
"""
Replace placeholder with proper XML include.
"""
f = open(filename, 'r')
filedata = f.read()
f.close()
newdata = filedata.replace("placeholderinclude", "xi:include")
fileout = filename
f = open(fileout, 'w')
f.write(newdata)
f.close()
tree = ElementTree.parse(filename, ElementTree.XMLParser(strip_cdata=False))
tree.write(filename, encoding="utf-8", xml_declaration=True, pretty_print=True)
def find_keyword(xmltree, keyword, filename):
"""
Finds keywords in an XML tree.
This function needs lots of TLC.
"""
result = True
section = ''
for tag in xmltree.iter():
if tag.tag == 'section' and' id' in tag.attrib:
section = 'in {0}'.format(tag.attrib['id'])
if tag.text:
if keyword in tag.text:
print('[-] {0} found in {1} {2}'.format(keyword, filename, section))
result = False
return result
def main():
"""
The main program. Cross-checks, validates XML files and report.
Returns True if the checks were successful.
"""
# we want to print pretty Unicode characters
reload(sys)
sys.setdefaultencoding('utf-8')
options = parse_arguments()
if options['all']:
options['capitalization'] = True
options['long'] = True
if options['learn']:
print_output(options, 'Adding unknown words to {0}'.format(VOCABULARY))
# if options['spelling']:
# if not os.path.exists(VOCABULARY):
# print_output(options, 'Creating project-specific vocabulary file {0}'.
# format(VOCABULARY))
# options['learn'] = True
print_output(options, 'Validating all XML files...')
result = validate_files(all_files(), options)
if result:
print_output(options, 'Validation checks successful')
if DOCBUILDER:
print_output(options, 'Validating report build...')
result = validate_report() and result
if result:
print('[+] Succesfully validated everything. Good to go')
else:
print('[-] Errors occurred')
if options['spelling'] and options['learn']:
print('[*] Don\'t forget to check the vocabulary file {0}'.
format(VOCABULARY))
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,271 @@
# Description:
# Allows hubot to execute PenText framework commands
#
# Dependencies:
# The PenText framework
#
# Configuration:
# See the various handlers in bash/
#
# Usage:
# build
# Builds a .pdf document of <type> based on files in <repository>. The file is stored in target/ of the specified repository.
# Usage: build <type> <repository> [namespace=ros] [branch=master] [-v]
# <type> Can be either report or quote
# <repository> Specifies the name of the gitlab repository where the files needed to do the job are located.
# [namespace] This optional parameter refers to the gitlab user or group this repository is part of. Defaults to ros
# [branch] This optional parameter specifies which branch to use. Defaults to master.
# [-v] Specifying this flag will yield verbose output.
#
# convert
# Converts gitlab issues in <respository> to xml files. The issues must be open and need to be labelled with either finding or non-finding.
# Depending on the label, the xml files will be put in either the finding/ or non-finding/ directory in the repository.
# Usage: convert <repository> [--closed] [--dry-run] [--issues] [--projects] [-v|--verbose] [-y]
# <repository> Specifies the name of the gitlab repository where the files needed to do the job are located.
# [--closed] If specified, will include closed issues
# [--dry-run] If specified, will not write xml files, but only displays output on screen
# [--issues] If specified, will list issues in given <repository>
# [--projects] If specified, will list gitlab repositories
# [-v|--verbose] If specified, will yield verbose output
# [-y] Assumes yes on all questions
#
# validate
# Validates the XML structure of a reports or quote to be able to generate a .pdf file. (See build command)
# Usage: validate <repository> [-a|-all] [--autofix] [-c|--capitalization] [--debug] [--edit] [--learn] [--long] [--offer] [--spelling] [-v|--verbose] [--no-report] [--quiet]
# <repository> Specifies the name of the gitlab repository where the files needed to do the job are located.
# [-a|-all] Perform all checks
# [--autofix] Try to automatically correct issues
# [-c|--capitalization] Check capitalization
# [--debug] Show debug information
# [--edit] Open files with issues using an editor
# [--learn] Store all unknown words in dictionary file
# [--long] Check for long lines
# [--offer] Validate offer master file
# [--spelling] Check spelling
# [-v|--verbose] If specified, will yield verbose output
# [--no-report] Do not validate report master file
# [--quiet] Don't output status messages
#
#
# Commands:
# hubot build <type> <repo> <target> - Builds a .pdf file from <target> in <repo>
# hubot convert <repo> <target> - Builds a .xml file from <target> in <repo>
# hubot invoice <repo> <target> - Builds pdf invoice from quote
# hubot quickscope <repo> <namespace> [branch=MASTER] - Converts quickscope into quotation
# hubot startpentest <name> - Bootstraps a pentest
# hubot startquote <name> - Bootstraps a quotation
# hubot validate <parms..> - Validates a report/quotation
# hubot usage [command] - Displays usage information for command. If no command is specified, supported commands are displayed.
#
# Author:
# Peter Mosmans
# John Sinteur
# Daniel Attevelt
#
# This is part of the PenText framework
#
USAGE_LABEL = '# Usage:'
Fs = require 'fs'
Path = require 'path'
admins = ['peter']
###
This will initialise the usage information for the chatops command used in the pentext framework
It will parse the file comment sections in search of usage information. See above for an example
! This section should always be above the commands section and should always be terminated by two consecutive #s !
! Only single word commands are supported !
robot gets a new property .usages which can be used later on
###
init_usage = (robot) ->
robot.usages = []
load_scripts(robot)
###
This will load all the scripts in the same folder as this one. It will then proceed
to parsing those scripts in order to extract the rosbot command usage information
###
load_scripts = (robot) ->
if Fs.existsSync(__dirname)
for file in Fs.readdirSync(__dirname).sort()
fullPath = Path.join __dirname, file
robot.logger.info "File: " + fullPath
body = Fs.readFileSync fullPath, 'utf-8'
parse_scripts(robot, body)
###
This function will parse the script for usage information.
It will do so by looping through every comment line until it hits the # Usage: label
Then it will start to look for a command tag that is identified by:
# (3 spaces) <command>. The will let the function know it's dealing with a command identifiers.
# (5 spaces) <infoline> lets the function know it's dealing with info line that should go together with the previously encountered command.
The sequence is broken by two sequential empty comment lines. e.g.:
#
#
###
parse_scripts = (robot, body) ->
parsing_usage = false
current_command = null
# https://regex101.com
cmd_regex = /^#[ ]{3}[\S]+/i
info_regex = /^#[ ]{5}[\S]+/i
# Loop through each comment line until there is none.
for line in body.split "\n"
break unless line[0] is '#' or line.substr(0, 2) is '//'
# Determine if we've reached the Usage: tag
if line.indexOf(USAGE_LABEL) != -1
parsing_usage = true
if parsing_usage
# Pre-cleaning ...
cleanedLine = line.replace(/^(#|\/\/)\s?/, "").trim()
# Are we dealing with a command?
if line.match cmd_regex
current_command = cleanedLine
robot.usages[current_command] = []
# Are we dealing with an info line ?
if line.match info_regex
if not robot.usages[current_command]
robot.logger.debug "Error parsing chatpos usage info: found info line, but no command line"
else
robot.usages[current_command].push cleanedLine
# Detects two sequential #'s and quits parsing usage when it does
if cleanedLine.length == 0
if current_command == null
parsing_usage = false
else
current_command = null
# Sanity check
robot.logger.info "--- Following usage information parsed ----"
for command, lines of robot.usages
for index, line of lines
robot.logger.info "* #{command} : #{line}"
module.exports = (robot) ->
run_cmd = (cmd, args, cb ) ->
spawn = require("child_process").spawn
child = spawn(cmd, args)
child.stdout.on "data", (buffer) -> cb buffer.toString()
child.stderr.on "data", (buffer) -> cb buffer.toString()
init_usage(robot)
# ***************************************************************************
# ChatOps command handlers
# ***************************************************************************
robot.respond /build (.*)/i, id:'chatops.build', (msg) ->
msg.match[0] = msg.match[0].replace(/^[a-z0-9]+$/i);
msg.match.shift();
args = msg.match[0].split(" ");
cmd = "bash/handler_build";
run_cmd cmd, args, (text) -> msg.send text.replace("\n","");
robot.respond /convert (.*)/i, id:'chatops.convert', (msg) ->
msg.match[0] = msg.match[0].replace(/^[a-z0-9]+$/i);
msg.match.shift();
args = msg.match[0].split(" ");
cmd = "bash/handler_convert";
run_cmd cmd, args, (text) -> msg.send text.replace("\n","");
robot.respond /invoice (.*)/i, id:'chatops.invoice', (msg) ->
msg.match[0] = msg.match[0].replace(/^[a-z0-9]+$/i);
msg.match.shift();
args = msg.match[0].split(" ");
cmd = "bash/handler_invoice";
run_cmd cmd, args, (text) -> msg.send text.replace("\n","");
robot.respond /quickscope (.*)/i, id:'chatops.quickscope', (msg) ->
msg.match[0] = msg.match[0].replace(/^[a-z0-9]+$/i);
msg.match.shift();
args = msg.match[0].split(" ");
cmd = "bash/handler_quickscope";
run_cmd cmd, args, (text) -> msg.send text.replace("\n","");
robot.respond /startpentest (.*)/i, id:'chatops.startpentest', (msg) ->
msg.match[0] = msg.match[0].replace(/^[a-z0-9]+$/i);
msg.match.shift();
args = msg.match[0].split(" ");
if args[0].substring(0, 4) == "off-"
msg.send "[-] Please do not start pen names with off-";
return;
if args[0].substring(0, 4) == "pen-"
msg.send "[-] Please do not start pen names with pen-";
return;
roomName = "pen-" + args[0];
newroom = robot.adapter.callMethod('createPrivateGroup', roomName, admins)
msg.send "[+] new channel created - Added " + admins + " to the new room " + roomName
newroom.then (roomId) =>
robot.messageRoom roomId.rid, "@all hello!"
args[1] = roomId.rid
cmd = "bash/handler_pentest";
run_cmd cmd, args, (text) -> msg.send text.replace("\n","");
robot.respond /startquote (.*)/i, id:'chatops.startquote',(msg) ->
msg.match[0] = msg.match[0].replace(/^[a-z0-9]+$/i);
msg.match.shift();
args = msg.match[0].split(" ");
if args[0].substring(0, 4) == "pen-"
msg.send "[-] Please do not start quote names with pen-";
return;
if args[0].substring(0, 4) == "off-"
msg.send "[-] Please do not start quote names with off-";
return;
roomName = "off-" + args[0]
newroom = robot.adapter.callMethod('createPrivateGroup', roomName, admins)
msg.send "[+] new channel created - Added " + admins + " to the new room " + roomName
newroom.then (roomId) =>
robot.messageRoom roomId.rid, "@all hello!"
cmd = "bash/handler_quote";
run_cmd cmd, args, (text) -> msg.send text.replace("\n","");
robot.respond /validate (.*)/i, id:'chatops.validate', (msg) ->
msg.match[0] = msg.match[0].replace(/^[a-z0-9]+$/i);
msg.match.shift();
args = msg.match[0].split(" ");
cmd = "bash/handler_validate";
run_cmd cmd, args, (text) -> msg.send text.replace("\n","");
# Handler for the usage command.
# Note that the regex option group (.*) also captures the space after the command
# This allows for the case when there is no command specified, supported commands can be displayed
robot.respond /usage(.*)/i, id:'chatops.usage', (msg) ->
msg.match[0] = msg.match[0].replace(/^[a-z0-9]+$/i);
msg.match.shift();
args = msg.match[0].trim().split(" ");
command = args[0]
# If not command is provided, return information on which commands can be handled
if command.trim().length == 0
msg.send "I can provide usage information for the following commands:"
for command of robot.usages
msg.send command
msg.send "Issue the command: usage <command> for usage information for this command"
return
# This deals when unsupported commands
if not robot.usages[command]
msg.send "I have no usage information for: " + command
return
# All odd case have been dealt with, let's get down to business
for index, line of robot.usages[command]
msg.send line

56
pull_upstream_changes.sh Normal file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/env bash
# pull_upstream_changes - Updates repo and applies upstream changes
#
# Copyright (C) 2016 Peter Mosmans [Radically Open Security]
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# File which has to exist in the target directory to qualify as target
FINGERPRINT="dtd"
# List of files and directories that need to be updated
SOURCEFILES="dtd xslt"
# Root directory within source repo
SOURCEROOT="xml"
## Don't change anything below this line
VERSION=0.6
source=$(dirname $(readlink -f $0))
target=$1
if [ -z "$target" ]; then
target=$(readlink -f .)
if [ "${target}" == "${source}" ]; then
echo "Usage: pull_upstream_changes [TARGET]"
echo " or run from within target directory"
exit
fi
fi
# Check if the target actually contains the repository
if [ ! -z ${FINGERPRINT} ] && [ ! -d $target/dtd ]; then
echo "[-] ${target} does not contain the correct repository"
exit
fi
# Update repository
echo "[*] Updating source repository (${source})..."
pushd "$source" >/dev/null && git pull && popd >/dev/null
# Only update newer files
echo "[*] Applying changes (if any)..."
for sourcefile in ${SOURCEFILES}; do
if [ -d "${source}/${SOURCEROOT}/${sourcefile}" ]; then
cp -prv ${source}/${SOURCEROOT}/${sourcefile} $target/
else
cp -pv ${source}/${SOURCEROOT}/${sourcefile} $target/${sourcefile}
fi
done
echo "[+] Done"

View File

@@ -28,7 +28,7 @@ Download Saxon Home Edition (HE) 9.6 **for Java** at: http://saxon.sourceforge.n
### FOP
Download Apache FOP 1.1 at https://xmlgraphics.apache.org/fop/download.html and unzip.
Download Apache FOP 2.1 at https://xmlgraphics.apache.org/fop/download.html and unzip.
### Fonts

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<quickscope xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xml="http://www.w3.org/XML/1998/namespace">
<!-- Today's date -->
<version date="2015-01-01"/>
<!-- YYYY-MM-DD -->
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../dtd/quickscope.xsd">
<!-- COMPANY INFO -->
<xi:include href="client_info.xml"/>
@@ -20,26 +20,26 @@
<!-- Which targets will need to be tested?
(one <target> element for each piece of software/service/server address/location...), delete/add as necessary -->
<targets>
<target>target1.sittingduck.com</target>
<target>target2.sittingduck.com</target>
<target>FishInABarral App</target>
<target>target1.target.com</target>
<target>target2.target.com</target>
</targets>
</meta>
<!-- Some information about any third parties involved with the software/service to be tested, if applicable.
If not applicable, delete the whole <third_party> element. If more parties are needed, add <third_party> elements -->
<!-- Do we need permission from third parties? Insert as many <third_party> elements as needed under this comment -->
<third_party>
<full_name>HotshotDevs Inc.</full_name>
<short_name>HotshotDevs</short_name>
<full_name>Third Party BV</full_name>
<short_name>Third Party</short_name>
<!-- Name of the person who will need to sign the waiver for this vendor -->
<waiver_rep>Hotshot Dev Lawyer</waiver_rep>
<address>Silicon Valley St. 50</address>
<city>San Francisco</city>
<country>US</country>
<waiver_rep>TP Waiver Rep</waiver_rep>
<address>TP Street 123</address>
<city>TP City</city>
<country>TP Country</country>
</third_party>
<pentest_info>
<!-- How long would you like the test to be? (in days) -->
<days>10</days>
<days>6</days>
<!-- How many mandays (if you don't know, try days * number of assigned pentesters) -->
<mandays>12</mandays>
<!-- Service execution (Use one of the following values: time-boxed, subscription) -->
<nature>time-boxed</nature>
<!-- Testing type (Use one of the following values: crystal-box, black-box, grey-box) -->
@@ -52,10 +52,11 @@
<delivery>TBD</delivery>
<!-- Do you need/want a code audit? (possible values: yes/no), only for pentest -->
<codeaudit perform="yes"/>
<!-- Is there an application that needs to be tested? Type its name below. If not, please DELETE <application_name> element -->
<application_name>FishInABarrel</application_name>
<!-- Is there an application that needs to be tested? Add an <application_name> element below. -->
<application_name>AppToTest</application_name>
<!-- rate (to be filled in by ROS ;) -->
<rate>1000000</rate>
<rate>40000</rate>
</pentest_info>
</quickscope>

View File

@@ -132,6 +132,7 @@
<xs:element name="invoice_mail" type="emailAddress"/>
<xs:element name="duration" type="xs:nonNegativeInteger"/>
<xs:element name="mandays" type="xs:nonNegativeInteger"/>
<xs:element name="test_planning" type="xs:string"/>
<xs:element name="report_due" type="xs:string"/>
<xs:element name="nature" type="xs:string"/>

View File

@@ -1,20 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd" />
<xs:import namespace="http://www.w3.org/2001/XInclude" schemaLocation="http://www.w3.org/2001/XInclude/XInclude.xsd"/>
<xs:import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
<xs:import namespace="http://www.w3.org/2001/XInclude"
schemaLocation="http://www.w3.org/2001/XInclude/XInclude.xsd"/>
<xs:include schemaLocation="common.xsd"/>
<xs:element name="generic_document">
<xs:complexType>
<xs:sequence>
<xs:element ref="meta"/>
<xs:element ref="generate_index"/>
<xs:element ref="section" maxOccurs="unbounded"/>
<xs:element ref="appendix" maxOccurs="unbounded"/>
<xs:element ref="appendix" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="meta">
<xs:complexType>
<xs:sequence>
@@ -27,9 +29,9 @@
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="subtitle" type="xs:string"/>
<xs:element name="collaborators">
<xs:complexType>
<xs:sequence>
@@ -38,7 +40,7 @@
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="reviewers">
<xs:complexType>
<xs:sequence>
@@ -46,9 +48,9 @@
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="reviewer" type="xs:string"/>
<xs:element name="approver">
<xs:complexType>
<xs:sequence>
@@ -57,10 +59,10 @@
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="bio" type="xs:string"/>
<xs:element name="classification" type="xs:NCName"/>
<xs:element name="section">
<xs:complexType>
<xs:sequence>
@@ -84,7 +86,7 @@
<xs:attribute ref="xml:base"/>
</xs:complexType>
</xs:element>
<xs:element name="appendix">
<xs:complexType>
<xs:sequence>
@@ -105,10 +107,18 @@
<xs:attribute ref="visibility" use="optional"/>
</xs:complexType>
</xs:element>
<!-- Placeholders -->
<xs:complexType name="block" mixed="true">
<xs:choice maxOccurs="unbounded">
<xs:group ref="inline-all"/>
<xs:group ref="placeholders"/>
</xs:choice>
<xs:attribute ref="xml:base"/>
</xs:complexType>
<!-- Placeholders -->
<xs:group name="placeholders">
<xs:choice></xs:choice>
<xs:choice/>
</xs:group>
</xs:schema>

View File

@@ -14,15 +14,16 @@
<xs:element ref="servicesdelivered" minOccurs="1" maxOccurs="1"/>
<xs:element ref="additionalcosts" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute ref="xml:lang"/>
<xs:attribute name="invoice_no" type="xs:string"/>
<xs:attribute name="date" type="xs:date" use="optional"/>
<xs:attribute name="denomination" use="required">
<xs:attribute name="denomination" use="optional" default="eur">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="eur"/>
<xs:enumeration value="gbp"/>
<xs:enumeration value="usd"/>
</xs:restriction>
<xs:enumeration value="eur"/>
<xs:enumeration value="usd"/>
<xs:enumeration value="gbp"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>

View File

@@ -44,6 +44,7 @@
<xs:complexType>
<xs:sequence>
<xs:element ref="duration"/>
<xs:element ref="mandays"/>
<xs:element ref="test_planning"/>
<xs:element ref="report_due"/>
<xs:element ref="nature"/>

78
xml/dtd/quickscope.xsd Normal file
View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude">
<xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd" />
<xs:import namespace="http://www.w3.org/2001/XInclude" schemaLocation="http://www.w3.org/2001/XInclude/XInclude.xsd"/>
<xs:include schemaLocation="common.xsd"/>
<xs:element name="quickscope">
<xs:complexType>
<xs:sequence>
<xs:element ref="client"/>
<xs:element ref="meta"/>
<xs:element ref="third_party" minOccurs="0"/>
<xs:element ref="pentest_info"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="meta">
<xs:complexType>
<xs:sequence>
<xs:element ref="offer_language"/>
<xs:element ref="offer_type"/>
<xs:element ref="requested_service"/>
<xs:element ref="targets"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="offer_language" type="xs:NCName"/>
<xs:element name="offer_type" type="xs:NCName"/>
<xs:element name="requested_service" type="xs:string"/>
<xs:element name="third_party">
<xs:complexType>
<xs:sequence>
<xs:element ref="full_name" minOccurs="1"/>
<xs:element ref="short_name"/>
<xs:element ref="waiver_rep"/>
<xs:element ref="address"/>
<xs:element ref="city"/>
<xs:element ref="country"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="pentest_info">
<xs:complexType>
<xs:sequence>
<xs:element ref="days"/>
<xs:element ref="mandays"/>
<xs:element ref="nature"/>
<xs:element ref="type"/>
<xs:element ref="planning"/>
<xs:element ref="delivery"/>
<xs:element ref="codeaudit"/>
<xs:element ref="application_name" minOccurs="0"/>
<xs:element ref="rate"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="days" type="xs:integer"/>
<xs:element name="mandays" type="xs:integer"/>
<xs:element name="planning" type="xs:NCName"/>
<xs:element name="delivery" type="xs:NCName"/>
<xs:element name="codeaudit">
<xs:complexType>
<xs:attribute name="perform" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
<xs:element name="application_name" type="xs:NCName"/>
<xs:element name="rate" type="xs:integer"/>
<xs:complexType name="block" mixed="true">
<xs:choice maxOccurs="unbounded">
<xs:group ref="inline-all"/>
<xs:group ref="placeholders"/>
</xs:choice>
<xs:attribute ref="xml:base"/>
</xs:complexType>
<xs:group name="placeholders">
<xs:choice/>
</xs:group>
</xs:schema>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude">
<xs:import schemaLocation="pentestreport.xsd"/>
<xs:import namespace="http://www.w3.org/2001/XInclude" schemaLocation="xi.xsd"/>
<xs:attribute name="noNamespaceSchemaLocation"/>
</xs:schema>

View File

@@ -79,7 +79,7 @@ the location of this file.
<!--
<directory recursive="true">/Library/Fonts/</directory>
-->
<font kerning="yes" embed-url="LiberationSansNarrow-Regular-webfont.ttf">
<font kerning="yes" embed-url="LiberationSansNarrow-Regular.ttf">
<font-triplet name="LiberationSansNarrow" style="normal" weight="normal"/>
</font>
<font kerning="yes" embed-url="LiberationSansNarrow-Bold.ttf">

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<quickscope xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xml="http://www.w3.org/XML/1998/namespace">
<!-- Today's date -->
<version date="2015-01-01"/>
<!-- YYYY-MM-DD -->
<!-- CLIENT INFO -->
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../dtd/quickscope.xsd">
<!-- COMPANY INFO -->
<xi:include href="client_info.xml"/>
<!-- SERVICE INFO -->
@@ -16,29 +16,23 @@
<offer_type>pentest</offer_type>
<!-- Required service -->
<!-- Note: is only used when type is 'other', if offer_type is a specific type, service name will be taken from the localisation strings -->
<requested_service></requested_service>
<!-- Which targets will need to be tested?
(one <target> element for each piece of software/service/server address/location...), delete/add as necessary -->
<requested_service>penetration testing services</requested_service>
<!-- Which targets will need to be tested?
(one <target> element for each piece of software/service/server address/location...), delete/add as necessary -->
<targets>
<target></target>
<target></target>
</targets>
</meta>
<!-- Some information about any third parties involved with the software/service to be tested, if applicable.
If not applicable, delete the whole <third_party> element. If more parties are needed, add <third_party> elements -->
<third_party>
<full_name></full_name>
<short_name></short_name>
<!-- Name of the person who will need to sign the waiver for this vendor -->
<waiver_rep></waiver_rep>
<address></address>
<city></city>
<country></country>
</third_party>
<!-- Do we need permission from third parties? Insert as many <third_party> elements as needed under this comment -->
<!-- INSERT OPTIONAL THIRD PARTIES HERE -->
<!-- ___________________________________ -->
<pentest_info>
<!-- How long would you like the test to be? (in days) -->
<days></days>
<days>0</days>
<!-- How many mandays (if you don't know, try days * number of assigned pentesters) -->
<mandays>0</mandays>
<!-- Service execution (Use one of the following values: time-boxed, subscription) -->
<nature>time-boxed</nature>
<!-- Testing type (Use one of the following values: crystal-box, black-box, grey-box) -->
@@ -51,8 +45,11 @@
<delivery>TBD</delivery>
<!-- Do you need/want a code audit? (possible values: yes/no), only for pentest -->
<codeaudit perform="yes"/>
<!-- Is there an application that needs to be tested? Type its name below. If not, please DELETE <application_name> element -->
<application_name></application_name>
<!-- Is there an application that needs to be tested? Add an <application_name> element below. -->
<!-- INSERT OPTIONAL APPLICATION NAME HERE -->
<!-- ___________________________________ -->
<!-- rate (to be filled in by ROS ;) -->
<rate>0</rate>

View File

@@ -1,120 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<pentest_report xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xsi:noNamespaceSchemaLocation="../dtd/pentestreport.xsd"
xml:lang="en"
findingCode="XXX">
<meta>
<title>Penetration Test Report</title>
<xi:include href="client_info.xml"/>
<targets><!--one target element per target-->
<target>dsfsd</target>
<target>adfsd</target>
</targets>
<collaborators>
<reviewers>
<reviewer>FirstName LastName</reviewer>
</reviewers>
<approver>
<name>Melanie Rieback</name>
<bio>Melanie Rieback is a former Asst. Prof. of Computer Science from the
VU, who is also the co-founder/CEO of Radically Open Security.</bio>
</approver>
<pentesters>
<pentester>
<name>FirstName LastName</name>
<bio>Info</bio>
</pentester>
</pentesters>
</collaborators>
<classification>Confidential</classification>
<version_history><!--needed for date on frontpage and in signature boxes; it is possible to add a new <version> after each review; in that case, make sure to update the date/time-->
<version number="auto" date="2016-08-25T10:00:00"><!--actual date-time here; you can leave the number attribute alone-->
<v_author>ROS Writer</v_author>
<!--name of the author here; for internal use only-->
<v_description>Initial draft</v_description>
<!--for internal use only-->
</version>
</version_history>
<xi:include href="snippets/company_info.xml"/>
</meta>
<generate_index/>
<section id="executiveSummary">
<title>Executive Summary</title>
<section id="introduction">
<title>Introduction</title>
<p>...</p>
<p>This report contains our findings as well as detailed explanations of exactly
how ROS performed the penetration test.</p>
</section>
<section id="scope">
<title>Scope of work</title>
<p>The scope of the penetration test was limited to the following target:</p>
<generate_targets/>
</section>
<section id="objectives">
<title>Project objectives</title>
<p>...</p>
</section>
<section id="timeline">
<title>Timeline</title>
<p>The Security Audit took place between X and Y, 2016.</p>
</section>
<xi:include href="resultsinanutshell.xml"/>
<section id="findingSummary">
<title>Summary of Findings</title>
<generate_findings/>
<!-- generated from Findings section -->
</section>
<section id="recommendationSummary">
<title>Summary of Recommendations</title>
<generate_recommendations/>
<!-- generated from Findings section -->
</section>
</section>
<xi:include href="snippets/report/methodology.xml"/>
<section id="recon">
<title>Reconnaissance and Fingerprinting</title>
<p>Through automated scans we were able to gain the following information about the
software and infrastructure. Detailed scan output can be found in the sections
below.</p>
<section id="scans">
<title>Automated Scans</title>
<p>As part of our active reconnaissance we used the following automated
scans:</p>
<ul><!--analyze_hosts - https://github.com/PeterMosmans/security-scripts-->
<li>nmap <a href="http://nmap.org">http://nmap.org</a>
</li>
<!--OWASP Zed Attack Proxy - https://github.com/zaproxy/zaproxy Skipfish https://code.google.com/p/skipfish/ sqlmap https://github.com/sqlmapproject/sqlmap testssl.sh
https://github.com/drwetter/testssl.sh-->
</ul>
</section>
</section>
<section id="techSummary">
<title>Pentest Technical Summary</title>
<section id="findings">
<title>Findings</title>
<p>We have identified the following issues:</p>
<!-- Listing of Findings (written by pentesters) -->
<!-- Extreme -->
<!-- High -->
<!-- Moderate -->
<!-- Elevated -->
<!-- Low -->
</section>
<section id="nonFindings">
<title>Non-Findings</title>
<p>In this section we list some of the things that were tried but turned out to
be dead ends.</p>
</section>
<!-- Listing of Non-Findings (written by pentesters) -->
</section>
<xi:include href="futurework.xml"/>
<xi:include href="conclusion.xml"/>
<appendix id="testteam">
<title>Testing team</title>
<generate_testteam/>
</appendix>
</pentest_report>

View File

@@ -55,6 +55,72 @@
<translation xml:lang="nl">VOOR</translation>
<translation xml:lang="en">FOR</translation>
</string>
<string id="page_kvk">
<translation xml:lang="nl">Kamer van Koophandel</translation>
<translation xml:lang="en">Chamber of Commerce</translation>
</string>
<string id="invoice_no">
<translation xml:lang="nl">Factuur nr.</translation>
<translation xml:lang="en">Invoice no.</translation>
</string>
<string id="invoice_fao">
<translation xml:lang="nl">T.a.v.</translation>
<translation xml:lang="en">F.a.o.</translation>
</string>
<string id="invoice_svcdeliv">
<translation xml:lang="nl">Geleverde diensten</translation>
<translation xml:lang="en">Services delivered</translation>
</string>
<string id="invoice_days">
<translation xml:lang="nl">daagse</translation>
<translation xml:lang="en">day</translation>
</string>
<string id="invoice_vat">
<translation xml:lang="nl">BTW</translation>
<translation xml:lang="en">VAT</translation>
</string>
<string id="invoice_vatno">
<translation xml:lang="nl">BTW-nummer</translation>
<translation xml:lang="en">VAT number</translation>
</string>
<string id="invoice_additional">
<translation xml:lang="nl">Extra gemaakte kosten</translation>
<translation xml:lang="en">Additional expenses</translation>
</string>
<string id="invoice_total">
<translation xml:lang="nl">Totaal te betalen</translation>
<translation xml:lang="en">Total amount to be paid</translation>
</string>
<string id="invoice_donation">
<translation xml:lang="nl">doneert > 90% van haar totale winst aan goede doelen.</translation>
<translation xml:lang="en">donates > 90% of its entire profits to
charity.</translation>
</string>
<string id="invoice_pleasepay">
<translation xml:lang="nl">Maak binnen 30 dagen het totale bedrag over op de volgende rekening:</translation>
<translation xml:lang="en">Please be so kind to pay within 30 days
by money transfer, to the following account:</translation>
</string>
<string id="invoice_iban">
<translation xml:lang="nl">IBAN</translation>
<translation xml:lang="en">IBAN</translation>
</string>
<string id="invoice_ref">
<translation xml:lang="nl">Referentie</translation>
<translation xml:lang="en">Reference</translation>
</string>
<string id="invoice_regards">
<translation xml:lang="nl">Met vriendelijke groet</translation>
<translation xml:lang="en">Kind regards</translation>
</string>
<string id="invoice_team">
<translation xml:lang="nl">uw team bij</translation>
<translation xml:lang="en">your dedicated team at</translation>
</string>
<string id="invoice_yaygreen">
<translation xml:lang="nl">Spaar papier — niet afdrukken tenzij absoluut noodzakelijk. Lees onze (unieke) voorwaarden op: https://radicallyopensecurity.com/TermsandConditions.pdf</translation>
<translation xml:lang="en">Please keep digital unless absolutely required. Read the (unique) terms and conditions of Radically Open Security at: https://radicallyopensecurity.com/TermsandConditions.pdf</translation>
</string>
<string id="qs2off_about">
<translation xml:lang="nl">Over <client_short/></translation>
<translation xml:lang="en">About <client_short/></translation>

View File

@@ -16,7 +16,7 @@
<!-- snippet --><p><company_short/> will test for the presence of the
most common vulnerabilities, using both publicly available vulnerability
scanning tools and manual testing. <company_short/> shall perform a
<p_duration/>-day, <p_boxtype/>, intrusive test via the internet.</p>
<p_duration/>-day (<p_mandays/>-manday), <p_boxtype/>, intrusive test via the internet.</p>
<!-- snippet --> <!--Not Needed if Disclaimer is Included; Duplicate Text-->
<!--p>It is possible that in the course of the penetration

View File

@@ -12,8 +12,7 @@
<li><client_poc1/> (<client_short/>)</li>
</ul>
<!-- remove this for non pentesting offers-->
<p>Our penetration tests are run a bit like a Capture The Flag
(CTF) competition:
<p>The workflow of our penetration testing team is modeled on that of a Capture The Flag (CTF) team:
<!-- remove this for non pentesting offers-->
<company_long/> has a geographically distributed team

View File

@@ -74,7 +74,5 @@
evidence it has which relates to this investigation or these
proceedings.</p>
<generate_waiver_signature_box/>
</standard_waiver>
</waivers>

View File

@@ -1,38 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<section>
<title>Over ons <company_long/></title>
<p><company_long/> is 's werelds eerste non-profit computer security consultancy bedrijf.
Wij zijn een <i>Fiscaal Fondswervende Instelling</i> en in die hoedanigheid kunnen we 90 procent van onze winst
<p><company_long/> is het eerste non-profit computer security consultancy bedrijf ter wereld.
We zijn een <i>Fiscaal Fondswervende Instelling</i> en kunnen daardoor 90 procent van onze winst
belastingvrij aan non-profit stichting NLnet doneren. Stichting NLnet ondersteunt al bijna twintig jaar
open-source, digitale rechten en internet onderzoek.</p>
open-source, digitale rechten en internetonderzoek.</p>
<p>Onze winst worden dus niet uitgekeerd aan aandeelhouders, investeerders of eigenaren.
Met de winst dienen we de maatschappij. Omdat wij geen winstoogmerk hebben kunnen we de beste ethische
veiligheidsexperts rekruteren. Met onze kernwaarden trekken we gelijkgestemde klanten aan. Wij stellen onze klanten
in staat om met IT veiligheidsbudgetten sociaal verantwoord ondernemen te ondersteunen.
Het hoge tempo waarmee wij groeien weerspiegelt de positieve respons van de markt op onze idealistische
filosofie en ons innovatieve business model.</p>
<p>Onze winst wordt dus niet uitgekeerd aan aandeelhouders, investeerders of eigenaren, maar ingezet om de maatschappij te dienen. Omdat we geen winstoogmerk hebben, kunnen we de beste ethische
veiligheidsexperts rekruteren. Met onze kernwaarden trekken we gelijkgestemde klanten aan, die we
in staat stellen om met hun IT-veiligheidsbudget het sociaal verantwoord ondernemen te ondersteunen.
Ons hoge groeitempo weerspiegelt de positieve respons van de markt op onze idealistische
filosofie en ons innovatieve businessmodel.</p>
<p><company_long/> heeft een aantal waarden die wij beschrijven als onze
"Kernwaarden." Deze zijn:</p>
<p>De waarden die <company_long/> als haar kernwaarden zou willen omschrijven zijn:</p>
<ul>
<li><b>Openheid van zaken</b><br/>
Wij bouwen geen toezichtssystemen, we helpen geen hacking activisten, we verkopen geen <i>exploits</i>
aan geheime diensten of iets in die richting. Als een opdracht ons moreel verwerpelijk lijkt, nemen
Wij bouwen geen toezichtssystemen, hacken geen activisten en verkopen geen <i>exploits</i>
aan geheime diensten. Als een opdracht ons moreel verwerpelijk lijkt, nemen
we die niet aan. </li>
<li><b>Open-Source</b><br/>
Wij geven ALLE tools en frameworks, die wij open-source bouwen, vrij op onze website.</li>
<li><b>Leren vissen</b><br/>
Tijdens de samenwerken delen wij niet alleen de resultaten met onze opdrachtgevers, maar
geven wij ook een stapsgewijze beschrijving waarmee klanten in de toekomst zelf de
veiligheid van hun systemen kunnen testen. Wij willen graag inzichtelijk maken wat we doen. Het is geen
Wij geven de broncode van <b>alle</b> tools en frameworks die we bouwen vrij op onze website.</li>
<li><b>Het "<i>teach to fish</i>"-principe</b><br/>
Tijdens het samenwerken delen we niet alleen onze bevindingen met onze opdrachtgevers, maar
beschrijven we ook stap voor stap hoe de opdrachtgever in de toekomst zelf de
veiligheid van zijn of haar systemen kan testen. Wij willen graag inzichtelijk maken wat we doen. Het is geen
hogere wiskunde. We helpen klanten om hun kennis en houding ten aanzien van veiligheid te verbeteren.</li>
<li><b>Gratis IoCs</b><br/>
Wij geven ALLE verzamelde bedreigingen (<i>Indicators of Compromise</i>) vrij in
een open-source <i>database</i> die iederen gratis kan gebruiken (Opgeschoond in
overeenstemming met klanten).</li>
<li><b>Zero days</b><br/>
Wij verkopen geen <i>'Zero days' exploits</i> (nuldagenaanval) - wij brengen ze op verantwoorde wijze aan het licht!</li>
<li><b>Gratis <i>IoC</i>s</b><br/>
Wij geven <b>alle</b> verzamelde gevarenindicatoren (<i>Indicators of Compromise</i>) vrij in
een open-source <i>database</i> die iederen gratis kan gebruiken (uiteraard gebeurt dit in overleg met de klant en worden de gegevens opgeschoond voor ze openbaar worden gemaakt).</li>
<li><b><i>Zero days</i></b><br/>
Wij verkopen geen <i>'Zero day' exploits</i> (pas bekend geworden kwetsbaarheden) - wij brengen ze op verantwoorde wijze aan het licht!</li>
</ul>
<p>Voor meer informatie over <company_long/> verwijzen wij u naar onze website:
<a href="http://www.radicallyopensecurity.com">www.radicallyopensecurity.com</a>.</p>

View File

@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<p>
<!--snippet -->Crystal-Box vs. Black-Box pentesting verwijst naar de hoeveelheid
informatie over het doelwit; de omgeving, architectuur, en/of applicaties die de klant
<div>
<p>
Crystal-Box vs. Black-Box pentesting verwijst naar de hoeveelheid
informatie over de doelwit omgeving, architectuur, en/of applicaties die de klant
in eerste instantie deelt met de pentesters. Bij Black-Box testing ontvangen de
pentesters helemaal geen informatie over het doelwit. Bij Crystal-Box tests
pentester helemaal geen informatie over het doelwit. Bij Crystal-Box tests
ontvangen de pentesters alle informatie die opgevraagd wordt betreffende het doelwit,
inclusief broncode (wanneer dit relevant is), toegang tot ontwikkelaars of systeembeheer, etc...
<br />
In dit geval zal <company_short/> een Black-Box test uitvoeren.
inclusief source code (wanneer dit relevant is), toegang tot developers of systeembeheer, etc...
</p>
<p>
In dit geval zal <company_short/> een Black-box test uitvoeren.
</p></div>
<!-- end of template -->

View File

@@ -1,39 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<section>
<title>Broncode Audit</title>
<p><company_short/> zal een broncode audit uitvoeren ter ondersteuning van pentesting.
Gedurende een code audit onderzoeken wij handmatig de broncode van een applicatie
<title>Broncode-audit</title>
<p><company_short/> zal een broncode-audit uitvoeren ter ondersteuning van pentesting.
Gedurende de code-audit onderzoeken wij handmatig de broncode van een applicatie
om te verzekeren dat er geen kwetsbaarheden in de beveiliging zitten en gebruiken wij
ons begrip van de code om het pentesten te leiden. Als er kwetsbaarheden gevonden worden
documenteren wij deze en komen met suggesties om deze op te lossen. Dit wordt gedaan
door goed-getrainde penetratie testers die zowel raw code kunnen herzien,
als het interpreteren van de bevindingen van de geautomatiseerde scans, wat het in context brengt.</p>
<p>Tijdens het code audit gedeelte van penetratie tests nemen wij de volgende criteria mee:</p>
documenteren wij deze en komen met suggesties om deze op te lossen. De audit wordt uitgevoerd
door goed getrainde penetratietesters die zowel raw code kunnen herzien
als de bevindingen van geautomatiseerde scans interpreteren en in context brengen.</p>
<p>Tijdens het code-audit-gedeelte van penetratietests nemen wij de volgende criteria mee:</p>
<ol>
<li>Risico Beoordeling en "Dreiging Modellering"<br/>
In deze stap analyseren wij de risico's van een bepaalde applicatie of systeem.
Dreiging Modellering is een specifieke, gestructureerde aanpak voor risico
analyse dat ons in staat stelt om beveiligingsrisico's te identificeren,
kwalificeren en te addresseren. Dit is de reden voor de vervlechting met
het proces van Code Herziening. Bijvoorbeeld: Gebruiksgegevens zijn heilig.
Wij focussen op versleutelde opslag, ontdekken of <client_short/> werknemers
een "backdoor" in hun data hebben en snijden gestolen toestellen af
<li>Risicobeoordeling en "Threat Modeling"<br/>
In deze stap analyseren wij de risico's van een bepaalde toepassing of een bepaald systeem.
"Threat modeling" is een specifieke, gestructureerde aanpak voor risico-analyse die wordt ingezet tijdens het codeherzieningsproces en die ons in staat stelt beveiligingsrisico's te identificeren, te
kwalificeren en te addresseren. Bijvoorbeeld: Gebruiksgegevens zijn heilig.
We controleren op versleutelde gegevensopslag, onderzoeken of <client_short/> werknemers
een "backdoor" in hun data hebben of ontkoppelen (indien van toepassing) gestolen toestellen
door deze op afstand te wissen en accounts in te trekken.</li>
<li>Doel en Context<br/>
Hier focussen wij op de risico's, voornamelijk in het snel en gemakkelijk
delen van interne documenten en routebeschrijvingen. Accountgegevens
zijn niet zo geheim als wij weten wie in een vergadering zit, maar
wat besproken wordt geheim is.</li>
Hier richten we ons vooral op de risico's, bijvoorbeeld wanneer (te) snel en gemakkelijk
interne documenten en agenda's worden gedeeld. Accountgegevens
zijn niet zo geheim als wij weten wie bij vergaderingen aanwezig is - zelfs als het besprokene wél geheim blijft.
</li>
<li>Complexiteit<br/>
De complexiteit van het systeem zit hem in de frameworks die de
webapplicatie ondersteunen. Wij zouden deze negeren en ons alleen richten
op de "custom" en backend code, waarvan wij weten dat het gebaseerd is
op .NET/ C#. We zouden ons ook focussen op implementatiefouten en bekende
fouten in de systemen. Bijvoorbeeld: We zouden bevestigen of u de laatste
versie van de software gebruikt, maar we zouden niet delven in het framework zelf.
Omdat wij aannemen dat de code is geschreven door een team zal dit waarschijnlijk duidelijk
geschreven code zijn. Als u meerdere full-release versies heeft, zullen er
ongetwijfeld meerdere code revisies en audits op deze code zijn.</li>
(web)applicatie ondersteunen. Wij richten ons voornamelijk
op de "custom" en back-end code, en dan in het bijzonder op implementatiefouten en bekende
fouten in de systemen. Bijvoorbeeld: We controleren of u de laatste
versie van de ondersteunende software gebruikt, maar duiken niet in het eigenlijke framework.
We nemen aan dat de code is geschreven door een team en dus waarschijnlijk duidelijk
geschreven is. Als u meerdere full-release versies heeft, zullen er
ongetwijfeld meerdere coderevisies en -audits zijn.</li>
</ol>
<p>Voor meer informatie verwijzen wij u naar de volgende link:
<a href="https://www.owasp.org/index.php/OWASP_Code_Review_V2_Table_of_Contents">https://www.owasp.org/index.php/OWASP_Code_Review_V2_Table_of_Contents</a></p>

View File

@@ -3,15 +3,15 @@
<title>Algemene voorwaarden</title>
<!-- snippet --><p><company_short/> zal alleen de <company_svc_short/>
uitvoeren als het de toestemming heeft gekregen van <generate_permission_parties/>
zoals uiteengezet in de penetration test verklaring, bijgevoegd als <b>Annex 2</b>,
of verschafd als los document.</p>
zoals uiteengezet in de penetratietestvrijwaring, bijgevoegd als <b>Annex 2</b>
of verschaft als los document.</p>
<p><company_short/> voert deze opdracht uit op basis van de algemene voorwaarden,
die bijgevoegd zijn als Annex 1.
<company_short/> weigert alle algemene voorwaarden die gebruikt worden door
<company_short/> verwerpt alle algemene voorwaarden die gebruikt worden door
<client_short/>.</p>
<p>Om akkoord te gaan met dit aanbod, tekent u deze brief in tweevoud en retourneert
deze naar:</p>
<p>Om akkoord te gaan met dit aanbod dient u deze brief in tweevoud te tekenen en te
retourneren naar:</p>
<contact>
<name><company_legal_rep/></name>
<address><company_long/><br/>Overdiemerweg 28<br/>1111 PP Diemen</address>

View File

@@ -1,20 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--snippet -->
<p>
<div><p>
Crystal-Box vs. Black-Box pentesting verwijst naar de hoeveelheid
informatie over de doelwit omgeving, architectuur, en/of applicaties die de klant
in eerste instantie deelt met de pentesters. Bij Black-Box testing ontvangen de
pentester helemaal geen informatie over het doelwit. Bij Crystal-Box tests
ontvangen de pentesters alle informatie die opgevraagd wordt betreffende het doelwit,
inclusief source code (wanneer dit relevant is), toegang tot developers of systeembeheer, etc...
<br />
<br />
<company_short/> zal een Crystal-Box pentest uitvoeren, wat de voorkeursmethode is.
In tegenstelling tot "real world" aanvallers, die alle tijd van de wereld hebben,
vinden pentests plaats in een beperkt tijdsbestek. Crystal-Box pentesting biedt ons
de mogelijkheid om zo efficiënt mogelijk onze tijd te benutten, wat zorgt voor
een maximalisatie van het aantal kwetsbaarheden die kunnen worden gevonden.
Daarnaast sluit de Crystal-Box pentest het beste aan bij de "Meekijken over de Schouder"
optie die <company_short/> aanbiedt aan <client_short/>.
</p>
<p>
<company_short/> zal een Crystal-box pentest uitvoeren - de methode die onze voorkeur heeft.
In tegenstelling tot "echte" hackers, die alle tijd van de wereld hebben,
vinden pentests plaats in een beperkt tijdsbestek. Crystal-box pentesting biedt ons
de mogelijkheid om onze tijd zo efficiënt mogelijk te gebruiken, waardoor het maximale aantal kwetsbaarheden kan worden gevonden.
Daarnaast sluit de Crystal-box pentest het beste aan bij de "meekijk"-optie die <company_short/> <client_short/> biedt.
</p></div>
<!-- end of template -->

View File

@@ -2,23 +2,22 @@
<section>
<title>Vrijwaring</title>
<p>Het is mogelijk dat in de loop van het penetratie testen <company_short/>
de operaties van het doelwit hindert of hier schade aan toebrengt.
<p>Het is mogelijk dat <company_short/> in de loop van het testen
bedrijfsvoering bij het doelwit hindert of bedrijfsschade aanricht.
<client_short/> geeft hier toestemming voor, onder voorbehoud dat <company_short/>
hier niet nalatig of roekeloos mee omgaat. <client_short/> waarborgt dit ook en heeft de bevoegdheid om
hier toestemming voor te geven.</p>
niet nalatig of roekeloos handelt. <client_short/> garandeert bovendien dat ze bevoegd is om
deze toestemming te verlenen.</p>
<p>Het is van belang om de limitaties van de diensten van <company_short/> te begrijpen.
<company_short/> geeft geen (en kan geen) garanties geven dat iets veilig is.
<company_short/>, heeft in plaats daarvan, een wettelijke inspanningsverplichting
voor de uit te voeren diensten.</p>
<p>Laat duidelijk zijn dat er grenzen zijn aan wat <company_short/> kan leveren.
<company_short/> kan geen garantie geven dat een systeem 100% veilig is, en doet dat dan ook niet.
<company_short/> heeft wel een wettelijke inspanningsverplichting.</p>
<p><company_short/> en <client_short/> komen hierbij overeen dat redelijke maatregelen
worden getroffen om, de vertrouwelijkheid van informatie en persoonlijke
gegevens van de doelwitten waar zij toegang tot krijgen
in de loop van het uitvoeren van de penetratie test, in stand wordt gehouden.
<p><company_short/> en <client_short/> komen hierbij overeen dat er redelijke maatregelen
worden getroffen om de informatie en persoonlijke
gegevens waar <company_short/> in de loop van de penetratietest toegang toe krijgt
zullen worden beschermd en vertrouwelijk zullen worden behandeld.
Beide partijen zullen de informatie en data die zij ontvangen of waar zij toegang tot krijgen
alleen gebruiken ten behoeve van de doelen die beschreven zijn in deze overeenkomst.
<company_short/> garandeert dat alle kern-leden, externe freelancers en vrijwilligers
die betrokken zijn bij het uitvoeren van de penetratie test een geheimhoudingsverklaring (NDA) hebben getekend.</p>
<company_short/> garandeert dat alle kernleden, externe freelancers en vrijwilligers
die bij het uitvoeren van de penetratietest betrokken zijn een geheimhoudingsverklaring (NDA) hebben getekend.</p>
</section>

View File

@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- snippet --><p>Gebaseerd op de verstrekte informatie, verwachten wij dat het dienstverband <p_duration/> dagen duurt.
De planning van dit dienstverband is als volgt:</p>
<!-- snippet --><p>Op basis van de verstrekte informatie verwachten wij dat het uitvoeren van de opdracht <p_duration/> dagen zal duren.
De planning van de opdracht is als volgt:</p>

View File

@@ -1,197 +1,295 @@
<?xml version="1.0" encoding="UTF-8"?>
<annex>
<title>Annex 1<br/>General Terms and Conditions</title>
<p><b>What is this document?</b></p>
<p>These are the general terms and conditions (in Dutch: “<i>algemene voorwaarden</i>”)
of <company_long/> (<company_short/>). This version of the general terms and conditions
is dated 15 July 2014.</p>
<p>In the spirit of <company_short/>'s philosophy, <company_short/> wants these
general terms and conditions to be as understandable as possible. If you have any
questions, feel free to ask for clarification.</p>
<p><b>What is <company_long/>?</b></p>
<p><company_short/> is a private limited liability company under Dutch law located
in Amsterdam, The Netherlands. It is registered at the Dutch Chamber of Commerce
under no. 60628081.</p>
<p><b>To what do these terms and conditions apply?</b></p>
<p>These general terms and conditions apply to all agreements between <company_short/>
and the customer. <company_short/> rejects any terms and conditions used by the
customer. The parties can only deviate from these general terms and conditions
in writing. These general terms and conditions are also intended to benefit any
person employed or engaged by <company_short/> during the performance of an assignment.</p>
<p><b>How does <company_short/> agree on an assignment?</b></p>
<p><company_short/> wants both parties to have a clear picture of an assignment
before it starts. This means there only is an agreement between <company_short/>
and the customer after <company_short/> sends a written offer containing the key
terms of the agreement and the customer subsequently accepts the offer.
Communications other than the written offer do not form part of the agreement.
<company_short/> can rescind an offer until it is accepted by the customer.</p>
<p><b>What can the customer expect from <company_short/>?</b></p>
<p>It is important to understand the limits of <company_short/>'s services.
<company_short/> does not (and cannot) give guarantees that something is secure.
<company_short/> instead has an obligation to make reasonable efforts
(in Dutch: “<i>inspanningsverplichting</i>”) to perform the agreed services.</p>
<p><company_short/> will make reasonable efforts to perform the assignment in
accordance with the plan set out in the offer (if any). If <company_short/>
expects it will not fulfill the plan as documented, it will let the customer
know without delay. <company_short/> is not automatically deemed to be in default
if it doesn't meet the plan.</p>
<p><company_short/> will make reasonable efforts to avoid disruption of the
customer's operations and damage to its owned or operated systems, but it
cannot guarantee that this will be avoided. The customer agrees
to this. <company_short/> is not obliged to restore the systems or recover any
data deleted or amended in the course of the assignment.</p>
<p><b>What can <company_short/> expect from the customer?</b></p>
<p>The customer will provide <company_short/> with all means necessary to allow
<company_short/> to perform the agreed services. If <company_short/> needs explicit
permission from the customer to perform its services (for example, when doing
penetration tests) the customer gives this permission. The customer also warrants
that it has the legal authority to give this permission.</p>
<p><b>How do the parties handle confidential information?</b></p>
<p><company_short/> and the customer will not disclose to others confidential
information and personal data they receive from each other or gain access to in
the course of an assignment. <company_short/> has the right to disclose this
information and data to persons engaged by <company_short/>, but only if these
persons have a similar confidentiality obligation vis-á-vis <company_short/>.
Any person will only use the information and data it receives or gains access
to for the purposes following from the agreement. Both parties will take reasonable
measures to maintain the confidentiality of the information and data they received
or gained access to, and will ensure that persons engaged by them do the same.</p>
<p><b>What does <company_short/> do with vulnerabilities it finds in the course
of an assignment?</b></p>
<p>If <company_short/> in the course of an assignment finds a vulnerability which
might affect the customer, it will report this to the customer. If a vulnerability
might affect third parties as well, <company_short/> retains the right to disclose
this vulnerability also to others than the customer. It will only do so after
having given the customer a reasonable period to take measures minimising the
impact of the vulnerability, in line with responsible disclosure best practices.</p>
<p><b>What does <company_short/> do with indicators of compromise it finds?</b></p>
<p>If <company_short/> in the course of an assignment finds indicators of
compromise, such as malware signatures and IP-addresses, it will report this to
the customer. <company_short/> retains the right to also publish this information
in a publicly accessible database. It will only do so after it has given the
customer the opportunity to object to the publication of data which would
negatively impact the customer.</p>
<p><b>Who owns the products developed in the course of the assignment?</b></p>
<p><company_short/> retains any intellectual property rights in products developed
for an assignment, such as software and reports. <company_short/>, however, wants
to teach as many customers as possible 'how to fish'.</p>
<p>For software it developed, this means that <company_short/> gives the customer
a permanent, non-exclusive, transferable, sub-licensable, worldwide license to
distribute and use the software in source and binary forms, with or without
modification (very similar to the BSD-license). If <company_short/>'s software
is based on other software which is provided under a license which restricts
<company_short/>'s ability to license its own software (such as the GPLv3 license),
the more restrictive license will apply.</p>
<p>For other products it developed, such as reports and analyses, <company_short/>
gives the customer the same license, but this license is exclusive to the customer
and does not contain the right to modification. The latter condition is intended
to ensure that the customer will not change <company_short/>'s products, such as
reports and analyses. <company_short/> retains the right to reuse these products,
for example for training and marketing purposes. <company_short/> will remove any
confidential information from these products before publication.</p>
<p><company_short/> retains title to any property transferred to the customer
until all outstanding payments by the customer have been done in full (in Dutch:
<i>eigendomsvoorbehoud</i>”). <company_short/> also only gives a license after
all outstanding payments have been done in full.</p>
<p><b>Who will perform the assignment?</b></p>
<p><company_short/> has the right to appoint the persons who will perform the
assignment. It has the right to replace a person with someone with at least the
same expertise, but only after having consulted with the customer. This means
that section 7:404 Dutch Civil Code (in Dutch: “<i>Burgerlijk Wetboek</i>”) is
excluded.</p>
<p>Due to the nature of <company_short/>'s business, <company_short/> regularly
works with freelancers for the performance of its assignments. <company_short/>
has the right to engage third parties, including freelancers, in the course of
the performance of an assignment.</p>
<p><company_short/> wants to be able to use the expertise of its entire team to
help with an assignment. This means that in the course of an assignment, it is
possible that the persons performing the assignment will consult with and be
advised by others in <company_short/>'s team. These others will of course be
bound by the same confidentiality obligations as the persons performing the assignment.</p>
<p><b>What happens when the scope of the assignment is bigger than agreed?</b></p>
<p><company_short/> and the customer will attempt to precisely define the scope
of the assignment before <company_short/> starts. If during the course of the
assignment, the scope turns out to be bigger than expected, <company_short/>
will report this to the customer and make a written offer for the additional work.</p>
<p><b>How is payment arranged?</b></p>
<p>All amounts in <company_short/>'s offers are in Euros, excluding VAT and
other applicable taxes, unless agreed otherwise.</p>
<p>For assignments where the parties agreed to an hourly fee, <company_short/>
will send an invoice after each month. For other assignments, <company_short/>
will send an invoice after completion of the assignment, and at moments set out
in the offer (if any). The customer must pay an invoice within 30 days of the
invoice date.</p>
<p><company_short/> may, prior to an assignment, agree on the payment of a
deposit by the customer. <company_short/> will settle deposits with interim
payments or the final invoice for the assignment.</p>
<p>If the payment is not received before the agreed term, the client will be
deemed to be in default without prior notice. <company_short/> will then have
the right to charge the statutory interest (in Dutch: “<i>wettelijke rente</i>”)
and any judicial and extrajudicial (collection) costs (in Dutch:
<i>gerechtelijke- en buitengerechtelijke (incasso)kosten</i>”).</p>
<p>If the customer cancels or delays the assignment two weeks before it starts,
<company_short/> is entitled to charge the customer 50% of the agreed price.
If the customer cancels or delays the assignment after it already started,
<company_short/> is entitled to charge the customer 100% of the agreed price.
<company_short/> is entitled to charge a pro rata percentage in the case of
cancellation or delay shorter than two weeks before the start of the assignment
(i.e. a cancellation one week before the assignment would entitle <company_short/>
to charge 75% of the agreed price).</p>
<p><b>For what can <company_short/> be held liable?</b></p>
<p>Any liability of <company_short/> resulting from or related to the performance
of an assignment, shall be limited to the amount that is paid out in that
specific case under an applicable indemnity insurance of <company_short/>,
if any, increased by the amount of the applicable deductible (in Dutch:
<i>eigen risico</i>”) which under that insurance shall be borne by <company_short/>.
If no amount is paid out under an insurance, these damages are limited to the
amount already paid for the assignment, with a maximum of EUR 10.000.
Each claim for damages shall expire after a period of one month from the day
following the day on which the customer became aware or could reasonably
be aware of the existence of the damages.</p>
<p>To make things clear, <company_short/> is not liable if a person associated
with <company_short/> acts contrary to any confidentiality or non-compete
obligation vis-á-vis the customer or a third party, this person might have
agreed to in another engagement.</p>
<p>What happens when third parties lodge a claim or initiate criminal proceedings
against <company_short/>?</p>
<p>The customer shall indemnify <company_short/> and any person employed or
engaged by <company_short/> for any claims of third parties which are in any
way related to the activities of <company_short/> and any person employed or
engaged by <company_short/> for the customer.</p>
<p>Should a third party lodge a claim against <company_short/> or any of the
consultants it engaged or employed as a result of the performance of the assignment
for the customer, then the customer will co-operate fully with <company_short/>
in defending against this claim, including by providing to <company_short/> any
evidence it has which relates to this claim.
Should the public prosecutor initiate an investigation or criminal proceedings
against <company_short/> or any of the consultants it engaged or employed as a
result of the performance of the assignment for the customer, then the customer
will also co-operate fully with <company_short/> in defending against this
investigation or proceedings, including by providing any evidence it has which
relates to this investigation or these proceedings.</p>
<p>The customer shall reimburse <company_short/> and any person employed or
engaged by <company_short/> all costs of legal defence and all damages in
relation to these claims, investigations or proceedings. This provision does
not apply to the extent a claim, investigation, or proceeding is the result of
the intent or recklessness (in Dutch: “<i>opzet of bewuste roekeloosheid</i>”)
of <company_short/> or a person employed or engaged by <company_short/>.</p>
<p><b>When is this agreement terminated and what happens then?</b></p>
<p>Each of the parties may terminate the agreement wholly or partly without
prior notice if the other party is declared bankrupt or is being wound up or if
the other party's affairs are being administered by the court
(in Dutch: “surséance van betaling”).</p>
<p><b>When can <company_short/> not be expected to perform the assignment?</b></p>
<p>In the case of force majeure (in Dutch: “<i>overmacht</i>”) as a result of
which <company_short/> cannot reasonably be expected to perform the assignment,
the performance will be suspended. Situations of force majeure include cases
where means, such as soft- and hardware, which are prescribed by the customer
do not function well. The agreement may be terminated by either party if a
situation of force majeure has continued longer than 90 days. The customer will
then have to pay the amount for the work already performed pro rata.</p>
<p><b>Which law applies and which court is competent?</b></p>
<p>Dutch law applies to the legal relationship between <company_short/> and its
customers. Any dispute between <company_short/> and a customer will be resolved
in the first instance exclusively by the District Court (in Dutch:
<i>rechtbank</i>”) of Amsterdam, the Netherlands.</p>
</annex>
<title>Annex 1<br/>Algemene Voorwaarden</title>
<p>
<b>Wat houdt dit document in?</b>
</p>
<p>
Dit zijn de algemene voorwaarden van <company_long/> (<company_short/>)
Deze versie van de algemene voorwaarden dateert van 15 juli 2014.
</p>
<p>
In lijn met de filosofie van <company_short/> wil <company_short/> dat deze algemene voorwaarden zo
begrijpelijk mogelijk zijn. Vraag gerust om opheldering als u vragen heeft.
</p>
<p>
<b>Wat is Radically Open Security?</b>
</p>
<p>
<company_short/> is een besloten vennootschap met beperkte aansprakelijkheid volgens
Nederlands recht en is gevestigd in Amsterdam, Nederland. Het bedrijf staat geregistreerd
bij de Nederlandse Kamer van koophandel onder nr. 60628081.
</p>
<p>
<b>Waarop zijn deze algemene voorwaarden van toepassing?</b>
</p>
<p>
Deze algemene voorwaarden zijn van toepassing op alle overeenkomsten tussen
<company_short/> en de klant. <company_short/> wijst algemene voorwaarden die gebruikt worden door de
klant van de hand. Partijen kunnen alleen schriftelijk van deze algemene
voorwaarden afwijken. Deze algemene voorwaarden zijn ook bedoeld ten gunste
van een persoon die tijdens het uitvoeren van een opdracht in dienst is van
of ingeschakeld is door <company_short/>.
</p>
<p>
<b>Hoe stemt <company_short/> in met een opdracht?</b>
</p>
<p>
<company_short/> wil dat beide partijen een duidelijk beeld hebben van een opdracht voordat
die begint. Dit betekent dat er alleen een overeenkomst is tussen <company_short/> en de
klant indien <company_short/> een schriftelijke offerte stuurt met daarin de belangrijkste
bepalingen van de overeenkomst en de klant vervolgens de offerte accepteert.
Mededelingen, anders dan de schriftelijke offerte, maken geen deel uit van de
overeenkomst. <company_short/> kan een offerte intrekken totdat het door de klant is geaccepteerd.
</p>
<p>
<b>Wat kan de klant verwachten van <company_short/>?</b>
</p>
<p>
Het is belangrijk om op de hoogte te zijn van de grenzen van de diensten van
<company_short/>. <company_short/> garandeert niet (en kan niet garanderen) dat iets veilig is. In plaats
daarvan heeft <company_short/> een inspanningsverplichting om de afgesproken diensten uit
te voeren.
</p>
<p>
<company_short/> zal redelijke inspanningen leveren om de opdracht uit te voeren conform
de planning die is vastgelegd in de offerte (indien van toepassing). Indien
<company_short/> verwacht dat het de planning niet haalt, brengt <company_short/> de klant onverwijld
op de hoogte. <company_short/> wordt niet automatisch in verzuim geacht te zijn indien
<company_short/> de planning niet haalt.
</p>
<p>
<company_short/> zal redelijke inspanningen leveren om schade aan systemen die eigendom
zijn van de klant of beheerd worden door de klant te voorkomen, maar kan niet
garanderen dat dergelijke schade zal worden vermeden. <company_short/> is niet verplicht
om data te herstellen die het tijdens de opdracht heeft verwijderd of gewijzigd.
</p>
<p>
<b>Wat kan <company_short/> van de klant verwachten?</b>
</p>
<p>
De klant zal <company_short/> voorzien van alle nodige middelen om <company_short/> in staat te stellen
om de afgesproken diensten uit te voeren. Indien <company_short/> nadrukkelijke toestemming
nodig heeft van de klant om zijn diensten uit te voeren, bijvoorbeeld bij het
uitvoeren van penetratietesten of een basis-securityscan, geeft de klant deze toestemming. De klant
garandeert tevens dat het de wettelijke bevoegdheid heeft om deze toestemming te geven.
</p>
<p>
<b>Hoe gaan de partijen om met vertrouwelijk informatie?</b>
</p>
<p>
<company_short/> en de klant onthullen aan anderen geen vertrouwelijke informatie en persoonlijke
gegevens die zij van elkaar ontvangen of waar zij gedurende de opdracht toegang
toe krijgen. <company_short/> heeft het recht om de informatie openbaar te maken aan personen
die door <company_short/> zijn ingeschakeld, maar alleen indien deze personen een vergelijkbare
geheimhoudingsplicht hebben ten aanzien van <company_short/>. Een ieder aan wie deze informatie
of deze gegevens openbaar zijn gemaakt zal dit alleen gebruiken voor de doelen
die voortkomen uit de overeenkomst. Beide partijen zullen redelijke maatregelen
nemen om de vertrouwelijkheid van deze informatie en gegevens te handhaven,
ook met betrekking tot personen die door de partijen zijn ingeschakeld.
</p>
<p>
<b>Wat doet <company_short/> met kwetsbaarheden die het tijdens de opdracht ontdekt?</b>
</p>
<p>
Indien <company_short/> tijdens de opdracht een kwetsbaarheid vindt die de klant zou kunnen
beïnvloeden, geeft <company_short/> dit door aan de klant. Indien een kwetsbaarheid derden
ook zou kunnen beïnvloeden, behoudt <company_short/> het recht om deze kwetsbaarheid ook
aan anderen dan te klant bekend te maken. <company_short/> zal dit alleen doen nadat <company_short/>
de klant een redelijke periode heeft gegeven om maatregelen te nemen om het
effect van de kwetsbaarheid te minimaliseren, overeenkomstig best practices
voor responsible disclosure.
</p>
<p>
<b>Wat doet <company_short/> als het indicaties van compromittering tegenkomt? </b>
</p>
<p>
Indien <company_short/> tijdens een opdracht indicaties van compromittering tegenkomt,
zoals malware-handtekeningen en IP-adressen, geeft <company_short/> dit door aan de klant.
<company_short/> behoudt het recht om deze informatie ook in een openbaar toegankelijke
database te publiceren. <company_short/> zal dit alleen doen nadat het de klant de mogelijkheid
heeft gegeven om bezwaar te maken tegen de publicatie van gegevens die een negatief
effect zouden hebben op de klant.
</p>
<p>
<b>Wie is eigenaar van de producten die tijdens de opdracht worden ontwikkeld?</b>
</p>
<p>
<company_short/> behoudt intellectuele eigendomsrechten van producten die voor een opdracht
zijn ontwikkeld, zoals software en rapporten. <company_short/> wil echter zoveel mogelijk
klanten leren vissen.
</p>
<p>
Voor software die <company_short/> heeft ontwikkeld betekent dit dat <company_short/> de klant een
permanente, niet-exclusieve, overdraagbare, sub-licentieerbare, wereldwijde
licentie geeft om de software in bronvorm of binaire vorm te verspreiden of
te gebruiken, met of zonder wijziging (vrijwel gelijk aan de BSD-licentie).
Indien de software van <company_short/> gebaseerd is op andere software die geleverd is
onder een licentie die het vermogen beperkt van <company_short/> om een licentie te verbinden
aan de eigen software (zoals de GPLv3-licentie), is de beperkendere licentie
van toepassing.
</p>
<p>
Voor overige producten die <company_short/> heeft ontwikkeld, zoals rapporten en analyses,
geeft <company_short/> dezelfde licentie aan de klant, maar deze licentie geldt exclusief
voor de klant en bevat geen recht op wijziging. De laatste voorwaarde is bedoeld
om te garanderen dat de klant de producten van <company_short/> niet verandert, zoals rapporten
en analyses. <company_short/> behoudt het recht om deze producten opnieuw te gebruiken,
bijvoorbeeld voor trainings- en marketingdoeleinden. Voorafgaand aan publicatie
verwijdert <company_short/> vertrouwelijke informatie van deze producten.
</p>
<p>
<company_short/> behoudt het eigendomsrecht van een goed dat is overgedragen aan de klant
totdat alle uitstaande betalingen volledig door de klant zijn voldaan, i.e.
eigendomsvoorbehoud. <company_short/> geeft tevens alleen een licentie nadat alle uitstaande
betalingen volledig zijn voldaan.
</p>
<p>
<b>Wie zal de opdracht uitvoeren?</b>
</p>
<p>
<company_short/> heeft het recht om personen te benoemen die de opdracht zullen uitvoeren.
<company_short/> heeft het recht om een persoon te vervangen door iemand met minstens
dezelfde expertise, maar alleen na overleg met de klant. Dit betekent dat artikel
7:404 van het Nederlands Burgerlijk Wetboek is uitgesloten.
</p>
<p>
Vanwege de aard van de zaken van <company_short/> werkt <company_short/> regelmatig met freelancers
voor het uitvoeren van de opdrachten. <company_short/> heeft het recht om derden in te schakelen,
waaronder freelancers, tijdens het uitvoeren van een opdracht.
</p>
<p>
<b>Wat gebeurt er wanneer de omvang van de opdracht groter is dan afgesproken?</b>
</p>
<p>
<company_short/> en de klant zullen proberen om de omvang van de opdracht nauwkeurig te
bepalen voordat <company_short/> begint. Indien tijdens de opdracht de omvang groter blijkt
te zijn dan verwacht zal <company_short/> dit rapporteren aan de klant en een schriftelijke
offerte opstellen voor het meerwerk.
</p>
<p>
<b>Hoe is de betaling geregeld?</b>
</p>
<p>
Alle bedragen in de offertes van <company_short/> zijn in euros en exclusief BTW en
overige van toepassing zijnde belastingen, tenzij anders overeengekomen.
</p>
<p>
Voor opdrachten waarbij de partijen een uurtarief hebben afgesproken stuurt
<company_short/> aan het einde van iedere maand een factuur. Voor overige opdrachten zal
<company_short/> een factuur sturen na voltooiing van de opdracht en op momenten zoals
vastgelegd in de offerte (indien van toepassing). De klant moet een factuur
binnen 30 dagen na factuurdatum betalen.
</p>
<p>
<company_short/> kan, voorafgaand aan een opdracht, instemmen met een aanbetaling door de klant.
<company_short/> zal aanbetalingen verrekenen met tussentijdse betalingen of met de laatste
factuur voor de opdracht.
</p>
<p>
Indien de betaling niet voor de afgesproken termijn is ontvangen wordt de
klant zonder voorafgaande kennisgeving geacht in verzuim te zijn. <company_short/> heeft
dan het recht om de wettelijke rente en eventuele gerechtelijke en buitengerechtelijke
(incasso)kosten in rekening te brengen.
</p>
<p>
Indien de klant de opdracht binnen twee weken voor de start annuleert of
uitstelt heeft <company_short/> het recht om de klant 50% van de afgesproken prijs in
rekening te brengen.
</p>
<p>
<b>Waarvoor kan <company_short/> aansprakelijk worden gesteld?</b>
</p>
<p>
Een aansprakelijkheid van <company_short/> ten gevolge van of in verband met de uitvoering
van een opdracht is beperkt tot het bedrag dat in dat specifieke geval krachtens
een van toepassing zijnde aansprakelijkheidsverzekering van <company_short/> is uitbetaald,
indien van toepassing, verhoogd met het bedrag van het eigen risico, dat volgens
de verzekering wordt gedragen door <company_short/>. Indien geen bedrag wordt uitbetaald
krachtens een verzekering, is deze schadevergoeding beperkt tot het bedrag
dat al is betaald voor de opdracht, met een maximum van 10.000 euro.
</p>
<p>
Elke vordering tot schadevergoeding verloopt na een periode van een maand
vanaf de dag volgend op de dag waarop de klant kennis had gekregen van of
redelijkerwijs kennis zou kunnen krijgen van het bestaan van de schadevergoeding.
</p>
<p>
Ter verduidelijking, <company_short/> is niet aansprakelijk wanneer een persoon die verbonden
is met <company_short/> handelt in strijd met eventuele geheimhouding of niet-concurrentiebeding
ten aanzien van de klant of derden, die deze persoon afgesproken zou kunnen
hebben in een andere verbintenis.
</p>
<p>
<b>Wat gebeurt er wanneer derden een vordering indienen of een strafrechtelijke
procedure instellen tegen <company_short/>?</b>
</p>
<p>
De klant vrijwaart <company_short/> en een persoon in dienst van of ingeschakeld door <company_short/>
van vorderingen van derden die op enige manier verband houden met de activiteiten
van <company_short/> en een persoon in dienst van of ingeschakeld door <company_short/> voor de klant.
De klant vergoed aan <company_short/> en een persoon in dienst van of ingeschakeld door <company_short/>
alle kosten voor juridische bijstand en alle schade met betrekking tot deze
vorderingen. Deze bepaling is niet van toepassing voor zover een vordering
het gevolg is van opzet of bewuste roekeloosheid van <company_short/> of een persoon in
dienst van of ingeschakeld door <company_short/>.
</p>
<p>
Indien een derde partij een vordering indient tegen <company_short/> of een van de adviseurs
die <company_short/> heeft ingeschakeld of in dienst heeft, als gevolg van het uitvoeren
van de opdracht voor de klant, zal de klant volledig meewerken met <company_short/> in de
verdediging tegen deze vordering, inclusief het leveren aan <company_short/> van enig
bewijs dat betrekking heeft op deze vordering. Indien de officier van justitie
een onderzoek instelt of een strafrechtelijke procedure instelt tegen <company_short/> of
een van de adviseurs die <company_short/> heeft ingeschakeld of in dienst heeft, als gevolg
van het uitvoeren van de opdracht voor de klant, zal de klant ook volledig
meewerken met <company_short/> in de verdediging tegen dit onderzoek of procedure, inclusief
het leveren van enig bewijs dat betrekking heeft op dit onderzoek of deze procedure.
</p>
<p>
<b>Wanneer wordt deze overeenkomst beëindigd en wat gebeurt er dan?</b>
</p>
<p>
Elk van de partijen kan de overeenkomst zonder voorafgaande kennisgeving
geheel of gedeeltelijk beëindigen indien de andere partij failliet is verklaard
of is ontbonden of indien de andere partij in surseance van betaling verkeert.
</p>
<p>
<b>Wanneer kan er niet van <company_short/> worden verwacht dat het de opdracht uitvoert?</b>
</p>
<p>
In het geval van overmacht als gevolg waarvan van <company_short/> redelijkerwijs niet verwacht
kan worden dat het de opdracht uitvoert, zal de uitvoering worden uitgesteld.
Situaties van overmacht zijn onder andere gevallen waarbij middelen zoals
software en hardware die zijn voorgeschreven door de klant niet goed functioneren.
Indien een situatie van overmacht langer dan 90 dagen heeft geduurd, kan de
overeenkomst door een van beide partijen worden beëindigd. De klant zal dan
naar rato het bedrag moeten betalen voor het werk dat al is uitgevoerd.
</p>
<p>
<b>Welk recht is van toepassing en welke rechtbank is bevoegd?</b>
</p>
<p>
Op de rechtsverhouding tussen <company_short/> en zijn klanten is het Nederlands recht
van toepassing. Een geschil tussen <company_short/> en een klant wordt in eerste instantie
uitsluitend beslecht door de Arrondissementsrechtbank te Amsterdam, Nederland.
</p>
</annex>

View File

@@ -1,58 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<section>
<title>Pentest Methodologie</title>
<p>Tijdens het uitvoeren van de penetratie tests volgt <company_long/> in grote lijnen de volgende stappen:</p>
<title>Pentestmethodologie</title>
<p>Tijdens het uitvoeren van de penetratietests volgt <company_long/> in grote lijnen de volgende stappen:</p>
<ol>
<li>Benodigdheden Verzamelen en Scoping; </li>
<li>Ontdekking;</li>
<li>Vaststellen voorwaarden/vereisten en Scoping;</li>
<li>Onderzoek;</li>
<li>Validatie;</li>
<li>Informatieverzameling;</li>
<li>Analyse van Bedreigingen en Kwetsbaarheden;</li>
<li>Verzamelen gegevens;</li>
<li>Analyse van Risico's en Kwetsbaarheden;</li>
<li>Exploitatie;</li>
<li>Rapportage;</li>
<li>Rapportage.</li>
</ol>
<p><b>Step 1: Benodigdheden Verzamelen en Scoping</b> <br/>
<p><b>Stap 1: Vaststellen voorwaarden/vereisten en Scoping</b> <br/>
De verwachtingen van beide partijen worden besproken en overeenkomsten worden gemaakt
betreffende het uitvoeren van de test(s). Bijvoorbeeld, contactgegevens en de
scope van de pentest worden vastgelegd.</p>
betreffende het uitvoeren van de test(s). Tijdens deze stap worden bijvoorbeeld alle contactgegevens verzameld en vastgesteld wat de
scope van de pentest is.</p>
<p><b>Step 2: Ontdekking</b><br/>
Zo veel mogelijk informatie betreffende de "target" organisatie en de "target" objecten
wordt verzameld. Deze informatie wordt passief verzameld, voornamelijk uit publieke bronnen.</p>
<p><b>Stap 2: Onderzoek</b><br/>
Er word zo veel mogelijk informatie betreffende de te testen organisatie en doelwitten verzameld. Deze informatie wordt passief verzameld, voornamelijk uit publieke bronnen.</p>
<p><b>Step 3: Validatie</b><br/>
Alle door de klant gespecificeerde systemen worden kruisverwezen met de bevindingen
van de Ontdekking stap. Wij doen dit om te garanderen dat de ontdekte systemen
<p><b>Stap 3: Validatie</b><br/>
Alle door de klant gespecificeerde systemen worden nagelopen aan de hand van wat tijdens de Onderzoeksstap is ontdekt. We doen dit om te garanderen dat de ontdekte systemen
wettelijk eigendom van de klant zijn en om de scope met de klant te verifiëren.</p>
<p><b>Step 4: Informatieverzameling</b><br/>
<p><b>Stap 4: Verzamelen gegevens</b><br/>
Informatie uit Stap 2 wordt hier gebruikt om actief informatie betreffende de
systemen te verzamelen. Activiteiten gedurende deze fase kunnen het volgende inhouden:
Vaststellen welke onderdelen van de verscheidene componenten zullen worden onderzocht;
Testen op de aanwezigheid van bekende kwetsbaarheden, gebruikmakend van automatische tests;
De aangeboden diensten identificeren en de voor hen gebruikte software te "fingerprinten."</p>
systemen te verzamelen. Mogelijke activiteiten gedurende deze fase zijn:
Vaststellen welke onderdelen van de verscheidene componenten zullen worden getest;
met behulp van geautomatiseerde tests controleren op de aanwezigheid van bekende kwetsbaarheden;
identificeren welke diensten op de onderzochte systemen worden aangeboden en de gebruikte software te "fingerprinten".</p>
<p><b>Step 5: Analyse van Bedreigingen en Kwetsbaarheden</b><br/>
Potentiële bedrijgingen en kwetsbaarheden worden geïndexeerd, gebaseerd op de verzamelde informatie.</p>
<p><b>Stap 5: Analyse van Risico's en Kwetsbaarheden</b><br/>
Potentiële risico's en kwetsbaarheden worden geïndexeerd op basis van de verzamelde informatie.</p>
<p><b>Step 6: Exploitatie</b><br/>
Hier wordt gepoogd om kwetsbaarheden van de verscheidene componenten te gebruiken.
De diverse applicaties en componenten van de klants infrastructuur worden
meedogenloos gesondeerd voor frequent voorkomende design-, configuratie- en programmeerfouten.</p>
<p><b>Stap 6: Exploitatie</b><br/>
Hier wordt gepoogd om kwetsbaarheden in de verscheidene componenten uit te buiten.
De diverse applicaties en componenten van de infrastructuur van de klant worden
grondig gecontroleerd op vaak voorkomende ontwerp-, configuratie- en programmeerfouten.</p>
<p>Notitie: <company_long/> gebruikt als basis open-source scanning tools, maar
voert in het algemeen de meeste exploitatie handmatig uit.</p>
<p>Opmerking: <company_long/> gebruikt open-source scanning tools als basis, maar
voert in de regel de meeste exploitatiepogingen handmatig uit.</p>
<p><b>Step 7: Rapportage</b><br/>
Na het afronden van de verificatie zal een rapport worden geleverd met een stapsgewijze benadering,
waarbij resultaten en ontdekte kwetsbaarheden worden beschreven. Het rapport en de resultaten
zullen worden gepresenteerd aan de verantwoordelijke projectleider of -manager in het kantoor van de klant.</p>
<p><b>Stap 7: Rapportage</b><br/>
Na het afronden van de test zal een rapport worden geleverd waarin de resultaten en ontdekte kwetsbaarheden stap voor stap worden beschreven. Het rapport en de resultaten worden eventueel gepresenteerd aan de verantwoordelijke projectleider of -manager in het kantoor van de klant.</p>
<p>Stappen 4-6 kunnen meerdere malen herhaald worden per test. Voorbeeld: Toegang kan worden
verkregen in een extern systeem dat fungeert als een opstapje tot het interne netwerk.
<p>Stappen 4-6 kunnen meerdere malen herhaald worden per test. Zo kan er bijvoorbeeld door exploitatie van kwetsbaarheden toegang worden
verkregen tot een extern systeem dat fungeert als een opstapje tot het interne netwerk.
Het interne netwerk zal vervolgens worden verkend in Stappen 4 en 5, om vervolgens te worden geëxploiteerd in Stap 6.</p>
</section>

View File

@@ -1,20 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<section>
<title>Planning en Betaling</title>
<p><company_short/> houdt het volgende schema aan voor haar werkzaamheden:</p>
<p><company_short/> houdt de volgende planning aan voor haar werkzaamheden:</p>
<p>
<ul>
<li><p_testingduration/>: <company_short/> voert <company_svc_short/> uit op het doelwit</li>
<li><p_reportwritingduration/>: <company_short/> maakt een concept rapport over de tests</li>
<li><p_reportdue/>: <company_short/> levert het definitieve rapport.</li>
<li><company_short/> voert <company_svc_short/> uit op het doelwit: <p_testingduration/>.</li>
<li><company_short/> levert het definitieve rapport: <p_reportdue/>.</li>
</ul>
</p>
<!-- snippet --><p>Ons vaste tarief voor de bovenstaand beschreven
<p>Ons vaste tarief voor de bovenstaand beschreven
<company_svc_short/> is <p_fee/>,- excl. BTW en bijkomende kosten.
<company_short/> zal een factuur sturen na afronding van deze opdracht.
<client_short/> zal het afgesproken bedrag binnen 30 dagen na de factureringsdatum overmaken.</p>
<!-- snippet --><p>Eventuele extra werkzaamheden zullen apart worden verrekend.
<p>Eventuele extra werkzaamheden zullen apart worden verrekend.
Een uurtarief zal hieraan voorafgaand worden besproken.</p>
</section>

View File

@@ -4,7 +4,7 @@
<p>Om de diensten naar behoren uit te kunnen voeren heeft <company_short/> toegang nodig tot:</p>
<!--Example of most common scenario, change if necessary!! :-->
<ul>
<li>test accounts</li>
<li>testaccounts</li>
<li>een testomgeving</li>
<li>contactgegevens van de systeemadministrators, voor noodgevallen</li>

View File

@@ -1,21 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<section>
<section todo="no">
<title>Projectoverzicht</title><!-- section with an overview of ROS activities -->
<!-- snippet --><p><company_short/> zal <company_svc_long/> uitvoeren voor <client_short/>
op de onderstaand beschreven systemen. De diensten zijn bedoelt om inzicht te bieden
op de hieronder beschreven systemen. De diensten zijn bedoeld om inzicht te bieden
in de veiligheid van deze systemen. Om dit te kunnen bewerkstelligen zal <company_short/>
toegang krijgen tot deze systemen, proberen kwetsbaarheden op te sporen en trachten
verdere toegang te krijgen door de gevonden kwetsbaarheden uit te buiten.</p>
<!-- snippet --><p><company_short/> zal de volgende objectieven testen
(de “<b>objectieven</b>”):</p>
<!-- snippet --><p><company_short/> zal de volgende doelwitten testen
(de “<b>Doelwitten</b>”):</p>
<generate_targets/>
<!-- snippet --><p><company_short/> zal testen op de aanwezigheid van de
meest voorkomende kwetsbaarheden, gebruik makend van zowel publiek beschikbare
scanning tools, als door handmatig testen. <company_short/> zal een
<p_duration/>-daagse, <p_boxtype/>, grondige test uitvoeren, via internet.</p>
scanning tools, als door handmatig testen. <company_short/> zal een grondige
<p_duration/>-daagse (<p_mandays/> mandagen), <p_boxtype/> test uitvoeren via internet.</p>
<section todo="yes">
<title>Scope</title>
<p><company_short/> schat de uitvoering van de penetratietest op ... dagen in totaal: </p>
<ul>
<li>... dagen voor het testen van ...;</li>
<li>... dagen voor het testen van ...;</li>
<li>... dagen voor de verificatie van potentiële risico's, opstellen van een Proof of Concept
en het vastleggen van onze bevindingen en aanbevelingen in het rapport.</li>
</ul>
<br/>
<b>Out of scope</b><br/>
<p>De onderliggende netwerkinfrastructuur, ..., ... en eventuele loadbalancing-infrastructuur maken geen deel uit van de scope.
Uitgesloten zijn ook:</p>
<ul>
<li>elke vorm van social engineering;</li>
<li>(D)DoS aanvallen;</li>
<li>...</li>
</ul>
</section>
<!-- snippet --> <!--Not Needed if Disclaimer is Included; Duplicate Text-->
<!--p>It is possible that in the course of the penetration

View File

@@ -4,48 +4,56 @@
<section>
<title>Team</title>
<p><company_short/> mag de activiteiten uitvoeren met haar kern-teamleden,
externe freelancers, en/of vrijwilligers.</p>
<p>Het eerste contactpersoon voor deze opdracht zal zijn:</p>
<ul>
<li><company_poc1/> (<company_short/>)</li>
<li><client_poc1/> (<client_short/>)</li>
</ul>
<p>Onze penetratie tests lijken een beetje op een "verover de vlag competitie":
<company_long/> heeft een geografisch gedistribueerd team
en wij gebruiken online infrastructuur (RocketChat, GitLabs, etc.)
om ons werk te coördineren. Dit geeft ons de mogelijkheid om
om verscheidene technische mensen uit de organisatie van de klant
uit te nodigen om op vrijwillige basis samen te werken met ons pentest team.
Natuurlijk geldt deze uitnodiging ook voor <client_short/>.</p>
<p>In de loop van het project hebben wij de insteek om actief te
brainstormen met <client_short/> over zowel de pentest, als het proces.
Dit is een doorlopende leerervaring voor zowel u, als voor onszelf.
Daarnaast hebben wij ervaren dat een directe lijn voor feedback naar de klant
de kwaliteit en de focus van het dienstverband enorm verbeteren.</p>
<p><company_short/> voert de activiteiten zoals genoemd in deze offerte uit
met haar kernteamleden, externe freelancers, en/of vrijwilligers.<br />
De eerste aanspreekpunt voor deze opdracht zijn:</p>
<ul>
<li><company_poc1/> (<company_short/>)</li>
<li><client_poc1/> (<client_short/>)</li>
</ul>
<p>De werkwijze van onze penetratietest-teams is gemodelleerd die van een
"<i>Capture The Flag</i>-team": <company_long/> heeft een
geografisch gedistribueerd team; wij gebruiken online infrastructuur
(RocketChat, GitLabs, etc.) om ons werk te coördineren. Dit geeft ons de
mogelijkheid om verscheidene technische mensen uit de organisatie van de
klant uit te nodigen om op vrijwillige basis samen te werken met ons
pentestteam. Uiteraard geldt deze uitnodiging ook voor <client_short/>.</p>
<p> <company_short/> betrekt <client_short/> actief bij het project door tussentijds
overleg te voeren over de voortgang van de <company_svc_short/> en over het proces.
Door deze manier van werken wordt het project een doorlopende leerervaring voor
zowel u als voor <company_short/>. <company_short/> heeft ervaren dat een
rechtstreeks contact met de klant tijdens het project de kwaliteit en de focus
van onze diensten aanzienlijk verbetert.</p>
</section>
<section>
<title>Rapportage</title>
<p><company_short/> zal rapporteren aan <client_short/> betreffende de
penetratie test. Dit rapport zal de genomen stappen bevatten die benodigd waren
gedurende de test en daarnaast de bevonden kwetsbaarheden. Daarnaast zal het
aanbevelingen bevatten, maar geen uitgebreide oplossingen om deze
kwetsbaarheden op te lossen.</p>
<p>Een voorbeeld van een Pentest rapport kan hier gevonden worden</p>
<ul>
<li><a href="https://github.com/radicallyopensecurity/templates/blob/master/sample-report/REP_SittingDuck-
pentestreport-v10.pdf">https://github.com/radicallyopensecurity/templates/blob/master/sample-report/REP_SittingDuck-
pentestreport-v10.pdf</a></li>
</ul>
<p>Een van <company_short/> haar kernwaarden is het
"Leer iemand Vissen" principe - ook bekend als het
"Meekijken over de Schouder" principe. Wij streven ernaar om
onze diensten te structureren, zodat zij kans kunnen bieden
om deze te benutten voor educatieve- of trainingsdoeleinden voor onze klanten.</p>
<p>
<company_short/> zal voor <client_short/> de tijdens de <company_svc_short/>
aangetroffen kwetsbaarheden onderzoeken en classificeren. Onze bevindingen verwerken we in een (Engelstalig)
rapport. De belangrijkste bevindingen worden voorzien van een gedetailleerd advies
voor het verbeteren van de onveilige situatie. De minder kritische bevindingen
zullen door ons minder gedetailleerd worden behandeld. Voorafgaand aan de oplevering
van het rapport krijgt <client_short/> inzage in de conceptversie, zodat er nog ruimte is voor
vragen en suggesties. De bevindingen uit het rapport zullen telefonisch en/of per email door
<client_short/> en <company_short/> worden besproken.
</p>
<p>Een voorbeeld van een pentestrapport vindt u hier:</p>
<ul>
<li>
<a
href="https://github.com/radicallyopensecurity/templates/blob/master/sample-report/REP_SittingDuck-
pentestreport-v10.pdf"
>https://github.com/radicallyopensecurity/templates/blob/master/sample-report/REP_SittingDuck-
pentestreport-v10.pdf</a>
</li>
</ul>
<p>Een van de kernwaarden van <company_short/> is het "Teach To Fish"-principe - ook
bekend als het "Peek over our Shoulder (PooS)"-principe. Wij streven ernaar
om onze diensten en rapporten zodanig te structureren dat onze klanten ze
mogelijk kunnen benutten voor educatieve of trainingsdoeleinden.</p>
</section>
</section>

View File

@@ -5,29 +5,28 @@
<section>
<title>Team</title>
<p><company_short/> voert de activiteiten zoals genoemd in deze offerte uit
met haar kern-teamleden, externe freelancers, en/of vrijwilligers.<br />
De eerste aanspreekpunt voor deze opdracht zijn:
met haar kernteamleden, externe freelancers, en/of vrijwilligers.<br />
De eerste aanspreekpunt voor deze opdracht zijn:</p>
<ul>
<li><company_poc1/> (<company_short/>)</li>
<li><client_poc1/> (<client_short/>)</li>
</ul>
</p>
<p>
<company_long/> werkt met een geografisch gespreid team. Onze teamleden bevinden
zich in verschillende uithoeken van de wereld. <company_short/> maakt gebruik van een eigen
online infrastructuur (RocketChat, GitLabs, et cetera) om het werk binnen het
online infrastructuur (RocketChat, GitLabs, etcetera) om het werk binnen het
team te coördineren. De online infrastructuur biedt ons de mogelijkheid
om technische mensen uit de organisatie van <client_short/> uit te nodigen op
vrijwillige basis met ons pentestteam samen te werken. Natuurlijk geldt deze
vrijwillige basis met ons pentestteam samen te werken. Uiteraard geldt deze
uitnodiging ook voor <generate_permission_parties/>.
</p>
<p> <company_short/> betrekt <client_short/> actief bij het project door tussentijds
overleg te voeren over de voortgang van de <company_svc_short/> en over het proces.
Door deze manier van werken wordt het project een doorlopende leerervaring voor
zowel u, als voor <company_short/>. <company_short/> heeft ervaren dat een
rechtstreeks contact met de klant tijdens het project, de kwaliteit en de focus
zowel u als voor <company_short/>. <company_short/> heeft ervaren dat een
rechtstreeks contact met de klant tijdens het project de kwaliteit en de focus
van onze diensten aanzienlijk verbetert.</p>
</section>
@@ -35,18 +34,18 @@
<title>Rapportage</title>
<p>
<company_short/> zal voor <client_short/> de tijdens de <company_svc_short/>
aangetroffen kwetsbaarheden onderzoeken en classificeren. Onze bevindingen verwerken we in een Engelstalig
aangetroffen kwetsbaarheden onderzoeken en classificeren. Onze bevindingen verwerken we in een (Engelstalig)
rapport. De belangrijkste bevindingen worden voorzien van een gedetailleerd advies
voor het verbeteren van de onveilige situatie. De minder kritische bevindingen
zullen door ons minder gedetailleerd worden behandeld. Voorafgaand aan de oplevering
van het rapport, krijgt <client_short/> inzage in de conceptversie zodat er nog ruimte is voor
vragen en suggesties. De bevindinen uit het rapport zullen telefonisch en/of per email door
van het rapport krijgt <client_short/> inzage in de conceptversie, zodat er nog ruimte is voor
vragen en suggesties. De bevindingen uit het rapport zullen telefonisch en/of per email door
<client_short/> en <company_short/> worden besproken.
</p>
<p>
De managementsamenvatting wordt door <client_short/> zelf geschreven. Het rapport
zal een omschrijving van de stappen en de gevonden kwetsbaarheden bevatten.
Daarnaast zal het aanbevelingen bevatten (maar geen uitgebreide oplossingen) om
De managementsamenvatting wordt door <client_short/> zelf geschreven. Het volledige rapport
bevat een omschrijving van alle stappen en de gevonden kwetsbaarheden.
Daarnaast bevat het aanbevelingen (maar geen uitgebreide oplossingen) om
de kwetsbaarheden te verhelpen. Het rapport wordt voorzien van een bijlage (annex)
met ruwe testgegevens.
</p>

View File

@@ -28,9 +28,7 @@ in de veiligheid van deze systemen. <company_short/> zal zich daartoe toegang ve
deze systemen om op zoek te gaan naar kwetsbaarheden. Vervolgens zal worden getracht
dergelijke kwetsbaarheden uit te buiten om verdere toegang en verhoogde privileges
te bemachtigen. <company_short/> zal de volgende doelwitten testen (de “Doelwitten”):
<ul>
<li>Doelsysteem</li>
</ul>
<generate_targets/>
</p>
<p>2. <i><signee_short/></i> verklaart hierbij <company_short/> en de Consultants op een datum die
per email zal worden bevestigd de meest uitvoerige toestemming te verlenen voor

View File

@@ -1,5 +1,19 @@
<finding id="..." threatLevel="Moderate" type="Information Leak">
<!-- Note: threatLevel can be Low, Moderate, Elevated, High or Extreme; type is free text -->
<!--
id needs to be unique across the report, preferably identical to the filename
(without extension).
threatLevel can be Low, Moderate, Elevated, High or Extreme.
type is the root cause, written in Title Case.
Examples: Easily Guessable Credentials
Lack Of Application Hardening
Lack Of Webserver Hardening
Missing Patch
Network Design Flaw
-->
<title>Title Case</title>

View File

@@ -76,8 +76,6 @@
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
href="snippets/report/methodology.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="code-audit-methodology.xml"/>
<section id="recon" break="before">
<title>Reconnaissance and Fingerprinting</title>
<p>Through automated scans we were able to gain the following information about the

View File

@@ -21,9 +21,11 @@
<xsl:import href="waiver.xslt"/>-->
<xsl:include href="styles_inv.xslt"/>
<xsl:include href="localisation.xslt"/>
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="lang" select="/*/@xml:lang"/>
<!-- ****** AUTO_NUMBERING_FORMAT: value of the <xsl:number> element used for auto numbering -->
<!--<xsl:param name="AUTO_NUMBERING_FORMAT" select="'1.1.1'"/>-->
@@ -76,7 +78,8 @@
<fo:table-body>
<fo:table-row>
<fo:table-cell xsl:use-attribute-sets="td">
<fo:block><xsl:value-of select="/offerte/meta/pentestinfo/duration"/>-day&#160;<xsl:value-of select="/offerte/meta/offered_service_short"/>&#160;<xsl:value-of select="/offerte/meta/permission_parties/client/short_name"/></fo:block>
<fo:block><xsl:value-of select="/offerte/meta/pentestinfo/duration"/>-
<xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_days'"/></xsl:call-template>&#160;<xsl:value-of select="/offerte/meta/offered_service_short"/>&#160;<xsl:value-of select="/offerte/meta/permission_parties/client/short_name"/></fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="td align-right">
<fo:block xsl:use-attribute-sets="p"><xsl:value-of select="$denomination"/>&#160;<xsl:number value="$fee" grouping-separator="," grouping-size="3"/>.--</fo:block>
@@ -84,7 +87,7 @@
</fo:table-row>
<fo:table-row>
<fo:table-cell xsl:use-attribute-sets="td">
<fo:block>VAT 21%</fo:block>
<fo:block><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_vat'"/></xsl:call-template> 21%</fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="td align-right">
<fo:block xsl:use-attribute-sets="p"><xsl:value-of select="$denomination"/>&#160;<xsl:number value="$vat" grouping-separator="," grouping-size="3"/>.--</fo:block>
@@ -92,7 +95,7 @@
</fo:table-row>
<fo:table-row xsl:use-attribute-sets="border-top bold">
<fo:table-cell xsl:use-attribute-sets="td">
<fo:block>Total amount to be paid</fo:block>
<fo:block><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_total'"/></xsl:call-template></fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="td align-right">
<fo:block xsl:use-attribute-sets="p"><xsl:value-of select="$denomination"/>&#160;<xsl:number value="$vat + $fee" grouping-separator="," grouping-size="3"/>.--</fo:block>
@@ -109,9 +112,9 @@
<xsl:template name="custom_invoice">
<xsl:variable name="denomination">
<xsl:choose>
<xsl:when test="/invoice/@denomination = 'usd'">$</xsl:when>
<xsl:when test="/invoice/@denomination = 'eur'"></xsl:when>
<xsl:when test="/invoice/@denomination = 'gbp'">£</xsl:when>
<xsl:when test="/invoice/@denomination = 'usd'">$</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="invoiceStart">
@@ -137,7 +140,7 @@
<xsl:if test="additionalcosts">
<fo:table-row>
<fo:table-cell xsl:use-attribute-sets="td padding-top">
<fo:block xsl:use-attribute-sets="bold">Additional Expenses</fo:block>
<fo:block xsl:use-attribute-sets="bold"><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_additional'"/></xsl:call-template></fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="td align-right padding-top">
<fo:block xsl:use-attribute-sets="p">&#160;</fo:block>
@@ -165,7 +168,7 @@
</xsl:variable>
<fo:table-row>
<fo:table-cell xsl:use-attribute-sets="td padding-top">
<fo:block>VAT 21%</fo:block>
<fo:block><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_vat'"/></xsl:call-template> 21%</fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="td align-right padding-top">
<fo:block xsl:use-attribute-sets="p"><xsl:value-of select="$denomination"/>&#160;<xsl:number value="$vat" grouping-separator="," grouping-size="3"/>.--</fo:block>
@@ -173,7 +176,7 @@
</fo:table-row>
<fo:table-row xsl:use-attribute-sets="border-top bold">
<fo:table-cell xsl:use-attribute-sets="td">
<fo:block>Total amount to be paid</fo:block>
<fo:block><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_total'"/></xsl:call-template></fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="td align-right">
<fo:block xsl:use-attribute-sets="p"><xsl:value-of select="$denomination"/>&#160;<xsl:number value="$total" grouping-separator="," grouping-size="3"/>.--</fo:block>
@@ -190,14 +193,14 @@
<xsl:template name="invoiceStart">
<xsl:param name="INVOICE_NO"/>
<xsl:param name="DATE"/>
<fo:block xsl:use-attribute-sets="title-0">Invoice nr. <xsl:value-of select="$INVOICE_NO"
<fo:block xsl:use-attribute-sets="title-0"><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_no'"/></xsl:call-template><xsl:text>&#160;</xsl:text><xsl:value-of select="$INVOICE_NO"
/></fo:block>
<fo:block>
<fo:block>
<xsl:value-of select="/*/meta//client/full_name"/>
</fo:block>
<fo:block>
<xsl:if test="/*/meta//client/invoice_rep">T.a.v. <xsl:value-of
<xsl:if test="/*/meta//client/invoice_rep"><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_fao'"/></xsl:call-template><xsl:text>&#160;</xsl:text><xsl:value-of
select="/offerte/meta/permission_parties/client/invoice_rep"/></xsl:if>
</fo:block>
<fo:block>
@@ -217,27 +220,26 @@
<fo:block xsl:use-attribute-sets="p big-space-below" text-align="right">
<xsl:value-of select="$DATE"/>
</fo:block>
<fo:block xsl:use-attribute-sets="title-2">Services Delivered</fo:block>
<fo:block xsl:use-attribute-sets="title-2"><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_svcdeliv'"/></xsl:call-template></fo:block>
</xsl:template>
<xsl:template name="invoiceEnd">
<xsl:param name="INVOICE_NO"/>
<fo:block xsl:use-attribute-sets="big-space-below"><xsl:value-of
select="/*/meta/company/full_name"/> donates > 90% of its entire profits to
charity.</fo:block>
<fo:block xsl:use-attribute-sets="big-space-below">Please be so kind to pay within 30 days
by money transfer, to the following account:</fo:block>
select="/*/meta/company/full_name"/><xsl:text>&#160;</xsl:text><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_donation'"/></xsl:call-template></fo:block>
<fo:block xsl:use-attribute-sets="big-space-below"><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_pleasepay'"/></xsl:call-template></fo:block>
<fo:block xsl:use-attribute-sets="big-space-below" margin-left="1.3cm">
<fo:block>
<xsl:value-of select="/*/meta/company/full_name"/>
</fo:block>
<fo:block>IBAN: <xsl:value-of select="/*/meta/company/iban"/></fo:block>
<fo:block>Reference: <xsl:value-of select="$INVOICE_NO"/></fo:block>
<fo:block>
<xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_iban'"/></xsl:call-template>: <xsl:value-of select="/*/meta/company/iban"/></fo:block>
<fo:block><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_ref'"/></xsl:call-template>: <xsl:value-of select="$INVOICE_NO"/></fo:block>
</fo:block>
<fo:block>Kind regards,</fo:block>
<fo:block>your dedicated team at</fo:block>
<fo:block><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_regards'"/></xsl:call-template>,</fo:block>
<fo:block><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_team'"/></xsl:call-template></fo:block>
<fo:block font-style="italic">
<xsl:value-of select="/*/meta/company/full_name"/>
</fo:block>
@@ -287,8 +289,8 @@
<fo:block xsl:use-attribute-sets="TinyFont">
<fo:block xsl:use-attribute-sets="bold orange-text"><xsl:value-of select="/*/meta/company/website"/></fo:block>
<fo:block><xsl:value-of select="/*/meta/company/email"/></fo:block>
<fo:block>Chamber of Commerce <xsl:value-of select="/*/meta/company/coc"/></fo:block>
<fo:block>VAT number <xsl:value-of select="/*/meta/company/vat_no"/></fo:block>
<fo:block><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'page_kvk'"/></xsl:call-template><xsl:text>&#160;</xsl:text><xsl:value-of select="/*/meta/company/coc"/></fo:block>
<fo:block><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_vatno'"/></xsl:call-template><xsl:text>&#160;</xsl:text><xsl:value-of select="/*/meta/company/vat_no"/></fo:block>
</fo:block>
</fo:table-cell>
</fo:table-row>
@@ -304,12 +306,12 @@
<xsl:template name="page_footer">
<fo:static-content flow-name="region-after-cover" xsl:use-attribute-sets="FooterFont">
<fo:block xsl:use-attribute-sets="footer">
<fo:inline xsl:use-attribute-sets="TinyFont orange-text">Please keep digital unless absolutely required. Read the (unique) terms and conditions of Radically Open Security at: https://radicallyopensecurity.com/TermsandConditions.pdf</fo:inline>
<fo:inline xsl:use-attribute-sets="TinyFont orange-text"><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_yaygreen'"/></xsl:call-template></fo:inline>
</fo:block>
</fo:static-content>
<fo:static-content flow-name="region-after-content" xsl:use-attribute-sets="FooterFont">
<fo:block xsl:use-attribute-sets="footer">
<fo:inline xsl:use-attribute-sets="TinyFont orange-text">Please keep digital unless absolutely required. Read the (unique) terms and conditions of Radically Open Security at: https://radicallyopensecurity.com/TermsandConditions.pdf</fo:inline>
<fo:inline xsl:use-attribute-sets="TinyFont orange-text"><xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_yaygreen'"/></xsl:call-template></fo:inline>
</fo:block>
</fo:static-content>
</xsl:template>

View File

@@ -18,8 +18,7 @@
<xsl:import href="graphics.xslt"/>
<xsl:import href="generic.xslt"/>
<xsl:import href="numbering.xslt"/>
<xsl:import href="placeholders.xslt"/><!--
<xsl:import href="snippets.xslt"/>-->
<xsl:import href="placeholders.xslt"/>
<xsl:import href="waiver.xslt"/>
<xsl:include href="localisation.xslt"/>

View File

@@ -3,11 +3,15 @@
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:fo="http://www.w3.org/1999/XSL/Format" exclude-result-prefixes="xs" version="2.0">
<xsl:include href="localisation.xslt"/>
<xsl:param name="INVOICE_NO">00/000</xsl:param>
<xsl:param name="DATE">
<xsl:value-of select="format-date(current-date(), '[Y]-[M,2]-[D1]', 'en', (), ())"/>
<xsl:value-of select="format-date(current-date(), '[Y]-[M,2]-[D,2]', 'en', (), ())"/>
</xsl:param>
<xsl:variable name="lang" select="/*/@xml:lang"/>
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- ROOT -->
@@ -22,6 +26,9 @@
<xsl:attribute name="invoice_no">
<xsl:value-of select="$INVOICE_NO"/>
</xsl:attribute>
<xsl:attribute name="xml:lang">
<xsl:value-of select="$lang"/>
</xsl:attribute>
<xsl:attribute name="denomination">
<xsl:value-of select="/offerte/meta/pentestinfo/fee/@denomination"/>
</xsl:attribute>
@@ -34,18 +41,30 @@
</xsl:element>
</meta>
<servicesdelivered>
<xsl:comment>Add/delete &lt;service> elements as needed</xsl:comment>
<service>
<description>
<xsl:value-of select="/offerte/meta/pentestinfo/duration"
/>-day&#160;<xsl:value-of select="/offerte/meta/offered_service_short"
/>-<xsl:call-template name="getString"><xsl:with-param name="stringID" select="'invoice_days'"/></xsl:call-template>&#160;<xsl:value-of select="/offerte/meta/offered_service_short"
/>&#160;<xsl:value-of
select="/offerte/meta/permission_parties/client/short_name"/>
</description>
<fee>
<fee vat="yes">
<xsl:value-of select="/offerte/meta/pentestinfo/fee"/>
</fee>
</service>
</servicesdelivered>
<additionalcosts>
<xsl:comment>Add/delete &lt;cost> elements as needed</xsl:comment>
<cost>
<description>...</description>
<fee vat="yes">0</fee>
</cost>
<cost>
<description>...</description>
<fee vat="yes">0</fee>
</cost>
</additionalcosts>
</invoice>

View File

@@ -61,7 +61,7 @@
<version_history>
<xsl:comment>needed for date on frontpage and in signature boxes; it is possible to add a new &lt;version> after each review; in that case, make sure to update the date/time</xsl:comment>
<version number="auto">
<xsl:attribute name="date"><xsl:value-of select="format-date(current-date(), '[Y]-[M,2]-[D1]', 'en', (), ())"/>T10:00:00</xsl:attribute>
<xsl:attribute name="date"><xsl:value-of select="format-date(current-date(), '[Y]-[M,2]-[D,2]', 'en', (), ())"/>T10:00:00</xsl:attribute>
<xsl:comment>actual date-time here; you can leave the number attribute alone</xsl:comment>
<v_author>ROS Writer</v_author>
<xsl:comment>name of the author here; for internal use only</xsl:comment>

View File

@@ -68,7 +68,11 @@
<fo:page-number/>/<fo:page-number-citation ref-id="EndOfDoc"/>
<fo:leader leader-pattern="space"/>
<fo:inline xsl:use-attribute-sets="TinyFont"><xsl:value-of
select="*/meta/company/full_name"/> - Chamber of Commerce
select="*/meta/company/full_name"/><xsl:text> - </xsl:text>
<xsl:call-template name="getString">
<xsl:with-param name="stringID" select="'page_kvk'"/>
</xsl:call-template>
<xsl:text>&#160;</xsl:text>
<xsl:value-of select="*/meta/company/coc"/></fo:inline>
</fo:block>
</fo:static-content>
@@ -77,7 +81,11 @@
<fo:page-number/>/<fo:page-number-citation ref-id="EndOfDoc"/>
<fo:leader leader-pattern="space"/>
<fo:inline xsl:use-attribute-sets="TinyFont"><xsl:value-of
select="*/meta/company/full_name"/> - Chamber of Commerce
select="*/meta/company/full_name"/><xsl:text> - </xsl:text>
<xsl:call-template name="getString">
<xsl:with-param name="stringID" select="'page_kvk'"/>
</xsl:call-template>
<xsl:text>&#160;</xsl:text>
<xsl:value-of select="*/meta/company/coc"/></fo:inline>
</fo:block>
</fo:static-content>

View File

@@ -147,6 +147,12 @@
<xsl:with-param name="placeholderElement" select="$placeholderElement"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="p_mandays">
<xsl:param name="placeholderElement" select="/*/meta/pentestinfo/mandays"/>
<xsl:call-template name="checkPlaceholder">
<xsl:with-param name="placeholderElement" select="$placeholderElement"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="p_boxtype">
<xsl:param name="placeholderElement" select="/*/meta/pentestinfo/type"/>
<xsl:call-template name="checkPlaceholder">

View File

@@ -89,14 +89,18 @@
<xsl:value-of select="/*/pentest_info/days"/>
</duration>
<xsl:comment>duration of pentest, in working days</xsl:comment>
<mandays>
<xsl:value-of select="/*/pentest_info/mandays"/>
</mandays>
<xsl:comment>duration of pentest, in mandays</xsl:comment>
<test_planning>
<xsl:value-of select="/*/pentest_info/planning"/>
</test_planning>
<xsl:comment>date or date range in text, e.g. May 18th until May 25th, 2015</xsl:comment>
<xsl:comment>date or date range in text, e.g. May 18th until May 25th, 2016</xsl:comment>
<report_due>
<xsl:value-of select="/*/pentest_info/delivery"/>
</report_due>
<xsl:comment>date or date range in text, e.g. May 18th until May 25th, 2015</xsl:comment>
<xsl:comment>date or date range in text, e.g. May 18th until May 25th, 2016</xsl:comment>
<nature>
<xsl:value-of select="/*/pentest_info/nature"/>
</nature>

View File

@@ -110,10 +110,16 @@
</xsl:if>
</fo:block>
<xsl:apply-templates/>
<xsl:call-template name="generate_waiver_signature_box"/>
</xsl:template>
<xsl:template match="generate_waiver_signature_box">
<xsl:template name="generate_waiver_signature_box">
<xsl:param name="signee_long" tunnel="yes"/>
<xsl:param name="signee_waiver_rep" tunnel="yes"/>
<xsl:param name="signee_city" tunnel="yes"/>
<fo:block keep-together.within-page="always" xsl:use-attribute-sets="signaturebox">
<fo:table width="100%" table-layout="fixed">
<fo:table-column column-width="proportional-column-width(10)"/>
@@ -138,20 +144,20 @@
<fo:table-cell xsl:use-attribute-sets="td">
<fo:block xsl:use-attribute-sets="p"><xsl:call-template name="getString">
<xsl:with-param name="stringID" select="'waiver_signed_in'"/>
</xsl:call-template> &#160;&#160;&#160; <xsl:value-of select="city"
</xsl:call-template> &#160;&#160;&#160; <xsl:value-of select="$signee_city"
/></fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell xsl:use-attribute-sets="td">
<xsl:choose>
<xsl:when test="waiver_rep">
<xsl:when test="$signee_waiver_rep">
<fo:block xsl:use-attribute-sets="p"><xsl:call-template
name="getString">
<xsl:with-param name="stringID"
select="'waiver_signed_by'"/>
</xsl:call-template> &#160;&#160;&#160;<xsl:value-of
select="waiver_rep"/></fo:block>
select="$signee_waiver_rep"/></fo:block>
</xsl:when>
<xsl:otherwise>
<fo:block xsl:use-attribute-sets="p"><xsl:call-template
@@ -169,7 +175,7 @@
<fo:block xsl:use-attribute-sets="p"><xsl:call-template name="getString">
<xsl:with-param name="stringID" select="'waiver_signed_for'"/>
</xsl:call-template> &#160;&#160;&#160;<xsl:value-of
select="full_name"/></fo:block>
select="$signee_long"/></fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
@@ -177,6 +183,9 @@
</fo:block>
</xsl:template>
<!-- deprecated element; ignore if still there -->
<xsl:template match="generate_waiver_signature_box"/>
<!-- special waiver placeholders -->
<!-- (tunnel ftw ;) -->
<xsl:template match="signee_long">