switch to json-based freewvsdb
Hanno Böck

Hanno Böck commited on 2019-12-11 18:39:17
Zeige 1 geänderte Dateien mit 40 Einfügungen und 68 Löschungen.

... ...
@@ -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 = []
87
-scanfiles = set()
88
-for sect in config.sections():
89
-    item = {}
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)
90 82
 
91
-    if (config.getboolean(sect, 'thirdparty', fallback=False)
92
-       and not opts.thirdparty):
93
-        continue
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
94 88
 
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'] = []
89
+scanfiles = set()
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,8 +101,11 @@ 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']:
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']:
142 109
                         mfile = os.path.join(root, filename)
143 110
                         try:
144 111
                             file = open(mfile, errors='replace')
... ...
@@ -147,40 +114,45 @@ for fdir in opts.dirs:
147 114
                         filestr = file.read()
148 115
                         file.close()
149 116
 
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']))):
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']))):
156 123
                             continue
157 124
 
158
-                    findversion = item['variable'].search(filestr)
125
+                        findversion = re.search(re.escape(det['variable'])
126
+                                                + r"[^0-9\n\r]*[.]*"
127
+                                                "([0-9.]*[0-9])[^0-9.]",
128
+                                                filestr)
159 129
                         if not findversion:
160 130
                             continue
161 131
                         findversion = findversion.group(1)
162 132
 
163 133
                         # Very ugly phpbb workaround
164
-                    if item['add_minor']:
134
+                        if 'add_minor' in det:
165 135
                             findversion = findversion.split('.')
166 136
                             findversion[-1] = str(int(findversion[-1])
167 137
                                                   + int(item['add_minor']))
168 138
                             findversion = '.'.join(findversion)
169 139
 
170 140
                         if (not versioncompare(item['safe'], findversion)
171
-                       or findversion in item['old_safe']):
141
+                           or ('old_safe' in item
142
+                           and findversion in item['old_safe'].split(','))):
172 143
                             if opts.all:
173 144
                                 vulnprint(item['name'], findversion, "ok", "",
174
-                                      mfile, item['subdir'], opts.xml)
145
+                                          mfile, det['subdir'], opts.xml)
175 146
                             continue
176 147
 
177 148
                         safev = item['safe']
178
-                    for ver in item['old_safe']:
149
+                        if 'old_safe' in item:
150
+                            for ver in item['old_safe'].split(','):
179 151
                                 if versioncompare(ver, findversion):
180 152
                                     safev = ver
181 153
 
182
-                    vulnprint(item['name'], findversion, safev, item['vuln'],
183
-                              mfile, item['subdir'], opts.xml)
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>')
187 159