KCSC CTF 2025
Legacy
Bài này mình lấy ý tưởng khai thác từ 1 CVE đã cũ (link) ta sẽ exploit Java Deserialize để get output thông qua exception.
Với phiên bản JDK17 thì các chain dùng sink TemplateImpl đều không dùng được nên ta sẽ exploit bằng các chain dùng sink InvokerTransformer + ChainedTransformer, ví dụ như CC5
Với ý tưởng lấy output ta sẽ write file malicious jar thực thi cmd và quăng output ra exception như sau:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class RunCheckConfig {
public RunCheckConfig(String args) throws Exception
{
Process proc = Runtime.getRuntime().exec(args);
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null)
{
sb.append(line).append("\n");
}
String result = sb.toString();
Exception e=new Exception(result);
throw e;
}
}Build thành file jar
Tiếp theo, vì web khi deser đã gọi đến toString nên khi build payload CC5 ta không cần dùng BadAttributeValueExpException.
Đầu tiên ta sẽ dùng FileOutputStream để write file jar độc hại
Sau khi save file jar độc hại lên server ta dùng URLClassLoader để load
Tóm lại ta sẽ có code exploit như sau
Kết quả:
Bước 1 write malicious jar

Bước 2 trigger malicious jar đọc output

OG
Bài này mình lấy ý tưởng từ việc thư viện MyBatis cho phép xử lý OGNL expression

Dẫn đến việc nếu như implement thư viện không đúng cách có thể SQLi2RCE.
Ta có thể thấy trang web dính SQLi tại tính năng findByUsername

Debug vào quá trình build query ta sẽ thấy code gọi đến org.apache.ibatis.parsing.GenericTokenParser#parse để handle OGNL expression
Tại đây nếu query của ta có sự xuất hiện của chuỗi ${ sẽ nhảy vào code xử lý OGNL tại org.apache.ibatis.scripting.xmltags.TextSqlNode#handleToken


Tại handleToken sẽ tiến hành xử lý OGNL expression

OgnlCache.getValue cũng đơn giản là gọi đến Ognl.getValue sinks exploit OGNL

Ta hoàn toàn kiểm soát được giá trị expression, tuy nhiên mặc định MyBatis có cơ chế StricterInvocation không cho phép OGNL gọi đến 1 số class độc hại

Ở đây ta có nhiều cách để bypass, Ví dụ như vì JDK dùng trong bài là JDK17 nên ta có thể bypass bằng
Web nằm sau nginx và không ra được internet, do đó ta sẽ triển khai Spring Echo với OGNL để lấy response.
Ta có thể set header với payload sau

Vì giá trị thứ 2 trong method setHeader phải là String nên ta sẽ convert @jdk.jshell.JShell@create().eval('java.lang.Runtime.getRuntime().exec("cmd")' thành string
Mặc định hàm eval sẽ trả về List<SnippetEvent> (docs), mình dùng get(0) để get ra SnippetEvent và dùng method value() để lấy response từ SnippetEvent.
Ví dụ:

Method SnippetEvent.value sẽ get đúng kết quả của eval rồi toString do đó mình sẽ thêm new String(java.lang.Runtime.getRuntime().exec("whoami").getInputStream().readAllBytes()) để khiến eval return output cmd luôn
Payload cuối cùng:

Last updated