├── 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 |
--------------------------------------------------------------------------------