💾 Archived View for thrig.me › blog › 2023 › 04 › 02 › wacky-unix-paths.gmi captured on 2023-12-28 at 16:05:53. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-11-14)

-=-=-=-=-=-=-

Wacky Unix Paths

/bin//sh

/bin//sh is a legal path.

    $ which /bin//sh
    /bin//sh
    $ /bin//sh -c 'echo hi'
    hi

/bin//sh is typically used for not so legal purposes. /bin//sh unlike the normal form /bin/sh fits neatly into a 64-bit box, and one may not want any NUL characters in that box...because reasons.

  /        b        i        n        /        /        s        h
  00101111 01100010 01101001 01101110 00101111 00101111 01110011 01101000

  /        b        i        n        /        s        h        \0
  00101111 01100010 01101001 01101110 00101111 01110011 01101000 00000000

So if you see /bin//sh it may not necessarily be a typo. It may also be up to no good. "shellcode" might be something to read up on.

trailing slash

This is an extremely important distinction for rsync, in that rsync does different things depending on whether a trailing / is present.

A trailing slash on the source changes this behavior to avoid creating an additional directory level at the destination. You can think of a trailing / on a source as meaning "copy the contents of this directory" as opposed to "copy the directory by name", but in both cases the attributes of the containing directory are transferred to the containing directory on the destination.
-- rsync version 3.2.5 protocol version 31

A good way to learn this difference is to practice with some small test directories to see what goes where. This is probably better than learning on a production system with production data. Also, always be sure to check your chdir(2) calls for errors. That is,

    cd -- "$somehwere" ;  something-that-assumes-somewhere

is very bad, and must be changed to

    cd -- "$somehwere" && something-that-assumes-somewhere

I learned that one in production. The cleanup was not pretty, and took some time. rsync was involved.

    $ pwd; (cd /etc && pwd); pwd
    /tmp
    /etc
    /tmp

Likewise for path merging a trailing slash or not yields a different result:

    $ perl -MURI -E 'say URI->new_abs(qw[  passwd file:///etc/ ])'
    file:///etc/passwd
    $ perl -MURI -E 'say URI->new_abs(qw[  passwd file:///etc  ])'
    file:///passwd

Your software may need to be aware of this difference.

silly things

Very silly things are supported;

    $ cd ////////////////////////etc////////////////////////
    $ pwd
    /etc

one may want to normalize paths somehow, and probably to match how realpath(3) does it. Or if you can just use it. Be aware that resolving a path and resolving symlinks may be two different things.

    $ cd ../../../../../../../../../../etc
    $ pwd
    /etc
    $ exec zsh
    % p=../../../../../../etc ; print -l $p $p:a
    ../../../../../../etc
    /etc
    % cd /tmp
    % mkdir -p a/b/c
    % ln -s a/b/c
    % p=c ; print -l $p $p:a $p:A
    c
    /tmp/c
    /tmp/a/b/c

Leading ../ are legal, though an attacker may try to get to the passwd file or similar by backtracking out of a tree of unknown depth. chroot(8) or not granting permission to read from most files (to say less of write permissions) are typical steps here.

/tech/openbsd/pledge.gmi

Software depots may make heavy use of symlinks including ../ runs to fit everything together.

A path might be changed underneath you. There are various system calls that operate on a descriptor rather than a path.

tags #unix