Live data from Hacker News

OpenBSD – pinning all system calls

marc.info

111–118 of 118 posts

Re: OpenBSD – pinning all system calls

#111

Earlier quoted context omitted.

Yeah and imagine advertising yourself as the "most secure OS in the world" at the same time

Yep, they implement kernel level security, rather than obsessing over language.

Kernel level security doesn’t help if you have a heap overflow in the kernel itself.

Re: OpenBSD – pinning all system calls

#112

Earlier quoted context omitted.

Even for go it should actually work as-is: the syscalls should exist statically in the binary, so the loader can enumerate and whitelist them. What gets blocked is the system constructing the entire thing at runtime, or at least setting the syscall number dynamically.

Isn’t that how all syscalls work? The syscall number typically goes in a register.

The syscall goes in a register but it does not have to appear literally right next to the `syscall` instruction in the binary. As TFA explains in the introduction, a syscall stub generally looks like

    mov eax,0x5
    syscall
However it doesn’t have to, `syscall` will work as long as `eax` is set no matter where it’s set, or where it’s set from. You could load it from an array or a computation for all `syscall` cares.

So as an attacker if you can get eax to a value you control (and probably a few other registries) then jump to the `syscall` instruction directly you have arbitrary syscall capabilities.

The point of this change is that the loader now records exact syscall stubs as “address X performs syscall S”, then on context switch the kernel validates if the syscall being performed matches what was recorded by the loader, and if not it aborts (I assume I didn’t actually check).

This means as long as your go binary uses a normal syscall stub it’ll be recognised by the loader and whitelisted, but if say a JIT constructs syscalls dynamically (instead of bouncing through libc or whatever) that will be rejected because the loader won’t have that (address, number) recorded.

Re: OpenBSD – pinning all system calls

#113
post #78

Earlier quoted context omitted.

>they have also mitigated attacks which weren’t even known to exist Indeed, I'm reminded of some other comments that tptacek made in a recent thread, about how encrypting vulnerability disclosures "just isn't done": https://news.ycombinator.com/item?id=38563897 https://news.ycombinator.com/item?id=38569179 I'll bet the NSA is very happy about this situation and is doing everything they can to keep the gravy train rol…

NSA doesn't care about your emailed vulnerability report. They're not spending their own money when they buy zero-day bug chains in platforms people actually use, and even if they were, those bug chains are so ludicrously cheap relative to their utility that any sigint (or law enforcement, for that matter) organization in the world, from Canada to El Salvador, can cheerfully afford them. Even if your emailed report w…

Thanks for the reply!

>As always it is helpful to remember as well that NSA's mission is to secure budget for NSA, full stop.

Sure, let's focus on an intelligence agency with budget constraints, Russia's GRU perhaps.

You claim that bug chains are "ludicrously cheap". Is cheap the same thing as abundant? If you had to guess, how many distinct zero-click exploit chains do does the GRU have for e.g. an iPhone in lockdown mode? Order of magnitude: do they have 1? 10? 100? 1000?

Zerodium pays up to 2M for "Full Chain with Persistence" for iOS: https://www.zerodium.com/program.html I don't think a low price relative to utility lets us conclude that such exploits are abundant. There's asymmetrical information in this market: buyers don't know the quality/novelty of what sellers have discovered, and sellers don't know how badly buyers need what they have to sell. It seems plausible to me that a savvy seller could negotiate a significantly higher price, similar to how tech workers are often able to negotiate significantly higher compensation -- especially if they were somehow able to prove that they weren't just replicating an exploit the broker already had in their inventory. I also suspect there is significant buying power on the buyer side which keeps acquisition prices low (hard to play buyers against each other, given low number of buyers who coordinate with each other).

In any case, I think this is the wrong question in a certain sense. The right question is about the relative cost of buying exploits vs developing in-house. I don't see why picking up the bug from email is hard or expensive. If the GRU is already running a program like XKEYSCORE, which seems likely, it could just be a matter of adding a few filtering rules for emails that go to select security@ email addresses. Have a GRU engineer monitor those emails, and see if any proof-of-concept work in the email can be quickly integrated into existing malware, in order to attack a target considered too low-value for the GRU's crown jewel exploits.

The real question is about the salary of that GRU engineer vs the cost of purchasing exploits. If the GRU engineer gets paid $100K, and a fresh exploit costs $500K, employing the GRU engineer to harvest a few temporary, expendable exploits a year looks quite favorable. I don't think the price/utility ratio of exploits from brokers affects the decision, since that price/utility ratio argument also works for exploits harvested+developed in-house.

Neither of us really knows what's going on in intelligence agencies, but my story seems about as plausible as yours. Given that simply using a Google Form for bug disclosures would be an easy and dramatic improvement on the status quo, I'm left with the sense that there is a lot of dysfunctional cargo-culting going on in the security world.

Looking forward to your response!

Re: OpenBSD – pinning all system calls

#114

Earlier quoted context omitted.

> If your mitigation doesn't stop any CVE that's being exploited right now in the wild, it's an academic exercise and not particularly useful IMO. If your only metric of security is "fixed CVEs", then you're rewarding mistakes that were rectified later, and punishing proactive approach to security that actually makes fewer CVEs appear in the first place. And Theo's reputation and influence on the security is evidence…

You're mischaracterizing their logic. They're saying it's a necessary but not sufficient metric. You can't then shoot it down for being not-sufficient; we all agree about that. It's not my recollection that Theo created OpenSSH, for what it's worth. My memory of this is that it was mostly Niels and Markus who did the lifting. You might do some digging on Theo's reputation among exploit developers. It's complicated.

> They're saying it's a necessary but not sufficient metric.

Okay, then I'm saying it shouldn't be necessary either, for the sole reason that preventing a future CVE is not measurable, while fixing a CVE is. If you so much as pay attention to fixing existing real-world CVEs, you're implicitly focusing on that measurement, as you cannot predict the future. I argue that we would be better off not paying attention to them at all.

If anything, we should take the wide array of CVEs that were discovered in other systems and not applicable to OpenBSD as evidence that their intuition and proactive approach works well. The only real metric of a security of a system is the absolute number of CVEs in a long period of time, in which OpenBSD shines.

Re: OpenBSD – pinning all system calls

#115

Earlier quoted context omitted.

Consider this: struct pinsyscall entries[] = { { .sysno = 1, .offset = 0x1234 }, { .sysno = 2, .offset = 0x5678 }, { .sysno = 1, .offset = 0x9abc } }; Now `nsyscalls` will be 3 and `pin` will be an array of 3 ints, initialised to `{ 0, 0, 0 }`. When we loop through, we'll set: 1. `pin[syscalls[0].sysno] = 0x1234` => `pin[1] = 0x1234` 2. `pin[syscalls[1].sysno] = 0x5678` => `pin[2] = 0x5678` Now when we come to 3, we'…

Oh, thanks, now I understand why there is an if in the for loop! But I still can't see how pin[] could be accessed out of bounds, since the array is allocated to be large enough to hold the largest value of .sysno occurring in the entries[] array.

Right, so this is the crux of the vulnerability. Firstly, note that the `MAX` macro is defined as:

    #define MAX(a, b) ((a) > (b) ? (a) : (b))
This is important because it doesn't cast either arg to any particular type. You can use it with `float`s, or `int`s, or `u_int`s... or a combination.

Referring back to the implementation, the first use of `MAX` (inside the `for` loop) is this:

    ...
    for (i = 0; i 
`npins` is an `int`, but `sysno` is a `u_int`. C integer promotion rules means that we'll actually be implicitly casting `npins` to a `u_int` here; it's as if we did this:

    ...
     npins = MAX((u_int)npins, syscalls[i].sysno);
    ...
This means that `npins` can end up as any value we like -- even up to `0xffffffff`. But remember that `npins` is _actually_ a signed int, so once it comes out of `MAX`, it'll be signed again. Thus we can use this to make `npins` negative.

Once we're out of the loop, `MAX` is used again here:

    ...
    npins = MAX(npins, SYS_kbind);
    ...
Where `SYS_kbind` is just:

    ...
    #define SYS_kbind       86
    ...
Integer literals in C are signed, so now this use of `MAX` is actually dealing with two signed integers. If we used the loop to make `npins` negative (as described just before) then this line will now take 86 as the maximum of the two values.

With `npins = 86`, an array of 86+1 will be allocated, but the `syscalls[i].sysno` in the next loop could of course easily be greater than 86 -- thus leading to out-of-bounds array access.

Re: OpenBSD – pinning all system calls

#116

Earlier quoted context omitted.

Oh, thanks, now I understand why there is an if in the for loop! But I still can't see how pin[] could be accessed out of bounds, since the array is allocated to be large enough to hold the largest value of .sysno occurring in the entries[] array.

Right, so this is the crux of the vulnerability. Firstly, note that the `MAX` macro is defined as: #define MAX(a, b) ((a) > (b) ? (a) : (b)) This is important because it doesn't cast either arg to any particular type. You can use it with `float`s, or `int`s, or `u_int`s... or a combination. Referring back to the implementation, the first use of `MAX` (inside the `for` loop) is this: ... for (i = 0; i `npins` is an `i…

Thanks! Very clear explanation!

So then it depends on if whatever code loaded the elf section does any validation of the data it reads. I can't help but thinking the whole code could use some structs and/or "getter setters" to talk dirty objective oriented speak. It needn't be that though, it could be as low level as some macros which helps doing the right thing with signedness and such. But my main impression is that a lot of the data structure semantics is kept in the heads of programmers instead of being formalised in the code.

In C there is always the opportunity to run with scissors in the middle of the road, but you can do a lot to protect yourself too, without loosing much, if any, performance.

Re: OpenBSD – pinning all system calls

#117
post #72

Earlier quoted context omitted.

Then report the bug like an adult instead of acting like you found some huge published vulnerability in code that was posted for peer review . Thats why the code is there, so others can identify issues; congrats, you did. People make mistakes in every project. So grow up

Would a code analyzer have detected this bug? (E.g. Valgrind, Flexelint, cppcheck, clang static analyzer, etc.) If yes, then why aren't code analyzers used on all OpenBSD code submissions, given their stance on having correct code & security focused.

No, probably not. It requires a crafted binary to be executed.

Re: OpenBSD – pinning all system calls

#118
post #81

Earlier quoted context omitted.

> Proper mitigations I think stem from proper design and threat modeling. Strong, reality-based statements like "this kills these vulnerabilities," or "this kills this CVE; it delays production of an exploit by one week." And also thorough testing by seasoned exploit writers. Anything else is relying on pure luck, superstition, and wishful thinking. The comment seems to imply that "proper design and threat modeling"…

>I'm sure OpenBSD developers have very good intuition on what could be used in a vulnerability, without having to write one themselves Why? On average programmers are not very good security engineers. And the opposite - security engineers are often not a good programmers. If your mitigation doesn't stop any CVE that's being exploited right now in the wild, it's an academic exercise and not particularly useful IMO. >A…

I wouldn't call OpenBSD programmers average.
Post reply on HN