2

Two of the top 3 security vulnerabilities in the OWASP Top 10 come from trusting user input (Injection and XSS). To deal with this, Ruby lets you "taint" Strings received from the user as unsafe.

In a type-safe language like Kotlin you can (theoretically) take this one step further with a Tainted class that wraps a String, but is not extended from CharSequence. Then everywhere you write your (for example) HTML output, you have to run all your Tainted objects through an escapeHtml(Tainted t), escapeSql(Tainted t), or escapeUrl(Tainted t), or you get a compile error.

I can make a Tainted class in Kotlin too, but Kotlin's String Templates assume that every class has a toString() method and make no complaint when writing these Tainted objects out in strings, thus defeating most of the purpose of a tainted class.

Is there a way I can generate a compile-time error in Kotlin when I do this:

val t = Tainted("Robert'); DROP TABLE STUDENTS; --")
return "SELECT * FROM STUDENTS WHERE NAME IN ($t);"

If there was a way to exclude a class from working inside a String Template (and StringBuilder) that would do it. Or a compiler setting to raise an error when using a certain class or classes in them? I'm just wondering if anyone has found a way to do this effectively in Kotlin.

Without this, there could still be a benefit of using a Tainted class to "Make Wrong Look Wrong", even if the IDE and compiler can only detect some and not all encoding errors.

GlenPeterson
  • 14,890
  • 6
  • 47
  • 75
  • Aren't string sanitation methods designed to prevent *runtime* problems? Who are you protecting at compile-time... the developer against himself? – Robert Harvey May 27 '16 at 20:56
  • @RobertHarvey What is more important to think about when coding a web/database app? I'm my own worst enemy in a lot of situations. – GlenPeterson May 27 '16 at 20:57
  • But you're not going to get a bad string until someone taints it. Surely the developer is smart enough to figure out how to make clean strings. Is your assumption here that some developers might be malicious? – Robert Harvey May 27 '16 at 20:58
  • @RobertHarvey you wrap the thing that takes parameters off requests so that it returns Tainted objects. Then you store them in the database, read them back, and *have* to encode them before writing them out again. To audit your code, you only need to look for ".queryParams(" to see that they are all wrapped in Tainted objects. It seems to me like it's worth taking every precaution. If your language has type safety, why not leverage it to do this for you? – GlenPeterson May 27 '16 at 21:00
  • Oh, I see what you are doing. Honestly, though, this seems like a job for a linter, not a compiler. It's not in the class of problems I would call "compiler problems." A bare, non-Tainted string is a perfectly legitimate use to a compiler. It might be a *warning.* – Robert Harvey May 27 '16 at 21:01
  • @RobertHarvey Look at "examples" here https://www.owasp.org/index.php/Top_10_2013-A1-Injection and here https://www.owasp.org/index.php/Top_10_2013-A3-Cross-Site_Scripting_(XSS) In Java, I can see, right when I type the evil thing into my IDE that it's highlighted as wrong. It makes it really easy to avoid mistakes. If I ignore that, it doesn't compile, the build breaks, and that's really hard to ignore. – GlenPeterson May 27 '16 at 21:04
  • That's very interesting. I had no idea that IDE's of any ilk did this. C# certainly has no such capabilities (that I know of), and [Resharper](https://www.jetbrains.com/resharper/) has [consistently](https://resharper-support.jetbrains.com/hc/en-us/community/posts/205992149-RS-support-for-SQL-Injection-Analysis) [demurred](https://resharper-support.jetbrains.com/hc/en-us/community/posts/205990739-Is-Resharper-support-security-analysis-and-vulnerabilities-) when asked if they would add such capabilities. – Robert Harvey May 27 '16 at 21:07
  • SQL injection should be a non-issue. Don't use languages that don't support prepared statements with parameters. – kevin cline May 27 '16 at 21:17
  • 1
    @RobertHarvey I think you may be imagining `Tainted` to be something more complicated than it is. `class Tainted { string _value; }` will do the trick; as long as the methods which get user input return a `Tainted` (and the only way to get a `string` out of a `Tainted` is to sanitise it) then you'll get instant feedback from the type checker if you write code that's vulnerable to SQL injection. It's simply a technique to use the type system for bookkeeping, it doesn't need special IDE support. – Benjamin Hodgson May 27 '16 at 21:53
  • @RobertHarvey: See the [Ur programming language](http://impredicative.com/ur/) and Ur/Web framework for some examples of what can be done by encoding certain safety assumptions in the type system. In Ur/Web, the type system guarantees that you cannot have SQL injection, for example, and you cannot have dead links (within the app). Galois is a company that has something like a CMS for government agencies. They encode the secrecy rules for classified documents within the Haskell type system, so that it is impossible to compile a plugin that violates those rules. The template library in the … – Jörg W Mittag Jun 20 '16 at 15:27
  • … Ocsigen web framework for OCaml makes it impossible to generate invalid HTML (trying to write a template that ends up generating invalid HTML is a compile time static type error). There's all sorts of stuff a powerful type system can encode, in fact, if the type system is powerful enough, it can encode *any* logical statement (unfortunately, if the type system is powerful enough, type checking becomes equivalent to solving the Halting Problem :-D ). But in this case, the Tiny Type Pattern may already be enough without powerful dependent-type trickery. – Jörg W Mittag Jun 20 '16 at 15:30
  • @JörgWMittag: Thanks. Always nice to check out interesting programming language research. – Robert Harvey Jun 20 '16 at 15:33

0 Answers0