News for hackers. Stuff that matters.
Re:Redox OS Crash Challenge by surajrmal on Sunday January 21, 2018 @01:12PM (#16199159)
> Rust being advertised as a safe language (which is true) got so much into the user's heads that they think if they write it in Rust it's safe and crash free by default. There are plenty of security/safety bugs that aren't about dereferencing a null or accessing invalid ptr.

> No cynicism intended, just an observation from what I see around.

The difference is what happens when a bug is encountered. If it is caught and panicked upon, then that is safe predictible behavior that cannot be exploited into something like privilege escallation.

Re:Redox OS Crash Challenge by hedora on Sunday January 21, 2018 @02:11PM (#16199443)
I remember when all the same arguments were made about Java, which led people to ignore the possibility of memory leakage and privilege escalation, even though both those things are common problems with idiomatic Java.

For instance:

Swing recommends you register callbacks all over the place, but those cause otherwise dereferenced windows to stay live from the GC’s perspective (this is a general problem with the callback pattern, not swing).

Java serialization surfaces all sorts of private methods to outside processes via the reflection APIs, which is even easier to exploit than arbitrary memory stomping in C.

Practically everything can throw a null pointer exception, and all generics code can throw ClassCastExceptions. Writing all the error handling logic for this is at least as hard as restricting yourself to a memory-safe subset of C++ templates. If you miss an error handling case, an attacker can use that to escalate up to increasingly high level invariant violations in your code.

Basic things like “final” have ill-defined semantics with multithreaded code (final fields can change value, even without reflection).

I don’t know Rust well enough to know which classes of these bugs it has (and I doubt the Rust community really does either—-it took the Java world a decade to notice some issues like the above).

With the exception of the “final” problems, I think fixing any of the things I listed reduces to solving the halting problem, or giving up on using turing complete languages.

This makes me skeptical of many claims coming from Rust proponents at the moment.

Re:Redox OS Crash Challenge by lordnaikon on Sunday January 21, 2018 @02:41PM (#16199573)
> I don’t know Rust well

That is one problem and i don't want to attack you. This is something Rust needs to work on! Rust is indeed a relatively hard language to learn and understand and it is not really clear from the beginning nor in the intermediate level if its worth the effort. I can only speak from an empirical standpoint. Time showed – to me and maybe i am the only one – that i have fewer bugs in general, especially in the late stage of development. Rust tends to feel a little viscid in the beginning but it catches up later where you don't try to find a race condition in a 100k cloc Program. Rust has a good way to reason about your program especially in a multi threaded environment. And this is where Rust is fundamentally different of what we – as programmers – have experienced in the wild. Yes there are many efforts in academia and research languages but non of them are used outside.

Rust does nothing new or has concepts that are not strongly researched in academia. Rust is trying to bring those findings into the wild.

In Rust practically nothing can throw null pointer exceptions or class cast exceptions. Rust don't let you express ill-defined semantics with multi threaded code – you can't have data races.

And this implies – of course – that the set of programs that you can write in safe Rust is smaller than in C/C++/Java/C# ... you can't possibly write programs with data races or dangling pointers / null pointers. Thus making like 60% of all CVE's (i pulled this number out my ____) impossible to write.

Rust can't prevent you from making logical errors but it can help you preventing various categories of bugs we see in the wild exactly now.

Rust has many problems of its own kind, but none of the ones you listed above. immaturity in its ecosystem due to its short lifetime, steep learning curve and many more. But it can deliver very well in certain disciplines today.

Re:Redox OS Crash Challenge by eat_veggies on Sunday January 21, 2018 @04:25PM (#16200130)
Do you recommend any resources to learn rust?
Re:Redox OS Crash Challenge by erickt on Sunday January 21, 2018 @04:42PM (#16200201)
The official rust book [1] is a great place to start. So are the exercism tutorials [2]

[1] https://doc.rust-lang.org/book/

[2] http://exercism.io/languages/rust/about

Re:Redox OS Crash Challenge by swsieber on Sunday January 21, 2018 @07:43PM (#16201021)
Version 1 or 2 of the rust book?
Re:Redox OS Crash Challenge by steveklabnik on Sunday January 21, 2018 @10:52PM (#16201782)
Author here. 2 is much better. And it’s almost done; we’re mostly in editing and bikeshedding the opening paragraph.
Re:Redox OS Crash Challenge by geofft on Sunday January 21, 2018 @03:31PM (#16199824)
Java remains a memory-safe language, though, right? Leaving aside poor deserialization APIs, it's pretty hard to provide malicious input to non-malicious Java source code that takes control over the interpreter.

Most of Java's security reputation, I think, comes from Java applets, which were a very different model that involved letting malicious actors write the Java code. Java continues to see success in both web application software and Android apps, both of which do not use the applet security model, and it seems that Java's security record there is far better than C or C++ would have been in the same roles.

Re:Redox OS Crash Challenge by rkeene2 on Sunday January 21, 2018 @03:56PM (#16199978)
Apache Struts and Equifax might disagree that the handling of exceptions doesn't cause security issues in Java.
Re:Redox OS Crash Challenge by geofft on Sunday January 21, 2018 @04:31PM (#16200154)
If I'm understanding right, the Equifax vulnerability was CVE-2017-5638, where if an invalid Content-Type issue is given, it gets passed to an error-message printing function that searches through the entire provided message for OGNL code (a domain-specific language that apparently can deserialize arbitrary Java objects, or something), and so an attacker can pass OGNL code that spawns an external process in the Content-Type header?

I'd argue that this isn't a language-specific issue at all. It happens to be the case that this is implemented using exception handling in Java, by throwing an object containing the request headers, and having it caught by something that parses the provided message for code. But a language without this type of exception handling, like C or Rust, could have the same issue as easily:

    if (strcmp(request->content_type, "multipart/form-data") != 0) {
        char *error = asprintf("Bad Content-Type header %s", request->content_type);
        log(error);
        free(error);
        return -1;
    }

    void log(char *message) {
        char *ognl = find_valid_ognl(message);
        if (ognl)
            message = evaluate(ognl);
        ...
    }
I doubt that any language can really, fundamentally, save you from wrongly deciding to evaluate untrusted strings. (I do think that the vulnerability here was made more likely by OGNL being able to instantiate arbitrary Java objects and by not distinguishing TrustedString and UntrustedString types, and a good language can gently steer you away from those mistakes, but it won't be able to completely save you.)
Re:Redox OS Crash Challenge by rkeene2 on Monday January 22, 2018 @12:56PM (#16206366)
I agree that it isn't Java-specific, but Java is affected despite being memory safe and "it's pretty hard to provide malicious input to non-malicious Java source code that takes control over the interpreter" may not be as true a statement as it appears.
Re:Redox OS Crash Challenge by geofft on Monday January 22, 2018 @01:37PM (#16206698)
That's a fair objection, and I already had to add a caveat about deserialization libraries that can instantiate arbitrary objects. (Which is a problem that affects other memory-safe dynamically-typed languages too, e.g., Python's pickle and yaml modules have the same problems.)

I think there is a meaningful distinction, still, between something like OGNL where the program / library is providing its own interpreter of the EDSL that is excessively capable (which can be done in any language, including Turing-incomplete languages, capability systems, etc.: a library can always dispatch input to whatever functions are available to it) -- i.e., where the programmer intended the functionality that was implemented, they just didn't think through what they were doing -- and things like buffer overflows and ROP where the course of program execution, on the existing interpreter / runtime / platform, is subverted to something the programmer did not intend. I'm not quite sure how to phrase it. (And I'm not sure on which side of the line arbitrary-object deserialization lands.)

Re:Redox OS Crash Challenge by rkeene2 on Monday January 22, 2018 @02:01PM (#16206924)
I'd phrase it as "Programmers can write vulnerabilities in any language" :-)
Re:Redox OS Crash Challenge by steveklabnik on Sunday January 21, 2018 @02:31PM (#16199516)
Rust is significantly different with regards to this stuff:

* There is no reflection API

* Exceptions don't exist

* There's no subtyping, so ClassCastExceptions can't exist. (There's subtyping with lifetimes, and you can't cast them, so that doesn't count)

* final doens't exist

That said, every language has things that you don't realize; we did have a sort of similar moment to this stuff before 1.0 with the "leakapocalypse." Rust will have its own issues. But it doesn't really inherit the problems you're talking about above.

Re:Redox OS Crash Challenge by quotemstr on Sunday January 21, 2018 @09:07PM (#16201403)
> Exceptions don't exist

They're called panics.

> There's no subtyping, so ClassCastExceptions can't exist.

Any sort of polymorphism opens you up to the possibility that code that's written to take abstract type A, implemented concretely in B and C, implicitly expects a B and blows up when it gets a C. Rust doesn't solve this problem.

> final doens't exist

Sure it does. It's just implied, and not-final has to be spelled out. This is one thing Rust did that I do agree was a good move. The other stuff? I remain unconvinced, especially with respect to structural subtyping.

Re:Redox OS Crash Challenge by inferiorhuman on Sunday January 21, 2018 @11:38PM (#16201965)
> > Exceptions don't exist > > They're called panics.

Nope.

https://doc.rust-lang.org/std/panic/fn.catch_unwind.html

Re:Redox OS Crash Challenge by quotemstr on Monday January 22, 2018 @12:06AM (#16202073)
It's non-local control flow with deterministic unwinding and defined stop points. It's an exception system.

Sure, it's not "recommended", but recommendations don't define semantics.

Re:Redox OS Crash Challenge by geofft on Monday January 22, 2018 @10:55AM (#16205284)
I'd say they do—a Rust user will never encounter a panic from a reasonable library that they're expected to catch.

If hypothetical unreasonable libraries are in scope, they can just open /proc/self/mem for writing (in safe Rust!) and violate memory safety, and that's not an argument that Rust isn't memory safe. So why should hypothetical unreasonable libraries be an argument that Rust has exceptions?

Re:Redox OS Crash Challenge by quotemstr on Monday January 22, 2018 @04:59PM (#16208351)
Because the language doesn't define what happens if you write to memory behind the runtime's back. It _does_ define, in detail, what occurs on panic. It's a legal thing to do. That some consider panicing in bad taste or whatever does not change the fact that panic is a supported feature of the language.
Re:Redox OS Crash Challenge by steveklabnik on Tuesday January 23, 2018 @02:19PM (#16216568)
It also defines that it may abort, and so culturally, people use them for only what’s intended, as otherwise, it limits your audience.
Re:Redox OS Crash Challenge by jimktrains2 on Sunday January 21, 2018 @09:49PM (#16201533)
> Any sort of polymorphism opens you up to the possibility that code that's written to take abstract type A, implemented concretely in B and C, implicitly expects a B and blows up when it gets a C. Rust doesn't solve this problem.

Can you explain this? Do you mean that the type C does not correctly implement A? Do you mean something that expects a specific value from a methid in A that only B will return? Both of those, while possible just seem like a complaint of "X doesn't prevent me from purposely breaking it".

Re:Redox OS Crash Challenge by dbaupp on Sunday January 21, 2018 @10:23PM (#16201646)
One example is something like enum A { B, C }: a function might have a precondition that it requires an A::B, and crashes/misbehaves when given an A::C. In Rust, this can be seen in Option::unwrap (requires a Some, panicking if given a None). Technically this is the same sort of thing as in Java, but, at least to me, it seems different/more easily controlled.
Re:Redox OS Crash Challenge by jimktrains2 on Sunday January 21, 2018 @11:15PM (#16201876)
Unwrap is essentially asking for it to fail under that condition, so that's not exactly broken.

Unwrap should always be suspect. It's easy to turn it into a pattern matcher instead, which explicitly forces you to hand the none case.

I'm not saying you're wrong, but I don't think it's an example of an error created by a polymorphic type. (Instances of the same type can do this as well.)

Re:Redox OS Crash Challenge by dbaupp on Monday January 22, 2018 @07:13AM (#16203795)
One can look at Option<T> as an interface/base class that can be satisfied by a T or by (). Indeed, in Java-style languages, one occasionally sees implementations that have an Option abstract base class, with two subclasses, Some and None. Both enums and subclassing are forms of polymorphism, the main conceptual difference is the polymorphism being closed or open (respectively). The fact that Rust adds extra layers of types/syntax on top of the raw polymorphism is syntactic sugar, just a disguise.

One could actually even express the Option concept as a trait, with manual downcasts:

  trait OptionLike {
      type Contained;
      fn is_some(self) -> bool;
      fn as_some(self) -> Some<Self::Contained>;
  }
  struct Some<T> { value: T }
  impl<T> OptionLike for Some<T> { ... }
  struct None<T> { _phantom: ...<T> }
  impl<T> OptionLike for None<T> { ... }
Under this scheme, Option<T> is expressed as a trait object like Box<OptionLike<Contained=T>>, and the whole thing looks a lot more like the OOP/subclassing approach.

In any case, the fact that unwrap is clearly documented to fail on the None case is orthogonal: it's an invariant about the (sub)types of it's arguments that isn't expressed in the signature.

Re:Redox OS Crash Challenge by steveklabnik on Sunday January 21, 2018 @11:03PM (#16201828)
See above about panics and exceptions; just because they’re similar doesn’t mean they’re the same.

I agree Rust doesn’t solve all bugs.

Re:Redox OS Crash Challenge by SAI_Peregrinus on Sunday January 21, 2018 @01:22PM (#16199211)
Crash bugs caused by a panic can't necessarily be used for privilege escalation, but they can certainly be used for DOS attacks.
Re:Redox OS Crash Challenge by halayli on Sunday January 21, 2018 @01:24PM (#16199220)
My point is that privilege escalation can happen from logical bugs
Re:Redox OS Crash Challenge by zerokernel on Sunday January 21, 2018 @02:04PM (#16199410)
Panics can of course result in exploitable system behaviour.
Re:Redox OS Crash Challenge by conradev on Sunday January 21, 2018 @06:07PM (#16200639)
Panics may be safe and unwind nicely, but they can still, for example, be triggered in an untested code path to DOS a system.

That's one reason that people run AFL against safe Rust.