6 ms·
How is that related? The new format strings must be static literals because they're decoded at compile time. It is impossible to use them for any kind of code i
by adwn 5y ago
How is that related? The new format strings must be static literals because they're decoded at compile time. It is impossible to use them for any kind of code injection.
- pron 5y agoIt'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.
- paulgb 5y agoThe 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.
- pron 5y ago> 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 https://openjdk.java.net/jeps/8273943
- stubish 5y agoLooks 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.
- paulgb 5y agoInteresting, 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?
- pron 5y ago> 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.
- thinkharderdev 5y agoBut 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.
- pron 5y agoWe 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.
- thinkharderdev 5y agoThat 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.
- pron 5y ago> 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.
- thinkharderdev 5y agoRight, 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.
- pabs3 5y agoIn Haskell the compiler could know that.
- acdha 5y agoYou 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.
- aseipp 5y agoWell, 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.)
- adwn 5y agoYou're still misunderstanding the purpose of format strings. They're not a templating engine for SQL, HTML, whatever. There's nothing to sanitize.
- gspr 5y agoI 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.
- adwn 5y agoYou 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.
- gspr 5y ago> 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).
- adwn 5y agoI'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.
- jamincan 5y ago
- kubb 5y agoSanitized against what? JavaScript or SQL injection? The content of the replaced variables is not executed.