commit 80139672bea0b9548ac7dfdee54315f4fa6214ff
parent e6f1a4011125086c5bf82cd4953be089aee4debc
Author: MTRNord <mtrnord1@gmail.com>
Date: Fri, 12 Aug 2022 20:28:19 +0200
Add basic afl target
Diffstat:
13 files changed, 125 insertions(+), 18 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -4,4 +4,5 @@ notes.md
src/secrets.rs
/fuzz
/meep.rs
-/weird_ones/security_issues
-\ No newline at end of file
+/weird_ones/security_issues
+/afl/*/out/*
+\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
@@ -3,9 +3,17 @@ edition = "2021"
name = "matrix-fuzz"
version = "0.1.0"
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[lib]
+name = "matrix_fuzz"
+path = "src/lib.rs"
+
+[[bin]]
+name = "createRoom"
+path = "src/fuzzTargets/createRoom.rs"
[dependencies]
+afl = "*"
+arbitrary = {version = "1", features = ["derive"]}
fuzzcheck = {git = "https://github.com/MTRNord/fuzzcheck-rs.git", branch = "patch-1"}
once_cell = "1.13.0"
reqwest = {version = "0.11.11", features = ["blocking", "json", "gzip"]}
diff --git a/README.md b/README.md
@@ -8,9 +8,9 @@ Matrix fuzzing is a dumb fuzzer fuzzing a few matrix endpoints. It requires a HS
# Current targets
-- `/_matrix/client/v3/createRoom` - `tests::tests::fuzz_create_room`
+- `/_matrix/client/v3/createRoom` - `tests::tests::fuzz_create_room` - `createRoom`
-# Usage
+# Usage of fuzzcheck-rs
1. Create a HS
1. Setup a user
@@ -29,6 +29,26 @@ Matrix fuzzing is a dumb fuzzer fuzzing a few matrix endpoints. It requires a HS
1. Verify the error by trying the output json yourself
1. Please make sure to follow https://matrix.org/security-disclosure-policy/ for found errors instead of posting them in public unless you are 100% sure they are not a security issue. If you are in doubt prefer the security disclosure policy.
+# Usage of afl.rs
+
+1. Create a HS
+1. Setup a user
+1. Add the secrets to src/secrets.rs.
+
+ Example code:
+
+ ```rust
+ pub const USERNAME: &str = "@a:localhost";
+ pub const PASSWORD: &str = "abc123";
+ ```
+
+1. Install afl.rs -> `cargo install afl`
+1. Run `cargo afl build`
+2. Run `cargo afl fuzz -i ./afl/<target>/in -o ./afl/<target>/out ./target/debug/<target>`
+3. Wait until it crashes
+4. Verification is a little harder. See https://github.com/rust-fuzz/afl.rs/issues/215 on how to reproduce things
+5. Please make sure to follow https://matrix.org/security-disclosure-policy/ for found errors instead of posting them in public unless you are 100% sure they are not a security issue. If you are in doubt prefer the security disclosure policy.
+
# Hall of Explosions (Bugs found)
- https://github.com/matrix-org/synapse/issues/13510
diff --git a/afl/createRoom/in/1 b/afl/createRoom/in/1
@@ -0,0 +1 @@
+{"initial_state":[{"content_keys":["","",""],"content_values":["","","",""],"type":"","state_key":""}],"room_version":"","topic":""}
+\ No newline at end of file
diff --git a/afl/createRoom/in/2 b/afl/createRoom/in/2
@@ -0,0 +1 @@
+{"initial_state":[{"content_keys":["","",""],"content_values":["","","",""],"type":"","state_key":""}],"room_alias_name":"�iy|?i�sY��=b�W\"�R\b���\u001for\n�6']��+䵥�s��\u001e�Q�\t�,fS{��!�\\\bR\u0012I��\u0018���\u0002\u0000�<\u001c0�ߡN\u0005ɺ��7����X��\u001e#,�w���hV��t;\u000eLTC��P\u001c\u000e\u000eV�\u000eΗ[u\u0011���\u0003\u0005���2���(^��\u0003��,_�\u0014���\u0006�$�$\u0011bA\u0002�qrf��L�Sl�%�c�vK�\u001c","room_version":"","topic":""}
+\ No newline at end of file
diff --git a/afl/createRoom/in/3 b/afl/createRoom/in/3
@@ -0,0 +1 @@
+{"creation_content_keys":["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","��","","","","\u0001","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\u0003","","","","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\u0002�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","H","","","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","��","","","","","","T�","","","","","","","","","�C","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","j","","","","","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","�","","","","","","","","","","","","","","","","","","","","","�","","","","","","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","�2","","","","","","","","","","","","","","","","","","","","","","","","","\u001c","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","O","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","��","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","\u0016","","","","","","","","","","","","","","","","","","","","","","","=","","","","","","","","h�!","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\u0002","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\u0006","","","","","","","","","","$","","","�","",""],"creation_content_values":["","","","","","","","","","","","","","","�I4�","","�","","","","","","","","e","","","","","","","","","","","\u001e-H'�","","","�","","\u0018","","","","","","","","�W","","","","","�","","","","","","","","","","","","","","","","b\u0003͊","","�Y","","","","","","","","","","","","","","","","","","","","","","","","\u000b�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","=","","","","","","","","","","","","","","","","","","","","","","","","","","","`","","","","","","","","","",")","\u0003","\u001f","","","","","","�","","","","","","","","%b","","","","","","\u0001k�u","","","","","","","","","",":","","","","","","","","","","","�","","","","\tc�","�?","","","","","","","","","","","","","","","","","","","","�","","","","","","","","","\b","","%","","","","","","","","","","","","","","","","","t","","�","","����","","","","","","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","�","*","","","","","","","","","","c","","","","","","�","","","","","","","","�","","","","","","","","","","m","","B","","","","","","","","","","","","","","","","","","","","","","","","","","","","U","","","","","","","","","","�\u0017�","","","","","�","","","})","","","","�","","","","","�2","","","","","","","","","2�","","","","","","","","","","","l","","","","","","","","","",""],"initial_state":[{"content_keys":["","","","",""],"content_values":[],"type":"","state_key":""},{"content_keys":["","","","","","","","","","","","",""],"content_values":["","","","","u","","","","","","","",""],"type":"","state_key":""},{"content_keys":[""],"content_values":["","",""],"type":"","state_key":""},{"content_keys":["","",""],"content_values":[""],"type":"","state_key":""},{"content_keys":["&",""],"content_values":["","","","","",""],"type":"","state_key":""},{"content_keys":["","","",""],"content_values":["","","",""],"type":"","state_key":""},{"content_keys":["","","","","","","","","","","","","","","","","","","","�","","","","","","","","","","","","","","","","","",""],"content_values":[""],"type":"","state_key":""},{"content_keys":[],"content_values":["",""],"type":"","state_key":""},{"content_keys":[],"content_values":["","",""],"type":"","state_key":""},{"content_keys":[],"content_values":[],"type":"","state_key":""},{"content_keys":["",""],"content_values":["","",""],"type":"","state_key":""},{"content_keys":[],"content_values":[""],"type":"","state_key":""},{"content_keys":["","",""],"content_values":[""],"type":"","state_key":""},{"content_keys":[],"content_values":["",""],"type":"","state_key":""},{"content_keys":["","","","","","","","","}","","","","","",""],"content_values":["","","","","","","","","",""],"type":"","state_key":""},{"content_keys":[],"content_values":["","","",""],"type":"","state_key":""},{"content_keys":["",""],"content_values":[""],"type":"","state_key":""},{"content_keys":["",""],"content_values":["",""],"type":"","state_key":""},{"content_keys":["","","",""],"content_values":["","","","",""],"type":"","state_key":""},{"content_keys":["",""],"content_values":["","","","",""],"type":"","state_key":""},{"content_keys":["",""],"content_values":[],"type":"","state_key":""},{"content_keys":[],"content_values":[],"type":"","state_key":""},{"content_keys":["",""],"content_values":[""],"type":"","state_key":""},{"content_keys":["","","","",""],"content_values":["","J","","","","!"],"type":"q","state_key":""},{"content_keys":["",""],"content_values":[""],"type":"","state_key":""},{"content_keys":[""],"content_values":[],"type":"","state_key":""},{"content_keys":["","","","",""],"content_values":["",""],"type":"","state_key":""},{"content_keys":[],"content_values":[],"type":"","state_key":"�"},{"content_keys":[],"content_values":[""],"type":"","state_key":""},{"content_keys":["","","","","",""],"content_values":["","","","","",""],"type":"","state_key":""},{"content_keys":["",""],"content_values":[""],"type":"","state_key":""},{"content_keys":[""],"content_values":[""],"type":"","state_key":""},{"content_keys":[""],"content_values":["",""],"type":"","state_key":""},{"content_keys":["",""],"content_values":[""],"type":"","state_key":""},{"content_keys":[],"content_values":["","","",""],"type":"","state_key":""},{"content_keys":[""],"content_values":[""],"type":"","state_key":"K"},{"content_keys":[""],"content_values":[],"type":"","state_key":""},{"content_keys":[""],"content_values":["","",""],"type":"","state_key":""},{"content_keys":["","","","","",""],"content_values":["","","",""],"type":"","state_key":""},{"content_keys":[""],"content_values":["","","",""],"type":"�","state_key":""},{"content_keys":[],"content_values":[""],"type":"","state_key":""},{"content_keys":[""],"content_values":[],"type":"","state_key":""},{"content_keys":["","","","","","",""],"content_values":[""],"type":"","state_key":""},{"content_keys":[],"content_values":[""],"type":"","state_key":""},{"content_keys":[""],"content_values":["","",""],"type":"","state_key":""},{"content_keys":["","","",""],"content_values":[],"type":"","state_key":""},{"content_keys":[""],"content_values":[""],"type":"","state_key":""},{"content_keys":["",""],"content_values":["","","","~","",""],"type":"","state_key":""},{"content_keys":[""],"content_values":["","",""],"type":"","state_key":""},{"content_keys":["","",""],"content_values":[""],"type":"","state_key":""},{"content_keys":[],"content_values":[],"type":"","state_key":""},{"content_keys":["","","","","","","","",""],"content_values":["","","",""],"type":"","state_key":""},{"content_keys":["","","","","","",""],"content_values":["",""],"type":"","state_key":""},{"content_keys":[],"content_values":["","","","",""],"type":"","state_key":""},{"content_keys":["","",""],"content_values":[],"type":"","state_key":""},{"content_keys":[""],"content_values":[""],"type":"","state_key":""},{"content_keys":[],"content_values":["",""],"type":"","state_key":""},{"content_keys":["","","",""],"content_values":["","","","",""],"type":"","state_key":""},{"content_keys":[],"content_values":[""],"type":"","state_key":""},{"content_keys":[],"content_values":["","",""],"type":"","state_key":"K��"},{"content_keys":[""],"content_values":["","","","","","","","","","","",""],"type":"","state_key":"5"}],"invite":["","�","","","","","","�","","","","","","","","","","","","","","\"","","","","","","","","","�","","","","","","","","","","","","","","","","","","","\u0010\u0019","","","\u0007","","","","","","","","","","","[","","","","","","","","","","","W","","","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","G","","�","","","","","","","","","","","","","","","","�","=��\u001e","","","","","","","","�,","","","","","","","","","","q","","","","","","","","","","","","","","","","","","�*","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","R","","","","","","","","","","�","","","","","","","","","","","","","","","","","","","","","p","","","","","","&","","","","","","","","","","","","","","","","e","\u000e","","�","","","","�","","","�","","","","","","","","","","","","","","","","","l","","","","","","","����ˆ@�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\f","","","","","","","","","�","","","","","","�","","","","G","","","","","","","","<","","","","I","","","�","","","","","","","","E\u0003\u0019","","","","","","","","","","","","","l�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\u0012","","","","","","","","","","","","","","","","","�","","","","","","","�","","","","","","","","","","","","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","\u0006","","","","","","","","","","","","","\u001a","","","","","","","","","","","","","","","","","�","","","","","","","","","","","","","","","","","","","c","","","","","","","","","","","","","","","","","","","","","","","","","","","","","5fv","","","","","","","","","�","","","","","","","","","","\u0007","","","","","","","","","","","","","","","","","","","","a","","","","","","","","","","","\u0002t\u0012\u001e��3�\u0010����}","","","","","","|","","","","","","","","'","","","","2","�<��","","","","","","","","","","","","","","","","","","�","","","\u001b","","","","","","","�","","","","","","","","","","","","","","","","","<θ\u0015","","","","","","","","","","","","","","","","","","�","","","","","","\u0011y�","","","","R","","�RI���#","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","I","","","","","","","","","","","","","","","!","","","","","","","","","","","","","","��","","","","","��","","","","","","\u001d","","Y�","","","","","","","","�","","","","","","","","","","","","","","","","","","","*�g","","","A","","","","","","","","","","","","","","","","","","","�","","","\u0010�\r","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","�","","","","","","","","","","","","","","","",";","","","","\u0006","","","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","\u0015\r|","",""],"room_version":"|","visibility":""}
+\ No newline at end of file
diff --git a/afl/createRoom/in/4 b/afl/createRoom/in/4
@@ -0,0 +1 @@
+{"room_version":"","topic":"��"}
+\ No newline at end of file
diff --git a/afl/createRoom/in/5 b/afl/createRoom/in/5
@@ -0,0 +1 @@
+{"room_alias_name":"","room_version":""}
+\ No newline at end of file
diff --git a/afl/createRoom/in/6 b/afl/createRoom/in/6
@@ -0,0 +1 @@
+{"creation_content_keys":["b","","","","","","","","","","","","","\u0006","","","","","","","","","","","","","","","","","","","","","","","","","�","","","","","","","","","","","","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","@","","A\u0010U","","","","","","","","","","","","","","","","","","","","","","_","","","","","","","","","","�","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"invite":["","","","","","","","","",""," ","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","�","","","","","","","","","","","","","","","","","","","","","�","","","","","","","","","","","","","","","","","� �","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","�S","�","�g-","","","�","","!","","","","","","","","�","","\u000e","","","","","","","","","","","","","","","","","","Lj","","","","","","","=","","�","","","","","","","","(e","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","�","","","","","",""],"is_direct":true,"name":"�?�jah�\u001a�h�����^�z]ɼ���$:%�t�\u001a��\\m�\u0000$Z���","preset":"�)m,|���b��\u001cNn","room_version":"\u001f"}
+\ No newline at end of file
diff --git a/afl/createRoom/in/7 b/afl/createRoom/in/7
@@ -0,0 +1 @@
+2�����La\u0002�3�Ԟ9U8�Y��\u001c����Vץʅ�9��K�� �rw}�@R\u0007\u001f�\t����\u000bJ\u000e�d��","room_version":"\u001f"}
+\ No newline at end of file
diff --git a/src/fuzzTargets/createRoom.rs b/src/fuzzTargets/createRoom.rs
@@ -0,0 +1,63 @@
+#![allow(non_snake_case)]
+use matrix_fuzz::{client, secrets::ACCESS_TOKEN, types::create_room::CreateRoomMagicJSON};
+
+fn main() {
+ afl::fuzz_nohook!(|data: CreateRoomMagicJSON| {
+ // FIXME: We probably should set it to null and not do a false positive
+ // HACK due to https://github.com/matrix-org/synapse/issues/13510
+ if let Some(room_alias_name) = &data.room_alias_name {
+ if room_alias_name.contains('\0') {
+ return;
+ }
+ }
+ // HACK due to NUL in type or state_key
+ if let Some(initial_state) = &data.initial_state {
+ for state in initial_state {
+ if state._type.contains('\0') {
+ return;
+ }
+ if state.state_key.contains('\0') {
+ return;
+ }
+ }
+ }
+ /*// HACK due to https://github.com/matrix-org/synapse/issues/13511
+ if let Some(pids) = &data.invite_3pid {
+ for pid in pids {
+ if pid.address.is_empty() {
+ return;
+ }
+ }
+ }*/
+
+ // TODO: Login once and reuse the access token
+ let access_token = ACCESS_TOKEN;
+ let client = client();
+ let resp = client
+ .post("http://localhost:8008/_matrix/client/v3/createRoom")
+ .header("Authorization", format!("Bearer {}", access_token))
+ .json(&data)
+ .send();
+ if let Ok(resp) = resp {
+ let status = resp.status();
+ if !status.is_success() {
+ //println!("Status: {:?}", status);
+ let content = resp.text();
+ if let Ok(ref content) = content {
+ if content.contains("M_ROOM_IN_USE")
+ || content.contains("Invalid characters in room alias")
+ || content.contains("':' is not permitted in the room alias name. Please note this expects a local part — 'wombat', not '#wombat:example.com'.")
+ || content.contains("M_UNSUPPORTED_ROOM_VERSION")
+ || content.contains("Invalid user_id")
+ || content.contains("is not a valid preset")
+ || content.contains("You are not allowed to set others state")
+ {
+ return;
+ }
+ }
+
+ panic!("Content: {:?}", content);
+ }
+ }
+ });
+}
diff --git a/src/lib.rs b/src/lib.rs
@@ -7,17 +7,17 @@ use crate::types::{Flow, LoginGet, LoginPost};
use once_cell::sync::OnceCell;
use std::collections::HashMap;
-mod secrets;
-mod types;
+pub mod secrets;
+pub mod types;
#[no_coverage]
-fn access_token() -> &'static String {
+pub fn access_token() -> &'static String {
static INSTANCE: OnceCell<String> = OnceCell::new();
INSTANCE.get_or_init(login)
}
#[no_coverage]
-fn client() -> &'static reqwest::blocking::Client {
+pub fn client() -> &'static reqwest::blocking::Client {
static INSTANCE: OnceCell<reqwest::blocking::Client> = OnceCell::new();
INSTANCE.get_or_init(|| {
reqwest::blocking::Client::builder()
@@ -134,17 +134,17 @@ mod tests {
// FIXME: We probably should set it to null and not do a false positive
// HACK due to https://github.com/matrix-org/synapse/issues/13510
if let Some(room_alias_name) = &data.room_alias_name {
- if room_alias_name.contains("\0") {
+ if room_alias_name.contains('\0') {
return true;
}
}
// HACK due to NUL in type or state_key
if let Some(initial_state) = &data.initial_state {
for state in initial_state {
- if state._type.contains("\0") {
+ if state._type.contains('\0') {
return true;
}
- if state.state_key.contains("\0") {
+ if state.state_key.contains('\0') {
return true;
}
}
@@ -168,7 +168,7 @@ mod tests {
.json(&json_data)
.send();
if let Ok(resp) = resp {
- let status = resp.status().clone();
+ let status = resp.status();
if !status.is_success() {
//println!("Status: {:?}", status);
let content = resp.text();
diff --git a/src/types/create_room.rs b/src/types/create_room.rs
@@ -1,8 +1,9 @@
+use arbitrary::Arbitrary;
use fuzzcheck::DefaultMutator;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
-#[derive(Clone, Serialize, Deserialize, Debug, Default)]
+#[derive(Clone, Serialize, Deserialize, Debug, Default, Arbitrary)]
pub struct CreateRoomMagicJSON {
#[serde(skip_serializing_if = "Option::is_none")]
pub creation_content: Option<HashMap<String, String>>,
@@ -74,7 +75,7 @@ impl From<&CreateRoomMagic> for CreateRoomMagicJSON {
}
}
-#[derive(Clone, Serialize, Deserialize, Debug, Default, DefaultMutator)]
+#[derive(Clone, Serialize, Deserialize, Debug, Default, DefaultMutator, Arbitrary)]
pub struct CreateRoomMagic {
#[serde(skip_serializing_if = "Option::is_none")]
pub creation_content_keys: Option<Vec<String>>,
@@ -103,7 +104,7 @@ pub struct CreateRoomMagic {
pub visibility: Option<String>,
}
-#[derive(Clone, Serialize, Deserialize, Debug, DefaultMutator, Default)]
+#[derive(Clone, Serialize, Deserialize, Debug, DefaultMutator, Default, Arbitrary)]
pub struct Invite3pid {
pub address: String,
pub id_access_token: String,
@@ -111,7 +112,7 @@ pub struct Invite3pid {
pub medium: String,
}
-#[derive(Clone, Serialize, Deserialize, Debug, Default)]
+#[derive(Clone, Serialize, Deserialize, Debug, Default, Arbitrary)]
pub struct StateEventJSON {
pub content: HashMap<String, String>,
#[serde(rename = "type")]
@@ -150,7 +151,7 @@ impl From<StateEvent> for StateEventJSON {
}
}
-#[derive(Clone, Serialize, Deserialize, Debug, DefaultMutator, Default)]
+#[derive(Clone, Serialize, Deserialize, Debug, DefaultMutator, Default, Arbitrary)]
pub struct StateEvent {
pub content_keys: Vec<String>,
pub content_values: Vec<String>,