사용자 입력을 명령에 안전하게 전달

사용자 입력을 명령에 안전하게 전달

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.pyBarmar가 지적한 간접적인 해결책 중 하나는 쉘 구문 분석 가능한 인수가 아닌 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();

관련 정보