Building Interactive SSH Applications
drewdevault.com
drewdevault.com
Show HN: ssh chat.shazow.net https://news.ycombinator.com/item?id=8743374
Sshtalk: An SSH-based chat made in assembler https://news.ycombinator.com/item?id=15829206
The reason I'm familiar with the client was to automate connections to network hardware. Basically, we have a rotated or per-user password stored somewhere secure; the ssh client contacts that server, gets the credentials, and then creates a connection to the actual device. The ssh client believes that passwords are insecure and should never be used, so doesn't let you programatically pipe one in. My solution? Just rewrite the ssh client to do what I want. golang.org/x/crypto/ssh made it simple, and users don't even know that they're using a fake SSH client, as I copied the text from the real SSH client verbatim (for accepting host keys and whatnot). As for ssh servers; I had to write one to test the client.
The only thing to beware of is that you need to manage the user's tty; if you haven't used a tty in raw mode before it will be a new experience. And the library has a bunch of places where waits are unbounded. So you need to do anything that blocks in its own goroutine that kills the connection when <-ctx.Done returns. Or accept indefinite blocking, as most programs seem to be happy with. Other than that, I like it a lot. Seems safer to me to just write the program you want, rather than to deal with 9000 historical edge cases in the opensshd+unix combination. PAM is also not involved ever, which is a great improvement to everyone's life.
I swear I read about this in a blog post, but that was many years ago and I couldn't quickly find it.
[0] https://wiki.prgmr.com/mediawiki/index.php/Management_Consol...
You can pretty much see the entire interface from the link above.
> logs = os.path.join(cfg("builds.sr.ht::worker", "buildlogs"), str(job_id))
Depending on where your job_id comes from, you may want to ensure "logs" variable still ends up pointing a subdirectory of buildlogs. You could use a combination of os.path.abspath() and various methods for checking the common prefix.
Maybe this is only a simplified snippet, but concatenating values with external parameters without checking ng the end result can lead to unpleasant surprises in production code.
If you thought websites were centralized, try a system where every keystroke gets mirrored to the server!
I would really like to see a Usenet / NNTP revival.
What if I try to login as "bob'; rm -rf /" or some such? Is the system robust against that?
But otherwise, yes, you can run any valid command or pipeline on the server side so rm -rf is certainly acceptable.
AuthorizedKeysCommandUser root
I'm pretty sure that is enough permissions to cause trouble.I was just talking about standard ssh behavior.
I wouldn’t use that without seriously studying it end to end. As another comment said, “seems kind of hacky”.
keys = (f"command=\"buildsrht-shell '{b64key}'\",restrict,pty " +
f"{key_type} {b64key} somebody\n")
Now it depends on how b64key is sanitized.Looking at the escaping function, it will allow $(execute whatever you want), because it doesn't handle $.
https://github.com/openssh/openssh-portable/blob/master/misc...
Anyway, this depends on being able to specify any username, which while possible, requires you to pass the check that user exists in the system, which will be harder.
But it may still be possible if some weird PAM module is used.
https://github.com/openssh/openssh-portable/blob/master/misc...
Because then you'll end up with '$(some)' instead of "$(some)"
https://github.com/openssh/openssh-portable/blob/b52c0c2e649...
There the "command" variable is the result of the function you mention, but here the use is only for logging. The actual argv for the subprocess is the "av" argument which comes from first splitting and then replacing "%u" etc.
I used this to disable c-X c-c (the exit command) when running gnu emacs as my login shell in the mid 1980s.
The web application security practices are pretty well known and lot of that does apply here too. But lot is different too, crucially I imagine each user session is it's own process which means you can apply more OS level primitives to them. chroot would be an obvious example, but there is tons of more things available.
Of course e.g. FreeBSD is a different bag.
Try to avoid the use of ‘IN’ or ‘NOT IN’. By
doing this you are performing a full table scan
as the query engine looks through every row to
check if the condition is met.
Is that really true for PostgreSQL? Take this query for example: SELECT * FROM t WHERE id IN (1,2,3)
I do this often in MySql DBs. I am pretty sure it uses an index on "id" if one exists. EXPLAIN confirms this. Why would a DB engine not use an index?EDIT: know what you do before judge and adopt technology, code reviews require previous background.