News for hackers. Stuff that matters.
Re:Format Strings in Rust 1.58 by pron on Friday January 14, 2022 @06:37AM (#29933226)
It's not enough that they're static literals. The replaced variables aren't. The language should provide a way for the format string to enforce that the expressions are sanitised.
Re:Format Strings in Rust 1.58 by paulgb on Friday January 14, 2022 @06:50AM (#29933321)
The compiler doesn’t know if the string being templated is SQL, HTML, YAML, JSON, or something else, so it doesn’t know how to sanitize the string.

IMHO generating code of any sort through string manipulation is a code smell, even if you ignore the security issues. There are better options like parameterized queries for SQL, macros for HTML, serde_json::json! for JSON, etc.

Re:Format Strings in Rust 1.58 by pron on Friday January 14, 2022 @06:57AM (#29933390)
> The compiler doesn’t know if the string being templated is SQL, HTML, YAML, JSON, or something else, so it doesn’t know how to sanitize the string.

That is the problem, and why security experts wouldn't let us add string interpolation to Java until we had a way to require the format string to say how it will be used and enforce proper validation. [1]

Even if programmers should be more careful, the fact remains that this is the #1 security vulnerability caused by language features. The language should, if possible, make it easier for developers to avoid the mistake rather than make it easier for them to make it.

[1]: https://openjdk.java.net/jeps/8273943

Re:Format Strings in Rust 1.58 by stubish on Friday January 14, 2022 @08:55PM (#29942854)
Looks like Java wants to skip format strings and jump straight to domain specific templating. I'm dubious doing this at the language level is a good idea. Picking a domain I'm familiar with, how do we handle this?

    SQL."SELECT * FROM orders WHERE \{mcol} LIKE '%' || \{qry} || '%'"
How does the the templating engine know that 'mcol' needs to be quoted as an SQL identifier using ", and that qry either needs to be quoted as an SQL string using ' or a replacement made to use a bind variable? And since 'qry' is being used in a LIKE expression, do any % or ? characters in it need to be escaped, or should they be passed through? I guess you need to force hints in the template (force, because we are trying stop people being able to write buggy code)

   SQL."SELECT * FROM orders WHERE \{mcol:sql_id} LIKE '%' || \{qry:sql_likestr} || '%'"
But none of that stops someone just doing this, which is the most common form of the bug:

   "SELECT * FROM orders WHERE " + mcol + " LIKE '%" + qry + "%'"
To stop people throwing arbitrary strings at a database connection, risking SQL injection attacks and other buggy behavior, you just need to stop people throwing strings at a database connection. Instead having the driver only accept an object. Which does not rely on a templating engine at all. std::fmt does not encourage or make it easier to write code with SQL injection bugs, and if you want to stop them, the only way is to stop the driver accepting arbitrary strings and instead force developers to use an API to correctly generate their SQL. Which is exactly what most ORMs do, although they generally allow people to force arbitrary strings in for convenience or non-standard SQL stanzas.
Re:Format Strings in Rust 1.58 by paulgb on Friday January 14, 2022 @07:26AM (#29933633)
Interesting, so to make sure I understand, if I were writing an SQL library I could require (at the type check level) that a query I was passed was constructed with a specific formatter, and that formatter would encode any substrings that I templated into it in a way appropriate for SQL?

I wonder how this would handle something like HTML injection, where the desired encoding can change within the same string depending on whether you’re in an attribute or a text block?

Re:Format Strings in Rust 1.58 by pron on Friday January 14, 2022 @08:07AM (#29933962)
> Interesting, so to make sure I understand, if I were writing an SQL library I could require (at the type check level) that a query I was passed was constructed with a specific formatter, and that formatter would encode any substrings that I templated into it in a way appropriate for SQL?

Yes. That's what Java's upcoming templated strings feature does. The library provides a templating policy as the way to create the appropriate type it requires.

> I wonder how this would handle something like HTML injection, where the desired encoding can change within the same string depending on whether you’re in an attribute or a text block?

The client library decides how to interpret and format the string in its policy.

Re:Format Strings in Rust 1.58 by thinkharderdev on Friday January 14, 2022 @08:03AM (#29933926)
But there is nothing enforcing the use of the correct template policy. I can still use the wrong CONCAT to build a SQL query. It certainly makes sense to make string interpolation extensible but doesn't actually eliminate the potential for doing things in an insecure way.
Re:Format Strings in Rust 1.58 by pron on Friday January 14, 2022 @08:10AM (#29933992)
We can't change the API of an existing library that already accepts strings for compatibility reasons (although we can make the safer API more attractive by making it more pleasant to use), but a new API can certainly enforce use of the correct policy by not accepting string parameters, only types that are constructed with the right policy, as the policy determines the type of the template and so the type system enforces the correct usage.
Re:Format Strings in Rust 1.58 by thinkharderdev on Friday January 14, 2022 @08:24AM (#29934129)
That is exactly my point. The way you can eliminate potential injection attacks is by not having libraries which accepts String and treat it as a sanitized input. But once you do that then there is no real reason to be wary of format strings. You can use format strings to build strings, but anything that needs a string that is sanitized against some potential injection attack only accepts a type that represents that invariant.
Re:Format Strings in Rust 1.58 by pron on Friday January 14, 2022 @08:27AM (#29934166)
> But once you do that then there is no real reason to be wary of format strings.

But then format strings don't help you much as you can't use them to create the sanitised types. You can't sanitise the string after it's been constructed.

Re:Format Strings in Rust 1.58 by thinkharderdev on Friday January 14, 2022 @08:49AM (#29934371)
Right, but there are many, many use cases for creating string in which you don't need some specific sanitization. Most of the time when I am using a format string I am not worried about sanitization.
Re:Format Strings in Rust 1.58 by pabs3 on Friday January 14, 2022 @06:58AM (#29933398)
In Haskell the compiler could know that.
Re:Format Strings in Rust 1.58 by acdha on Friday January 14, 2022 @07:23AM (#29933605)
You can construct a SQL client which doesn’t accept normal strings in either language but how would Haskell be different otherwise? It can’t magically tell what you’re going to do with a string after formatting it.
Re:Format Strings in Rust 1.58 by aseipp on Friday January 14, 2022 @07:34AM (#29933697)
Well, you can use strong types that separate e.g. String/SQLQuery/XMLBlob from one another, and then have very narrow conversion routines that are heavily audited to handle them safely. You can then use type directed programming to make conversions a little simpler (sometimes). This can give the appearance of things being handled "by the compiler", e.g. because typeclass resolution can be used to pick an appropriate instance. But it's not magical or anything. Maybe that's basically what you meant anyway.

Any statically typed language can do the first part, the second part is a tad less trivial (and arguably a footgun in some scenarios, but that's another discussion.)

Re:Format Strings in Rust 1.58 by adwn on Friday January 14, 2022 @06:51AM (#29933330)
You're still misunderstanding the purpose of format strings. They're not a templating engine for SQL, HTML, whatever. There's nothing to sanitize.
Re:Format Strings in Rust 1.58 by gspr on Friday January 14, 2022 @07:02AM (#29933437)
I think the point is that they may well be used like that. Maybe not explicitly, but I bet you that any language has a user that uses string formatting to build, say, an SQL query that is then passed as a string to the SQL engine.
Re:Format Strings in Rust 1.58 by adwn on Friday January 14, 2022 @07:14AM (#29933530)
You don't need format strings to create vulnerable queries. If you can't use them, this code:

    let query = format!("SELECT name FROM users WHERE id = {}", user_id);
can easily be replaced by this:

    let mut query = String::from("SELECT name FROM users WHERE id = ");
    query += user_id;
What, are you also going to forbid simple string operations? There will be some user that will use them to create an unsanitized query.
Re:Format Strings in Rust 1.58 by gspr on Friday January 14, 2022 @07:48AM (#29933803)
> You don't need format strings to create vulnerable queries. If you can't use them, this code:

I know, thank you.

> What, are you also going to forbid simple string operations?

Dude, chill. Why do you feel attacked? I'm just stating facts. Those facts are not a critique of you (or of Rust, a language I love).

Re:Format Strings in Rust 1.58 by adwn on Friday January 14, 2022 @10:19AM (#29935484)
I'm not feeling "attacked". I'm trying to help you understand that the argument "feature X might be used in a way that could lead to a incorrect behavior" on its own isn't enough to warrant exclusion of that feature, because that same argument can be used against basically all features of a language.
Re:Format Strings in Rust 1.58 by jamincan on Friday January 14, 2022 @09:19AM (#29934668)
There is a legitimate point that some programmers might misuse format strings and that by using named capturing in the format string, this misuse would be slightly more ergonomic. Nevertheless, legitimate uses of format strings also become more ergonomic, and legitimate uses would seem to far out-strip illegitimate uses.

Furthermore, within the Rust ecosystem, the tools to build SQL queries, or serialize/deserialize JSON generally provide interfaces that are more ergonomic than manually using format strings, so a programmer has little incentive to do so as it would constitute more work on their part.

Re:Format Strings in Rust 1.58 by kubb on Friday January 14, 2022 @06:54AM (#29933367)
Sanitized against what? JavaScript or SQL injection? The content of the replaced variables is not executed.