├── README.md └── windows-exploit-suggester.py /README.md: -------------------------------------------------------------------------------- 1 | DESCRIPTION 2 | =========== 3 | This tool compares a targets patch levels against the Microsoft vulnerability 4 | database in order to detect potential missing patches on the target. It also 5 | notifies the user if there are public exploits and Metasploit modules 6 | available for the missing bulletins. 7 | 8 | It requires the 'systeminfo' command output from a Windows host in order to 9 | compare that the Microsoft security bulletin database and determine the 10 | patch level of the host. 11 | 12 | It has the ability to automatically download the security bulletin database 13 | from Microsoft with the --update flag, and saves it as an Excel spreadsheet. 14 | 15 | When looking at the command output, it is important to note that it assumes 16 | all vulnerabilities and then selectively removes them based upon the hotfix 17 | data. This can result in many false-positives, and it is key to know what 18 | software is actually running on the target host. For example, if there are 19 | known IIS exploits it will flag them even if IIS is not running on the 20 | target host. 21 | 22 | The output shows either public exploits (E), or Metasploit modules (M) as 23 | indicated by the character value. 24 | 25 | It was heavily inspired by Linux_Exploit_Suggester by Pentura. 26 | 27 | Blog Post: "Introducing Windows Exploit Suggester", https://blog.gdssecurity.com/labs/2014/7/11/introducing-windows-exploit-suggester.html 28 | 29 | USAGE 30 | ===== 31 | update the database 32 | ``` 33 | $ ./windows-exploit-suggester.py --update 34 | [*] initiating... 35 | [*] successfully requested base url 36 | [*] scraped ms download url 37 | [+] writing to file 2014-06-06-mssb.xlsx 38 | [*] done 39 | ``` 40 | install dependencies 41 | 42 | (install python-xlrd, $ pip install xlrd --upgrade) 43 | 44 | feed it "systeminfo" input, and point it to the microsoft database 45 | ``` 46 | $ ./windows-exploit-suggester.py --database 2014-06-06-mssb.xlsx --systeminfo win7sp1-systeminfo.txt 47 | [*] initiating... 48 | [*] database file detected as xls or xlsx based on extension 49 | [*] reading from the systeminfo input file 50 | [*] querying database file for potential vulnerabilities 51 | [*] comparing the 15 hotfix(es) against the 173 potential bulletins(s) 52 | [*] there are now 168 remaining vulns 53 | [+] windows version identified as 'Windows 7 SP1 32-bit' 54 | [*] 55 | [M] MS14-012: Cumulative Security Update for Internet Explorer (2925418) - Critical 56 | [E] MS13-101: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Elevation of Privilege (2880430) - Important 57 | [M] MS13-090: Cumulative Security Update of ActiveX Kill Bits (2900986) - Critical 58 | [M] MS13-080: Cumulative Security Update for Internet Explorer (2879017) - Critical 59 | [M] MS13-069: Cumulative Security Update for Internet Explorer (2870699) - Critical 60 | [M] MS13-059: Cumulative Security Update for Internet Explorer (2862772) - Critical 61 | [M] MS13-055: Cumulative Security Update for Internet Explorer (2846071) - Critical 62 | [M] MS13-053: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Remote Code Execution (2850851) - Critical 63 | [M] MS13-009: Cumulative Security Update for Internet Explorer (2792100) - Critical 64 | [M] MS13-005: Vulnerability in Windows Kernel-Mode Driver Could Allow Elevation of Privilege (2778930) - Important 65 | [*] done 66 | ``` 67 | 68 | possible exploits for an operating system can be used without hotfix data 69 | ``` 70 | $ ./windows-exploit-suggester.py --database 2014-06-06-mssb.xlsx --ostext 'windows server 2008 r2' 71 | [*] initiating... 72 | [*] database file detected as xls or xlsx based on extension 73 | [*] getting OS information from command line text 74 | [*] querying database file for potential vulnerabilities 75 | [*] comparing the 0 hotfix(es) against the 196 potential bulletins(s) 76 | [*] there are now 196 remaining vulns 77 | [+] windows version identified as 'Windows 2008 R2 64-bit' 78 | [*] 79 | [M] MS13-009: Cumulative Security Update for Internet Explorer (2792100) - Critical 80 | [M] MS13-005: Vulnerability in Windows Kernel-Mode Driver Could Allow Elevation of Privilege (2778930) - Important 81 | [E] MS11-011: Vulnerabilities in Windows Kernel Could Allow Elevation of Privilege (2393802) - Important 82 | [M] MS10-073: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Elevation of Privilege (981957) - Important 83 | [M] MS10-061: Vulnerability in Print Spooler Service Could Allow Remote Code Execution (2347290) - Critical 84 | [E] MS10-059: Vulnerabilities in the Tracing Feature for Services Could Allow Elevation of Privilege (982799) - Important 85 | [E] MS10-047: Vulnerabilities in Windows Kernel Could Allow Elevation of Privilege (981852) - Important 86 | [M] MS10-002: Cumulative Security Update for Internet Explorer (978207) - Critical 87 | [M] MS09-072: Cumulative Security Update for Internet Explorer (976325) - Critical 88 | ``` 89 | 90 | LIMITATIONS 91 | =========== 92 | Currently, if the 'systeminfo' command reveals 'File 1' as the output for 93 | the hotfixes, it will not be able to determine which are installed on 94 | the target. If this occurs, the list of hotfixes will need to be 95 | retrieved from the target host and passed in using the --hotfixes flag 96 | 97 | It currently does not seperate 'editions' of the Windows OS such as 98 | 'Tablet' or 'Media Center' for example, or different architectures, such as 99 | Itanium-based only 100 | 101 | False positives also occur where it assumes EVERYTHING is installed 102 | on the target Windows operating system. If you receive the 'File 1' 103 | output, try executing 'wmic qfe list full' and feed that as input 104 | with the --hotfixes flag, along with the 'systeminfo' 105 | 106 | LICENSE 107 | ======= 108 | This program is free software: you can redistribute it and/or modify 109 | it under the terms of the GNU General Public License as published by 110 | the Free Software Foundation, either version 3 of the License, or 111 | (at your option) any later version. 112 | 113 | This program is distributed in the hope that it will be useful, 114 | but WITHOUT ANY WARRANTY; without even the implied warranty of 115 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 116 | GNU General Public License for more details. 117 | 118 | You should have received a copy of the GNU General Public License 119 | along with this program. If not, see . 120 | 121 | -------------------------------------------------------------------------------- /windows-exploit-suggester.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Windows Exploit Suggester 5 | # revision 3.3, 2017-02-13 6 | # 7 | # author: Sam Bertram, Gotham Digital Science 8 | # contact: labs@gdssecurity.com,sbertram@gdssecurity.com,sammbertram@gmail.com 9 | # blog post: "Introducing Windows Exploit Suggester", http://blog.gdssecurity.com/ 10 | # 11 | # DESCRIPTION 12 | # 13 | # This tool compares a targets patch levels against the Microsoft vulnerability 14 | # database in order to detect potential missing patches on the target. It also 15 | # notifies the user if there are public exploits and Metasploit modules 16 | # available for the missing bulletins. 17 | # 18 | # It requires the 'systeminfo' command output from a Windows host in order to 19 | # compare that the Microsoft security bulletin database and determine the 20 | # patch level of the host. 21 | # 22 | # It has the ability to automatically download the security bulletin database 23 | # from Microsoft with the --update flag, and saves it as an Excel spreadsheet. 24 | # 25 | # When looking at the command output, it is important to note that it assumes 26 | # all vulnerabilities and then selectively removes them based upon the hotfix 27 | # data. This can result in many false-positives, and it is key to know what 28 | # software is actually running on the target host. For example, if there are 29 | # known IIS exploits it will flag them even if IIS is not running on the 30 | # target host. 31 | # 32 | # The output shows either public exploits (E), or Metasploit modules (M) as 33 | # indicated by the character value. 34 | # 35 | # It was heavily inspired by Linux_Exploit_Suggester by Pentura. 36 | # 37 | # Blog Post: "Introducing Windows Exploit Suggester", https://blog.gdssecurity.com/labs/2014/7/11/introducing-windows-exploit-suggester.html 38 | # 39 | # USAGE 40 | # 41 | # update the database 42 | # 43 | # $ ./windows-exploit-suggester.py --update 44 | # [*] initiating... 45 | # [*] successfully requested base url 46 | # [*] scraped ms download url 47 | # [+] writing to file 2014-06-06-mssb.xlsx 48 | # [*] done 49 | # 50 | # install dependencies 51 | # 52 | # (install python-xlrd, $ pip install xlrd --upgrade) 53 | # 54 | # feed it "systeminfo" input, and point it to the microsoft database 55 | # 56 | # $ ./windows-exploit-suggester.py --database 2014-06-06-mssb.xlsx --systeminfo win7sp1-systeminfo.txt 57 | # [*] initiating... 58 | # [*] database file detected as xls or xlsx based on extension 59 | # [*] reading from the systeminfo input file 60 | # [*] querying database file for potential vulnerabilities 61 | # [*] comparing the 15 hotfix(es) against the 173 potential bulletins(s) 62 | # [*] there are now 168 remaining vulns 63 | # [+] windows version identified as 'Windows 7 SP1 32-bit' 64 | # [*] 65 | # [M] MS14-012: Cumulative Security Update for Internet Explorer (2925418) - Critical 66 | # [E] MS13-101: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Elevation of Privilege (2880430) - Important 67 | # [M] MS13-090: Cumulative Security Update of ActiveX Kill Bits (2900986) - Critical 68 | # [M] MS13-080: Cumulative Security Update for Internet Explorer (2879017) - Critical 69 | # [M] MS13-069: Cumulative Security Update for Internet Explorer (2870699) - Critical 70 | # [M] MS13-059: Cumulative Security Update for Internet Explorer (2862772) - Critical 71 | # [M] MS13-055: Cumulative Security Update for Internet Explorer (2846071) - Critical 72 | # [M] MS13-053: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Remote Code Execution (2850851) - Critical 73 | # [M] MS13-009: Cumulative Security Update for Internet Explorer (2792100) - Critical 74 | # [M] MS13-005: Vulnerability in Windows Kernel-Mode Driver Could Allow Elevation of Privilege (2778930) - Important 75 | # [*] done 76 | # 77 | # possible exploits for an operating system can be used without hotfix data 78 | # $ ./windows-exploit-suggester.py --database 2014-06-06-mssb.xlsx --ostext 'windows server 2008 r2' 79 | # [*] initiating... 80 | # [*] database file detected as xls or xlsx based on extension 81 | # [*] getting OS information from command line text 82 | # [*] querying database file for potential vulnerabilities 83 | # [*] comparing the 0 hotfix(es) against the 196 potential bulletins(s) 84 | # [*] there are now 196 remaining vulns 85 | # [+] windows version identified as 'Windows 2008 R2 64-bit' 86 | # [*] 87 | # [M] MS13-009: Cumulative Security Update for Internet Explorer (2792100) - Critical 88 | # [M] MS13-005: Vulnerability in Windows Kernel-Mode Driver Could Allow Elevation of Privilege (2778930) - Important 89 | # [E] MS11-011: Vulnerabilities in Windows Kernel Could Allow Elevation of Privilege (2393802) - Important 90 | # [M] MS10-073: Vulnerabilities in Windows Kernel-Mode Drivers Could Allow Elevation of Privilege (981957) - Important 91 | # [M] MS10-061: Vulnerability in Print Spooler Service Could Allow Remote Code Execution (2347290) - Critical 92 | # [E] MS10-059: Vulnerabilities in the Tracing Feature for Services Could Allow Elevation of Privilege (982799) - Important 93 | # [E] MS10-047: Vulnerabilities in Windows Kernel Could Allow Elevation of Privilege (981852) - Important 94 | # [M] MS10-002: Cumulative Security Update for Internet Explorer (978207) - Critical 95 | # [M] MS09-072: Cumulative Security Update for Internet Explorer (976325) - Critical 96 | # 97 | # TROUBLESHOOTING 98 | # 99 | # If you're receiving the following error message, update the xlrd library 100 | # $ pip install xlrd --update 101 | # 102 | # [*] initiating winsploit version 24... 103 | # [*] database file detected as xls or xlsx based on extension 104 | # Traceback (most recent call last): 105 | # File "windows-exploit-suggester/windows-exploit-suggester.py", line 1414, in 106 | # main() 107 | # File "windows-exploit-suggester/windows-exploit-suggester.py", line 354, in main 108 | # wb = xlrd.open_workbook(ARGS.database) 109 | # File "/usr/lib/pymodules/python2.7/xlrd/__init__.py", line 370, in open_workbook 110 | # biff_version = bk.getbof(XL_WORKBOOK_GLOBALS) 111 | # File "/usr/lib/pymodules/python2.7/xlrd/__init__.py", line 1323, in getbof 112 | # raise XLRDError('Expected BOF record; found 0x%04x' % opcode) 113 | # xlrd.biffh.XLRDError: Expected BOF record; found 0x4b50 114 | # 115 | # LIMITATIONS 116 | # 117 | # Currently, if the 'systeminfo' command reveals 'File 1' as the output for 118 | # the hotfixes, it will not be able to determine which are installed on 119 | # the target. If this occurs, the list of hotfixes will need to be 120 | # retrieved from the target host and passed in using the --hotfixes flag 121 | # 122 | # It currently does not seperate 'editions' of the Windows OS such as 123 | # 'Tablet' or 'Media Center' for example, or different architectures, such as 124 | # Itanium-based only 125 | # 126 | # False positives also occur where it assumes EVERYTHING is installed 127 | # on the target Windows operating system. If you receive the 'File 1' 128 | # output, try executing 'wmic qfe list full' and feed that as input 129 | # with the --hotfixes flag, along with the 'systeminfo' 130 | # 131 | # LICENSE 132 | # 133 | # This program is free software: you can redistribute it and/or modify 134 | # it under the terms of the GNU General Public License as published by 135 | # the Free Software Foundation, either version 3 of the License, or 136 | # (at your option) any later version. 137 | # 138 | # This program is distributed in the hope that it will be useful, 139 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 140 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141 | # GNU General Public License for more details. 142 | # 143 | # You should have received a copy of the GNU General Public License 144 | # along with this program. If not, see . 145 | # 146 | # TODOLIST 147 | # 148 | # TODO better if/then/case when detecting OS. more flexibility with parsing 149 | # different systeminfo output 150 | # TODO seperate by editions? may result in false positives 151 | # TODO count the number of exploits in the summary prior to outputting it? 152 | # TODO finish -s --search function so that all info on an MS number can be 153 | # returned 154 | # TODO add titles to exploit list so that it is more portable 155 | # TODO test for Windows RT systeminfo output 156 | # TODO improved msf/poc output? perhaps adding details on each MS number? 157 | # TODO if it's running on windows, then try and execute the systeminfo command? 158 | # TODO SPEED. this is now way too slow... somewhat improved! 159 | # TODO automatically install python module? xlrd. 160 | # TODO manually override MS11-011 for Non-Affected Products. The bulletin 161 | # database is wrong. 162 | # Windows 7 for 32-bit Systems Service Pack 1 163 | # Windows 7 for x64-based Systems Service Pack 1 164 | # Windows Server 2008 R2 for x64-based Systems Service Pack 1 165 | # Windows Server 2008 R2 for Itanium-based Systems Service Pack 1 166 | # 167 | # CHANGE LOG 168 | # v33 2017-02-13 169 | # - added links to exploits and resources for each bulletins. can be ignored with the -q/--quiet flag 170 | # - hard coded ms11-011 to ignore false positives 171 | # - added additional resources 172 | # 173 | # v31 2016-02-10 174 | # - changed bulletin url, microsoft 404'd it 175 | # 176 | # v30 2016-01-04 177 | # - added exploits and bulletins from the past six months 178 | # 179 | # v29 2015-09-16 180 | # - adding support for windows 10 181 | # 182 | # v28 2015-07-30 183 | # - added bulletin scraping for xlsx and xls files using regex. thanks to 184 | # edebernis for reporting the bug 185 | # - added ms15-022, ms15-015 update to msf 186 | # 187 | # v27 2015-06-18 188 | # - added new bulletin url that is only xls and not xlsx. thanks to bstork for 189 | # reporting the bug 190 | # - added ms15-010, ms15-051, and ms15-052 191 | # 192 | # v26 2015-06-02 193 | # - small bug fix with linked output 194 | # - added duplicates flag that can allow for bulletins to be displayed 195 | # multiple times. this will allow for greater analysis on linked bulletins 196 | # 197 | # v25 2015-05-18 198 | # - added ms15-051 local priv 199 | # 200 | # v24 2015-01-30 201 | # - added --sub/-s command in order to display output of msids as linked 202 | # this aides in demonstrating what patches need to be applied precisely. 203 | # this change was implemented in v23, but only followed the depth to level 204 | # 1 instead of the entire way. 205 | # - fixed a bug that know allows for multiple supercedes msids in the db 206 | # - allowed for getarchitecture to be recursive, and reduced redunancy when 207 | # it is called throughout the program 208 | # - added ms14-070 209 | # 210 | # v23 2015-01-26 211 | # - typo in --local flag case (pontential vs potential). issue #5 closed. 212 | # 213 | # v22 2015-01-23 214 | # - speed optimisations! it was too slow beforehand. realised i could easily 215 | # make it a bit more efficient 216 | # 217 | # v21 2015-01-22 218 | # - changed display formatting to include nested/linked MS numbers. makes it 219 | # easier to determine the dependencies 220 | # - made args global 221 | # - changed some code formatting, including double-space instead of \t 222 | # - added some additional comments 223 | # - disable ANSI output if on windows platform 224 | # - added recent exploits 225 | # 226 | # v20 2014-12-16 227 | # - added ms14-068,ms14-064,ms14-060, and ms14-058 to the internal vuln list 228 | # 229 | # v19 2014-10-08 230 | # - added support for windows server 2012, this includes ignoring the 231 | # architecture for 2012, and forcing from 32-bit to 64-bit 232 | # 233 | # v18 2014-09-02 234 | # - added ms14-029 poc 235 | # 236 | # v17 2014-08-05 237 | # - fixed a bug where it would not detect OS version when a unicode char comes 238 | # before search string 239 | # 240 | # v16 2014-07-28 241 | # - improved reading of various file encodings for systeminfo. now attempts to 242 | # detect the file first, otherwise loops through common encodings 243 | # - improved OS, service pack, architecture, and release detection. this is now 244 | # not English-dependent as it was previously 245 | # - better architecture detection of systeminfo input (look for -based string) 246 | # - added /usr/bin/env python 247 | # - added ms14-035 poc 248 | # 249 | # v15 2014-07-15 250 | # - changed file open to io, and attempt to decode as utf-8; otherwise attempt 251 | # utf-16 252 | # 253 | # v14 2014-07-13 254 | # - allowed for --ostext flag to properly supersede OS detection of systeminfo 255 | # input 256 | # 257 | # v13a 2014-07-01 258 | # - added new msf flags for ms13-097, and ms14-009 259 | # 260 | # v12a 2014-06-06 261 | # - quick cleanup for release 262 | # 263 | # v11a 2014-05-02 264 | # - fixed the bulletin scrape regex for the update command. ms changed it 265 | # 266 | # v10a 2014-03-24 267 | # - added a hotfixes argument, that can be used to supplement the list 268 | # of hotfixes detected in the systeminfo input 269 | # - added severity at the end of the output when reporting bulletins 270 | # - added a 'patches' argument, that can be used to determine any 271 | # of the hotfixes for a specific bulletin. this is good for debugging. 272 | # 273 | # v09a 2014-03-18 274 | # - again, another massive bug on the linked kb searching function 275 | # getlinkedms(). should be fixed now 276 | # - also checks columns 11 and 12 for superseded, i think it has to 277 | # do with dos and *nix output 278 | # 279 | # v08a 2014-02-14 280 | # - bug where the superseded column wasn't being checked 281 | # this may be because it's only xlsx and it parsed differently in csv 282 | # - added some new exploits from edb 283 | # 284 | # v07a 2014-02-12 285 | # - added indicator for os version, and in green 286 | # - better parsing of architecture for itanium based support 287 | # 288 | # v06a 2014-01-19 289 | # - added 'ostext' or 'o' option, when don't have any patch information 290 | # but just know the OS 291 | # 292 | # v05a 293 | # - added a check for "Kernel version" column, as well as "OS version" 294 | # 295 | # v04a 296 | # - added support for XLSX files directly with the updated XLRD library, this 297 | # requires the python-xlrd library to be installed and upgraded with: 298 | # $ pip install xlrd --upgrade 299 | # - changed MS13-101 to E, as there isn't a metasploit module (yet!) 300 | # 301 | # v03a 302 | # - fixed an issue where component KB wasn't being checked 303 | # 304 | # FUNCTIONS 305 | # 306 | # def main(): 307 | # def run(database): 308 | # def detect_encoding(filename): 309 | # def trace(database): 310 | # def patches(database): 311 | # def getversion(name, release, servicepack, architecture): 312 | # def getname(ostext): 313 | # def getrelease(ostext): 314 | # def getservicepack(ostext): 315 | # def getarchitecture(ostext): 316 | # def getitanium(ostext): 317 | # def getpatch(ostext): 318 | # def getbulletinids(haystack): 319 | # def isaffected(name, release, servicepack, architecture, haystack): 320 | # def getlinkedms(msids, database): 321 | # def getexploit(msid = 0): 322 | # def update(): 323 | # def merge_list(li): 324 | # 325 | import re 326 | import platform 327 | import argparse 328 | import subprocess 329 | import csv 330 | import StringIO 331 | import os 332 | import datetime 333 | import urllib2 334 | import io 335 | from random import randint 336 | from time import sleep 337 | from tempfile import NamedTemporaryFile 338 | from sys import exit 339 | 340 | # constants/globals 341 | MSSB_URL = 'http://www.microsoft.com/en-gb/download/confirmation.aspx?id=36982' 342 | BULLETIN_URL = 'http://download.microsoft.com/download/6/7/3/673E4349-1CA5-40B9-8879-095C72D5B49D/BulletinSearch.xlsx' 343 | VERSION = "3.3" 344 | 345 | # global parser 346 | parser = argparse.ArgumentParser(description="search microsoft security bulletins for exploits based upon the patch level of the machine by feeding in systeminfo command") 347 | parser.add_argument("-v", "--verbose", help="verbose output", action="store_true") 348 | parser.add_argument("-i", "--systeminfo", help="feed in an input file that contains the 'systeminfo' command") 349 | parser.add_argument("-d", "--database", help="the file that contains the microsoft security bulletin database") 350 | parser.add_argument("-u", "--update", help="required flag to even run the script", action="store_true") 351 | parser.add_argument("-a", "--audit", help="show all entries, not only exploits", action="store_true") 352 | parser.add_argument("-t", "--trace", help="used to determine linked ms bulletins") 353 | parser.add_argument("-p", "--patches", help="used to determine specific patches for a ms bulletin") 354 | parser.add_argument("-o", "--ostext", help="a loose text representation of the windows OS (ex: \"windows xp home edition sp2\")") 355 | parser.add_argument("-s", "--sub", help="generate output using linked/sub bulletins. WARNING: SLOW!", action="store_true") 356 | parser.add_argument("-2", "--duplicates", help="allow duplicate ms bulletin output within the results. this will produce a lot of output, but is useful when determining linked ms bulletins", action="store_true") 357 | parser.add_argument("-q", "--quiet", help="don't show exploit information. shorter output", action="store_true") 358 | # hotfixes 359 | # used to parse "wmic qfe list full" input, and to solve the 'File 1' errors 360 | parser.add_argument("-H", "--hotfixes", help="a loose list of hotfixes to be added, for use with the following command: 'wmic qfe list full'") 361 | 362 | # search by exploit type only 363 | exptypegroup = parser.add_mutually_exclusive_group() 364 | exptypegroup.add_argument("-r", "--remote", help="search remote exploits only", action="store_true") 365 | exptypegroup.add_argument("-l", "--local", help="search local exploits only", action="store_true") 366 | 367 | # global args parsed 368 | ARGS = parser.parse_args() 369 | 370 | def main(): 371 | ALERT("initiating winsploit version %s..." % VERSION) 372 | 373 | database = '' 374 | 375 | # if there is a database switch 376 | if ARGS.database: 377 | 378 | # split name and extension 379 | name, extension = os.path.splitext(ARGS.database) 380 | 381 | # csv 382 | if 'csv' in extension: 383 | 384 | ALERT("database file detected as csv based on extension", ALERT.NORMAL) 385 | 386 | # attempt to open the file 387 | try: 388 | dbfile = open(ARGS.database, 'r') 389 | 390 | except IOError, e: 391 | ALERT("could not open the file %s" % filename, ALERT.BAD) 392 | exit(1) 393 | 394 | data = '' 395 | for line in dbfile: 396 | data += line 397 | database = data 398 | 399 | dbfile.close() 400 | 401 | # xls or xslx 402 | elif 'xls' in extension: 403 | 404 | ALERT("database file detected as xls or xlsx based on extension", ALERT.NORMAL) 405 | 406 | try: 407 | import xlrd 408 | except ImportError as e: 409 | ALERT("please install and upgrade the python-xlrd library", ALERT.BAD) 410 | exit(1) 411 | 412 | # open the xls file 413 | try: 414 | wb = xlrd.open_workbook(ARGS.database) 415 | except IOError as e: 416 | ALERT("no such file or directory '%s'. ensure you have the correct database file passed in --database/-d" % ARGS.database, ALERT.BAD) 417 | exit(1) 418 | #sh = wb.sheet_by_name('Export Bulletin Search Spreadsh') 419 | sh = wb.sheet_by_index(0) 420 | 421 | # read the spreadsheet into a temp file 422 | f = NamedTemporaryFile(mode='wb') 423 | wr = csv.writer(f, quoting=csv.QUOTE_NONE, delimiter=',') 424 | 425 | data = '' 426 | 427 | # loop through xls 428 | for rownum in xrange(sh.nrows): 429 | 430 | values = sh.row_values(rownum) 431 | 432 | # loop through row values, and process input 433 | for i in range(len(values)): 434 | values[i] = unicode(values[i]).encode('utf8') 435 | values[i] = values[i].replace('\n',' ') 436 | values[i] = values[i].replace(',','') 437 | values[i] = values[i].replace('.0','') 438 | 439 | data += ",".join(values) 440 | data += '\n' 441 | 442 | # set the database to the csv data 443 | database = data 444 | 445 | # unknown filetype, error 446 | else: 447 | ALERT("unknown filetype. change file extension to indicate csv or xls/xlsx", ALERT.BAD) 448 | exit(1) 449 | 450 | if ARGS.trace: trace(database) 451 | elif ARGS.systeminfo or ARGS.ostext: run(database) 452 | elif ARGS.update: update() 453 | elif ARGS.patches: patches(database) 454 | 455 | # error 456 | else: 457 | ALERT("an error occured while running, not enough arguments", ALERT.BAD) 458 | exit(1) 459 | 460 | ALERT("done") 461 | # end main() 462 | 463 | def run(database): 464 | 465 | # variables used 466 | ostext=None 467 | name=None 468 | release=None 469 | servicepack=None 470 | 471 | # will default to 32-bit, but can be 64 bit or itanium 472 | architecture=None 473 | 474 | hotfixes=set([]) 475 | bulletinids=set([]) 476 | 477 | potential=[] 478 | 479 | vulns={} 480 | ids=set([]) 481 | 482 | cmdoutput = [] 483 | 484 | # test for database 485 | if not ARGS.database: 486 | ALERT("please supply a MSSB database file with the --database or -d flag, this can be downloaded using the --update command", ALERT.BAD) 487 | exit(1) 488 | 489 | # read from ostext first 490 | if ARGS.ostext: 491 | ALERT("getting OS information from command line text") 492 | 493 | name=getname(ARGS.ostext) 494 | release=getrelease(ARGS.ostext) 495 | servicepack=getservicepack(ARGS.ostext) 496 | architecture=getarchitecture(ARGS.ostext) 497 | 498 | # the os name at least has to be identified 499 | if not name: 500 | ALERT("unable to determine the windows version command line text from '%s'" % ARGS.ostext, ALERT.BAD) 501 | exit(1) 502 | 503 | # get the systeminfo information from the input file 504 | if ARGS.systeminfo: 505 | 506 | ALERT("attempting to read from the systeminfo input file") 507 | 508 | # when reading the systeminfo file, we want to attempt to detect it using chardet 509 | # if this doesn't work, we will loop through a list of common encodings and try them all 510 | encodings = ['utf-8', 'utf-16', 'utf-16-le', 'utf-16-be', 'iso-8859-2'] 511 | 512 | detected_encoding = detect_encoding(ARGS.systeminfo) 513 | 514 | # insert detected encoding to the front of the list 515 | if detected_encoding: 516 | if ARGS.verbose: ALERT("detected encoding of file as '%s'" % detected_encoding) 517 | encodings.insert(0, detected_encoding) 518 | 519 | cmdfile = None 520 | cmdoutput = None 521 | 522 | # now loop through all encodings, with the detected one first (if it was possible) 523 | for encoding in encodings: 524 | 525 | if ARGS.verbose: ALERT(" attempting to read with '%s' encoding" % encoding) 526 | 527 | # if we can read the file, and read the command output, we are done with the loop 528 | try: 529 | cmdfile = io.open(ARGS.systeminfo, "r", encoding=encoding) # throws UnicodeDecodeError 530 | cmdoutput = cmdfile.readlines() # throws UnicodeError 531 | break 532 | 533 | except (UnicodeError, UnicodeDecodeError) as e: 534 | ALERT("could not read file using '%s' encoding: %s" % (encoding, e), ALERT.BAD) 535 | 536 | # file might not exist 537 | except: 538 | ALERT("could not read from input file specified: %s" % ARGS.systeminfo, ALERT.BAD) 539 | exit(1) 540 | 541 | # general catchall if somehow it was able to keep processing 542 | if not cmdfile or not cmdoutput: 543 | ALERT("could not read from input file, or could not detect encoding", ALERT.BAD) 544 | exit(1) 545 | 546 | # file read successfully 547 | ALERT("systeminfo input file read successfully (%s)" % encoding, ALERT.GOOD) 548 | 549 | # error 550 | if not ARGS.systeminfo and not ARGS.ostext and platform.system() != 'Windows': 551 | ALERT("please run from a Windows machine, or provide an input file using --systeminfo, or use the --ostext option to get data with no patch information", ALERT.BAD) 552 | exit(1) 553 | 554 | # parse the systeminfo information 555 | hotfix=False 556 | 557 | # loop through the systeminfo input 558 | for haystack in cmdoutput: 559 | 560 | # only attempt to set the version, arch, service pack if there is no 561 | # ostext flag 562 | if not ARGS.ostext: 563 | 564 | # when detecting the operating system version, every line (independent of language) 565 | # appears to have Microsoft Windows in it, sometimes with (R) 566 | if "Microsoft" in haystack and "Windows" in haystack and not name: 567 | name = getname(haystack) 568 | 569 | # the windows release is similar to the above and has the text 'Microsoft Windows' in the text 570 | if "Microsoft" in haystack and "Windows" in haystack and not release: 571 | release = getrelease(haystack) 572 | 573 | # similar to OS, there is the words 'Service Pack' 574 | if "Service Pack" in haystack and not servicepack: 575 | servicepack = getservicepack(haystack) 576 | 577 | # get architecture only if -based is in the line, and --ostext hasn't been used 578 | if "-based" in haystack and not architecture: 579 | architecture=getarchitecture(haystack) 580 | 581 | # look for kbs 582 | if ("KB" in haystack or "]: " in haystack): 583 | patch=getpatch(haystack) 584 | 585 | # if a patch was parsed 586 | if patch: 587 | if ARGS.verbose: ALERT("found hotfix %s" % patch) 588 | hotfixes.add(patch) 589 | 590 | # now process the hotfixes argument input 591 | if ARGS.hotfixes: 592 | 593 | encodings = ['utf-8', 'utf-16', 'utf-16-le', 'utf-16-be', 'iso-8859-2'] 594 | 595 | detected_encoding = detect_encoding(ARGS.systeminfo) 596 | 597 | # insert detected encoding to the front of the list 598 | if detected_encoding: 599 | if ARGS.verbose: ALERT("detected encoding of file as '%s'" % detected_encoding) 600 | encodings.insert(0, detected_encoding) 601 | 602 | cmdfile = None 603 | hotfixesfile = None 604 | 605 | # now loop through all encodings, with the detected one first (if it was possible) 606 | for encoding in encodings: 607 | 608 | if ARGS.verbose: ALERT(" attempting to read with '%s' encoding" % encoding) 609 | 610 | # if we can read the file, and read the command output, we are done with the loop 611 | try: 612 | cmdfile = io.open(ARGS.hotfixes, "r", encoding=encoding) # throws UnicodeDecodeError 613 | hotfixesfile = cmdfile.readlines() # throws UnicodeError 614 | break 615 | 616 | except (UnicodeError, UnicodeDecodeError) as e: 617 | if ARGS.verbose: ALERT("could not read file using '%s' encoding: %s" % (encoding, e), ALERT.BAD) 618 | 619 | # file might not exist 620 | except: 621 | ALERT("could not read from input file specified: %s" % ARGS.hotfixes, ALERT.BAD) 622 | exit(1) 623 | 624 | # general catchall if somehow it was able to keep processing 625 | if not cmdfile or not hotfixesfile: 626 | ALERT("could not read from input file, or could not detect encoding", ALERT.BAD) 627 | exit(1) 628 | 629 | # file read successfully 630 | ALERT("hotfixes input file read successfully (%s)" % encoding, ALERT.GOOD) 631 | 632 | # loop through hotfixes file input 633 | for haystack in hotfixesfile: 634 | # look for kbs 635 | if ("KB" in haystack or "]: " in haystack): 636 | patch=getpatch(haystack) 637 | 638 | # if a patch was parsed 639 | if patch: 640 | if ARGS.verbose: ALERT("found hotfix %s" % patch) 641 | hotfixes.add(patch) 642 | 643 | if ARGS.verbose: 644 | ALERT("name: %s; release: %s; servicepack: %s; architecture: %s" % (name, release, servicepack, architecture)) 645 | 646 | # verify that a windows os was at least able to be parsed 647 | if not name: 648 | if ARGS.systeminfo: 649 | ALERT("unable to determine the windows versions from the input file specified. consider using --ostext option to force detection (example: --ostext 'windows 7 sp1 64-bit')", ALERT.BAD) 650 | exit(1) 651 | 652 | if ARGS.verbose: 653 | ALERT("name: %s" % name) 654 | ALERT("release: %s" % release) 655 | ALERT("service pack: %s" % servicepack) 656 | ALERT("architecture: %s" % architecture) 657 | 658 | ALERT("querying database file for potential vulnerabilities") 659 | 660 | # potential, all matches within the CSV database for the name,release,sp,arch 661 | # bulletinds, set of the above with MSIDs (good to keep count) 662 | 663 | # get the potential bulletins 664 | try: 665 | for row in csv.reader(StringIO.StringIO(database)): 666 | bulletinid=row[1] 667 | affected=row[6] 668 | 669 | if isaffected(name, release, servicepack, architecture, affected): 670 | 671 | # only add the bulletin if it's not already in the list 672 | if bulletinid not in bulletinids: 673 | potential.append(row) 674 | bulletinids.add(bulletinid) 675 | 676 | if ARGS.verbose: 677 | ALERT("%s has been added to potential list '%s'" % (bulletinid, affected)) 678 | 679 | except csv.Error, e: 680 | ALERT('could not parse database file, make sure it is in the proper format', ALERT.BAD) 681 | exit(1) 682 | 683 | # there should always be some potential vulns, because of the amount of windows software and false positives 684 | if len(bulletinid) == 0: 685 | ALERT("there are no potential vulnerabilities for, ensure you're searching a valid windows OS", ALERT.BAD) 686 | exit(1) 687 | 688 | ALERT("comparing the %s hotfix(es) against the %s potential bulletins(s) with a database of %s known exploits" % (len(hotfixes), len(bulletinids), getexploit())) 689 | 690 | # start removing the vulns because of hotfixes 691 | for row in list(potential): 692 | 693 | # ms bulletin 694 | bulletinid=row[1] 695 | kb=row[2] 696 | componentkb=row[7] 697 | 698 | for hotfix in hotfixes: 699 | 700 | # if either the hotfixes match the kb or componentkb columns, and the bulletin is in the list 701 | # of potential bulletins 702 | if (hotfix == kb or hotfix == componentkb) and bulletinid in bulletinids: 703 | 704 | if ARGS.verbose: 705 | ALERT(" %s hotfix triggered a removal of %skb and the %s bulletin; componentkb is %s" % (hotfix,kb,bulletinid,componentkb)) 706 | 707 | # get the linked ms, this will automatically calculate the superseded by as well 708 | linkedms = getlinkedms([bulletinid], csv.reader(StringIO.StringIO(database))) 709 | linkedmsstr = '' 710 | 711 | # calculate the pretty string, only care when verbose 712 | if len(linkedms) > 0: 713 | for m in linkedms: 714 | linkedmsstr += ' ' + m 715 | 716 | if ARGS.verbose: 717 | 718 | if hotfix == kb: 719 | ALERT(" due to presence of KB%s (Bulletin KB) removing%s bulletin(s)" % (kb, linkedmsstr)) 720 | 721 | elif componentkb == kb: 722 | ALERT(" due to presence of KB%s (Component KB) removing%s bulletin(s)" % (componentkb, linkedmsstr)) 723 | 724 | bulletinids = bulletinids.difference(linkedms) 725 | potential.remove(row) 726 | 727 | ALERT("there are now %s remaining vulns" % len(bulletinids)) 728 | 729 | # search local exploits only 730 | if ARGS.local: 731 | ALERT("searching for local exploits only") 732 | for row in list(potential): 733 | bulletinid = row[1] 734 | impact = row[4] 735 | 736 | if bulletinid in bulletinids and not "elevation of privilege" in impact.lower(): 737 | 738 | remove = getlinkedms([bulletinid], csv.reader(StringIO.StringIO(database))) 739 | 740 | if ARGS.verbose: 741 | ALERT(" removing %s (total of %s MS ids), because of its impact %s" % (bulletinid, len(remove), impact)) 742 | 743 | bulletinids = bulletinids.difference(remove) 744 | potential.remove(row) 745 | 746 | # search remote exploits only 747 | if ARGS.remote: 748 | ALERT("searching for remote exploits only") 749 | for row in list(potential): 750 | bulletinid = row[1] 751 | impact = row[4] 752 | 753 | if bulletinid in bulletinids and not "remote code execution" in impact.lower(): 754 | 755 | remove = getlinkedms([bulletinid], csv.reader(StringIO.StringIO(database))) 756 | 757 | if ARGS.verbose: 758 | ALERT(" removing %s (total of %s MS ids), because of its impact %s" % (bulletinid, len(remove), impact)) 759 | 760 | bulletinids = bulletinids.difference(remove) 761 | potential.remove(row) 762 | 763 | # print windows version 764 | version=getversion(name, release, servicepack, architecture) 765 | 766 | ALERT("[E] exploitdb PoC, [M] Metasploit module, [*] missing bulletin", ALERT.GOOD) 767 | ALERT("windows version identified as '%s'" % version, ALERT.GOOD) 768 | 769 | # spacer 770 | ALERT("") 771 | 772 | # vulns, the dictionary of the bulletins based off of the potential bulletins 773 | # also, a good opportunity to remove false-positives due to the 774 | # differences in the technet post and bulletin 775 | for row in potential: 776 | id = row[1] 777 | 778 | # start removing vulns because of false-positives 779 | # Manual override for MS11-011 to reduce false positives. The article was updated, but the bulletin database wasn't (https://technet.microsoft.com/en-us/library/security/ms11-011.aspx) 780 | # V1.2 (March 18, 2011): Added Windows 7 for 32-bit Systems Service Pack 1, Windows 7 for x64-based Systems Service Pack 1, Windows Server 2008 R2 for x64-based Systems Service Pack 1, and Windows Server 2008 R2 for Itanium-based Systems Service Pack 1 to Non-Affected Software. This is an informational change only. There were no changes to the security update files or detection logic. 781 | if id == 'MS11-011': 782 | ms11_011 = ['Windows 7 for 32-bit Systems Service Pack 1', 'Windows 7 for x64-based Systems Service Pack 1', 'Windows Server 2008 R2 for x64-based Systems Service Pack 1','Windows Server 2008 R2 for Itanium-based Systems Service Pack 1'] 783 | for not_affected in ms11_011: 784 | compare_version = getversion(getname(not_affected),getrelease(not_affected),getservicepack(not_affected),getarchitecture(not_affected)) 785 | if version == compare_version: 786 | if ARGS.verbose: ALERT("Ignoring MS11-011 false positive due to it not affecting '%s'" % compare_version) 787 | id = False 788 | 789 | for bulletinid in bulletinids: 790 | if bulletinid == id: 791 | title = row[5] 792 | kb = row[2] 793 | severity = row[3] 794 | if id not in ids: 795 | vulns[id] = [title,kb,severity] 796 | ids.add(id) 797 | 798 | # alerted, if a bulletin has been alerted to the user so that it doesn't appear twice 799 | # this occurs when a bulletin has multiple parents 800 | # msids, the actual data for all of the relevant msids (the row from the CSV) 801 | alerted = set() 802 | msids = sorted(vulns, reverse=True) 803 | 804 | # loop through the bulletinids which is the set of the actual bulletins that are to 805 | # be alerted 806 | for msid in msids: 807 | 808 | ## don't alert twice, no matter the case 809 | if msid not in alerted: 810 | 811 | # get the msid, exploitability alert rating, and resources 812 | m,exploit,resources = getexploit(msid) 813 | 814 | # only display the message, if the exploit flag isn't used 815 | # or if it is used, and the alert level is MSF or EXP 816 | if ARGS.audit or (exploit == ALERT.MSF or exploit == ALERT.EXP): 817 | 818 | alert = ALERT.NORMAL 819 | if exploit: alert = exploit 820 | 821 | ALERT("%s: %s (%s) - %s" % (msid, vulns[msid][0], vulns[msid][1], vulns[msid][2]), alert) 822 | if resources and not ARGS.quiet: 823 | for resource in resources: 824 | ALERT(" %s" % resource) 825 | ALERT("") 826 | 827 | alerted.add(msid) 828 | 829 | # only attempt to display linked/sub msids based on cli arguments 830 | if ARGS.sub: 831 | 832 | # linked ms, the children of this msid 833 | linked = set(getlinkedms([msid], csv.reader(StringIO.StringIO(database)))) 834 | linked = linked.intersection(msids) 835 | 836 | # loop through the linked msids, and only display those that qualify and 837 | # those that have not been alerted yet 838 | for lmsid in sorted(linked, reverse=True): 839 | if lmsid in msids and lmsid not in alerted: 840 | lexploit = getexploit(lmsid) 841 | lalert = ALERT.NORMAL 842 | if ARGS.audit or (lexploit == ALERT.MSF or lexploit == ALERT.EXP): 843 | if lexploit: lalert = lexploit 844 | ALERT("|_%s: %s (%s) - %s" % (lmsid, vulns[lmsid][0], vulns[lmsid][1], vulns[lmsid][2]), lalert) 845 | 846 | # only allow duplicate events to be displayed when command-line args passed 847 | if not ARGS.duplicates: alerted.add(lmsid) 848 | 849 | # end run() 850 | 851 | 852 | # attempt to detect character encoding of a file 853 | # otherwise return None 854 | # https://stackoverflow.com/questions/3323770/character-detection-in-a-text-file-in-python-using-the-universal-encoding-detect 855 | def detect_encoding(filename): 856 | try: 857 | import chardet 858 | data = open(filename, "r").read() 859 | result = chardet.detect(data) 860 | encoding = result['encoding'] 861 | return encoding 862 | except: 863 | return None 864 | 865 | # the trace command is used to determine linked MS bulletins 866 | # TODO much of this is duplicated from run(). should be merged 867 | def trace(database): 868 | 869 | # convert to upper 870 | bulletinid = ARGS.trace.upper() 871 | ALERT("searching for bulletin id %s" % bulletinid) 872 | 873 | # get linked msids 874 | lmsids = getlinkedms([bulletinid], csv.reader(StringIO.StringIO(database))) 875 | 876 | msids = [] 877 | 878 | if ARGS.ostext: 879 | ALERT("getting OS information from command line text") 880 | 881 | name=getname(ARGS.ostext) 882 | release=getrelease(ARGS.ostext) 883 | servicepack=getservicepack(ARGS.ostext) 884 | architecture=getarchitecture(ARGS.ostext) 885 | 886 | if ARGS.verbose: 887 | ALERT("name: %s" % name) 888 | ALERT("release: %s" % release) 889 | ALERT("service pack: %s" % servicepack) 890 | ALERT("architecture: %s" % architecture) 891 | 892 | # the os name at least has to be identified 893 | if not name: 894 | ALERT("unable to determine the windows version command line text from '%s'" % ARGS.ostext, ALERT.BAD) 895 | exit(1) 896 | 897 | # get linked msids, loop through the row 898 | for row in csv.reader(StringIO.StringIO(database)): 899 | msid = row[1] 900 | affected = row[6] 901 | 902 | if msid in lmsids: 903 | # debug 904 | #print ("%s,%s,%s,%s,%s,%s" % (msid, name, release, servicepack, architecture, affected)) 905 | 906 | if isaffected(name, release, servicepack, architecture, affected) and msid not in msids: msids.append(msid) 907 | 908 | 909 | else: msids = lmsids 910 | 911 | ALERT("linked msids %s" % msids, ALERT.GOOD) 912 | 913 | 914 | def patches(database): 915 | 916 | kbs = [] 917 | 918 | # convert to upper 919 | bulletinid = ARGS.patches.upper() 920 | ALERT("searching all kb's for bulletin id %s" % bulletinid) 921 | 922 | # get linked msids, loop through the row 923 | for row in csv.reader(StringIO.StringIO(database)): 924 | 925 | bulletinkb=row[2] 926 | componentkb=row[7] 927 | 928 | # if there's a match 929 | if bulletinid in row[1]: 930 | kbs.append(bulletinkb) 931 | kbs.append(componentkb) 932 | 933 | ALERT("relevant kbs %s" % (sorted(set(kbs), reverse=True)), ALERT.GOOD) 934 | 935 | def getversion(name, release, servicepack, architecture): 936 | 937 | version = "Windows " + name 938 | 939 | # append release first 940 | if release: version += " R" + release 941 | 942 | # then service pack 943 | if servicepack: version += " SP" + servicepack 944 | 945 | # architecture 946 | if architecture == "Itanium": version += " Itanium-based" 947 | else: version += " %s-bit" % architecture 948 | 949 | return version 950 | 951 | 952 | def getname(ostext): 953 | 954 | if ostext == False: 955 | return False 956 | 957 | osname=False 958 | 959 | osnamearray=[["xp","XP"], 960 | ["2000","2000"], 961 | ["2003","2003"], 962 | ["vista","Vista"], 963 | ["2008","2008"], 964 | [" 7","7"], 965 | [" 8","8"], 966 | ["2012","2012"], 967 | ["8.1","8.1"], 968 | [" 10","10"]] 969 | 970 | for needle in osnamearray: 971 | ostext = ostext.lower() 972 | if "windows" + needle[0] in ostext or "windows " + needle[0] in ostext or "server" + needle[0] in ostext or "server " + needle[0] in ostext: 973 | osname = needle[1] 974 | 975 | # the first loop is a more restrictive detection of the OS name, but it does not detect the following 976 | # > Microsoft Windows\xFF7 Entreprise 977 | # so if there is no detection from the first attempt, then search on a more loosely based string of 978 | # needle and space 979 | if not osname: 980 | for needle in osnamearray: 981 | if needle[0] + " " in ostext.lower(): 982 | osname = needle[1] 983 | 984 | return osname 985 | 986 | 987 | def getrelease(ostext): 988 | 989 | if ostext == False: 990 | return False 991 | 992 | osrelease=False 993 | 994 | regex="( r| rc|release|rel)[ ]*(\d)" 995 | m=re.search(regex, ostext.lower()) 996 | 997 | if m and m.group(2): 998 | osrelease=m.group(2) 999 | 1000 | return osrelease 1001 | 1002 | def getservicepack(ostext): 1003 | 1004 | if ostext == False: 1005 | return False 1006 | 1007 | servicepack=False 1008 | 1009 | regex="(sp|pack|pack:)[ ]*(\d)" 1010 | m=re.search(regex, ostext.lower()) 1011 | if m and m.group(2): 1012 | servicepack=m.group(2) 1013 | 1014 | return servicepack 1015 | 1016 | 1017 | # architecture defaults to 32, but can be 64-bit 1018 | # or itanium based 1019 | def getarchitecture(ostext): 1020 | 1021 | # default to 32-bit 1022 | architecture="32" 1023 | 1024 | # haystack 1025 | s = ostext.lower() 1026 | 1027 | # attempt to be as flexible as possible 1028 | # matching '64-based', 'x64', ' 64', 'i64', '64bit', '64 bit', '64-bit' 1029 | if ("64-based" in s) or ("x64" in s) or (" 64" in s) or ("i64" in s) or ("64bit" in s) or ("64 bit" in s) or ("64-bit" in s): architecture="64" 1030 | 1031 | # target Itanium with a simple search for 'tani' 1032 | if "tani" in s: architecture="Itanium" 1033 | 1034 | if getname(ostext) == "2008" and getrelease(ostext) == "2" and architecture == "32": 1035 | if ARGS.verbose: 1036 | ALERT("forcing unidentified architecture to 64-bit because OS identified as Windows 2008 R2 (although could be Itanium and wasn't detected?)") 1037 | architecture = "64" 1038 | 1039 | # windows server 2012 is only 64-bit arch 1040 | if getname(ostext) == "2012" and architecture == "32": 1041 | if ARGS.verbose: 1042 | ALERT("forcing unidentified architecture to 64-bit because OS identified as Windows Server 2012 does not support 32-bit") 1043 | architecture = "64" 1044 | 1045 | return architecture 1046 | 1047 | # itanium build search string 1048 | def getitanium(ostext): 1049 | 1050 | if ostext == False: 1051 | return False 1052 | 1053 | regex="(tanium)" 1054 | m=re.search(regex, ostext.lower()) 1055 | 1056 | if m: 1057 | return True 1058 | 1059 | return False 1060 | 1061 | def getpatch(ostext): 1062 | 1063 | patch=False 1064 | 1065 | regex="(\d){5,10}" 1066 | m=re.search(regex, ostext.lower()) 1067 | if m and m.group(): 1068 | patch=m.group() 1069 | 1070 | return patch 1071 | 1072 | # get the bulletin ids from the haystack 1073 | # these are typically in the form of: 1074 | # MS14-009[2898860] 1075 | # MS13-052[2833940],MS14-009[2898856] 1076 | # will return a list if found, otherwise false 1077 | def getbulletinids(haystack): 1078 | regex="MS[\d]{2,3}-[\d]{2,3}" 1079 | m = re.findall(regex, haystack) 1080 | if len(m) > 0: return m 1081 | return False 1082 | 1083 | def isaffected(name, release, servicepack, architecture, haystack): 1084 | 1085 | if name == getname(haystack): 1086 | 1087 | # ensure None are set to False 1088 | # example, if getservicepack() does not get called in the systeminfo parsing 1089 | # then servicepack will be None. this will then fail when comparing to False. 1090 | if release == None: release = False 1091 | if servicepack == None: servicepack = False 1092 | if architecture == None: architecture = False 1093 | 1094 | # print "%s,%s,%s,%s" % (name, release, servicepack, architecture) 1095 | # print "%s,%s,%s,%s" % (getname(haystack),getrelease(haystack),getservicepack(haystack),getarchitecture(haystack)) 1096 | 1097 | n = (name == getname(haystack)) 1098 | r = (release == getrelease(haystack)) 1099 | s = (servicepack == getservicepack(haystack)) 1100 | a = (architecture == getarchitecture(haystack)) 1101 | 1102 | # we ignore the architecture for 2012 servers, as there is only 64-bit 1103 | if name == "2012": return r and s 1104 | 1105 | # print "%s,%s,%s,%s,%s" % (name, release, servicepack, architecture, (a and r and s)) 1106 | 1107 | return a and r and s 1108 | 1109 | # search entire database for linked msids 1110 | # this will also search the superseded column (11) 1111 | def getlinkedms(msids, database): 1112 | 1113 | lmsids = [] 1114 | 1115 | # go through each row in the database 1116 | for row in database: 1117 | 1118 | # base MS-XX 1119 | rowid=row[1] 1120 | 1121 | # superseded MS-XX 1122 | 1123 | # first try row 12, and then row 11 for the supercedes column due to 1124 | # differences in csv and xlrd parsing. this was a bug that might be 1125 | # fixed now 1126 | rowidsuper = getbulletinids(row[12]) 1127 | if rowidsuper == False: rowidsuper=getbulletinids(row[11]) 1128 | 1129 | rowidsuper = merge_list(rowidsuper) 1130 | 1131 | # loop through each msid for each row 1132 | for msid in msids: 1133 | 1134 | # debug output, what we're working with 1135 | #print "%s,%s,%s" % (msid, rowid, rowidsuper) 1136 | # MS14-053,MS14-053,['MS13-052', 'MS14-009'] 1137 | # MS14-053,MS14-053,['MS13-004'] 1138 | # MS14-053,MS14-053,['MS13-004'] 1139 | # MS14-053,MS14-053,['MS13-004'] 1140 | # MS14-053,MS14-053,['MS13-004'] 1141 | # MS14-053,MS14-053,[] 1142 | 1143 | # if the msid matches the row, get the supercedes column (which is a list) 1144 | if msid == rowid or rowid in lmsids: 1145 | #print "%s,%s,%s" % (msid, rowid, rowidsuper) 1146 | lmsids.append(msid) 1147 | lmsids = lmsids + rowidsuper 1148 | 1149 | return sorted(set(lmsids), reverse=True) 1150 | 1151 | # determines whether or not an msid is in a list of exploits. if msid = 0 1152 | # then it will just return the count 1153 | def getexploit(msid = 0): 1154 | # search using searchsploit 1155 | #MS Windows (ListBox/ComboBox Control) Local Exploit (MS03-045) /windows/local/122.c 1156 | #MS Windows Utility Manager Local SYSTEM Exploit (MS04-011) /windows/local/271.c 1157 | #MS Windows 2000 Utility Manager Privilege Elevation Exploit (MS04-019) /windows/local/350.c 1158 | #MS Windows 2K POSIX Subsystem Privilege Escalation Exploit (MS04-020) /windows/local/351.c 1159 | #MS Windows 2000 Universal Language Utility Manager Exploit (MS04-019) /windows/local/352.c 1160 | #MS Windows 2K/XP Task Scheduler .job Exploit (MS04-022) /windows/local/353.c 1161 | #MS Windows 2k Utility Manager (All-In-One) Exploit (MS04-019) /windows/local/355.c 1162 | #MS Windows XP Task Scheduler (.job) Universal Exploit (MS04-022) /windows/local/368.c 1163 | #MS Windows (HTA) Script Execution Exploit (MS05-016) /windows/local/938.cpp 1164 | #MS Windows COM Structured Storage Local Exploit (MS05-012) /windows/local/1019.c 1165 | #MS Windows CSRSS Local Privilege Escalation Exploit (MS05-018) /windows/local/1198.c 1166 | #MS Windows 2k Kernel APC Data-Free Local Escalation Exploit (MS05-055) /windows/local/1407.c 1167 | #MS Windows Telephony Service Command Execution Exploit (MS05-040) /windows/local/1584.cpp 1168 | #MS Windows (NtClose DeadLock) Vulnerability PoC (MS06-030) /windows/local/1910.c 1169 | #MS Windows XP/2K (Mrxsmb.sys) Privilege Escalation PoC (MS06-030) /windows/local/1911.c 1170 | #Microsoft IIS ASP Stack Overflow Exploit (MS06-034) /windows/local/2056.c 1171 | #MS Windows (Windows Kernel) Privilege Escalation Exploit (MS06-049) /windows/local/2412.c 1172 | #MS Windows GDI Local Privilege Escalation Exploit (MS07-017) /windows/local/3688.c 1173 | #MS Windows GDI Local Privilege Escalation Exploit (MS07-017) 2 /windows/local/3755.c 1174 | #Kodak Image Viewer TIF/TIFF Code Execution Exploit PoC (MS07-055) /windows/local/4584.c 1175 | #Microsoft Office .WPS File Stack Overflow Exploit (MS08-011) /windows/local/5107.c 1176 | #Microsoft Office Excel Code Execution Exploit (MS08-014) /windows/local/5287.txt 1177 | #Microsoft Office XP SP3 PPT File Buffer Overflow Exploit (ms08-016) /windows/local/5320.txt 1178 | #MS Windows GDI Image Parsing Stack Overflow Exploit (MS08-021) /windows/local/5442.cpp 1179 | 1180 | #MS Word Record Parsing Buffer Overflow (MS09-027) /windows/local/14693.py 1181 | #MS Excel Malformed FEATHEADER Record Exploit (MS09-067) /windows/local/14706.py 1182 | #MS Word Record Parsing Buffer Overflow MS09-027 (meta) /windows/local/17177.rb 1183 | #MS Internet Explorer Object Tag Exploit (MS03-020) /windows/remote/37.pl 1184 | #MS Windows Media Services Remote Exploit (MS03-022) /windows/remote/48.c 1185 | #Microsoft WordPerfect Document Converter Exploit (MS03-036) /windows/remote/92.c 1186 | #MS Windows (RPC DCOM) Scanner (MS03-039) /windows/remote/97.c 1187 | #MS Windows (RPC DCOM) Long Filename Overflow Exploit (MS03-026) /windows/remote/100.c 1188 | #MS Windows (RPC DCOM2) Remote Exploit (MS03-039) /windows/remote/103.c 1189 | #MS Windows (RPC2) Universal Exploit & DoS (RPC3) (MS03-039) /windows/remote/109.c 1190 | #MS Windows 2000/XP Workstation Service Overflow (MS03-049) /windows/remote/119.c 1191 | #MS Frontpage Server Extensions fp30reg.dll Exploit (MS03-051) /windows/remote/121.c 1192 | #MS Windows Workstation Service WKSSVC Remote Exploit (MS03-049) /windows/remote/123.c 1193 | #MS Windows XP Workstation Service Remote Exploit (MS03-049) /windows/remote/130.c 1194 | #MS Windows Messenger Service Remote Exploit FR (MS03-043) /windows/remote/135.c 1195 | #MS Internet Explorer URL Injection in History List (MS04-004) /windows/remote/151.txt 1196 | #MS Windows IIS 5.0 SSL Remote buffer overflow Exploit (MS04-011) /windows/remote/275.c 1197 | #MS Windows Lsasrv.dll RPC Remote Buffer Overflow Exploit (MS04-011) /windows/remote/293.c 1198 | #MS Windows XP/2K Lsasrv.dll Remote Universal Exploit (MS04-011) /windows/remote/295.c 1199 | #MS Windows JPEG GDI+ Overflow Administrator Exploit (MS04-028) /windows/remote/475.sh 1200 | #MS Windows JPEG GDI+ Overflow Download Shellcode Exploit (MS04-028) /windows/remote/478.c 1201 | #MS Windows JPEG GDI+ Remote Heap Overflow Exploit (MS04-028) /windows/remote/480.c 1202 | #MS Windows Metafile (.emf) Heap Overflow Exploit (MS04-032) /windows/remote/584.c 1203 | #MS Windows Compressed Zipped Folders Exploit (MS04-034) /windows/remote/640.c 1204 | #MS Windows NetDDE Remote Buffer Overflow Exploit (MS04-031) /windows/remote/734.c 1205 | #MS Internet Explorer .ANI files handling Universal Exploit (MS05-002) /windows/remote/765.c 1206 | #MS Internet Explorer .ANI files handling Downloader Exploit (MS05-002) /windows/remote/771.cpp 1207 | #MS Exchange Server Remote Code Execution Exploit (MS05-021) /windows/remote/947.pl 1208 | #MS Outlook Express NNTP Buffer Overflow Exploit (MS05-030) /windows/remote/1066.cpp 1209 | #MS Windows Message Queuing BoF Universal Exploit (MS05-017) (v.0.3) /windows/remote/1075.c 1210 | #MS Internet Explorer (blnmgr.dll) COM Object Remote Exploit (MS05-038) /windows/remote/1144.html 1211 | #MS Windows Plug-and-Play Service Remote Overflow (MS05-039) /windows/remote/1146.c 1212 | #MS Windows Plug-and-Play Service Remote Universal Exploit (MS05-039) /windows/remote/1149.c 1213 | #Microsoft Windows DTC Remote Exploit (PoC) (MS05-051) (updated) /windows/remote/1352.cpp 1214 | #Windows Media Player 7.1 <= 10 BMP Heap Overflow PoC (MS06-005) (2) /windows/remote/1502.py 1215 | #MS Windows Media Player 9 Plugin Overflow Exploit (MS06-006) (meta) /windows/remote/1504.pm 1216 | #MS Windows Media Player 10 Plugin Overflow Exploit (MS06-006) /windows/remote/1505.html 1217 | #MS Windows Color Management Module Overflow Exploit (MS05-036) (2) /windows/remote/1506.c 1218 | #MS Windows Media Player Plugin Overflow Exploit (MS06-006)(3) /windows/remote/1520.pl 1219 | #MS Windows RRAS Remote Stack Overflow Exploit (MS06-025) /windows/remote/1940.pm 1220 | #MS Windows RRAS RASMAN Registry Stack Overflow Exploit (MS06-025) /windows/remote/1965.pm 1221 | #MS Internet Explorer (MDAC) Remote Code Execution Exploit (MS06-014) /windows/remote/2052.sh 1222 | #MS Windows DHCP Client Broadcast Attack Exploit (MS06-036) /windows/remote/2054.txt 1223 | #MS Windows NetpIsRemote() Remote Overflow Exploit (MS06-040) /windows/remote/2162.pm 1224 | #Internet Explorer (MDAC) Remote Code Execution Exploit (MS06-014) (2) /windows/remote/2164.pm 1225 | #MS Windows CanonicalizePathName() Remote Exploit (MS06-040) /windows/remote/2223.c 1226 | #MS Windows NetpIsRemote() Remote Overflow Exploit (MS06-040) (2) /windows/remote/2265.c 1227 | #MS Windows NetpIsRemote() Remote Overflow Exploit (MS06-040) (2k3) /windows/remote/2355.pm 1228 | #MS Windows NetpManageIPCConnect Stack Overflow Exploit (MS06-070) /windows/remote/2789.cpp 1229 | #MS Windows Wkssvc NetrJoinDomain2 Stack Overflow Exploit (MS06-070) /windows/remote/2800.cpp 1230 | #MS Windows ASN.1 Remote Exploit (MS04-007) /windows/remote/3022.txt 1231 | #MS Internet Explorer VML Remote Buffer Overflow Exploit (MS07-004) /windows/remote/3137.html 1232 | #MS Internet Explorer VML Download and Execute Exploit (MS07-004) /windows/remote/3148.pl 1233 | #MS Internet Explorer Recordset Double Free Memory Exploit (MS07-009) /windows/remote/3577.html 1234 | #MS Windows (.ANI) GDI Remote Elevation of Privilege Exploit (MS07-017) /windows/remote/3804.txt 1235 | #MS Internet Explorer <= 7 Remote Arbitrary File Rewrite PoC (MS07-027) /windows/remote/3892.html 1236 | #Microsoft Internet Explorer TIF/TIFF Code Execution (MS07-055) /windows/remote/4616.pl 1237 | #MS Windows Message Queuing Service RPC BOF Exploit (MS07-065) /windows/remote/4745.cpp 1238 | #MS Windows 2000 AS SP4 Message Queue Exploit (MS07-065) /windows/remote/4760.txt 1239 | #Windows Media Encoder wmex.dll ActiveX BOF Exploit (MS08-053) /windows/remote/6454.html 1240 | #MS Windows GDI (EMR_COLORMATCHTOTARGETW) Exploit MS08-021 /windows/remote/6656.txt 1241 | #MS Windows Server Service Code Execution Exploit (MS08-067) (Univ) /windows/remote/6841.txt 1242 | #MS Windows Server Service Code Execution Exploit (MS08-067) /windows/remote/7104.c 1243 | #SmbRelay3 NTLM Replay Attack Tool/Exploit (MS08-068) /windows/remote/7125.txt 1244 | #MS Windows Server Service Code Execution Exploit (MS08-067) (2k/2k3) /windows/remote/7132.py 1245 | #Microsoft XML Core Services DTD Cross-Domain Scripting PoC MS08-069 /windows/remote/7196.html 1246 | #MS Internet Explorer 7 Memory Corruption Exploit (MS09-002) (xp sp2) /windows/remote/8079.html 1247 | #MS Internet Explorer 7 Memory Corruption Exploit (MS09-002) (py) /windows/remote/8080.py 1248 | #MS Internet Explorer 7 Memory Corruption PoC (MS09-002) (win2k3sp2) /windows/remote/8082.html 1249 | #MS Internet Explorer 7 Memory Corruption Exploit (MS09-002) (fast) /windows/remote/8152.py 1250 | #Microsoft SRV2.SYS SMB Negotiate ProcessID Function Table Dereference (MS09-050) /windows/remote/14674.txt 1251 | #Microsoft Services MS06-066 nwwks.dll /windows/remote/16369.rb 1252 | #Microsoft Services MS06-066 nwapi32.dll /windows/remote/16373.rb 1253 | #MS03-020 Internet Explorer Object Type /windows/remote/16581.rb 1254 | #MS03-046 Exchange 2000 XEXCH50 Heap Overflow /windows/remote/16820.rb 1255 | 1256 | # no ms number yet? 1257 | #MS??-???,http://www.exploit-db.com/exploits/30014/,P,??2914486 1258 | # bulletin, type, details 1259 | exploits = [ 1260 | 1261 | ['MS16-135', ALERT.EXP, [ # CVE-2016-7255 1262 | "https://www.exploit-db.com/exploits/40745/ -- Microsoft Windows Kernel - win32k Denial of Service (MS16-135)", 1263 | "https://www.exploit-db.com/exploits/41015/ -- Microsoft Windows Kernel - 'win32k.sys' 'NtSetWindowLongPtr' Privilege Escalation (MS16-135) (2)", 1264 | "https://github.com/tinysec/public/tree/master/CVE-2016-7255"]], 1265 | 1266 | ['MS16-129', ALERT.EXP, [ # CVE 2016-7200, CVE-2016-7201 1267 | "https://www.exploit-db.com/exploits/40990/ -- Microsoft Edge (Windows 10) - 'chakra.dll' Info Leak / Type Confusion Remote Code Execution", 1268 | "https://github.com/theori-io/chakra-2016-11"]], 1269 | 1270 | ['MS16-098', ALERT.EXP, [ 1271 | "https://www.exploit-db.com/exploits/41020/ -- Microsoft Windows 8.1 (x64) - RGNOBJ Integer Overflow (MS16-098)"]], 1272 | 1273 | ['MS16-075', ALERT.MSF, [ 1274 | "https://github.com/foxglovesec/RottenPotato", 1275 | "https://github.com/Kevin-Robertson/Tater", 1276 | "https://bugs.chromium.org/p/project-zero/issues/detail?id=222 -- Windows: Local WebDAV NTLM Reflection Elevation of Privilege", 1277 | "https://foxglovesecurity.com/2016/01/16/hot-potato/ -- Hot Potato - Windows Privilege Escalation"]], 1278 | 1279 | ['MS16-074', ALERT.EXP, [ # CVE 2016-3216 1280 | "https://www.exploit-db.com/exploits/39990/ -- Windows - gdi32.dll Multiple DIB-Related EMF Record Handlers Heap-Based Out-of-Bounds Reads/Memory Disclosure (MS16-074), PoC", 1281 | "https://www.exploit-db.com/exploits/39991/ -- Windows Kernel - ATMFD.DLL NamedEscape 0x250C Pool Corruption (MS16-074), PoC"]], # CVE 2016-3220 1282 | 1283 | ['MS16-063', ALERT.EXP, [ # CVE 2016-0199 1284 | "https://www.exploit-db.com/exploits/39994/ -- Internet Explorer 11 - Garbage Collector Attribute Type Confusion (MS16-063), PoC"]], 1285 | 1286 | ['MS16-042', ALERT.EXP, [ # CVE 2016-0122 1287 | "https://www.exploit-db.com/exploits/39694/ -- Microsoft Office Excel Out-of-Bounds Read Remote Code Execution (MS16-042), PoC"]], 1288 | 1289 | ['MS16-059', ALERT.EXP, [ # CVE 2016-0185 1290 | "https://www.exploit-db.com/exploits/39805/ -- Microsoft Windows Media Center - .MCL File Processing Remote Code Execution (MS16-059), PoC"]], 1291 | 1292 | ['MS16-056', ALERT.EXP, [ # CVE-2015-1730 1293 | "https://www.exploit-db.com/exploits/40881/ -- Microsoft Internet Explorer - jscript9 Java­Script­Stack­Walker Memory Corruption (MS15-056)", 1294 | "http://blog.skylined.nl/20161206001.html -- MSIE jscript9 Java­Script­Stack­Walker memory corruption"]], 1295 | 1296 | ['MS16-032', ALERT.EXP, [ # CVE 2016-0099 1297 | "https://www.exploit-db.com/exploits/40107/ -- MS16-032 Secondary Logon Handle Privilege Escalation, MSF", 1298 | "https://www.exploit-db.com/exploits/39574/ -- Microsoft Windows 8.1/10 - Secondary Logon Standard Handles Missing Sanitization Privilege Escalation (MS16-032), PoC", 1299 | "https://www.exploit-db.com/exploits/39719/ -- Microsoft Windows 7-10 & Server 2008-2012 (x32/x64) - Local Privilege Escalation (MS16-032) (PowerShell), PoC", 1300 | "https://www.exploit-db.com/exploits/39809/ -- Microsoft Windows 7-10 & Server 2008-2012 (x32/x64) - Local Privilege Escalation (MS16-032) (C#)"]], 1301 | 1302 | ['MS16-016', ALERT.MSF, [ # CVE 2016-0051 1303 | "https://www.exploit-db.com/exploits/40085/ -- MS16-016 mrxdav.sys WebDav Local Privilege Escalation, MSF", 1304 | "https://www.exploit-db.com/exploits/39788/ -- Microsoft Windows 7 - WebDAV Privilege Escalation Exploit (MS16-016) (2), PoC", 1305 | "https://www.exploit-db.com/exploits/39432/ -- Microsoft Windows 7 SP1 x86 - WebDAV Privilege Escalation (MS16-016) (1), PoC"]], 1306 | 1307 | ['MS16-014', ALERT.EXP, [ # CVE 2016-0400 1308 | "Windows 7 SP1 x86 - Privilege Escalation (MS16-014), https://www.exploit-db.com/exploits/40039/, PoC"]], 1309 | 1310 | ['MS16-007', ALERT.EXP, [ # CVE 2016-0015, CVE 2016-0016 1311 | "https://www.exploit-db.com/exploits/39232/ -- Microsoft Windows devenum.dll!DeviceMoniker::Load() - Heap Corruption Buffer Underflow (MS16-007), PoC", 1312 | "https://www.exploit-db.com/exploits/39233/ -- Microsoft Office / COM Object DLL Planting with WMALFXGFXDSP.dll (MS-16-007), PoC"]], 1313 | 1314 | ['MS15-134', ALERT.EXP, [ # CVE 2015-6131 1315 | "https://www.exploit-db.com/exploits/38911/ -- Microsoft Windows Media Center Library Parsing RCE Vulnerability aka self-executing' MCL File, PoC", 1316 | "https://www.exploit-db.com/exploits/38912/ -- Microsoft Windows Media Center Link File Incorrectly Resolved Reference, PoC", 1317 | "https://www.exploit-db.com/exploits/38918/ -- Microsoft Office / COM Object - 'els.dll' DLL Planting (MS15-134)", 1318 | "https://code.google.com/p/google-security-research/issues/detail?id=514 -- Microsoft Office / COM Object DLL Planting with els.dll"]], 1319 | 1320 | ['MS15-132', ALERT.EXP, [ # CVE 2015-6132, CVE 2015-6128 1321 | "https://www.exploit-db.com/exploits/38968/ -- Microsoft Office / COM Object DLL Planting with comsvcs.dll Delay Load of mqrt.dll (MS15-132), PoC", 1322 | "https://www.exploit-db.com/exploits/38918/ -- Microsoft Office / COM Object els.dll DLL Planting (MS15-134), PoC"]], 1323 | 1324 | ['MS15-112', ALERT.EXP, [ # CVE 2015-6086 1325 | "https://www.exploit-db.com/exploits/39698/ -- Internet Explorer 9/10/11 - CDOMStringDataList::InitFromString Out-of-Bounds Read (MS15-112)"]], 1326 | 1327 | ['MS15-111', ALERT.EXP, [ # CVE 2015-2553 1328 | "https://www.exploit-db.com/exploits/38474/ -- Windows 10 Sandboxed Mount Reparse Point Creation Mitigation Bypass (MS15-111), PoC"]], 1329 | 1330 | ['MS15-102', ALERT.EXP, [ # CVE 2015-2524, CVE 2015-2525, CVE 2015-2528 1331 | "https://www.exploit-db.com/exploits/38202/ -- Windows CreateObjectTask SettingsSyncDiagnostics Privilege Escalation, PoC", 1332 | "https://www.exploit-db.com/exploits/38200/ -- Windows Task Scheduler DeleteExpiredTaskAfter File Deletion Privilege Escalation, PoC", 1333 | "https://www.exploit-db.com/exploits/38201/ -- Windows CreateObjectTask TileUserBroker Privilege Escalation, PoC"]], 1334 | 1335 | ['MS15-100', ALERT.MSF, [ # CVE 2015-2509 1336 | "https://www.exploit-db.com/exploits/38195/ -- MS15-100 Microsoft Windows Media Center MCL Vulnerability, MSF", 1337 | "https://www.exploit-db.com/exploits/38151/ -- Windows Media Center - Command Execution (MS15-100), PoC"]], 1338 | 1339 | ['MS15-097', ALERT.EXP, [ # CVE 2015-2508, CVE 2015-2527 1340 | "https://www.exploit-db.com/exploits/38198/ -- Windows 10 Build 10130 - User Mode Font Driver Thread Permissions Privilege Escalation, PoC", 1341 | "https://www.exploit-db.com/exploits/38199/ -- Windows NtUserGetClipboardAccessToken Token Leak, PoC"]], 1342 | 1343 | ['MS15-078', ALERT.MSF, [ # CVE 2015-2426, CVE 2015-2433 1344 | "https://www.exploit-db.com/exploits/38222/ -- MS15-078 Microsoft Windows Font Driver Buffer Overflow"]], 1345 | 1346 | ['MS15-052', ALERT.EXP, [ # CVE 2015-1674 1347 | "https://www.exploit-db.com/exploits/37052/ -- Windows - CNG.SYS Kernel Security Feature Bypass PoC (MS15-052), PoC"]], 1348 | 1349 | ['MS15-051', ALERT.MSF, [ # CVE 2015-1701 1350 | "https://github.com/hfiref0x/CVE-2015-1701, Win32k Elevation of Privilege Vulnerability, PoC", 1351 | "https://www.exploit-db.com/exploits/37367/ -- Windows ClientCopyImage Win32k Exploit, MSF"]], 1352 | 1353 | ['MS15-022', ALERT.EXP, [ # CVE 2015-0097 1354 | "https://www.exploit-db.com/exploits/37657/ -- Microsoft Word Local Machine Zone Remote Code Execution Vulnerability, PoC", 1355 | "https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/37657.zip"]], 1356 | 1357 | ['MS15-010', ALERT.EXP, [ # CVE 2015-0057 1358 | "https://www.exploit-db.com/exploits/39035/ -- Microsoft Windows 8.1 - win32k Local Privilege Escalation (MS15-010), PoC", 1359 | "https://www.exploit-db.com/exploits/37098/ -- Microsoft Windows - Local Privilege Escalation (MS15-010), PoC", 1360 | "https://www.exploit-db.com/exploits/39035/ -- Microsoft Windows win32k Local Privilege Escalation (MS15-010), PoC"]], 1361 | 1362 | ['MS15-001', ALERT.EXP, [ # CVE 2015-0002 1363 | "http://www.exploit-db.com/exploits/35661/ -- Windows 8.1 (32/64 bit) - Privilege Escalation (ahcache.sys/NtApphelpCacheControl), PoC"]], 1364 | 1365 | ['MS14-070', ALERT.EXP, [ # CVE 2014 4076 1366 | "http://www.exploit-db.com/exploits/35936/ -- Microsoft Windows Server 2003 SP2 - Privilege Escalation, PoC"]], 1367 | 1368 | ['MS14-068', ALERT.EXP, [ # CVE 2014-6324 1369 | "http://www.exploit-db.com/exploits/35474/ -- Windows Kerberos - Elevation of Privilege (MS14-068), PoC"]], 1370 | 1371 | ['MS14-064', ALERT.MSF, [ # CVE 2014-6332 1372 | "https://www.exploit-db.com/exploits/37800// -- Microsoft Windows HTA (HTML Application) - Remote Code Execution (MS14-064), PoC", 1373 | "http://www.exploit-db.com/exploits/35308/ -- Internet Explorer OLE Pre-IE11 - Automation Array Remote Code Execution / Powershell VirtualAlloc (MS14-064), PoC", 1374 | "http://www.exploit-db.com/exploits/35229/ -- Internet Explorer <= 11 - OLE Automation Array Remote Code Execution (#1), PoC", 1375 | "http://www.exploit-db.com/exploits/35230/ -- Internet Explorer < 11 - OLE Automation Array Remote Code Execution (MSF), MSF", 1376 | "http://www.exploit-db.com/exploits/35235/ -- MS14-064 Microsoft Windows OLE Package Manager Code Execution Through Python, MSF", 1377 | "http://www.exploit-db.com/exploits/35236/ -- MS14-064 Microsoft Windows OLE Package Manager Code Execution, MSF"]], 1378 | 1379 | ['MS14-062', ALERT.MSF, [ # CVE 2014-4971 1380 | "http://www.exploit-db.com/exploits/34112/ -- Microsoft Windows XP SP3 MQAC.sys - Arbitrary Write Privilege Escalation, PoC", 1381 | "http://www.exploit-db.com/exploits/34982/ -- Microsoft Bluetooth Personal Area Networking (BthPan.sys) Privilege Escalation"]], 1382 | 1383 | ['MS14-060', ALERT.MSF, [ # CVE 2014-4114 1384 | "http://www.exploit-db.com/exploits/35055/ -- Windows OLE - Remote Code Execution 'Sandworm' Exploit (MS14-060), PoC", 1385 | "http://www.exploit-db.com/exploits/35020/ -- MS14-060 Microsoft Windows OLE Package Manager Code Execution, MSF"]], 1386 | 1387 | ['MS14-058', ALERT.MSF, [ # CVE 2014-4113 1388 | "http://www.exploit-db.com/exploits/35101/ -- Windows TrackPopupMenu Win32k NULL Pointer Dereference, MSF"]], 1389 | 1390 | ['MS14-040', ALERT.EXP, [ # CVE 2014-1767 1391 | "https://www.exploit-db.com/exploits/39525/ -- Microsoft Windows 7 x64 - afd.sys Privilege Escalation (MS14-040), PoC", 1392 | "https://www.exploit-db.com/exploits/39446/ -- Microsoft Windows - afd.sys Dangling Pointer Privilege Escalation (MS14-040), PoC"]], 1393 | 1394 | ['MS14-035', ALERT.EXP], 1395 | ['MS14-029', ALERT.EXP, [ 1396 | "http://www.exploit-db.com/exploits/34458/"]], 1397 | 1398 | ['MS14-026', ALERT.EXP, [ # CVE 2014-1806 1399 | "http://www.exploit-db.com/exploits/35280/, -- .NET Remoting Services Remote Command Execution, PoC"]], 1400 | 1401 | ['MS14-017', ALERT.MSF], 1402 | ['MS14-012', ALERT.MSF], 1403 | ['MS14-009', ALERT.MSF], 1404 | ['MS14-002', ALERT.EXP], 1405 | ['MS13-101', ALERT.EXP], 1406 | ['MS13-097', ALERT.MSF], 1407 | ['MS13-096', ALERT.MSF], 1408 | ['MS13-090', ALERT.MSF], 1409 | ['MS13-080', ALERT.MSF], 1410 | ['MS13-071', ALERT.MSF], 1411 | ['MS13-069', ALERT.MSF], 1412 | ['MS13-067', ALERT.EXP], 1413 | ['MS13-059', ALERT.MSF], 1414 | ['MS13-055', ALERT.MSF], 1415 | ['MS13-053', ALERT.MSF], 1416 | ['MS13-009', ALERT.MSF], 1417 | ['MS13-005', ALERT.MSF], 1418 | ['MS12-037', ALERT.EXP, [ # CVE 2012-1876 1419 | "http://www.exploit-db.com/exploits/35273/ -- Internet Explorer 8 - Fixed Col Span ID Full ASLR, DEP & EMET 5., PoC", 1420 | "http://www.exploit-db.com/exploits/34815/ -- Internet Explorer 8 - Fixed Col Span ID Full ASLR, DEP & EMET 5.0 Bypass (MS12-037), PoC"]], 1421 | 1422 | ['MS12-022', ALERT.MSF], 1423 | ['MS11-080', ALERT.MSF], 1424 | ['MS11-011', ALERT.EXP], 1425 | ['MS10-073', ALERT.MSF], 1426 | ['MS10-061', ALERT.MSF], 1427 | ['MS10-059', ALERT.EXP], 1428 | ['MS10-047', ALERT.EXP], 1429 | ['MS10-015', ALERT.MSF], 1430 | ['MS10-002', ALERT.MSF], 1431 | ['MS09-072', ALERT.MSF], 1432 | ['MS09-067', ALERT.MSF], 1433 | ['MS09-065', ALERT.MSF], 1434 | ['MS09-053', ALERT.MSF], 1435 | ['MS09-050', ALERT.MSF, [ 1436 | "https://www.rapid7.com/db/modules/exploit/windows/smb/ms09_050_smb2_negotiate_func_index -- MS09-050 Microsoft SRV2.SYS SMB Negotiate ProcessID Function Table Dereference"]], 1437 | 1438 | ['MS09-050', ALERT.MSF], 1439 | ['MS09-043', ALERT.MSF], 1440 | ['MS09-020', ALERT.MSF], 1441 | ['MS09-004', ALERT.MSF], 1442 | ['MS09-002', ALERT.MSF], 1443 | ['MS09-001', ALERT.MSF], 1444 | ['MS08-078', ALERT.MSF], 1445 | ['MS08-070', ALERT.MSF], 1446 | ['MS08-067', ALERT.MSF], 1447 | ['MS08-067', ALERT.MSF], 1448 | ['MS08-053', ALERT.MSF], 1449 | ['MS08-041', ALERT.MSF], 1450 | ['MS08-025', ALERT.EXP], 1451 | ['MS07-065', ALERT.MSF], 1452 | ['MS07-065', ALERT.MSF], 1453 | ['MS07-064', ALERT.MSF], 1454 | ['MS07-029', ALERT.MSF], 1455 | ['MS07-029', ALERT.MSF], 1456 | ['MS07-017', ALERT.MSF], 1457 | ['MS06-071', ALERT.MSF], 1458 | ['MS06-070', ALERT.MSF], 1459 | ['MS06-070', ALERT.MSF], 1460 | ['MS06-067', ALERT.MSF], 1461 | ['MS06-066', ALERT.MSF], 1462 | ['MS06-066', ALERT.MSF], 1463 | ['MS06-063', ALERT.MSF], 1464 | ['MS06-057', ALERT.MSF], 1465 | ['MS06-055', ALERT.MSF], 1466 | ['MS06-049', ALERT.EXP], 1467 | ['MS06-040', ALERT.MSF], 1468 | ['MS06-040', ALERT.MSF], 1469 | ['MS06-035', ALERT.MSF], 1470 | ['MS06-025', ALERT.MSF], 1471 | ['MS06-025', ALERT.MSF], 1472 | ['MS06-019', ALERT.MSF], 1473 | ['MS06-013', ALERT.MSF], 1474 | ['MS06-001', ALERT.MSF], 1475 | ['MS05-054', ALERT.MSF], 1476 | ['MS05-047', ALERT.MSF], 1477 | ['MS05-039', ALERT.MSF], 1478 | ['MS05-039', ALERT.MSF], 1479 | ['MS05-030', ALERT.MSF], 1480 | ['MS05-017', ALERT.MSF], 1481 | ['MS05-017', ALERT.MSF], 1482 | ['MS04-045', ALERT.MSF], 1483 | ['MS04-031', ALERT.MSF], 1484 | ['MS04-031', ALERT.MSF], 1485 | ['MS04-011', ALERT.MSF], 1486 | ['MS04-011', ALERT.MSF], 1487 | ['MS04-007', ALERT.MSF], 1488 | ['MS04-007', ALERT.MSF], 1489 | ['MS03-051', ALERT.MSF], 1490 | ['MS03-049', ALERT.MSF], 1491 | ['MS03-049', ALERT.MSF], 1492 | ['MS03-046', ALERT.MSF], 1493 | ['MS03-026', ALERT.MSF], 1494 | ['MS03-026', ALERT.MSF], 1495 | ['MS03-022', ALERT.MSF], 1496 | ['MS03-020', ALERT.MSF], 1497 | ['MS03-007', ALERT.MSF], 1498 | ['MS02-065', ALERT.MSF], 1499 | ['MS02-063', ALERT.MSF], 1500 | ['MS02-056', ALERT.MSF], 1501 | ['MS02-039', ALERT.MSF], 1502 | ['MS02-018', ALERT.MSF], 1503 | ['MS01-033', ALERT.MSF], 1504 | ['MS01-026', ALERT.MSF], 1505 | ['MS01-023', ALERT.MSF], 1506 | ['MS00-094', ALERT.MSF] 1507 | ] 1508 | 1509 | # return the count of exploits 1510 | if msid == 0: return len(exploits) 1511 | 1512 | for exploit in exploits: 1513 | if msid == exploit[0]: 1514 | # need 3 values to unpack, in case there are resources 1515 | if len(exploit) == 2: 1516 | exploit.append(None) 1517 | return exploit 1518 | 1519 | # otherwise there are 3 values 1520 | return exploit 1521 | 1522 | return [False,False,False] 1523 | 1524 | # the update function 1525 | def update(): 1526 | 1527 | # compute the filenames to be used 1528 | filenames = '%s-mssb' % datetime.datetime.now().strftime('%Y-%m-%d') 1529 | xlsFile = '%s.%s' % (filenames, 'xls') 1530 | csvFile = '%s.%s' % (filenames, 'csv') 1531 | 1532 | # url request opener with user-agent 1533 | opener = urllib2.build_opener() 1534 | opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36')] 1535 | 1536 | # grab the new data from ms and scrape the site 1537 | #try: 1538 | # response = opener.open(MSSB_URL) 1539 | #except urllib2.URLError, e: 1540 | # ALERT("error getting url %s" % MSSB_URL, ALERT.BAD) 1541 | # exit(1) 1542 | # 1543 | #ALERT("successfully requested base url") 1544 | 1545 | # 2016-02-10, ms changed link to http://download.microsoft.com/download/6/7/3/673E4349-1CA5-40B9-8879-095C72D5B49D/BulletinSearch.xlsx 1546 | # 1547 | # now parse the data, ensure we have an mssb link 1548 | # BulletinSearch_20131111_151603.xlsx (recommended) 1549 | #html = response.read() 1550 | #m = re.findall('url=(.*BulletinSearch.*.xls[x]*)', html) 1551 | # m = re.findall('href="(.*BulletinSearch.*.xlsx)"', html) # old bulletin request url, 20140502 1552 | 1553 | # ensure we get the bulletin search 1554 | #if m and m[0]: 1555 | bulletinUrl = BULLETIN_URL 1556 | # ALERT("scraped ms download url") 1557 | # if the file was xlsx, add an x to the extension 1558 | # if "xlsx" in bulletinUrl: xlsFile += "x" 1559 | #else: 1560 | # ALERT("error finding the ms download url from previous response", ALERT.BAD) 1561 | # exit(1) 1562 | 1563 | # now download the mssb file, with a random sleep 1564 | try: 1565 | #sleep(randint(1,3)) 1566 | response = opener.open(bulletinUrl) 1567 | except urllib2.URLError, e: 1568 | ALERT("error getting ms sb url %s" % bulletinUrl, ALERT.BAD) 1569 | exit(1) 1570 | 1571 | bulletinData = response.read() 1572 | 1573 | ALERT("writing to file %s" % xlsFile, ALERT.GOOD) 1574 | f = open(xlsFile, 'wb') 1575 | f.write(bulletinData) 1576 | f.close 1577 | 1578 | # modified ALERT class for exploit and metasploit level logging 1579 | class ALERT(object): 1580 | 1581 | def __init__(self, message, level=0, ansi=True): 1582 | 1583 | # default to ansi alerting, if it's detected as windows platform then disable 1584 | if platform.system() is "Windows": ansi = False 1585 | 1586 | good = '[+]' 1587 | bad = '[-]' 1588 | normal = '[*]' 1589 | 1590 | msf = '[M]' 1591 | exploit = '[E]' 1592 | 1593 | if ansi == True: 1594 | if level == ALERT.GOOD: print("%s%s%s" % ('\033[1;32m',good,"\033[0;0m")), 1595 | elif level == ALERT.BAD: print("%s%s%s" % ('\033[1;31m',bad,"\033[0;0m")), 1596 | elif level == ALERT.MSF: print("%s%s%s" % ('\033[1;32m',msf,"\033[0;0m")), 1597 | elif level == ALERT.EXP: print("%s%s%s" % ('\033[1;32m',exploit,"\033[0;0m")), 1598 | else: print("%s%s%s" % ('\033[1;34m',normal,"\033[0;0m")), 1599 | 1600 | else: 1601 | if level == ALERT.GOOD: print('%s' % good), 1602 | elif level == ALERT.BAD: print('%s' % bad), 1603 | elif level == ALERT.MSF: print('%s' % msf), 1604 | elif level == ALERT.EXP: print('%s' % exploit), 1605 | else: print('%s' % normal), 1606 | 1607 | print message 1608 | 1609 | @staticmethod 1610 | @property 1611 | def BAD(self): return -1 1612 | 1613 | @staticmethod 1614 | @property 1615 | def NORMAL(self): return 0 1616 | 1617 | @staticmethod 1618 | @property 1619 | def GOOD(self): return 1 1620 | 1621 | @staticmethod 1622 | @property 1623 | def MSF(self): return 2 1624 | 1625 | @staticmethod 1626 | @property 1627 | def EXP(self): return 3 1628 | 1629 | # this helper function will merge a list of lists into one sorted set 1630 | def merge_list(li): 1631 | s = [] 1632 | if li: 1633 | for l in li: 1634 | if isinstance(l, list): s = s + l 1635 | else: s.append(l) 1636 | return s 1637 | 1638 | if __name__ == '__main__': 1639 | main() 1640 | 1641 | --------------------------------------------------------------------------------