Browse code

switch to json-based freewvsdb

Hanno Böck authored on11/12/2019 18:39:17
Showing1 changed files
... ...
@@ -23,13 +23,12 @@
23 23
 # return your changes to the public. We would be especially happy if you tell
24 24
 # us what you're going to do with this code.
25 25
 
26
-import configparser
27
-
28 26
 import os
29 27
 import glob
30 28
 import re
31 29
 import argparse
32 30
 import sys
31
+import json
33 32
 from xml.sax.saxutils import escape
34 33
 
35 34
 
... ...
@@ -73,60 +72,25 @@ parser.add_argument("-3", "--thirdparty", action="store_true",
73 72
                     help="Scan for third-party components like jquery")
74 73
 opts = parser.parse_args()
75 74
 
76
-# Parse vulnerability database
77
-config = configparser.ConfigParser()
78
-try:
79
-    config.read(glob.glob('/usr/share/freewvs/*.freewvs'))
80
-    config.read(glob.glob('/usr/local/share/freewvs/*.freewvs'))
81
-    config.read(glob.glob(os.path.dirname(sys.argv[0])
82
-                          + '/freewvsdb/*.freewvs'))
83
-except configparser.MissingSectionHeaderError as err:
84
-    print("Error parsing config files: %s" % err)
85
-
86
-vdb = []
75
+jdir = False
76
+for p in [os.path.dirname(sys.argv[0]) + '/freewvsdb', '/var/lib/freewvs']:
77
+    if os.path.isdir(p):
78
+        jdir = p
79
+if not jdir:
80
+    print("Can't find freewvs json db")
81
+    sys.exit(1)
82
+
83
+jconfig = []
84
+for cfile in glob.glob(jdir + '/*.json'):
85
+    with open(cfile) as json_file:
86
+        data = json.load(json_file)
87
+        jconfig += data
88
+
87 89
 scanfiles = set()
88
-for sect in config.sections():
89
-    item = {}
90
-
91
-    if (config.getboolean(sect, 'thirdparty', fallback=False)
92
-       and not opts.thirdparty):
93
-        continue
94
-
95
-    # base options
96
-    item['name'] = sect
97
-    item['safe'] = config.get(sect, 'safe')
98
-    item['file'] = config.get(sect, 'file')
99
-    item['vuln'] = config.get(sect, 'vuln')
100
-    item['subdir'] = int(config.get(sect, 'subdir'))
101
-    scanfiles.add(item['file'])
102
-
103
-    # match magic
104
-    item['variable'] = re.compile(re.escape(config.get(sect, 'variable'))
105
-                                  + r"[^0-9\n\r]*[.]*([0-9.]*[0-9])[^0-9.]")
106
-
107
-    # optional options
108
-    if config.has_option(sect, 'extra_match'):
109
-        item['extra_match'] = config.get(sect, 'extra_match')
110
-    else:
111
-        item['extra_match'] = False
112
-    if config.has_option(sect, 'extra_nomatch'):
113
-        item['extra_nomatch'] = config.get(sect, 'extra_nomatch')
114
-    else:
115
-        item['extra_nomatch'] = False
116
-    if config.has_option(sect, 'path_match'):
117
-        item['path_match'] = config.get(sect, 'path_match')
118
-    else:
119
-        item['path_match'] = False
120
-    if config.has_option(sect, 'add_minor'):
121
-        item['add_minor'] = config.get(sect, 'add_minor')
122
-    else:
123
-        item['add_minor'] = False
124
-    if config.has_option(sect, 'old_safe'):
125
-        item['old_safe'] = config.get(sect, 'old_safe').split(",")
126
-    else:
127
-        item['old_safe'] = []
90
+for app in jconfig:
91
+    for det in app['detection']:
92
+        scanfiles.add(det['file'])
128 93
 
129
-    vdb.append(item)
130 94
 
131 95
 if opts.xml:
132 96
     print('<?xml version="1.0" ?>')
... ...
@@ -137,50 +101,58 @@ if opts.xml:
137 101
 for fdir in opts.dirs:
138 102
     for root, NULL, files in os.walk(fdir):
139 103
         for filename in scanfiles.intersection(files):
140
-            for item in vdb:
141
-                if filename == item['file']:
142
-                    mfile = os.path.join(root, filename)
143
-                    try:
144
-                        file = open(mfile, errors='replace')
145
-                    except Exception:
146
-                        continue
147
-                    filestr = file.read()
148
-                    file.close()
149
-
150
-                    if ((item['extra_match']
151
-                       and item['extra_match'] not in filestr)
152
-                       or (item['extra_nomatch']
153
-                       and item['extra_nomatch'] in filestr)
154
-                       or (item['path_match']
155
-                       and not root.endswith(item['path_match']))):
156
-                        continue
157
-
158
-                    findversion = item['variable'].search(filestr)
159
-                    if not findversion:
160
-                        continue
161
-                    findversion = findversion.group(1)
162
-
163
-                    # Very ugly phpbb workaround
164
-                    if item['add_minor']:
165
-                        findversion = findversion.split('.')
166
-                        findversion[-1] = str(int(findversion[-1])
167
-                                              + int(item['add_minor']))
168
-                        findversion = '.'.join(findversion)
169
-
170
-                    if (not versioncompare(item['safe'], findversion)
171
-                       or findversion in item['old_safe']):
172
-                        if opts.all:
173
-                            vulnprint(item['name'], findversion, "ok", "",
174
-                                      mfile, item['subdir'], opts.xml)
175
-                        continue
176
-
177
-                    safev = item['safe']
178
-                    for ver in item['old_safe']:
179
-                        if versioncompare(ver, findversion):
180
-                            safev = ver
181
-
182
-                    vulnprint(item['name'], findversion, safev, item['vuln'],
183
-                              mfile, item['subdir'], opts.xml)
104
+            for item in jconfig:
105
+                if not opts.thirdparty and 'thirdparty' in item:
106
+                    continue
107
+                for det in item['detection']:
108
+                    if filename == det['file']:
109
+                        mfile = os.path.join(root, filename)
110
+                        try:
111
+                            file = open(mfile, errors='replace')
112
+                        except Exception:
113
+                            continue
114
+                        filestr = file.read()
115
+                        file.close()
116
+
117
+                        if (('extra_match' in det
118
+                           and det['extra_match'] not in filestr)
119
+                           or ('extra_nomatch' in det
120
+                           and det['extra_nomatch'] in filestr)
121
+                           or ('path_match' in det
122
+                           and not root.endswith(det['path_match']))):
123
+                            continue
124
+
125
+                        findversion = re.search(re.escape(det['variable'])
126
+                                                + r"[^0-9\n\r]*[.]*"
127
+                                                "([0-9.]*[0-9])[^0-9.]",
128
+                                                filestr)
129
+                        if not findversion:
130
+                            continue
131
+                        findversion = findversion.group(1)
132
+
133
+                        # Very ugly phpbb workaround
134
+                        if 'add_minor' in det:
135
+                            findversion = findversion.split('.')
136
+                            findversion[-1] = str(int(findversion[-1])
137
+                                                  + int(item['add_minor']))
138
+                            findversion = '.'.join(findversion)
139
+
140
+                        if (not versioncompare(item['safe'], findversion)
141
+                           or ('old_safe' in item
142
+                           and findversion in item['old_safe'].split(','))):
143
+                            if opts.all:
144
+                                vulnprint(item['name'], findversion, "ok", "",
145
+                                          mfile, det['subdir'], opts.xml)
146
+                            continue
147
+
148
+                        safev = item['safe']
149
+                        if 'old_safe' in item:
150
+                            for ver in item['old_safe'].split(','):
151
+                                if versioncompare(ver, findversion):
152
+                                    safev = ver
153
+
154
+                        vulnprint(item['name'], findversion, safev,
155
+                                  item['vuln'], mfile, det['subdir'], opts.xml)
184 156
 
185 157
 if opts.xml:
186 158
     print('</freewvs>')