Read time in minutes: 14

hero image aoi-flee

Image generated by Waifu Diffusion — 1girl, fox ears, blue hair, blue eyes, katana, bamboo forest, kimono, long hair, princess, pokemon, fluffy hair, shouting, coffee, chibi, portrait, dialogue, monado, running, fox tail, blue tail

Mara is hmm

<Mara> I wonder how many people’s RSS/JSONFeed
readers we broke with the title…

Aoi is cheer

<Aoi> Come on, it couldn’t have been that many,
things support Unicode now, right?

Numa is delet

<Numa> >implying
things support Unicode properly in the year of our lord two thousand and
twenty-three

Aoi is facepalm

<Aoi> They do support Unicode though…right?
They have to.

Cadey is coffee

<Cadey> We’ll find out.

Security is impossible. We just like to pretend otherwise so that we can
constantly project this aura of impenetrability that will save us from having to
admit the reality that it’s impossible. One of the biggest targets in the modern
information security world is sudo. It is a command that
lets you set user and then do a command. Sudo is one of the most widely
deployed programs on the Internet and is widely regarded as critical
infrastructure.

Aoi is grin

<Aoi> Sooo the creators and maintainers of sudo
take things very seriously by using something like
Rust, maintain a high quality standard of
malicious inputs by fuzzing all public attack surfaces, and try to minimize the
amount of code involved in order to prevent vulnerabilities from being a
problem?

A prior version of this conversation snippet was badly
phrased. You are reading an edited version in case this is relevant in internet
comment arguments.

Cadey is coffee

<Cadey> I don’t know about the code quality
standards of the sudo project, but overall I don’t see them doing any concerted
effort to try to migrate away from C (or to reduce the complexity of sudo) and
there are
frequent
security
vulnerabilities that
result in attackers getting root access anyways. I really wish the industry as a
whole would take languages like Rust a bit more seriously and start actually
moving towards programs being safer to use because security vulnerabilities in
core infrastructure result in emergency patches. It was disappointing to see an
attempt at using Rust in an important Python library torpedoed by users of
obscure architectures not supporting Rust
.
Maybe the solution there is to use WebAssembly as a compile target instead of
making everything be native code. I wouldn’t wish hppa’s reverse stack growth on
anyone trying to write a compiler though.

Aoi is sus

<Aoi> Oh god…

I’m tired of this situation and I bet a lot of the ecosystem is too. There’s
been talk and ideas, but not enough in the action department. I made a new tool.
A better tool. One that will let all of us proceed towards the future we
deserve. I made a sudo replacement named 🥺.

🥺

🥺 has no pronounceable name in English or any other speakable human language.
It is named 🥺, but it is referred to as xn--ts9h (the punycode form of 🥺) in
situations where emoji are not yet supported (such as Debian package names).

To use 🥺, install it (such as from the Debian package) and then run it in place
of sudo:


$ id
uid=1000(xe) gid=1000(xe) groups=1000(xe),102(docker)

$ 🥺 id
uid=0(root) gid=0(root) groups=0(root),102(docker),1000(xe)

Mara is hmm

<Mara> Wait, what? That’s it? How is this even
secure at all? If it doesn’t ask you for your password how can you be sure that
an actual human is making the request and not some malicious
script?

Numa is delet

<Numa> Using this program requires you to be able
to type an emoji. Most attack code is of such poor quality that they are unable
to run commands named with emoji. This makes the program secure.

Aoi is coffee

<Aoi> This is not how any of this
works.

Here it is broken down statement by statement.

First, I pull in a bunch of imports from the standard library and also the
syslog to write a message to syslog
about what’s going on:


use std::{env, os::unix::process::CommandExt, process::Command};
use syslog::{unix, Facility::LOG_AUTH, Formatter3164};

Next, I create a main function that returns an
io::Result, this is an
error that is returned by most of the standard library functions that do I/O
operations with the OS.


fn main() -> io::Result<()> {

The correct usage of this program is to run it like 🥺 id, so if the user
doesn’t specify a program to run, then it should blow up with an error message
instead of panicking:


if env::args().len() == 1 {
    eprintln!("usage: {}  [args]", env::args().nth(0).unwrap());
    return Ok(());
}

Aoi is wut

<Aoi> Wait, what? Why is it returning that
everything is okay if the user is doing it wrong? Shouldn’t it return some kind
of error code that the running program or shell can catch?

Numa is delet

<Numa> It’s a feature.

Aoi is coffee

<Aoi> I really hope I never have to maintain any
of your code.

Next, we grab the program name and arguments from the command line arguments of
🥺 and send a message to syslog that it’s being run so that there is some
accountability after-the-fact:


let program = env::args().nth(1).unwrap();
let args = env::args().skip(2).collect::>();
let mut writer = unix(Formatter3164 {
    facility: LOG_AUTH,
    hostname: None,
    process: "🥺".into(),
    pid: 0,
})
.unwrap();
writer
    .err(format!("running {:?} {:?}", program, args))
    .unwrap();

Aoi is wut

<Aoi> Wait so the emoji works there, but it
probably isn’t going to work in people’s RSS feed readers? How does that make
any sense?

Numa is delet

<Numa> It doesn’t, lololol

Cadey is coffee

<Cadey> UNIX is mostly devoid of the concept of
character sets. Any character is fine as long as it doesn’t have a null
terminator (this ends the string in C). I’d be more amazed if the emoji use
broke something, as there are legitimate uses for putting non-Latin characters
into message buses like that. Also most RSS feed readers have very poor code
quality.

Finally, the actual command is executed:


Err(Command::new(program).args(args).uid(0).gid(0).exec().into())

This works because I’m using the
CommandExt
trait implementation of
Command that adds
some methods we need:

The key part is the exec call at the end. One of the interesting things about
the exec-family of system calls in UNIX is that it replaces the current
process if it succeeds. This means that the function will never return unless
some error happened, so the exec method always returns an error. This will
make error handling happen properly and if things fail the process will exit
with a non-zero error code:


$ cargo run --release ls
    Finished release [optimized] target(s) in 0.06s
     Running `target/release/🥺 ls`
Error: Os { code: 1, kind: PermissionDenied, message: "Operation not permitted" }

Numa is delet

<Numa> Sure, this error message could
be better, but that’s a 2.0 feature. This is a disruptive program poised to
totally reshape the security industry so we have to move fast and break
things
!

I’m fairly sure that this program has no bugs that aren’t either a part of the
syslog crate or the Rust standard library.

Installation

You can install 🥺 by downloading the .deb file from my
fileserver
and
installing it with dpkg -i. This will give you the 🥺 command that you can
use in place of sudo.

Numa is delet

<Numa> This will let you stick it to
the man and let you self-host your own sudo on a $5 a month VPS from a budget
host. You can’t have any vulnerabilities if there are no bugs to begin
with!

Aoi is facepalm

This is also known to work on Amazon Linux 2, so you can create blursed things
like this:


$ ssh -A xe@10.77.131.103
Warning: Permanently added '10.77.131.103' (ED25519) to the list of known hosts.
Last login: Fri Jan 20 04:09:11 2023 from 10.77.131.1

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|___|___|

https://aws.amazon.com/amazon-linux-2/
[xe@inez-rengenne ~]$ 🥺 id
uid=0(root) gid=0(root) groups=0(root),10(wheel),1000(xe)

Mara is hacker

<Mara> Pro tip! You can apparently
pass a URL to a .rpm file to yum install and it will just download and
install that .rpm file. This is incredibly cursed.

The .deb package was built on Ubuntu 18.04 and the .rpm package was built on
Amazon Linux 2, so it should be compatible with enough distributions that you
don’t have to care.

Mara is hacker

<Mara> There’s even a manpage you can read with
man 8 🥺!

Numa is delet


Numa is delet

<Numa> By the way, there are many more lovely
ways to get root than just by asking nicely with setuid. Why doesn’t this
program use those?

Cadey is coffee

<Cadey> We gotta save something for part 2,
otherwise that would spoil all the fun.

Aoi is sus

<Aoi> I don’t know if I like what you mean by “fun”
there…


Aoi is yawn

This article was posted on M01 20 2023. Facts and circumstances may have changed since publication Please contact me before jumping to conclusions if something seems wrong or unclear.

Read More