셸 스케줄 검증이 첫 토큰 basename 만 화이트리스트와 대조하고 뒤 인자를 검증하지 않아, 운영자가 bash 를 등록하면 `bash -c id` 로 임의 OS 명령이 실행됐다(KVE-2026-1653). 인터프리터는 범용 크론 용도로 등록을 허용하되, 스크립트 자리(첫 인자)에 형태 규칙을 적용해 인라인 코드·상대경로·트래버설· artisan 우회·완전거부형(env/awk/make 등)을 저장·실행 양쪽에서 거부한다.
58 lines
2.0 KiB
PHP
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));
|
|
}
|
|
}
|