
daemon
서버 A에서 실행 중인 데몬이 있습니다 .
daemon_adm.py
여기에는 데몬 (서버 A) 을 제어하는 인수 기반 스크립트가 있습니다 . 이 스크립트를 통해 사용자 입력에서 오는 "메시지"를 삽입할 수 있습니다 daemon
. 당신이 원하는 무엇이든 무료 텍스트입니다.
daemon_adm.py
그런 다음 phpseclib의 SSH2 클래스를 사용하는 PHP 용 서버 B에 웹 인터페이스가 있습니다 .
daemon_adm.py
사용자 입력을 명령줄에 전달하는 것이 권장되지 않는다는 것을 알고 있지만 웹 서버 B에서 서버 A 로 텍스트를 전달하는 방법이 있어야 합니다.
명령줄 유틸리티에 텍스트를 인수로 안전하게 전달하려면 어떻게 해야 합니까?
인수를 에코하고 다음과 같이 파이프하더라도 daemon_adm.py
:
<?php
$command = '/path/to/daemon_adm.py "'.$text.'"';
ssh->exec($command);
// or whatever other library or programming language
?>
이 명령은 형식화된 문자열을 사용하여 SSH 인터페이스에 의해 실행되므로 코드가 삽입될 수 있습니다.
<?php
$text = 'safetext"; echo "hazard"';
$command = '/path/to/daemon_adm.py "'.$text.'"';
ssh->exec($command);
// command sent: /path/to/daemon_adm.py "safetext"; echo "hazard"
?>
현재 염두에 두고 있는 옵션은 모든 사용자 입력을 base64로 인코딩하고(내가 아는 한 문자 집합에 따옴표와 공백을 사용하지 않음) daemon_adm.py
다음과 같이 내부에서 디코딩하는 것입니다.
<?php
$text = 'safetext"; echo "hazard"';
// Enconding it to base64
$command = '/path/to/daemon_adm.py '.$encoded_text;
ssh->exec($command);
// command sent: /path/to/daemon_adm.py c2FmZXRleHQiOyBlY2hvICJoYXphcmQi
?>
이것은 충분히 안전합니까, 아니면 복잡합니까?
-- 편집하다 --
daemon_adm.py
Barmar가 지적한 간접적인 해결책 중 하나는 쉘 구문 분석 가능한 인수가 아닌 stdin의 텍스트 데이터를 허용하는 것입니다 .
답변1
ssh2::exec()
원격 명령의 stdin
, stdout
및 에 연결된 스트림을 반환합니다 . stderr
그래서 당신은 할 수 있습니다 :
$command = '/path/to/daemon_adm.py';
$stream = $ssh->exec($command);
fwrite($stream, "$text\n");
stdin을 통해 매개변수를 전달하지 않으려면 다음을 사용할 수 있습니다.escapeshellarg()
:
$command = '/path/to/daemon_adm.py ' . escapeshellarg($text);
$ssh->exec($command);
답변2
셸 조각에 문자열을 삽입하고 셸이 문자열을 문자 그대로 해석하도록 정렬하려면 비교적 간단한 두 가지 접근 방식이 있습니다.
- 문자열을 작은따옴표로 묶고 각 작은따옴표를
'
4자 문자열로 바꿉니다'\''
. - 각 ASCII 구두점 문자 앞에는
\
(다른 문자도 접두사로 사용할 수 있음)을 붙이고 줄 바꿈을''
또는""
(작은 따옴표 또는 큰 따옴표 사이에 줄 바꿈)로 바꿉니다.
SSH를 통해 원격 명령을 호출하는 경우 원격 셸이 명령을 확장한다는 점을 명심하고, 추가적으로 로컬 셸을 통해 SSH를 호출하는 경우 로컬 셸도 확장을 수행하므로 인용을 두 번 해야 합니다.
PHP는 다음을 제공합니다.escapeshellarg
쉘 특수 문자를 이스케이프하는 함수입니다. Snceexec
확장을 수행하려면 보호하려는 문자열에 대해 두 번 호출하세요.
이는 텍스트 문자열에는 적합하지만 바이트 문자열에는 적합하지 않습니다. 대부분의 쉘은 널 바이트를 통과시키지 않습니다.
오류가 덜 발생하고 임의의 바이트 문자열을 허용하지만 다른 쪽 끝에서 실행되는 것을 변경해야 하는 또 다른 접근 방식은 다음과 같습니다.원격 명령의 표준 입력에 문자열을 전달합니다..
답변3
당신은 다음과 같은 것을 할 수 있습니다 ...
$ssh->enablePTY();
$ssh->exec('/path/to/daemon_adm.py');
$ssh->write('...');
echo $ssh->read();