├── LICENSE ├── README.md ├── autoproxy.py └── option.py /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 | # sqlmap-autoproxy 2 | config sqlmap use proxy automatically(自动获取代理IP) 3 | 4 | 自己通过修改sqlmap源码实现了sqlmap注入时自动走代理的功能(自动获取免费代理,由于地域原因,获取的都是中国国内的代理IP) 5 | 6 | ## Install 7 | 方法1: 8 | > - 将autoproxy.py放到thirdparty目录下 9 | > - 用option.py 替换lib/core/option.py 10 | 11 | 方法2: 12 | > 其实option.py只是修改了如下两处,也可以将autoproxy.py放到thirdparty下,然后自行修改lib/core/option.py文件 13 | > 1. 添加`from thirdparty.autoproxy import main as getproxyip` 14 | > 2. 在`conf.proxyList = []`后添加: 15 | > ```python 16 | > conf.proxyList = [] 17 | > if conf.proxyFile == 'auto': 18 | > getproxyip() 19 | > for line in open(paths.SQLMAP_ROOT_PATH +"/thirdparty/proxy.txt", 'r'): 20 | > conf.proxyList.append("http://"+line) 21 | > return 22 | > ``` 23 | 图示:https://s1.ax1x.com/2020/08/06/ac5kct.png 24 | 25 | ## Usage 26 | 使用sqlmap时添加参数: --proxy-file auto 一定要是auto 27 | 28 | ## 原理 29 | 其实就是自己实现了一个自动获取代理的脚本,自动检测可用性后记录到文件,在sqlmap的init函数中,调用了`_setProxyList()`函数,该函数用于将代理文件中的IP放入conf.proxyList中,sqlmap会从这个列表中自动获取代理.所以魔改该函数使得当--proxy-file的值为auto时,自动调用获取代理的脚本,使用获取到的IP作为sqlmap的代理. 30 | 31 | **autoproxy.py可以单独使用,生成的proxy.txt在autoproxy的同级目录中** 32 | 33 | 展示:https://s1.ax1x.com/2020/08/06/agx7vT.png 34 | 35 | 欢迎交流~共同进步~欢迎各位大佬帮忙提建议~ 36 | -------------------------------------------------------------------------------- /autoproxy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Author: Gality 6 | Name:autoproxy.py 7 | Usage: python3 autoproxy.py 8 | require: requests, lxml 9 | Description: Get proxy automatically(China)and config sqlmap use proxy IP 10 | E-mail: gality365@gmail.com 11 | """ 12 | 13 | 14 | import requests 15 | import os 16 | from lxml import etree 17 | 18 | 19 | # 获取代理IP列表 20 | def getproxy(page=''): 21 | print("[*] 正在获取代理IP列表") 22 | url = "https://ip.ihuan.me/address/5Lit5Zu9.html" + page 23 | proxy_list = [] 24 | headers = { 25 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'} 26 | r = requests.get(url, headers=headers) 27 | sel = etree.HTML(r.text) 28 | page = sel.xpath('//ul[@class="pagination"]/li[8]/a/attribute::href')[0] 29 | for li in sel.xpath('//tbody//tr'): 30 | if li.xpath('./td[6]/text()')[0] == "支持": 31 | proxy_list.append(li.xpath('./td[1]/a/text()')[0] + ":" + li.xpath('./td[2]/text()')[0]) 32 | if proxy_list == []: 33 | tmp_list, tmp = getproxy(page) 34 | proxy_list += tmp_list 35 | print("[*] 获取到" + str(len(proxy_list)) + "个代理IP") 36 | return proxy_list, page 37 | 38 | 39 | # 检测代理可用性 40 | def checkproxy(proxy_list): 41 | print("[*] 正在检测代理IP可用性,请稍等...") 42 | checked_list = [] 43 | i = 1 44 | for proxy in proxy_list: 45 | proxy_url = "http://" + proxy 46 | proxies = {'http': proxy_url, 'https': proxy_url, } 47 | print("[*] 正在检测第" + str(i) + "个IP......",end="") 48 | try: 49 | r = requests.get("http://ip111.cn/", proxies=proxies, timeout=3) 50 | except requests.exceptions.RequestException as e: 51 | i += 1 52 | print("超时") 53 | continue 54 | if r.status_code == 200: 55 | checked_list.append(proxy) 56 | print("可用") 57 | else: 58 | print("Response Code:", r.status_code) 59 | i += 1 60 | if checked_list == []: 61 | print("[!] 所有获取到的IP均不可用,将会自动获取新的代理") 62 | return checked_list 63 | 64 | 65 | # 主函数 66 | def main(): 67 | path = os.path.dirname(os.path.realpath(__file__)) + '/proxy.txt' 68 | proxy_list = [] 69 | checked_list = [] 70 | page = "" 71 | print("[!] 本脚本基于小幻HTTP代理,请勿大量抓取代理^-^") 72 | print("[*] 正在执行获取代理脚本,您可以随时通过ctrl+c终止选取过程并进入后续步骤") 73 | try: 74 | try: 75 | f = open(path, 'r') 76 | for line in f.readlines(): 77 | proxy_list.append(line[:-1]) 78 | except IOError: 79 | pass 80 | 81 | f = open(path , 'w') 82 | if proxy_list == []: 83 | print("[!] 未检测到本地有代理IP列表文件,将自动获取代理IP") 84 | while True: 85 | proxy_list, page = getproxy(page) 86 | checked_list += checkproxy(proxy_list) 87 | if len(checked_list) < 3: 88 | print("[!] 由于可用IP少于3个,鉴于免费代理的不稳定性, 将自动获取更多代理") 89 | continue 90 | else: 91 | break 92 | else: 93 | print("[*] 检测到本地代理文件,正在测试可用性...") 94 | checked_list += checkproxy(proxy_list) 95 | if len(checked_list) < 3: 96 | print("[!] 由于可用IP少于3个,鉴于免费代理的不稳定性, 将自动获取更多代理") 97 | while True: 98 | proxy_list, page = getproxy(page) 99 | checked_list += checkproxy(proxy_list) 100 | if len(checked_list) < 3: 101 | continue 102 | else: 103 | break 104 | print(checked_list) 105 | except IOError: 106 | print('Permisson deny,check that you have permission to read and write %s', path) 107 | except KeyboardInterrupt: 108 | pass 109 | except IndexError: 110 | print("出现异常,请稍后重试") 111 | finally: 112 | for proxy in checked_list: 113 | f.write(proxy + "\n") 114 | f.close() 115 | 116 | 117 | if __name__ == '__main__': 118 | main() 119 | 120 | -------------------------------------------------------------------------------- /option.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Copyright (c) 2006-2020 sqlmap developers (http://sqlmap.org/) 5 | See the file 'LICENSE' for copying permission 6 | """ 7 | 8 | from __future__ import division 9 | 10 | import codecs 11 | import functools 12 | import glob 13 | import inspect 14 | import logging 15 | import os 16 | import random 17 | import re 18 | import socket 19 | import sys 20 | import tempfile 21 | import threading 22 | import time 23 | 24 | from lib.controller.checks import checkConnection 25 | from lib.core.common import Backend 26 | from lib.core.common import boldifyMessage 27 | from lib.core.common import checkFile 28 | from lib.core.common import dataToStdout 29 | from lib.core.common import decodeStringEscape 30 | from lib.core.common import fetchRandomAgent 31 | from lib.core.common import filterNone 32 | from lib.core.common import findLocalPort 33 | from lib.core.common import findPageForms 34 | from lib.core.common import getConsoleWidth 35 | from lib.core.common import getFileItems 36 | from lib.core.common import getFileType 37 | from lib.core.common import getPublicTypeMembers 38 | from lib.core.common import getSafeExString 39 | from lib.core.common import intersect 40 | from lib.core.common import normalizePath 41 | from lib.core.common import ntToPosixSlashes 42 | from lib.core.common import openFile 43 | from lib.core.common import parseRequestFile 44 | from lib.core.common import parseTargetDirect 45 | from lib.core.common import paths 46 | from lib.core.common import randomStr 47 | from lib.core.common import readCachedFileContent 48 | from lib.core.common import readInput 49 | from lib.core.common import resetCookieJar 50 | from lib.core.common import runningAsAdmin 51 | from lib.core.common import safeExpandUser 52 | from lib.core.common import safeFilepathEncode 53 | from lib.core.common import saveConfig 54 | from lib.core.common import setColor 55 | from lib.core.common import setOptimize 56 | from lib.core.common import setPaths 57 | from lib.core.common import singleTimeWarnMessage 58 | from lib.core.common import urldecode 59 | from lib.core.compat import cmp 60 | from lib.core.compat import round 61 | from lib.core.compat import xrange 62 | from lib.core.convert import getUnicode 63 | from lib.core.data import conf 64 | from lib.core.data import kb 65 | from lib.core.data import logger 66 | from lib.core.data import mergedOptions 67 | from lib.core.data import queries 68 | from lib.core.datatype import AttribDict 69 | from lib.core.datatype import InjectionDict 70 | from lib.core.datatype import OrderedSet 71 | from lib.core.defaults import defaults 72 | from lib.core.dicts import DBMS_DICT 73 | from lib.core.dicts import DUMP_REPLACEMENTS 74 | from lib.core.enums import ADJUST_TIME_DELAY 75 | from lib.core.enums import AUTH_TYPE 76 | from lib.core.enums import CUSTOM_LOGGING 77 | from lib.core.enums import DUMP_FORMAT 78 | from lib.core.enums import HTTP_HEADER 79 | from lib.core.enums import HTTPMETHOD 80 | from lib.core.enums import MKSTEMP_PREFIX 81 | from lib.core.enums import MOBILES 82 | from lib.core.enums import OPTION_TYPE 83 | from lib.core.enums import PAYLOAD 84 | from lib.core.enums import PRIORITY 85 | from lib.core.enums import PROXY_TYPE 86 | from lib.core.enums import REFLECTIVE_COUNTER 87 | from lib.core.enums import WIZARD 88 | from lib.core.exception import SqlmapConnectionException 89 | from lib.core.exception import SqlmapDataException 90 | from lib.core.exception import SqlmapFilePathException 91 | from lib.core.exception import SqlmapGenericException 92 | from lib.core.exception import SqlmapInstallationException 93 | from lib.core.exception import SqlmapMissingDependence 94 | from lib.core.exception import SqlmapMissingMandatoryOptionException 95 | from lib.core.exception import SqlmapMissingPrivileges 96 | from lib.core.exception import SqlmapSilentQuitException 97 | from lib.core.exception import SqlmapSyntaxException 98 | from lib.core.exception import SqlmapSystemException 99 | from lib.core.exception import SqlmapUnsupportedDBMSException 100 | from lib.core.exception import SqlmapUserQuitException 101 | from lib.core.exception import SqlmapValueException 102 | from lib.core.log import FORMATTER 103 | from lib.core.optiondict import optDict 104 | from lib.core.settings import CODECS_LIST_PAGE 105 | from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR 106 | from lib.core.settings import DBMS_ALIASES 107 | from lib.core.settings import DEFAULT_GET_POST_DELIMITER 108 | from lib.core.settings import DEFAULT_PAGE_ENCODING 109 | from lib.core.settings import DEFAULT_TOR_HTTP_PORTS 110 | from lib.core.settings import DEFAULT_TOR_SOCKS_PORTS 111 | from lib.core.settings import DEFAULT_USER_AGENT 112 | from lib.core.settings import DUMMY_URL 113 | from lib.core.settings import IGNORE_CODE_WILDCARD 114 | from lib.core.settings import IS_WIN 115 | from lib.core.settings import KB_CHARS_BOUNDARY_CHAR 116 | from lib.core.settings import KB_CHARS_LOW_FREQUENCY_ALPHABET 117 | from lib.core.settings import LOCALHOST 118 | from lib.core.settings import MAX_CONNECT_RETRIES 119 | from lib.core.settings import MAX_NUMBER_OF_THREADS 120 | from lib.core.settings import NULL 121 | from lib.core.settings import PARAMETER_SPLITTING_REGEX 122 | from lib.core.settings import PRECONNECT_CANDIDATE_TIMEOUT 123 | from lib.core.settings import PROXY_ENVIRONMENT_VARIABLES 124 | from lib.core.settings import SOCKET_PRE_CONNECT_QUEUE_SIZE 125 | from lib.core.settings import SQLMAP_ENVIRONMENT_PREFIX 126 | from lib.core.settings import SUPPORTED_DBMS 127 | from lib.core.settings import SUPPORTED_OS 128 | from lib.core.settings import TIME_DELAY_CANDIDATES 129 | from lib.core.settings import UNION_CHAR_REGEX 130 | from lib.core.settings import UNKNOWN_DBMS_VERSION 131 | from lib.core.settings import URI_INJECTABLE_REGEX 132 | from lib.core.threads import getCurrentThreadData 133 | from lib.core.threads import setDaemon 134 | from lib.core.update import update 135 | from lib.parse.configfile import configFileParser 136 | from lib.parse.payloads import loadBoundaries 137 | from lib.parse.payloads import loadPayloads 138 | from lib.request.basic import checkCharEncoding 139 | from lib.request.basicauthhandler import SmartHTTPBasicAuthHandler 140 | from lib.request.chunkedhandler import ChunkedHandler 141 | from lib.request.connect import Connect as Request 142 | from lib.request.dns import DNSServer 143 | from lib.request.httpshandler import HTTPSHandler 144 | from lib.request.pkihandler import HTTPSPKIAuthHandler 145 | from lib.request.rangehandler import HTTPRangeHandler 146 | from lib.request.redirecthandler import SmartRedirectHandler 147 | from lib.utils.crawler import crawl 148 | from lib.utils.deps import checkDependencies 149 | from lib.utils.har import HTTPCollectorFactory 150 | from lib.utils.purge import purge 151 | from lib.utils.search import search 152 | from thirdparty import six 153 | from thirdparty.keepalive import keepalive 154 | from thirdparty.multipart import multipartpost 155 | from thirdparty.six.moves import http_client as _http_client 156 | from thirdparty.six.moves import http_cookiejar as _http_cookiejar 157 | from thirdparty.six.moves import urllib as _urllib 158 | from thirdparty.socks import socks 159 | from thirdparty.autoproxy import main as getproxyip 160 | from xml.etree.ElementTree import ElementTree 161 | 162 | authHandler = _urllib.request.BaseHandler() 163 | chunkedHandler = ChunkedHandler() 164 | httpsHandler = HTTPSHandler() 165 | keepAliveHandler = keepalive.HTTPHandler() 166 | proxyHandler = _urllib.request.ProxyHandler() 167 | redirectHandler = SmartRedirectHandler() 168 | rangeHandler = HTTPRangeHandler() 169 | multipartPostHandler = multipartpost.MultipartPostHandler() 170 | 171 | # Reference: https://mail.python.org/pipermail/python-list/2009-November/558615.html 172 | try: 173 | WindowsError 174 | except NameError: 175 | WindowsError = None 176 | 177 | def _loadQueries(): 178 | """ 179 | Loads queries from 'xml/queries.xml' file. 180 | """ 181 | 182 | def iterate(node, retVal=None): 183 | class DictObject(object): 184 | def __init__(self): 185 | self.__dict__ = {} 186 | 187 | def __contains__(self, name): 188 | return name in self.__dict__ 189 | 190 | if retVal is None: 191 | retVal = DictObject() 192 | 193 | for child in node.findall("*"): 194 | instance = DictObject() 195 | retVal.__dict__[child.tag] = instance 196 | if child.attrib: 197 | instance.__dict__.update(child.attrib) 198 | else: 199 | iterate(child, instance) 200 | 201 | return retVal 202 | 203 | tree = ElementTree() 204 | try: 205 | tree.parse(paths.QUERIES_XML) 206 | except Exception as ex: 207 | errMsg = "something appears to be wrong with " 208 | errMsg += "the file '%s' ('%s'). Please make " % (paths.QUERIES_XML, getSafeExString(ex)) 209 | errMsg += "sure that you haven't made any changes to it" 210 | raise SqlmapInstallationException(errMsg) 211 | 212 | for node in tree.findall("*"): 213 | queries[node.attrib['value']] = iterate(node) 214 | 215 | def _setMultipleTargets(): 216 | """ 217 | Define a configuration parameter if we are running in multiple target 218 | mode. 219 | """ 220 | 221 | initialTargetsCount = len(kb.targets) 222 | seen = set() 223 | 224 | if not conf.logFile: 225 | return 226 | 227 | debugMsg = "parsing targets list from '%s'" % conf.logFile 228 | logger.debug(debugMsg) 229 | 230 | if not os.path.exists(conf.logFile): 231 | errMsg = "the specified list of targets does not exist" 232 | raise SqlmapFilePathException(errMsg) 233 | 234 | if checkFile(conf.logFile, False): 235 | for target in parseRequestFile(conf.logFile): 236 | url, _, data, _, _ = target 237 | key = re.sub(r"(\w+=)[^%s ]*" % (conf.paramDel or DEFAULT_GET_POST_DELIMITER), r"\g<1>", "%s %s" % (url, data)) 238 | if key not in seen: 239 | kb.targets.add(target) 240 | seen.add(key) 241 | 242 | elif os.path.isdir(conf.logFile): 243 | files = os.listdir(conf.logFile) 244 | files.sort() 245 | 246 | for reqFile in files: 247 | if not re.search(r"([\d]+)\-request", reqFile): 248 | continue 249 | 250 | for target in parseRequestFile(os.path.join(conf.logFile, reqFile)): 251 | url, _, data, _, _ = target 252 | key = re.sub(r"(\w+=)[^%s ]*" % (conf.paramDel or DEFAULT_GET_POST_DELIMITER), r"\g<1>", "%s %s" % (url, data)) 253 | if key not in seen: 254 | kb.targets.add(target) 255 | seen.add(key) 256 | 257 | else: 258 | errMsg = "the specified list of targets is not a file " 259 | errMsg += "nor a directory" 260 | raise SqlmapFilePathException(errMsg) 261 | 262 | updatedTargetsCount = len(kb.targets) 263 | 264 | if updatedTargetsCount > initialTargetsCount: 265 | infoMsg = "sqlmap parsed %d " % (updatedTargetsCount - initialTargetsCount) 266 | infoMsg += "(parameter unique) requests from the " 267 | infoMsg += "targets list ready to be tested" 268 | logger.info(infoMsg) 269 | 270 | def _adjustLoggingFormatter(): 271 | """ 272 | Solves problem of line deletition caused by overlapping logging messages 273 | and retrieved data info in inference mode 274 | """ 275 | 276 | if hasattr(FORMATTER, '_format'): 277 | return 278 | 279 | def format(record): 280 | message = FORMATTER._format(record) 281 | message = boldifyMessage(message) 282 | if kb.get("prependFlag"): 283 | message = "\n%s" % message 284 | kb.prependFlag = False 285 | return message 286 | 287 | FORMATTER._format = FORMATTER.format 288 | FORMATTER.format = format 289 | 290 | def _setRequestFromFile(): 291 | """ 292 | This function checks if the way to make a HTTP request is through supplied 293 | textual file, parses it and saves the information into the knowledge base. 294 | """ 295 | 296 | if conf.requestFile: 297 | for requestFile in re.split(PARAMETER_SPLITTING_REGEX, conf.requestFile): 298 | requestFile = safeExpandUser(requestFile) 299 | url = None 300 | seen = set() 301 | 302 | if not checkFile(requestFile, False): 303 | errMsg = "specified HTTP request file '%s' " % requestFile 304 | errMsg += "does not exist" 305 | raise SqlmapFilePathException(errMsg) 306 | 307 | infoMsg = "parsing HTTP request from '%s'" % requestFile 308 | logger.info(infoMsg) 309 | 310 | for target in parseRequestFile(requestFile): 311 | url = target[0] 312 | if url not in seen: 313 | kb.targets.add(target) 314 | if len(kb.targets) > 1: 315 | conf.multipleTargets = True 316 | seen.add(url) 317 | 318 | if url is None: 319 | errMsg = "specified file '%s' " % requestFile 320 | errMsg += "does not contain a usable HTTP request (with parameters)" 321 | raise SqlmapDataException(errMsg) 322 | 323 | if conf.secondReq: 324 | conf.secondReq = safeExpandUser(conf.secondReq) 325 | 326 | if not checkFile(conf.secondReq, False): 327 | errMsg = "specified second-order HTTP request file '%s' " % conf.secondReq 328 | errMsg += "does not exist" 329 | raise SqlmapFilePathException(errMsg) 330 | 331 | infoMsg = "parsing second-order HTTP request from '%s'" % conf.secondReq 332 | logger.info(infoMsg) 333 | 334 | try: 335 | target = next(parseRequestFile(conf.secondReq, False)) 336 | kb.secondReq = target 337 | except StopIteration: 338 | errMsg = "specified second-order HTTP request file '%s' " % conf.secondReq 339 | errMsg += "does not contain a valid HTTP request" 340 | raise SqlmapDataException(errMsg) 341 | 342 | def _setCrawler(): 343 | if not conf.crawlDepth: 344 | return 345 | 346 | if not conf.bulkFile: 347 | if conf.url: 348 | crawl(conf.url) 349 | elif conf.requestFile and kb.targets: 350 | target = next(iter(kb.targets)) 351 | crawl(target[0], target[2], target[3]) 352 | 353 | def _doSearch(): 354 | """ 355 | This function performs search dorking, parses results 356 | and saves the testable hosts into the knowledge base. 357 | """ 358 | 359 | if not conf.googleDork: 360 | return 361 | 362 | kb.data.onlyGETs = None 363 | 364 | def retrieve(): 365 | links = search(conf.googleDork) 366 | 367 | if not links: 368 | errMsg = "unable to find results for your " 369 | errMsg += "search dork expression" 370 | raise SqlmapGenericException(errMsg) 371 | 372 | for link in links: 373 | link = urldecode(link) 374 | if re.search(r"(.*?)\?(.+)", link) or conf.forms: 375 | kb.targets.add((link, conf.method, conf.data, conf.cookie, None)) 376 | elif re.search(URI_INJECTABLE_REGEX, link, re.I): 377 | if kb.data.onlyGETs is None and conf.data is None and not conf.googleDork: 378 | message = "do you want to scan only results containing GET parameters? [Y/n] " 379 | kb.data.onlyGETs = readInput(message, default='Y', boolean=True) 380 | if not kb.data.onlyGETs or conf.googleDork: 381 | kb.targets.add((link, conf.method, conf.data, conf.cookie, None)) 382 | 383 | return links 384 | 385 | while True: 386 | links = retrieve() 387 | 388 | if kb.targets: 389 | infoMsg = "found %d results for your " % len(links) 390 | infoMsg += "search dork expression" 391 | 392 | if not conf.forms: 393 | infoMsg += ", " 394 | 395 | if len(links) == len(kb.targets): 396 | infoMsg += "all " 397 | else: 398 | infoMsg += "%d " % len(kb.targets) 399 | 400 | infoMsg += "of them are testable targets" 401 | 402 | logger.info(infoMsg) 403 | break 404 | 405 | else: 406 | message = "found %d results " % len(links) 407 | message += "for your search dork expression, but none of them " 408 | message += "have GET parameters to test for SQL injection. " 409 | message += "Do you want to skip to the next result page? [Y/n]" 410 | 411 | if not readInput(message, default='Y', boolean=True): 412 | raise SqlmapSilentQuitException 413 | else: 414 | conf.googlePage += 1 415 | 416 | def _setBulkMultipleTargets(): 417 | if not conf.bulkFile: 418 | return 419 | 420 | conf.bulkFile = safeExpandUser(conf.bulkFile) 421 | 422 | infoMsg = "parsing multiple targets list from '%s'" % conf.bulkFile 423 | logger.info(infoMsg) 424 | 425 | if not checkFile(conf.bulkFile, False): 426 | errMsg = "the specified bulk file " 427 | errMsg += "does not exist" 428 | raise SqlmapFilePathException(errMsg) 429 | 430 | found = False 431 | for line in getFileItems(conf.bulkFile): 432 | if conf.scope and not re.search(conf.scope, line, re.I): 433 | continue 434 | 435 | if re.match(r"[^ ]+\?(.+)", line, re.I) or kb.customInjectionMark in line: 436 | found = True 437 | kb.targets.add((line.strip(), conf.method, conf.data, conf.cookie, None)) 438 | 439 | if not found and not conf.forms and not conf.crawlDepth: 440 | warnMsg = "no usable links found (with GET parameters)" 441 | logger.warn(warnMsg) 442 | 443 | def _findPageForms(): 444 | if not conf.forms or conf.crawlDepth: 445 | return 446 | 447 | if conf.url and not checkConnection(): 448 | return 449 | 450 | found = False 451 | infoMsg = "searching for forms" 452 | logger.info(infoMsg) 453 | 454 | if not any((conf.bulkFile, conf.googleDork)): 455 | page, _, _ = Request.queryPage(content=True, ignoreSecondOrder=True) 456 | if findPageForms(page, conf.url, True, True): 457 | found = True 458 | else: 459 | if conf.bulkFile: 460 | targets = getFileItems(conf.bulkFile) 461 | elif conf.googleDork: 462 | targets = [_[0] for _ in kb.targets] 463 | kb.targets.clear() 464 | else: 465 | targets = [] 466 | 467 | for i in xrange(len(targets)): 468 | try: 469 | target = targets[i].strip() 470 | 471 | if not re.search(r"(?i)\Ahttp[s]*://", target): 472 | target = "http://%s" % target 473 | 474 | page, _, _ = Request.getPage(url=target.strip(), cookie=conf.cookie, crawling=True, raise404=False) 475 | if findPageForms(page, target, False, True): 476 | found = True 477 | 478 | if conf.verbose in (1, 2): 479 | status = '%d/%d links visited (%d%%)' % (i + 1, len(targets), round(100.0 * (i + 1) / len(targets))) 480 | dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status), True) 481 | except KeyboardInterrupt: 482 | break 483 | except Exception as ex: 484 | errMsg = "problem occurred while searching for forms at '%s' ('%s')" % (target, getSafeExString(ex)) 485 | logger.error(errMsg) 486 | 487 | if not found: 488 | warnMsg = "no forms found" 489 | logger.warn(warnMsg) 490 | 491 | def _setDBMSAuthentication(): 492 | """ 493 | Check and set the DBMS authentication credentials to run statements as 494 | another user, not the session user 495 | """ 496 | 497 | if not conf.dbmsCred: 498 | return 499 | 500 | debugMsg = "setting the DBMS authentication credentials" 501 | logger.debug(debugMsg) 502 | 503 | match = re.search(r"^(.+?):(.*?)$", conf.dbmsCred) 504 | 505 | if not match: 506 | errMsg = "DBMS authentication credentials value must be in format " 507 | errMsg += "username:password" 508 | raise SqlmapSyntaxException(errMsg) 509 | 510 | conf.dbmsUsername = match.group(1) 511 | conf.dbmsPassword = match.group(2) 512 | 513 | def _setMetasploit(): 514 | if not conf.osPwn and not conf.osSmb and not conf.osBof: 515 | return 516 | 517 | debugMsg = "setting the takeover out-of-band functionality" 518 | logger.debug(debugMsg) 519 | 520 | msfEnvPathExists = False 521 | 522 | if IS_WIN: 523 | try: 524 | __import__("win32file") 525 | except ImportError: 526 | errMsg = "sqlmap requires third-party module 'pywin32' " 527 | errMsg += "in order to use Metasploit functionalities on " 528 | errMsg += "Windows. You can download it from " 529 | errMsg += "'https://github.com/mhammond/pywin32'" 530 | raise SqlmapMissingDependence(errMsg) 531 | 532 | if not conf.msfPath: 533 | for candidate in os.environ.get("PATH", "").split(';'): 534 | if all(_ in candidate for _ in ("metasploit", "bin")): 535 | conf.msfPath = os.path.dirname(candidate.rstrip('\\')) 536 | break 537 | 538 | if conf.osSmb: 539 | isAdmin = runningAsAdmin() 540 | 541 | if not isAdmin: 542 | errMsg = "you need to run sqlmap as an administrator " 543 | errMsg += "if you want to perform a SMB relay attack because " 544 | errMsg += "it will need to listen on a user-specified SMB " 545 | errMsg += "TCP port for incoming connection attempts" 546 | raise SqlmapMissingPrivileges(errMsg) 547 | 548 | if conf.msfPath: 549 | for path in (conf.msfPath, os.path.join(conf.msfPath, "bin")): 550 | if any(os.path.exists(normalizePath(os.path.join(path, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfcli", "msfconsole")): 551 | msfEnvPathExists = True 552 | if all(os.path.exists(normalizePath(os.path.join(path, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfvenom",)): 553 | kb.oldMsf = False 554 | elif all(os.path.exists(normalizePath(os.path.join(path, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfencode", "msfpayload")): 555 | kb.oldMsf = True 556 | else: 557 | msfEnvPathExists = False 558 | 559 | conf.msfPath = path 560 | break 561 | 562 | if msfEnvPathExists: 563 | debugMsg = "provided Metasploit Framework path " 564 | debugMsg += "'%s' is valid" % conf.msfPath 565 | logger.debug(debugMsg) 566 | else: 567 | warnMsg = "the provided Metasploit Framework path " 568 | warnMsg += "'%s' is not valid. The cause could " % conf.msfPath 569 | warnMsg += "be that the path does not exists or that one " 570 | warnMsg += "or more of the needed Metasploit executables " 571 | warnMsg += "within msfcli, msfconsole, msfencode and " 572 | warnMsg += "msfpayload do not exist" 573 | logger.warn(warnMsg) 574 | else: 575 | warnMsg = "you did not provide the local path where Metasploit " 576 | warnMsg += "Framework is installed" 577 | logger.warn(warnMsg) 578 | 579 | if not msfEnvPathExists: 580 | warnMsg = "sqlmap is going to look for Metasploit Framework " 581 | warnMsg += "installation inside the environment path(s)" 582 | logger.warn(warnMsg) 583 | 584 | envPaths = os.environ.get("PATH", "").split(";" if IS_WIN else ":") 585 | 586 | for envPath in envPaths: 587 | envPath = envPath.replace(";", "") 588 | 589 | if any(os.path.exists(normalizePath(os.path.join(envPath, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfcli", "msfconsole")): 590 | msfEnvPathExists = True 591 | if all(os.path.exists(normalizePath(os.path.join(envPath, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfvenom",)): 592 | kb.oldMsf = False 593 | elif all(os.path.exists(normalizePath(os.path.join(envPath, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfencode", "msfpayload")): 594 | kb.oldMsf = True 595 | else: 596 | msfEnvPathExists = False 597 | 598 | if msfEnvPathExists: 599 | infoMsg = "Metasploit Framework has been found " 600 | infoMsg += "installed in the '%s' path" % envPath 601 | logger.info(infoMsg) 602 | 603 | conf.msfPath = envPath 604 | 605 | break 606 | 607 | if not msfEnvPathExists: 608 | errMsg = "unable to locate Metasploit Framework installation. " 609 | errMsg += "You can get it at 'https://www.metasploit.com/download/'" 610 | raise SqlmapFilePathException(errMsg) 611 | 612 | def _setWriteFile(): 613 | if not conf.fileWrite: 614 | return 615 | 616 | debugMsg = "setting the write file functionality" 617 | logger.debug(debugMsg) 618 | 619 | if not os.path.exists(conf.fileWrite): 620 | errMsg = "the provided local file '%s' does not exist" % conf.fileWrite 621 | raise SqlmapFilePathException(errMsg) 622 | 623 | if not conf.fileDest: 624 | errMsg = "you did not provide the back-end DBMS absolute path " 625 | errMsg += "where you want to write the local file '%s'" % conf.fileWrite 626 | raise SqlmapMissingMandatoryOptionException(errMsg) 627 | 628 | conf.fileWriteType = getFileType(conf.fileWrite) 629 | 630 | def _setOS(): 631 | """ 632 | Force the back-end DBMS operating system option. 633 | """ 634 | 635 | if not conf.os: 636 | return 637 | 638 | if conf.os.lower() not in SUPPORTED_OS: 639 | errMsg = "you provided an unsupported back-end DBMS operating " 640 | errMsg += "system. The supported DBMS operating systems for OS " 641 | errMsg += "and file system access are %s. " % ', '.join([o.capitalize() for o in SUPPORTED_OS]) 642 | errMsg += "If you do not know the back-end DBMS underlying OS, " 643 | errMsg += "do not provide it and sqlmap will fingerprint it for " 644 | errMsg += "you." 645 | raise SqlmapUnsupportedDBMSException(errMsg) 646 | 647 | debugMsg = "forcing back-end DBMS operating system to user defined " 648 | debugMsg += "value '%s'" % conf.os 649 | logger.debug(debugMsg) 650 | 651 | Backend.setOs(conf.os) 652 | 653 | def _setTechnique(): 654 | validTechniques = sorted(getPublicTypeMembers(PAYLOAD.TECHNIQUE), key=lambda x: x[1]) 655 | validLetters = [_[0][0].upper() for _ in validTechniques] 656 | 657 | if conf.technique and isinstance(conf.technique, six.string_types): 658 | _ = [] 659 | 660 | for letter in conf.technique.upper(): 661 | if letter not in validLetters: 662 | errMsg = "value for --technique must be a string composed " 663 | errMsg += "by the letters %s. Refer to the " % ", ".join(validLetters) 664 | errMsg += "user's manual for details" 665 | raise SqlmapSyntaxException(errMsg) 666 | 667 | for validTech, validInt in validTechniques: 668 | if letter == validTech[0]: 669 | _.append(validInt) 670 | break 671 | 672 | conf.technique = _ 673 | 674 | def _setDBMS(): 675 | """ 676 | Force the back-end DBMS option. 677 | """ 678 | 679 | if not conf.dbms: 680 | return 681 | 682 | debugMsg = "forcing back-end DBMS to user defined value" 683 | logger.debug(debugMsg) 684 | 685 | conf.dbms = conf.dbms.lower() 686 | regex = re.search(r"%s ([\d\.]+)" % ("(%s)" % "|".join(SUPPORTED_DBMS)), conf.dbms, re.I) 687 | 688 | if regex: 689 | conf.dbms = regex.group(1) 690 | Backend.setVersion(regex.group(2)) 691 | 692 | if conf.dbms not in SUPPORTED_DBMS: 693 | errMsg = "you provided an unsupported back-end database management " 694 | errMsg += "system. Supported DBMSes are as follows: %s. " % ', '.join(sorted(_ for _ in DBMS_DICT)) 695 | errMsg += "If you do not know the back-end DBMS, do not provide " 696 | errMsg += "it and sqlmap will fingerprint it for you." 697 | raise SqlmapUnsupportedDBMSException(errMsg) 698 | 699 | for dbms, aliases in DBMS_ALIASES: 700 | if conf.dbms in aliases: 701 | conf.dbms = dbms 702 | 703 | break 704 | 705 | def _listTamperingFunctions(): 706 | """ 707 | Lists available tamper functions 708 | """ 709 | 710 | if conf.listTampers: 711 | infoMsg = "listing available tamper scripts\n" 712 | logger.info(infoMsg) 713 | 714 | for script in sorted(glob.glob(os.path.join(paths.SQLMAP_TAMPER_PATH, "*.py"))): 715 | content = openFile(script, "rb").read() 716 | match = re.search(r'(?s)__priority__.+"""(.+)"""', content) 717 | if match: 718 | comment = match.group(1).strip() 719 | dataToStdout("* %s - %s\n" % (setColor(os.path.basename(script), "yellow"), re.sub(r" *\n *", " ", comment.split("\n\n")[0].strip()))) 720 | 721 | def _setTamperingFunctions(): 722 | """ 723 | Loads tampering functions from given script(s) 724 | """ 725 | 726 | if conf.tamper: 727 | last_priority = PRIORITY.HIGHEST 728 | check_priority = True 729 | resolve_priorities = False 730 | priorities = [] 731 | 732 | for script in re.split(PARAMETER_SPLITTING_REGEX, conf.tamper): 733 | found = False 734 | 735 | path = safeFilepathEncode(paths.SQLMAP_TAMPER_PATH) 736 | script = safeFilepathEncode(script.strip()) 737 | 738 | try: 739 | if not script: 740 | continue 741 | 742 | elif os.path.exists(os.path.join(path, script if script.endswith(".py") else "%s.py" % script)): 743 | script = os.path.join(path, script if script.endswith(".py") else "%s.py" % script) 744 | 745 | elif not os.path.exists(script): 746 | errMsg = "tamper script '%s' does not exist" % script 747 | raise SqlmapFilePathException(errMsg) 748 | 749 | elif not script.endswith(".py"): 750 | errMsg = "tamper script '%s' should have an extension '.py'" % script 751 | raise SqlmapSyntaxException(errMsg) 752 | except UnicodeDecodeError: 753 | errMsg = "invalid character provided in option '--tamper'" 754 | raise SqlmapSyntaxException(errMsg) 755 | 756 | dirname, filename = os.path.split(script) 757 | dirname = os.path.abspath(dirname) 758 | 759 | infoMsg = "loading tamper module '%s'" % filename[:-3] 760 | logger.info(infoMsg) 761 | 762 | if not os.path.exists(os.path.join(dirname, "__init__.py")): 763 | errMsg = "make sure that there is an empty file '__init__.py' " 764 | errMsg += "inside of tamper scripts directory '%s'" % dirname 765 | raise SqlmapGenericException(errMsg) 766 | 767 | if dirname not in sys.path: 768 | sys.path.insert(0, dirname) 769 | 770 | try: 771 | module = __import__(safeFilepathEncode(filename[:-3])) 772 | except Exception as ex: 773 | raise SqlmapSyntaxException("cannot import tamper module '%s' (%s)" % (getUnicode(filename[:-3]), getSafeExString(ex))) 774 | 775 | priority = PRIORITY.NORMAL if not hasattr(module, "__priority__") else module.__priority__ 776 | 777 | for name, function in inspect.getmembers(module, inspect.isfunction): 778 | if name == "tamper" and inspect.getargspec(function).args and inspect.getargspec(function).keywords == "kwargs": 779 | found = True 780 | kb.tamperFunctions.append(function) 781 | function.__name__ = module.__name__ 782 | 783 | if check_priority and priority > last_priority: 784 | message = "it appears that you might have mixed " 785 | message += "the order of tamper scripts. " 786 | message += "Do you want to auto resolve this? [Y/n/q] " 787 | choice = readInput(message, default='Y').upper() 788 | 789 | if choice == 'N': 790 | resolve_priorities = False 791 | elif choice == 'Q': 792 | raise SqlmapUserQuitException 793 | else: 794 | resolve_priorities = True 795 | 796 | check_priority = False 797 | 798 | priorities.append((priority, function)) 799 | last_priority = priority 800 | 801 | break 802 | elif name == "dependencies": 803 | try: 804 | function() 805 | except Exception as ex: 806 | errMsg = "error occurred while checking dependencies " 807 | errMsg += "for tamper module '%s' ('%s')" % (getUnicode(filename[:-3]), getSafeExString(ex)) 808 | raise SqlmapGenericException(errMsg) 809 | 810 | if not found: 811 | errMsg = "missing function 'tamper(payload, **kwargs)' " 812 | errMsg += "in tamper script '%s'" % script 813 | raise SqlmapGenericException(errMsg) 814 | 815 | if kb.tamperFunctions and len(kb.tamperFunctions) > 3: 816 | warnMsg = "using too many tamper scripts is usually not " 817 | warnMsg += "a good idea" 818 | logger.warning(warnMsg) 819 | 820 | if resolve_priorities and priorities: 821 | priorities.sort(key=functools.cmp_to_key(lambda a, b: cmp(a[0], b[0])), reverse=True) 822 | kb.tamperFunctions = [] 823 | 824 | for _, function in priorities: 825 | kb.tamperFunctions.append(function) 826 | 827 | def _setPreprocessFunctions(): 828 | """ 829 | Loads preprocess functions from given script(s) 830 | """ 831 | 832 | if conf.preprocess: 833 | for script in re.split(PARAMETER_SPLITTING_REGEX, conf.preprocess): 834 | found = False 835 | function = None 836 | 837 | script = safeFilepathEncode(script.strip()) 838 | 839 | try: 840 | if not script: 841 | continue 842 | 843 | if not os.path.exists(script): 844 | errMsg = "preprocess script '%s' does not exist" % script 845 | raise SqlmapFilePathException(errMsg) 846 | 847 | elif not script.endswith(".py"): 848 | errMsg = "preprocess script '%s' should have an extension '.py'" % script 849 | raise SqlmapSyntaxException(errMsg) 850 | except UnicodeDecodeError: 851 | errMsg = "invalid character provided in option '--preprocess'" 852 | raise SqlmapSyntaxException(errMsg) 853 | 854 | dirname, filename = os.path.split(script) 855 | dirname = os.path.abspath(dirname) 856 | 857 | infoMsg = "loading preprocess module '%s'" % filename[:-3] 858 | logger.info(infoMsg) 859 | 860 | if not os.path.exists(os.path.join(dirname, "__init__.py")): 861 | errMsg = "make sure that there is an empty file '__init__.py' " 862 | errMsg += "inside of preprocess scripts directory '%s'" % dirname 863 | raise SqlmapGenericException(errMsg) 864 | 865 | if dirname not in sys.path: 866 | sys.path.insert(0, dirname) 867 | 868 | try: 869 | module = __import__(safeFilepathEncode(filename[:-3])) 870 | except Exception as ex: 871 | raise SqlmapSyntaxException("cannot import preprocess module '%s' (%s)" % (getUnicode(filename[:-3]), getSafeExString(ex))) 872 | 873 | for name, function in inspect.getmembers(module, inspect.isfunction): 874 | if name == "preprocess" and inspect.getargspec(function).args and all(_ in inspect.getargspec(function).args for _ in ("page", "headers", "code")): 875 | found = True 876 | 877 | kb.preprocessFunctions.append(function) 878 | function.__name__ = module.__name__ 879 | 880 | break 881 | 882 | if not found: 883 | errMsg = "missing function 'preprocess(page, headers=None, code=None)' " 884 | errMsg += "in preprocess script '%s'" % script 885 | raise SqlmapGenericException(errMsg) 886 | else: 887 | try: 888 | _, _, _ = function("", {}, None) 889 | except: 890 | handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.PREPROCESS, suffix=".py") 891 | os.close(handle) 892 | 893 | open(filename, "w+b").write("#!/usr/bin/env\n\ndef preprocess(page, headers=None, code=None):\n return page, headers, code\n") 894 | open(os.path.join(os.path.dirname(filename), "__init__.py"), "w+b").write("pass") 895 | 896 | errMsg = "function 'preprocess(page, headers=None, code=None)' " 897 | errMsg += "in preprocess script '%s' " % script 898 | errMsg += "should return a tuple '(page, headers, code)' " 899 | errMsg += "(Note: find template script at '%s')" % filename 900 | raise SqlmapGenericException(errMsg) 901 | 902 | def _setThreads(): 903 | if not isinstance(conf.threads, int) or conf.threads <= 0: 904 | conf.threads = 1 905 | 906 | def _setDNSCache(): 907 | """ 908 | Makes a cached version of socket._getaddrinfo to avoid subsequent DNS requests. 909 | """ 910 | 911 | def _getaddrinfo(*args, **kwargs): 912 | if args in kb.cache.addrinfo: 913 | return kb.cache.addrinfo[args] 914 | 915 | else: 916 | kb.cache.addrinfo[args] = socket._getaddrinfo(*args, **kwargs) 917 | return kb.cache.addrinfo[args] 918 | 919 | if not hasattr(socket, "_getaddrinfo"): 920 | socket._getaddrinfo = socket.getaddrinfo 921 | socket.getaddrinfo = _getaddrinfo 922 | 923 | def _setSocketPreConnect(): 924 | """ 925 | Makes a pre-connect version of socket.create_connection 926 | """ 927 | 928 | if conf.disablePrecon: 929 | return 930 | 931 | def _thread(): 932 | while kb.get("threadContinue") and not conf.get("disablePrecon"): 933 | try: 934 | for key in socket._ready: 935 | if len(socket._ready[key]) < SOCKET_PRE_CONNECT_QUEUE_SIZE: 936 | s = socket.create_connection(*key[0], **dict(key[1])) 937 | with kb.locks.socket: 938 | socket._ready[key].append((s, time.time())) 939 | except KeyboardInterrupt: 940 | break 941 | except: 942 | pass 943 | finally: 944 | time.sleep(0.01) 945 | 946 | def create_connection(*args, **kwargs): 947 | retVal = None 948 | 949 | key = (tuple(args), frozenset(kwargs.items())) 950 | with kb.locks.socket: 951 | if key not in socket._ready: 952 | socket._ready[key] = [] 953 | 954 | while len(socket._ready[key]) > 0: 955 | candidate, created = socket._ready[key].pop(0) 956 | if (time.time() - created) < PRECONNECT_CANDIDATE_TIMEOUT: 957 | retVal = candidate 958 | break 959 | else: 960 | try: 961 | candidate.shutdown(socket.SHUT_RDWR) 962 | candidate.close() 963 | except socket.error: 964 | pass 965 | 966 | if not retVal: 967 | retVal = socket._create_connection(*args, **kwargs) 968 | 969 | return retVal 970 | 971 | if not hasattr(socket, "_create_connection"): 972 | socket._ready = {} 973 | socket._create_connection = socket.create_connection 974 | socket.create_connection = create_connection 975 | 976 | thread = threading.Thread(target=_thread) 977 | setDaemon(thread) 978 | thread.start() 979 | 980 | def _setHTTPHandlers(): 981 | """ 982 | Check and set the HTTP/SOCKS proxy for all HTTP requests. 983 | """ 984 | 985 | with kb.locks.handlers: 986 | if conf.proxyList is not None: 987 | conf.proxy = conf.proxyList[0] 988 | conf.proxyList = conf.proxyList[1:] + conf.proxyList[:1] 989 | 990 | if len(conf.proxyList) > 1: 991 | infoMsg = "loading proxy '%s' from a supplied proxy list file" % conf.proxy 992 | logger.info(infoMsg) 993 | 994 | elif not conf.proxy: 995 | if conf.hostname in ("localhost", "127.0.0.1") or conf.ignoreProxy: 996 | proxyHandler.proxies = {} 997 | 998 | if conf.proxy: 999 | debugMsg = "setting the HTTP/SOCKS proxy for all HTTP requests" 1000 | logger.debug(debugMsg) 1001 | 1002 | try: 1003 | _ = _urllib.parse.urlsplit(conf.proxy) 1004 | except Exception as ex: 1005 | errMsg = "invalid proxy address '%s' ('%s')" % (conf.proxy, getSafeExString(ex)) 1006 | raise SqlmapSyntaxException(errMsg) 1007 | 1008 | hostnamePort = _.netloc.rsplit(":", 1) 1009 | 1010 | scheme = _.scheme.upper() 1011 | hostname = hostnamePort[0] 1012 | port = None 1013 | username = None 1014 | password = None 1015 | 1016 | if len(hostnamePort) == 2: 1017 | try: 1018 | port = int(hostnamePort[1]) 1019 | except: 1020 | pass # drops into the next check block 1021 | 1022 | if not all((scheme, hasattr(PROXY_TYPE, scheme), hostname, port)): 1023 | errMsg = "proxy value must be in format '(%s)://address:port'" % "|".join(_[0].lower() for _ in getPublicTypeMembers(PROXY_TYPE)) 1024 | raise SqlmapSyntaxException(errMsg) 1025 | 1026 | if conf.proxyCred: 1027 | _ = re.search(r"\A(.*?):(.*?)\Z", conf.proxyCred) 1028 | if not _: 1029 | errMsg = "proxy authentication credentials " 1030 | errMsg += "value must be in format username:password" 1031 | raise SqlmapSyntaxException(errMsg) 1032 | else: 1033 | username = _.group(1) 1034 | password = _.group(2) 1035 | 1036 | if scheme in (PROXY_TYPE.SOCKS4, PROXY_TYPE.SOCKS5): 1037 | proxyHandler.proxies = {} 1038 | 1039 | if scheme == PROXY_TYPE.SOCKS4: 1040 | warnMsg = "SOCKS4 does not support resolving (DNS) names (i.e. causing DNS leakage)" 1041 | singleTimeWarnMessage(warnMsg) 1042 | 1043 | socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5 if scheme == PROXY_TYPE.SOCKS5 else socks.PROXY_TYPE_SOCKS4, hostname, port, username=username, password=password) 1044 | socks.wrapmodule(_http_client) 1045 | else: 1046 | socks.unwrapmodule(_http_client) 1047 | 1048 | if conf.proxyCred: 1049 | # Reference: http://stackoverflow.com/questions/34079/how-to-specify-an-authenticated-proxy-for-a-python-http-connection 1050 | proxyString = "%s@" % conf.proxyCred 1051 | else: 1052 | proxyString = "" 1053 | 1054 | proxyString += "%s:%d" % (hostname, port) 1055 | proxyHandler.proxies = {"http": proxyString, "https": proxyString} 1056 | 1057 | proxyHandler.__init__(proxyHandler.proxies) 1058 | 1059 | if not proxyHandler.proxies: 1060 | for _ in ("http", "https"): 1061 | if hasattr(proxyHandler, "%s_open" % _): 1062 | delattr(proxyHandler, "%s_open" % _) 1063 | 1064 | debugMsg = "creating HTTP requests opener object" 1065 | logger.debug(debugMsg) 1066 | 1067 | handlers = filterNone([multipartPostHandler, proxyHandler if proxyHandler.proxies else None, authHandler, redirectHandler, rangeHandler, chunkedHandler if conf.chunked else None, httpsHandler]) 1068 | 1069 | if not conf.dropSetCookie: 1070 | if not conf.loadCookies: 1071 | conf.cj = _http_cookiejar.CookieJar() 1072 | else: 1073 | conf.cj = _http_cookiejar.MozillaCookieJar() 1074 | resetCookieJar(conf.cj) 1075 | 1076 | handlers.append(_urllib.request.HTTPCookieProcessor(conf.cj)) 1077 | 1078 | # Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html 1079 | if conf.keepAlive: 1080 | warnMsg = "persistent HTTP(s) connections, Keep-Alive, has " 1081 | warnMsg += "been disabled because of its incompatibility " 1082 | 1083 | if conf.proxy: 1084 | warnMsg += "with HTTP(s) proxy" 1085 | logger.warn(warnMsg) 1086 | elif conf.authType: 1087 | warnMsg += "with authentication methods" 1088 | logger.warn(warnMsg) 1089 | else: 1090 | handlers.append(keepAliveHandler) 1091 | 1092 | opener = _urllib.request.build_opener(*handlers) 1093 | opener.addheaders = [] # Note: clearing default "User-Agent: Python-urllib/X.Y" 1094 | _urllib.request.install_opener(opener) 1095 | 1096 | def _setSafeVisit(): 1097 | """ 1098 | Check and set the safe visit options. 1099 | """ 1100 | if not any((conf.safeUrl, conf.safeReqFile)): 1101 | return 1102 | 1103 | if conf.safeReqFile: 1104 | checkFile(conf.safeReqFile) 1105 | 1106 | raw = readCachedFileContent(conf.safeReqFile) 1107 | match = re.search(r"\A([A-Z]+) ([^ ]+) HTTP/[0-9.]+\Z", raw.split('\n')[0].strip()) 1108 | 1109 | if match: 1110 | kb.safeReq.method = match.group(1) 1111 | kb.safeReq.url = match.group(2) 1112 | kb.safeReq.headers = {} 1113 | 1114 | for line in raw.split('\n')[1:]: 1115 | line = line.strip() 1116 | if line and ':' in line: 1117 | key, value = line.split(':', 1) 1118 | value = value.strip() 1119 | kb.safeReq.headers[key] = value 1120 | if key.upper() == HTTP_HEADER.HOST.upper(): 1121 | if not value.startswith("http"): 1122 | scheme = "http" 1123 | if value.endswith(":443"): 1124 | scheme = "https" 1125 | value = "%s://%s" % (scheme, value) 1126 | kb.safeReq.url = _urllib.parse.urljoin(value, kb.safeReq.url) 1127 | else: 1128 | break 1129 | 1130 | post = None 1131 | 1132 | if '\r\n\r\n' in raw: 1133 | post = raw[raw.find('\r\n\r\n') + 4:] 1134 | elif '\n\n' in raw: 1135 | post = raw[raw.find('\n\n') + 2:] 1136 | 1137 | if post and post.strip(): 1138 | kb.safeReq.post = post 1139 | else: 1140 | kb.safeReq.post = None 1141 | else: 1142 | errMsg = "invalid format of a safe request file" 1143 | raise SqlmapSyntaxException(errMsg) 1144 | else: 1145 | if not re.search(r"(?i)\Ahttp[s]*://", conf.safeUrl): 1146 | if ":443/" in conf.safeUrl: 1147 | conf.safeUrl = "https://%s" % conf.safeUrl 1148 | else: 1149 | conf.safeUrl = "http://%s" % conf.safeUrl 1150 | 1151 | if (conf.safeFreq or 0) <= 0: 1152 | errMsg = "please provide a valid value (>0) for safe frequency ('--safe-freq') while using safe visit features" 1153 | raise SqlmapSyntaxException(errMsg) 1154 | 1155 | def _setPrefixSuffix(): 1156 | if conf.prefix is not None and conf.suffix is not None: 1157 | # Create a custom boundary object for user's supplied prefix 1158 | # and suffix 1159 | boundary = AttribDict() 1160 | 1161 | boundary.level = 1 1162 | boundary.clause = [0] 1163 | boundary.where = [1, 2, 3] 1164 | boundary.prefix = conf.prefix 1165 | boundary.suffix = conf.suffix 1166 | 1167 | if " like" in boundary.suffix.lower(): 1168 | if "'" in boundary.suffix.lower(): 1169 | boundary.ptype = 3 1170 | elif '"' in boundary.suffix.lower(): 1171 | boundary.ptype = 5 1172 | elif "'" in boundary.suffix: 1173 | boundary.ptype = 2 1174 | elif '"' in boundary.suffix: 1175 | boundary.ptype = 4 1176 | else: 1177 | boundary.ptype = 1 1178 | 1179 | # user who provides --prefix/--suffix does not want other boundaries 1180 | # to be tested for 1181 | conf.boundaries = [boundary] 1182 | 1183 | def _setAuthCred(): 1184 | """ 1185 | Adds authentication credentials (if any) for current target to the password manager 1186 | (used by connection handler) 1187 | """ 1188 | 1189 | if kb.passwordMgr and all(_ is not None for _ in (conf.scheme, conf.hostname, conf.port, conf.authUsername, conf.authPassword)): 1190 | kb.passwordMgr.add_password(None, "%s://%s:%d" % (conf.scheme, conf.hostname, conf.port), conf.authUsername, conf.authPassword) 1191 | 1192 | def _setHTTPAuthentication(): 1193 | """ 1194 | Check and set the HTTP(s) authentication method (Basic, Digest, NTLM or PKI), 1195 | username and password for first three methods, or PEM private key file for 1196 | PKI authentication 1197 | """ 1198 | 1199 | global authHandler 1200 | 1201 | if not conf.authType and not conf.authCred and not conf.authFile: 1202 | return 1203 | 1204 | if conf.authFile and not conf.authType: 1205 | conf.authType = AUTH_TYPE.PKI 1206 | 1207 | elif conf.authType and not conf.authCred and not conf.authFile: 1208 | errMsg = "you specified the HTTP authentication type, but " 1209 | errMsg += "did not provide the credentials" 1210 | raise SqlmapSyntaxException(errMsg) 1211 | 1212 | elif not conf.authType and conf.authCred: 1213 | errMsg = "you specified the HTTP authentication credentials, " 1214 | errMsg += "but did not provide the type (e.g. --auth-type=\"basic\")" 1215 | raise SqlmapSyntaxException(errMsg) 1216 | 1217 | elif (conf.authType or "").lower() not in (AUTH_TYPE.BASIC, AUTH_TYPE.DIGEST, AUTH_TYPE.NTLM, AUTH_TYPE.PKI): 1218 | errMsg = "HTTP authentication type value must be " 1219 | errMsg += "Basic, Digest, NTLM or PKI" 1220 | raise SqlmapSyntaxException(errMsg) 1221 | 1222 | if not conf.authFile: 1223 | debugMsg = "setting the HTTP authentication type and credentials" 1224 | logger.debug(debugMsg) 1225 | 1226 | authType = conf.authType.lower() 1227 | 1228 | if authType in (AUTH_TYPE.BASIC, AUTH_TYPE.DIGEST): 1229 | regExp = "^(.*?):(.*?)$" 1230 | errMsg = "HTTP %s authentication credentials " % authType 1231 | errMsg += "value must be in format 'username:password'" 1232 | elif authType == AUTH_TYPE.NTLM: 1233 | regExp = "^(.*\\\\.*):(.*?)$" 1234 | errMsg = "HTTP NTLM authentication credentials value must " 1235 | errMsg += "be in format 'DOMAIN\\username:password'" 1236 | elif authType == AUTH_TYPE.PKI: 1237 | errMsg = "HTTP PKI authentication require " 1238 | errMsg += "usage of option `--auth-pki`" 1239 | raise SqlmapSyntaxException(errMsg) 1240 | 1241 | aCredRegExp = re.search(regExp, conf.authCred) 1242 | 1243 | if not aCredRegExp: 1244 | raise SqlmapSyntaxException(errMsg) 1245 | 1246 | conf.authUsername = aCredRegExp.group(1) 1247 | conf.authPassword = aCredRegExp.group(2) 1248 | 1249 | kb.passwordMgr = _urllib.request.HTTPPasswordMgrWithDefaultRealm() 1250 | 1251 | _setAuthCred() 1252 | 1253 | if authType == AUTH_TYPE.BASIC: 1254 | authHandler = SmartHTTPBasicAuthHandler(kb.passwordMgr) 1255 | 1256 | elif authType == AUTH_TYPE.DIGEST: 1257 | authHandler = _urllib.request.HTTPDigestAuthHandler(kb.passwordMgr) 1258 | 1259 | elif authType == AUTH_TYPE.NTLM: 1260 | try: 1261 | from ntlm import HTTPNtlmAuthHandler 1262 | except ImportError: 1263 | errMsg = "sqlmap requires Python NTLM third-party library " 1264 | errMsg += "in order to authenticate via NTLM. Download from " 1265 | errMsg += "'https://github.com/mullender/python-ntlm'" 1266 | raise SqlmapMissingDependence(errMsg) 1267 | 1268 | authHandler = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(kb.passwordMgr) 1269 | else: 1270 | debugMsg = "setting the HTTP(s) authentication PEM private key" 1271 | logger.debug(debugMsg) 1272 | 1273 | _ = safeExpandUser(conf.authFile) 1274 | checkFile(_) 1275 | authHandler = HTTPSPKIAuthHandler(_) 1276 | 1277 | def _setHTTPExtraHeaders(): 1278 | if conf.headers: 1279 | debugMsg = "setting extra HTTP headers" 1280 | logger.debug(debugMsg) 1281 | 1282 | conf.headers = conf.headers.split("\n") if "\n" in conf.headers else conf.headers.split("\\n") 1283 | 1284 | for headerValue in conf.headers: 1285 | if not headerValue.strip(): 1286 | continue 1287 | 1288 | if headerValue.count(':') >= 1: 1289 | header, value = (_.lstrip() for _ in headerValue.split(":", 1)) 1290 | 1291 | if header and value: 1292 | conf.httpHeaders.append((header, value)) 1293 | elif headerValue.startswith('@'): 1294 | checkFile(headerValue[1:]) 1295 | kb.headersFile = headerValue[1:] 1296 | else: 1297 | errMsg = "invalid header value: %s. Valid header format is 'name:value'" % repr(headerValue).lstrip('u') 1298 | raise SqlmapSyntaxException(errMsg) 1299 | 1300 | elif not conf.requestFile and len(conf.httpHeaders or []) < 2: 1301 | if conf.encoding: 1302 | conf.httpHeaders.append((HTTP_HEADER.ACCEPT_CHARSET, "%s;q=0.7,*;q=0.1" % conf.encoding)) 1303 | 1304 | # Invalidating any caching mechanism in between 1305 | # Reference: http://stackoverflow.com/a/1383359 1306 | conf.httpHeaders.append((HTTP_HEADER.CACHE_CONTROL, "no-cache")) 1307 | 1308 | def _setHTTPUserAgent(): 1309 | """ 1310 | Set the HTTP User-Agent header. 1311 | Depending on the user options it can be: 1312 | 1313 | * The default sqlmap string 1314 | * A default value read as user option 1315 | * A random value read from a list of User-Agent headers from a 1316 | file choosed as user option 1317 | """ 1318 | 1319 | debugMsg = "setting the HTTP User-Agent header" 1320 | logger.debug(debugMsg) 1321 | 1322 | if conf.mobile: 1323 | if conf.randomAgent: 1324 | _ = random.sample([_[1] for _ in getPublicTypeMembers(MOBILES, True)], 1)[0] 1325 | conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, _)) 1326 | else: 1327 | message = "which smartphone do you want sqlmap to imitate " 1328 | message += "through HTTP User-Agent header?\n" 1329 | items = sorted(getPublicTypeMembers(MOBILES, True)) 1330 | 1331 | for count in xrange(len(items)): 1332 | item = items[count] 1333 | message += "[%d] %s%s\n" % (count + 1, item[0], " (default)" if item == MOBILES.IPHONE else "") 1334 | 1335 | test = readInput(message.rstrip('\n'), default=items.index(MOBILES.IPHONE) + 1) 1336 | 1337 | try: 1338 | item = items[int(test) - 1] 1339 | except: 1340 | item = MOBILES.IPHONE 1341 | 1342 | conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, item[1])) 1343 | 1344 | elif conf.agent: 1345 | conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, conf.agent)) 1346 | 1347 | elif not conf.randomAgent: 1348 | _ = True 1349 | 1350 | for header, _ in conf.httpHeaders: 1351 | if header.upper() == HTTP_HEADER.USER_AGENT.upper(): 1352 | _ = False 1353 | break 1354 | 1355 | if _: 1356 | conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, DEFAULT_USER_AGENT)) 1357 | 1358 | else: 1359 | userAgent = fetchRandomAgent() 1360 | 1361 | infoMsg = "fetched random HTTP User-Agent header value '%s' from " % userAgent 1362 | infoMsg += "file '%s'" % paths.USER_AGENTS 1363 | logger.info(infoMsg) 1364 | 1365 | conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, userAgent)) 1366 | 1367 | def _setHTTPReferer(): 1368 | """ 1369 | Set the HTTP Referer 1370 | """ 1371 | 1372 | if conf.referer: 1373 | debugMsg = "setting the HTTP Referer header" 1374 | logger.debug(debugMsg) 1375 | 1376 | conf.httpHeaders.append((HTTP_HEADER.REFERER, conf.referer)) 1377 | 1378 | def _setHTTPHost(): 1379 | """ 1380 | Set the HTTP Host 1381 | """ 1382 | 1383 | if conf.host: 1384 | debugMsg = "setting the HTTP Host header" 1385 | logger.debug(debugMsg) 1386 | 1387 | conf.httpHeaders.append((HTTP_HEADER.HOST, conf.host)) 1388 | 1389 | def _setHTTPCookies(): 1390 | """ 1391 | Set the HTTP Cookie header 1392 | """ 1393 | 1394 | if conf.cookie: 1395 | debugMsg = "setting the HTTP Cookie header" 1396 | logger.debug(debugMsg) 1397 | 1398 | conf.httpHeaders.append((HTTP_HEADER.COOKIE, conf.cookie)) 1399 | 1400 | def _setHostname(): 1401 | """ 1402 | Set value conf.hostname 1403 | """ 1404 | 1405 | if conf.url: 1406 | try: 1407 | conf.hostname = _urllib.parse.urlsplit(conf.url).netloc.split(':')[0] 1408 | except ValueError as ex: 1409 | errMsg = "problem occurred while " 1410 | errMsg += "parsing an URL '%s' ('%s')" % (conf.url, getSafeExString(ex)) 1411 | raise SqlmapDataException(errMsg) 1412 | 1413 | def _setHTTPTimeout(): 1414 | """ 1415 | Set the HTTP timeout 1416 | """ 1417 | 1418 | if conf.timeout: 1419 | debugMsg = "setting the HTTP timeout" 1420 | logger.debug(debugMsg) 1421 | 1422 | conf.timeout = float(conf.timeout) 1423 | 1424 | if conf.timeout < 3.0: 1425 | warnMsg = "the minimum HTTP timeout is 3 seconds, sqlmap " 1426 | warnMsg += "will going to reset it" 1427 | logger.warn(warnMsg) 1428 | 1429 | conf.timeout = 3.0 1430 | else: 1431 | conf.timeout = 30.0 1432 | 1433 | try: 1434 | socket.setdefaulttimeout(conf.timeout) 1435 | except OverflowError as ex: 1436 | raise SqlmapValueException("invalid value used for option '--timeout' ('%s')" % getSafeExString(ex)) 1437 | 1438 | def _checkDependencies(): 1439 | """ 1440 | Checks for missing dependencies. 1441 | """ 1442 | 1443 | if conf.dependencies: 1444 | checkDependencies() 1445 | 1446 | def _createHomeDirectories(): 1447 | """ 1448 | Creates directories inside sqlmap's home directory 1449 | """ 1450 | 1451 | if conf.get("purge"): 1452 | return 1453 | 1454 | for context in "output", "history": 1455 | directory = paths["SQLMAP_%s_PATH" % context.upper()] 1456 | try: 1457 | if not os.path.isdir(directory): 1458 | os.makedirs(directory) 1459 | 1460 | _ = os.path.join(directory, randomStr()) 1461 | open(_, "w+b").close() 1462 | os.remove(_) 1463 | 1464 | if conf.get("outputDir") and context == "output": 1465 | warnMsg = "using '%s' as the %s directory" % (directory, context) 1466 | logger.warn(warnMsg) 1467 | except (OSError, IOError) as ex: 1468 | tempDir = tempfile.mkdtemp(prefix="sqlmap%s" % context) 1469 | warnMsg = "unable to %s %s directory " % ("create" if not os.path.isdir(directory) else "write to the", context) 1470 | warnMsg += "'%s' (%s). " % (directory, getUnicode(ex)) 1471 | warnMsg += "Using temporary directory '%s' instead" % getUnicode(tempDir) 1472 | logger.warn(warnMsg) 1473 | 1474 | paths["SQLMAP_%s_PATH" % context.upper()] = tempDir 1475 | 1476 | def _pympTempLeakPatch(tempDir): # Cross-referenced function 1477 | raise NotImplementedError 1478 | 1479 | def _createTemporaryDirectory(): 1480 | """ 1481 | Creates temporary directory for this run. 1482 | """ 1483 | 1484 | if conf.tmpDir: 1485 | try: 1486 | if not os.path.isdir(conf.tmpDir): 1487 | os.makedirs(conf.tmpDir) 1488 | 1489 | _ = os.path.join(conf.tmpDir, randomStr()) 1490 | 1491 | open(_, "w+b").close() 1492 | os.remove(_) 1493 | 1494 | tempfile.tempdir = conf.tmpDir 1495 | 1496 | warnMsg = "using '%s' as the temporary directory" % conf.tmpDir 1497 | logger.warn(warnMsg) 1498 | except (OSError, IOError) as ex: 1499 | errMsg = "there has been a problem while accessing " 1500 | errMsg += "temporary directory location(s) ('%s')" % getSafeExString(ex) 1501 | raise SqlmapSystemException(errMsg) 1502 | else: 1503 | try: 1504 | if not os.path.isdir(tempfile.gettempdir()): 1505 | os.makedirs(tempfile.gettempdir()) 1506 | except Exception as ex: 1507 | warnMsg = "there has been a problem while accessing " 1508 | warnMsg += "system's temporary directory location(s) ('%s'). Please " % getSafeExString(ex) 1509 | warnMsg += "make sure that there is enough disk space left. If problem persists, " 1510 | warnMsg += "try to set environment variable 'TEMP' to a location " 1511 | warnMsg += "writeable by the current user" 1512 | logger.warn(warnMsg) 1513 | 1514 | if "sqlmap" not in (tempfile.tempdir or "") or conf.tmpDir and tempfile.tempdir == conf.tmpDir: 1515 | try: 1516 | tempfile.tempdir = tempfile.mkdtemp(prefix="sqlmap", suffix=str(os.getpid())) 1517 | except: 1518 | tempfile.tempdir = os.path.join(paths.SQLMAP_HOME_PATH, "tmp", "sqlmap%s%d" % (randomStr(6), os.getpid())) 1519 | 1520 | kb.tempDir = tempfile.tempdir 1521 | 1522 | if not os.path.isdir(tempfile.tempdir): 1523 | try: 1524 | os.makedirs(tempfile.tempdir) 1525 | except Exception as ex: 1526 | errMsg = "there has been a problem while setting " 1527 | errMsg += "temporary directory location ('%s')" % getSafeExString(ex) 1528 | raise SqlmapSystemException(errMsg) 1529 | 1530 | if six.PY3: 1531 | _pympTempLeakPatch(kb.tempDir) 1532 | 1533 | def _cleanupOptions(): 1534 | """ 1535 | Cleanup configuration attributes. 1536 | """ 1537 | 1538 | if conf.encoding: 1539 | try: 1540 | codecs.lookup(conf.encoding) 1541 | except LookupError: 1542 | errMsg = "unknown encoding '%s'" % conf.encoding 1543 | raise SqlmapValueException(errMsg) 1544 | 1545 | debugMsg = "cleaning up configuration parameters" 1546 | logger.debug(debugMsg) 1547 | 1548 | width = getConsoleWidth() 1549 | 1550 | if conf.eta: 1551 | conf.progressWidth = width - 26 1552 | else: 1553 | conf.progressWidth = width - 46 1554 | 1555 | for key, value in conf.items(): 1556 | if value and any(key.endswith(_) for _ in ("Path", "File", "Dir")): 1557 | conf[key] = safeExpandUser(value) 1558 | 1559 | if conf.testParameter: 1560 | conf.testParameter = urldecode(conf.testParameter) 1561 | conf.testParameter = [_.strip() for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.testParameter)] 1562 | else: 1563 | conf.testParameter = [] 1564 | 1565 | if conf.ignoreCode: 1566 | if conf.ignoreCode == IGNORE_CODE_WILDCARD: 1567 | conf.ignoreCode = xrange(0, 1000) 1568 | else: 1569 | try: 1570 | conf.ignoreCode = [int(_) for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.ignoreCode)] 1571 | except ValueError: 1572 | errMsg = "options '--ignore-code' should contain a list of integer values or a wildcard value '%s'" % IGNORE_CODE_WILDCARD 1573 | raise SqlmapSyntaxException(errMsg) 1574 | else: 1575 | conf.ignoreCode = [] 1576 | 1577 | if conf.paramFilter: 1578 | conf.paramFilter = [_.strip() for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.paramFilter.upper())] 1579 | else: 1580 | conf.paramFilter = [] 1581 | 1582 | if conf.base64Parameter: 1583 | conf.base64Parameter = urldecode(conf.base64Parameter) 1584 | conf.base64Parameter = conf.base64Parameter.replace(" ", "") 1585 | conf.base64Parameter = re.split(PARAMETER_SPLITTING_REGEX, conf.base64Parameter) 1586 | else: 1587 | conf.base64Parameter = [] 1588 | 1589 | if conf.agent: 1590 | conf.agent = re.sub(r"[\r\n]", "", conf.agent) 1591 | 1592 | if conf.user: 1593 | conf.user = conf.user.replace(" ", "") 1594 | 1595 | if conf.rParam: 1596 | if all(_ in conf.rParam for _ in ('=', ',')): 1597 | original = conf.rParam 1598 | conf.rParam = [] 1599 | for part in original.split(';'): 1600 | if '=' in part: 1601 | left, right = part.split('=', 1) 1602 | conf.rParam.append(left) 1603 | kb.randomPool[left] = filterNone(_.strip() for _ in right.split(',')) 1604 | else: 1605 | conf.rParam.append(part) 1606 | else: 1607 | conf.rParam = conf.rParam.replace(" ", "") 1608 | conf.rParam = re.split(PARAMETER_SPLITTING_REGEX, conf.rParam) 1609 | else: 1610 | conf.rParam = [] 1611 | 1612 | if conf.paramDel: 1613 | conf.paramDel = decodeStringEscape(conf.paramDel) 1614 | 1615 | if conf.skip: 1616 | conf.skip = conf.skip.replace(" ", "") 1617 | conf.skip = re.split(PARAMETER_SPLITTING_REGEX, conf.skip) 1618 | else: 1619 | conf.skip = [] 1620 | 1621 | if conf.cookie: 1622 | conf.cookie = re.sub(r"[\r\n]", "", conf.cookie) 1623 | 1624 | if conf.delay: 1625 | conf.delay = float(conf.delay) 1626 | 1627 | if conf.url: 1628 | conf.url = conf.url.strip().lstrip('/') 1629 | if not re.search(r"\A\w+://", conf.url): 1630 | conf.url = "http://%s" % conf.url 1631 | 1632 | if conf.fileRead: 1633 | conf.fileRead = ntToPosixSlashes(normalizePath(conf.fileRead)) 1634 | 1635 | if conf.fileWrite: 1636 | conf.fileWrite = ntToPosixSlashes(normalizePath(conf.fileWrite)) 1637 | 1638 | if conf.fileDest: 1639 | conf.fileDest = ntToPosixSlashes(normalizePath(conf.fileDest)) 1640 | 1641 | if conf.msfPath: 1642 | conf.msfPath = ntToPosixSlashes(normalizePath(conf.msfPath)) 1643 | 1644 | if conf.tmpPath: 1645 | conf.tmpPath = ntToPosixSlashes(normalizePath(conf.tmpPath)) 1646 | 1647 | if any((conf.googleDork, conf.logFile, conf.bulkFile, conf.forms, conf.crawlDepth)): 1648 | conf.multipleTargets = True 1649 | 1650 | if conf.optimize: 1651 | setOptimize() 1652 | 1653 | if conf.os: 1654 | conf.os = conf.os.capitalize() 1655 | 1656 | if conf.forceDbms: 1657 | conf.dbms = conf.forceDbms 1658 | 1659 | if conf.dbms: 1660 | kb.dbmsFilter = [] 1661 | for _ in conf.dbms.split(','): 1662 | for dbms, aliases in DBMS_ALIASES: 1663 | if _.strip().lower() in aliases: 1664 | kb.dbmsFilter.append(dbms) 1665 | conf.dbms = dbms if conf.dbms and ',' not in conf.dbms else None 1666 | break 1667 | 1668 | if conf.testFilter: 1669 | conf.testFilter = conf.testFilter.strip('*+') 1670 | conf.testFilter = re.sub(r"([^.])([*+])", r"\g<1>.\g<2>", conf.testFilter) 1671 | 1672 | try: 1673 | re.compile(conf.testFilter) 1674 | except re.error: 1675 | conf.testFilter = re.escape(conf.testFilter) 1676 | 1677 | if conf.csrfToken: 1678 | original = conf.csrfToken 1679 | try: 1680 | re.compile(conf.csrfToken) 1681 | 1682 | if re.escape(conf.csrfToken) != conf.csrfToken: 1683 | message = "provided value for option '--csrf-token' is a regular expression? [y/N] " 1684 | if not readInput(message, default='N', boolean=True): 1685 | conf.csrfToken = re.escape(conf.csrfToken) 1686 | except re.error: 1687 | conf.csrfToken = re.escape(conf.csrfToken) 1688 | finally: 1689 | class _(six.text_type): 1690 | pass 1691 | conf.csrfToken = _(conf.csrfToken) 1692 | conf.csrfToken._original = original 1693 | 1694 | if conf.testSkip: 1695 | conf.testSkip = conf.testSkip.strip('*+') 1696 | conf.testSkip = re.sub(r"([^.])([*+])", r"\g<1>.\g<2>", conf.testSkip) 1697 | 1698 | try: 1699 | re.compile(conf.testSkip) 1700 | except re.error: 1701 | conf.testSkip = re.escape(conf.testSkip) 1702 | 1703 | if "timeSec" not in kb.explicitSettings: 1704 | if conf.tor: 1705 | conf.timeSec = 2 * conf.timeSec 1706 | kb.adjustTimeDelay = ADJUST_TIME_DELAY.DISABLE 1707 | 1708 | warnMsg = "increasing default value for " 1709 | warnMsg += "option '--time-sec' to %d because " % conf.timeSec 1710 | warnMsg += "switch '--tor' was provided" 1711 | logger.warn(warnMsg) 1712 | else: 1713 | kb.adjustTimeDelay = ADJUST_TIME_DELAY.DISABLE 1714 | 1715 | if conf.retries: 1716 | conf.retries = min(conf.retries, MAX_CONNECT_RETRIES) 1717 | 1718 | if conf.code: 1719 | conf.code = int(conf.code) 1720 | 1721 | if conf.csvDel: 1722 | conf.csvDel = decodeStringEscape(conf.csvDel) 1723 | 1724 | if conf.torPort and hasattr(conf.torPort, "isdigit") and conf.torPort.isdigit(): 1725 | conf.torPort = int(conf.torPort) 1726 | 1727 | if conf.torType: 1728 | conf.torType = conf.torType.upper() 1729 | 1730 | if conf.outputDir: 1731 | paths.SQLMAP_OUTPUT_PATH = os.path.realpath(os.path.expanduser(conf.outputDir)) 1732 | setPaths(paths.SQLMAP_ROOT_PATH) 1733 | 1734 | if conf.string: 1735 | conf.string = decodeStringEscape(conf.string) 1736 | 1737 | if conf.getAll: 1738 | for _ in WIZARD.ALL: 1739 | conf.__setitem__(_, True) 1740 | 1741 | if conf.noCast: 1742 | DUMP_REPLACEMENTS.clear() 1743 | 1744 | if conf.dumpFormat: 1745 | conf.dumpFormat = conf.dumpFormat.upper() 1746 | 1747 | if conf.torType: 1748 | conf.torType = conf.torType.upper() 1749 | 1750 | if conf.col: 1751 | conf.col = re.sub(r"\s*,\s*", ',', conf.col) 1752 | 1753 | if conf.exclude: 1754 | regex = False 1755 | if any(_ in conf.exclude for _ in ('+', '*')): 1756 | try: 1757 | re.compile(conf.exclude) 1758 | except re.error: 1759 | pass 1760 | else: 1761 | regex = True 1762 | 1763 | if not regex: 1764 | conf.exclude = re.sub(r"\s*,\s*", ',', conf.exclude) 1765 | conf.exclude = r"\A%s\Z" % '|'.join(re.escape(_) for _ in conf.exclude.split(',')) 1766 | 1767 | if conf.binaryFields: 1768 | conf.binaryFields = conf.binaryFields.replace(" ", "") 1769 | conf.binaryFields = re.split(PARAMETER_SPLITTING_REGEX, conf.binaryFields) 1770 | 1771 | envProxy = max(os.environ.get(_, "") for _ in PROXY_ENVIRONMENT_VARIABLES) 1772 | if re.search(r"\A(https?|socks[45])://.+:\d+\Z", envProxy) and conf.proxy is None: 1773 | debugMsg = "using environment proxy '%s'" % envProxy 1774 | logger.debug(debugMsg) 1775 | 1776 | conf.proxy = envProxy 1777 | 1778 | if any((conf.proxy, conf.proxyFile, conf.tor)): 1779 | conf.disablePrecon = True 1780 | 1781 | if conf.dummy: 1782 | conf.batch = True 1783 | 1784 | threadData = getCurrentThreadData() 1785 | threadData.reset() 1786 | 1787 | def _cleanupEnvironment(): 1788 | """ 1789 | Cleanup environment (e.g. from leftovers after --sqlmap-shell). 1790 | """ 1791 | 1792 | if issubclass(_http_client.socket.socket, socks.socksocket): 1793 | socks.unwrapmodule(_http_client) 1794 | 1795 | if hasattr(socket, "_ready"): 1796 | socket._ready.clear() 1797 | 1798 | def _purge(): 1799 | """ 1800 | Safely removes (purges) sqlmap data directory. 1801 | """ 1802 | 1803 | if conf.purge: 1804 | purge(paths.SQLMAP_HOME_PATH) 1805 | 1806 | def _setConfAttributes(): 1807 | """ 1808 | This function set some needed attributes into the configuration 1809 | singleton. 1810 | """ 1811 | 1812 | debugMsg = "initializing the configuration" 1813 | logger.debug(debugMsg) 1814 | 1815 | conf.authUsername = None 1816 | conf.authPassword = None 1817 | conf.boundaries = [] 1818 | conf.cj = None 1819 | conf.dbmsConnector = None 1820 | conf.dbmsHandler = None 1821 | conf.dnsServer = None 1822 | conf.dumpPath = None 1823 | conf.hashDB = None 1824 | conf.hashDBFile = None 1825 | conf.httpCollector = None 1826 | conf.httpHeaders = [] 1827 | conf.hostname = None 1828 | conf.ipv6 = False 1829 | conf.multipleTargets = False 1830 | conf.outputPath = None 1831 | conf.paramDict = {} 1832 | conf.parameters = {} 1833 | conf.path = None 1834 | conf.port = None 1835 | conf.proxyList = None 1836 | conf.resultsFP = None 1837 | conf.scheme = None 1838 | conf.tests = [] 1839 | conf.trafficFP = None 1840 | conf.HARCollectorFactory = None 1841 | conf.fileWriteType = None 1842 | 1843 | def _setKnowledgeBaseAttributes(flushAll=True): 1844 | """ 1845 | This function set some needed attributes into the knowledge base 1846 | singleton. 1847 | """ 1848 | 1849 | debugMsg = "initializing the knowledge base" 1850 | logger.debug(debugMsg) 1851 | 1852 | kb.absFilePaths = set() 1853 | kb.adjustTimeDelay = None 1854 | kb.alerted = False 1855 | kb.aliasName = randomStr() 1856 | kb.alwaysRefresh = None 1857 | kb.arch = None 1858 | kb.authHeader = None 1859 | kb.bannerFp = AttribDict() 1860 | kb.binaryField = False 1861 | kb.browserVerification = None 1862 | 1863 | kb.brute = AttribDict({"tables": [], "columns": []}) 1864 | kb.bruteMode = False 1865 | 1866 | kb.cache = AttribDict() 1867 | kb.cache.addrinfo = {} 1868 | kb.cache.content = {} 1869 | kb.cache.encoding = {} 1870 | kb.cache.alphaBoundaries = None 1871 | kb.cache.hashRegex = None 1872 | kb.cache.intBoundaries = None 1873 | kb.cache.parsedDbms = {} 1874 | kb.cache.regex = {} 1875 | kb.cache.stdev = {} 1876 | 1877 | kb.captchaDetected = None 1878 | 1879 | kb.chars = AttribDict() 1880 | kb.chars.delimiter = randomStr(length=6, lowercase=True) 1881 | kb.chars.start = "%s%s%s" % (KB_CHARS_BOUNDARY_CHAR, randomStr(length=3, alphabet=KB_CHARS_LOW_FREQUENCY_ALPHABET), KB_CHARS_BOUNDARY_CHAR) 1882 | kb.chars.stop = "%s%s%s" % (KB_CHARS_BOUNDARY_CHAR, randomStr(length=3, alphabet=KB_CHARS_LOW_FREQUENCY_ALPHABET), KB_CHARS_BOUNDARY_CHAR) 1883 | kb.chars.at, kb.chars.space, kb.chars.dollar, kb.chars.hash_ = ("%s%s%s" % (KB_CHARS_BOUNDARY_CHAR, _, KB_CHARS_BOUNDARY_CHAR) for _ in randomStr(length=4, lowercase=True)) 1884 | 1885 | kb.codePage = None 1886 | kb.columnExistsChoice = None 1887 | kb.commonOutputs = None 1888 | kb.connErrorChoice = None 1889 | kb.connErrorCounter = 0 1890 | kb.cookieEncodeChoice = None 1891 | kb.copyExecTest = None 1892 | kb.counters = {} 1893 | kb.customInjectionMark = CUSTOM_INJECTION_MARK_CHAR 1894 | kb.data = AttribDict() 1895 | kb.dataOutputFlag = False 1896 | 1897 | # Active back-end DBMS fingerprint 1898 | kb.dbms = None 1899 | kb.dbmsFilter = [] 1900 | kb.dbmsVersion = [UNKNOWN_DBMS_VERSION] 1901 | 1902 | kb.delayCandidates = TIME_DELAY_CANDIDATES * [0] 1903 | kb.dep = None 1904 | kb.disableHtmlDecoding = False 1905 | kb.dnsMode = False 1906 | kb.dnsTest = None 1907 | kb.docRoot = None 1908 | kb.droppingRequests = False 1909 | kb.dumpColumns = None 1910 | kb.dumpTable = None 1911 | kb.dumpKeyboardInterrupt = False 1912 | kb.dynamicMarkings = [] 1913 | kb.dynamicParameter = False 1914 | kb.endDetection = False 1915 | kb.explicitSettings = set() 1916 | kb.extendTests = None 1917 | kb.errorChunkLength = None 1918 | kb.errorIsNone = True 1919 | kb.falsePositives = [] 1920 | kb.fileReadMode = False 1921 | kb.fingerprinted = False 1922 | kb.followSitemapRecursion = None 1923 | kb.forcedDbms = None 1924 | kb.forcePartialUnion = False 1925 | kb.forceThreads = None 1926 | kb.forceWhere = None 1927 | kb.forkNote = None 1928 | kb.futileUnion = None 1929 | kb.fuzzUnionTest = None 1930 | kb.heavilyDynamic = False 1931 | kb.headersFile = None 1932 | kb.headersFp = {} 1933 | kb.heuristicDbms = None 1934 | kb.heuristicExtendedDbms = None 1935 | kb.heuristicMode = False 1936 | kb.heuristicPage = False 1937 | kb.heuristicTest = None 1938 | kb.hintValue = "" 1939 | kb.htmlFp = [] 1940 | kb.httpErrorCodes = {} 1941 | kb.inferenceMode = False 1942 | kb.ignoreCasted = None 1943 | kb.ignoreNotFound = False 1944 | kb.ignoreTimeout = False 1945 | kb.identifiedWafs = set() 1946 | kb.injection = InjectionDict() 1947 | kb.injections = [] 1948 | kb.laggingChecked = False 1949 | kb.lastParserStatus = None 1950 | kb.lastCtrlCTime = None 1951 | 1952 | kb.locks = AttribDict() 1953 | for _ in ("cache", "connError", "count", "handlers", "hint", "index", "io", "limit", "log", "socket", "redirect", "request", "value"): 1954 | kb.locks[_] = threading.Lock() 1955 | 1956 | kb.matchRatio = None 1957 | kb.maxConnectionsFlag = False 1958 | kb.mergeCookies = None 1959 | kb.multipleCtrlC = False 1960 | kb.negativeLogic = False 1961 | kb.nullConnection = None 1962 | kb.oldMsf = None 1963 | kb.orderByColumns = None 1964 | kb.originalCode = None 1965 | kb.originalPage = None 1966 | kb.originalPageTime = None 1967 | kb.originalTimeDelay = None 1968 | kb.originalUrls = dict() 1969 | 1970 | # Back-end DBMS underlying operating system fingerprint via banner (-b) 1971 | # parsing 1972 | kb.os = None 1973 | kb.osVersion = None 1974 | kb.osSP = None 1975 | 1976 | kb.pageCompress = True 1977 | kb.pageTemplate = None 1978 | kb.pageTemplates = dict() 1979 | kb.pageEncoding = DEFAULT_PAGE_ENCODING 1980 | kb.pageStable = None 1981 | kb.partRun = None 1982 | kb.permissionFlag = False 1983 | kb.postHint = None 1984 | kb.postSpaceToPlus = False 1985 | kb.postUrlEncode = True 1986 | kb.prependFlag = False 1987 | kb.processResponseCounter = 0 1988 | kb.previousMethod = None 1989 | kb.processUserMarks = None 1990 | kb.proxyAuthHeader = None 1991 | kb.queryCounter = 0 1992 | kb.randomPool = {} 1993 | kb.redirectChoice = None 1994 | kb.reflectiveMechanism = True 1995 | kb.reflectiveCounters = {REFLECTIVE_COUNTER.MISS: 0, REFLECTIVE_COUNTER.HIT: 0} 1996 | kb.requestCounter = 0 1997 | kb.resendPostOnRedirect = None 1998 | kb.resolutionDbms = None 1999 | kb.responseTimes = {} 2000 | kb.responseTimeMode = None 2001 | kb.responseTimePayload = None 2002 | kb.resumeValues = True 2003 | kb.rowXmlMode = False 2004 | kb.safeCharEncode = False 2005 | kb.safeReq = AttribDict() 2006 | kb.secondReq = None 2007 | kb.serverHeader = None 2008 | kb.singleLogFlags = set() 2009 | kb.skipSeqMatcher = False 2010 | kb.smokeMode = False 2011 | kb.reduceTests = None 2012 | kb.tlsSNI = {} 2013 | kb.stickyDBMS = False 2014 | kb.storeHashesChoice = None 2015 | kb.suppressResumeInfo = False 2016 | kb.tableFrom = None 2017 | kb.technique = None 2018 | kb.tempDir = None 2019 | kb.testMode = False 2020 | kb.testOnlyCustom = False 2021 | kb.testQueryCount = 0 2022 | kb.testType = None 2023 | kb.threadContinue = True 2024 | kb.threadException = False 2025 | kb.tableExistsChoice = None 2026 | kb.uChar = NULL 2027 | kb.udfFail = False 2028 | kb.unionDuplicates = False 2029 | kb.unionTemplate = None 2030 | kb.webSocketRecvCount = None 2031 | kb.wizardMode = False 2032 | kb.xpCmdshellAvailable = False 2033 | 2034 | if flushAll: 2035 | kb.checkSitemap = None 2036 | kb.headerPaths = {} 2037 | kb.keywords = set(getFileItems(paths.SQL_KEYWORDS)) 2038 | kb.normalizeCrawlingChoice = None 2039 | kb.passwordMgr = None 2040 | kb.preprocessFunctions = [] 2041 | kb.skipVulnHost = None 2042 | kb.storeCrawlingChoice = None 2043 | kb.tamperFunctions = [] 2044 | kb.targets = OrderedSet() 2045 | kb.testedParams = set() 2046 | kb.userAgents = None 2047 | kb.vainRun = True 2048 | kb.vulnHosts = set() 2049 | kb.wafFunctions = [] 2050 | kb.wordlists = None 2051 | 2052 | def _useWizardInterface(): 2053 | """ 2054 | Presents simple wizard interface for beginner users 2055 | """ 2056 | 2057 | if not conf.wizard: 2058 | return 2059 | 2060 | logger.info("starting wizard interface") 2061 | 2062 | while not conf.url: 2063 | message = "Please enter full target URL (-u): " 2064 | conf.url = readInput(message, default=None) 2065 | 2066 | message = "%s data (--data) [Enter for None]: " % ((conf.method if conf.method != HTTPMETHOD.GET else None) or HTTPMETHOD.POST) 2067 | conf.data = readInput(message, default=None) 2068 | 2069 | if not (any('=' in _ for _ in (conf.url, conf.data)) or '*' in conf.url): 2070 | warnMsg = "no GET and/or %s parameter(s) found for testing " % ((conf.method if conf.method != HTTPMETHOD.GET else None) or HTTPMETHOD.POST) 2071 | warnMsg += "(e.g. GET parameter 'id' in 'http://www.site.com/vuln.php?id=1'). " 2072 | if not conf.crawlDepth and not conf.forms: 2073 | warnMsg += "Will search for forms" 2074 | conf.forms = True 2075 | logger.warn(warnMsg) 2076 | 2077 | choice = None 2078 | 2079 | while choice is None or choice not in ("", "1", "2", "3"): 2080 | message = "Injection difficulty (--level/--risk). Please choose:\n" 2081 | message += "[1] Normal (default)\n[2] Medium\n[3] Hard" 2082 | choice = readInput(message, default='1') 2083 | 2084 | if choice == '2': 2085 | conf.risk = 2 2086 | conf.level = 3 2087 | elif choice == '3': 2088 | conf.risk = 3 2089 | conf.level = 5 2090 | else: 2091 | conf.risk = 1 2092 | conf.level = 1 2093 | 2094 | if not conf.getAll: 2095 | choice = None 2096 | 2097 | while choice is None or choice not in ("", "1", "2", "3"): 2098 | message = "Enumeration (--banner/--current-user/etc). Please choose:\n" 2099 | message += "[1] Basic (default)\n[2] Intermediate\n[3] All" 2100 | choice = readInput(message, default='1') 2101 | 2102 | if choice == '2': 2103 | options = WIZARD.INTERMEDIATE 2104 | elif choice == '3': 2105 | options = WIZARD.ALL 2106 | else: 2107 | options = WIZARD.BASIC 2108 | 2109 | for _ in options: 2110 | conf.__setitem__(_, True) 2111 | 2112 | logger.debug("muting sqlmap.. it will do the magic for you") 2113 | conf.verbose = 0 2114 | 2115 | conf.batch = True 2116 | conf.threads = 4 2117 | 2118 | dataToStdout("\nsqlmap is running, please wait..\n\n") 2119 | 2120 | kb.wizardMode = True 2121 | 2122 | def _saveConfig(): 2123 | """ 2124 | Saves the command line options to a sqlmap configuration INI file 2125 | Format. 2126 | """ 2127 | 2128 | if not conf.saveConfig: 2129 | return 2130 | 2131 | debugMsg = "saving command line options to a sqlmap configuration INI file" 2132 | logger.debug(debugMsg) 2133 | 2134 | saveConfig(conf, conf.saveConfig) 2135 | 2136 | infoMsg = "saved command line options to the configuration file '%s'" % conf.saveConfig 2137 | logger.info(infoMsg) 2138 | 2139 | def setVerbosity(): 2140 | """ 2141 | This function set the verbosity of sqlmap output messages. 2142 | """ 2143 | 2144 | if conf.verbose is None: 2145 | conf.verbose = 1 2146 | 2147 | conf.verbose = int(conf.verbose) 2148 | 2149 | if conf.verbose == 0: 2150 | logger.setLevel(logging.ERROR) 2151 | elif conf.verbose == 1: 2152 | logger.setLevel(logging.INFO) 2153 | elif conf.verbose > 2 and conf.eta: 2154 | conf.verbose = 2 2155 | logger.setLevel(logging.DEBUG) 2156 | elif conf.verbose == 2: 2157 | logger.setLevel(logging.DEBUG) 2158 | elif conf.verbose == 3: 2159 | logger.setLevel(CUSTOM_LOGGING.PAYLOAD) 2160 | elif conf.verbose == 4: 2161 | logger.setLevel(CUSTOM_LOGGING.TRAFFIC_OUT) 2162 | elif conf.verbose >= 5: 2163 | logger.setLevel(CUSTOM_LOGGING.TRAFFIC_IN) 2164 | 2165 | def _normalizeOptions(inputOptions): 2166 | """ 2167 | Sets proper option types 2168 | """ 2169 | 2170 | types_ = {} 2171 | for group in optDict.keys(): 2172 | types_.update(optDict[group]) 2173 | 2174 | for key in inputOptions: 2175 | if key in types_: 2176 | value = inputOptions[key] 2177 | if value is None: 2178 | continue 2179 | 2180 | type_ = types_[key] 2181 | if type_ and isinstance(type_, tuple): 2182 | type_ = type_[0] 2183 | 2184 | if type_ == OPTION_TYPE.BOOLEAN: 2185 | try: 2186 | value = bool(value) 2187 | except (TypeError, ValueError): 2188 | value = False 2189 | elif type_ == OPTION_TYPE.INTEGER: 2190 | try: 2191 | value = int(value) 2192 | except (TypeError, ValueError): 2193 | value = 0 2194 | elif type_ == OPTION_TYPE.FLOAT: 2195 | try: 2196 | value = float(value) 2197 | except (TypeError, ValueError): 2198 | value = 0.0 2199 | 2200 | inputOptions[key] = value 2201 | 2202 | def _mergeOptions(inputOptions, overrideOptions): 2203 | """ 2204 | Merge command line options with configuration file and default options. 2205 | 2206 | @param inputOptions: optparse object with command line options. 2207 | @type inputOptions: C{instance} 2208 | """ 2209 | 2210 | if inputOptions.configFile: 2211 | configFileParser(inputOptions.configFile) 2212 | 2213 | if hasattr(inputOptions, "items"): 2214 | inputOptionsItems = inputOptions.items() 2215 | else: 2216 | inputOptionsItems = inputOptions.__dict__.items() 2217 | 2218 | for key, value in inputOptionsItems: 2219 | if key not in conf or value not in (None, False) or overrideOptions: 2220 | conf[key] = value 2221 | 2222 | if not conf.api: 2223 | for key, value in conf.items(): 2224 | if value is not None: 2225 | kb.explicitSettings.add(key) 2226 | 2227 | for key, value in defaults.items(): 2228 | if hasattr(conf, key) and conf[key] is None: 2229 | conf[key] = value 2230 | 2231 | if conf.unstable: 2232 | if key in ("timeSec", "retries", "timeout"): 2233 | conf[key] *= 2 2234 | 2235 | if conf.unstable: 2236 | conf.forcePartial = True 2237 | 2238 | lut = {} 2239 | for group in optDict.keys(): 2240 | lut.update((_.upper(), _) for _ in optDict[group]) 2241 | 2242 | envOptions = {} 2243 | for key, value in os.environ.items(): 2244 | if key.upper().startswith(SQLMAP_ENVIRONMENT_PREFIX): 2245 | _ = key[len(SQLMAP_ENVIRONMENT_PREFIX):].upper() 2246 | if _ in lut: 2247 | envOptions[lut[_]] = value 2248 | 2249 | if envOptions: 2250 | _normalizeOptions(envOptions) 2251 | for key, value in envOptions.items(): 2252 | conf[key] = value 2253 | 2254 | mergedOptions.update(conf) 2255 | 2256 | def _setTrafficOutputFP(): 2257 | if conf.trafficFile: 2258 | infoMsg = "setting file for logging HTTP traffic" 2259 | logger.info(infoMsg) 2260 | 2261 | conf.trafficFP = openFile(conf.trafficFile, "w+") 2262 | 2263 | def _setupHTTPCollector(): 2264 | if not conf.harFile: 2265 | return 2266 | 2267 | conf.httpCollector = HTTPCollectorFactory(conf.harFile).create() 2268 | 2269 | def _setDNSServer(): 2270 | if not conf.dnsDomain: 2271 | return 2272 | 2273 | infoMsg = "setting up DNS server instance" 2274 | logger.info(infoMsg) 2275 | 2276 | isAdmin = runningAsAdmin() 2277 | 2278 | if isAdmin: 2279 | try: 2280 | conf.dnsServer = DNSServer() 2281 | conf.dnsServer.run() 2282 | except socket.error as ex: 2283 | errMsg = "there was an error while setting up " 2284 | errMsg += "DNS server instance ('%s')" % getSafeExString(ex) 2285 | raise SqlmapGenericException(errMsg) 2286 | else: 2287 | errMsg = "you need to run sqlmap as an administrator " 2288 | errMsg += "if you want to perform a DNS data exfiltration attack " 2289 | errMsg += "as it will need to listen on privileged UDP port 53 " 2290 | errMsg += "for incoming address resolution attempts" 2291 | raise SqlmapMissingPrivileges(errMsg) 2292 | 2293 | def _setProxyList(): 2294 | if not conf.proxyFile: 2295 | return 2296 | 2297 | conf.proxyList = [] 2298 | if conf.proxyFile == 'auto': 2299 | getproxyip() 2300 | for line in open(paths.SQLMAP_ROOT_PATH +"/thirdparty/proxy.txt", 'r'): 2301 | conf.proxyList.append("http://"+line) 2302 | return 2303 | 2304 | for match in re.finditer(r"(?i)((http[^:]*|socks[^:]*)://)?([\w\-.]+):(\d+)", readCachedFileContent(conf.proxyFile)): 2305 | _, type_, address, port = match.groups() 2306 | conf.proxyList.append("%s://%s:%s" % (type_ or "http", address, port)) 2307 | 2308 | def _setTorProxySettings(): 2309 | if not conf.tor: 2310 | return 2311 | 2312 | if conf.torType == PROXY_TYPE.HTTP: 2313 | _setTorHttpProxySettings() 2314 | else: 2315 | _setTorSocksProxySettings() 2316 | 2317 | def _setTorHttpProxySettings(): 2318 | infoMsg = "setting Tor HTTP proxy settings" 2319 | logger.info(infoMsg) 2320 | 2321 | port = findLocalPort(DEFAULT_TOR_HTTP_PORTS if not conf.torPort else (conf.torPort,)) 2322 | 2323 | if port: 2324 | conf.proxy = "http://%s:%d" % (LOCALHOST, port) 2325 | else: 2326 | errMsg = "can't establish connection with the Tor HTTP proxy. " 2327 | errMsg += "Please make sure that you have Tor (bundle) installed and setup " 2328 | errMsg += "so you could be able to successfully use switch '--tor' " 2329 | raise SqlmapConnectionException(errMsg) 2330 | 2331 | if not conf.checkTor: 2332 | warnMsg = "use switch '--check-tor' at " 2333 | warnMsg += "your own convenience when accessing " 2334 | warnMsg += "Tor anonymizing network because of " 2335 | warnMsg += "known issues with default settings of various 'bundles' " 2336 | warnMsg += "(e.g. Vidalia)" 2337 | logger.warn(warnMsg) 2338 | 2339 | def _setTorSocksProxySettings(): 2340 | infoMsg = "setting Tor SOCKS proxy settings" 2341 | logger.info(infoMsg) 2342 | 2343 | port = findLocalPort(DEFAULT_TOR_SOCKS_PORTS if not conf.torPort else (conf.torPort,)) 2344 | 2345 | if not port: 2346 | errMsg = "can't establish connection with the Tor SOCKS proxy. " 2347 | errMsg += "Please make sure that you have Tor service installed and setup " 2348 | errMsg += "so you could be able to successfully use switch '--tor' " 2349 | raise SqlmapConnectionException(errMsg) 2350 | 2351 | # SOCKS5 to prevent DNS leaks (http://en.wikipedia.org/wiki/Tor_%28anonymity_network%29) 2352 | socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5 if conf.torType == PROXY_TYPE.SOCKS5 else socks.PROXY_TYPE_SOCKS4, LOCALHOST, port) 2353 | socks.wrapmodule(_http_client) 2354 | 2355 | def _setHttpChunked(): 2356 | if conf.chunked and conf.data: 2357 | _http_client.HTTPConnection._set_content_length = lambda self, a, b: None 2358 | 2359 | def _checkWebSocket(): 2360 | if conf.url and (conf.url.startswith("ws:/") or conf.url.startswith("wss:/")): 2361 | try: 2362 | from websocket import ABNF 2363 | except ImportError: 2364 | errMsg = "sqlmap requires third-party module 'websocket-client' " 2365 | errMsg += "in order to use WebSocket functionality" 2366 | raise SqlmapMissingDependence(errMsg) 2367 | 2368 | def _checkTor(): 2369 | if not conf.checkTor: 2370 | return 2371 | 2372 | infoMsg = "checking Tor connection" 2373 | logger.info(infoMsg) 2374 | 2375 | try: 2376 | page, _, _ = Request.getPage(url="https://check.torproject.org/", raise404=False) 2377 | except SqlmapConnectionException: 2378 | page = None 2379 | 2380 | if not page or "Congratulations" not in page: 2381 | errMsg = "it appears that Tor is not properly set. Please try using options '--tor-type' and/or '--tor-port'" 2382 | raise SqlmapConnectionException(errMsg) 2383 | else: 2384 | infoMsg = "Tor is properly being used" 2385 | logger.info(infoMsg) 2386 | 2387 | def _basicOptionValidation(): 2388 | if conf.limitStart is not None and not (isinstance(conf.limitStart, int) and conf.limitStart > 0): 2389 | errMsg = "value for option '--start' (limitStart) must be an integer value greater than zero (>0)" 2390 | raise SqlmapSyntaxException(errMsg) 2391 | 2392 | if conf.limitStop is not None and not (isinstance(conf.limitStop, int) and conf.limitStop > 0): 2393 | errMsg = "value for option '--stop' (limitStop) must be an integer value greater than zero (>0)" 2394 | raise SqlmapSyntaxException(errMsg) 2395 | 2396 | if conf.level is not None and not (isinstance(conf.level, int) and conf.level >= 1 and conf.level <= 5): 2397 | errMsg = "value for option '--level' must be an integer value from range [1, 5]" 2398 | raise SqlmapSyntaxException(errMsg) 2399 | 2400 | if conf.risk is not None and not (isinstance(conf.risk, int) and conf.risk >= 1 and conf.risk <= 3): 2401 | errMsg = "value for option '--risk' must be an integer value from range [1, 3]" 2402 | raise SqlmapSyntaxException(errMsg) 2403 | 2404 | if isinstance(conf.limitStart, int) and conf.limitStart > 0 and \ 2405 | isinstance(conf.limitStop, int) and conf.limitStop < conf.limitStart: 2406 | warnMsg = "usage of option '--start' (limitStart) which is bigger than value for --stop (limitStop) option is considered unstable" 2407 | logger.warn(warnMsg) 2408 | 2409 | if isinstance(conf.firstChar, int) and conf.firstChar > 0 and \ 2410 | isinstance(conf.lastChar, int) and conf.lastChar < conf.firstChar: 2411 | errMsg = "value for option '--first' (firstChar) must be smaller than or equal to value for --last (lastChar) option" 2412 | raise SqlmapSyntaxException(errMsg) 2413 | 2414 | if conf.textOnly and conf.nullConnection: 2415 | errMsg = "switch '--text-only' is incompatible with switch '--null-connection'" 2416 | raise SqlmapSyntaxException(errMsg) 2417 | 2418 | if conf.eta and conf.verbose > defaults.verbose: 2419 | errMsg = "switch '--eta' is incompatible with option '-v'" 2420 | raise SqlmapSyntaxException(errMsg) 2421 | 2422 | if conf.secondUrl and conf.secondReq: 2423 | errMsg = "option '--second-url' is incompatible with option '--second-req')" 2424 | raise SqlmapSyntaxException(errMsg) 2425 | 2426 | if conf.direct and conf.url: 2427 | errMsg = "option '-d' is incompatible with option '-u' ('--url')" 2428 | raise SqlmapSyntaxException(errMsg) 2429 | 2430 | if conf.direct and conf.dbms: 2431 | errMsg = "option '-d' is incompatible with option '--dbms'" 2432 | raise SqlmapSyntaxException(errMsg) 2433 | 2434 | if conf.titles and conf.nullConnection: 2435 | errMsg = "switch '--titles' is incompatible with switch '--null-connection'" 2436 | raise SqlmapSyntaxException(errMsg) 2437 | 2438 | if conf.dumpTable and conf.search: 2439 | errMsg = "switch '--dump' is incompatible with switch '--search'" 2440 | raise SqlmapSyntaxException(errMsg) 2441 | 2442 | if conf.chunked and not any((conf.data, conf.requestFile, conf.forms)): 2443 | errMsg = "switch '--chunked' requires usage of (POST) options/switches '--data', '-r' or '--forms'" 2444 | raise SqlmapSyntaxException(errMsg) 2445 | 2446 | if conf.api and not conf.configFile: 2447 | errMsg = "switch '--api' requires usage of option '-c'" 2448 | raise SqlmapSyntaxException(errMsg) 2449 | 2450 | if conf.data and conf.nullConnection: 2451 | errMsg = "option '--data' is incompatible with switch '--null-connection'" 2452 | raise SqlmapSyntaxException(errMsg) 2453 | 2454 | if conf.string and conf.nullConnection: 2455 | errMsg = "option '--string' is incompatible with switch '--null-connection'" 2456 | raise SqlmapSyntaxException(errMsg) 2457 | 2458 | if conf.notString and conf.nullConnection: 2459 | errMsg = "option '--not-string' is incompatible with switch '--null-connection'" 2460 | raise SqlmapSyntaxException(errMsg) 2461 | 2462 | if conf.tor and conf.osPwn: 2463 | errMsg = "option '--tor' is incompatible with switch '--os-pwn'" 2464 | raise SqlmapSyntaxException(errMsg) 2465 | 2466 | if conf.noCast and conf.hexConvert: 2467 | errMsg = "switch '--no-cast' is incompatible with switch '--hex'" 2468 | raise SqlmapSyntaxException(errMsg) 2469 | 2470 | if conf.dumpAll and conf.search: 2471 | errMsg = "switch '--dump-all' is incompatible with switch '--search'" 2472 | raise SqlmapSyntaxException(errMsg) 2473 | 2474 | if conf.string and conf.notString: 2475 | errMsg = "option '--string' is incompatible with switch '--not-string'" 2476 | raise SqlmapSyntaxException(errMsg) 2477 | 2478 | if conf.regexp and conf.nullConnection: 2479 | errMsg = "option '--regexp' is incompatible with switch '--null-connection'" 2480 | raise SqlmapSyntaxException(errMsg) 2481 | 2482 | if conf.regexp: 2483 | try: 2484 | re.compile(conf.regexp) 2485 | except Exception as ex: 2486 | errMsg = "invalid regular expression '%s' ('%s')" % (conf.regexp, getSafeExString(ex)) 2487 | raise SqlmapSyntaxException(errMsg) 2488 | 2489 | if conf.paramExclude: 2490 | try: 2491 | re.compile(conf.paramExclude) 2492 | except Exception as ex: 2493 | errMsg = "invalid regular expression '%s' ('%s')" % (conf.paramExclude, getSafeExString(ex)) 2494 | raise SqlmapSyntaxException(errMsg) 2495 | 2496 | if conf.cookieDel and len(conf.cookieDel): 2497 | errMsg = "option '--cookie-del' should contain a single character (e.g. ';')" 2498 | raise SqlmapSyntaxException(errMsg) 2499 | 2500 | if conf.crawlExclude: 2501 | try: 2502 | re.compile(conf.crawlExclude) 2503 | except Exception as ex: 2504 | errMsg = "invalid regular expression '%s' ('%s')" % (conf.crawlExclude, getSafeExString(ex)) 2505 | raise SqlmapSyntaxException(errMsg) 2506 | 2507 | if conf.scope: 2508 | try: 2509 | re.compile(conf.scope) 2510 | except Exception as ex: 2511 | errMsg = "invalid regular expression '%s' ('%s')" % (conf.scope, getSafeExString(ex)) 2512 | raise SqlmapSyntaxException(errMsg) 2513 | 2514 | if conf.dumpTable and conf.dumpAll: 2515 | errMsg = "switch '--dump' is incompatible with switch '--dump-all'" 2516 | raise SqlmapSyntaxException(errMsg) 2517 | 2518 | if conf.predictOutput and (conf.threads > 1 or conf.optimize): 2519 | errMsg = "switch '--predict-output' is incompatible with option '--threads' and switch '-o'" 2520 | raise SqlmapSyntaxException(errMsg) 2521 | 2522 | if conf.threads > MAX_NUMBER_OF_THREADS and not conf.get("skipThreadCheck"): 2523 | errMsg = "maximum number of used threads is %d avoiding potential connection issues" % MAX_NUMBER_OF_THREADS 2524 | raise SqlmapSyntaxException(errMsg) 2525 | 2526 | if conf.forms and not any((conf.url, conf.googleDork, conf.bulkFile)): 2527 | errMsg = "switch '--forms' requires usage of option '-u' ('--url'), '-g' or '-m'" 2528 | raise SqlmapSyntaxException(errMsg) 2529 | 2530 | if conf.crawlExclude and not conf.crawlDepth: 2531 | errMsg = "option '--crawl-exclude' requires usage of switch '--crawl'" 2532 | raise SqlmapSyntaxException(errMsg) 2533 | 2534 | if conf.safePost and not conf.safeUrl: 2535 | errMsg = "option '--safe-post' requires usage of option '--safe-url'" 2536 | raise SqlmapSyntaxException(errMsg) 2537 | 2538 | if conf.safeFreq and not any((conf.safeUrl, conf.safeReqFile)): 2539 | errMsg = "option '--safe-freq' requires usage of option '--safe-url' or '--safe-req'" 2540 | raise SqlmapSyntaxException(errMsg) 2541 | 2542 | if conf.safeReqFile and any((conf.safeUrl, conf.safePost)): 2543 | errMsg = "option '--safe-req' is incompatible with option '--safe-url' and option '--safe-post'" 2544 | raise SqlmapSyntaxException(errMsg) 2545 | 2546 | if conf.csrfUrl and not conf.csrfToken: 2547 | errMsg = "option '--csrf-url' requires usage of option '--csrf-token'" 2548 | raise SqlmapSyntaxException(errMsg) 2549 | 2550 | if conf.csrfMethod and not conf.csrfToken: 2551 | errMsg = "option '--csrf-method' requires usage of option '--csrf-token'" 2552 | raise SqlmapSyntaxException(errMsg) 2553 | 2554 | if conf.csrfToken and conf.threads > 1: 2555 | errMsg = "option '--csrf-url' is incompatible with option '--threads'" 2556 | raise SqlmapSyntaxException(errMsg) 2557 | 2558 | if conf.requestFile and conf.url and conf.url != DUMMY_URL: 2559 | errMsg = "option '-r' is incompatible with option '-u' ('--url')" 2560 | raise SqlmapSyntaxException(errMsg) 2561 | 2562 | if conf.direct and conf.proxy: 2563 | errMsg = "option '-d' is incompatible with option '--proxy'" 2564 | raise SqlmapSyntaxException(errMsg) 2565 | 2566 | if conf.direct and conf.tor: 2567 | errMsg = "option '-d' is incompatible with switch '--tor'" 2568 | raise SqlmapSyntaxException(errMsg) 2569 | 2570 | if not conf.technique: 2571 | errMsg = "option '--technique' can't be empty" 2572 | raise SqlmapSyntaxException(errMsg) 2573 | 2574 | if conf.tor and conf.ignoreProxy: 2575 | errMsg = "switch '--tor' is incompatible with switch '--ignore-proxy'" 2576 | raise SqlmapSyntaxException(errMsg) 2577 | 2578 | if conf.tor and conf.proxy: 2579 | errMsg = "switch '--tor' is incompatible with option '--proxy'" 2580 | raise SqlmapSyntaxException(errMsg) 2581 | 2582 | if conf.proxy and conf.proxyFile: 2583 | errMsg = "switch '--proxy' is incompatible with option '--proxy-file'" 2584 | raise SqlmapSyntaxException(errMsg) 2585 | 2586 | if conf.checkTor and not any((conf.tor, conf.proxy)): 2587 | errMsg = "switch '--check-tor' requires usage of switch '--tor' (or option '--proxy' with HTTP proxy address of Tor service)" 2588 | raise SqlmapSyntaxException(errMsg) 2589 | 2590 | if conf.torPort is not None and not (isinstance(conf.torPort, int) and conf.torPort >= 0 and conf.torPort <= 65535): 2591 | errMsg = "value for option '--tor-port' must be in range [0, 65535]" 2592 | raise SqlmapSyntaxException(errMsg) 2593 | 2594 | if conf.torType not in getPublicTypeMembers(PROXY_TYPE, True): 2595 | errMsg = "option '--tor-type' accepts one of following values: %s" % ", ".join(getPublicTypeMembers(PROXY_TYPE, True)) 2596 | raise SqlmapSyntaxException(errMsg) 2597 | 2598 | if conf.dumpFormat not in getPublicTypeMembers(DUMP_FORMAT, True): 2599 | errMsg = "option '--dump-format' accepts one of following values: %s" % ", ".join(getPublicTypeMembers(DUMP_FORMAT, True)) 2600 | raise SqlmapSyntaxException(errMsg) 2601 | 2602 | if conf.skip and conf.testParameter: 2603 | if intersect(conf.skip, conf.testParameter): 2604 | errMsg = "option '--skip' is incompatible with option '-p'" 2605 | raise SqlmapSyntaxException(errMsg) 2606 | 2607 | if conf.rParam and conf.testParameter: 2608 | if intersect(conf.rParam, conf.testParameter): 2609 | errMsg = "option '--randomize' is incompatible with option '-p'" 2610 | raise SqlmapSyntaxException(errMsg) 2611 | 2612 | if conf.mobile and conf.agent: 2613 | errMsg = "switch '--mobile' is incompatible with option '--user-agent'" 2614 | raise SqlmapSyntaxException(errMsg) 2615 | 2616 | if conf.proxy and conf.ignoreProxy: 2617 | errMsg = "option '--proxy' is incompatible with switch '--ignore-proxy'" 2618 | raise SqlmapSyntaxException(errMsg) 2619 | 2620 | if conf.alert and conf.alert.startswith('-'): 2621 | errMsg = "value for option '--alert' must be valid operating system command(s)" 2622 | raise SqlmapSyntaxException(errMsg) 2623 | 2624 | if conf.timeSec < 1: 2625 | errMsg = "value for option '--time-sec' must be a positive integer" 2626 | raise SqlmapSyntaxException(errMsg) 2627 | 2628 | if conf.uChar and not re.match(UNION_CHAR_REGEX, conf.uChar): 2629 | errMsg = "value for option '--union-char' must be an alpha-numeric value (e.g. 1)" 2630 | raise SqlmapSyntaxException(errMsg) 2631 | 2632 | if conf.hashFile and any((conf.direct, conf.url, conf.logFile, conf.bulkFile, conf.googleDork, conf.configFile, conf.requestFile, conf.updateAll, conf.smokeTest, conf.wizard, conf.dependencies, conf.purge, conf.listTampers)): 2633 | errMsg = "option '--crack' should be used as a standalone" 2634 | raise SqlmapSyntaxException(errMsg) 2635 | 2636 | if isinstance(conf.uCols, six.string_types): 2637 | if not conf.uCols.isdigit() and ("-" not in conf.uCols or len(conf.uCols.split("-")) != 2): 2638 | errMsg = "value for option '--union-cols' must be a range with hyphon " 2639 | errMsg += "(e.g. 1-10) or integer value (e.g. 5)" 2640 | raise SqlmapSyntaxException(errMsg) 2641 | 2642 | if conf.dbmsCred and ':' not in conf.dbmsCred: 2643 | errMsg = "value for option '--dbms-cred' must be in " 2644 | errMsg += "format : (e.g. \"root:pass\")" 2645 | raise SqlmapSyntaxException(errMsg) 2646 | 2647 | if conf.encoding: 2648 | _ = checkCharEncoding(conf.encoding, False) 2649 | if _ is None: 2650 | errMsg = "unknown encoding '%s'. Please visit " % conf.encoding 2651 | errMsg += "'%s' to get the full list of " % CODECS_LIST_PAGE 2652 | errMsg += "supported encodings" 2653 | raise SqlmapSyntaxException(errMsg) 2654 | else: 2655 | conf.encoding = _ 2656 | 2657 | if conf.loadCookies: 2658 | if not os.path.exists(conf.loadCookies): 2659 | errMsg = "cookies file '%s' does not exist" % conf.loadCookies 2660 | raise SqlmapFilePathException(errMsg) 2661 | 2662 | def initOptions(inputOptions=AttribDict(), overrideOptions=False): 2663 | _setConfAttributes() 2664 | _setKnowledgeBaseAttributes() 2665 | _mergeOptions(inputOptions, overrideOptions) 2666 | 2667 | def init(): 2668 | """ 2669 | Set attributes into both configuration and knowledge base singletons 2670 | based upon command line and configuration file options. 2671 | """ 2672 | 2673 | _useWizardInterface() 2674 | setVerbosity() 2675 | _saveConfig() 2676 | _setRequestFromFile() 2677 | _cleanupOptions() 2678 | _cleanupEnvironment() 2679 | _purge() 2680 | _checkDependencies() 2681 | _createHomeDirectories() 2682 | _createTemporaryDirectory() 2683 | _basicOptionValidation() 2684 | _setProxyList() 2685 | _setTorProxySettings() 2686 | _setDNSServer() 2687 | _adjustLoggingFormatter() 2688 | _setMultipleTargets() 2689 | _listTamperingFunctions() 2690 | _setTamperingFunctions() 2691 | _setPreprocessFunctions() 2692 | _setTrafficOutputFP() 2693 | _setupHTTPCollector() 2694 | _setHttpChunked() 2695 | _checkWebSocket() 2696 | 2697 | parseTargetDirect() 2698 | 2699 | if any((conf.url, conf.logFile, conf.bulkFile, conf.requestFile, conf.googleDork)): 2700 | _setHostname() 2701 | _setHTTPTimeout() 2702 | _setHTTPExtraHeaders() 2703 | _setHTTPCookies() 2704 | _setHTTPReferer() 2705 | _setHTTPHost() 2706 | _setHTTPUserAgent() 2707 | _setHTTPAuthentication() 2708 | _setHTTPHandlers() 2709 | _setDNSCache() 2710 | _setSocketPreConnect() 2711 | _setSafeVisit() 2712 | _doSearch() 2713 | _setBulkMultipleTargets() 2714 | _checkTor() 2715 | _setCrawler() 2716 | _findPageForms() 2717 | _setDBMS() 2718 | _setTechnique() 2719 | 2720 | _setThreads() 2721 | _setOS() 2722 | _setWriteFile() 2723 | _setMetasploit() 2724 | _setDBMSAuthentication() 2725 | loadBoundaries() 2726 | loadPayloads() 2727 | _setPrefixSuffix() 2728 | update() 2729 | _loadQueries() 2730 | --------------------------------------------------------------------------------