Stream: wg-secure-code

Topic: encoding crate versions in binaries


Shnatsel (Jan 06 2019 at 02:03, on Zulip):

I'm making another thread for the "encode versions of dependency crates in binaries so they can be audited" idea. So I've tried this:

#[used]
#[no_mangle]
pub static ASAN_DEFAULT_OPTIONS: &'static [u8] = b"SORTA_UNIQUE_PREFIX;key=val\0";

fn main() {
    println!("Hello, world!");
}

And this doesn't preserve the string in the compiled binary, even in debug mode. It works if I print the string. So this gets dropped as unused at some point despite the #[used] annotation, which in itself only guarantees the item will persist until linking.
This seems to detail additional steps required to make this work: https://github.com/rust-lang/rust/issues/47384 - but I have no clue what linker scripts are or how do I mess with them, so I'm probably insufficiently competent to dig deeper into this.

Shnatsel (Jan 06 2019 at 02:09, on Zulip):

It is entirely possible that I'm doing this wrong and that there is a much simpler way to put some stuff somewhere in the binary, like a data section.

Alex Gaynor (Jan 06 2019 at 02:12, on Zulip):

If you really wanted to optimize, I think you'd want it in a custom ELF section that the linker wouldn't even map into memory.

Shnatsel (Jan 06 2019 at 02:12, on Zulip):

For now I'm trying to make the compiler preserve my string in the binary, nothing more

Shnatsel (Jan 06 2019 at 02:13, on Zulip):

such optimizations are likely not going to be portable so I'm not tackling them just yet

Shnatsel (Jan 06 2019 at 02:15, on Zulip):

But yeah, good idea. Also it's 3AM here and I feel like my speech is getting less and less coherent, so I'm logging off for today.

Tony Arcieri (Jan 06 2019 at 17:44, on Zulip):

haha goodnight @Shnatsel

Tony Arcieri (Jan 06 2019 at 17:44, on Zulip):

question for when you wake up: are you also encoding the rustc version? or is there an existing way to get that?

Tony Arcieri (Jan 06 2019 at 17:44, on Zulip):

I want both of these things :smiley:

Shnatsel (Jan 06 2019 at 17:45, on Zulip):

Yeah we should absolutely encode rustc version as well

Tony Arcieri (Jan 06 2019 at 17:45, on Zulip):

not sure what your use case is but I'd like for an endpoint agent to be able to extract information about currently deployed artifacts

Shnatsel (Jan 06 2019 at 17:47, on Zulip):

The only way to detect stdlib bugs is to encode stdlib version, which currently matches rustc version. So we definitely need to encode rustc version. In build.rs we can just call rustc --version, we don't even need any fancy way to detect it

Shnatsel (Jan 06 2019 at 17:47, on Zulip):

And I have no idea what you mean by "endpoint agent"

Shnatsel (Jan 06 2019 at 17:52, on Zulip):

> strings target/release/testie | grep 1.31.1 clang LLVM (rustc version 1.31.1 (b6c32da9b 2018-12-18))
so that's already encoded

Shnatsel (Jan 06 2019 at 17:54, on Zulip):

it even survives LTO

Tony Arcieri (Jan 06 2019 at 17:56, on Zulip):

@Shnatsel an agent that runs on production hosts and monitors deployed artifacts

Shnatsel (Jan 12 2019 at 17:24, on Zulip):

I have a reasonably ergonomic prototype that encodes contents of Cargo.lock in the binary. It requires you to add the lib as a dependency and call a no-op function from a location reachable in the code; putting it in main() is recommended. Sadly it requires nightly because of test::black_box(). I also have a tool recovering that info.
...aaand now we will wait for like a week until I get an approval to release this from Google.

Shnatsel (Jan 16 2019 at 20:03, on Zulip):

I've applied for open-sourcing of my prototype, so now we wait. Two weeks or so, since I'm also asking for copyright assignment to myself so that contributors would not be required to sign a CLA. I'll probably hack on it a bit more in the meanwhile.

Shnatsel (Feb 09 2019 at 19:21, on Zulip):

3 weeks later I am cleared to release my 60-LoC prototype, so you will be seeing it go up in the next few days.

Shnatsel (Mar 02 2019 at 20:19, on Zulip):

At long last I have released my proof-of-concept implementation of embedding Cargo.lockinto compiled binaries and recovering it: https://www.reddit.com/r/rust/comments/awlqfi/

DevQps (Mar 13 2019 at 19:37, on Zulip):

It's been over a week but I will take a look at it!

DevQps (Mar 13 2019 at 20:01, on Zulip):

I read the all the Reddit posts and it seems like a cool job you did!

I think the project is mainly targeting organizations (or people) that are actually running the binaries in production and want to know whether their binary contains any (potential) vulnerabilities or not right?

When scanning for vulnerabilities on published crates we can just look at the Cargo.toml file that contains the dependencies right?

I think it would be great if we can somehow include this into Cargo. The question is how we can do it in a stable way that is maybe independent of the specific platform it is compiled for. Another question is whether it would be a good thing to add the dependencies by default, or let people enable the flag themselves? At one point you can say: The amount of bytes included is very small, on the other hand: Organizations that want to monitor their binaries probably will do that as a clear choice. If they actually never monitored their binaries for vulnerabilities and suddenly want to do so, they can always recompile and redeploy their application with these flags enabled.

Shnatsel (Mar 13 2019 at 20:08, on Zulip):

I think the project is mainly targeting organizations (or people) that are actually running the binaries in production and want to know whether their binary contains any (potential) vulnerabilities or not right?

Yep.
I actually want to enable this unconditionally, except for embedded platforms and WASM, and maybe allow strip to remove it. I think "secure by default" is worth a couple of kb in binary size.
As for portability, goblin can parse ELF, PE and Mach-O, so we'll have a native Rust tool for recovering this info easily. It might be worth including some start/stop markers just in case to make recovering this info dead simple from any language.

DevQps (Mar 13 2019 at 23:02, on Zulip):

That sounds good in my opinion! Especially if it's only in the executable / object file and not present during run-time (the program does not use those after all). We should probably create an issue at Cargo for this? Or is it already present?

Shnatsel (Mar 13 2019 at 23:48, on Zulip):

Yeah I need to write an RFC

Tony Arcieri (Mar 14 2019 at 15:55, on Zulip):

@Shnatsel I have been meaning to implement your STDIN request for processing Cargo.lock files with cargo audit. I totally want to use this :wink:

Tony Arcieri (Mar 14 2019 at 15:55, on Zulip):

especially with the binaries we are shipping to now-production

Last update: Nov 11 2019 at 21:55UTC