Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PoC of introducing FromSpoofableRequestParts and Spoofable #3001

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

bengsparks
Copy link
Contributor

@bengsparks bengsparks commented Oct 20, 2024

Motivation

PoC to check which solution to pick for #2998.
Attempts to come as close to the original idea of extractors as possible, without increasing implementation complexity.

Solution

Add a new trait FromSpoofableRequestParts that is private to axum-extra.
This trait is only to be implemented by extractors that read from spoofable portions of HTTP requests.
No extractor should ever implement both FromSpoofableRequestParts and FromRequestsParts.

A blanket implementation of FromRequestsParts is provided by Spoofable for all extractors that implement FromSpoofableRequestParts, so that reading via destructuring i.e. Spoofable(Extractor(inner)) can continue to be used in handlers.

use axum::{routing::get, Router};
use axum_extra::extract::{Scheme, Spoofable};
use tokio::net::TcpListener;

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(f));

    let listener = TcpListener::bind("127.0.0.1:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

async fn f(Spoofable(Scheme(scheme)): Spoofable<Scheme>) -> String {
    scheme
}

See examples/spoofable-scheme for a short demonstration.

@yanns
Copy link
Collaborator

yanns commented Oct 20, 2024

Thanks!
How would we force Host and Schema to use this? We would remove the FromRequestParts for them right?

@bengsparks
Copy link
Contributor Author

The traits share the same function signatures and bounds, so simply exchanging the trait name within the impl block is sufficient.

@yanns
Copy link
Collaborator

yanns commented Nov 7, 2024

To finish this PR: could you use this for Host and Schema?
In the documentation, should we link to https://owasp.org/www-community/pages/attacks/ip_spoofing_via_http_headers? or is it better not to have any link, but only a description? We could re-use some of the content of the page:

Malicious actors utilize spoofing to inject payloads via HTTP headers, leading to generating inaccurate logs or inject malicious payloads via HTTP headers.
As remediation, always validate and sanitize the extract value:

  • Implement strict input validation to ensure that client-provided data, including headers, is legitimate.
  • Sanitize input to remove potentially harmful content.

@bengsparks
Copy link
Contributor Author

bengsparks commented Nov 7, 2024

To finish this PR: could you use this for Host and Schema?

Yes; I added an example to the PR that showcases Spoofable<Scheme>.
The implementation for Host would be similar.

In the documentation, should we link to https://owasp.org/www-community/pages/attacks/ip_spoofing_via_http_headers? or is it better not to have any link, but only a description? We could re-use some of the content of the page:

Malicious actors utilize spoofing to inject payloads via HTTP headers, leading to generating inaccurate logs or inject malicious payloads via HTTP headers.
As remediation, always validate and sanitize the extract value:

  • Implement strict input validation to ensure that client-provided data, including headers, is legitimate.
  • Sanitize input to remove potentially harmful content.

Those bullet points sound good enough! Maybe add an inline example in the docs that uses scheme.parse<ExpectedSchemeEnum> to validate the extracted Scheme

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants