1. 3

A language is Turing complete if it can be used to solve any computational problem. We often refer to any such language as a ‘programming’ language as they can be used to program any and all aspects of a computer.

HTML and CSS are not programming languages (turing-complete) because they cannot be used to solve a computational problem. For example, you cannot calculate 1+1 in HTML or CSS. This is why HTML and CSS are so safe for web-browsing, because they cannot ‘do’ anything other than convey data/information to you.

Javascript, on the other hand, is turing-complete. Javascript can be used to make any program you want, an operating system, a word processor, or a piece of malware.

It is absurd that anyone would accept and run a turing-complete language (such as Javascript) by default and without first reading or performing an audit of the code. It is the equivilent of using the default operating system that comes on a new laptop without first reading a security audit, sure it may be ‘convenient’ but it is not secure.

This is why I have permanently disabled Javascript. Sure, when the Javascript is FOSS I consider allowing it, but you should never accept it by default.

(This was originally written by neal at https://freepo.st/post/jsc91hl6a0 – I thought it could provoke interesting discussions here at lobsters :)

  1.  

  2. 8

    From a security perspective, turing completeness is not “the problem”. Being able to perform computations is not a security issue by itself, although, in practice, programmable things are often ripe for exploitation due to their (not inherent) complexity and the fact that an attacker can automate things and e.g. fill significant parts of the address space with shell code without having to deliver gigabytes of data over the network.

    Being able to perform arbitrary computations does not imply having access to every resource on a computer.

    1. 3

      But CSS(3) is (unfortunately) Turing-complete?

      Update: Okay, maybe not in any meaningful way Turing-complete, check the comments @ https://freepo.st/post/jsc91hl6a0

      1. 3

        That a language is Turing-complete is overrated in risk due to the otherwise-beneficial LANGSEC crowd. Most of INFOSEC assumes components will be compromised somehow. The solution was isolation, mediation, and monitoring. That solution can work with web browsers as well. The simplest way to defeat the risk Javascript poses to your machine is to use a different machine for untrusted, web browsing. That’s physical isolation. The other end of the spectrum is a secure, browsing architecture. OP2 & IBOS come to mind. The middle end is a virtualization scheme that isolates the browser from the rest of the system. Preferably multiple instances of the browser representing domains with different levels of trust.

        You can also disable Javascript. I’ve been a NoScript user a long time. Yet, even if it’s enabled, the above methods mitigate the risk it poses.

        1. 4

          Sometimes I wonder if disabling features in a browser is sufficient when I have no real way of knowing what disabling said feature is actually doing. At a certain point, differentiating between supposed browser (for want of a better term) modes is debating an abstraction that may or may not resemble reality. We can form airtight arguments, but how can we verify they map to reality? This is a long way of asking: “what if the browser is lying to me?”

          1. 4

            If your browser is a trusted component then your browser is a trusted component with all that implies.

            If your browser is not a trusted component then presumably you have it securely sandboxed in some way in which case it doesn’t matter whether it lies to you, it can’t escape the sandbox.

            1. 2

              Do you see what I mean, though? Implementation is reality, in spite of the spec.

              1. 1

                No, I don’t. Either your browser is trusted or it isn’t, there’s no real third option.

                1. 3

                  Maybe I’m just struggling with the notion of a trusted browser. Cognitive dissonance: No such thing that supports modern features even exists, that I have ever seen or heard of. This is an example of what I mentioned above: an airtight argument that falls short of mapping reality.

                  On Plan 9 I use a very simple browser called mothra. It does almost nothing at all: renders basic HTML and displays inline images. There is no CSS or JavaScript support at all, and in fact it ignores most HTML styling beyond bold and italics. In most cases I’m reasonbly sure remote servers are not causing it to do weird things, but I have crashed it before and I’m sure I will probably manage to crash it again.

                  1. 3

                    Re secure browsers

                    Look up the ones I mentioned. The prototypes often use components like Webkit so they’re more realistic. All need a lot of work before mainstream-worthy but already prove architectural principles. Best examples are OP2 Web Browser and Illinois Browser Operating System.

                    Re disabling functionality

                    I think I get what you mean. It’s a real risk where people have disabled features that reactivated on update. Or the code is still there for malware to call even though regular app doesnt use it. Or you eliminate a behavior that can be reconstructed by chaining what’s still there (eg ROP).

                    Original solution from high-assurance was a combination of requirements-to-design-to-code traceability, modularity, simplified design, and mostly loop-free layering. You got only what you needed in a product easy to verify. For mainstream’s bloat, the technique from Poly2 is best where they straight-up deleted code out of the OS (syscalls) or apps. A friend of mine did this on a WinXP box at file level until his whole system took up under 650MB. That’s with browser, office, and antivirus!

                    So yeah, it has to be deleted or provably unreachable. That means memory safety is probably a prerequisite, too.

                    1. 2

                      It’s already (widely) trusted; whether it’s trustworthy is the relevant question.

                      A well-designed browser might contain untrusted components, properly isolated. But the browser system as a whole is still trusted (unless it isn’t and is instead properly isolated, as in e.g. Qubes). And the UI will always be as trusted as the most trusted part of the system, because an attacker who can subvert the UI can make you give the rest of the system the inputs that would make it do anything the attacker wants that’s within its capabilities. There really is no getting around that - the only solution is to ensure that the UI is well-defined, well-isolated and small enough to be auditable (or to have the browser as a whole be untrusted, which is difficult if we’re talking about e.g. doing online banking - you can secure the OS against the browser, but an attacker who subverts the browser already has the keys to the kingdom in most respects).

                      I wouldn’t trust anything Plan 9 (it’s from the same authors as Go, right?), and certainly I would assume any crashes in a C program are exploitable security vulnerability until proven otherwise.

                      1. 3

                        But this brings us full circle to the question of why we trust any program at all. I’ve managed to crash every OS and browser I’ve ever run. Your final paragraph undermines the distinction between trusted and untrusted, in general.

                        Ken Thompson and Rob Pike did work on Plan 9 (as well as UNIX, obviously). Mothra was written by Tom Duff (of Duff’s Device fame). It’s buggy as hell but remains small enough to read and understand.

                        1. 4

                          But this brings us full circle to the question of why we trust any program at all. I’ve managed to crash every OS and browser I’ve ever run. Your final paragraph undermines the distinction between trusted and untrusted, in general.

                          Trusted components mean components that we do trust, rather than components that we necessarily should trust. We trust a lot more code than we probably should, and I think that strategy will come to haunt us shortly (as attackers get more sophisticated) even though it’s been successful to date. I think trustworthy code will require better tools (I think a language like Noether gets most of the way there) - it’s simply too easy to introduce undefined behaviour even in carefully reviewed C that was known to be security-relevant (e.g. https://bugs.chromium.org/p/nativeclient/issues/detail?id=245 ) - though I guess that’s ultimately a matter of opinion.

                          I think you hit a real insight, that the UI of anything is always going to be as trusted as the rest of that component and it’s not possible to have a secured system with an untrusted frontend. To someone with my views that means not trusting anything with a C/C++ UI and hence probably nothing with a GUI; as I’ve said, one could use Qubes or similar and be reasonably confident that one’s system will not be compromised by websites, but there is no principled way to do online banking (say) safely. On the other hand, so far online banking hasn’t resulted in so many people losing money - and if it does then Keynes' statement about successful bankers applies equally to successful bank customers.

                          But yeah, everything is insecure and we’re all doomed.

                          1. 4

                            lmm 8 hours ago | link |

                            Thanks for the Noether reference. That’s fascinating. Reason is two lines of research I occasionally do. One, for anti-subversion & easier verification, is composing a full platform from a series of languages from ultra-simple, bare metal to complex, application grade. I proposed this in verifiable vs reproducible builds. Another was concept of integrating various languages or DSL’s on a common core that each handled a different type of job. The fascinating thing about this one is it does both things I did in my work to a greater degree with full nesting. Only other that did was CertiKOS & sklogic’s tool to a degree but more on the DSL part.

                            Will have to read up on it more. :)

                            1. 3

                              If you find anything then please let me know - the language design seems right to me, but it looks like there hasn’t been any work for a year or more (or if there has been, it hasn’t made it to GitHub). What I really want is a language like that but with an explicit, verified cost model, along the lines of http://lambda-the-ultimate.org/node/5021 .

              2. 3

                The obvious follow-up: “How would I know?”

                1. 1

                  A good first step is not using proprietary browsers.

                  1. 3

                    Open source is obviously preferable but does not completely solve the problem of complexity in codebase too large to be read (much less understood) by a human being.

            2. 4

              It is the equivilent of using the default operating system that comes on a new laptop without first reading a security audit

              No it’s not. An operating system has the power to destroy every file on your computer if programmed to do so. JavaScript in the browser does not. At worst, it can probably spin the CPU to 100% or track what sites you visited.

              1. 7

                At worst, it can cascade exploits to achieve anything it wants. Arbitrary code running on your computer is arbitrary code running in your computer.

                1. 5

                  Hold on. There is a huge difference between arbitrary code (i.e. arbitrary instructions) and arbitrary computations. The latter can be achieved using very few instructions or with other simple systems such as lambda calculus. Though these can be used to perform any computation imaginable within the resource limits, they may yet be completely incapable of speaking the language used by the rest of the system. We need not even introduce the concept of a sandbox (or other externally imposed mitigations) for this to be true. And so the exploitation they can do is entirely dependent on the nature of the vulnerabilities, just as it is with e.g. parser bugs for non-turing complete formats (which can also cascade exploits – if they happen to be of the kind that cascade).

                  In other words, arbitrary computations are not inherently capable of producing arbitrary code. That power must be granted through a sufficiently severe exploit, if it is not a built-in feature of the language’s implementation.

                  This is one of the reasons why I think focusing on turing completeness as a security issue is somewhat misguided.

                  1. 3

                    At worst, it can cascade exploits to achieve anything it wants. Arbitrary code running on your computer is arbitrary code running in your computer.

                    No it really isn’t. Not when we’re talking about an airtight sandbox. A great many document formats are Turing-complete (e.g. PostScript), but we don’t generally see this as a problem.

                    1. 4

                      You’ve described mitigations but are not really disagreeing with what I said. The mitigations may even be effective, but note that they were necessary in the first place. That underscores my point.

                      1. 2

                        Sandbox was a poor choice of term. The difficulty of securely rendering a format has nothing to do with whether that format is Turing-complete or not (provided you’re willing to accept failure as an answer sometimes). Browsers have had far more vulnerabilities in “running” JPEG/PNG/SVG/etc. than in running JavaScript, and will continue to do so, because the code for those things is more likely to be the kind of bit-twiddling C code that’s always full of vulnerabilities. JPEG is not Turing-complete but that fact is just utterly irrelevant.

                2. 2

                  Turing-incompleteness isn’t worth it with current technology. Remember XSLT? That’s the declarative pure alternative to JavaScript - your server serves XML and a transformation that can be applied to it. And it sucks.

                  I hope for good Turing-incomplete languages - I’m watching Idris with great hope and interest. But we’re not there yet.

                  1. 3

                    Idris is Turing complete by not requiring all the functions to be “total”. From the language creator himself: http://cs.stackexchange.com/questions/19577/what-can-idris-not-do-by-giving-up-turing-completeness/23916#23916

                    1. 2

                      Well, it has an escape hatch, sure. But the non-Turing-complete dialect of Idris is clearly defined and arguably more idiomatic than the Turing-complete one; I would expect it to be trivial to have a compiler flag analogous to Haskell’s -Xsafe if there isn’t one already.