Showing posts with label release. Show all posts
Showing posts with label release. Show all posts

Saturday, February 6, 2016

Generic setuid/setgid wrapper for scripts

The setuid or setgid bit on a binary executable allows the binary to run with the effective uid or gid set to the owner of the executable, rather than the user that runs it. It is a rudimentary way for anyone to impersonate as the executable owner, so the owner can provide limited services using the owner's identity, including using files only accessible by the owner.

Historically, system binaries such as /sbin/ping are setuid root since ping requires privileged network access, but capabilities have reduced those needs. Binaries that manipulate privileged files still need to be setuid root, such as /bin/passwd. To setuid non-root user is less common but is still useful to control filesystem access.

Sometimes it is useful to write a shell script and making it setuid or setgid for the sake of controlling filesystem access. Many experts generally warn against setuid shell scripts. Here are the common security issues specific to scripts.
  • Anyone could create a symlink that resembles shell options and obtain an interactive shell with elevated privileges.
  • Anyone could create a symlink to a genuine setuid script, then after the OS executes the interpreter, perform a symlink switcheroo to a malicious script.
  • Command line interpretation can be changed by PATH or IFS.
Some people advocate (warning: bad advice) creating a binary specifically for executing the shell, but it can render other safety guards ineffective. The dynamic loader is more careful with the LD_PRELOAD and LD_LIBRARY_PATH directives with a setuid executable. But in this case, only the wrapper binary is setuid, but the shell run under is not, so it will pull in the whole slew of dynamic loading hooks unless we sanitize the environment.

One technique that an OS overcomes the switcheroo problem is to open the script file and pass /dev/fd/N to the interpreter, which ensures the same file is seen by the OS and the interpreter. This must be explicitly enabled on the OS and is still ignored by Linux. At least on Mac OS X, the interpreter's own setuid bit is also ignored.

When it comes to my own need, it basically boils down to:
  1. Don't bother with setuid/setgid, but use sudo which sanitizes environments. My use case is most similar to the line "ALL ALL = (script-owner) NOPASSWD: /path/to/script" in /etc/sudoers, to be run as "sudo -u script-owner /path/to/script". But sudoers manual begins with a "Quick guide to EBNF" which scares me.
  2. Rewrite my shell script as a full blown C program. I'm not feeling overly excited about that.
  3. Write a setuid/setgid wrapper binary in C, and the rest as shell script.
Needless to say, I took the last approach.

ps. In doing this, I found out about the shortest open source license called "Fair License" which is appropriate for such a short program.

Thursday, June 3, 2010

strxcpy—More Consistent, Safer String Copying and Concatenation

This is now published as a Google Project under the name strxcpy. The full motivation article that was previously found in this blog post has been relocated here.

The C language makes it easy to write programs with buffer overflow problems, but there is still something the library can do to help the programmer make fewer mistakes. For this reason, we propose strxcpy(), a variant of strcpy() and strcat(), which combines both string copying and concatenation.
char *strxcpy(char *dest, const char *dest_end, const char *src, size_t n);

The function takes two parameters to define the buffer, dest and dest_end. It guarantees that it will not overwrite the memory location past dest_end, and the string at dest is always NUL terminated. Furthermore, it does not require dest to be a NUL terminated string. The return value is a character pointer to the NUL terminator of the dest string, so that we can easily append another string to it by calling strxcpy() again.

We also propose the sprintf() variants using the same idiom.
char *vsxprintf(char *dest, const char *dest_end, const char *fmt, va_list ap);
char *sxprintf(char *dest, const char *dest_end, const char *fmt, ...);

See the motivation for buffer overflow problems.

Wednesday, May 12, 2010

Abbreviating output to a line in the terminal

A very long time ago, I quickly whipped together a Perl script that will reduce the standard output from another program to just a line, prefixed with an animation character, and optionally suffixed with ellipses if the line is too long. It is useful if only the most recent output is significant, and that I only want to know if the program is making progress. It can be applied to many commands, e.g.
  • tar zxvf source-1.1.0.tar.gz | abbrev
  • unzip archive.zip | abbrev
  • make | abbrev
  • tail -F /var/log/messages | abbrev
I've long wanted to rewrite that Perl script in C, and now here it is (abbrev.c). The program is licensed under GNU General Public License, version 3.

Compiling is simple if you're using GNU make:
make abbrev
You don't need to supply a Makefile. The implicit rule will work. You can optionally supply CFLAGS=-O3 to the make command, as well as optionally strip the executable after make. To install, just move the executable to somewhere in your PATH. It should compile out of the box on Linux and Mac OS X.

There are some subtle features that one might not notice:
  • Output is throttled to a certain frame rate (default 30 fps).
  • Resizing the terminal window will cause the line length to adjust accordingly.
Hope you enjoy it.

Wednesday, March 3, 2010

SyslogNotify: A syslog relay for desktop notification framework such as Growl

I just created a new project, SyslogNotify, on Google Code:
Syslog, from the days of BSD Unix, has been collecting log messages from processes in real-time for decades. They are saved to the disk by default. This tradition has continued to Mac OS X. Meanwhile, desktop notification framework such as Growl allows application messages to be displayed in a non-intrusive way. Many modern applications such as Disk Utility and Installer lack native Growl support, but they emit syslog entries that are indicative of the progress they are making, which could be useful for display on Growl.

SyslogNotify is a daemon written in Python that understands syslogd UDP protocol defined by RFC 3164, and forwards syslog messages to desktop notification. This allows many applications, kernel, and system services instant presence on the desktop.
I started working on this because sometimes my computer gets scanned by failed SSH login attempts, and they do nothing but to keep my computer busy. I was going to work on an automatic blocker, but decided that it was a bit risky to manipulate /etc/hosts.deny programmatically using a setuid root script. I settled on this project for the time being that allows me to monitor SSH login attempts in progress on Growl, so I can manually block the offender.