Rust函数是否会生成易受SQL注入攻击的SQL字符串?

Ama*_*ani 1 sql rust

我有以下Rust函数,它String为SQLite数据库创建一个SQL语句.

fn add_repo_statement(repo: &Repo) -> String {
    format!("INSERT INTO repositories (name, scm, path)
            VALUES ({}, {}, {})", repo.name, repo.scm, repo.path)
}
Run Code Online (Sandbox Code Playgroud)

我对SQL注入不是很熟悉; 是这样的Rust函数容易受到SQL注入吗?如果是,那究竟是什么问题和可能的解决方案?

She*_*ter 9

是的,这很脆弱

这不是Rust特定的或SQLite特定的; 如果使用任何语言的用户提供的参数为任何数据库生成SQL字符串,则它很容易受到攻击.

我对SQL注入不是很熟悉

没有理由继续留在这个状态.去那里学习 ; 我们会等的...


该TL; DR是恶意用户可以指定值repo.name,repo.scm或者repo.path,当组合时,生成SQL你想要什么,不办:

fn main() {
    let sql = format!(
        "INSERT INTO repositories (name, scm, path) VALUES ({}, {}, {})",
        r#""hi", "from", "injection"); DROP TABLE repositories; --"#, 
        "",
        ""
    );
    println!("{}", sql);
}
Run Code Online (Sandbox Code Playgroud)
INSERT INTO repositories (name, scm, path) VALUES ("hi", "from", "injection"); DROP TABLE repositories; --, , )
Run Code Online (Sandbox Code Playgroud)

修复是使用适当的引用/参数化机制.我鼓励你使用像Diesel这样的访问抽象层.这样做,您的代码看起来像这个未经测试的代码:

insert_into(repositories)
    .values((name.eq(repo.name), scm.eq(repo.scm), path.eq(repo.path)))
    .execute(conn);
Run Code Online (Sandbox Code Playgroud)

或者你可以做得更好

insert_into(repositories)
    .values(repo)
    .execute(conn);
Run Code Online (Sandbox Code Playgroud)

如果您不想出于任何原因使用Diesel,直接驱动程序(如rusqlite)提供了类似的机制,如此未经测试的代码所示:

conn.execute(
    "INSERT INTO repositories (name, scm, path) VALUES (?1, ?2, ?3)",
    &[&repo.name, &repo.scm, &repo.path],
).unwrap();
Run Code Online (Sandbox Code Playgroud)