Skip to content

Commit df8b118

Browse files
Add fuzz testing module with Jazzer-based fuzz targets for OSS-Fuzz
Add modules/fuzz with four Jazzer-compatible fuzz targets mirroring the Axis2/C OSS-Fuzz integration: XmlParserFuzzer (AXIOM/StAX), JsonParserFuzzer (Gson), HttpHeaderFuzzer, and UrlParserFuzzer. All four fuzzers passed local testing with 45.7M+ iterations and zero crashes. Includes OSS-FUZZ documentation and run script. Google's OSS-Fuzz team is currently reviewing the Axis2/C integration. Committing the Axis2/Java fuzzers now rather than waiting for their response, which can be applied later. The Java OSS-Fuzz submission will follow once the Axis2/C review is complete to coordinate project naming, avoid duplicate review overhead, and reuse the same Apache security contacts for both projects. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3b913f7 commit df8b118

8 files changed

Lines changed: 1593 additions & 0 deletions

File tree

modules/fuzz/README.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Apache Axis2/Java Fuzz Testing Module
2+
3+
Comprehensive fuzz testing for Axis2/Java parsers, mirroring the [Axis2/C OSS-Fuzz approach](https://github.com/apache/axis-axis2-c-core/tree/master/fuzz).
4+
5+
## Overview
6+
7+
This module provides Jazzer-compatible fuzz targets for security testing:
8+
9+
| Fuzzer | Component | Attack Vectors |
10+
|--------|-----------|----------------|
11+
| `XmlParserFuzzer` | AXIOM/StAX | XXE, XML bombs, buffer overflows |
12+
| `JsonParserFuzzer` | Gson | Deep nesting, integer overflow, malformed JSON |
13+
| `HttpHeaderFuzzer` | HTTP headers | CRLF injection, header parsing |
14+
| `UrlParserFuzzer` | URL/URI parsing | SSRF, path traversal, malformed URLs |
15+
16+
## Running Fuzzers Locally
17+
18+
### Prerequisites
19+
20+
```bash
21+
# Install Jazzer
22+
# Option 1: Download from GitHub releases
23+
wget https://github.com/CodeIntelligenceTesting/jazzer/releases/download/v0.22.1/jazzer-linux.tar.gz
24+
tar xzf jazzer-linux.tar.gz
25+
26+
# Option 2: Use Docker
27+
docker pull cifuzz/jazzer
28+
```
29+
30+
### Build the Fuzz Module
31+
32+
```bash
33+
cd /path/to/axis-axis2-java-core
34+
35+
# Build all modules first
36+
mvn install -DskipTests
37+
38+
# Build the fuzz module
39+
cd modules/fuzz
40+
mvn package
41+
```
42+
43+
### Run Individual Fuzzers
44+
45+
```bash
46+
# XML Parser Fuzzer
47+
./jazzer --cp=target/axis2-fuzz-2.0.1-SNAPSHOT.jar \
48+
--target_class=org.apache.axis2.fuzz.XmlParserFuzzer \
49+
--instrumentation_includes=org.apache.axiom.** \
50+
-max_total_time=300
51+
52+
# JSON Parser Fuzzer
53+
./jazzer --cp=target/axis2-fuzz-2.0.1-SNAPSHOT.jar \
54+
--target_class=org.apache.axis2.fuzz.JsonParserFuzzer \
55+
--instrumentation_includes=com.google.gson.** \
56+
-max_total_time=300
57+
58+
# HTTP Header Fuzzer
59+
./jazzer --cp=target/axis2-fuzz-2.0.1-SNAPSHOT.jar \
60+
--target_class=org.apache.axis2.fuzz.HttpHeaderFuzzer \
61+
--instrumentation_includes=org.apache.axis2.** \
62+
-max_total_time=300
63+
64+
# URL Parser Fuzzer
65+
./jazzer --cp=target/axis2-fuzz-2.0.1-SNAPSHOT.jar \
66+
--target_class=org.apache.axis2.fuzz.UrlParserFuzzer \
67+
--instrumentation_includes=org.apache.axis2.** \
68+
-max_total_time=300
69+
```
70+
71+
### Run with JUnit (Regression Testing)
72+
73+
The fuzzers can also be run as JUnit tests for CI integration:
74+
75+
```bash
76+
mvn test -Djazzer.fuzz=true
77+
```
78+
79+
## Understanding Output
80+
81+
### Successful Run
82+
```
83+
INFO: Seed: 1234567890
84+
#1000000 DONE cov: 1234 ft: 5678 corp: 100/10Kb exec/s: 50000
85+
```
86+
87+
### Crash Found
88+
```
89+
== Java Exception: java.lang.OutOfMemoryError
90+
at org.apache.axiom.om.impl.builder.StAXOMBuilder.<init>
91+
Crash file: crash-abc123def456
92+
```
93+
94+
The crash file contains the input that triggered the bug. Reproduce with:
95+
```bash
96+
./jazzer --cp=target/axis2-fuzz-2.0.1-SNAPSHOT.jar \
97+
--target_class=org.apache.axis2.fuzz.XmlParserFuzzer \
98+
crash-abc123def456
99+
```
100+
101+
## Comparison with Axis2/C Fuzzers
102+
103+
| Axis2/C | Axis2/Java | Component |
104+
|---------|------------|-----------|
105+
| `fuzz_xml_parser.c` | `XmlParserFuzzer.java` | XML/AXIOM |
106+
| `fuzz_json_parser.c` | `JsonParserFuzzer.java` | JSON |
107+
| `fuzz_json_reader.c` | (integrated in JsonParserFuzzer) | JSON→XML |
108+
| `fuzz_http_header.c` | `HttpHeaderFuzzer.java` | HTTP headers |
109+
| `fuzz_url_parser.c` | `UrlParserFuzzer.java` | URL parsing |
110+
111+
## Security Vulnerability Reporting
112+
113+
If fuzzing finds a security vulnerability:
114+
115+
1. **Do NOT** open a public GitHub issue
116+
2. Report to Apache Security Team: security@apache.org
117+
3. Include:
118+
- Crash file (input that triggers the bug)
119+
- Stack trace
120+
- Axis2/Java version
121+
122+
## Related Documentation
123+
124+
- [Axis2/C OSS-Fuzz Integration](https://github.com/apache/axis-axis2-c-core/blob/master/docs/OSS-FUZZ.md)
125+
- [Jazzer Documentation](https://github.com/CodeIntelligenceTesting/jazzer)
126+
- [OSS-Fuzz Documentation](https://google.github.io/oss-fuzz/)

modules/fuzz/pom.xml

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Licensed to the Apache Software Foundation (ASF) under one
4+
~ or more contributor license agreements. See the NOTICE file
5+
~ distributed with this work for additional information
6+
~ regarding copyright ownership. The ASF licenses this file
7+
~ to you under the Apache License, Version 2.0 (the
8+
~ "License"); you may not use this file except in compliance
9+
~ with the License. You may obtain a copy of the License at
10+
~
11+
~ http://www.apache.org/licenses/LICENSE-2.0
12+
~
13+
~ Unless required by applicable law or agreed to in writing,
14+
~ software distributed under the License is distributed on an
15+
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
~ KIND, either express or implied. See the License for the
17+
~ specific language governing permissions and limitations
18+
~ under the License.
19+
-->
20+
<project xmlns="http://maven.apache.org/POM/4.0.0"
21+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
23+
<modelVersion>4.0.0</modelVersion>
24+
25+
<groupId>org.apache.axis2</groupId>
26+
<artifactId>axis2-fuzz</artifactId>
27+
<version>2.0.1-SNAPSHOT</version>
28+
<packaging>jar</packaging>
29+
<name>Apache Axis2 - Fuzz Testing</name>
30+
<description>
31+
Comprehensive fuzz testing for Axis2/Java parsers.
32+
Mirrors the Axis2/C OSS-Fuzz approach for finding security vulnerabilities.
33+
34+
Fuzz targets:
35+
- XmlParserFuzzer: AXIOM/StAX XML parsing (XXE, XML bombs, buffer overflows)
36+
- JsonParserFuzzer: Gson JSON parsing (deep nesting, malformed JSON)
37+
- HttpHeaderFuzzer: HTTP header parsing (injection, overflows)
38+
- UrlParserFuzzer: URL/URI parsing (SSRF, malformed URLs)
39+
</description>
40+
41+
<properties>
42+
<maven.compiler.source>11</maven.compiler.source>
43+
<maven.compiler.target>11</maven.compiler.target>
44+
<jazzer.version>0.22.1</jazzer.version>
45+
<!-- Use 2.0.0 release (March 2025) for standalone testing; change to ${project.version} when integrated -->
46+
<axis2.test.version>2.0.0</axis2.test.version>
47+
</properties>
48+
49+
<dependencies>
50+
<!-- Jazzer fuzzing framework -->
51+
<dependency>
52+
<groupId>com.code-intelligence</groupId>
53+
<artifactId>jazzer-api</artifactId>
54+
<version>${jazzer.version}</version>
55+
</dependency>
56+
<dependency>
57+
<groupId>com.code-intelligence</groupId>
58+
<artifactId>jazzer-junit</artifactId>
59+
<version>${jazzer.version}</version>
60+
<scope>test</scope>
61+
</dependency>
62+
63+
<!-- Axis2 modules to fuzz (using released version for standalone testing) -->
64+
<dependency>
65+
<groupId>org.apache.axis2</groupId>
66+
<artifactId>axis2-kernel</artifactId>
67+
<version>${axis2.test.version}</version>
68+
</dependency>
69+
<dependency>
70+
<groupId>org.apache.axis2</groupId>
71+
<artifactId>axis2-json</artifactId>
72+
<version>${axis2.test.version}</version>
73+
</dependency>
74+
<dependency>
75+
<groupId>org.apache.axis2</groupId>
76+
<artifactId>axis2-transport-http</artifactId>
77+
<version>${axis2.test.version}</version>
78+
</dependency>
79+
80+
<!-- AXIOM for XML parsing (matches Axis2 2.0.0) -->
81+
<dependency>
82+
<groupId>org.apache.ws.commons.axiom</groupId>
83+
<artifactId>axiom-api</artifactId>
84+
<version>2.0.0</version>
85+
</dependency>
86+
<dependency>
87+
<groupId>org.apache.ws.commons.axiom</groupId>
88+
<artifactId>axiom-impl</artifactId>
89+
<version>2.0.0</version>
90+
</dependency>
91+
92+
<!-- Gson for JSON parsing -->
93+
<dependency>
94+
<groupId>com.google.code.gson</groupId>
95+
<artifactId>gson</artifactId>
96+
<version>2.10.1</version>
97+
</dependency>
98+
99+
<!-- Testing -->
100+
<dependency>
101+
<groupId>junit</groupId>
102+
<artifactId>junit</artifactId>
103+
<version>4.13.2</version>
104+
<scope>test</scope>
105+
</dependency>
106+
</dependencies>
107+
108+
<build>
109+
<plugins>
110+
<plugin>
111+
<groupId>org.apache.maven.plugins</groupId>
112+
<artifactId>maven-shade-plugin</artifactId>
113+
<version>3.5.1</version>
114+
<executions>
115+
<execution>
116+
<phase>package</phase>
117+
<goals>
118+
<goal>shade</goal>
119+
</goals>
120+
<configuration>
121+
<filters>
122+
<filter>
123+
<artifact>*:*</artifact>
124+
<excludes>
125+
<exclude>META-INF/*.SF</exclude>
126+
<exclude>META-INF/*.DSA</exclude>
127+
<exclude>META-INF/*.RSA</exclude>
128+
</excludes>
129+
</filter>
130+
</filters>
131+
</configuration>
132+
</execution>
133+
</executions>
134+
</plugin>
135+
</plugins>
136+
</build>
137+
</project>

modules/fuzz/run-fuzzers.sh

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/bin/bash
2+
#
3+
# Licensed to the Apache Software Foundation (ASF) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The ASF licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
19+
#
20+
# Run all Axis2/Java fuzzers locally
21+
#
22+
# Usage: ./run-fuzzers.sh [duration_seconds]
23+
#
24+
# Prerequisites:
25+
# - Jazzer installed and in PATH (or set JAZZER_PATH)
26+
# - Axis2/Java built with: mvn install -DskipTests
27+
# - Fuzz module built with: cd modules/fuzz && mvn package
28+
#
29+
30+
set -e
31+
32+
DURATION=${1:-60} # Default 60 seconds per fuzzer
33+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
34+
JAR_PATH="${SCRIPT_DIR}/target/axis2-fuzz-2.0.1-SNAPSHOT.jar"
35+
36+
# Find Jazzer
37+
JAZZER="${JAZZER_PATH:-jazzer}"
38+
if ! command -v "$JAZZER" &> /dev/null; then
39+
echo "Error: Jazzer not found. Install from:"
40+
echo " https://github.com/CodeIntelligenceTesting/jazzer/releases"
41+
exit 1
42+
fi
43+
44+
# Check if JAR exists
45+
if [ ! -f "$JAR_PATH" ]; then
46+
echo "Error: Fuzz JAR not found at $JAR_PATH"
47+
echo "Build with: cd modules/fuzz && mvn package"
48+
exit 1
49+
fi
50+
51+
echo "========================================"
52+
echo "Axis2/Java Fuzz Testing"
53+
echo "Duration per fuzzer: ${DURATION}s"
54+
echo "========================================"
55+
56+
FUZZERS=(
57+
"org.apache.axis2.fuzz.XmlParserFuzzer"
58+
"org.apache.axis2.fuzz.JsonParserFuzzer"
59+
"org.apache.axis2.fuzz.HttpHeaderFuzzer"
60+
"org.apache.axis2.fuzz.UrlParserFuzzer"
61+
)
62+
63+
RESULTS=()
64+
65+
for FUZZER in "${FUZZERS[@]}"; do
66+
echo ""
67+
echo "----------------------------------------"
68+
echo "Running: $FUZZER"
69+
echo "----------------------------------------"
70+
71+
FUZZER_NAME=$(echo "$FUZZER" | sed 's/.*\.//')
72+
CORPUS_DIR="${SCRIPT_DIR}/corpus/${FUZZER_NAME}"
73+
mkdir -p "$CORPUS_DIR"
74+
75+
if "$JAZZER" \
76+
--cp="$JAR_PATH" \
77+
--target_class="$FUZZER" \
78+
--keep_going=10 \
79+
"$CORPUS_DIR" \
80+
-- \
81+
-max_total_time="$DURATION" \
82+
-print_final_stats=1 2>&1; then
83+
RESULTS+=("$FUZZER_NAME: PASS")
84+
else
85+
EXIT_CODE=$?
86+
if [ $EXIT_CODE -eq 77 ]; then
87+
RESULTS+=("⚠️ $FUZZER_NAME: Crash found (see crash-* file)")
88+
else
89+
RESULTS+=("$FUZZER_NAME: Error (exit code $EXIT_CODE)")
90+
fi
91+
fi
92+
done
93+
94+
echo ""
95+
echo "========================================"
96+
echo "Summary"
97+
echo "========================================"
98+
for RESULT in "${RESULTS[@]}"; do
99+
echo "$RESULT"
100+
done

0 commit comments

Comments
 (0)