Before all
坑還好多,先放著當自己的memo和碎碎念,慢慢補完…
這幾天滾了一圈社區文章,發現自己對Java整個Web體系根本不熟…來開發吧XD
正在照這個複現一些有問題的功能並練習patch(主要還是先忙面試)
https://xz.aliyun.com/t/16232
https://xz.aliyun.com/t/16284
社區寶藏蠻多的XD  
我最近看到很喜歡的設計:
From DEVCORE Wargame 2024: https://github.com/DEVCORE-Wargame/HITCON-2024/tree/main/challenges/Expressionism/  
挖庫挖庫 >W<b
P.S. 初學Java開發 歡迎各位給我建議/指正我w  
What, Why, How maven?
Maven是一個方便搭建web服務的一個專案,主要服務 Java,但也支援 C# 等其他語言的部署,只需提供架設檔(pom.xml)就會幫你把服務編譯/打包好,非常之方便~  
pom.xml
我是使用spring boot server架設,是一個方便測試/打包的網頁框架!
結構長這樣(我知道還有很多,POM SPEC(Link)):  
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 
 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 
 
 <groupId>com.example</groupId>
 <artifactId>javademo</artifactId>
 <version>1.0-SNAPSHOT</version>
 <packaging>jar</packaging>
 <name>CTF JAVA WEB Demo</name>
 <description>A simple Spring Boot application in Java</description>
 
 
 <dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-thymeleaf</artifactId>
 </dependency>
 </dependencies>
 
 
 <parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>3.1.3</version>
 <relativePath/>
 </parent>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 </project>
 
 
 | 
在打滲透時可以特別注意dependencies中是否版本過舊,另外,TomCat 的 Credential 也可能存在pom.xml或者settings.xml中:  
| 12
 3
 4
 5
 6
 7
 
 | <servers><server>
 <id>TomcatServer</id>
 <username>tomcat</username>
 <password>password</password>
 </server>
 </servers>
 
 | 
Structure
Spring Boot架構大概長這樣:  
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | .├── pom.xml
 └── src
 └── main
 ├── java
 │   └── com
 │       └── example
 │           └── javademo
 │               ├── App.java
 │               └── MainController.java
 └── resources
 ├── static
 │   ├── test.txt
 │   └── wifu.gif
 └── templates
 └── index.html
 
 | 
pom.xml就是剛剛的結構,接下來src存source
main代表主結構,resources中的static與templates跟Flask一樣,分別是放靜態檔案及html模板
java資料夾內則是執行的程式碼,App.java跟MainController.java不是一定要這樣命名,但我覺得這比較能體現他們功能:
App.java  
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | package com.example.javademo;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 
 @SpringBootApplication
 public class App {
 public static void main(String[] args) {
 SpringApplication.run(App.class, args);
 }
 }
 
 
 | 
支撐整個 SpringApplication 並定義它(hint: 在java裡,主class必須跟檔名一樣)
而MainController一樣是Spring架設時會自己抓的,控制每個路由要幹嘛  
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 
 | package com.example.javademo;
 import org.springframework.expression.ExpressionParser;
 import org.springframework.expression.spel.standard.SpelExpressionParser;
 import org.springframework.expression.spel.support.StandardEvaluationContext;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.*;
 import java.util.Map;
 import java.util.HashMap;
 import java.util.concurrent.atomic.AtomicReference;
 
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 
 @Controller
 public class MainController {
 
 @GetMapping("/")
 @ResponseBody
 public String home() {
 return "Hello Whale!";
 }
 
 @GetMapping("/template")
 public String template(@RequestParam(value = "name", defaultValue = "Whale") String name, Model model) {
 model.addAttribute("name", name);
 return "index";
 }
 
 @GetMapping("/get")
 @ResponseBody
 public Map<String, String> getParams(@RequestParam Map<String, String> queryParams) {
 return queryParams;
 }
 
 @PostMapping("/post")
 @ResponseBody
 public Map<String, String> postParams(@RequestBody Map<String, String> bodyParams) {
 return bodyParams;
 }
 
 @GetMapping("/cmd")
 @ResponseBody
 public String executeCommand(@RequestParam(value = "cmd", defaultValue = "whoami") String cmd) {
 StringBuilder output = new StringBuilder();
 try {
 Process process = Runtime.getRuntime().exec(cmd);
 BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
 String line;
 while ((line = reader.readLine()) != null) {
 output.append(line).append("<br>");
 }
 } catch (Exception e) {
 return "<h1>Error: " + e.getMessage() + "</h1>";
 }
 return "<h1>Execution Result:</h1><p>" + output + "</p>";
 }
 
 
 @RequestMapping(value = "/evaluate", method = RequestMethod.POST)
 @ResponseBody
 public String evaluate(@RequestParam(value = "id", defaultValue = "1+1") String id) {
 
 ExpressionParser parser = new SpelExpressionParser();
 StandardEvaluationContext context = new StandardEvaluationContext();
 
 try {
 Object result = parser.parseExpression(id).getValue(context);
 return id+" = " + result;
 } catch (Exception e) {
 return "Error: Invalid Expression - " + e.getMessage();
 }
 }
 }
 
 | 
如果有寫其他web app的經驗看應該會很快能點出每個地方在幹嘛(大同小異!):  
- @GetMapping修飾符定義了路由,RequestMethod
- @ResponseBody則定義了純粹的回顯資料,對於有template的顯示是不需要的
- @RequestParam則是請求的parameters,預設跟常見的- a=1&b=2一樣,用parser取出,不過像我POST區就定義是- Map<String, String>,這時就必須以JSON請求
/cmd路由示範了Java裡執行命令並回顯得方法
/evaluate路由則示範了SPeL Injection的漏洞
小筆記:  
| 12
 
 | ${#request}的payload在注入jsp時可以獲得位置和一些敏感資訊  T(java.lang.Runtime).getRuntime().exec('curl localhost:9999/pwned'):基本RCE Chain
 
 | 
compile & run
Maven下載一樣走apt install
我是用spring boot,要先compile:  
| 12
 
 | mvn clean compile mvn spring-boot:run
 
 | 
提個外話
Tomcat  
Structure
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | 這個結構對於用maven, springboot架設jsp的網站有問題嗎├── pom.xml
 └── src
 └── main
 ├── java
 │   ├── Application.java
 │   └── JspController.java
 ├── resources
 │   └── messages.properties
 └── webapp
 └── WEB-INF
 ├── dispatcher-servlet.xml
 ├── views
 │   ├── application.properties
 │   └── index.jsp
 └── web.xml
 
 | 
dispatcher-servlet.xml(非必要)  
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="
 http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context.xsd">
 
 <context:component-scan base-package="com.example" />
 
 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
 <property name="prefix" value="/WEB-INF/views/" />
 <property name="suffix" value=".jsp" />
 </bean>
 
 <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
 <property name="basename" value="messages" />
 </bean>
 </beans>
 
 
 | 
但可以方便定義一些內容  
application.properties  
| 12
 
 | spring.mvc.view.prefix=/WEB-INF/views/spring.mvc.view.suffix=.jsp
 
 | 
定義mvc應該怎麼渲染jsp files,而所謂的jsp就像這樣:  
| 12
 3
 4
 5
 6
 7
 
 | <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %><html>
 <head><title>Spring Boot JSP Example</title></head>
 <body>
 <h1><spring:message code="message.${name}" /></h1>
 </body>
 </html>
 
 | 
大致可理解成一個支援java表達,更靈活的html template
而上面其實就是一個SPeL Injection的範例
舉例來說,讀取訊息就可以像在src/main/resources/messages.properties寫入:  
| 1
 | message.whale=I'm flying and eating...  
 | 
jsp讀取到message.whale就會顯示這段文字~