Commit 90dc33a5 authored by Alexandre Dulaunoy's avatar Alexandre Dulaunoy
Browse files

Merge pull request #126 from PidgeyL/master

Add plug-in features, bugfixes and update documentation
parents f3c45453 716daaef
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -107,7 +107,8 @@
    This script uses the <abbr title="Common Vulnerability Enumeration">CVE</abbr> dictionary from NIST's NVD. As there are a lot of products, they can not make a title for each <abbr title="Common Vulnerability Enumeration">CVE</abbr> manually. That's why CVE-Search has another script, called <span class="code">db_mgmt_cpe_other_dictionary.py</span>.
    This script takes the <abbr title="Common Vulnerability Enumeration">CVEs</abbr> that have no title, and splits them into a human readable format. <br />
    <br />
    To add this dictionary, type <span class="code">python3 db_mgmt_cpe_other_dictionary.py</span> and hit enter.
    To add this dictionary, type <span class="code">python3 db_mgmt_cpe_other_dictionary.py</span> and hit enter.<br />
    <b>NOTE:</b> It is possible this script will crash, due to the large amount of information. If this happens, first run <span class="code">python3 db_mgmt_create_index.py</span>
  </p>
  <h3 id="update">Updating the database</h3>
  <p>
+4 −1
Original line number Diff line number Diff line
@@ -108,7 +108,10 @@ This script uses the CVE dictionary from NIST's NVD. As there are a lot
This script takes the CVEs that have no title, and splits them into a
 human readable format. <br /> <br />
To add this dictionary, type *python3 db_mgmt_cpe_other_dictionary.py*
 and hit enter.
 and hit enter. <br />
**NOTE:** It is possible this script will crash, due to the large amount of
 information. If this happens, first run *python3 db_mgmt_create_index.py*


###Updating the database
Before updating the database, you have to decide if you will use the web
+37 −16
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ colRANKING= db['ranking']
colMSBULLETIN=      db['ms']
colCAPEC=           db['capec']
colPlugSettings=    db['plugin_settings']
colPlugUserSettings=db['plugin_user_settings']

# Functions
def sanitize(x):
@@ -344,9 +345,29 @@ def p_writeSetting(plugin, setting, value):
  colPlugSettings.update({"plugin": plugin}, {"$set": {setting: value}}, upsert=True)

def p_readSetting(plugin, setting):
  data = colPlugSettings.distinct(setting, {'plugin': plugin})
  if len(data) !=0: return data[0]
  else:             return None
  data = list(colPlugSettings.find({'plugin': plugin}, {setting: 1}))
  if len(data) !=0:
    data = data[0]
    if setting in data:
      return data[setting]
  return None

def p_deleteSettings(plugin):
  colPlugSettings.remove({"plugin": plugin})

def p_writeUserSetting(plugin, user, setting, value):
  colPlugUserSettings.update({"plugin": plugin, "user":user}, {"$set": {setting: value}}, upsert=True)

def p_readUserSetting(plugin, user, setting):
  data = list(colPlugUserSettings.find({'plugin': plugin, 'user': user}, {setting: 1}))
  if len(data) !=0:
    data = data[0]
    if setting in data:
      return data[setting]
  return None

def p_deleteUserSettings(plugin):
  colPlugUserSettings.remove({"plugin": plugin})

# Query
def p_queryData(collection, query):
+77 −64
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ class PluginManager():
    data = open(conf.getPluginLoadSettings(), "r").read()
    data = [x.split("\t") for x in data.split("\n") if not x.startswith("#") and x]
    data = [[x.strip() for x in y if x.strip()] for y in data]
    uids = []
    for x in [x for x in data if len(x) == 2]:
      try:
        if x[1].lower() == "load" or x[1].lower() == "default":
@@ -44,11 +43,13 @@ class PluginManager():
          plugin.setUID(plugin.getName().replace(" ", "_"))
          # Ensure UID's unique
          while True:
            if plugin.getUID() in uids: plugin.setUID(plugin.getUID()+"_")
            if plugin.getUID() in self.plugins.keys(): plugin.setUID(plugin.getUID()+"_");
            else: break
          # Load settings if needed
          if x[1].lower() == "load":
            plugin.loadSettings(settingsReader)
          # Set load state
          plugin.setLoadState(x[1])
          # Add to list
          self.plugins[plugin.getUID().strip()] = plugin
          print("[+] Loaded plugin %s"%x[0])
@@ -56,25 +57,13 @@ class PluginManager():
        print("[!] Failed to load module %s: "%x[0])
        print("[!]  -> %s"%e)

  def onCVEOpen(self, cve, **args):
    for plugin in self.getWebPlugins():
      plugin.onCVEOpen(cve, **args)

  def onCVEAction(self, cve, plugin, action, **args):
    if plugin.strip() in self.plugins.keys(): # Check if plugin exists
      if self.plugins[plugin].isWebPlugin():  # Check if plugin is web plugin
        try:
          return self.plugins[plugin].onCVEAction(cve, action, **args)
        except Exception as e:
          print("[!] Failed to perform %s action on module %s: "%(action, plugin))
          print("[!]  -> %s"%e)

  # Get's - Plug-in manager
  def getPlugins(self):
    return self.plugins.values()
    return sorted(self.plugins.values(), key=lambda k: k.getName())

  def getWebPlugins(self):
    webPlugins = []
    for plugin in self.plugins.values():
    for plugin in self.getPlugins():
      if plugin.isWebPlugin():
        webPlugins.append(plugin)
    return webPlugins
@@ -82,16 +71,23 @@ class PluginManager():
  def getWebPluginsWithPage(self, **args):
    plugins = []
    for plug in self.getWebPlugins():
      try:
        page = plug.getPage(**args)
        if page and page[0]: # Make sure there is a page
          plugins.append(plug)
      except Exception as e:
        print("[!] Failed to check webpage from module %s: "%(plug.getName()))
        print("[!]  -> %s"%e)
    return plugins

  # Get's - Plug-in specific
  def getCVEActions(self, cve, **args):
    actions = []
    for plugin in self.getWebPlugins():
      try:
        for action in plugin.getCVEActions(cve, **args):
        actions_ = plugin.getCVEActions(cve, **args)
        if actions_:
          for action in actions_:
            action['auth'] = plugin.requiresAuth
            action['plugin'] = plugin.getUID()
            actions.append(action)
@@ -105,33 +101,22 @@ class PluginManager():
      return self.plugins[plugin].requiresAuth
    else: return False

  def openPage(self, name, **args):
    if name.strip() in self.plugins.keys(): # Check if plugin exists
      if self.plugins[name].isWebPlugin():  # Check if plugin is web plugin
        pageInfo = self.plugins[name].getPage(**args)
        if type(pageInfo) == tuple:
          page, content = pageInfo
          if page: return ("plugins/%s"%page, content)
          else:    return None
        else:
          return ("error.html", {'status': {'except': 'plugin-page-missing'}})
      else:
        return ("error.html", {'status': {'except': 'plugin-not-webplugin'}})
    return ("error.html", {'status': {'except': 'plugin-not-loaded'}})

  def openSubpage(self, subpage, **args):
    if name.strip() in self.plugins.keys(): # Check if plugin exists
      if self.plugins[name].isWebPlugin():  # Check if plugin is web plugin
        pageInfo = self.plugins[name].getSubpage(subpage, **args)
        if type(pageInfo) == tuple:
          page, content = pageInfo
          if page: return ("plugins/%s"%page, content)
        # Else, the page is missing, so we send None to throw a 404
        return None
      else:
        return ("error.html", {'status': {'except': 'plugin-not-webplugin'}})
    return ("error.html", {'status': {'except': 'plugin-not-loaded'}})
  def getFilters(self, **args):
    filters = []
    for plugin in self.getWebPlugins():
      try:
        filters_ = plugin.getFilters(**args)
        if filters_:
          for filter_ in filters_:
            filter_['auth']   = plugin.requiresAuth
            filter_['plugin'] = plugin.getUID()
            filters.append(filter_)
      except Exception as e:
        print("[!] Plugin %s failed on fetching filters!"%plugin.getName())
        print("[!]  -> %s"%e)
    return filters

  # Get's - Plug-in specific with stored data
  def cvePluginInfo(self, cve, **args):
    cveInfo = []
    for plugin in self.getWebPlugins():
@@ -153,28 +138,56 @@ class PluginManager():
      # Validate format
      if type(data) == list and all([(type(x) == dict and 'n' in x and 'd' in x) for x in data]):
        results.extend(data)
    # Sort through data
    for collection in results:
      for item in collection['d']:
        # Check if already in result data
        if not any(item['id']==entry['id'] for entry in result['data']):
          entry=db.getCVE(item['id'])
        if not any(item==entry['id'] for entry in result['data']):
          entry=db.getCVE(item)
          entry['reason']=collection['n']
          result['data'].append(entry)
    return result

# Filters
  def getFilters(self, **args):
    filters = []
  # Actions
  def onCVEOpen(self, cve, **args):
    for plugin in self.getWebPlugins():
      plugin.onCVEOpen(cve, **args)

  def onCVEAction(self, cve, plugin, action, **args):
    if plugin.strip() in self.plugins.keys(): # Check if plugin exists
      if self.plugins[plugin].isWebPlugin():  # Check if plugin is web plugin
        try:
        for filter_ in plugin.getFilters(**args):
          filter_['auth']   = plugin.requiresAuth
          filter_['plugin'] = plugin.getUID()
          filters.append(filter_)
          return self.plugins[plugin].onCVEAction(cve, action, **args)
        except Exception as e:
        print("[!] Plugin %s failed on fetching filters!"%plugin.getName())
          print("[!] Failed to perform %s action on module %s: "%(action, plugin))
          print("[!]  -> %s"%e)
    return filters

  def openPage(self, name, **args):
    if name.strip() in self.plugins.keys(): # Check if plugin exists
      if self.plugins[name].isWebPlugin():  # Check if plugin is web plugin
        pageInfo = self.plugins[name].getPage(**args)
        if type(pageInfo) == tuple:
          page, content = pageInfo
          if page: return ("plugins/%s"%page, content)
          else:    return None
        else:
          return ("error.html", {'status': {'except': 'plugin-page-missing'}})
      else:
        return ("error.html", {'status': {'except': 'plugin-not-webplugin'}})
    return ("error.html", {'status': {'except': 'plugin-not-loaded'}})

  def openSubpage(self, subpage, **args):
    if name.strip() in self.plugins.keys(): # Check if plugin exists
      if self.plugins[name].isWebPlugin():  # Check if plugin is web plugin
        pageInfo = self.plugins[name].getSubpage(subpage, **args)
        if type(pageInfo) == tuple:
          page, content = pageInfo
          if page: return ("plugins/%s"%page, content)
        # Else, the page is missing, so we send None to throw a 404
        return None
      else:
        return ("error.html", {'status': {'except': 'plugin-not-webplugin'}})
    return ("error.html", {'status': {'except': 'plugin-not-loaded'}})

  def doFilter(self, filters, **args):
    plug_fils = {key[5:]: value for (key, value) in filters.items() if key.startswith('plug_')}
+4 −1
Original line number Diff line number Diff line
@@ -13,12 +13,15 @@ class Plugin():
    self.name = None
    self.uid = None
    self.requiresAuth = False
    self.loadstate = "default"

  # Get
  def getName(self):      return self.name
  def getUID(self):       return self.uid
  def getLoadState(self): return self.loadstate
  # Set
  def setUID(self, uid):         self.uid = uid
  def setLoadState(self, state): self.loadstate = state
  # Don't override
  def isWebPlugin(self):  return False
  # To override without returns
Loading