Commit 59eb813b authored by Sophie Brun's avatar Sophie Brun Committed by Lorenzo Faletra

Import Debian changes 3.7.0-0kali1

python-faraday (3.7.0-0kali1) kali-dev; urgency=medium

  * New upstream version 3.7.0 
parents f966a230 0f1e5bca
......@@ -16,6 +16,8 @@ The PRIMARY AUTHORS are:
* Micaela Ranea Sánchez
* Sebastian Kulesz
* Eric Horvat
* Jorge Luis González Iznaga
* Javier Montilva
Project contributors
......
* Add vulnerability preview to status report
* Update Fierce Plugin. Import can be done from GTK console.
* Update Goohost plugin and now Faraday imports Goohost .txt report.
* Update plugin for support WPScan v-3.4.5
* Update Qualysguard plugin to its 8.17.1.0.2 version
* Update custom fields with Searcher
* Update Recon-ng Plugin so that it accepts XML reports
* Add postres version to status-change command
* Couchdb configuration section will not be added anymore
* Add unit test for config/default.xml
......@@ -9,6 +9,20 @@ New features in the latest update
=====================================
3.7 [Apr 3rd, 2019]:
---
* New feature vulnerability preview to view vulnerability data.
* Update Fierce Plugin. Import can be done from GTK console.
* Update Goohost plugin and now Faraday imports Goohost .txt report.
* Update plugin for support WPScan v-3.4.5
* Update Qualysguard plugin to its 8.17.1.0.2 version
* Update custom fields with Searcher
* Update Recon-ng Plugin so that it accepts XML reports
* Add postres version to status-change command
* Couchdb configuration section will not be added anymore
* Add unit test for config/default.xml
3.6 [Feb 21th, 2019]:
---
* Fix CSRF (Cross-Site Request Forgery) vulnerability in vulnerability attachments API.
......
......@@ -9,6 +9,20 @@ New features in the latest update
=====================================
3.7 [Apr 3rd, 2019]:
---
* New feature vulnerability preview to view vulnerability data.
* Update Fierce Plugin. Import can be done from GTK console.
* Update Goohost plugin and now Faraday imports Goohost .txt report.
* Update plugin for support WPScan v-3.4.5
* Update Qualysguard plugin to its 8.17.1.0.2 version
* Update custom fields with Searcher
* Update Recon-ng Plugin so that it accepts XML reports
* Add postres version to status-change command
* Couchdb configuration section will not be added anymore
* Add unit test for config/default.xml
3.6 [Feb 21th, 2019]:
---
* Fix CSRF (Cross-Site Request Forgery) vulnerability in vulnerability attachments API.
......
......@@ -2,7 +2,7 @@
<faraday>
<appname>Faraday - Penetration Test IDE</appname>
<version>3.6.0</version>
<version>3.7.0</version>
<debug_status>0</debug_status>
<font>-Misc-Fixed-medium-r-normal-*-12-100-100-100-c-70-iso8859-1</font>
<home_path>~/</home_path>
......
python-faraday (3.6.0-1parrot2) testing; urgency=medium
python-faraday (3.7.0-0kali1) kali-dev; urgency=medium
* Allow marshmallow 2.15.3 only (credits: dmknght).
* New upstream version 3.7.0
-- Lorenzo "Palinuro" Faletra <palinuro@parrotsec.org> Wed, 20 Mar 2019 00:50:48 +0100
-- Sophie Brun <sophie@offensive-security.com> Fri, 05 Apr 2019 15:03:12 +0200
python-faraday (3.6.0-1parrot1) testing; urgency=medium
python-faraday (3.6.0-0kali3) kali-dev; urgency=medium
* Import new upstream release.
* Add a missing depend: python-pip
-- Lorenzo "Palinuro" Faletra <palinuro@parrotsec.org> Thu, 28 Feb 2019 14:05:14 +0100
-- Sophie Brun <sophie@offensive-security.com> Fri, 29 Mar 2019 14:57:21 +0100
python-faraday (3.5.0-1parrot2) testing; urgency=medium
python-faraday (3.6.0-0kali2) kali-dev; urgency=medium
* Import new upstream release.
* Prompt the password initialization the first time (see 5366)
-- Lorenzo "Palinuro" Faletra <palinuro@parrotsec.org> Tue, 05 Feb 2019 17:58:08 +0100
-- Sophie Brun <sophie@offensive-security.com> Thu, 28 Mar 2019 14:38:37 +0100
python-faraday (3.4-1parrot1) testing; urgency=medium
python-faraday (3.6.0-0kali1) kali-dev; urgency=medium
* Import new upstream release.
* New upstream version 3.6.0
-- Lorenzo "Palinuro" Faletra <palinuro@parrotsec.org> Sat, 22 Dec 2018 11:01:55 +0100
-- Sophie Brun <sophie@offensive-security.com> Fri, 22 Feb 2019 10:32:15 +0100
python-faraday (3.3-1parrot1) testing; urgency=medium
python-faraday (3.5.0-0kali2) kali-dev; urgency=medium
* Import new upstream release.
* Improve database migration in postinst when systemd is not used
-- Lorenzo "Palinuro" Faletra <palinuro@parrotsec.org> Wed, 28 Nov 2018 03:33:08 +0100
-- Sophie Brun <sophie@offensive-security.com> Tue, 05 Feb 2019 09:35:55 +0100
python-faraday (3.2-1parrot1) testing; urgency=medium
python-faraday (3.5.0-0kali1) kali-dev; urgency=medium
* Import new upstream release.
* New upstream version 3.5.0
* Update dependencies
* Bump Standards-Version
* Update lintian-overrides
* Refresh patches
* d/rules: fix permissions
* Migrate database if upgrade
* Import upstream patch to fix issues: admin creation and dir creation
-- Sophie Brun <sophie@offensive-security.com> Mon, 04 Feb 2019 16:24:53 +0100
python-faraday (3.4-0kali1) kali-dev; urgency=medium
* Update debian/copyright
* New upstream version 3.4
* Update email address
* Add missing depends: python-flask-restless
-- Lorenzo "Palinuro" Faletra <palinuro@parrotsec.org> Thu, 01 Nov 2018 21:19:34 +0100
-- Sophie Brun <sophie@offensive-security.com> Wed, 19 Dec 2018 11:33:12 +0100
python-faraday (3.1.1-0parrot1) testing; urgency=medium
python-faraday (3.3-0kali1) kali-dev; urgency=medium
* Disable autostart.
* Import new upstream release
-- Sophie Brun <sophie@freexian.com> Fri, 23 Nov 2018 15:55:57 +0100
python-faraday (3.2-0kali1) kali-dev; urgency=medium
* Import new upstream release
-- Lorenzo "Palinuro" Faletra <palinuro@parrotsec.org> Fri, 19 Oct 2018 18:48:19 +0200
-- Sophie Brun <sophie@freexian.com> Wed, 24 Oct 2018 10:18:27 +0200
python-faraday (3.1.1-0kali1) kali-dev; urgency=medium
......
Source: python-faraday
Section: python
Priority: optional
Maintainer: Parrot Dev Team <team@parrotsec.org>
Uploaders: Lorenzo "Palinuro" Faletra <palinuro@parrotsec.org>
Build-Depends: debhelper (>= 11), dh-python, python
Maintainer: Kali Developers <devel@kali.org>
Uploaders: Sophie Brun <sophie@offensive-security.com>
Build-Depends: debhelper-compat (= 12), dh-python, python
Standards-Version: 4.3.0
Homepage: https://faradaysec.com
Vcs-Git: git://git.parrotsec.org/security-tools/python-faraday
Vcs-Browser: https://nest.parrotsec.org/security-tools/python-faraday
Homepage: http://faradaysec.com
Vcs-Git: git://git.kali.org/packages/python-faraday.git
Vcs-Browser: http://git.kali.org/gitweb/?p=packages/python-faraday.git;a=summary
Package: python-faraday
Architecture: all
......@@ -40,6 +40,7 @@ Depends: curl,
python-nplusone,
python-openssl,
python-pil,
python-pip,
python-psycopg2,
python-pyasn1-modules,
python-requests,
......
#!/bin/sh
aux_file_path="$HOME/.faraday/password_changed.txt"
systemctl start python-faraday
sleep 3
cd /usr/share/python-faraday && ./faraday.py "$@"
if [ ! -f $aux_file_path ]; then
touch $aux_file_path
cd /usr/share/python-faraday
echo "Please, set a new password for the Faraday's default user 'faraday'"
./manage.py change-password
./faraday.py --login
else
cd /usr/share/python-faraday && ./faraday.py "$@"
fi
systemctl stop python-faraday
Description: Allow marshmallow 2.15.3 only
Author: dmknght
Origin: https://nest.parrotsec.org/security-tools/python-faraday/merge_requests/1/
Reviewed-By: Lorenzo "Palinuro" Faletra <palinuro@parrotsec.org>
Last-Update: 2019-03-19
--- python-faraday-3.6.0.orig/requirements_server.txt
+++ python-faraday-3.6.0/requirements_server.txt
@@ -10,7 +10,7 @@ flask-session>=0.3.1
flask>=1.0
future>=0.17.1
IPy>=0.83
-marshmallow>=2.15.3
+marshmallow==2.15.3
Pillow>=4.2.1
psycopg2>=2.7.1
pyasn1-modules>=0.0.11
......@@ -2,4 +2,3 @@ remove-unwanted-checks.diff
copy-images-directory.patch
fix-syntax-error.patch
fix-path-to-VERSION.patch
fix-marshmallow-version.patch
......@@ -7,3 +7,6 @@ After=postgresql.service
Type=simple
ExecStartPre=/bin/sh -c 'if ! su postgres -c "psql -lqt" | cut -d \| -f 1 | grep -qw faraday; then cd /usr/share/python-faraday && python manage.py initdb; fi'
ExecStart=/usr/share/python-faraday/faraday-server.py
[Install]
WantedBy=multi-user.target
"""add markdown column to exectuive reports
Revision ID: 5272b3f5a820
Revises: 2ca03a8feef5
Create Date: 2019-03-27 19:26:28.354078+00:00
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '5272b3f5a820'
down_revision = '2ca03a8feef5'
branch_labels = None
depends_on = None
def upgrade():
op.add_column('executive_report', sa.Column('markdown', sa.Boolean(), nullable=False, server_default='False'))
def downgrade():
op.drop_column('executive_report', 'markdown')
......@@ -12,6 +12,7 @@ import socket
import re
import os
import sys
import random
current_path = os.path.abspath(os.getcwd())
......@@ -41,48 +42,61 @@ class FierceParser(object):
"""
def __init__(self, output):
self.target = None
self.items = []
r = re.search(
"DNS Servers for ([\w\.-]+):\r\n([^$]+)Trying zone transfer first...",
regex = re.search(
"DNS Servers for ([\w\.-]+):\n([^$]+)Trying zone transfer first...",
output)
if r is not None:
self.target = r.group(1)
mstr = re.sub("\t", "", r.group(2))
self.dns = mstr.split()
if regex is not None:
self.target = regex.group(1)
mstr = re.sub("\t", "", regex.group(2))
self.dns = filter(None, mstr.splitlines())
r = re.search(
"Now performing [\d]+ test\(s\)...\r\n([^$]+)\x0D\nSubnets found ",
regex = re.search(
"Now performing [\d]+ test\(s\)...\n([^$]+)\nSubnets found ",
output)
if r is not None:
list = r.group(1).split("\r\n")
for i in list:
if regex is not None:
hosts_list = regex.group(1).splitlines()
for i in hosts_list:
if i != "":
mstr = i.split("\t")
item = {'host': mstr[1], 'type': "A", 'ip': mstr[0]}
self.items.append(item)
host = mstr[1]
record = "A"
ip = mstr[0]
self.add_host_info_to_items(ip, host, record)
self.isZoneVuln = False
output= output.replace('\\$', '')
r = re.search(
output = output.replace('\\$', '')
regex = re.search(
"Whoah, it worked - misconfigured DNS server found:([^$]+)\There isn't much point continuing, you have everything.", output)
if r is not None:
if regex is not None:
self.isZoneVuln = True
list = r.group(1).split("\n")
for i in list:
dns_list = regex.group(1).splitlines()
for i in dns_list:
if i != "":
mstr = i.split()
if (mstr and mstr[0] != "" and len(mstr) > 3 and mstr[3] in valid_records):
item = {'host': mstr[0],
'type': mstr[3], 'ip': mstr[4]}
self.items.append(item)
host = mstr[0]
record = mstr[3]
ip = mstr[4]
self.add_host_info_to_items(ip, host, record)
def add_host_info_to_items(self, ip_address, hostname, record):
data = {}
exists = False
for item in self.items:
if ip_address in item['ip']:
item['hosts'].append(hostname)
exists = True
if not exists:
data['ip'] = ip_address
data['hosts'] = [hostname]
data['record'] = record
self.items.append(data)
class FiercePlugin(core.PluginBase):
......@@ -103,6 +117,8 @@ class FiercePlugin(core.PluginBase):
r'^(sudo fierce|fierce|sudo fierce\.pl|fierce\.pl|perl fierce\.pl|\.\/fierce\.pl).*?')
global current_path
self.xml_arg_re = re.compile(r"^.*(>\s*[^\s]+).*$")
def canParseCommandString(self, current_input):
if self._command_regex.match(current_input.strip()):
return True
......@@ -111,7 +127,7 @@ class FiercePlugin(core.PluginBase):
def resolveCNAME(self, item, items):
for i in items:
if (i['host'] == item['ip']):
if (item['ip'] in i['hosts']):
item['ip'] = i['ip']
return item
try:
......@@ -122,7 +138,7 @@ class FiercePlugin(core.PluginBase):
def resolveNS(self, item, items):
try:
item['host'] = item['ip']
item['hosts'][0] = item['ip']
item['ip'] = socket.gethostbyname(item['ip'])
except:
pass
......@@ -135,9 +151,9 @@ class FiercePlugin(core.PluginBase):
item['isResolver'] = False
item['isZoneVuln'] = False
if (item['type'] == "CNAME"):
if (item['record'] == "CNAME"):
self.resolveCNAME(item, parser.items)
if (item['type'] == "NS"):
if (item['record'] == "NS"):
self.resolveNS(item, parser.items)
item['isResolver'] = True
item['isZoneVuln'] = parser.isZoneVuln
......@@ -149,20 +165,15 @@ class FiercePlugin(core.PluginBase):
item['ip'] = ''
for item in parser.items:
if item['ip'] == "127.0.0.1" or item['ip'] == '':
continue
h_id = self.createAndAddHost(item['ip'])
i_id = self.createAndAddInterface(
h_id,
h_id = self.createAndAddHost(
item['ip'],
ipv4_address=item['ip'],
hostname_resolution=[item['host']])
hostnames=item['hosts'])
if item['isResolver']:
s_id = self.createAndAddServiceToInterface(
s_id = self.createAndAddServiceToHost(
h_id,
i_id,
"domain",
"tcp",
ports=['53'])
......@@ -176,7 +187,22 @@ class FiercePlugin(core.PluginBase):
ref=["CVE-1999-0532"])
def processCommandString(self, username, current_path, command_string):
return None
self._output_file_path = os.path.join(
self.data_path,
"%s_%s_output-%s.txt" % (
self.get_ws(),
self.id,
random.uniform(1, 10))
)
arg_match = self.xml_arg_re.match(command_string)
if arg_match is None:
return "%s > %s" % (command_string, self._output_file_path)
else:
return re.sub(arg_match.group(1),
r"> %s" % self._output_file_path,
command_string)
def createPlugin():
......
......@@ -34,31 +34,25 @@ class GoohostParser(object):
TODO: Test goohost output version. Handle what happens if the parser doesn't support it.
TODO: Test cases.
@param goohost_filepath A proper simple report generated by goohost
@param goohost_scantype You could select scan type ip, mail or host
"""
def __init__(self, goohost_filepath, goohost_scantype):
self.filepath = goohost_filepath
self.scantype = goohost_scantype
def __init__(self, output, goohost_scantype):
with open(self.filepath, "r") as f:
line = f.readline()
self.items = []
while line:
if self.scantype == 'ip':
minfo = line.split()
item = {'host': minfo[0], 'ip': minfo[1]}
elif self.scantype == 'host':
line = line.strip()
item = {'host': line, 'ip': self.resolve(line)}
lines = filter(None, output.split('\n'))
for line in lines:
if goohost_scantype == 'ip':
data = line.split()
item = {'host': data[0], 'ip': data[1]}
self.add_host_info_to_items(item['ip'], item['host'])
elif goohost_scantype == 'host':
data = line.strip()
item = {'host': data, 'ip': self.resolve(data)}
self.add_host_info_to_items(item['ip'], item['host'])
else:
item = {'data': line}
self.items.append(item)
line = f.readline()
def resolve(self, host):
try:
return socket.gethostbyname(host)
......@@ -66,6 +60,19 @@ class GoohostParser(object):
pass
return host
def add_host_info_to_items(self, ip_address, hostname):
data = {}
exists = False
for item in self.items:
if ip_address in item['ip']:
item['hosts'].append(hostname)
exists = True
if not exists:
data['ip'] = ip_address
data['hosts'] = [hostname]
self.items.append(data)
class GoohostPlugin(core.PluginBase):
"""
......@@ -83,44 +90,45 @@ class GoohostPlugin(core.PluginBase):
self._current_path = None
self._command_regex = re.compile(
r'^(sudo goohost\.sh|goohost\.sh|sh goohost\.sh|\.\/goohost\.sh).*?')
self.scantype = "host"
self.host = None
global current_path
self.output_path = None
self._command_string = None
def parseOutputString(self, output, debug=False):
"""
This method will discard the output the shell sends, it will read it from
the xml where it expects it to be present.
This method will check if the import was made through the console or by importing a Goohost report.
Import from Console:The method will take the path of the report generated by Goohost from the output the shell sends and will read
the information from the txt where it expects it to be present.
Import from Report: The method receives the output of the txt report as parameter.
self.scantype defines the method used to generate the Goohost report
NOTE: if 'debug' is true then it is being run from a test case and the
output being sent is valid.
"""
if self.output_path is None:
mypath = re.search("Results saved in file (\S+)", output)
if mypath is not None:
self.output_path = self._current_path + "/" + mypath.group(1)
if self._command_string:
# Import from console
self.scantype = self.define_scantype_by_command(self._command_string)
report_output = output
output = self.read_output_file(report_output)
else:
return False
# Import from report
self.scantype = self.define_scantype_by_output(output)
if debug:
parser = GoohostParser(output, self.scantype)
else:
if not os.path.exists(self.output_path):
return False
parser = GoohostParser(self.output_path, self.scantype)
parser = GoohostParser(output, self.scantype)
if self.scantype == 'host' or self.scantype == 'ip':
for item in parser.items:
h_id = self.createAndAddHost(item['ip'])
i_id = self.createAndAddInterface(
h_id,
h_id = self.createAndAddHost(
item['ip'],
ipv4_address=item['ip'],
hostname_resolution=item['host'])
hostnames=item['hosts'])
del parser
......@@ -129,16 +137,47 @@ class GoohostPlugin(core.PluginBase):
Set output path for parser...
"""
self._current_path = current_path
self._command_string = command_string
def setHost(self):
pass
def define_scantype_by_command(self, command):
method_regex = re.compile(r'-m (mail|host|ip)')
method = method_regex.search(command)
if method:
return method.group(1)
return 'host'
def define_scantype_by_output(self, output):
lines = output.split('\n')
line = lines[0].split(' ')
if len(line) == 1:
return 'host'
elif len(line) == 2:
return 'ip'
def read_output_file(self, report_path):
mypath = re.search("Results saved in file (\S+)", report_path)
if not mypath:
return False
else:
self.output_path = self._current_path + "/" + mypath.group(1)
if not os.path.exists(self.output_path):
return False
with open(self.output_path, 'r') as report:
output = report.read()
return output
def createPlugin():
return GoohostPlugin()
if __name__ == '__main__':
parser = GoohostParser(sys.argv[1])
with open('/home/javier/Plugins/goohost/report-10071-google.com.txt','r') as report:
output = report.read()
parser = GoohostPlugin()
parser.parseOutputString(output)
for item in parser.items:
if item.status == 'up':
print item
......@@ -11,6 +11,7 @@ from plugins import core
import re
import os
import sys
import logging
try:
......@@ -23,6 +24,8 @@ except ImportError:
ETREE_VERSION = [int(i) for i in ETREE_VERSION.split('.')]
logger = logging.getLogger(__name__)
current_path = os.path.abspath(os.getcwd())
__author__ = 'Francisco Amato'
......@@ -69,7 +72,6 @@ class QualysguardXmlParser():
"""
def __init__(self, xml_output):
tree, type_report = self.parse_xml(xml_output)
if not tree or type_report is None:
......@@ -105,7 +107,7 @@ class QualysguardXmlParser():
type_report = None
except SyntaxError, err:
self.devlog('SyntaxError: %s. %s' % (err, xml_output))
logger.error('SyntaxError: %s.' % (err))
return None, None
return tree, type_report
......@@ -254,7 +256,7 @@ class ItemScanReport():
self.node = item_node
self.ip = item_node.get('value')
self.os = self.get_text_from_subnode('OS')
self.hostname = self.get_hostname(item_node)
self.vulns = self.getResults(item_node)
def getResults(self, tree):
......@@ -267,6 +269,12 @@ class ItemScanReport():
for self.issues in tree.findall('INFOS/CAT'):
for v in self.issues.findall('INFO'):
yield ResultsScanReport(v, self.issues)
for self.issues in tree.findall('SERVICES/CAT'):
for v in self.issues.findall('SERVICE'):
yield ResultsScanReport(v, self.issues)
for self.issues in tree.findall('PRACTICES/CAT'):
for v in self.issues.findall('PRACTICE'):
yield ResultsScanReport(v, self.issues)
def get_text_from_subnode(self, subnode_xpath_expr):
"""
......@@ -280,6 +288,14 @@ class ItemScanReport():
return None
def get_hostname(self, node):
hostname = node.get('name')
if hostname == 'No registered hostname':
return ""
return hostname
class ResultsScanReport():
"""
......@@ -294,10 +310,10 @@ class ResultsScanReport():
self.severity = self.node.get('severity')
self.title = self.get_text_from_subnode('TITLE')
self.cvss = self.get_text_from_subnode('CVSS_BASE')
self.pci = self.get_text_from_subnode('PCI_FLAG')
self.diagnosis = self.get_text_from_subnode('DIAGNOSIS')
self.solution = self.get_text_from_subnode('SOLUTION')
self.result = self.get_text_from_subnode('RESULT')
self.consequence = self.get_text_from_subnode('CONSEQUENCE')
self.desc = cleaner_results(self.diagnosis)
if self.result:
......@@ -305,6 +321,11 @@ class ResultsScanReport():
else:
self.desc += ''
if self.consequence:
self.desc += '\nConsequence: ' + cleaner_results(self.consequence)
else:
self.desc += ''
self.ref = []
for r in issue_node.findall('CVE_ID_LIST/CVE_ID'):
self.node = r
......@@ -313,6 +334,9 @@ class ResultsScanReport():
self.node = r
self.ref.append('bid-' + self.get_text_from_subnode('ID'))
if self.cvss:
self.ref.append('CVSS BASE: ' + self.cvss)