code-423n4 / 2024-03-phala-network-findings

0 stars 0 forks source link

Attacker can take over the blockchain node server running in cloud by http_request #56

Closed c4-bot-3 closed 3 months ago

c4-bot-3 commented 3 months ago

Lines of code

https://github.com/code-423n4/2024-03-phala-network/blob/main/phala-blockchain/crates/pink/chain-extension/src/lib.rs#L74-L98

Vulnerability details

Impact

This is a common issue in web2, if we running the node in cloud like aws, azure, gcp, there is a metadata endpoint in 169.254.169.254, which will store some secret like ak/sk.

So attacker can leverage this extension functon to call metadata endpoint to get the ak/sk with your cloud server, which can use to access your cloud server.

Example reference: https://hackingthe.cloud/aws/exploitation/ec2-metadata-ssrf/

Proof of Concept

As we can see, the funtion http_request will call async_http_request, it will collect everything (url, method, headers) user passed and send a request and return the response to user.

There is nothing limit or blacklist, and anyone can call it to send request to anywhere they want. In web2, it will named SSRF (Server-side request forgery). So if user call this function to make request to metadata endpoint (with special header to meet some cloud provider requirement), the cloud provider will return the ak/sk with the server. Anyone can use it to login in your cloud server

async fn async_http_request(
    request: HttpRequest,
    timeout_ms: u64,
) -> Result<HttpResponse, HttpRequestError> {
    if timeout_ms == 0 {
        return Err(HttpRequestError::Timeout);
    }
    let timeout = Duration::from_millis(timeout_ms);
    let url: reqwest::Url = request.url.parse().or(Err(HttpRequestError::InvalidUrl))?;
    let client = reqwest::Client::builder()
        .trust_dns(true)
        .timeout(timeout)
        .env_proxy(url.host_str().unwrap_or_default())
        .build()
        .or(Err(HttpRequestError::FailedToCreateClient))?;

    let method: Method =
        FromStr::from_str(request.method.as_str()).or(Err(HttpRequestError::InvalidMethod))?;
    let mut headers = HeaderMap::new();
    for (key, value) in &request.headers {
        let key =
            HeaderName::from_str(key.as_str()).or(Err(HttpRequestError::InvalidHeaderName))?;
        let value = HeaderValue::from_str(value).or(Err(HttpRequestError::InvalidHeaderValue))?;
        headers.insert(key, value);
    }

    let result = client
        .request(method, url)
        .headers(headers)
        .body(request.body)
        .send()
        .await;

    let mut response = match result {
        Ok(response) => response,
        Err(err) => {
            // If there is somthing wrong with the network, we can not inspect the reason too
            // much here. Let it return a non-standard 523 here.
            return Ok(HttpResponse {
                status_code: 523,
                reason_phrase: "Unreachable".into(),
                body: format!("{err:?}").into_bytes(),
                headers: vec![],
            });
        }
    };

Tools Used

manual audit

Recommended Mitigation Steps

actually this function is very dangerous, we should use it carefullly, here is some mitigation

Assessed type

Other

c4-pre-sort commented 3 months ago

141345 marked the issue as primary issue

c4-pre-sort commented 3 months ago

141345 marked the issue as sufficient quality report

141345 commented 3 months ago

metadata endpoint SSRF (Server-side request forgery)

kvinwang commented 3 months ago

We had a discussion when designing this and decided to have a professional external firewall program handle the network security. That's why all outgoing requests are supported to set a SOCKS proxy server.

c4-sponsor commented 3 months ago

kvinwang (sponsor) disputed

OpenCoreCH commented 3 months ago

Duplicating all SSRF issues, the fact that the destination address in the issue is 127.0.0.1 or some other internal address does not really make the difference, the underlying issue is the same.

c4-judge commented 3 months ago

OpenCoreCH marked the issue as duplicate of #53

c4-judge commented 3 months ago

OpenCoreCH changed the severity to 2 (Med Risk)

c4-judge commented 3 months ago

OpenCoreCH marked the issue as satisfactory

c4-judge commented 3 months ago

OpenCoreCH marked the issue as unsatisfactory: Out of scope