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

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

daemon서버 A에서 실행 중인 데몬이 있습니다 .

daemon_adm.py데몬 프로세스 (서버 A) 를 제어하기 위한 매개변수 기반 스크립트가 있습니다 . 이 스크립트를 통해 사용자 입력에서 "메시지"를 삽입할 수 있습니다 daemon. 당신이 좋아하는 무엇이든 무료로 텍스트를 보내세요.

daemon_adm.py그런 다음 서버 B에는 phpseclib의 SSH2 클래스를 사용하여 PHP에서 사용되는 웹 인터페이스가 있습니다 .

사용자 입력을 명령줄에 전달하는 것은 권장되지 않지만 웹 서버 B에서 daemon_adm.py서버 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
?>

이것이 충분히 안전합니까, 아니면 복잡합니까?

- 편집하다 -

Barmar가 지적한 간접적인 해결책은 daemon_adm.py쉘에서 구문 분석 가능한 인수가 아닌 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쉘 특수 문자를 이스케이프하는 기능입니다. 세세exec확장을 수행하려면 보호할 문자열을 두 번 호출합니다.

이는 텍스트 문자열에서는 작동하지만 바이트 문자열에서는 작동하지 않습니다. 대부분의 쉘은 널 바이트를 통과시키지 않습니다.

오류가 덜 발생하고 임의의 바이트 문자열이 통과하도록 허용하는 또 다른 접근 방식은 다른 쪽 끝에서 실행 중인 항목을 변경해야 하는 것입니다.원격 명령의 표준 입력에 문자열 전달.

답변3

당신은 다음과 같은 일을 할 수 있습니다 ...

$ssh->enablePTY();
$ssh->exec('/path/to/daemon_adm.py');
$ssh->write('...');
echo $ssh->read();

관련 정보