Based on the route specified by the user, trace the complete call chain from the entry point to the final usage point, and output hierarchical call information.Suitable for parameter flow tracing of multiple vulnerability types.
Core Features
Only output call chain information, without performing vulnerability detection or security recommendations.
Output content includes:
- Complete HTTP packet - Request template directly usable in Burp Suite
- Detailed parameter definitions - The name, type, and nested structure of each parameter
- Hierarchical call relationships - Controller → Service → DAO → parent class
- Parameter flow tracing - The complete path from the HTTP entry point to the final usage point
- Parameter variable name tracing - Changes in the variable name of the same parameter across different classes
- Final usage point annotation - How the parameter is used at the final layer
Applicable Vulnerability Types
| Vulnerability Type | Trace Final Usage Point |
|---|---|
| SQL Injection | sql + param、Statement.execute()、MyBatis ${}, Hibernate HQL concatenation |
| Command Injection | Runtime.exec(cmd)、ProcessBuilder(cmd) |
| SSRF | HttpClient.execute(url)、URL.openConnection()、RestTemplate |
| XSS | response.getWriter().write(), template engine output,@ResponseBody |
| File Operations | new File(path)、FileInputStream()、Files.read() |
| XXE | DocumentBuilder.parse()、SAXParser、XMLReader |
| Deserialization | ObjectInputStream.readObject()、JSON.parseObject() |
| LDAP Injection | DirContext.search(filter)、LdapTemplate |
| Expression Injection | SpelExpression.getValue()、OGNL、MVEL、Freemarker |
| Path Traversal | new File(basePath + userInput)、Paths.get() |
Workflow
1. Receive user input
User provides:
- Route path: such as
/admin/user_login.actionor/api/faceCapture - Project path: the directory where the source code or decompiled files are located
2. Locate entry point and method identification
Locate the route entry class according to the framework type:
| Framework | Entry Locating Method |
|---|---|
| Spring MVC | @RequestMapping annotation matching |
| Struts 2 | action configuration in struts.xml |
| Servlet | web.xml or @WebServlet |
| JAX-RS | @Path annotation matching |
Important note: When the entry class contains multiple business methods (for example, a Web Service has multiple interface methods, or a Controller has multiple endpoint methods), the skill will automatically identify and trace all methods. For detailed implementation strategy, please refer to:multi-method-tracing.md
2.1 Multi-method tracing execution flow (mandatory requirement)
The following steps must be strictly followed, using the TodoWrite tool to manage tasks:
Step 1: Count all methods
First scan the entry class, identify all methods that need to be traced, and output the method list:
正在扫描入口类: UserQueryServiceImpl
发现以下 10 个方法需要追踪:
1. getBasicQuery(searchJson, pageJson, extend)
2. getAdvancedQuery(searchJson, pageJson, extend)
3. getDetailQuery(searchJson, pageJson, extend)
4. getStatisticsQuery(searchJson, pageJson, extend)
5. getExportQuery(searchJson, pageJson, extend)
... (列出所有方法)
10. getReportQuery(searchJson, pageJson, extend)
共计: 10 个方法
Step 2: Create TodoList tasks
The TodoWrite tool must be used, adding each method as an independent task:
TodoWrite([
{"content": "追踪方法 1/10: getBasicQuery", "status": "pending", "activeForm": "追踪 getBasicQuery"},
{"content": "追踪方法 2/10: getAdvancedQuery", "status": "pending", "activeForm": "追踪 getAdvancedQuery"},
{"content": "追踪方法 3/10: getDetailQuery", "status": "pending", "activeForm": "追踪 getDetailQuery"},
{"content": "追踪方法 4/10: getStatisticsQuery", "status": "pending", "activeForm": "追踪 getStatisticsQuery"},
# ... 所有 10 个方法
{"content": "追踪方法 10/10: getReportQuery", "status": "pending", "activeForm": "追踪 getReportQuery"},
{"content": "生成总索引文件", "status": "pending", "activeForm": "生成总索引"}
])
Step 3: Execute tasks one by one (optimization strategy)
Execute each task in TodoList order, and adopt different tracing strategies according to the number of interfaces:
| Interface Number | Tracing Strategy | Report Content |
|---|---|---|
| 1st interface | Complete trace chain | Includes all levels, branches, variable tracing, and controllability determination |
| The 2nd and subsequent interfaces | Simplified trace chain | Must include: request template + method parameter definitions + call chain + Sink identification + controllability determination |
Execution flow:
- Mark the current task as
in_progress - Select the tracing strategy based on the interface sequence number
- Generate the corresponding type of report file
- Mark the task as
completed - Continue to the next task
--- 方法 1/10: getBasicQuery ---
状态: in_progress
[完整追踪链...]
[生成报告: myproject_trace_getBasicQuery_20260205.md]
状态: completed ✅
--- 方法 2/10: getAdvancedQuery ---
状态: in_progress
[简化追踪链...]
[生成报告: myproject_trace_getAdvancedQuery_20260205.md (简化版)]
状态: completed ✅
--- 方法 3/10: getDetailQuery ---
状态: in_progress
[简化追踪链...]
[生成报告: myproject_trace_getDetailQuery_20260205.md (简化版)]
状态: completed ✅
... 继续直到所有任务完成 ...
Step 4: Complete verification
After all method tracing is complete:
- Generate the master index file
- Verify the number of generated files
- Output the completion report
# 验证命令
ls route_tracer/{route_name}/*.md | wc -l
# 期望结果: 11 (10个方法报告 + 1个总索引)
2.2 Interruption recovery mechanism
If execution is interrupted, when continuing next time you must:
- Check the already generated report files
- Compare against the method list to identify incomplete methods
- Create TodoList tasks only for the incomplete methods
- Continue execution
# 检查已完成的方法
existing_files = ls("/path/to/route_tracer/{route_name}/*.md")
completed_methods = [extract_method_name(f) for f in existing_files]
# 创建剩余任务
remaining_tasks = []
for method in all_methods:
if method not in completed_methods:
remaining_tasks.append({
"content": f"追踪方法: {method}",
"status": "pending",
"activeForm": f"追踪 {method}"
})
TodoWrite(remaining_tasks)
2.3 Mandatory rules
| Rule | Description |
|---|---|
| Must count | Before starting, you must count and output the number of all methods |
| Must use TodoList | You must use TodoWrite to add each method as a task |
| Interface optimization strategy | When the number of interfaces > 3, adopt the following optimization plan: - 1st interface: generate a complete call chain trace (including all levels, branches, variable tracing) - 2nd and subsequent interfaces: generate only the complete Burp Suite data packet + simple trace chain (excluding detailed code and branch determination) |
| Must mark status | Immediately mark each task as completed after it is finished |
| Ending early is prohibited | Ending is prohibited when there are pending tasks in the TodoList |
| Must verify quantity | Before ending, you must verify the number of generated files |
2.4 File generation rules (mandatory)
All interface quantities uniformly use the following strategy, with no need for batch processing:
| Interface sequence number | Report type | Content |
|---|---|---|
| 1st | Full version | All levels, branches, variable tracing, controllability determination (approximately 20000-30000 characters) |
| 2nd and subsequent | Simplified version | Request template + method parameter definitions + call chain + Sink identification + controllability determination (approximately 2000-4000 characters) |
File naming convention:
| Rule | Format |
|---|---|
| ✅ Correct | {项目名}_trace_{方法名}_{时间戳}.md |
| ❌ Incorrect | {方法名}_{时间戳}.md (missing project prefix) |
Variable replacement check (mandatory):
When generating each simplified report, you must ensure the following content is correctly replaced (retaining template variables is prohibited):
| Check item | Incorrect example | Correct example |
|---|---|---|
| Method name | ${method} |
queryUserById |
| Route path | /api/${method} |
/biz/ws/userService → queryUserById |
| Service implementation class | ${ServiceImpl} |
UserServiceImpl |
| SOAP method tag | <web:${method}> |
<web:queryUserById> |
| Call chain method | ${ServiceImpl}.${method}() |
UserServiceImpl.queryUserById() |
File content verification:
After generating each file, you must check:
- File nameContains the project prefix (e.g.
myproject_trace_) - File contentContains no
${...}form of unreplaced variables - Method nameCorrectly displayed in the report title, data packets, and call chain
2.5 Simplified version must include content (mandatory)
| Must include | Description | Cannot be omitted |
|---|---|---|
| HTTP/SOAP request template | Placeholder format {{param}}, used to illustrate the structure |
✅ |
| Example test data packet | A complete data packet containing actual test values, which can be used directly for Burp testing | ✅ |
| Parameter definition table specific to the method | Read from the method code signature; do not assume | ✅ |
| Call chain hierarchy diagram | [L1] → [L2] → [Sink] format | ✅ |
| Sink identification | Identify the final usage point type of the method | ✅ |
| Controllability determination conclusion | Controllability determination of the method parameters | ✅ |
2.5.1 Test data packet generation rules (mandatory)
Test data packets must contain actual testable values; placeholders are prohibited:
| Java type | Placeholder (prohibited) | Actual value generation rule |
|---|---|---|
| String (ID type) | {{userId}} |
Numeric string such as 1001 |
| String (name type) | {{name}} |
Meaningful test value such as testUser |
| String (date type) | {{date}} |
Standard format such as 2026-01-01 |
| String (path type) | {{path}} |
Valid path such as /tmp/test.txt |
| String (URL type) | {{url}} |
Complete URL such as http://example.com/api |
| int/Integer | {{count}} |
Number such as 10 |
| boolean/Boolean | {{flag}} |
true or false |
| JSON string | {{xxxJson}} |
Complete JSON such as {"id":"1","name":"test"} |
Method for generating test values:
- Extract from code - Look for values in code comments, unit tests, and sample data
- Infer from field semantics - Generate reasonable values based on the meaning of the field name (e.g.
email→test@example.com) - Infer from type - Use descriptive text for String, reasonable range values for numbers
- Use general security test values - Avoid special characters to ensure the request can be sent normally
2.6 Independent method parameter inspection rules (mandatory)
When tracing each method, the following steps must be performed; skipping is prohibited:
Step 1: Read the actual code signature of the method
The actual code must be read to obtain the real parameters; assumptions are prohibited:
方法A: getDictionaryAll(String codeTypes) → 1个参数
方法B: getCommonQuery(String searchJson, ...) → 3个参数
方法C: executeCommand(String cmd, String args) → 2个参数
Step 2: Independently trace the method's call chain to the Sink
Different methods may have different Sink types:
| Method example | Call chain | Sink type |
|---|---|---|
| getCommonQuery | → DAO → SQL execution | SQL |
| executeTask | → Runtime.exec() | COMMAND |
| fetchUrl | → HttpClient.get() | HTTP |
| parseXml | → DocumentBuilder.parse() | XML |
| getDictionaryAll | → Map.get() | No sensitive Sink |
Step 3: Determine the controllability of the method parameters
Determine based on the Sink type actually traced for the method:
| Sink type | Key determination points |
|---|---|
| SQL | Whether the parameter is concatenated into SQL |
| COMMAND | Whether the parameter is passed to command execution |
| HTTP | Whether the parameter is used to construct a URL |
| FILE | Whether the parameter is used for a file path |
| XML | Whether the parameter is passed to an XML parser |
| No sensitive Sink | Mark as "no sensitive operation" |
Step 4: Output the independent determination result for this method
Prohibited actions:
- ❌ Prohibited to write "refer to the parameter definition of the 1st interface"
- ❌ Prohibited to reuse the controllability conclusions of other methods
- ❌ Prohibited to assume that all methods have the same parameters or Sink types
2.7 Pre-generation checklist for the simplified version (must be executed for each method)
| # | Check item | Must be executed |
|---|---|---|
| 1 | Read the code signature of this method to obtain the actual parameter list | ☐ |
| 2 | Trace the call chain of this method to the final usage point | ☐ |
| 3 | Identify the Sink type of this method (SQL/COMMAND/HTTP/FILE/XML/none) | ☐ |
| 4 | Determine the controllability of this method's parameters | ☐ |
| 5 | Output the controllability determination table for this method | ☐ |
3. Trace the call chain
Starting from the entry method, trace layer by layer:
Controller/Action 层
↓ 调用
Service/Manager 层
↓ 调用
DAO/Repository 层
↓ 执行
SQL/数据库操作
Tracing rules:
- Identify method calls - Check the
this.xxx()in the method body or method calls on injected objects - Track dependency injection - Identify
@Autowired、@Resource, objects injected via constructor - Track parent class methods - If calling
super.xxx()or an inherited method, trace to the parent class - Record parameter passing - Record how parameters are passed from the upper layer to the lower layer
4. Decompilation support
When source code is unavailable, use the CFR decompiler (see java-shared/DECOMPILE_STRATEGY.md):
# 反编译单个文件
java -jar {CFR_JAR} /path/to/SomeClass.class --outputdir {output_path}/decompiled
# 反编译目录
find /path/to/classes -name "*.class" | xargs java -jar {CFR_JAR} --outputdir {output_path}/decompiled
# 批量反编译
java -jar {CFR_JAR} /path/to/A.class /path/to/B.class --outputdir {output_path}/decompiled
Output format
Strictly generate the output file according to the fill-in template in the references/ directory.
| Scenario | Template | File naming |
|---|---|---|
| 1st interface (full version) | OUTPUT_TEMPLATE_FULL.md | {project_name}_trace_{method_name}_{YYYYMMDD_HHMMSS}.md |
| 2nd+ interface (simplified version) | OUTPUT_TEMPLATE_SIMPLE.md | {project_name}_trace_{method_name}_{YYYYMMDD_HHMMSS}.md |
| Multi-method index | OUTPUT_TEMPLATE_INDEX.md | {project_name}_trace_all_methods_{YYYYMMDD_HHMMSS}.md |
Key rules:
- All [fill in] placeholders must be replaced with actual content
- Each method must be independently traced to the Sink; it is prohibited to reuse the conclusions of other methods
- Multi-method routing must generate an index file
- General specification reference: java-shared/OUTPUT_STANDARD.md
Single-method routing
File naming: {项目名}_audit/route_tracer/{路由名}/{项目名}_trace_{路由标识}_{时间戳}.md
Directory structure:
{project_name}_audit/
└── route_tracer/
└── {route_name}/
└── {project_name}_trace_{route_id}_20260204.md
Multi-interface method routing (important)
When the entry class contains multiple business methods (such as a Web Service or a Controller with multiple endpoints), an independent tracing report file must be generated for each method.
File naming rules:
- Single method report:
{项目名}_trace_{方法名}_{时间戳}.md - Master index report:
{项目名}_trace_all_methods_{时间戳}.md
Directory structure:
{project_name}_audit/
└── route_tracer/
└── {route_name}/
├── {project_name}_trace_getBasicQuery_20260204.md # 方法1
├── {project_name}_trace_getAdvancedQuery_20260204.md # 方法2
├── {project_name}_trace_getDetailQuery_20260204.md # 方法3
├── {project_name}_trace_getImageQuery_20260204.md # 方法N
├── ... (每个方法一个独立文件)
└── {project_name}_trace_all_methods_20260204.md # 总索引
Route name description:
- The route name is extracted from the route path, removing the leading slash and special characters
- For example:
/biz/ws/userService→biz_ws_userService - For example:
/api/user/login.action→api_user_login
Execution flow:
正在扫描入口类: UserQueryServiceImpl
✅ 发现 10 个入口方法
--- 方法 1/10: getBasicQuery ---
[生成独立报告: myproject_trace_getBasicQuery_20260204.md]
--- 方法 2/10: getAdvancedQuery ---
[生成独立报告: myproject_trace_getAdvancedQuery_20260204.md]
...
✅ 所有 10 个方法追踪完成
✅ 生成总索引: myproject_trace_all_methods_20260204.md
Master index report content:
# /api/ws/userQuery Web Service 所有方法追踪索引
生成时间: 2026-02-04
入口类: UserQueryServiceImpl
方法总数: 10
## 方法清单
| # | 方法名 | 参数列表 | 详细报告 |
|:--|:-------|:---------|:---------|
| 1 | getBasicQuery | searchJson, pageJson, extend | [查看](myproject_trace_getBasicQuery_20260204.md) |
| 2 | getAdvancedQuery | searchJson, pageJson, extend | [查看](myproject_trace_getAdvancedQuery_20260204.md) |
| 3 | getDetailQuery | searchJson, pageJson, extend | [查看](myproject_trace_getDetailQuery_20260204.md) |
| ... | ... | ... | ... |
For detailed implementation strategy, please refer to:multi-method-tracing.md
Output template
Complete tracing chain (applicable to the 1st interface)
Complete call chain tracing report, including all levels, branches, variable tracing, and other content.
# 路由调用链追踪报告
**追踪路由**: `/admin/image/getImageCapture.action`
**生成时间**: 2026-02-04
**项目路径**: /path/to/project
---
## 1. HTTP 请求数据包
### 1.1 完整请求模板
```http
POST /admin/image/getImageCapture.action HTTP/1.1
Host: {{host}}
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID={{session}}
searchJson={{searchJson}}&pageJson={{pageJson}}&extend={{extend}}
```
### 1.2 参数详细定义
#### 顶层参数
| 参数名 | Java类型 | HTTP位置 | 必填 | 说明 |
|:-------|:---------|:---------|:-----|:-----|
| searchJson | String | Body | 是 | JSON格式,反序列化为 ImageCaptureBean |
| pageJson | String | Body | 是 | JSON格式,反序列化为 Page<ImageCapture> |
| extend | String | Body | 否 | 扩展参数 |
#### pageJson 内部结构 (Page<ImageCapture>)
| 字段名 | Java类型 | 说明 | 最终使用位置 |
|:-------|:---------|:-----|:-------------|
| orderBy | String | 排序字段 | **AbstractDao.findSql():234 - SQL拼接** |
| order | String | 排序方向 (asc/desc) | **AbstractDao.findSql():234 - SQL拼接** |
| pageSize | int | 每页条数 | 分页查询 |
| currentPage | int | 当前页码 | 分页查询 |
#### searchJson 内部结构 (ImageCaptureBean)
| 字段名 | Java类型 | 说明 |
|:-------|:---------|:-----|
| userBean | UserBean | 用户信息对象 |
| startTime | String | 开始时间 |
| endTime | String | 结束时间 |
| deviceIds | List<String> | 设备ID列表 |
### 1.3 测试用数据包示例
```http
POST /admin/image/getImageCapture.action HTTP/1.1
Host: 192.168.1.100:8080
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID=ABC123
searchJson={"userBean":{"loginName":"admin"},"startTime":"2026-01-01","endTime":"2026-02-01"}&pageJson={"orderBy":"id","order":"desc","pageSize":10,"currentPage":1}&extend=
```
---
## 2. 调用链层级追踪
### [Level 1] Action 入口层
**文件**: `com/example/web/action/ImageCaptureAction.java:125`
**类名**: `ImageCaptureAction`
**方法签名**:
```java
public String getImageCapture(String searchJson, String pageJson, String extend)
```
**完整代码:**
```java
public String getImageCapture(String searchJson, String pageJson, String extend) {
// pageJson 反序列化为 Page 对象
Page<ImageCapture> page = (Page)JsonUtils.fromJson(pageJson, (new TypeToken<Page<ImageCapture>>() {
}).getType(), (String)null);
this.defaultImageCaptureSearchOrder(page);
// searchJson 反序列化为 ImageCaptureBean 对象
ImageCaptureBean searchBean = (ImageCaptureBean)JsonUtils.fromJson(searchJson, ImageCaptureBean.class, (String)null);
if (searchBean.getUserBean() != null && StringUtil.isEmpty(searchBean.getUserBean().getHostLoginIp())) {
String addressIp = WebServiceUtil.getWebServiceIp();
if (StringUtil.isEmpty(addressIp)) {
addressIp = searchBean.getUserBean().getLoginServerName();
}
searchBean.getUserBean().setHostLoginIp(addressIp);
}
searchBean.setSecordExcute(false);
String json = WebServiceUtil.valiatePam((new TypeToken<ReturnMsgBean<ImageCapture>>() {
}).getType(), new Object[]{page, searchBean});
if (json == null) {
// 关键调用: 传递 searchBean, page, extend 到 Manager 层
json = this.imageCaptureManager.getImageCaptureJson(searchBean, page, extend);
}
return json;
}
```
**参数转换:**
| HTTP参数 | 转换后类型 | 转换后变量名 | 传递到下一层 |
|:---------|:-----------|:-------------|:-------------|
| pageJson (String) | Page<ImageCapture> | page | ✅ |
| searchJson (String) | ImageCaptureBean | searchBean | ✅ |
| extend (String) | String | extend | ✅ |
**Page对象关键字段:**
- `page.orderBy` ← pageJson.orderBy (String类型)
- `page.order` ← pageJson.order (String类型)
**下一层调用**: `this.imageCaptureManager.getImageCaptureJson(searchBean, page, extend)`
---
### [Level 2] Manager 服务层
**文件**: `com/example/service/ImageCaptureManager.java:89`
**类名**: `ImageCaptureManager`
**方法签名**:
```java
public String getImageCaptureJson(ImageCaptureBean searchBean, Page<ImageCapture> page, String extend)
```
**完整代码:**
```java
public String getImageCaptureJson(ImageCaptureBean searchBean, Page<ImageCapture> page, String extend) {
// 关键调用: 将 page 传递给 DAO 层
Page<ImageCapture> result = this.imageCaptureDao.getImageCapturePage(searchBean, page);
return JsonUtils.toJson(result);
}
```
**参数传递:**
| 接收参数 | 类型 | 传递到下一层 |
|:---------|:-----|:-------------|
| searchBean | ImageCaptureBean | ✅ |
| page | Page<ImageCapture> | ✅ (含 orderBy, order) |
| extend | String | ❌ (未传递) |
**下一层调用**: `this.imageCaptureDao.getImageCapturePage(searchBean, page)`
---
### [Level 3] DAO 数据访问层
**文件**: `com/example/dao/ImageCaptureDao.java:56`
**类名**: `ImageCaptureDao`
**父类**: `AbstractDao<ImageCapture>`
**方法签名**:
```java
public Page<ImageCapture> getImageCapturePage(ImageCaptureBean searchBean, Page<ImageCapture> page)
```
**完整代码:**
```java
public Page<ImageCapture> getImageCapturePage(ImageCaptureBean searchBean, Page<ImageCapture> page) {
String sql = buildQuerySql(searchBean);
// 关键调用: 调用父类 AbstractDao.findSql(),传入 page 对象
return super.findSql(sql, page);
}
```
**参数传递:**
| 接收参数 | 类型 | 传递到下一层 |
|:---------|:-----|:-------------|
| searchBean | ImageCaptureBean | ❌ (用于构建SQL) |
| page | Page<ImageCapture> | ✅ (传递给父类) |
**下一层调用**: `super.findSql(sql, page)` → 父类 `AbstractDao.findSql()`
---
### [Level 4] 父类基础层 (最终使用点)
**文件**: `com/example/dao/base/AbstractDao.java:234`
**类名**: `AbstractDao<T>`
**方法签名**:
```java
protected Page<T> findSql(String sql, Page<T> page)
```
**完整代码:**
```java
protected Page<T> findSql(String sql, Page<T> page) {
if (page.getOrderBy() != null) {
// ⚠️ 最终使用点: orderBy 和 order 直接拼接到 SQL 语句
sql = sql + " ORDER BY " + page.getOrderBy() + " " + page.getOrder();
}
// 执行 SQL 查询
return executeQuery(sql, page);
}
```
**参数最终使用:**
| 参数 | 类型 | 使用方式 | 代码位置 |
|:-----|:-----|:---------|:---------|
| page.getOrderBy() | String | **直接拼接到 SQL** | AbstractDao.java:235 |
| page.getOrder() | String | **直接拼接到 SQL** | AbstractDao.java:235 |
---
## 3. 调用链总结图
```
HTTP Request
│
├─ searchJson (String) ──→ ImageCaptureBean searchBean
│ └─ userBean: UserBean
│ └─ startTime: String
│ └─ endTime: String
│
├─ pageJson (String) ────→ Page<ImageCapture> page
│ ├─ orderBy: String ─────────────────────┐
│ ├─ order: String ───────────────────────┤
│ ├─ pageSize: int │
│ └─ currentPage: int │
│ │
└─ extend (String) ──────→ (未向下传递) │
│
┌──────────────────────────────────────────────────────────────────────┘
│
▼ 参数流向追踪
[L1] ImageCaptureAction.getImageCapture()
│
│ page (含 orderBy, order), searchBean
▼
[L2] ImageCaptureManager.getImageCaptureJson()
│
│ page (含 orderBy, order), searchBean
▼
[L3] ImageCaptureDao.getImageCapturePage()
│
│ page (含 orderBy, order)
▼
[L4] AbstractDao.findSql()
│
└──→ sql = sql + " ORDER BY " + page.getOrderBy() + " " + page.getOrder()
▲ ▲
│ │
└── orderBy 直接拼接 ──────────┴── order 直接拼接
```
---
## 4. 参数变量名追踪表(核心)
**追踪同一参数在不同类中的变量名变化:**
### 4.1 pageJson.orderBy 参数追踪
| 层级 | 类名 | 变量名 | 类型 | 代码位置 | 说明 |
|:-----|:-----|:-------|:-----|:---------|:-----|
| HTTP | - | `pageJson` | String | 请求Body | 原始JSON字符串 |
| L1 | ImageCaptureAction | `pageJson` → `page.orderBy` | Page.orderBy: String | :125 | JsonUtils.fromJson()反序列化 |
| L2 | ImageCaptureManager | `page.orderBy` | Page.orderBy: String | :89 | 参数名不变,直接传递 |
| L3 | ImageCaptureDao | `page.orderBy` | Page.orderBy: String | :56 | 参数名不变,传递给父类 |
| L4 | AbstractDao | `page.getOrderBy()` | String | :235 | **最终使用: SQL拼接** |
### 4.2 pageJson.order 参数追踪
| 层级 | 类名 | 变量名 | 类型 | 代码位置 | 说明 |
|:-----|:-----|:-------|:-----|:---------|:-----|
| HTTP | - | `pageJson` | String | 请求Body | 原始JSON字符串 |
| L1 | ImageCaptureAction | `pageJson` → `page.order` | Page.order: String | :125 | JsonUtils.fromJson()反序列化 |
| L2 | ImageCaptureManager | `page.order` | Page.order: String | :89 | 参数名不变 |
| L3 | ImageCaptureDao | `page.order` | Page.order: String | :56 | 参数名不变 |
| L4 | AbstractDao | `page.getOrder()` | String | :235 | **最终使用: SQL拼接** |
### 4.3 searchJson 参数追踪
| 层级 | 类名 | 变量名 | 类型 | 代码位置 | 说明 |
|:-----|:-----|:-------|:-----|:---------|:-----|
| HTTP | - | `searchJson` | String | 请求Body | 原始JSON字符串 |
| L1 | ImageCaptureAction | `searchJson` → `searchBean` | ImageCaptureBean | :128 | JsonUtils.fromJson()反序列化 |
| L2 | ImageCaptureManager | `searchBean` | ImageCaptureBean | :89 | 参数名不变 |
| L3 | ImageCaptureDao | `searchBean` | ImageCaptureBean | :56 | **最终使用: buildQuerySql()** |
### 4.4 变量名变化示例(当参数名在不同层改变时)
```
HTTP: pageJson (String)
↓ JsonUtils.fromJson()
L1 ImageCaptureAction: page (Page<ImageCapture>)
↓ 方法参数传递
L2 ImageCaptureManager: page (Page<ImageCapture>) ← 同名
↓ 方法参数传递
L3 ImageCaptureDao: page (Page<ImageCapture>) ← 同名
↓ super.findSql(sql, page)
L4 AbstractDao: page (Page<T>) ← 泛型类型变化
↓ page.getOrderBy()
最终使用: sql = sql + " ORDER BY " + page.getOrderBy()
```
### 4.5 完整参数追踪汇总
| 原始HTTP参数 | L1变量名 | L2变量名 | L3变量名 | L4变量名 | 最终使用 |
|:-------------|:---------|:---------|:---------|:---------|:---------|
| pageJson | page | page | page | page | page.getOrderBy() → SQL拼接 |
| pageJson.orderBy | page.orderBy | page.orderBy | page.orderBy | page.getOrderBy() | SQL ORDER BY 子句 |
| pageJson.order | page.order | page.order | page.order | page.getOrder() | SQL ORDER BY 子句 |
| searchJson | searchBean | searchBean | searchBean | - | buildQuerySql() |
| extend | extend | - | - | - | 未向下传递 |
5. Parameter Actual Usage Check (CRITICAL - Prevent Vulnerability Misjudgment)
Trace each parameter from the HTTP entry point to the final usage point, and determine whether the parameter truly participates in sensitive operations.
This check is crucial for accurately determining vulnerabilities and can avoid misjudging cases where "a parameter is passed but not used" as vulnerabilities.
5.1 Check Description
| Status | Meaning | Effect on Vulnerability Determination |
|---|---|---|
| ✅ Used | The parameter value directly or indirectly participates in sensitive operations | Must further check whether a vulnerability exists |
| ❌ Not Used | The parameter is passed but does not participate in sensitive operations (overwritten by hardcoding/ignored) | Exclude vulnerability |
| ⚠️ Partially Used | Some fields of the parameter are used, while some are not used | Only check the fields that are used |
5.2 "Hardcoded Override" Scenarios for Each Vulnerability Type
| Vulnerability Type | Parameter | Hardcoded Override Scenario | Conclusion |
|---|---|---|---|
| SQL Injection | page.orderBy |
SQL is already hardcoded order by createTime desc |
Parameter not used |
| Command Injection | cmd |
Code hardcoded Runtime.exec("ls -la") |
Parameter not used |
| SSRF | url |
Code hardcoded httpClient.get("http://internal/api") |
Parameter not used |
| File Operation | path |
Code hardcoded new File("/tmp/fixed.txt") |
Parameter not used |
| XXE | xml |
Code uses a fixed XML template | Parameter not used |
| Expression Injection | expr |
Code hardcoded expression SpEL.parse("#{fixed}") |
Parameter not used |
5.3 Parameter Usage Checklist (Output Template)
## 参数实际使用检查
| 参数 | Sink类型 | 覆盖类型 | 覆盖条件 | 可控性结论 | 可控场景 |
|:-----|:---------|:---------|:---------|:-----------|:---------|
| page.orderBy | SQL ORDER BY | 条件覆盖 | `isEmpty(orderBy)` | ⚠️ 条件可控 | 非空时可控 |
| page.order | SQL ORDER BY | 无覆盖 | - | ✅ 完全可控 | 任意值 |
| cmd | Runtime.exec | 无覆盖 | - | ✅ 完全可控 | 任意值 |
| url | HTTP请求 | 安全检查覆盖 | `!isInternalUrl(url)` | ⚠️ 条件可控 | 外网URL时可控 |
| path | File操作 | 白名单覆盖 | `!allowedPaths.contains()` | ⚠️ 白名单内可控 | /tmp, /data 等 |
| searchBean.keyword | SQL WHERE | 无条件覆盖 | 总是覆盖 | ❌ 不可控 | 无 |
Controllability conclusion description:
| Conclusion | Meaning | Audit Requirement |
|---|---|---|
| ✅ Fully Controllable | The parameter has no override at all, and user input reaches the Sink directly | Must audit the security of the Sink point |
| ⚠️ Conditionally Controllable | The parameter is controllable under specific conditions | Need to verify bypass conditions before auditing |
| ❌ Not Controllable | The parameter is unconditionally overwritten or safely handled | The vulnerability for this parameter can be excluded |
5.4 General Override Condition Identification Rules (Applicable to All Vulnerability Types)
After tracing to a parameter assignment operation, override conditions must be checked. This rule applies to any type of parameter:
| Override Type | Code Feature | Controllability Determination | Applicable Scenario |
|---|---|---|---|
| Unconditional Override | x = "hardcoded"; (not inside if) |
❌ Not Controllable | All vulnerability types |
| Empty Value Protection Override | if (isEmpty(x)) { x = default; } |
⚠️ Controllable when non-empty | All vulnerability types |
| null Protection Override | if (x == null) { x = default; } |
⚠️ Controllable when non-null | All vulnerability types |
| Whitelist Override | if (!list.contains(x)) { x = default; } |
⚠️ Controllable within whitelist | All vulnerability types |
| Security check coverage | if (!isAllowed(x)) { x = safe; } |
⚠️ Controllable when check is bypassed | SSRF/File/Command |
| Format validation coverage | if (!isValid(x)) { x = default; } |
⚠️ Controllable when format matches | All vulnerability types |
| Conditional branch coverage | if (cond) { x = default; } |
⚠️ Controllable when condition is not met | All vulnerability types |
Common coverage condition identification (general):
| Condition type | Identification pattern | Controllable scenario |
|---|---|---|
| Null check | isEmpty(), isBlank(), == null, length() == 0 |
Controllable when not null |
| Whitelist check | contains(), Arrays.asList(), allowedList.contains() |
Controllable within whitelist |
| Blacklist check | !contains(), blacklist.contains() → Reject |
Controllable when not in blacklist |
| Format validation | matches(), Pattern.compile(), isValid() |
Controllable when format matches |
| Security check | isAllowed(), isSafe(), checkSecurity() |
Controllable when check is bypassed |
| Range check | x > min && x < max, inRange() |
Controllable within range |
Original hardcoded coverage detection rules (still applicable):
| Sensitive operation type | Hardcoded coverage determination method | Example |
|---|---|---|
| SQL ORDER BY | Check whether the SQL string already contains order by |
sql + " order by id desc" |
| SQL WHERE | Check whether the condition uses parameterization #{} or a hardcoded value |
WHERE status = 1 |
| Command execution | Check whether the command string uses a hardcoded command | exec("ls -la") |
| HTTP request | Check whether the URL uses a hardcoded address | get("http://fixed.com") |
| File operation | Check whether the path uses a hardcoded path | new File("/tmp/log.txt") |
| XML parsing | Check whether the XML comes from a fixed template | parse(FIXED_XML) |
5.5 Hardcoded coverage detail output format
When a parameter is found to be overwritten by hardcoding, details must be output:
### 硬编码覆盖详情
#### {参数名} - 被硬编码覆盖
**代码位置**: `{ClassName}.java:{line}`
**覆盖代码**: {展示硬编码覆盖的代码片段}
**判定**:
- {参数}被传递到{方法}
- 但{敏感操作}已经包含硬编码值
- **结论**: ❌ 参数未使用,不存在漏洞
5.6 Parameter actual usage checklist
Before outputting the tracking report, the following checks must be completed:
| # | Check item | Status |
|---|---|---|
| 1 | Identify all parameters passed to the final layer | ☐ |
| 2 | Determine the sensitive operation type of each parameter | ☐ |
| 3 | Check whether hardcoded coverage exists | ☐ |
| 4 | Mark the actual usage status of each parameter | ☐ |
| 5 | Output details for parameters that are "overwritten by hardcoding" | ☐ |
| 6 | Check the semantics of the coverage condition and output a controllability conclusion | ☐ |
6. Parameter controllability determination (CRITICAL - basis for general vulnerability determination)
Applicable to all vulnerability types: SQL injection, command injection, SSRF, file operations, XXE, expression injection, etc.
For detailed determination principles, please refer to:CONTROLLABILITY_ANALYSIS.md
6.1 Core determination process
1. 追踪参数从 HTTP 入口到 Sink 的完整路径
2. 识别路径上所有对参数的赋值/覆盖操作
3. 检查覆盖操作的条件语义(识别代码意图,非模式匹配)
4. 输出可控性结论
6.2 Coverage types and controllability
| Coverage type | Determination criteria | Controllability conclusion |
|---|---|---|
| No coverage | The parameter is passed directly to the Sink | ✅ Fully controllable |
| Unconditional coverage | The assignment is not within any condition | ❌ Not controllable |
| Conditional coverage | Assignment within a condition requires semantic determination | ⚠️ Controllable condition |
6.3 Condition semantic determination (key)
Identify based on code semantics, rather than matching fixed method names:
| Semantic type | Determination method | Controllable scenario |
|---|---|---|
| Null protection | Condition checks whether the parameter is null; sets a default value when null | Controllable when non-null |
| Whitelist validation | Condition checks whether the parameter is in the allowed list | Controllable within the whitelist |
| Security check | Condition checks whether the parameter is safe | Controllable when bypassing the check |
6.4 Output format
Must output the controllability determination table:
| 参数 | Sink类型 | 覆盖类型 | 覆盖条件 | 可控性结论 | 可控场景 |
|:-----|:---------|:---------|:---------|:-----------|:---------|
| {name} | {sink} | {type} | {condition} | {✅/⚠️/❌} | {scenario} |
Must output the controllability summary:
| 可控性类型 | 参数列表 | 审计要求 |
|:-----------|:---------|:---------|
| ✅ 完全可控 | {list} | 必须审计 Sink 安全性 |
| ⚠️ 条件可控 | {list} | 需验证绕过条件 |
| ❌ 不可控 | {list} | 可排除漏洞可能 |
6.5 Sink types
| Sink | Description |
|---|---|
| SQL | SQL concatenation/execution |
| COMMAND | System command execution |
| HTTP | HTTP request initiation |
| FILE | File read/write operations |
| XML | XML parsing |
| LDAP | LDAP query |
| EXPRESSION | Expression parsing |
| DESERIALIZE | Deserialization |
| RESPONSE | Response output |
| PATH | Path concatenation |
7. Branch condition tracking (CRITICAL - avoid vulnerability misjudgment)
When tracking the call chain, all conditional branches must be recorded to ensure whether the code will actually execute is identified!
For detailed determination principles, please refer to:BRANCH_TRACING.md
7.1 Core determination process
1. 识别代码中的条件分支(if/else/switch)
2. 检查每个分支的执行内容
3. 判定敏感操作在哪些分支中执行
4. 输出执行路径结论
7.2 Branch types that must be identified
Identify based on code semantics, rather than matching fixed method names:
| Branch type | Semantic feature | Tracking key points |
|---|---|---|
| Environment/platform branch | Select different paths based on the runtime environment | Annotate the execution content of each environment |
| Security check branch | Perform security validation on the input | Annotate the interception condition |
| Feature toggle branch | Determine whether to execute based on configuration | Annotate the impact of the toggle state |
| Null/exception branch | Check parameter validity | Annotate the early exit condition |
| Permission determination branch | Check user permissions | Annotate the permission requirements |
7.3 Early exit point identification
| Exit type | Semantics | Must annotate |
|---|---|---|
| Security interception exit | Security check failed, refuse to continue | ⚠️ Security interception |
| Null protection exit | Parameter invalid, return early | ⚠️ Early exit |
| Exception thrown exit | Condition not satisfied, throw an exception | ⚠️ Exception exit |
7.4 Output format
Must output the branch structure:
methodName(param)
├─ [if 条件A] → 分支A执行内容
│ └─→ 敏感操作 ⚠️
└─ [else] → 默认分支 / return / throw
Must output the execution path conclusion:
| 路径 | 条件 | 敏感操作 | 可利用性 |
|:-----|:-----|:---------|:---------|
| 路径A | {条件} | ✅ 执行 | 可利用 |
| 路径B | {条件} | ❌ 不执行 | 不可利用 |
Tracking strategy
Strategy 1: Dependency injection tracking
Identify Spring/Struts dependency injection:
// Spring
@Autowired
private ImageCaptureManager imageCaptureManager;
// Struts
private ImageCaptureService faceCaptureService;
public void setImageCaptureService(ImageCaptureService service) {
this.faceCaptureService = service;
}
Track imageCaptureManager.xxx() When called, locate the ImageCaptureManager class.
Strategy 2: Inheritance Chain Tracing
When calling super.xxx() or a parent class method:
public class ImageCaptureDao extends AbstractDao<ImageCapture> {
public Page<ImageCapture> query(Page<ImageCapture> page) {
return super.findSql(sql, page); // 追踪到 AbstractDao
}
}
Tracing steps:
- Identify
extends AbstractDao - Search for the
findSqlmethod in the parent class - Continue tracing the parent class's parent class (if any)
Strategy 3: Interface Implementation Tracing
When calling an interface method:
@Autowired
private UserService userService; // 接口类型
userService.getUser(id); // 需要找到实现类
Tracing steps:
- Identify
UserServiceis an interface - Search for the class of
implements UserServiceclass - Locate the method of the implementation class
Strategy 4: MyBatis/Hibernate Tracing
For ORM frameworks:
MyBatis:
@Mapper
public interface UserMapper {
List<User> selectByPage(@Param("page") Page page);
}
Trace to the SQL definition in the corresponding XML file.
Hibernate:
session.createQuery("FROM User WHERE id = " + id);
Identify HQL/SQL directly in the code.
Decompilation Tool Usage
When to Decompile
| Scenario | Operation |
|---|---|
| .java source code exists | Read and inspect directly |
| Only .class files exist | Use decompile_file |
| The entire project has only .class files | Use decompile_directory |
| The parent class is in a JAR package | First extract the JAR, then decompile_file |
Decompilation Command Reference
# 检查 CFR 状态
java -jar {CFR_JAR} --help
# 检查 Java 版本
java -version
# 如果 CFR 不存在,下载
curl -L -o {output_path}/cfr-0.152.jar "https://xget.xi-xu.me/gh/leibnitz27/cfr/releases/download/0.152/cfr-0.152.jar"
# 反编译单个类
java -jar {CFR_JAR} /path/to/AbstractDao.class --outputdir {output_path}/decompiled
# 反编译整个 DAO 包
find /path/to/com/example/dao -name "*.class" | xargs java -jar {CFR_JAR} --outputdir {output_path}/decompiled
Output Specification
Required Information
Each level must include:
- File location - Full package path + file name + line number
- Class name - Including parent class information (if any)
- Method signature - Method name + parameter list + return type
- Key code - Show the code snippet that calls the next level
- Parameter passing - Explain how parameters are passed to the next level
Prohibited Operations
- ❌ Do not perform vulnerability detection or vulnerability determination
- ❌ Do not provide remediation solutions
- ❌ Do not infer non-existent call relationships
- ❌ Do not omit any level
Output File Naming
{project_name}_audit/route_tracer/{route_name}/{project_name}_trace_{route_id}_{timestamp}.md
示例:
myproject_audit/route_tracer/biz_ws_userService/myproject_trace_queryUserById_20260204.md
Simple tracing chain (applicable to the 2nd and subsequent interfaces)
Must include the following content: request template + method parameter definition + call chain + Sink identification + controllability determination
# 路由调用链追踪报告(简化版)
**追踪路由**: `{route}`
**方法**: `{method}`
**生成时间**: {date}
---
## 1. HTTP 请求数据包
### 1.1 完整请求模板
```http
{该方法的完整请求模板}
1.2 Method Parameter Definition
Parameter source: Read from the {ClassName}.{method}() method signature
Top-level parameters
| Parameter name | Java type | Description |
|---|---|---|
| {param} | {type} | {desc} |
Parameter internal structure (if any)
| Field name | Java type | Description |
|---|---|---|
| {field} | {type} | {desc} |
1.3 Test Data Packet Example
{测试数据包}
2. Call Chain Tracing
Call chain levels
[L1] {Class}.{method}()
↓
[L2] {Class}.{method}()
↓
[Sink] {Sink类型}: {具体位置}
Sink Identification
| Sink type | Location | Description |
|---|---|---|
| {SQL/COMMAND/HTTP/FILE/XML/no sensitive Sink} | {Class.java:line} | {specific operation} |
Parameter Passing Relationships
| Parameter | L1 | L2 | ... | Final use |
|---|---|---|---|---|
| {param} | {var} | {var} | ... | {usage} |
3. Controllability Determination
| Parameter | Sink type | Override type | Override condition | Controllability conclusion | Controllable scenario |
|---|---|---|---|---|---|
| {param} | {sink} | {type} | {condition} | {✅/⚠️/❌/-} | {scenario} |
Controllability summary:
| Type | Parameter | Audit requirement |
|---|---|---|
| ✅ Fully controllable | {list} | Sink security needs to be audited |
| ⚠️ Conditionally controllable | {list} | Bypass conditions need to be verified |
| ❌ Not controllable | {list} | Vulnerability possibility can be ruled out |
| - No sensitive Sink | {list} | Low risk |
**简化版生成注意事项:**
- 必须从该方法实际代码读取参数,禁止假设
- 必须独立追踪该方法的调用链到 Sink
- 必须识别该方法的 Sink 类型(可能与第1个接口不同)
- 必须输出该方法的可控性判定(禁止复用其他方法结论)
- 如果该方法无敏感 Sink,在可控性判定中标注"无敏感Sink,低风险"
---
## 限制与边界
**仅执行以下操作:**
- 追踪指定路由的调用链
- 输出每层的文件位置和方法签名
- 记录参数传递关系
- 生成 HTTP 请求模板
**不执行以下操作:**
- 不进行安全漏洞检测
- 不提供修复方案
- 不判定漏洞等级
- 不检查业务逻辑正确性