0x01 Vulnerabilities

Sqli:

  1. POST http://127.0.0.1/dili/admin/index.php/category_content/save &uploadedfile=sqli
  2. GET http://127.0.0.1/dili/admin/index.php/category_content/attachment/list?ids=sqli
  3. GET http://127.0.0.1/dili/admin/index.php/content/attachment/list?ids=sqli
  4. GET http://127.0.0.1/didi/admin/index.php/user/view?page=sqli

xss:

  1. POST http://127.0.0.1/didi/admin/index.php/attachment/save &tpl=xss

0x02 SQLi

URL:admin/index.php/content/attachment?ids=user%28%29%29%20and%20%28extractvalue%281,%20concat%280x5c,%28select%20user%28%29%29%29%29%29%23aaa%29
ids参数未过滤导致注入
相关代码
admin\controllers\category_content.php
对获取的ids参数传入where语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function attachment($action = 'list')
{
if ($action == 'list')
{
$response = array();
$ids = $this->input->get('ids', TRUE);
$attachments = $this->db->select('aid, realname, name, image, folder, type')
->where("aid in ($ids)")#attack
->get($this->db->dbprefix('attachments'))
->result_array();
foreach ($attachments as $v)
{
array_push($response, implode('|', $v));
}
echo implode(',', $response);
}

system\database\DB_active_rec.php
where()方法中使用_protect_identifiers()方法对传入参数进行过滤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
{
if ( ! is_array($key))
{
$key = array($key => $value);
}

// If the escape value was not set will will base it on the global setting
if ( ! is_bool($escape))
{
$escape = $this->_protect_identifiers;
}

foreach ($key as $k => $v)
{
$prefix = (count($this->ar_where) == 0 AND count($this->ar_cache_where) == 0) ? '' : $type;

if (is_null($v) && ! $this->_has_operator($k))
{
// value appears not to have been set, assign the test to IS NULL
$k .= ' IS NULL';
}

if ( ! is_null($v))
{
if ($escape === TRUE)
{
$k = $this->_protect_identifiers($k, FALSE, $escape);

$v = ' '.$this->escape($v);
}

if ( ! $this->_has_operator($k))
{
$k .= ' = ';
}
}
else
{
$k = $this->_protect_identifiers($k, FALSE, $escape);#过滤操作
}

$this->ar_where[] = $prefix.$k.$v;

if ($this->ar_caching === TRUE)
{
$this->ar_cache_where[] = $prefix.$k.$v;
$this->ar_cache_exists[] = 'where';
}

}

return $this;
}

system\database\DB_driver.php
当碰到有空格的参数,将其分割为$alias,$item,并返回拼接,由于未做过滤导致注入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function _protect_identifiers($item, $prefix_single = FALSE, $protect_identifiers = NULL, $field_exists = TRUE)
{
if ( ! is_bool($protect_identifiers))
{
$protect_identifiers = $this->_protect_identifiers;
}

if (is_array($item))
{
$escaped_array = array();

foreach ($item as $k => $v)
{
$escaped_array[$this->_protect_identifiers($k)] = $this->_protect_identifiers($v);
}

return $escaped_array;
}
if (strpos($item, ' ') !== FALSE)
{
$alias = strstr($item, ' ');
$item = substr($item, 0, - strlen($alias));
}
else
{
$alias = '';
}
.......
return $item.$alias;#过滤操作名没有对传入的$item进行过滤导致sql注入
}

img

URL:http://127.0.0.1/didi/admin/index.php/user/view?page=1,15
相关文件
\admin\controllers\user.php
获取offest参数传递给了get_users方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public function view($role = 0)
{
$offset = $this->input->get('page', TRUE) ? $this->input->get('page', TRUE) : 0; #获取参数
$data['list'] = $this->user_mdl->get_users($role, 15, $offset); #传入get_users方法
$data['role'] = $role;
$data['roles'] = $this->user_mdl->get_roles();
//加载分页
$this->load->library('pagination');
$config['base_url'] = backend_url('user/view') . '?dilicms';
$config['per_page'] = 15;
$config['page_query_string'] = TRUE;
$config['query_string_segment'] = 'page';
$config['total_rows'] = $this->user_mdl->get_users_num($role);
$this->pagination->initialize($config);
$data['pagination'] = $this->pagination->create_links();
$this->_template('user_list', $data);
}

D:\phpStudy\WWW\didi\shared\models\user_mdl.php
get_users使用$this->db->offset()方法设置了分页offset
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public function get_users($role_id = 0, $limit = 0, $offset = 0)
{
$table_admins = $this->db->dbprefix('admins');
$table_roles = $this->db->dbprefix('roles');
$this->db->where("$table_admins.uid <>", 1);
if ($role_id)
{
$this->db->where("$table_admins.role", $role_id);
}
if ($limit)
{
$this->db->limit($limit);
}
if ($offset)
{
$this->db->offset($offset); #设置offset
}
return $this->db->from($table_admins)
->join($table_roles, "$table_roles.id = $table_admins.role")
->get()
->result();
}

D:\phpStudy\WWW\didi\system\database\DB_active_rec.php
offset并没有对参数进行过滤放入sql语句
1
2
3
4
5
public function offset($offset)		#并没有对参数做任何处理放入了查询语句
{

$this->ar_offset = $offset;
return $this;
}

img