5 ms·
Personally, I think there are some very interesting possibilities for using Haskell in the highly-secure web application space. The most trivial example would b
by rcoder 18y ago
Personally, I think there are some very interesting possibilities for using Haskell in the highly-secure web application space. The most trivial example would be simply using the type checker to protect against SQL injection and cross-site scripting attacks by representing user input with a different type than query parameters or HTML output.
I've also thought for a while that Haskell would be a great environment in which to implement a static analysis tool to check the security of existing application code. In particular, I think that the PHP community could really use an information-flow and type-checking tool external to the core runtime which could be used to run a quick "sanity check" over source code. The simplicity of the language (relative to, say, Ruby or Perl) makes it a prime target for parsing and analysis, and the large body of existing code in the wild makes for an interesting set of test cases.
- tptacek 18y agoThere's this meme about type checking defeating SQL Injection that I don't really understand. There are basically three situations I see injection problems recurring in modern web code: * The stupid cases where people are interpolating input strings directly into query strings, so that a query for "O'Neill" will accidentally break your SQL. * The not-so-stupid cases where column sorts and query builders pass limits, sort orders, and groupings directly from user inputs. * The cases where stored procedures resort to dynamic SQL. The first problem is solved not by better type checking, but by switching to parameterized queries, where the query string is parsed prior to argument binding. The second problem is solved by not passing SQL literals in and out of input. The third problem isn't even happening in the application's programming language. Which of these problems is handled well by application type checking? As for XSS attacks, I'm again skeptical. If the problem was as easy as type checking, you'd solve it trivially by output filtering everything from the database, neutralizing HTML metacharacters. It's not that easy: there are lots of times when you really do need to honor HTML in input.
- rcoder 18y agoYou're right that #1 is indeed just a matter of using the right API. (I actually blame the poor state of many database client libraries and tutorial docs for the proliferation of interpolated query params, but the point remains that it's basically a mechanical fix.) For #2, the problem is a bit trickier, but again, it just requires attention on the part of the developer. Given the limited use of stored procedures by most LAMP developers, I think that #3 may be the least critical, even if it is the most difficult to tackle with a simple code analysis tool. As you suggest, none of these issues are particularly hard to avoid via careful programming. The problem is that programmers often aren't careful, and when working in languages which offer "one-size-fits-all" string, array, and file types, they tend to just shove everything into and out of those containers without thinking about type or flow checking. Type checking isn't a panacea, but it can flag issues of either type 1 or 2 early, which gives developers a chance to catch themselves before they commit (or even worse, deploy) a potential security hole. Part of my motivation for this comes from reading a lot of unit tests and specs for webapp code. If you step back and think a bit, it becomes obvious that a lot of the test harness is simply devoted to type checking, and that the verbosity (and easy satisfaction of coverage metrics such tests provide) often mask otherwise glaring gaps in the actual test coverage.
- tptacek 18y agoI guess I'm asking, how does Haskell reduce the amount of effort required to write secure SQL? * It helps in the first case, but then, so do parameterized queries, which developers already have and are familiar with. * It doesn't help --- at least not elegantly --- in the second case. * It can't help in the third case, because that error is happening in the database itself. (By the way, not sure why injections in dynamic SQL in stored procedures would be least critical). I get you loud and clear that "even though it's easy to avoid these problems in PHP, developers don't". You're right. "Use good code" is not a solution for the problem of "bad code". But is Haskell? I like the idea of static analysis in Haskell.
- rcoder 18y agoWhere a static analysis tool can help is in flagging those cases where a developer might have made a bad assumption, and forcing them to reconsider that code point. Basically, it's a way to enforce some basic code review practices without requiring one of your senior developers to be able + willing to read over your junior devs' code. The whole point of programming is to automate those tasks that can be automated, right? So, let's automate the first-pass stage of a basic security audit as much as we can. To your specific points: * Parameterized queries are available in some cases, as you said, but don't work when you have to build some portion of the query (sort order, grouping, etc.) at runtime. Static tools can help flag such dynamic values as being tainted or clean, as well as help insure that resulting queries will be well-formed. * All that's necessary to extend your type checking to the database is to enforce the same level of discipline you do for built-in API functions. Just as static analysis tools need a signature for primitive functions provided by the runtime platform (syscalls for C, primitive library functions for PHP, etc.), your static checker could ensure that queries which used stored procedures checked at least the asserted type signature of those procedures. (SQL is pretty type-savvy, and most stored proc authors should be able to trivially provide type sigs for their code.) The advantage to using Haskell for all of this is twofold: * There are excellent existing parsing and graph algorithm libraries maintained by the Haskell community * Working in a strict, pure functional language makes you think in terms of mathematical theories, rather than stateful effects, which in turn tends to result in better, more deterministic code That being said, I think you could use OCaml, Lisp, or any number of other high-level languages to similar effect. The uniquely math-oriented world view of Haskell (and its implementers and users) does tend to lend itself to just the kind of defensible reasoning that you would want from a security-focused static analysis tool, though.
- bayareaguy 18y agoFor protection against sql injection, I'd recommend taking a look at Meredith Patterson's Libdejector http://sourceforge.net/project/showfiles.php?group_id=145075 http://sourceforge.net/project/showfiles.php?group_id=145075 A partial presentation on it is here: http://www.blackhat.com/presentations/bh-usa-05/bh-us-05-hansen.pdf http://www.blackhat.com/presentations/bh-usa-05/bh-us-05-han... It works by having the user offer an exemplar of a dynamic query and then verifying that the actual query is limited to the syntactic forms seen in the exemplar.
- tptacek 18y agoThis is the kind of thing you deploy when you didn't write the app. You can implement it easily for Rails apps by proxying MySQL network connections and parsing the queries. If you can write a lexer, you can catch 99% of attacks just by counting terminals. It's not the right idea, at all, for development teams. The reason is, parameterized queries solve this problem. If you're parsing queries before you bind parameters, you're not injectable. Audit your code to ensure you're using stored procedures. Audit your inputs to make sure they aren't passing things like "DESC" and "ASC" when they should be passing "down" and "up", which you can't fuck up. Then stop thinking about that problem. Move on to a more important problem, which everyone ignores: locking down your database connection. Why does the (one) database connection in WordPress have rights to insert into "wp_users"? A much better area to spend your time in.
- rcoder 18y agoI agree 100% with the assertion that modern webapps should divide privileges across multiple database connections/security principals. A large portion of SQL injection and session-hijacking issues could be rendered useless overnight if the basic tenet of "minimal privilege" were taken to heart by LAMP coders.
- bayareaguy 18y agoFor MySQL you can use the excellent http://forge.mysql.com/wiki/MySQL_Proxy http://forge.mysql.com/wiki/MySQL_Proxy in just this way. However didn't the Remote Agent bug story posted here recently reveal the weakness in relying on auditing? A bug identified by a formal verifier was accidentally re-introduced later in development after they "stopped thinking about the problem".
- eelco 18y agoThe main problem is that both SQL and HTML are often simply represented by strings. The programmer has to keep track herself to make sure everything is escaped and unescaped at the right moment. The point is that you can use Haskell's type system to get guarantees about and keep track of escaping. It's really light-weight to add new types. Also, dynamic typing would probably mess this up. Still, all this mainly comes down at the shoulders of the library designer. But, looking at some of the available libraries (such as Text.XHtml) this works really well. In the case of Text.XHtml the easy/default case when using a string in HTML is that it's escaped. When you want to 'parse' a string to HTML you'll have to be explicit. That makes it really hard to 'accidentily' forget to escape HTML. The way I look at Haskell's type system is that it's a great tool for easily enabling 'safe' programming. It won't work automatically, but it gives you the opportunity to let the type checker take care of guaranteeing that everything will work as expected ;)
- tptacek 18y agoYeah, I think this is a bit naive. Of the three SQLi cases I mentioned, only the first is due to the app language's handling of string input and query strings, and that case is just as easily handled by parameterized queries. The second case is not due to the fact that the same type is used for input and query strings; when a web app passes DESC or ASC or LIMIT 100 in via POST arguments, that's a design problem type systems don't solve. Likewise, type systems might fix the simplest XSS problems, but the nasty ones occur in code that is explicitly trying to handle input that has been laundered through the database and must include HTML characters.
- rcoder 18y agoI still don't see why "type systems don't solve" the problem of keeping data domains separate. If user input is of a different type than SQL query components, you simply can't allow GET or POST arguments to hit the database un-sanitized. Yes, you can perform the check by hand (i.e., fix the "design problem"), but as we've all seen, programmers don't do that consistently, which leaves us patching the same class of vulnerability time and time again. Type systems also don't have to be the algebraic types of Haskell; SELinux DTE and FlowCaml/Jif information flow analysis both fit loosely under the umbrella of "type checking," and yet allow for very fine-grained and interesting security properties of complex, real-world systems to be asserted and enforced.