root/branch/UmitWeb/umitWeb/views/scan.py @ 2988

Revision 2988, 9.7 kB (checked in by rcarvalho, 5 years ago)

UmitWeb now is using the new ScanJsonParser? to parse the scan result.

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Copyright (C) 2005 Insecure.Com LLC.
4#
5# Author: Rodolfo da Silva Carvalho <rodolfo.ueg@gmail.com>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21from types import *
22from umitWeb.Http import HttpResponse, Http404, Http500, Http403, HttpError
23from umitWeb.Auth import authenticate, ERROR
24from umitWeb.Server import UmitWebServer as server
25from umitWeb.WebLogger import getLogger
26from umitWeb.Json import ScanJsonParser
27from umitCore.NmapCommand import NmapCommand
28from umitCore.NmapParser import NmapParser, HostInfo
29from umitCore.UmitConf import CommandProfile
30from umitCore.UmitDB import Scans, UmitDB
31from urllib import quote
32from tempfile import mktemp
33import random
34import sys
35import os
36#from StringIO import StringIO
37import re
38import md5
39from threading import Thread
40from time import time
41import datetime
42
43
44logger = getLogger(__name__)
45
46@authenticate()
47def index(req):
48    response = HttpResponse()
49    response.loadTemplate("scans.html")
50    return response
51
52
53@authenticate(ERROR)
54def new(req):
55    response = HttpResponse()
56    response['Content-type'] = "text/plain"
57   
58    #Replace dangerous commands
59    command = re.sub(r"[\\;|`&]", "", req.POST['command'])
60    if req.session.user.is_permitted(command):
61        try:
62            nmapCommand = NmapCommand(command)
63            resourceID = server.currentInstance.addResource(nmapCommand)
64            server.currentInstance.fireResourceEvent(resourceID, "run_scan")
65           
66            req.session['command_' + resourceID] = command
67            req.session['profile_' + resourceID] = req.POST['profile_name']
68            req.session['target_' + resourceID] = req.POST['target']
69            response.write("{'result': 'OK', 'status': 'RUNNING', 'id': '%s'}" % resourceID)
70        except Exception, e:
71            response.write("{'result': 'FAIL', 'status': '%s'}" % str(e).replace("'", "\\'"))
72        return response
73    else:
74        raise Http403
75
76
77@authenticate(ERROR)
78def check(req, resource_id):
79    response = HttpResponse()
80    response['Content-type'] = "text/javascript"
81   
82    nmapCommand = server.currentInstance.getResource(resource_id)
83   
84    if nmapCommand is None:
85        raise Http404
86   
87    try:
88        output = nmapCommand.get_output()
89        if nmapCommand.scan_state():
90            response.write("{'result': 'OK', 'status': 'RUNNING', " + \
91                           "'output': {'text': '%s'}}" % output.replace("'", "\\'").replace("\n", "\\n' + \n'"))
92        else:
93            profile = CommandProfile()
94            parser = NmapParser()
95            parser.set_xml_file(nmapCommand.get_xml_output_file())
96            parser.parse()
97
98            parser.profile_name = req.session['profile_' + resource_id]
99            parser.target = req.session['target_' + resource_id]
100            parser.nmap_command = req.session['command_' + resource_id]
101            parser.profile = profile.get_command(parser.profile_name)
102            parser.profile_hint = profile.get_hint(parser.profile_name)
103            parser.profile_description = profile.get_description(parser.profile_name)
104            parser.profile_annotation = profile.get_annotation(parser.profile_name)
105            parser.profile_options = profile.get_options(parser.profile_name)
106            try:
107                parser.nmap_output = nmapCommand.get_raw_output()
108            except:
109                parser.nmap_output = "\\n".join(self.scan_result.get_nmap_output().split("\n"))
110            #del parser['nmap']
111            #parsed_scan = #str(__scan_to_json(parser))
112            parsed_scan = ScanJsonParser(parser).parse()
113            text_out = nmapCommand.get_output().replace("'", "\\'").replace("\n", "\\n' + \n'")
114            response.write("{'result': 'OK', 'status': 'FINISHED', 'output':" + \
115                           " {'full': %s, 'plain': '%s'}}" % (parsed_scan, text_out))
116            server.currentInstance.removeResource(resource_id)
117            fname = mktemp()
118            fresult = open(fname, "w", 0)
119            parser.write_xml(fresult)
120            req.session['scan_result_' + resource_id] = open(fname, 'r').read()
121    except Exception, e:
122        if "running" in str(e).lower():
123            response.write("{'result': 'OK', 'status': 'RUNNING', " + \
124                           "'output': {'text': ''}}")
125        else:
126            raise Http500("Nmap command raised an exception!\n%s" % str(e))
127    return response
128
129
130@authenticate(ERROR)
131def upload_result(req):
132    if req.POST:
133        if req.POST['type'] == "file":
134            try:
135                parser = NmapParser()
136                parser.set_xml_file(req.FILES['scan_result']['temp_file'])
137                parser.parse()
138                parsed_scan = __scan_to_json(parser)
139                junk = r"odpojfsdkjfpisudŕij208u-0w9rsdnfkdfçwrtwqr/fsasd~/???çds"
140                key = md5.new(str(random.randint(0, sys.maxint-1)) \
141                                  + str(random.randint(1, sys.maxint-1)//2) \
142                                  + junk).hexdigest()
143                req.session['scan_result_' + key] = open(req.FILES['scan_result']['temp_name'], 'r').read()
144                text_out = parser.nmap_output.replace("'", "\\'").replace("\r", "").replace("\n", "\\n' + \n'")
145                parsed_scan = str(parsed_scan).replace("\n", "\\n' + \n'")
146                return HttpResponse(("{'result': 'OK', 'id': '%s', 'output': " + \
147                                    "{'plain': '%s', 'full': %s}}") % \
148                                    (key, text_out, parsed_scan), "text/plain")
149            except Exception, ex:
150                return HttpResponse("{'result': 'FAIL', 'output': '%s'}" % str(ex).replace("'", "\\'"), "text/plain")
151        else:
152            scan_id = req.POST['scanId']
153            db = UmitDB()
154            if scan_id not in [str(sid) for sid in db.get_scans_ids()]:
155                return HttpResponse("{'result': 'FAIL', 'output': 'Scan not found!'}")
156           
157            scan = Scans(scans_id=scan_id)
158            ftemp = open(mktemp(), "w", 0)
159            ftemp.write(scan.nmap_xml_output)
160            ftemp.flush()
161            parser = NmapParser(ftemp.name)
162            parser.parse()
163            return HttpResponse("{'result': 'OK', 'output': {'plain': '%s', 'full': %s}}" % \
164                                (parser.get_nmap_output().replace("'", "\\'").\
165                                replace("\r", "").replace("\n", "\\n' + \n'"),
166                                str(__scan_to_json(parser))), 
167                                "text/plain")
168    else:
169        raise HttpError(400, "Invalid GET request.")
170
171@authenticate(ERROR)
172def save_result(req, scan_id):
173    print req.POST
174    if req.POST:
175        scan = req.session.get("scan_result_" + scan_id, None)
176        parser = NmapParser()
177        fname = mktemp()
178        ftemp = open(fname, "a", 0)
179        ftemp.write(scan)
180        ftemp.close()
181        parser.set_xml_file(fname)
182        parser.parse()
183        parser.scan_name = req.POST['filename']
184        parser.write_xml(open(fname, "w", 0))
185        ftemp = open(fname, "r")
186        scan = ftemp.read()
187        if not scan:
188            raise Http404
189       
190        if req.POST['destination'] == "database":
191            Scans(scan_name=parser.scan_name,
192                    nmap_xml_output=scan,
193                    date=time())
194            return HttpResponse("{'result': 'OK'}", "text/plain")
195        else:
196            response = HttpResponse(scan, "text/xml")
197            response['Content-disposition'] = "attachment; filename=" + quote(req.POST['filename'].replace(" ", "_")) + ".usr"
198            return response
199    else:
200        raise HttpError(400, "Invalid GET request.")
201   
202
203@authenticate(ERROR)
204def get_saved_scans(req):
205    db = UmitDB()
206    data = [{"id": str(s.scans_id), 
207             "name": str(s.scan_name).replace("'", "\\'"),
208             "date": datetime.datetime.fromtimestamp(s.date).strftime("%Y-%m-%d %H:%M:%S")}
209             for s in db.get_scans() if req.POST.get("search", "").lower() in s.scan_name.lower()]
210    return HttpResponse(str(data))
211
212
213@authenticate(ERROR)
214def get_scan(req, scan_id):
215    db = UmitDB()
216    if scan_id not in [str(sid) for sid in db.get_scans_ids()]:
217        raise Http404
218   
219    scan = Scans(scans_id=scan_id)
220    ftemp = open(mktemp(), "w", 0)
221    ftemp.write(scan.nmap_xml_output)
222    ftemp.flush()
223    parser = NmapParser(ftemp.name)
224    parser.parse()
225    return HttpResponse("{'result': 'OK', 'output': '%s', 'xml': '%s'}" % \
226                        (parser.get_nmap_output().replace("'", "\\'").\
227                        replace("\r", "").replace("\n", "\\n' + \n'"),
228                        open(ftemp.name).read().replace('"', "'").\
229                        replace("'", "\\'").\
230                        replace("\n", "\\n' + \n'")), 
231                        "text/plain")
232
233
234@authenticate(ERROR)
235def delete_scan(req, scan_id):
236    db = UmitDB()
237    cursor = db.cursor
238    if int(scan_id) not in db.get_scans_ids():
239        raise Http404
240   
241    try:
242        cursor.execute("DELETE FROM scans WHERE scans_id=%d" % int(scan_id))
243    except Exception, e:
244        return HttpResponse("{'result': 'FAIL', 'error': '%s'}" % str(e))
245   
246    return HttpResponse("{'result': 'OK'}")
Note: See TracBrowser for help on using the browser.