3

我有一个格式化 MySQL 查询的小型 Rust 程序,但我发现它在更大的查询上失败,返回

Urlencoded 有效负载大小大于允许的大小(默认值:256kB)

我正在使用actix web,它看起来像这样

use actix_web::{
    web, App, HttpResponse, HttpServer, Result,
};

#[derive(Deserialize)]
pub struct MyParams {
    q: String,
}

fn index(params: web::Form<MyParams>) -> Result<HttpResponse> {
    Ok(HttpResponse::Ok()
        .content_type("text/html; charset=utf-8")
        .body("test"))
        // .body(mysql_format2(&params.q[..])))
}

fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new().service(
            web::resource("/")
                .route(web::post().to(index))
        )
    })
    .bind("127.0.0.1:48627")?
    .run()
}

调用这个的 PHP 脚本看起来像

$this->FormattedMySQL = str_repeat("make a big query ", 1024*256);

$query =  http_build_query([
    'q' => $this->FormattedMySQL,
]);

// if I change this to 16385 (+1)
// then it breaks and returns that error
$query = substr($query, 0, 16384);

if ($this->FormatMySQL && strlen($query) <= 262144) {
    try {
        $this->VerbosePrint('formatting');
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, MYSQL_FORMAT_ENDPOINT);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        $this->FormattedMySQL = curl_exec($ch);
        curl_close($ch);
    } catch (Exception $_) { }
}

我错过了什么,或者为什么这似乎会为 16kB 而不是 256kB 抛出此错误?

我看到也可以设置Payload配置,但我不完全确定如何/在我现有的代码中应用它。

4

1 回答 1

3

快速回答是有第二个配置 ( FormConfig),这就是你要面对的。目前还不清楚,因为它返回的错误类型与PayloadConfig(这是有原因的,我将在“更长的版本”中解释)

将您的 actix 服务器定义更改为此以将其更改为 256kb:

HttpServer::new(|| {
    App::new().service(
        web::resource("/")
            .route(web::post()
                .to(index)
            )
            .data(web::Form::<MyParams>::configure(|cfg| cfg.limit(256 * 1024)))
    )
})
.bind("127.0.0.1:48627")?
.run()

您还需要 import actix_web::FromRequest,因为这是对象类型从请求变为 urlencoded 形式的地方,也是configure()方法所在的地方。

现在,为了解释!

Actix 与其他框架非常相似,具有多层限制。你找到了其中一个,这是另一个。

您发现的那个可以通过内存耗尽来防止拒绝服务(即,有人故意发送大量有效负载来破坏您的服务器,因为它必须将主体存储在某个地方以进行处理)。它管理请求的整个有效负载。

您要针对的限制是对每个单独字段的限制要小得多,并且它的存在是为了防止不同类型的耗尽攻击。假设你的攻击者知道你正在用一些东西解析输入;让我们假设它是 JSON。通过发送任意大且复杂的 JSON,他们可以在处理单个请求时有效地锁定您的服务器。小数据输入,非常大的后果。

因此,这两个限制通常是相互独立的,并允许您根据自己的要求微调限制。很多小田地?没问题。一大块?也不是问题。

如果您想查看代码本身,限制的效果FormConfig位于此处。由于类型返回与PayloadConfig限制相同((Overflow此结构的变体)[ https://docs.rs/actix-web/1.0.7/actix_web/error/enum.UrlencodedError.html]),信息不清楚,结果你最终摸不着头脑。

我认为,“类似”错误的主要目的是防止服务器向潜在的攻击者指示他们击中的限制,这似乎是他们的想法。面向用户的错误描述是问题所在,可以通过适当的 PR 进行调整。

于 2019-09-16T21:46:43.053 回答