mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-09-27 13:34:33 +00:00
Minor patch for shellExec (adding timeout)
This commit is contained in:
parent
a3d29174fb
commit
c36d056481
3 changed files with 44 additions and 5 deletions
|
|
@ -27,6 +27,7 @@ import platform
|
|||
import posixpath
|
||||
import random
|
||||
import re
|
||||
import signal
|
||||
import socket
|
||||
import string
|
||||
import subprocess
|
||||
|
|
@ -2476,22 +2477,58 @@ def getConsoleWidth(default=80):
|
|||
|
||||
return width or default
|
||||
|
||||
def shellExec(cmd):
|
||||
def shellExec(cmd, timeout=None):
|
||||
"""
|
||||
Executes arbitrary shell command
|
||||
Executes arbitrary shell command, optionally bounded by 'timeout' seconds - killing (and
|
||||
flagging) a hung child instead of blocking forever, as callers otherwise have no other
|
||||
watchdog around this call (e.g. --vuln-test runs one such call per entry, unattended)
|
||||
|
||||
>>> shellExec('echo 1').strip() == '1'
|
||||
True
|
||||
"""
|
||||
|
||||
retVal = ""
|
||||
timedOut = []
|
||||
|
||||
try:
|
||||
retVal = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0] or ""
|
||||
popenKwargs = {"shell": True, "stdout": subprocess.PIPE, "stderr": subprocess.STDOUT}
|
||||
if timeout:
|
||||
# shell=True's Popen.pid is the shell, not the (possibly grandchild) command it runs -
|
||||
# killing just that pid leaves the real child holding the stdout pipe open, so
|
||||
# communicate() keeps blocking past the deadline; run it in its own group/session instead
|
||||
# so the whole tree can be killed at once
|
||||
if IS_WIN:
|
||||
popenKwargs["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP
|
||||
else:
|
||||
popenKwargs["preexec_fn"] = os.setsid
|
||||
|
||||
process = subprocess.Popen(cmd, **popenKwargs)
|
||||
|
||||
def _kill():
|
||||
timedOut.append(True)
|
||||
try:
|
||||
if IS_WIN:
|
||||
subprocess.call(["taskkill", "/F", "/T", "/PID", str(process.pid)])
|
||||
else:
|
||||
os.killpg(os.getpgid(process.pid), signal.SIGKILL)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
timer = threading.Timer(timeout, _kill) if timeout else None
|
||||
if timer:
|
||||
timer.daemon = True
|
||||
timer.start()
|
||||
|
||||
retVal = process.communicate()[0] or ""
|
||||
|
||||
if timer:
|
||||
timer.cancel()
|
||||
except Exception as ex:
|
||||
retVal = getSafeExString(ex)
|
||||
finally:
|
||||
retVal = getText(retVal)
|
||||
if timedOut:
|
||||
retVal += "\n[shellExec] child process tree killed after exceeding %d-second timeout" % timeout
|
||||
|
||||
return retVal
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ from lib.core.enums import OS
|
|||
from thirdparty import six
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.10.9.24"
|
||||
VERSION = "1.10.9.25"
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -268,7 +268,9 @@ def vulnTest(tests=None, label="vuln"):
|
|||
|
||||
os.environ["SQLMAP_UNSAFE_EVAL"] = '1'
|
||||
|
||||
output = shellExec(cmd)
|
||||
# bounded well above the slowest known entry (GraphQL, ~96s) - a hung entry fails fast and
|
||||
# visibly instead of silently burning the whole CI job's timeout (see #6129 CI investigation)
|
||||
output = shellExec(cmd, timeout=180)
|
||||
|
||||
if not all((check in output if not check.startswith('~') else check[1:] not in output) for check in checks) or "unhandled exception" in output:
|
||||
dataToStdout("---\n\n$ %s\n" % cmd)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue