1. 취약점 소개
2019년 1월 11일 ThinkPHP 팀은 안전하지 않은 동적 함수 호출로 인한 원격 코드 실행 취약점을 수정한 패치 업데이트를 출시했습니다. 이 취약점은 매우 유해하며 기본적으로 원격 코드를 실행할 수 있습니다. 여러 버전의 ThinkPHP에서 소스 코드 분석 및 검증을 수행한 후, Venus ADLab 보안 연구원들은 특히 영향을 받는 버전이 ThinkPHP 5.0-5.0.23의 정식 버전임을 확인했습니다.
2. 취약점 재현
로컬 환경에서는 ThinkPHP 5.0.22 정식 버전 + PHP5.5.38 + Apache를 사용하여 재현합니다. 환경을 설치한 후 그림과 같이 POC를 실행하여 시스템 명령을 실행합니다.
3. 취약점 분석
분석을 위해 먼저 공식 홈페이지에서 다운로드한 5.0.22 정식 버전을 사용합니다. 취약점의 핵심 포인트 찾기:
thinkphp/library/think/Request.php:518
메소드 함수의 두 번째 if 분기에서는 외부에서 제어 가능한 데이터 $_POST[Config::get['var_method']가 도입되었습니다. var_method의 값은 _method입니다.
Request 클래스의 __construct 함수는 다음과 같습니다.
$options 매개변수는 제어 가능하므로 공격자는 이 클래스의 filter 속성, method 속성 및 get 속성의 값을 덮어쓸 수 있습니다. Request 클래스의 param 함수에서:
$this->mergeParam이 비어 있으면 $this->get(false)가 여기에서 호출됩니다. $this->get 함수 추적:
$this->input 함수는 함수 끝에서 호출되고 $this->get이 전달되며 $this->get의 값은 다음과 같습니다. 공격자가 제어할 수 있습니다. $this->input 함수 추적:
이 함수는 $this->getFileter를 호출하여 필터를 얻습니다. 함수 본문은 다음과 같습니다.
$this->필터 값은 생성자를 호출하여 공격자에 의해 재정의되고 제어됩니다. 값을 반환한 후 입력 함수에 들어갑니다.
filterValue 함수를 다음과 같이 봅니다. :
call_user_func 함수 호출에서 $filter를 제어할 수 있고, $value를 제어할 수 있습니다. 따라서 코드 실행이 발생할 수 있습니다.
취약점 유발 프로세스:
ThinkPHP5의 진입점에서 분석을 시작합니다:
thinkphp/library/think/App.php:77
run 함수의 첫 번째 줄은 Request 클래스를 인스턴스화하고 이를 $request에 할당합니다. 그런 다음 RouteCheck($request,$config)를 호출합니다.
여기서 Route::check는 경로 감지를 위해 호출됩니다. 기능은 다음과 같습니다.
빨간색 글꼴 부분에 주목하세요. 변수 적용 범위에 대한 메소드 함수를 호출하는 처음의 첫 번째 단계에 해당합니다. 여기서 재정의해야 하는 속성은 $this->filter, $this->method, $this->get입니다. $request->method()의 반환 값은 $this->method이므로 이 값도 제어해야 합니다. 여기서 반환값은 $method에 할당되고, self::$rules[$method]의 값을 빼서 $rules에 부여합니다. 참고: THINKPHP5에는 공급업체 디렉터리의 일부 파일을 자동으로 로드하는 자동 클래스 로딩 메커니즘이 있습니다. 그러나 정식 버전과 코어 버전의 공급업체 디렉터리 구조가 다릅니다.
풀 버전의 디렉터리 구조는 다음과 같습니다.
코어 버전의 디렉터리 구조는 다음과 같습니다.
풀 버전에는 코어 버전보다 폴더가 여러 개 더 많은 것을 볼 수 있습니다. . 특별한 주의가 필요한 것은 think-captcha/src 폴더에 helper.php 파일이 있다는 것입니다:
여기서 thinkRoute::get 함수가 호출되어 경로 등록 작업을 수행합니다. 이 단계의 영향은 위에서 언급한 self::$rules의 값을 변경하는 것입니다. 이 경로를 통해서만 RCE를 수행할 수 있으며, 그렇지 않으면 성공하지 못합니다. 이것이 바로 정식 버전에만 영향을 미치고 코어 버전에는 영향을 미치지 않는 이유입니다. 이때 self::$rules의 값은 다음과 같습니다.
그리고 공격자의 컨트롤에서 반환된 $method의 값을 가져오면 $rules의 값이 이 경로의 규칙이 됩니다. 그런 다음 위의 단계로 돌아가서 $rules를 가져오고 수신 URL에 따라 $item 값을 가져옵니다. 따라서 $rules[$item] 값은 보안 문자 라우팅 배열이 되며 추가로 self::를 호출할 수 있습니다. parrule 함수. 함수 본문이 약간 길어졌습니다. 핵심 사항은 다음과 같습니다.
이때 전달된 $route 값은 thinkcaptchaCaptchaController@index입니다. 따라서 빨간색으로 표시된 if 분기를 입력합니다. 이 분기에서는 $result의 'type' 키에 해당하는 값이 'method'입니다. 그런 다음 $result는 계층별로 run 함수에 반환되고 $dispatch에 할당됩니다.
그런 다음 $dispatch를 self::exec 함수로 가져옵니다.
Request 클래스의 param 메소드를 호출하는 빨간색으로 표시된 분기를 입력하세요. 따라서 익스플로잇 체인의 세 번째 단계가 충족되어 명령이 실행됩니다.
Venstar ADLab 보안 연구원들은 ThinkPHP5.0-5.0.23의 각 버전을 분석한 결과 ThinkPHP5.0.2-5.0.23이 동일한 POC를 사용할 수 있는 반면 ThinkPHP5.0-5.0.1은 POC를 변경해야 한다는 사실을 발견했습니다. Route.php의 규칙 기능에 대한 작은 구현 차이가 있습니다.
ThinkPHP5.0-5.0.1 버전 thinkphp/library/think/Route.php:235, $type을 대문자로 변환:
ThinkPHP5.0.2-5.0.23 버전에서는 규칙 함수에서 $ type이 소문자로 변환되었습니다:
4. 패치 분석
ThinkPHP5.0.24에는 $this->method 판정이 추가되었으며 클래스 함수의 자유 호출이 더 이상 허용되지 않습니다.
5. 결론
사용자는 ThinkPHP 버전 5.0.24로 업그레이드하고 공격을 피하기 위해 디버그 모드를 활성화하지 않는 것이 좋습니다.
관련 추천: "PHP 튜토리얼"
위 내용은 ThinkPHP5 코어 클래스 원격 코드 취약점 분석 요청의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!