Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit db94d24

Browse files
committed
Initial support for #2709 (more work to be done)
1 parent 116c1c8 commit db94d24

13 files changed

Lines changed: 59 additions & 45 deletions

File tree

lib/core/common.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3207,13 +3207,13 @@ def decodeIntToUnicode(value):
32073207

32083208
if Backend.isDbms(DBMS.MYSQL):
32093209
# https://github.com/sqlmapproject/sqlmap/issues/1531
3210-
retVal = getUnicode(raw, conf.charset or UNICODE_ENCODING)
3210+
retVal = getUnicode(raw, conf.encoding or UNICODE_ENCODING)
32113211
elif Backend.isDbms(DBMS.MSSQL):
32123212
retVal = getUnicode(raw, "UTF-16-BE")
32133213
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE):
32143214
retVal = unichr(value)
32153215
else:
3216-
retVal = getUnicode(raw, conf.charset)
3216+
retVal = getUnicode(raw, conf.encoding)
32173217
else:
32183218
retVal = getUnicode(chr(value))
32193219
except:

lib/core/option.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,8 +1409,8 @@ def _setHTTPExtraHeaders():
14091409
raise SqlmapSyntaxException(errMsg)
14101410

14111411
elif not conf.requestFile and len(conf.httpHeaders or []) < 2:
1412-
if conf.charset:
1413-
conf.httpHeaders.append((HTTP_HEADER.ACCEPT_CHARSET, "%s;q=0.7,*;q=0.1" % conf.charset))
1412+
if conf.encoding:
1413+
conf.httpHeaders.append((HTTP_HEADER.ACCEPT_CHARSET, "%s;q=0.7,*;q=0.1" % conf.encoding))
14141414

14151415
# Invalidating any caching mechanism in between
14161416
# Reference: http://stackoverflow.com/a/1383359
@@ -2577,15 +2577,15 @@ def _basicOptionValidation():
25772577
errMsg += "format <username>:<password> (e.g. \"root:pass\")"
25782578
raise SqlmapSyntaxException(errMsg)
25792579

2580-
if conf.charset:
2581-
_ = checkCharEncoding(conf.charset, False)
2580+
if conf.encoding:
2581+
_ = checkCharEncoding(conf.encoding, False)
25822582
if _ is None:
2583-
errMsg = "unknown charset '%s'. Please visit " % conf.charset
2583+
errMsg = "unknown charset '%s'. Please visit " % conf.encoding
25842584
errMsg += "'%s' to get the full list of " % CODECS_LIST_PAGE
25852585
errMsg += "supported charsets"
25862586
raise SqlmapSyntaxException(errMsg)
25872587
else:
2588-
conf.charset = _
2588+
conf.encoding = _
25892589

25902590
if conf.loadCookies:
25912591
if not os.path.exists(conf.loadCookies):

lib/core/optiondict.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@
201201
"crawlExclude": "string",
202202
"csvDel": "string",
203203
"dumpFormat": "string",
204+
"encoding": "string",
204205
"eta": "boolean",
205206
"flushSession": "boolean",
206207
"forms": "boolean",

lib/core/settings.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from lib.core.enums import OS
2020

2121
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
22-
VERSION = "1.1.9.22"
22+
VERSION = "1.1.9.23"
2323
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
2424
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
2525
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
@@ -67,6 +67,7 @@
6767
RANDOM_INTEGER_MARKER = "[RANDINT]"
6868
RANDOM_STRING_MARKER = "[RANDSTR]"
6969
SLEEP_TIME_MARKER = "[SLEEPTIME]"
70+
INFERENCE_MARKER = "[INFERENCE]"
7071

7172
PAYLOAD_DELIMITER = "__PAYLOAD_DELIMITER__"
7273
CHAR_INFERENCE_MARK = "%c"
@@ -175,6 +176,9 @@
175176
# Character used for operation "greater" in inference
176177
INFERENCE_GREATER_CHAR = ">"
177178

179+
# Character used for operation "greater or equal" in inference
180+
INFERENCE_GREATER_EQUALS_CHAR = ">="
181+
178182
# Character used for operation "equals" in inference
179183
INFERENCE_EQUALS_CHAR = "="
180184

lib/parse/cmdline.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -631,9 +631,6 @@ def cmdLineParser(argv=None):
631631
general.add_option("--binary-fields", dest="binaryFields",
632632
help="Result fields having binary values (e.g. \"digest\")")
633633

634-
general.add_option("--charset", dest="charset",
635-
help="Force character encoding used for data retrieval")
636-
637634
general.add_option("--check-internet", dest="checkInternet",
638635
action="store_true",
639636
help="Check Internet connection before assessing the target")
@@ -648,9 +645,15 @@ def cmdLineParser(argv=None):
648645
help="Delimiting character used in CSV output "
649646
"(default \"%s\")" % defaults.csvDel)
650647

648+
general.add_option("--charset", dest="charset",
649+
help="Blind SQL injection charset (e.g. \"0123456789abcdef\")")
650+
651651
general.add_option("--dump-format", dest="dumpFormat",
652652
help="Format of dumped data (CSV (default), HTML or SQLITE)")
653653

654+
general.add_option("--encoding", dest="encoding",
655+
help="Character encoding used for data retrieval (e.g. GBK)")
656+
654657
general.add_option("--eta", dest="eta",
655658
action="store_true",
656659
help="Display for each output the estimated time of arrival")

lib/request/basic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ def decodePage(page, contentEncoding, contentType):
279279
kb.pageCompress = False
280280
raise SqlmapCompressionException
281281

282-
if not conf.charset:
282+
if not conf.encoding:
283283
httpCharset, metaCharset = None, None
284284

285285
# Reference: http://stackoverflow.com/questions/1020892/python-urllib2-read-to-unicode
@@ -296,7 +296,7 @@ def decodePage(page, contentEncoding, contentType):
296296
else:
297297
kb.pageEncoding = None
298298
else:
299-
kb.pageEncoding = conf.charset
299+
kb.pageEncoding = conf.encoding
300300

301301
# can't do for all responses because we need to support binary files too
302302
if contentType and not isinstance(page, unicode) and "text/" in contentType.lower():

lib/takeover/web.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ def _webFileInject(self, fileContent, fileName, directory):
144144
randInt = randomInt()
145145
query += "OR %d=%d " % (randInt, randInt)
146146

147-
query += getSQLSnippet(DBMS.MYSQL, "write_file_limit", OUTFILE=outFile, HEXSTRING=hexencode(uplQuery, conf.charset))
147+
query += getSQLSnippet(DBMS.MYSQL, "write_file_limit", OUTFILE=outFile, HEXSTRING=hexencode(uplQuery, conf.encoding))
148148
query = agent.prefixQuery(query)
149149
query = agent.suffixQuery(query)
150150
payload = agent.payload(newValue=query)

lib/takeover/xp_cmdshell.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def xpCmdshellForgeCmd(self, cmd, insertIntoTable=None):
163163
# Obfuscate the command to execute, also useful to bypass filters
164164
# on single-quotes
165165
self._randStr = randomStr(lowercase=True)
166-
self._cmd = "0x%s" % hexencode(cmd, conf.charset)
166+
self._cmd = "0x%s" % hexencode(cmd, conf.encoding)
167167
self._forgedCmd = "DECLARE @%s VARCHAR(8000);" % self._randStr
168168
self._forgedCmd += "SET @%s=%s;" % (self._randStr, self._cmd)
169169

lib/techniques/blind/inference.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939
from lib.core.settings import INFERENCE_BLANK_BREAK
4040
from lib.core.settings import INFERENCE_UNKNOWN_CHAR
4141
from lib.core.settings import INFERENCE_GREATER_CHAR
42+
from lib.core.settings import INFERENCE_GREATER_EQUALS_CHAR
4243
from lib.core.settings import INFERENCE_EQUALS_CHAR
44+
from lib.core.settings import INFERENCE_MARKER
4345
from lib.core.settings import INFERENCE_NOT_EQUALS_CHAR
4446
from lib.core.settings import MAX_BISECTION_LENGTH
4547
from lib.core.settings import MAX_REVALIDATION_STEPS
@@ -67,7 +69,12 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
6769
partialValue = u""
6870
finalValue = None
6971
retrievedLength = 0
70-
asciiTbl = getCharset(charsetType)
72+
73+
if charsetType is None and conf.charset:
74+
asciiTbl = sorted(set(ord(_) for _ in conf.charset))
75+
else:
76+
asciiTbl = getCharset(charsetType)
77+
7178
threadData = getCurrentThreadData()
7279
timeBasedCompare = (kb.technique in (PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED))
7380
retVal = hashDBRetrieve(expression, checkConf=True)
@@ -109,7 +116,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
109116
elif (kb.fileReadMode or dump) and conf.firstChar is not None and (isinstance(conf.firstChar, int) or (isinstance(conf.firstChar, basestring) and conf.firstChar.isdigit())):
110117
firstChar = int(conf.firstChar) - 1
111118
if kb.fileReadMode:
112-
firstChar *= 2
119+
firstChar <<= 1
113120
elif isinstance(firstChar, basestring) and firstChar.isdigit() or isinstance(firstChar, int):
114121
firstChar = int(firstChar) - 1
115122
else:
@@ -271,7 +278,7 @@ def getChar(idx, charTbl=None, continuousOrder=True, expand=charsetType is None,
271278
lastCheck = False
272279
unexpectedCode = False
273280

274-
while len(charTbl) != 1:
281+
while len(charTbl) > 1:
275282
position = None
276283

277284
if charsetType is None:
@@ -444,23 +451,22 @@ def blindThread():
444451

445452
if threadData.shared.index[0] - firstChar >= length:
446453
kb.locks.index.release()
447-
448454
return
449455

450456
threadData.shared.index[0] += 1
451-
curidx = threadData.shared.index[0]
457+
currentCharIndex = threadData.shared.index[0]
452458
kb.locks.index.release()
453459

454460
if kb.threadContinue:
455461
charStart = time.time()
456-
val = getChar(curidx)
462+
val = getChar(currentCharIndex, asciiTbl, not(charsetType is None and conf.charset))
457463
if val is None:
458464
val = INFERENCE_UNKNOWN_CHAR
459465
else:
460466
break
461467

462468
with kb.locks.value:
463-
threadData.shared.value[curidx - 1 - firstChar] = val
469+
threadData.shared.value[currentCharIndex - 1 - firstChar] = val
464470
currentValue = list(threadData.shared.value)
465471

466472
if kb.threadContinue:
@@ -488,10 +494,10 @@ def blindThread():
488494
count += 1 if currentValue[i] is not None else 0
489495

490496
if startCharIndex > 0:
491-
output = '..' + output[2:]
497+
output = ".." + output[2:]
492498

493499
if (endCharIndex - startCharIndex == conf.progressWidth) and (endCharIndex < length - 1):
494-
output = output[:-2] + '..'
500+
output = output[:-2] + ".."
495501

496502
if conf.verbose in (1, 2) and not showEta and not conf.api:
497503
_ = count - firstChar
@@ -549,7 +555,7 @@ def blindThread():
549555
testValue = unescaper.escape("'%s'" % commonValue) if "'" not in commonValue else unescaper.escape("%s" % commonValue, quote=False)
550556

551557
query = kb.injection.data[kb.technique].vector
552-
query = agent.prefixQuery(query.replace("[INFERENCE]", "(%s)=%s" % (expressionUnescaped, testValue)))
558+
query = agent.prefixQuery(query.replace(INFERENCE_MARKER, "(%s)%s%s" % (expressionUnescaped, INFERENCE_EQUALS_CHAR, testValue)))
553559
query = agent.suffixQuery(query)
554560

555561
result = Request.queryPage(agent.payload(newValue=query), timeBasedCompare=timeBasedCompare, raise404=False)
@@ -573,7 +579,7 @@ def blindThread():
573579
testValue = unescaper.escape("'%s'" % commonPattern) if "'" not in commonPattern else unescaper.escape("%s" % commonPattern, quote=False)
574580

575581
query = kb.injection.data[kb.technique].vector
576-
query = agent.prefixQuery(query.replace("[INFERENCE]", "(%s)=%s" % (subquery, testValue)))
582+
query = agent.prefixQuery(query.replace(INFERENCE_MARKER, "(%s)=%s" % (subquery, testValue)))
577583
query = agent.suffixQuery(query)
578584

579585
result = Request.queryPage(agent.payload(newValue=query), timeBasedCompare=timeBasedCompare, raise404=False)
@@ -594,9 +600,9 @@ def blindThread():
594600
# If we had no luck with commonValue and common charset,
595601
# use the returned other charset
596602
if not val:
597-
val = getChar(index, otherCharset, otherCharset == asciiTbl)
603+
val = getChar(index, otherCharset, otherCharset==asciiTbl)
598604
else:
599-
val = getChar(index, asciiTbl)
605+
val = getChar(index, asciiTbl, not(charsetType is None and conf.charset))
600606

601607
if val is None:
602608
finalValue = partialValue

plugins/dbms/mssqlserver/filesystem.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def _dataToScr(self, fileContent, chunkName):
4646
scrString = ""
4747

4848
for lineChar in fileContent[fileLine:fileLine + lineLen]:
49-
strLineChar = hexencode(lineChar, conf.charset)
49+
strLineChar = hexencode(lineChar, conf.encoding)
5050

5151
if not scrString:
5252
scrString = "e %x %s" % (lineAddr, strLineChar)

0 commit comments

Comments
 (0)