进入题目后,通过和源网页的比对,发现个 shortcut icon十分可疑,访问后发现其中存在字符串。

告诉我们ks,class,ico,xml文件都是可下载的,姑且认为这是个任意文件下载。

通过各种报错以及引入包的路径,可以陆续找到所有class文件。

比较重要的报错页面:http://116.85.48.102:5050/image/banner/1

com.didichuxing.ctf.controller.user.StaticController
通过/WEB-INF/web.xml可以慢慢找出所有的已经编译好的class文件

结构

我们通过jd-gui来进行反编译得到源码,并且审计。

其中, com.didichuxing.ctf.listener这个包最为重要,是整个题目的主要逻辑,通过阅读代码,发现其实就是通过sdl.ks进行RSA加密,这里有个坑就是,Flag是通过私钥加密,公钥解密的。

模仿源代码的写法,写出加密email的逻辑:

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class HelloWorld {
	public static void main(String[] args) throws NoSuchAlgorithmException {
		HelloWorld h = new HelloWorld();
		SecretKeySpec signingKey = new SecretKeySpec("sdl welcome you !".getBytes(), "HmacSHA256");
		Mac mac = Mac.getInstance("HmacSHA256");
	    try {
			mac.init(signingKey);
		} catch (InvalidKeyException e1) {
			e1.printStackTrace();
		}
		String email = "[email protected]";
		byte[] e = mac.doFinal(String.valueOf(email.trim()).getBytes());
		System.out.println(byte2hex(e));
	}
	public static String byte2hex(byte[] b)
	{
	    StringBuilder hs = new StringBuilder();

	    for (int n = 0; (b != null) && (n < b.length); n++) {
	      String stmp = Integer.toHexString(b[n] & 0xFF);
	      if (stmp.length() == 1)
	        hs.append('0');
	      hs.append(stmp);
	    }
	    return hs.toString().toUpperCase();
	}
}

ps:${email}替换为得到的hash

得到了email的hash,然后根据路由,POST请求 url/test/getflag/${email} 得到Flag的hash。

得到了加密后的flag,用java仿照撸了个解密脚本出来:

import org.apache.commons.codec.binary.Hex;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

public class TestSign {
    //证书密码
    private static final String PASSWORD = "sdlwelcomeyou";
    //证书别名
    private static final String ALIAS = "www.didichuxing.com";

    public static void main(String[] args) throws Exception {

        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(new FileInputStream("G:\\1常用\\0day\\DDCTF\\sdl.ks"), PASSWORD.toCharArray());
        Certificate x509Certificate = keyStore.getCertificate(ALIAS);

        encrypt(x509Certificate.getPublicKey(), (PrivateKey) keyStore.getKey(ALIAS, PASSWORD.toCharArray()));
    }

    public static void encrypt(PublicKey publicKey, PrivateKey privateKey) throws Exception {

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        RSAPublicKey pubKey = (RSAPublicKey) publicKey;
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
        cipher.init(Cipher.ENCRYPT_MODE, rsaPrivateKey);

        byte[] cipherText = Hex.decodeHex("4B512050B350ED3952627BB36A07C87B981F9A3616651244ED80522A868E1A6619EB28E499B6A9B8D0F2403894CA357698A0C69B686786483003A974AAC76F0FDB923A34AD58C1C761EACE646BE4F1EA56490F18627DA9580AD4955EE6D9EE2757AA2A29861744C2553BCEFBE895F4D0E63F32651E6A3E97A001E4E1C59AAF7069C007CBC3786C5180CCD4DA158C190FCBF492FC31C385FF58B0CFB7905DE1366C9473BB6A4EFBDBFF5833A2F8A0A66A0023373C143C5E681A6B1BED3CE1B92822232506CF1C53253266AE31ECF0FA8EF5646F4D241D47951113C5215C656D2D698788D2F96CBAC9DDC635A61ED30514C28C5DFF9322486E19E25E268855FC49");

        cipher.init(Cipher.DECRYPT_MODE, pubKey);
        byte[] plainText = cipher.doFinal(cipherText);
        System.out.println("解密之后的内容 : " +  new String(plainText));

    }


}

Get Flag!





本文链接地址: DDCTF2018 WEB2 专属链接 writeup

原创文章,转载请注明: 转载自Lz1y's Blog

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.