├── LICENSE ├── README.md ├── example.png ├── http-vulners-paths.txt ├── http-vulners-regex.json ├── http-vulners-regex.nse ├── paths_regex_example.png ├── simple_regex_example.png ├── vulners.nse ├── vulners_enterprise.nse └── vulners_enterprise_output.png /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nmap_vulners 2 | 3 | [![Current Release](https://img.shields.io/github/release/vulnersCom/nmap-vulners.svg "Current Release")](https://github.com/vulnersCom/nmap-vulners/releases/latest) 4 | [![Downloads](https://img.shields.io/github/downloads/vulnersCom/nmap-vulners/total.svg "Downloads")](https://github.com/vulnersCom/nmap-vulners/releases) [![PayPal](https://img.shields.io/badge/donate-PayPal-green.svg)](https://paypal.me/videns) 5 | 6 | ## Description 7 | 8 | NSE script uses info about known services to provide data on vulnerabilities. Note that it is already included into the standard nmap NSE library. 9 | 10 | ![Result example](example.png) 11 | 12 | ## Dependencies: 13 | nmap libraries: 14 | http 15 | json 16 | string 17 | http-vulners-regex 18 | 19 | Keep in mind that the script depends on having information about software versions, so it only works with -sV flag. 20 | 21 | **NB:** Now it can actually be run without -sV flag if http-vulners-regex script is run as well. 22 | 23 | ## Installation 24 | locate where your nmap scripts are located on your system 25 | for *nix system it might be ~/.nmap/scripts/ or $NMAPDIR 26 | for Mac it might be /usr/local/Cellar/nmap//share/nmap/scripts/ 27 | for Windows it might be C:\Program Files (x86)\Nmap\scripts 28 | copy the provided script (vulners.nse) into that directory 29 | run *nmap --script-updatedb* to update the nmap script DB 30 | 31 | ## Usage 32 | Use it as straightforward as you can: 33 | nmap -sV --script vulners [--script-args mincvss=] 34 | 35 | It is KISS after all. 36 | 37 | # http-vulners-regex 38 | 39 | ## Description 40 | 41 | NSE script scans HTTP responses and identifies CPEs for the mentioned software. It can therefore boost the efficiency of the main vulners script. 42 | 43 | ![Result example](simple_regex_example.png) 44 | Or with the paths: 45 | ![Result example](paths_regex_example.png) 46 | 47 | ## Dependencies 48 | nmap libraries: 49 | http 50 | json 51 | string 52 | stdnse 53 | shortport 54 | table 55 | 56 | ## Installation 57 | locate where nmap is located on your system 58 | for *nix system it might be ~/.nmap/ or $NMAPDIR 59 | for Mac it might be /usr/local/Cellar/nmap//share/nmap/ 60 | for Windows it might be C:\Program Files (x86)\Nmap\ 61 | copy the provided script (http-vulners-regex.nse) into /scripts/ 62 | copy the provided json with the regexes to /nselib/data/ 63 | copy the provided txt file with the default paths to /nselib/data/ 64 | note that you can specify your own file via command line 65 | run *nmap --script-updatedb* to update the nmap script DB 66 | 67 | ## Usage 68 | As a usual NSE script: 69 | nmap --script http-vulners-regex.nse [--script-args paths={"/"}] 70 | 71 | 72 | # vulners_enterprise 73 | 74 | ## Description 75 | This is basically the good old faithfull nmap-vulners from above with an important exception: it requires an API_KEY to work. 76 | 77 | Moreover it specifically uses CVSS v3 score rather than v2 in its output. 78 | 79 | You can either specify it on the CLI using the 'api_key' script argument, set it into an envirotnment variable VULNERS_API_KEY, or store it in a file readable by the user running nmap. In this case you must specify the absolute path to the file using the 'api_key_file' script argument. 80 | 81 | ![Result example](vulners_enterprise_output.png) 82 | 83 | ## Usage 84 | As a usual NSE script: 85 | nmap -sV --script vulners_enterprise [--script-args mincvss=,api_key=,api_key_file=,api_host=http://my_host.com] 86 | 87 | ### NSE Arguments 88 | 89 | **vulners_enterprise.mincvss** Limit CVEs shown to those with this CVSS score or greater. 90 | 91 | **vulners_enterprise.api_key** API token to be used in the requests 92 | 93 | **vulners_enterprise.api_key_file** Absolute path to the file with a single line containing the API token 94 | 95 | **vulners_enterprise.api_host** URL to vulners API without the leading slash. Defaults to https://vulners.com 96 | 97 | -------------------------------------------------------------------------------- /example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vulnersCom/nmap-vulners/b913758f029b570e67c6def343b838dda1c9e7e4/example.png -------------------------------------------------------------------------------- /http-vulners-paths.txt: -------------------------------------------------------------------------------- 1 | default.asp 2 | /default.asp 3 | /default.aspx 4 | /default.cfm 5 | /default.cgi 6 | /default.html 7 | /default.jhtml 8 | /default.jsa 9 | /default.jsp 10 | /default.php 11 | /default.pl 12 | /default.shtml 13 | /home.asp 14 | /home.aspx 15 | /home.cfm 16 | /home.cgi 17 | /home.html 18 | /home.jhtml 19 | /home.jsa 20 | /home.jsp 21 | /home.php 22 | /home.pl 23 | /home.shtml 24 | /index.asp 25 | /index.aspx 26 | /index.cfm 27 | /index.cgi 28 | /index.html 29 | /index.jhtml 30 | /index.jsa 31 | /index.jsp 32 | /index.php 33 | /index.pl 34 | /index.shtml 35 | /menu.asp 36 | /menu.aspx 37 | /menu.cfm 38 | /menu.cgi 39 | /menu.html 40 | /menu.jhtml 41 | /menu.jsa 42 | /menu.jsp 43 | /menu.php 44 | /menu.pl 45 | /menu.shtml 46 | /main.asp 47 | /main.aspx 48 | /main.cfm 49 | /main.cgi 50 | /main.html 51 | /main.jhtml 52 | /main.jsa 53 | /main.jsp 54 | /main.php 55 | /main.pl 56 | /main.shtml 57 | /start.asp 58 | /start.aspx 59 | /start.cfm 60 | /start.cgi 61 | /start.html 62 | /start.jhtml 63 | /start.jsa 64 | /start.jsp 65 | /start.php 66 | /start.pl 67 | /start.shtml 68 | /localstart.asp 69 | /localstart.aspx 70 | /localstart.cfm 71 | /localstart.cgi 72 | /localstart.html 73 | /localstart.jhtml 74 | /localstart.jsa 75 | /localstart.jsp 76 | /localstart.php 77 | /localstart.pl 78 | /localstart.shtml 79 | /inicio.asp 80 | /inicio.aspx 81 | /inicio.cfm 82 | /inicio.cgi 83 | /inicio.html 84 | /inicio.jhtml 85 | /inicio.jsa 86 | /inicio.jsp 87 | /inicio.php 88 | /inicio.pl 89 | /inicio.shtml 90 | /indice.asp 91 | /indice.aspx 92 | /indice.cfm 93 | /indice.cgi 94 | /indice.html 95 | /indice.jhtml 96 | /indice.jsa 97 | /indice.jsp 98 | /indice.php 99 | /indice.pl 100 | /indice.shtml 101 | /base.asp 102 | /base.aspx 103 | /base.cfm 104 | /base.cgi 105 | /base.html 106 | /base.inc 107 | /base.jhtml 108 | /base.jsa 109 | /base.jsp 110 | /base.php 111 | /base.pl 112 | /base.shtml 113 | /admin.asp 114 | /admin.aspx 115 | /admin.cfm 116 | /admin.cgi 117 | /admin.html 118 | /admin.jhtml 119 | /admin.jsa 120 | /admin.jsp 121 | /admin.php 122 | /admin.pl 123 | /admin.shtml 124 | /readme.txt 125 | /robots.txt 126 | -------------------------------------------------------------------------------- /http-vulners-regex.json: -------------------------------------------------------------------------------- 1 | { 2 | "AOLserver, headers": { 3 | "alias": "cpe:/a:aol:aolserver", 4 | "regex": "Server:%s*AOLserver/?([%d.]+)" 5 | }, 6 | "All in One SEO Pack, html": { 7 | "alias": "cpe:/a:semperfiwebdesign:all_in_one_seo_pack", 8 | "regex": "Atlassian Bitbucket v([%d.]+)<" 17 | }, 18 | "Bugzilla, html": { 19 | "alias": "cpe:/a:mozilla:bugzilla", 20 | "regex": "version ([%d.]+)<" 21 | }, 22 | "Chamilo, headers": { 23 | "alias": "cpe:/a:chamilo:chamilo_lms", 24 | "regex": "X%-Powered%-By:%s*Chamilo ([%d.]+)" 25 | }, 26 | "Chamilo, html": { 27 | "alias": "cpe:/a:chamilo:chamilo_lms", 28 | "regex": "\">Chamilo ([%d.]+)" 29 | }, 30 | "Cherokee, headers": { 31 | "alias": "cpe:/a:cherokee-project:cherokee", 32 | "regex": "Server:%s*Cherokee/([%d.]+)" 33 | }, 34 | "CherryPy, headers": { 35 | "alias": "cpe:/a:cherrypy:cherrypy", 36 | "regex": "Server:%s*CherryPy/?([%d%.]+)" 37 | }, 38 | "CompaqHTTPServer, headers": { 39 | "alias": "cpe:/a:compaq:compaqhttpserver", 40 | "regex": "Server:%s*CompaqHTTPServer/?([%d%.]+)" 41 | }, 42 | "Coppermine, html": { 43 | "alias": "cpe:/a:coppermine-gallery:coppermine_photo_gallery", 44 | "regex": "Jenkins ver%. ([%d.]+)" 73 | }, 74 | "Kibana, headers": { 75 | "alias": "cpe:/a:elasticsearch:kibana", 76 | "regex": "kbn%-version:%s*^([%d.]+)$" 77 | }, 78 | "Liferay, headers": { 79 | "alias": "cpe:/a:liferay:liferay_portal", 80 | "regex": "Liferay%-Portal:%s*[a-zA-Z%s]+([%d.]+)" 81 | }, 82 | "Monkey HTTP Server, headers": { 83 | "alias": "cpe:/a:monkey-project:monkey_http_daemon", 84 | "regex": "Server:%s*Monkey/?([%d.]+)" 85 | }, 86 | "NextGEN Gallery, html": { 87 | "alias": "cpe:/a:imagely:nextgen_gallery", 88 | "regex": " %-%->" 89 | }, 90 | "SPIP, headers": { 91 | "alias": "cpe:/a:spip:spip", 92 | "regex": "Composed%-By:%s*SPIP ([%d.]+) @" 93 | }, 94 | "TeamCity, html": { 95 | "alias": "cpe:/a:jetbrains:teamcity", 96 | "regex": "Version ([%d%.]+)" 97 | }, 98 | "cPanel, headers": { 99 | "alias": "cpe:/a:cpanel:cpanel", 100 | "regex": "Server:%s*cpsrvd/([%d.]+)" 101 | }, 102 | "Google Web Toolkit (GWT), headers": { 103 | "regex": "%.gwt_version%s?=%s?\"([%d.]+)\"", 104 | "alias": "cpe:/a:google:web_toolkit" 105 | }, 106 | "Apache Coyote (Tomcat), headers": { 107 | "regex": "Apache%-Coyote/([%d.]+)", 108 | "alias": "cpe:/a:apache:tomcat" 109 | }, 110 | "ASP.Net, headers": { 111 | "regex": "X%-AspNet%-Version: ([%d.]+)", 112 | "alias": "cpe:/a:microsoft:asp.net" 113 | }, 114 | "BOA Web Server, headers": { 115 | "regex": "BOA/([%d.]+)", 116 | "alias": "cpe:/a:boa:boa" 117 | }, 118 | "CKEditor, headers": { 119 | "regex": "CKEDITOR.*version:\"([%d.]+)\"", 120 | "alias": "cpe:/a:ckeditor:ckeditor" 121 | }, 122 | "Ember, headers": { 123 | "regex": "Ember%.VERSION%s*=%s*[\"']([%..]+)[\"']", 124 | "alias": "cpe:/a:emberjs:ember.js" 125 | }, 126 | "H2O, headers": { 127 | "regex": "h2o/([%d.]+%-DEV)", 128 | "alias": "cpe:/a:h2o_project:h2o" 129 | }, 130 | "H2O, headers_1": { 131 | "regex": "h2o/([%d.]+)", 132 | "alias": "cpe:/a:h2o_project:h2o" 133 | }, 134 | "Jetty, headers": { 135 | "regex": "Jetty%s?%.?([a-z%d.]+)%.?", 136 | "alias": "cpe:/a:mortbay:jetty" 137 | }, 138 | "JBoss Enterprise Application Platform, headers": { 139 | "regex": "JBoss%-EAP/([%d.]+)", 140 | "alias": "cpe:/a:redhat:jboss_enterprise_application_platform" 141 | }, 142 | "Java JDK, headers": { 143 | "regex": "%.jdk(%d[x%d._]+)", 144 | "alias": "cpe:/a:oracle:jdk" 145 | }, 146 | "Java Server Faces, headers": { 147 | "regex": "%.JSF/([%d.]+)", 148 | "alias": "cpe:/a:oracle:mojarra" 149 | }, 150 | "jQuery UI Touch Punch, headers": { 151 | "regex": "jQuery UI Touch Punch ([%d.]+)", 152 | "alias": "cpe:/a:jquery:jquery_ui" 153 | }, 154 | "Liferay Portal, headers": { 155 | "regex": "Liferay Portal Enterprise Edition ([%d.]+)", 156 | "alias": "cpe:/a:liferay:liferay_portal" 157 | }, 158 | "Linux, headers": { 159 | "regex": "Linux ([a-z0-9%.%._]+)", 160 | "alias": "cpe:/o:linux:linux_kernel" 161 | }, 162 | "OpenCms, headers": { 163 | "regex": "OpenCms/([%d.]+)", 164 | "alias": "cpe:/a:alkacon:opencms" 165 | }, 166 | "Microsoft IIS, headers": { 167 | "regex": "Microsoft%-IIS/([%d.]+)", 168 | "alias": "cpe:/a:microsoft:iis" 169 | }, 170 | "Microsoft .Net Framework, headers": { 171 | "regex": "Microsoft %.NET Framework ([%d.]+)", 172 | "alias": "cpe:/a:microsoft:.net_framework" 173 | }, 174 | "Microsoft SharePoint, headers": { 175 | "regex": "MicrosoftSharePointTeamServices: ([%d.]+)", 176 | "alias": "cpe:/a:microsoft:sharepoint" 177 | }, 178 | "Oracle iPlanet, headers": { 179 | "regex": "Sun%-Java%-System%-Web%-Server/([%d.]+.*)", 180 | "alias": "cpe:/a:oracle:iplanet_web_server" 181 | }, 182 | "Oracle-Application-Server, headers": { 183 | "regex": "Oracle%-Application%-Server%-([%d.]+.*)", 184 | "alias": "cpe:/a:oracle:application_server" 185 | }, 186 | "Oracle OpenSSO, headers": { 187 | "regex": "Oracle OpenSSO ([%d.]+.*)", 188 | "alias": "cpe:/a:oracle:opensso" 189 | }, 190 | "Orion, headers": { 191 | "regex": "Orion/([%d.]+)", 192 | "alias": "cpe:/a:solarwinds:orion_core_services" 193 | }, 194 | "Nexpose, headers": { 195 | "regex": "NSC/([%d.]+) %.JVM%.", 196 | "alias": "cpe:/a:rapid7:nexpose" 197 | }, 198 | "Squid Cache, headers": { 199 | "regex": "squid/([%d.]+)", 200 | "alias": "cpe:/a:squid-cache:squid" 201 | }, 202 | "Telerik": { 203 | "regex": "", 204 | "alias": "cpe:/a:telerik:analytics_monitor_library" 205 | }, 206 | "Tornado Server, headers": { 207 | "regex": "TornadoServer/([%d.]+)", 208 | "alias": "cpe:/a:tornadoweb:tornado" 209 | }, 210 | "Undertow, headers": { 211 | "regex": "X%-Powered%-By: Undertow/([%d.]+)", 212 | "alias": "cpe:/a:redhat:undertow" 213 | }, 214 | "Microsoft CRM, headers": { 215 | "regex": "var APPLICATION_FULL_VERSION = '([%d.]+)';", 216 | "alias": "cpe:/a:microsoft:business_solutions_crm" 217 | }, 218 | "Varnish Cache, headers": { 219 | "regex": "Varnish/([%d.]+)", 220 | "alias": "cpe:/a:varnish-cache:varnish" 221 | }, 222 | "WildFly, headers": { 223 | "regex": "Server: WildFly/([%d.]+)", 224 | "alias": "cpe:/a:redhat:jboss_wildfly_application_server" 225 | }, 226 | "ASP.Net MVC Framework, headers": { 227 | "regex": "X%-AspNetMvc%-Version: ([%d.]+)", 228 | "alias": "cpe:/a:microsoft:asp.net" 229 | }, 230 | "Apache Cocoon, headers": { 231 | "regex": "X%-Cocoon%-Version: ([%d.]+)", 232 | "alias": "cpe:/a:apache:cocoon" 233 | }, 234 | "Outlook Web Access, headers": { 235 | "regex": "X%-OWA%-Version: ([%d.]+)", 236 | "alias": "cpe:/a:microsoft:outlook_web_access" 237 | }, 238 | "IBM TeaLeaf, headers": { 239 | "regex": "X%-TeaLeaf%-UIEventCapture%-Version: ([%d.]+)", 240 | "alias": "cpe:/a:ibm:tealeaf_consumer_experience" 241 | }, 242 | "FlashCom, headers": { 243 | "alias": "cpe:/a:macromedia:flash_communication_server", 244 | "regex": "Server:%s*FlashCom/?([%d%.]+)" 245 | }, 246 | "Grandstream, headers": { 247 | "alias": "cpe:/o:grandstream:gxv_device_firmware", 248 | "regex": "Server:%s*Grandstream/?([%d%.]+)" 249 | }, 250 | "Igor Sysoev nginx": { 251 | "regex": "nginx/([%d.]+)", 252 | "alias": "cpe:/a:igor_sysoev:nginx" 253 | }, 254 | "Java Server Faces": { 255 | "regex": "JSF/([%d.]+)", 256 | "alias": "cpe:/a:oracle:mojarra" 257 | }, 258 | "Jetty": { 259 | "regex": "Jetty%.[v%d.]+%.", 260 | "alias": "cpe:/a:mortbay:jetty" 261 | }, 262 | "Java": { 263 | "regex": "java/([%d%.%.]+)", 264 | "alias": "cpe:/a:oracle:jre" 265 | }, 266 | "GlassFish Server": { 267 | "regex": "GlassFish Server Open Source Edition ([%d%.]+)", 268 | "alias": "cpe:/a:oracle:glassfish_server" 269 | }, 270 | "Oracle Weblogic": { 271 | "regex": "WebLogic Server ?([%d%.]+)", 272 | "alias": "cpe:/a:oracle:weblogic_server" 273 | }, 274 | "Oracle Weblogic_1": { 275 | "regex": "WebLogic ([%d%.]+)", 276 | "alias": "cpe:/a:oracle:weblogic_server" 277 | }, 278 | "Oracle Application Server Containers for J2EE 10g": { 279 | "regex": "Oracle Application Server Containers for J2EE 10g %.([%d%.]+)%.", 280 | "alias": "cpe:/a:oracle:application_server" 281 | }, 282 | "Oracle Application Server 10g": { 283 | "regex": "Oracle.Application.Server.10g/([%d%.]+)", 284 | "alias": "cpe:/a:oracle:application_server" 285 | }, 286 | "Oracle Application Server": { 287 | "regex": "Oracle Application Server/([%d%.]+)", 288 | "alias": "cpe:/a:oracle:application_server" 289 | }, 290 | "Oracle9iA": { 291 | "regex": "Oracle9iAS/([%d%.]+)", 292 | "alias": "cpe:/a:oracle:application_server" 293 | }, 294 | "Artifactory, headers": { 295 | "regex": "Artifactory/([%d.]+)", 296 | "alias": "cpe:/a:jfrog:artifactory" 297 | }, 298 | "jQuery UI, headers": { 299 | "regex": "jQuery UI ([%d.]+)", 300 | "alias": "cpe:/a:jqueryui:jquery_ui" 301 | }, 302 | "Allegro RomPager, headers_0_0": { 303 | "alias": "cpe:/a:allegrosoft:rompager", 304 | "regex": "Server:%s*Allegro%-Software%-RomPager/([%d.]+)" 305 | }, 306 | "Apache Tomcat, headers_0_0": { 307 | "alias": "cpe:/a:apache:tomcat", 308 | "regex": "Server:%s*^Apache%-Coyote/([%d.]+)" 309 | }, 310 | "Apache Tomcat, headers_1_0": { 311 | "alias": "cpe:/a:apache:tomcat", 312 | "regex": "X%-Powered%-By:%s* ?Tomcat ?%-([%d.]+)" 313 | }, 314 | "Apache Tomcat, headers_2": { 315 | "alias": "cpe:/a:apache:tomcat", 316 | "regex": "Apache Tomcat/([%d.]+)" 317 | }, 318 | "Artifactory, html_0_0": { 319 | "alias": "cpe:/a:jfrog:artifactory", 320 | "regex": "Artifactory Pro Power Pack ([%d.]+)" 321 | }, 322 | "Artifactory, html_0_1": { 323 | "alias": "cpe:/a:jfrog:artifactory", 324 | "regex": "Artifactory Pro ([%d.]+)" 325 | }, 326 | "Artifactory, html_0_2": { 327 | "alias": "cpe:/a:jfrog:artifactory", 328 | "regex": "Artifactory Power Pack ([%d.]+)" 329 | }, 330 | "Artifactory, html_0_3": { 331 | "alias": "cpe:/a:jfrog:artifactory", 332 | "regex": "Artifactory ([%d.]+)" 333 | }, 334 | "Artifactory Web Server, headers_0_0": { 335 | "alias": "cpe:/a:jfrog:artifactory", 336 | "regex": "Server:%s*Artifactory/([%d.]+)" 337 | }, 338 | "Atlassian Confluence, html_0_0": { 339 | "alias": "cpe:/a:atlassian:confluence", 340 | "regex": "Powered by ]+atlassian%.com/software/confluence[^>]+>Atlassian Confluence ([%d.]+)" 341 | }, 342 | "Atlassian FishEye, html_0_0": { 343 | "alias": "cpe:/a:atlassian:fisheye", 344 | "regex": "Log in to FishEye and Crucible ([%d.]+)" 345 | }, 346 | "Atlassian FishEye, html_0_1": { 347 | "alias": "cpe:/a:atlassian:fisheye", 348 | "regex": "Log in to FishEye ([%d.]+)" 349 | }, 350 | "Atlassian FishEye, html_0_2": { 351 | "alias": "cpe:/a:atlassian:fisheye", 352 | "regex": "FishEye and Crucible ([%d.]+)" 353 | }, 354 | "Atlassian FishEye, html_0_3": { 355 | "alias": "cpe:/a:atlassian:fisheye", 356 | "regex": "FishEye ([%d.]+)" 357 | }, 358 | "Banshee, html_0_0": { 359 | "alias": "cpe:/a:banshee-project:banshee", 360 | "regex": "Built upon the ]+banshee%-php%.org/\">[a-z]+v([%d.]+)" 361 | }, 362 | "Dancer, headers_0": { 363 | "alias": "cpe:/a:dancer:dancer", 364 | "regex": "Server:%s*Perl Dancer ([%d.]+)" 365 | }, 366 | "Dancer, headers_1": { 367 | "alias": "cpe:/a:dancer:dancer", 368 | "regex": "X%-Powered%-By:%s*Perl Dancer ([%d.]+)" 369 | }, 370 | "Django, html_0": { 371 | "alias": "cpe:/a:djangoproject:django", 372 | "regex": "powered by ]+>Django ?([%d.]+)" 373 | }, 374 | "Dojo, script_0_0": { 375 | "alias": "cpe:/a:dojotoolkit:dojo", 376 | "regex": "([%d.]+)/dojo/dojo%.xd%.js" 377 | }, 378 | "Dojo, script_0_1": { 379 | "alias": "cpe:/a:dojotoolkit:dojo", 380 | "regex": "([%d.]+)/dojo/dojo%.js" 381 | }, 382 | "EmbedThis Appweb, headers_0_0": { 383 | "alias": "cpe:/a:embedthis:appweb", 384 | "regex": "Server:%s*Mbedthis%-Appweb/([%d.]+)" 385 | }, 386 | "FreeBSD, headers_0_0": { 387 | "alias": "cpe:/o:freebsd:freebsd", 388 | "regex": "Server:%s*FreeBSD ([%d.]+)" 389 | }, 390 | "GlassFish, headers_0_0": { 391 | "alias": "cpe:/a:oracle:glassfish_server", 392 | "regex": "Server:%s*GlassFish Server Open Source Edition ?/?([%d.]+)" 393 | }, 394 | "GlassFish, headers_0_1": { 395 | "alias": "cpe:/a:oracle:glassfish_server", 396 | "regex": "Server:%s*GlassFish Server ?/?([%d.]+)" 397 | }, 398 | "GlassFish, headers_0_2": { 399 | "alias": "cpe:/a:oracle:glassfish_server", 400 | "regex": "Server:%s*GlassFish Open Source Edition ?/?([%d.]+)" 401 | }, 402 | "GlassFish, headers_0_3": { 403 | "alias": "cpe:/a:oracle:glassfish_server", 404 | "regex": "Server:%s*GlassFish ?/?([%d.]+)" 405 | }, 406 | "HP iLO, headers_0_0": { 407 | "alias": "cpe:/o:hp:integrated_lights-out", 408 | "regex": "Server:%s*HP%-iLO%-Server/([%d.]+)" 409 | }, 410 | "IBM Tivoli Storage Manager, headers_0_0": { 411 | "alias": "cpe:/a:ibm:tivoli_storage_manager", 412 | "regex": "Server:%s*TSM_HTTP/([%d.]+)" 413 | }, 414 | "IIS, headers_0_0": { 415 | "alias": "cpe:/a:microsoft:iis", 416 | "regex": "Server:%s*Microsoft%-IIS/([%d.]+)" 417 | }, 418 | "IIS, headers_0_1": { 419 | "alias": "cpe:/a:microsoft:iis", 420 | "regex": "Server:%s*IIS/([%d.]+)" 421 | }, 422 | "Intel Active Management Technology, headers_0_0": { 423 | "alias": "cpe:/o:intel:active_management_technology_firmware", 424 | "regex": "Server:%s*Intel%(R%) Active Management Technology ([%d.]+)" 425 | }, 426 | "JBoss Application Server, headers_0_0": { 427 | "alias": "cpe:/a:redhat:jboss_community_application_server", 428 | "regex": "X%-Powered%-By:%s*JBoss%-([%d.]+)" 429 | }, 430 | "JBoss Web, headers_0_0": { 431 | "alias": "cpe:/a:redhat:jboss_enterprise_web_server", 432 | "regex": "X%-Powered%-By:%s*JBossWeb%-([%d.]+)" 433 | }, 434 | "JavaServer Faces, headers_0_0": { 435 | "alias": "cpe:/a:oracle:mojarra", 436 | "regex": "X%-Powered%-By:%s*JSF/([%d.]+)" 437 | }, 438 | "LabVIEW, headers_0_0": { 439 | "alias": "cpe:/a:ni:labview", 440 | "regex": "Server:%s*LabVIEW/([%d%.]+)" 441 | }, 442 | "Lua, headers_0_0": { 443 | "alias": "cpe:/a:lua:lua", 444 | "regex": "X%-Powered%-By:%s* ?Lua ([%d.]+)" 445 | }, 446 | "Microsoft PowerPoint, html_0_0": { 447 | "alias": "cpe:/a:microsoft:powerpoint", 448 | "regex": "[^<]+[^!]+%d+[^!]+([%d.]+)" 449 | }, 450 | "MochiWeb, headers_0_0": { 451 | "alias": "cpe:/a:mochiweb_project:mochiweb", 452 | "regex": "Server:%s*MochiWeb/([%d.]+)" 453 | }, 454 | "Nginx, headers_0_0": { 455 | "alias": "cpe:/a:nginx:nginx", 456 | "regex": "Server:%s*nginx/([%d.]+)" 457 | }, 458 | "Nginx, headers_0_1": { 459 | "alias": "cpe:/a:nginx:nginx", 460 | "regex": "Server:%s*nginx%-reuseport/([%d.]+)" 461 | }, 462 | "Oracle Commerce, headers_0_0": { 463 | "alias": "cpe:/a:oracle:commerce_platform", 464 | "regex": "X%-ATG%-Version:%s*ATGPlatform/([%d.]+)" 465 | }, 466 | "Oracle HTTP Server, headers_0_0": { 467 | "alias": "cpe:/a:oracle:http_server", 468 | "regex": "Server:%s*Oracle%-HTTP%-Server/([%d.]+)" 469 | }, 470 | "PHP, headers_0_0": { 471 | "alias": "cpe:/a:php:php", 472 | "regex": "PHP/([%d]+[%.]+[%-%w%d%.]*)" 473 | }, 474 | "PHP, headers_1": { 475 | "alias": "cpe:/a:php:php", 476 | "regex": "Server:%s*php/?([%d.]+)" 477 | }, 478 | "PHP, headers_2": { 479 | "alias": "cpe:/a:php:php", 480 | "regex": "X%-Powered%-By:%s*php/?([%d.]+)" 481 | }, 482 | "Phusion Passenger, headers_0": { 483 | "alias": "cpe:/a:phusion:passenger", 484 | "regex": "Server:%s*Phusion Passenger ([%d.]+)" 485 | }, 486 | "Phusion Passenger, headers_1": { 487 | "alias": "cpe:/a:phusion:passenger", 488 | "regex": "X%-Powered%-By:%s*Phusion Passenger ?([%d.]+)" 489 | }, 490 | "Phusion Passenger, headers_2_0": { 491 | "alias": "cpe:/a:phusion:passenger", 492 | "regex": "Phusion Passenger %([a-zA-Z_/]+%) ([%d.]+)" 493 | }, 494 | "SUSE, headers_0_0": { 495 | "alias": "cpe:/o:suse:linux_enterprise_server", 496 | "regex": "Server:%s*SUSE/?%s?%-?([%d.]+)" 497 | }, 498 | "SUSE, headers_1_0": { 499 | "alias": "cpe:/o:suse:linux_enterprise_server", 500 | "regex": "X%-Powered%-By:%s*SUSE/?%s?%-?([%d.]+)" 501 | }, 502 | "Splunk, html_0_0": { 503 | "alias": "cpe:/a:splunk:splunk", 504 | "regex": "

© [%-%d]+ Splunk Inc%. Splunk ([%d%.]+ build [%d%.]*%d)[^<]*

" 505 | }, 506 | "Splunk, html_0_1": { 507 | "alias": "cpe:/a:splunk:splunk", 508 | "regex": "

© [%-%d]+ Splunk Inc%. Splunk ([%d%.]+)[^<]*

" 509 | }, 510 | "SunOS, headers_0_0": { 511 | "alias": "cpe:/o:sun:sunos", 512 | "regex": "Server:%s*SunOS( [%d%.]+)?" 513 | }, 514 | "SunOS, headers_1_0": { 515 | "alias": "cpe:/o:sun:sunos", 516 | "regex": "Servlet%-engine:%s*SunOS( [%d%.]+)?" 517 | }, 518 | "TornadoServer, headers_0_0": { 519 | "alias": "cpe:/a:tornadoweb:tornado", 520 | "regex": "Server:%s*TornadoServer/([%d.]+)" 521 | }, 522 | "Trac, html_0_0": { 523 | "alias": "cpe:/a:edgewall_software:trac", 524 | "regex": "Powered by Trac[ /]([%d.]+)" 525 | }, 526 | "TwistedWeb, headers_0_0": { 527 | "alias": "cpe:/a:twistedmatrix:twistedweb", 528 | "regex": "Server:%s*TwistedWeb/([%d.]+)" 529 | }, 530 | "Varnish, headers_0_0": { 531 | "alias": "cpe:/a:varnish-cache:varnish", 532 | "regex": "Via:%s*varnish %(Varnish/([%d.]+)%)" 533 | }, 534 | "W3 Total Cache, headers_0_0": { 535 | "alias": "cpe:/a:w3edge:total_cache", 536 | "regex": "X%-Powered%-By:%s*W3 Total Cache/([%d.]+)" 537 | }, 538 | "Winstone Servlet Container, headers_0_0": { 539 | "alias": "cpe:/a:jenkins:jenkins", 540 | "regex": "Server:%s*Winstone Servlet Container v?([%d.]+)" 541 | }, 542 | "Winstone Servlet Container, headers_0_1": { 543 | "alias": "cpe:/a:jenkins:jenkins", 544 | "regex": "Server:%s*Winstone Servlet Engine v?([%d.]+)" 545 | }, 546 | "Winstone Servlet Container, headers_1_0": { 547 | "alias": "cpe:/a:jenkins:jenkins", 548 | "regex": "X%-Powered%-By:%s*Winstone.([%d.]+)" 549 | }, 550 | "WooCommerce, html_0_0_0": { 551 | "alias": "cpe:/a:woocommerce:woocommerce", 552 | "regex": "XAMPP Version ([%d%.]+)" 565 | }, 566 | "Xitami, headers_0_0": { 567 | "alias": "cpe:/a:imatix:xitami", 568 | "regex": "Server:%s*Xitami/([%d.]+)" 569 | }, 570 | "Yaws, headers_0_0": { 571 | "alias": "cpe:/a:yaws:yaws", 572 | "regex": "Server:%s*Yaws ([%d.]+)" 573 | }, 574 | "Yoast SEO, html_0_0": { 575 | "alias": "cpe:/a:yoast:wordpress_seo", 576 | "regex": "" 665 | }, 666 | "thttpd, headers_0_0": { 667 | "alias": "cpe:/a:acme_labs:thttpd", 668 | "regex": "Server:%s* ?thttpd/([%d.]+)" 669 | }, 670 | "Apache Subversion_0_0": { 671 | "regex": ">Apache Subversion%s+version%s+([%d.]+%s*%(r%d+%))", 672 | "alias": "cpe:/a:apache:subversion" 673 | }, 674 | "JBoss, headers_0_0": { 675 | "regex": "JBPAPP_([%d_]+GA)", 676 | "alias": "cpe:/a:redhat:jboss" 677 | }, 678 | "JBoss, headers_0_1": { 679 | "regex": "JBPAPP_([%d_]+)", 680 | "alias": "cpe:/a:redhat:jboss" 681 | }, 682 | "JBoss Webserver, headers_0_0": { 683 | "regex": "JBoss%s?Web[/%-]{1}([%d.]+GA)", 684 | "alias": "cpe:/a:redhat:jboss" 685 | }, 686 | "JBoss Webserver, headers_0_1": { 687 | "regex": "JBoss%s?Web/([%d.]+)", 688 | "alias": "cpe:/a:redhat:jboss" 689 | }, 690 | "JBoss Webserver, headers_0_2": { 691 | "regex": "JBoss%s?Web%-([%d.]+)", 692 | "alias": "cpe:/a:redhat:jboss" 693 | }, 694 | "Embedthis-http, headers_0_0": { 695 | "alias": "cpe:/a:embedthis:appweb", 696 | "regex": "Server:%s*Embedthis%-http/([%d.]+)" 697 | }, 698 | "Moxa, headers_0_0": { 699 | "alias": "cpe:/h:moxa", 700 | "regex": "Server:%s*MoxaHttp/([%d.]+)" 701 | }, 702 | "Ruby on Rails, headers_0_0_0": { 703 | "alias": "cpe:/a:rubyonrails:ruby_on_rails", 704 | "regex": "X%-Powered%-By:%s*mod_rails %(mod_rails/mod_rack%) ?/?([%d%.]+)" 705 | }, 706 | "Ruby on Rails, headers_0_0_1": { 707 | "alias": "cpe:/a:rubyonrails:ruby_on_rails", 708 | "regex": "X%-Powered%-By:%s*mod_rack %(mod_rails/mod_rack%) ?/?([%d%.]+)" 709 | }, 710 | "Ruby on Rails, headers_0_0_2": { 711 | "alias": "cpe:/a:rubyonrails:ruby_on_rails", 712 | "regex": "X%-Powered%-By:%s*Phusion[%._ ]Passenger %(mod_rails/mod_rack%) ?/?([%d%.]+)" 713 | }, 714 | "Ruby on Rails, headers_0_1_0": { 715 | "alias": "cpe:/a:rubyonrails:ruby_on_rails", 716 | "regex": "X%-Powered%-By:%s*mod_rails ?/?([%d%.]+)" 717 | }, 718 | "Ruby on Rails, headers_0_1_1": { 719 | "alias": "cpe:/a:rubyonrails:ruby_on_rails", 720 | "regex": "X%-Powered%-By:%s*mod_rack ?/?([%d%.]+)" 721 | }, 722 | "Ruby on Rails, headers_0_1_2": { 723 | "alias": "cpe:/a:rubyonrails:ruby_on_rails", 724 | "regex": "X%-Powered%-By:%s*Phusion[%._ ]Passenger ?/?([%d%.]+)" 725 | } 726 | } 727 | -------------------------------------------------------------------------------- /http-vulners-regex.nse: -------------------------------------------------------------------------------- 1 | description = [[ 2 | Identifies the used software for each found http port and builds CPEs for the identified versions. 3 | 4 | * Makes an HTTP GET request to the found open http port (with a default empty path of "/"). 5 | * Uses a local copy of Vulners regular expressions (defaults to http-vulners-regex.json) to identify software mentioned on the page of the HTTP service and forms CPEs for the found entries 6 | * Outputs all the found CPEs by page (so mind the duplicates) 7 | ]] 8 | 9 | --- 10 | -- @usage 11 | -- nmap -sV --script http-vulners-regex.nse [--script-args paths={"/"}] 12 | -- 13 | -- @args http-vulners-regex.paths Specify paths to make requests to. Should be a single string meaning filename to read or a list of strings. 14 | -- 15 | -- @output 16 | -- 17 | -- 80/tcp open http syn-ack Apache httpd 2.4.10 18 | -- | http-vulners-regex: 19 | -- | /: 20 | -- | cpe:/a:nginx:nginx:1.13.4 21 | -- |_ cpe:/a:php:php:5.6.38 22 | -- 23 | -- @xmloutput 24 | -- 25 | -- 26 | -- cpe:/a:nginx:nginx:1.13.4 27 | -- cpe:/a:php:php:5.6.38 28 | --
29 | 30 | author = 'gmedian AT vulners DOT com' 31 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 32 | categories = {"safe", "default"} 33 | 34 | 35 | local shortport = require "shortport" 36 | local http = require "http" 37 | local json = require "json" 38 | local string = require "string" 39 | local table = require "table" 40 | local nmap = require "nmap" 41 | local stdnse = require "stdnse" 42 | 43 | local patterns = {} 44 | local registry_tab = {} 45 | local tab = {} 46 | local paths = {} 47 | local default_paths = { 48 | "/", 49 | "/index.html", 50 | "/index.php", 51 | "/wp-admin/login.php", 52 | "/about.html", 53 | "/about.php", 54 | "/500.html", 55 | "/theonethatdoesnotexist" -- cause why not 56 | } 57 | 58 | portrule = shortport.http 59 | 60 | 61 | function get_cpes(field) 62 | local vers 63 | 64 | for name, pattern in pairs(patterns) do 65 | _, _, vers = field:find(pattern.regex) 66 | if vers ~= nil then 67 | cpe = pattern.alias .. ":" .. vers 68 | if not registry_tab[cpe] then 69 | table.insert(tab, cpe) 70 | registry_tab[cpe] = 1 71 | end 72 | end 73 | end 74 | end 75 | 76 | function get_paths_from_file(filename) 77 | local file, filename_full, status 78 | local paths = {} 79 | 80 | filename_full = nmap.fetchfile('nselib/data/' .. filename) 81 | if not(filename_full) then 82 | stdnse.debug1("No file found at nselib/data/%s, using local copy", filename) 83 | filename_full = filename 84 | end 85 | 86 | file = io.open(filename_full, "r") 87 | if file == nil then 88 | stdnse.debug1("Failed to open a file with paths") 89 | return {} 90 | end 91 | file:close() 92 | for line in io.lines(filename_full) do 93 | paths[#paths+1] = line 94 | end 95 | return paths 96 | end 97 | 98 | function get_paths(paths_arg) 99 | local default_paths_file = 'http-vulners-paths.txt' 100 | 101 | if type(paths_arg) == 'table' then 102 | -- Just do nothing whether it has entries or is an empty one 103 | do end 104 | elseif type(paths_arg) == 'string' then 105 | stdnse.debug1("Trying to read paths from a specified file " .. paths_arg) 106 | paths_arg = get_paths_from_file(paths_arg) 107 | else 108 | stdnse.debug1("Paths arguments should be a filename or a list of paths to use. Ignoring the argument") 109 | paths_arg = {} 110 | end 111 | 112 | -- If provided file could not be found, try the default one 113 | if #paths_arg == 0 then 114 | stdnse.debug1("Trying to read paths from a default file " .. default_paths_file) 115 | paths_arg = get_paths_from_file(default_paths_file) 116 | end 117 | 118 | -- Fall back to the hardcoded values when the default file could not be found as well 119 | if #paths_arg == 0 then 120 | stdnse.debug1("Using the default hardcoded paths.") 121 | paths_arg = default_paths 122 | end 123 | 124 | for _, path in ipairs(paths_arg) do 125 | paths[path] = 1 126 | end 127 | end 128 | 129 | action = function(host, port) 130 | local output = stdnse.output_table() 131 | local changed = false 132 | local paths_arg = stdnse.get_script_args(SCRIPT_NAME .. ".paths") or {} 133 | local regex_filename = 'http-vulners-regex.json' 134 | local regex_filename_full, file 135 | local cpe 136 | local response, status 137 | 138 | get_paths(paths_arg) 139 | 140 | regex_filename_full = nmap.fetchfile('nselib/data/' .. regex_filename) 141 | if not(regex_filename_full) then 142 | stdnse.debug1("No file found at nselib/data/%s, using local copy", regex_filename) 143 | regex_filename_full = regex_filename 144 | end 145 | 146 | file = io.open(regex_filename_full, "r") 147 | if file == nil then 148 | stdnse.debug1("Failed to open the json file") 149 | return 150 | end 151 | 152 | status, patterns = json.parse(file:read("*all")) 153 | if status == nil then 154 | stdnse.debug1("Unable to parse json from file read.") 155 | return 156 | end 157 | file:close() 158 | 159 | if port.version == nil or port.version.cpe == nil then 160 | stdnse.debug1("port.version (or .cpe) table is nil") 161 | return 162 | end 163 | 164 | 165 | for path, _ in pairs(paths) do 166 | if type(path) ~= 'string' then 167 | path = tostring(path) 168 | end 169 | stdnse.debug1("Analyze path " .. path) 170 | tab = {} 171 | response = http.get(host, port, path) 172 | if not response.status then 173 | stdnse.debug1("HTTP Error retrieving %s: %s", path, response["status-line"]) 174 | return 175 | end 176 | 177 | local body = response.rawbody or tostring(response.body) 178 | body = stdnse.string_or_blank(body, nil) 179 | if body ~= nil then 180 | get_cpes(body) 181 | end 182 | 183 | local rawheaders = response.rawheader 184 | if #rawheaders == 0 then 185 | stdnse.debug1("Rawheaders are empty...") 186 | else 187 | for i, header in ipairs(rawheaders) do 188 | stdnse.debug1("Analyzing:\t"..header) 189 | get_cpes(header) 190 | end 191 | end 192 | 193 | if #tab > 0 then 194 | output[path] = tab 195 | changed = true 196 | end 197 | end 198 | 199 | if (not changed) then 200 | return 201 | end 202 | 203 | -- NOTE[gmedian]: store the results in a somewhat persistent storage for other scripts to access 204 | -- It so happens that sometimes port.version.cpe does not contain the CPEs found by the predecessing script 205 | -- So have to additionally store the results separately 206 | host.registry.vulners_cpe = host.registry.vulners_cpe or {} 207 | for cpe, _ in pairs(registry_tab) do 208 | stdnse.debug1("Add CPE %s to host registry", cpe) 209 | table.insert(host.registry.vulners_cpe, cpe) 210 | table.insert(port.version.cpe, cpe) 211 | end 212 | 213 | nmap.set_port_version(host, port) 214 | 215 | return output 216 | end 217 | -------------------------------------------------------------------------------- /paths_regex_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vulnersCom/nmap-vulners/b913758f029b570e67c6def343b838dda1c9e7e4/paths_regex_example.png -------------------------------------------------------------------------------- /simple_regex_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vulnersCom/nmap-vulners/b913758f029b570e67c6def343b838dda1c9e7e4/simple_regex_example.png -------------------------------------------------------------------------------- /vulners.nse: -------------------------------------------------------------------------------- 1 | description = [[ 2 | For each available CPE the script prints out known vulns (links to the correspondent info) and correspondent CVSS scores. 3 | 4 | Its work is pretty simple: 5 | * work only when some software version is identified for an open port 6 | * take all the known CPEs for that software (from the standard nmap -sV output) 7 | * make a request to a remote server (vulners.com API) to learn whether any known vulns exist for that CPE 8 | * if no info is found this way, try to get it using the software name alone 9 | * print the obtained info out 10 | 11 | NB: 12 | Since the size of the DB with all the vulns is more than 250GB there is no way to use a local db. 13 | So we do make requests to a remote service. Still all the requests contain just two fields - the 14 | software name and its version (or CPE), so one can still have the desired privacy. 15 | ]] 16 | 17 | --- 18 | -- @usage 19 | -- nmap -sV --script vulners [--script-args mincvss=] 20 | -- 21 | -- @args vulners.mincvss Limit CVEs shown to those with this CVSS score or greater. 22 | -- 23 | -- @output 24 | -- 25 | -- 53/tcp open domain ISC BIND DNS 26 | -- | vulners: 27 | -- | ISC BIND DNS: 28 | -- | CVE-2012-1667 8.5 https://vulners.com/cve/CVE-2012-1667 29 | -- | CVE-2002-0651 7.5 https://vulners.com/cve/CVE-2002-0651 30 | -- | CVE-2002-0029 7.5 https://vulners.com/cve/CVE-2002-0029 31 | -- | CVE-2015-5986 7.1 https://vulners.com/cve/CVE-2015-5986 32 | -- | CVE-2010-3615 5.0 https://vulners.com/cve/CVE-2010-3615 33 | -- | CVE-2006-0987 5.0 https://vulners.com/cve/CVE-2006-0987 34 | -- |_ CVE-2014-3214 5.0 https://vulners.com/cve/CVE-2014-3214 35 | -- 36 | -- @xmloutput 37 | -- 38 | --
39 | -- false 40 | -- 8.5 41 | -- CVE-2012-1667 42 | -- cve 43 | --
44 | -- 45 | -- false 46 | -- 7.8 47 | -- CVE-2015-4620 48 | -- cve 49 | --
50 | -- 51 | 52 | dependencies = {"http-vulners-regex"} 53 | author = 'gmedian AT vulners DOT com' 54 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 55 | categories = {"vuln", "safe", "external", "default"} 56 | 57 | 58 | local http = require "http" 59 | local url = require "url" 60 | local json = require "json" 61 | local string = require "string" 62 | local table = require "table" 63 | local nmap = require "nmap" 64 | local stdnse = require "stdnse" 65 | 66 | local api_version="1.7" 67 | local mincvss=stdnse.get_script_args("vulners.mincvss") 68 | mincvss = tonumber(mincvss) or 0.0 69 | 70 | portrule = function(host, port) 71 | local vers=port.version 72 | return vers ~= nil and vers.version ~= nil or (host.registry.vulners_cpe ~= nil) 73 | end 74 | 75 | local cve_meta = { 76 | __tostring = function(me) 77 | return ("\t%s\t%s\thttps://vulners.com/%s/%s%s"):format(me.id, me.cvss or "", me.type, me.id, me.is_exploit and '\t*EXPLOIT*' or '') 78 | end, 79 | } 80 | 81 | --- 82 | -- Return a string with all the found cve's and correspondent links 83 | -- 84 | -- @param vulns a table with the parsed json response from the vulners server 85 | -- 86 | function make_links(vulns) 87 | local output = {} 88 | 89 | if not vulns or not vulns.data or not vulns.data.search then 90 | return 91 | end 92 | 93 | for _, vuln in ipairs(vulns.data.search) do 94 | local v = { 95 | id = vuln._source.id, 96 | type = vuln._source.type, 97 | -- Mark the exploits out 98 | is_exploit = vuln._source.bulletinFamily:lower() == "exploit", 99 | -- Sometimes it might happen, so check the score availability 100 | cvss = tonumber(vuln._source.cvss.score), 101 | } 102 | 103 | -- NOTE[gmedian]: exploits seem to have cvss == 0, so print them anyway 104 | if not v.cvss or (v.cvss == 0 and v.is_exploit) or mincvss <= v.cvss then 105 | setmetatable(v, cve_meta) 106 | output[#output+1] = v 107 | end 108 | end 109 | 110 | if #output > 0 then 111 | -- Sort the acquired vulns by the CVSS score 112 | table.sort(output, function(a, b) 113 | return a.cvss > b.cvss or (a.cvss == b.cvss and a.id > b.id) 114 | end) 115 | return output 116 | end 117 | end 118 | 119 | 120 | --- 121 | -- Issues the requests, receives json and parses it, calls make_links when successfull 122 | -- 123 | -- @param what string, future value for the software query argument 124 | -- @param vers string, the version query argument 125 | -- @param type string, the type query argument 126 | -- 127 | function get_results(what, vers, type) 128 | local api_endpoint = "https://vulners.com/api/v3/burp/software/" 129 | local vulns 130 | local response 131 | local status 132 | local attempt_n=0 133 | local query = { 134 | software= what, 135 | version= vers, 136 | type=type 137 | } 138 | local api_url = ('%s?%s'):format(api_endpoint, url.build_query(query)) 139 | local option={ 140 | header={ 141 | ['User-Agent'] = string.format('Vulners NMAP Plugin %s', api_version), 142 | ['Accept-Encoding'] = "gzip, deflate" 143 | }, 144 | any_af = true, 145 | } 146 | 147 | 148 | stdnse.debug1("Trying to get vulns of " .. what .. " for type " .. type) 149 | 150 | -- Sometimes we cannot contact vulners, so have to try several more times 151 | while attempt_n < 3 do 152 | stdnse.debug1("Attempt ".. attempt_n .. " to contact vulners.") 153 | response = http.get_url(api_url, option) 154 | status = response.status 155 | if status ~= nil then 156 | break 157 | end 158 | attempt_n = attempt_n + 1 159 | stdnse.sleep(1) 160 | end 161 | 162 | if status == nil then 163 | -- Something went really wrong out there 164 | -- According to the NSE way we will die silently rather than spam user with error messages 165 | stdnse.debug1("Failed to cantact vulners in several attempts.") 166 | return 167 | elseif status ~= 200 then 168 | -- Again just die silently 169 | stdnse.debug1("Response from vulners is not 200 but " .. status) 170 | return 171 | end 172 | 173 | status, vulns = json.parse(response.body) 174 | 175 | if status == true then 176 | stdnse.debug1("Have successfully parsed json response.") 177 | if vulns.result == "OK" then 178 | stdnse.debug1("Response from vulners is OK.") 179 | return make_links(vulns) 180 | else 181 | stdnse.debug1("Response from vulners is not OK with body:") 182 | stdnse.debug1(response.body) 183 | end 184 | else 185 | stdnse.debug1("Unable to parse json.") 186 | stdnse.debug1(response.body) 187 | end 188 | end 189 | 190 | 191 | --- 192 | -- Calls get_results for type="software" 193 | -- 194 | -- It is called from action when nothing is found for the available cpe's 195 | -- 196 | -- @param software string, the software name 197 | -- @param version string, the software version 198 | -- 199 | function get_vulns_by_software(software, version) 200 | return get_results(software, version, "software") 201 | end 202 | 203 | 204 | --- 205 | -- Calls get_results for type="cpe" 206 | -- 207 | -- Takes the version number from the given cpe and tries to get the result. 208 | -- If none found, changes the given cpe a bit in order to possibly separate version number from the patch version 209 | -- And makes another attempt. 210 | -- Having failed returns an empty string. 211 | -- 212 | -- @param cpe string, the given cpe 213 | -- 214 | function get_vulns_by_cpe(cpe) 215 | local vers_regexp=":([%d%.%-%_]+)([^:]*)$" 216 | 217 | -- TODO[gmedian]: add check for cpe:/a as we might be interested in software rather than in OS (cpe:/o) and hardware (cpe:/h) 218 | -- TODO[gmedian]: work not with the LAST part but simply with the THIRD one (according to cpe doc it must be version) 219 | 220 | -- NOTE[gmedian]: take only the numeric part of the version 221 | local _, _, vers, patch = cpe:find(vers_regexp) 222 | 223 | if not vers then 224 | return 225 | end 226 | 227 | stdnse.debug1("Got cpe " .. cpe .. " with version ".. vers .. " and patch " .. (patch or "nil")) 228 | 229 | local output = get_results(cpe, vers, "cpe") 230 | 231 | if not output then 232 | if patch and patch ~= "" then 233 | local new_cpe 234 | 235 | new_cpe = cpe:gsub(vers_regexp, ":%1:%2") 236 | stdnse.debug1("Forming new cpe for another attempt " .. new_cpe) 237 | output = get_results(new_cpe, vers, "cpe") 238 | end 239 | end 240 | 241 | return output 242 | end 243 | 244 | 245 | action = function(host, port) 246 | local tab=stdnse.output_table() 247 | local changed=false 248 | local output 249 | 250 | for i, cpe in ipairs(port.version.cpe) do 251 | -- There are two cpe's for nginx, have to check them both 252 | cpe = cpe:gsub(":nginx:nginx", ":igor_sysoev:nginx") 253 | stdnse.debug1("Analyzing cpe " .. cpe) 254 | output = get_vulns_by_cpe(cpe) 255 | if cpe:find(":igor_sysoev:nginx") then 256 | cpe = cpe:gsub(":igor_sysoev:nginx", ":nginx:nginx") 257 | stdnse.debug1("Now going to analyze the second version " .. cpe) 258 | local output_nginx=get_vulns_by_cpe(cpe) 259 | if not output then 260 | output = output_nginx 261 | elseif output_nginx then 262 | -- Need to merge two arrays, sorted by cvss 263 | -- Presumably the former output contains by far less entries, so iterate on it and insert into the latter 264 | -- pos will represent current position in output_nginx 265 | local pos=1 266 | for i, v in ipairs(output) do 267 | while pos <= #output_nginx and output_nginx[pos].cvss >= v.cvss do 268 | pos = pos + 1 269 | end 270 | table.insert(output_nginx, pos, v) 271 | end 272 | output = output_nginx 273 | end 274 | end 275 | if output then 276 | tab[cpe] = output 277 | changed = true 278 | end 279 | end 280 | 281 | -- NOTE[gmedian]: check whether we have pre-matched CPEs in registry (from http-vulners-regex.nse in particular) 282 | if host.registry.vulners_cpe ~= nil and #host.registry.vulners_cpe > 0 then 283 | stdnse.debug1("Found some CPEs in host registry.") 284 | for i, cpe in ipairs(host.registry.vulners_cpe) do 285 | -- avoid duplicates in output, will still however make redundant requests 286 | if tab[cpe] == nil then 287 | stdnse.debug1("Analyzing pre-matched cpe " .. cpe) 288 | output = get_vulns_by_cpe(cpe) 289 | if output then 290 | tab[cpe] = output 291 | changed = true 292 | end 293 | end 294 | end 295 | end 296 | 297 | -- NOTE[gmedian]: issue request for type=software, but only when nothing is found so far 298 | if not changed then 299 | local vendor_version = port.version.product .. " " .. port.version.version 300 | output = get_vulns_by_software(port.version.product, port.version.version) 301 | if output then 302 | tab[vendor_version] = output 303 | changed = true 304 | end 305 | end 306 | 307 | if (not changed) then 308 | return 309 | end 310 | return tab 311 | end 312 | 313 | -------------------------------------------------------------------------------- /vulners_enterprise.nse: -------------------------------------------------------------------------------- 1 | description = [[ 2 | For each available CPE the script prints out known vulns (links to the correspondent info) and correspondent CVSS scores. 3 | 4 | Its work is pretty simple: 5 | * work only when some software version is identified for an open port 6 | * take all the known CPEs for that software (from the standard nmap -sV output) 7 | * make a request to a remote server (vulners.com API) to learn whether any known vulns exist for that CPE 8 | * if no info is found this way, try to get it using the software name alone 9 | * print the obtained info out 10 | 11 | NB: 12 | Since the size of the DB with all the vulns is more than 250GB there is no way to use a local db. 13 | So we do make requests to a remote service. Still all the requests contain just two fields - the 14 | software name and its version (or CPE), so one can still have the desired privacy. 15 | 16 | NB2: 17 | This script requires a valid API token. You can either specify it on the CLI using the 'api_key' script argument, 18 | set it into an envirotnment variable VULNERS_API_KEY, or store it in a file readable by the user running nmap. 19 | In this case you must specify the absolute path to the file using the 'api_key_file' script argument. 20 | ]] 21 | 22 | --- 23 | -- @usage 24 | -- nmap -sV --script vulners_enterprise [--script-args mincvss=,api_key=,api_key_file=,api_host=http://my_host.com] 25 | -- 26 | -- @args vulners_enterprise.mincvss Limit CVEs shown to those with this CVSS score or greater. 27 | -- @args vulners_enterprise.api_key API token to be used in the requests 28 | -- @args vulners_enterprise.api_key_file Absolute path to the file with a single line containing the API token 29 | -- @args vulners_enterprise.api_host URL to vulners API without the leading slash. Defaults to https://vulners.com 30 | -- 31 | -- @output 32 | -- 33 | -- PORT STATE SERVICE REASON VERSION 34 | -- 22/tcp open ssh syn-ack OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.13 (Ubuntu Linux; protocol 2.0) 35 | -- | vulners_enterprise: 36 | -- | cpe:/a:openbsd:openssh:6.6.1p1: 37 | -- | PRION:CVE-2020-16088 cvssV3: 9.8 https://vulners.com/prion/PRION:CVE-2020-16088 38 | -- | PRION:CVE-2015-5600 cvssV2: 8.5 https://vulners.com/prion/PRION:CVE-2015-5600 39 | -- | CVE-2015-5600 cvssV2: 8.5 https://vulners.com/cve/CVE-2015-5600 40 | -- | PRION:CVE-2015-6564 cvssV2: 6.9 https://vulners.com/prion/PRION:CVE-2015-6564 41 | -- | CVE-2015-6564 cvssV2: 6.9 https://vulners.com/cve/CVE-2015-6564 42 | -- | CVE-2020-14145 cvssV3: 5.9 https://vulners.com/cve/CVE-2020-14145 43 | -- | CVE-2018-15919 cvssV3: 5.3 https://vulners.com/cve/CVE-2018-15919 44 | -- | PRION:CVE-2015-5352 cvssV2: 4.3 https://vulners.com/prion/PRION:CVE-2015-5352 45 | -- | CVE-2015-5352 cvssV2: 4.3 https://vulners.com/cve/CVE-2015-5352 46 | -- | PRION:CVE-2015-6563 cvssV2: 1.9 https://vulners.com/prion/PRION:CVE-2015-6563 47 | -- |_ CVE-2015-6563 cvssV2: 1.9 https://vulners.com/cve/CVE-2015-6563 48 | -- 49 | -- @xmloutput 50 | -- 51 | --
52 | -- false 53 | -- 8.5 54 | -- CVE-2012-1667 55 | -- cve 56 | --
57 | -- 58 | -- false 59 | -- 7.8 60 | -- CVE-2015-4620 61 | -- cve 62 | --
63 | -- 64 | 65 | dependencies = {"http-vulners-regex"} 66 | author = 'gmedian AT vulners DOT com' 67 | license = "Same as Nmap--See https://nmap.org/book/man-legal.html" 68 | categories = {"vuln", "safe", "external", "default"} 69 | 70 | 71 | local http = require "http" 72 | local url = require "url" 73 | local json = require "json" 74 | local string = require "string" 75 | local table = require "table" 76 | local nmap = require "nmap" 77 | local stdnse = require "stdnse" 78 | local os = require "os" 79 | 80 | local api_version="1.9" 81 | local mincvss=stdnse.get_script_args(SCRIPT_NAME .. ".mincvss") 82 | mincvss = tonumber(mincvss) or 0.0 83 | 84 | local api_key_file=stdnse.get_script_args(SCRIPT_NAME .. ".api_key_file") 85 | api_key_file = api_key_file or "" 86 | 87 | local api_host=stdnse.get_script_args(SCRIPT_NAME .. ".api_host") 88 | api_host = api_host or 'https://vulners.com' 89 | 90 | local api_key=stdnse.get_script_args(SCRIPT_NAME .. ".api_key") 91 | api_key = api_key or os.getenv("VULNERS_API_KEY") 92 | 93 | portrule = function(host, port) 94 | local vers=port.version 95 | return vers ~= nil and vers.version ~= nil or (host.registry.vulners_cpe ~= nil) 96 | end 97 | 98 | local cve_meta = { 99 | __tostring = function(me) 100 | return ("\t%s\t%s: %s\thttps://vulners.com/%s/%s%s"):format(me.id, me.cvss_type, me.cvss or "", me.type, me.id, me.is_exploit and '\t*EXPLOIT*' or '') 101 | end, 102 | } 103 | 104 | 105 | --- 106 | -- Return a string read from api_key_file to be used as an API_KEY 107 | -- 108 | function read_api_key_file() 109 | 110 | stdnse.debug1("api_key not specified. Trying to read api_key_file.") 111 | 112 | if api_key_file == nil or api_key_file == "" then 113 | stdnse.debug1("No api_key_file set") 114 | return "" 115 | end 116 | 117 | local file = io.open(api_key_file, "r") 118 | if file == nil then 119 | stdnse.debug1("Failed to open api_key_file " .. api_key_file) 120 | return "" 121 | end 122 | 123 | api_key = file:read("*line") 124 | 125 | file:close() 126 | 127 | return api_key 128 | end 129 | 130 | 131 | --- 132 | -- Return a string with all the found cve's and correspondent links 133 | -- 134 | -- @param vulns a table with the parsed json response from the vulners server 135 | -- 136 | function make_links(vulns) 137 | local output = {} 138 | local cvss = "" 139 | 140 | if not vulns or not vulns.data or not vulns.data.search then 141 | return 142 | end 143 | 144 | for _, vuln in ipairs(vulns.data.search) do 145 | 146 | 147 | local v = { 148 | id = vuln._source.id, 149 | type = vuln._source.type, 150 | -- Mark the exploits out 151 | is_exploit = vuln._source.bulletinFamily:lower() == "exploit", 152 | -- Sometimes it might happen, so check the score availability 153 | } 154 | if vuln._source.cvss3.cvssV3 == nil then 155 | v['cvss'] = vuln._source.cvss.score 156 | v['cvss_type'] = "cvssV2" 157 | else 158 | v['cvss'] = vuln._source.cvss3.cvssV3.baseScore 159 | v['cvss_type'] = "cvssV3" 160 | end 161 | 162 | -- NOTE[gmedian]: exploits seem to have cvss == 0, so print them anyway 163 | if not v.cvss or (v.cvss == 0 and v.is_exploit) or mincvss <= v.cvss then 164 | setmetatable(v, cve_meta) 165 | output[#output+1] = v 166 | end 167 | end 168 | 169 | if #output > 0 then 170 | -- Sort the acquired vulns by the CVSS score 171 | table.sort(output, function(a, b) 172 | return a.cvss > b.cvss or (a.cvss == b.cvss and a.id > b.id) 173 | end) 174 | return output 175 | end 176 | end 177 | 178 | 179 | --- 180 | -- Issues the requests, receives json and parses it, calls make_links when successfull 181 | -- 182 | -- @param what string, future value for the software query argument 183 | -- @param vers string, the version query argument 184 | -- @param type string, the type query argument 185 | -- 186 | function get_results(what, vers, type) 187 | local api_endpoint = api_host .. "/api/v3/burp/softwareapi/" 188 | local vulns 189 | local response 190 | local status 191 | local attempt_n=0 192 | local query = { 193 | software= what, 194 | version= vers, 195 | type=type, 196 | apiKey=api_key 197 | } 198 | local api_url = ('%s?%s'):format(api_endpoint, url.build_query(query)) 199 | local option={ 200 | header={ 201 | ['User-Agent'] = string.format('Vulners NMAP Enterprise %s', api_version), 202 | ['Accept-Encoding'] = "gzip, deflate" 203 | }, 204 | any_af = true, 205 | } 206 | 207 | stdnse.debug1("Trying to get vulns of " .. what .. " for type " .. type) 208 | 209 | -- Sometimes we cannot contact vulners, so have to try several more times 210 | while attempt_n < 3 do 211 | stdnse.debug1("Attempt ".. attempt_n .. " to contact vulners.") 212 | response = http.get_url(api_url, option) 213 | status = response.status 214 | if status ~= nil then 215 | break 216 | end 217 | attempt_n = attempt_n + 1 218 | stdnse.sleep(1) 219 | end 220 | 221 | if status == nil then 222 | -- Something went really wrong out there 223 | -- According to the NSE way we will die silently rather than spam user with error messages 224 | stdnse.debug1("Failed to cantact vulners in several attempts.") 225 | return 226 | elseif status ~= 200 then 227 | -- Again just die silently 228 | stdnse.debug1("Response from vulners is not 200 but " .. status) 229 | return 230 | end 231 | 232 | status, vulns = json.parse(response.body) 233 | 234 | if status == true then 235 | stdnse.debug1("Have successfully parsed json response.") 236 | if vulns.result == "OK" then 237 | stdnse.debug1("Response from vulners is OK.") 238 | return make_links(vulns) 239 | else 240 | stdnse.debug1("Response from vulners is not OK with body:") 241 | stdnse.debug1(response.body) 242 | end 243 | else 244 | stdnse.debug1("Unable to parse json.") 245 | stdnse.debug1(response.body) 246 | end 247 | end 248 | 249 | 250 | --- 251 | -- Calls get_results for type="software" 252 | -- 253 | -- It is called from action when nothing is found for the available cpe's 254 | -- 255 | -- @param software string, the software name 256 | -- @param version string, the software version 257 | -- 258 | function get_vulns_by_software(software, version) 259 | return get_results(software, version, "software") 260 | end 261 | 262 | 263 | --- 264 | -- Calls get_results for type="cpe" 265 | -- 266 | -- Takes the version number from the given cpe and tries to get the result. 267 | -- If none found, changes the given cpe a bit in order to possibly separate version number from the patch version 268 | -- And makes another attempt. 269 | -- Having failed returns an empty string. 270 | -- 271 | -- @param cpe string, the given cpe 272 | -- 273 | function get_vulns_by_cpe(cpe) 274 | local vers_regexp=":([%d%.%-%_]+)([^:]*)$" 275 | 276 | -- TODO[gmedian]: add check for cpe:/a as we might be interested in software rather than in OS (cpe:/o) and hardware (cpe:/h) 277 | -- TODO[gmedian]: work not with the LAST part but simply with the THIRD one (according to cpe doc it must be version) 278 | 279 | -- NOTE[gmedian]: take only the numeric part of the version 280 | local _, _, vers, patch = cpe:find(vers_regexp) 281 | 282 | if not vers then 283 | return 284 | end 285 | 286 | stdnse.debug1("Got cpe " .. cpe .. " with version ".. vers .. " and patch " .. (patch or "nil")) 287 | 288 | local output = get_results(cpe, vers, "cpe") 289 | 290 | if not output then 291 | if patch and patch ~= "" then 292 | local new_cpe 293 | 294 | new_cpe = cpe:gsub(vers_regexp, ":%1:%2") 295 | stdnse.debug1("Forming new cpe for another attempt " .. new_cpe) 296 | output = get_results(new_cpe, vers, "cpe") 297 | end 298 | end 299 | 300 | return output 301 | end 302 | 303 | 304 | action = function(host, port) 305 | local tab=stdnse.output_table() 306 | local changed=false 307 | local output 308 | 309 | api_key = api_key or read_api_key_file() 310 | 311 | if api_key == nil or api_key == "" then 312 | stdnse.debug1("Api key is not set in either arg, ENV or file. Exiting.") 313 | return 314 | end 315 | 316 | stdnse.debug1("Api file is set to " .. api_key_file) 317 | stdnse.debug1("Host is set to " .. api_host) 318 | stdnse.debug1("Api key is set to " .. api_key) 319 | 320 | for i, cpe in ipairs(port.version.cpe) do 321 | -- There are two cpe's for nginx, have to check them both 322 | cpe = cpe:gsub(":nginx:nginx", ":igor_sysoev:nginx") 323 | stdnse.debug1("Analyzing cpe " .. cpe) 324 | output = get_vulns_by_cpe(cpe) 325 | if cpe:find(":igor_sysoev:nginx") then 326 | cpe = cpe:gsub(":igor_sysoev:nginx", ":nginx:nginx") 327 | stdnse.debug1("Now going to analyze the second version " .. cpe) 328 | local output_nginx=get_vulns_by_cpe(cpe) 329 | if not output then 330 | output = output_nginx 331 | elseif output_nginx then 332 | -- Need to merge two arrays, sorted by cvss 333 | -- Presumably the former output contains by far less entries, so iterate on it and insert into the latter 334 | -- pos will represent current position in output_nginx 335 | local pos=1 336 | for i, v in ipairs(output) do 337 | while pos <= #output_nginx and output_nginx[pos].cvss >= v.cvss do 338 | pos = pos + 1 339 | end 340 | table.insert(output_nginx, pos, v) 341 | end 342 | output = output_nginx 343 | end 344 | end 345 | if output then 346 | tab[cpe] = output 347 | changed = true 348 | end 349 | end 350 | 351 | -- NOTE[gmedian]: check whether we have pre-matched CPEs in registry (from http-vulners-regex.nse in particular) 352 | if host.registry.vulners_cpe ~= nil and #host.registry.vulners_cpe > 0 then 353 | stdnse.debug1("Found some CPEs in host registry.") 354 | for i, cpe in ipairs(host.registry.vulners_cpe) do 355 | -- avoid duplicates in output, will still however make redundant requests 356 | if tab[cpe] == nil then 357 | stdnse.debug1("Analyzing pre-matched cpe " .. cpe) 358 | output = get_vulns_by_cpe(cpe) 359 | if output then 360 | tab[cpe] = output 361 | changed = true 362 | end 363 | end 364 | end 365 | end 366 | 367 | -- NOTE[gmedian]: issue request for type=software, but only when nothing is found so far 368 | if not changed then 369 | local vendor_version = port.version.product .. " " .. port.version.version 370 | output = get_vulns_by_software(port.version.product, port.version.version) 371 | if output then 372 | tab[vendor_version] = output 373 | changed = true 374 | end 375 | end 376 | 377 | if (not changed) then 378 | return 379 | end 380 | return tab 381 | end 382 | 383 | -------------------------------------------------------------------------------- /vulners_enterprise_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vulnersCom/nmap-vulners/b913758f029b570e67c6def343b838dda1c9e7e4/vulners_enterprise_output.png --------------------------------------------------------------------------------