Commit 1259b9ed authored by akhuziy's avatar akhuziy
Browse files

setuid binary now doesn't use config file due to vulnerabilities

parent 57e184ca
......@@ -32,12 +32,13 @@ Sample configs must not be used in the code.
The aggregator tool requires an access to the database (currently InlfuxDB). DB credentials are stored in a plain text file and accessible by anyone who has right to read configuration files. In order to prevent users from accessing DB credentials and job data that does not belong to them, the toolkit provides a setuid executable to run aggregator. In order to use this feature follow the instructions:
1. Configure aggregator to use setuid binary by setting `SECUSER=True` in `conf/config.py`.
2. Compile setuid binary: `cd setuid-runner; make`. It requires Python3 to be installed in the system.
3. You can move `setuid-runner/setuid-runner` and `setuid-runner/config.ini` anywhere where it is accessible by users
4. Set path to `data.py` in `config.ini`
5. Change the ownership of all files to `safeuser` and remove the access for anyone else: `chown -R safeuser aggregator && chmod -R go-rwx aggregator`
6. Set **setuid** bit of the `setuid-runner` binary and ownership accordingly: `chmod u+s,a+rx setuid-runner && chown safeuser setuid-runner`
7. Now in order to fetch the data call `setuid-runner` as you call `data.py`, for instance: `./setuid-runner -t text JOBID`
2. Compile setuid binary: `cd setuid-runner; make`.
- It requires Python3 to be installed in the system.
- Configure the Makefile and set at least `SPATH` variable and `LDFLAGS` variable if needed.
3. You can move `setuid-runner/setuid-runner` anywhere where it is accessible by users
4. Change the ownership of all files to `safeuser` and remove the access for anyone else: `chown -R safeuser aggregator && chmod -R go-rwx aggregator`
5. Set **setuid** bit of the `setuid-runner` binary and ownership accordingly: `chmod u+s,a+rx setuid-runner && chown safeuser setuid-runner`
6. Now in order to fetch the data call `setuid-runner` as you call `data.py`, for instance: `./setuid-runner -t text JOBID`
## Usage
......
CXX = g++
CXXFLAGS = -Wall -pedantic -std=c++11
# Python include paths. The output of python3-config --includes
PYINC := $(shell python3-config --includes)
# Python libraries and ld flags. The output of python3-config --ldflags
PYLIBS := $(shell python3-config --ldflags)
# You can set this to use rpath for Python libraries for instance
LDFLAGS :=
LDFLAGS :=
# SET THIS VARIABLE TO the location of the data.py, for example
# SPATH := /cm/shared/apps/profit/aggregator/data.py
SPATH :=
TARGETS = setuid-runner
......@@ -16,7 +21,7 @@ OBJ = setuid-runner.o
all: $(TARGETS)
$(OBJ): $(SRC)
$(CXX) $(PYINC) $(CXXFLAGS) -c $(SRC)
$(CXX) $(PYINC) $(CXXFLAGS) -DSPATH="\"$(SPATH)\"" -c $(SRC)
setuid-runner: $(OBJ)
$(CXX) $(LDFLAGS) -o $@ $(OBJ) $(PYLIBS)
......
spath = /path/to/aggregator/data.py
......@@ -11,8 +11,18 @@
#include <libgen.h>
#include <Python.h>
#ifndef SPATH
#error "The binary should be compiled with SPATH variable"
#endif
using namespace std;
// throw an error
static inline void error(string s, int errn){
cout << s << endl;
exit(errn);
}
// trim from start (in place)
static inline void ltrim(string &s) {
s.erase(s.begin(), find_if(s.begin(), s.end(), [](int ch) {
......@@ -34,43 +44,14 @@ static inline string trim(string &s) {
return s;
}
// throw an error
static inline void error(string s, int errn){
cout << s << endl;
exit(errn);
}
int main(int argc, char **argv)
{
char conffile[PATH_MAX], scriptfile[PATH_MAX];
strncpy(conffile, argv[0], sizeof(conffile));
dirname(conffile);
strncat(conffile, "/config.ini", sizeof(conffile));
ifstream cFile (conffile);
if (cFile.is_open())
{
string line, sfile;
while(getline(cFile, line)){
auto delimiterPos = line.find("=");
auto name = line.substr(0, delimiterPos);
if (trim(name) == "spath") {
string val = line.substr(delimiterPos + 1);
val = trim(val);
strncpy(scriptfile, val.c_str(), sizeof(scriptfile));
}
}
string scriptfile = SPATH;
if (strlen(scriptfile) == 0) {
error("Config file should contain a valid spath value", 1);
}
if (trim(scriptfile).length() == 0) {
error(string("SPATH cannot be empty. Recompile the binary"), 1);
}
else {
error("Couldn't open config file for reading. Config location: " + string(conffile), 2);
}
// check the arguments for special characters
for(int i=1; i<argc; i++) {
if (string(argv[i]).find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-_ ") != std::string::npos){
......@@ -78,13 +59,13 @@ int main(int argc, char **argv)
}
}
wchar_t *program = Py_DecodeLocale(scriptfile, NULL);
wchar_t *program = Py_DecodeLocale(scriptfile.c_str(), NULL);
FILE* fp;
Py_SetProgramName(program);
Py_Initialize();
fp = _Py_fopen(scriptfile, "r");
fp = _Py_fopen(scriptfile.c_str(), "r");
if (fp == NULL) {
error(string("Cannot open the script ") + scriptfile, 4);
}
......@@ -100,7 +81,7 @@ int main(int argc, char **argv)
PySys_SetArgv(argc, pargv);
int pyres = PyRun_SimpleFile(fp, scriptfile);
int pyres = PyRun_SimpleFile(fp, scriptfile.c_str());
if (pyres < 0) {
error(string("Error running the tool ") + scriptfile + " (error " + to_string(pyres) + ")", 5);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment