Skip to content

Commit 5a9dc15

Browse files
committed
Introduction of --base64-safe
1 parent f1fd080 commit 5a9dc15

File tree

8 files changed

+31
-6
lines changed

8 files changed

+31
-6
lines changed

lib/core/agent.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,12 @@ def payload(self, place=None, parameter=None, value=None, newValue=None, where=N
183183
newValue = self.adjustLateValues(newValue)
184184

185185
# TODO: support for POST_HINT
186-
newValue = encodeBase64(newValue, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
187-
origValue = encodeBase64(origValue, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
186+
newValue = encodeBase64(newValue, binary=False, encoding=conf.encoding or UNICODE_ENCODING, safe=conf.base64Safe)
187+
188+
if parameter in kb.base64Originals:
189+
origValue = kb.base64Originals[parameter]
190+
else:
191+
origValue = encodeBase64(origValue, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
188192

189193
if place in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER):
190194
_ = "%s%s" % (origValue, kb.customInjectionMark)

lib/core/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ def paramToDict(place, parameters=None):
631631

632632
if parameter in (conf.base64Parameter or []):
633633
try:
634-
oldValue = value
634+
kb.base64Originals[parameter] = oldValue = value
635635
value = decodeBase64(value, binary=False, encoding=conf.encoding or UNICODE_ENCODING)
636636
parameters = re.sub(r"\b%s(\b|\Z)" % re.escape(oldValue), value, parameters)
637637
except:

lib/core/convert.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ def decodeBase64(value, binary=True, encoding=None):
198198
True
199199
>>> decodeBase64("MTIz", binary=False)
200200
'123'
201-
>>> decodeBase64("A-B_CD") == decodeBase64("A+B/CD")
201+
>>> decodeBase64("A-B_CDE") == decodeBase64("A+B/CDE")
202202
True
203203
>>> decodeBase64(b"MTIzNA") == b"1234"
204204
True
@@ -231,7 +231,7 @@ def decodeBase64(value, binary=True, encoding=None):
231231

232232
return retVal
233233

234-
def encodeBase64(value, binary=True, encoding=None, padding=True):
234+
def encodeBase64(value, binary=True, encoding=None, padding=True, safe=False):
235235
"""
236236
Returns a decoded representation of provided Base64 value
237237
@@ -241,6 +241,8 @@ def encodeBase64(value, binary=True, encoding=None, padding=True):
241241
'MTIzNA=='
242242
>>> encodeBase64(u"1234", binary=False, padding=False)
243243
'MTIzNA'
244+
>>> encodeBase64(decodeBase64("A-B_CDE"), binary=False, safe=True)
245+
'A-B_CDE'
244246
"""
245247

246248
if value is None:
@@ -254,6 +256,16 @@ def encodeBase64(value, binary=True, encoding=None, padding=True):
254256
if not binary:
255257
retVal = getText(retVal, encoding)
256258

259+
if safe:
260+
padding = False
261+
262+
# Reference: https://en.wikipedia.org/wiki/Base64#URL_applications
263+
# Reference: https://perldoc.perl.org/MIME/Base64.html
264+
if isinstance(retVal, bytes):
265+
retVal = retVal.replace(b'+', b'-').replace(b'/', b'_')
266+
else:
267+
retVal = retVal.replace('+', '-').replace('/', '_')
268+
257269
if not padding:
258270
retVal = retVal.rstrip(b'=' if isinstance(retVal, bytes) else '=')
259271

lib/core/option.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,6 +1856,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
18561856
kb.arch = None
18571857
kb.authHeader = None
18581858
kb.bannerFp = AttribDict()
1859+
kb.base64Originals = {}
18591860
kb.binaryField = False
18601861
kb.browserVerification = None
18611862

lib/core/optiondict.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@
203203
"answers": "string",
204204
"batch": "boolean",
205205
"base64Parameter": "string",
206+
"base64Safe": "boolean",
206207
"binaryFields": "string",
207208
"charset": "string",
208209
"checkInternet": "boolean",

lib/core/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from thirdparty.six import unichr as _unichr
1919

2020
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
21-
VERSION = "1.4.8.6"
21+
VERSION = "1.4.8.7"
2222
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
2323
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
2424
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)

lib/parse/cmdline.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,9 @@ def cmdLineParser(argv=None):
622622
general.add_argument("--base64", dest="base64Parameter",
623623
help="Parameter(s) containing Base64 encoded data")
624624

625+
general.add_argument("--base64-safe", dest="base64Safe", action="store_true",
626+
help="Use URL and filename safe Base64 alphabet")
627+
625628
general.add_argument("--batch", dest="batch", action="store_true",
626629
help="Never ask for user input, use the default behavior")
627630

sqlmap.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,10 @@ answers =
699699
# Parameter(s) containing Base64 encoded data
700700
base64Parameter =
701701

702+
# Use URL and filename safe Base64 alphabet (Reference: https://en.wikipedia.org/wiki/Base64#URL_applications).
703+
# Valid: True or False
704+
base64Safe = False
705+
702706
# Never ask for user input, use the default behaviour.
703707
# Valid: True or False
704708
batch = False

0 commit comments

Comments
 (0)