Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a Rust function which generates a String of SQL vulnerable to SQL injection?

Tags:

sql

rust

I have the following Rust function which creates a String of an SQL statement for a SQLite database.

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

I'm not very familiar with SQL injection; is such a Rust function vulnerable to SQL injection? If yes, what exactly is the problem and possible solution?

like image 339
Amani Avatar asked Dec 18 '22 23:12

Amani


1 Answers

Yes, this is vulnerable

This isn't Rust-specific or SQLite-specific; if you generate a SQL string using user-provided parameters in any language for any database, it is vulnerable.

I'm not very familiar with SQL injection

There's simply no excuse to remain in this state. Go out there and learn; we will wait...


The TL;DR is that a malicious user can specify values for repo.name, repo.scm, or repo.path that, when combined, generates SQL that does not do what you want:

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

The fix is to use appropriate quoting/parameterization mechanisms. I'd encourage you to use an access abstraction layer like Diesel. Doing so, your code would look something like this untested code:

insert_into(repositories)
    .values((name.eq(repo.name), scm.eq(repo.scm), path.eq(repo.path)))
    .execute(conn);

Or you can make it nicer as

insert_into(repositories)
    .values(repo)
    .execute(conn);

If you don't want to use Diesel for whatever reason, direct drivers like rusqlite provide similar mechanisms, shown in this untested code:

conn.execute(
    "INSERT INTO repositories (name, scm, path) VALUES (?1, ?2, ?3)",
    &[&repo.name, &repo.scm, &repo.path],
).unwrap();
like image 151
Shepmaster Avatar answered Jan 26 '23 00:01

Shepmaster