В идеале , вы должны сконструировать это таким образом, чтобы вообще не подвергать вас этой проблеме - то есть, пусть интерпретатор Python выполняет работу по генерации правильно заключенных в кавычкиstring (а затем снова заключить его в кавычки для безопасной передачи в ssh).
try:
from shlex import quote # Python 3
except ImportError:
from pipes import quote # Python 2
import subprocess
# specify your commands the way they're actually seen by the operating system -- with
# lists of strings as argument vectors.
rmt_pipeline = [[ 'lastlog', '-u', 'ubuntu' ],
[ 'grep', '-v', 'Latest' ],
[ 'awk', '{$1="";$2="";$3="";print $0 }' ]]
# ...then, let shlex.quote() or pipes.quote() determine how to make those lists be valid
# shell syntax, as expected by the remote copy of sh -c '...' invoked by ssh
rmt_pipeline_str = ' | '.join(' '.join(quote(word) for word in piece)
for piece in rmt_pipeline)
# ...finally, generate the argument vector for our local copy of ssh...
ssh_cmd = [ 'ssh', '-i', '/Users/abcxyz/keypair', rmt_pipeline_str ]
# and actually invoke it.
user_output = subprocess.Popen(ssh_cmd, stdout=subprocess.PIPE).stdout
Если вы действительно хотите использовать os.popen()
- что не следует, как Pythonдокументация явно предлагает использовать subprocess
вместо - вы можете заменить последнюю строку на:
ssh_cmd_str = ' '.join(quote(word) for word in ssh_cmd)
user_output = os.popen(ssh_cmd_str)
В операционных системах семейства UNIX выполнение всех программ происходит через execve()
syscall, который передает список строк C.Указав этот список самостоятельно, вы получаете максимально возможный контроль над тем, как происходит выполнение, и предотвращаете атаки с внедрением оболочки (когда пользователь, уполномоченный предоставлять параметр для одной из ваших программ, передает содержимое, интерпретируемое оболочкой как синтаксис, а не какданные, и, следовательно, вместо этого запускает совершенно другую программу или операцию косвенного обращения.