Thinking Outside the Box
Openbox supports a --replace command-line option,
which will replace the currently running window manager instance.
If we run openbox --replace our custom terminal,
the current X windows session is stopped and restarted.
This kills all currently-running graphical programs
including our VNC connection.
However, the kiosk system itself is not restarted,
which means we won’t lose changes made since the last reboot.
This is very interesting.
We seem to have reloaded openbox, which was started by root,
even though we requested the restart as the guest user.
This certainly warrants further investigation.
We know that as the guest user,
we should have control over the files in our home folder.
Our current kiosk interface is the Firefox browser
which stores the user’s profile folder in the users home folder.
When we edit files in this folder and force an openbox restart,
openbox recreates the Firefox bookmark configuration file each time it restarts.
We can demonstrate this with a simple test.
This file contains the default bookmarks including the kiosk’s main page address.
If we delete the bookmarks file,
and we again run openbox --replace,
the bookmark file is recreated.
This tells us that the kiosk software is rebuilding the bookmarks file
every time the X session restarts.
According to the permissions on the file, it is owned by the guest user.
However, it stands to reason that
the kiosk operates at a higher privilege level,
so a second simple test may be in order.
Since the kiosk is configured to write the bookmarks file in the profile folder,
let’s replace that folder with a symlink
in an attempt to force the kiosk to write the bookmarks file
to a different location.
If the underlying kiosk refresh script raises privileges,
we may be able to redirect it to write in a privileged directory.
Before we test this, let’s backup our profile folder
Next, we’ll create a symlink to /usr/bin,
a folder the guest user can not normally write to…
…and verify the symlink was created.
Now that the symlink is created,
let’s run openbox --replace to attempt to regenerate bookmarks.html.
Once reconnected to the kiosk,
we find that the bookmarks file has been written to /usr/bin,
indicating that the process creating it is in fact privileged.
We can write files to privileged directories!
However, in order to escalate our privileges,
we need to make the file executable
and we must write executable commands to the file.
We own the file, so let’s try to make it executable with chmod.
If we check the file permissions, we find that they have changed.
This is promising.
We can modify the file after creation.
However, despite the fact that the we own the file, we are not able to rename it.
This is dictated by the permissions of the containing folder.
Now, we need to add executable instructions to the file.
Our previous method of text editing, ScratchPad,
won’t allow us to save changes to the file
due to the permissions on the parent folder.
Ordinarily, we could use a command-line editor,
but since our makeshift gtkdialog terminal
is noninteractive, this won’t work.
We could also consider using a graphical editor,
but there are no graphical editors installed on the system.
We might also consider building the file one line at a time
with echo commands and standard bash redirects.
However, our gtkdialog terminal uses a bash redirect when processing our command.
If our terminal command contains another redirect,
it would be canceled out by the redirect to /tmp/termout.txt.
To get around this,
we’ll use Scratchpad to create a new script in our home directory,
and save it as testscript.sh
This simple script will overwrite the contents of our bookmarks file.
We’ll make our script executable,
and then execute it.
The bookmarks file has been overwritten by a simple script
that will launch our gtkdialog terminal.
Our goal is to get the system to run this as root, giving us a root shell.
With the script in place, we need to get the system to run it as a privileged user.
Normally, we could leverage several privilege escalation techniques.
For example, the scripts in the protected /etc/profile.d/ folder,
all of which must have an .sh extension, are run at user login.
If we wrote our bookmark file to that directory,
and added a .sh extension,
our terminal would run as root when that user logged in.
Unfortunately, we cannot rename the file.
We’ll face this restriction on all other privileged directories on the system.
This means we’re stuck with the bookmarks.html filename.
There is another potential option.
The /etc/cron.d directory is a part of the Cron job scheduler.
Any scripts placed in this folder would be run as root.
However, as with /etc/profile.d, there is a catch.
Files placed in the cron.d folder
must be owned by the root user or they will not run.
Since we cannot change the ownership of the file,
we cannot leverage this attack vector either.
However, certain cron directories including cron.hourly,
cron.daily, cron.weekly, and cron.monthly
do not have such stringent requirements and will accept non-root-owned files.
Given the obvious timing benefits, cron.hourly is our best option.
Let’s focus on this attack vector.