lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Mon, Oct 7, 2013 at 11:27 PM, Sean Conner <sean@conman.org> wrote:
It was thus said that the Great Rena once stated:
> On Mon, Oct 7, 2013 at 9:25 PM, Sean Conner <sean@conman.org> wrote:
>
> > It was thus said that the Great Rena once stated:
> > > Does anyone have experience running Lua safely as root? What environment
> > > variables, files, and behaviours to watch out for to avoid creating a
> > > security flaw or potentially breaking something? I recall hearing about
> > Lua
> > > being used in the BSD kernel, so I think it should be possible.
> >
> >   I do.  I've written a few programs in Lua that I run as root, but they
> > have a well defined function, and none of the programs execute arbitrary
> > Lua code (in other words, I know the code being run as root).
> >
> >   But I'm not sure what you are asking in particular.  It's easy to
> > create a Lua jail (I've done that too), but if you are running as root,
> > it's because you want to do something that root can only do, so my
> > question to you is: what are you trying to do?
> >
> In particular I'm interested in reading a lot of system information from
> /proc and making it available to another program in a somewhat saner
> /format for display. Some things in /proc can only be read by root.

  If you are doing something like that, the advice typically given is to do
the absolute minimum as root, then switch credentials to lesser priviledges.
In this case, it's opening a file under /proc.  As root, I would do
something like:

        -- we don't accept filenames directly---we map given keys to
        -- the data file we want.  This way, we can limit the files read
        -- using priviledged credentials.

        files =
        {
          "somekey" = "/proc/some/protected/file",
          "someotherkey" = "/proc/another/protected/file"
        }

        -- check to see if we have at least one argument

        if #arg == 0 then
          io.stderr:write("some usage text\n")
          os.exit(1)
        end

        -- read the key, and translate it to a file to open.

        filetoopen = files[arg[1]]
        if filetoopen == nil then
          io.stderr:write("naughty naughty, can't see that\n")
          os.exit(1)
        end

        -- attempt to open the file

        fp = io.open(filetoopen,"r")
        if fp == nil then
          io.stderr:write("can't open data\n")
          os.exit(1)
        end

        -- we have the file open
        -- now we drop privs

        setgid('nobody')
        setuid('nobody')

        -- now the rest of the code

  This is just an example, but again, you want to do the minimum required of
root, then drop the priviledges (once a file is open as root, you still have
access to the files (or sockets) you've opened).  The less you trust user
input, the better.  If you are going to execute programs and not give an
absolute or relative path (just a program name, like 'ls') then you'll
probably want to use a restricted $PATH, or just hardcode the absolute
filepath.  Be wary if you find $LD_LIBRARY_PATH set (again, if you are
executing programs from your script as root).

  -spc



I hadn't thought about dropping root after opening files, but I'm not sure it'll work for this case. Every time I want to get up to date stats from some of the files in /proc I need to open them again - every time I open them I get a snapshot of the contents. Additionally to collect stats like the top hogs of CPU/memory, the only way I know is to check certain files under /proc/$PID/ for every PID, and some of them are only readable by root or the process they belong to (e.g. /proc/$PID/io which has stats on I/O operations). So a program that monitors this information has to keep root privileges as long as it runs.

--
Sent from my Game Boy.