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

Skip to content

Commit e7ffc8f

Browse files
committed
Adding support for STDIN pipe (e.g. '... -r - ...')
1 parent bf83a4d commit e7ffc8f

5 files changed

Lines changed: 51 additions & 33 deletions

File tree

lib/core/common.py

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
from lib.core.settings import SAFE_VARIABLE_MARKER
161161
from lib.core.settings import SENSITIVE_DATA_REGEX
162162
from lib.core.settings import SENSITIVE_OPTIONS
163+
from lib.core.settings import STDIN_PIPE_DASH
163164
from lib.core.settings import SUPPORTED_DBMS
164165
from lib.core.settings import TEXT_TAG_REGEX
165166
from lib.core.settings import TIME_STDEV_COEFF
@@ -1165,6 +1166,14 @@ def getHeader(headers, key):
11651166
break
11661167
return retVal
11671168

1169+
def checkPipedInput():
1170+
"""
1171+
Checks whether input to program has been provided via standard input (e.g. cat /tmp/req.txt | python sqlmap.py -r -)
1172+
# Reference: https://stackoverflow.com/a/33873570
1173+
"""
1174+
1175+
return not os.isatty(sys.stdin.fileno())
1176+
11681177
def checkFile(filename, raiseOnError=True):
11691178
"""
11701179
Checks for file existence and readability
@@ -1178,19 +1187,22 @@ def checkFile(filename, raiseOnError=True):
11781187
if filename:
11791188
filename = filename.strip('"\'')
11801189

1181-
try:
1182-
if filename is None or not os.path.isfile(filename):
1183-
valid = False
1184-
except:
1185-
valid = False
1186-
1187-
if valid:
1190+
if filename == STDIN_PIPE_DASH:
1191+
return checkPipedInput()
1192+
else:
11881193
try:
1189-
with open(filename, "rb"):
1190-
pass
1194+
if filename is None or not os.path.isfile(filename):
1195+
valid = False
11911196
except:
11921197
valid = False
11931198

1199+
if valid:
1200+
try:
1201+
with open(filename, "rb"):
1202+
pass
1203+
except:
1204+
valid = False
1205+
11941206
if not valid and raiseOnError:
11951207
raise SqlmapSystemException("unable to read file '%s'" % filename)
11961208

@@ -3305,13 +3317,19 @@ def openFile(filename, mode='r', encoding=UNICODE_ENCODING, errors="replace", bu
33053317
Returns file handle of a given filename
33063318
"""
33073319

3308-
try:
3309-
return codecs.open(filename, mode, encoding, errors, buffering)
3310-
except IOError:
3311-
errMsg = "there has been a file opening error for filename '%s'. " % filename
3312-
errMsg += "Please check %s permissions on a file " % ("write" if mode and ('w' in mode or 'a' in mode or '+' in mode) else "read")
3313-
errMsg += "and that it's not locked by another process."
3314-
raise SqlmapSystemException(errMsg)
3320+
if filename == STDIN_PIPE_DASH:
3321+
if filename not in kb.cache.content:
3322+
kb.cache.content[filename] = sys.stdin.read()
3323+
3324+
return contextlib.closing(StringIO(readCachedFileContent(filename)))
3325+
else:
3326+
try:
3327+
return codecs.open(filename, mode, encoding, errors, buffering)
3328+
except IOError:
3329+
errMsg = "there has been a file opening error for filename '%s'. " % filename
3330+
errMsg += "Please check %s permissions on a file " % ("write" if mode and ('w' in mode or 'a' in mode or '+' in mode) else "read")
3331+
errMsg += "and that it's not locked by another process."
3332+
raise SqlmapSystemException(errMsg)
33153333

33163334
def decodeIntToUnicode(value):
33173335
"""
@@ -4797,14 +4815,7 @@ def _parseBurpLog(content):
47974815
if not(conf.scope and not re.search(conf.scope, url, re.I)):
47984816
yield (url, conf.method or method, data, cookie, tuple(headers))
47994817

4800-
checkFile(reqFile)
4801-
try:
4802-
with openFile(reqFile, "rb") as f:
4803-
content = f.read()
4804-
except (IOError, OSError, MemoryError) as ex:
4805-
errMsg = "something went wrong while trying "
4806-
errMsg += "to read the content of file '%s' ('%s')" % (reqFile, getSafeExString(ex))
4807-
raise SqlmapSystemException(errMsg)
4818+
content = readCachedFileContent(reqFile)
48084819

48094820
if conf.scope:
48104821
logger.info("using regular expression '%s' for filtering targets" % conf.scope)

lib/core/option.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ def _setMultipleTargets():
226226
errMsg = "the specified list of targets does not exist"
227227
raise SqlmapFilePathException(errMsg)
228228

229-
if os.path.isfile(conf.logFile):
229+
if checkFile(conf.logFile, False):
230230
for target in parseRequestFile(conf.logFile):
231231
url, _, data, _, _ = target
232232
key = re.sub(r"(\w+=)[^%s ]*" % (conf.paramDel or DEFAULT_GET_POST_DELIMITER), r"\g<1>", "%s %s" % (url, data))
@@ -292,7 +292,7 @@ def _setRequestFromFile():
292292
conf.requestFile = safeExpandUser(conf.requestFile)
293293
seen = set()
294294

295-
if not os.path.isfile(conf.requestFile):
295+
if not checkFile(conf.requestFile, False):
296296
errMsg = "specified HTTP request file '%s' " % conf.requestFile
297297
errMsg += "does not exist"
298298
raise SqlmapFilePathException(errMsg)
@@ -309,7 +309,7 @@ def _setRequestFromFile():
309309
if conf.secondReq:
310310
conf.secondReq = safeExpandUser(conf.secondReq)
311311

312-
if not os.path.isfile(conf.secondReq):
312+
if not checkFile(conf.secondReq, False):
313313
errMsg = "specified second-order HTTP request file '%s' " % conf.secondReq
314314
errMsg += "does not exist"
315315
raise SqlmapFilePathException(errMsg)
@@ -411,7 +411,7 @@ def _setBulkMultipleTargets():
411411
infoMsg = "parsing multiple targets list from '%s'" % conf.bulkFile
412412
logger.info(infoMsg)
413413

414-
if not os.path.isfile(conf.bulkFile):
414+
if not checkFile(conf.bulkFile, False):
415415
errMsg = "the specified bulk file "
416416
errMsg += "does not exist"
417417
raise SqlmapFilePathException(errMsg)

lib/core/settings.py

Lines changed: 4 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.3.3.29"
22+
VERSION = "1.3.3.30"
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)
@@ -222,6 +222,9 @@
222222
except LookupError:
223223
DEFAULT_PAGE_ENCODING = "utf8"
224224

225+
# Marker for program piped input
226+
STDIN_PIPE_DASH = '-'
227+
225228
# URL used in dummy runs
226229
DUMMY_URL = "http://foo/bar?id=1"
227230

sqlmap.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040

4141
from lib.core.common import banner
4242
from lib.core.common import checkIntegrity
43+
from lib.core.common import checkPipedInput
4344
from lib.core.common import createGithubIssue
4445
from lib.core.common import dataToStdout
4546
from lib.core.common import getSafeExString
@@ -131,6 +132,9 @@ def main():
131132
cmdLineOptions.update(cmdLineParser().__dict__)
132133
initOptions(cmdLineOptions)
133134

135+
if checkPipedInput():
136+
conf.batch = True
137+
134138
if conf.get("api"):
135139
# heavy imports
136140
from lib.utils.api import StdDbOut

txt/checksum.md5

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ c1da277517c7ec4c23e953a51b51e203 lib/controller/handler.py
3030
fb6be55d21a70765e35549af2484f762 lib/controller/__init__.py
3131
ed7874be0d2d3802f3d20184f2b280d5 lib/core/agent.py
3232
a932126e7d80e545c5d44af178d0bc0c lib/core/bigarray.py
33-
c775aa0369c9eb044efb5065f60a25cd lib/core/common.py
33+
b096680d917729fd9658f9b75d44bb3b lib/core/common.py
3434
de8d27ae6241163ff9e97aa9e7c51a18 lib/core/convert.py
3535
abcb1121eb56d3401839d14e8ed06b6e lib/core/data.py
3636
f89512ef3ebea85611c5dde6c891b657 lib/core/datatype.py
@@ -43,14 +43,14 @@ f89512ef3ebea85611c5dde6c891b657 lib/core/datatype.py
4343
fb6be55d21a70765e35549af2484f762 lib/core/__init__.py
4444
18c896b157b03af716542e5fe9233ef9 lib/core/log.py
4545
947f41084e551ff3b7ef7dda2f25ef20 lib/core/optiondict.py
46-
63c5c71af3fd05cd0a1c97dbbe7216b5 lib/core/option.py
46+
94679a06c134ca5c1db1e435e1cb9fb1 lib/core/option.py
4747
fe370021c6bc99daf44b2bfc0d1effb3 lib/core/patch.py
4848
4b12aa67fbf6c973d12e54cf9cb54ea0 lib/core/profiling.py
4949
d5ef43fe3cdd6c2602d7db45651f9ceb lib/core/readlineng.py
5050
7d8a22c582ad201f65b73225e4456170 lib/core/replication.py
5151
3179d34f371e0295dd4604568fb30bcd lib/core/revision.py
5252
d6269c55789f78cf707e09a0f5b45443 lib/core/session.py
53-
96b86cf1a93128720caa88a22f604ea1 lib/core/settings.py
53+
2d4b155258f2ae85c7f287c58742e1fb lib/core/settings.py
5454
4483b4a5b601d8f1c4281071dff21ecc lib/core/shell.py
5555
10fd19b0716ed261e6d04f311f6f527c lib/core/subprocessng.py
5656
10d7e4f7ba2502cce5cf69223c52eddc lib/core/target.py
@@ -236,7 +236,7 @@ ec2ba8c757ac96425dcd2b97970edd3a shell/stagers/stager.asp_
236236
0c48ddb1feb7e38a951ef05a0d48e032 shell/stagers/stager.jsp_
237237
2f9e459a4cf6a58680978cdce5ff7971 shell/stagers/stager.php_
238238
41522f8ad02ac133ca0aeaab374c36a8 sqlmapapi.py
239-
a436dd078b06bf664637b27f42889a35 sqlmap.py
239+
05fe39a2fbd1cff87cb43c5c36e64365 sqlmap.py
240240
772fb3dd15edc9d4055ab9f9dee0c203 tamper/0x2char.py
241241
3d89a5c4c33d4d1d9303f5e3bd11f0ae tamper/apostrophemask.py
242242
1fd0eec63970728c1e6628b2e4c21d81 tamper/apostrophenullencode.py

0 commit comments

Comments
 (0)