Adding support for STDIN pipe (e.g. '... -r - ...')

This commit is contained in:
Miroslav Stampar
2019-03-15 15:36:13 +01:00
parent bf83a4d1f8
commit e7ffc8f9b1
5 changed files with 51 additions and 33 deletions

View File

@@ -160,6 +160,7 @@ from lib.core.settings import REFLECTIVE_MISS_THRESHOLD
from lib.core.settings import SAFE_VARIABLE_MARKER
from lib.core.settings import SENSITIVE_DATA_REGEX
from lib.core.settings import SENSITIVE_OPTIONS
from lib.core.settings import STDIN_PIPE_DASH
from lib.core.settings import SUPPORTED_DBMS
from lib.core.settings import TEXT_TAG_REGEX
from lib.core.settings import TIME_STDEV_COEFF
@@ -1165,6 +1166,14 @@ def getHeader(headers, key):
break
return retVal
def checkPipedInput():
"""
Checks whether input to program has been provided via standard input (e.g. cat /tmp/req.txt | python sqlmap.py -r -)
# Reference: https://stackoverflow.com/a/33873570
"""
return not os.isatty(sys.stdin.fileno())
def checkFile(filename, raiseOnError=True):
"""
Checks for file existence and readability
@@ -1178,19 +1187,22 @@ def checkFile(filename, raiseOnError=True):
if filename:
filename = filename.strip('"\'')
try:
if filename is None or not os.path.isfile(filename):
valid = False
except:
valid = False
if valid:
if filename == STDIN_PIPE_DASH:
return checkPipedInput()
else:
try:
with open(filename, "rb"):
pass
if filename is None or not os.path.isfile(filename):
valid = False
except:
valid = False
if valid:
try:
with open(filename, "rb"):
pass
except:
valid = False
if not valid and raiseOnError:
raise SqlmapSystemException("unable to read file '%s'" % filename)
@@ -3305,13 +3317,19 @@ def openFile(filename, mode='r', encoding=UNICODE_ENCODING, errors="replace", bu
Returns file handle of a given filename
"""
try:
return codecs.open(filename, mode, encoding, errors, buffering)
except IOError:
errMsg = "there has been a file opening error for filename '%s'. " % filename
errMsg += "Please check %s permissions on a file " % ("write" if mode and ('w' in mode or 'a' in mode or '+' in mode) else "read")
errMsg += "and that it's not locked by another process."
raise SqlmapSystemException(errMsg)
if filename == STDIN_PIPE_DASH:
if filename not in kb.cache.content:
kb.cache.content[filename] = sys.stdin.read()
return contextlib.closing(StringIO(readCachedFileContent(filename)))
else:
try:
return codecs.open(filename, mode, encoding, errors, buffering)
except IOError:
errMsg = "there has been a file opening error for filename '%s'. " % filename
errMsg += "Please check %s permissions on a file " % ("write" if mode and ('w' in mode or 'a' in mode or '+' in mode) else "read")
errMsg += "and that it's not locked by another process."
raise SqlmapSystemException(errMsg)
def decodeIntToUnicode(value):
"""
@@ -4797,14 +4815,7 @@ def parseRequestFile(reqFile, checkParams=True):
if not(conf.scope and not re.search(conf.scope, url, re.I)):
yield (url, conf.method or method, data, cookie, tuple(headers))
checkFile(reqFile)
try:
with openFile(reqFile, "rb") as f:
content = f.read()
except (IOError, OSError, MemoryError) as ex:
errMsg = "something went wrong while trying "
errMsg += "to read the content of file '%s' ('%s')" % (reqFile, getSafeExString(ex))
raise SqlmapSystemException(errMsg)
content = readCachedFileContent(reqFile)
if conf.scope:
logger.info("using regular expression '%s' for filtering targets" % conf.scope)

View File

@@ -226,7 +226,7 @@ def _setMultipleTargets():
errMsg = "the specified list of targets does not exist"
raise SqlmapFilePathException(errMsg)
if os.path.isfile(conf.logFile):
if checkFile(conf.logFile, False):
for target in parseRequestFile(conf.logFile):
url, _, data, _, _ = target
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():
conf.requestFile = safeExpandUser(conf.requestFile)
seen = set()
if not os.path.isfile(conf.requestFile):
if not checkFile(conf.requestFile, False):
errMsg = "specified HTTP request file '%s' " % conf.requestFile
errMsg += "does not exist"
raise SqlmapFilePathException(errMsg)
@@ -309,7 +309,7 @@ def _setRequestFromFile():
if conf.secondReq:
conf.secondReq = safeExpandUser(conf.secondReq)
if not os.path.isfile(conf.secondReq):
if not checkFile(conf.secondReq, False):
errMsg = "specified second-order HTTP request file '%s' " % conf.secondReq
errMsg += "does not exist"
raise SqlmapFilePathException(errMsg)
@@ -411,7 +411,7 @@ def _setBulkMultipleTargets():
infoMsg = "parsing multiple targets list from '%s'" % conf.bulkFile
logger.info(infoMsg)
if not os.path.isfile(conf.bulkFile):
if not checkFile(conf.bulkFile, False):
errMsg = "the specified bulk file "
errMsg += "does not exist"
raise SqlmapFilePathException(errMsg)

View File

@@ -19,7 +19,7 @@ from lib.core.enums import DBMS_DIRECTORY_NAME
from lib.core.enums import OS
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.3.3.29"
VERSION = "1.3.3.30"
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
@@ -222,6 +222,9 @@ try:
except LookupError:
DEFAULT_PAGE_ENCODING = "utf8"
# Marker for program piped input
STDIN_PIPE_DASH = '-'
# URL used in dummy runs
DUMMY_URL = "http://foo/bar?id=1"