Files
Gnuboard7/app/Rules/AllowedShellCommand.php
HeuJung 2fb452aa44 fix(security): 스케줄 셸 인터프리터 인라인 코드 우회 차단
셸 스케줄 검증이 첫 토큰 basename 만 화이트리스트와 대조하고 뒤 인자를
검증하지 않아, 운영자가 bash 를 등록하면 `bash -c id` 로 임의 OS 명령이
실행됐다(KVE-2026-1653). 인터프리터는 범용 크론 용도로 등록을 허용하되,
스크립트 자리(첫 인자)에 형태 규칙을 적용해 인라인 코드·상대경로·트래버설·
artisan 우회·완전거부형(env/awk/make 등)을 저장·실행 양쪽에서 거부한다.
2026-08-17 20:59:42 +09:00

58 lines
2.0 KiB
PHP

<?php
namespace App\Rules;
use App\Support\ScheduleCommandValidator;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* Shell 타입 스케줄의 command 가 실행 허용된 명령인지 검증하는 Custom Rule.
*
* 스케줄 생성 권한만 위임받은 계정이 임의 OS 명령을 서버에서 실행하는 것을 저장 시점에 차단한다.
* 허용 여부는 `config/schedule_security.php` 의 opt-in 게이트와 실행 파일 화이트리스트가 결정하며,
* 관리자 환경설정에 노출되지 않으므로 위임 관리자가 스스로 범위를 넓힐 수 없다.
*/
class AllowedShellCommand implements ValidationRule
{
/**
* 값이 실행 허용된 shell 명령인지 검증합니다.
*
* @param string $attribute 검증 대상 필드명
* @param mixed $value 검증 대상 값
* @param Closure $fail 실패 콜백
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if ($value === null || $value === '') {
return;
}
if (! is_string($value)) {
$fail(__('validation.schedule_command.shell_not_allowed'));
return;
}
$verdict = ScheduleCommandValidator::inspectShellCommand($value);
if ($verdict['allowed']) {
return;
}
// 인터프리터에 인라인 코드/명령을 넘기거나 안전하지 않은 스크립트 경로를 지정한
// 경우는 전용 안내로 구분한다 — 화이트리스트 미등재와는 조치 방법이 다르다.
$interpreterReasons = [
ScheduleCommandValidator::SHELL_REASON_INTERPRETER,
ScheduleCommandValidator::SHELL_REASON_INLINE_CODE,
ScheduleCommandValidator::SHELL_REASON_SCRIPT_PATH,
];
$key = in_array($verdict['reason'], $interpreterReasons, true)
? 'validation.schedule_command.shell_interpreter_denied'
: 'validation.schedule_command.shell_not_allowed';
$fail(__($key));
}
}