This patch is to avoid nepenthes running as root. There is some fishy code in nepenthes in regard to signednss issues and buffer boundaries and nepenthis handeles per definition untrusted data so better do not run as root. With this patch when started as root nepentis will drop privileges after startup to nobody. Nobody is a bad choice because nobody should never own any files so better create a user for running nepenthis and pprovide nepentis with its userid and groupid by the --uid and --gid parameters. You have to make sure that the nephentis user has read and write premissions to the directories where it should drop it's logfiles and the malware. To get back the old behaviour, start nephentis with 'nepenthes -u 0 -g 0'. Additional modifications: * change -v to canonical -V (small -v is usually for --verbose) * added --help output * fixed --workingdir support - but I don't understand the effect of basedir in relation to workingdir' * added processing of -? and -: (why ':'?) * stopped the abuse of printf in show_logo - SCNR * fixed typos in teh README and added a few new ones * expanded the README --Maximillian Dornseif --- nepenthes-20050807/core/src/Nepenthes.cpp 2005-07-12 23:48:11.000000000 +0200 +++ nepenthes-md/core/src/Nepenthes.cpp 2005-08-08 09:47:48.000000000 +0200 @@ -53,6 +66,11 @@ #include "DialogueFactoryManager.hpp" #include "DNSManager.hpp" +void show_logo(); +void show_help(); +void droppriv(uid_t uid, gid_t gid); + + using namespace nepenthes; Nepenthes *g_Nepenthes; @@ -136,28 +154,47 @@ char *confpath = "conf/nepenthes.conf"; char *basedir; char *workingdir = NULL; + uid_t uid; + gid_t gid; + struct passwd *nobody; #ifdef WIN32 #else + /* Initialize uid and gid to nobody. Can be overwritten by commandline */ + nobody = getpwnam("nobody"); + if (nobody && nobody->pw_uid) + { + uid = nobody->pw_uid; + gid = nobody->pw_gid; + } + else + { + // no nobody (?!), we use th oldsch00l default + uid = (unsigned int) -2; + gid = (unsigned int) -2; + } while( 1 ) { int option_index = 0; static struct option long_options[] = { { "basedir", 1, 0, 'b' }, + { "workingdir", 0, 0, 'w' }, { "config", 1, 0, 'c' }, { "log", 1, 0, 'l' }, { "disk-log", 1, 0, 'd' }, { "check-config", 0, 0, 'k' }, { "help", 0, 0, 'h' }, { "no-color", 0, 0, 'o' }, - { "version", 0, 0, 'v' }, + { "version", 0, 0, 'V' }, + { "uid", 1, 0, 'u' }, + { "gid", 1, 0, 'g' }, { 0, 0, 0, 0 } }; - int c = getopt_long(argc, argv, "ob:c:hkvl:d:", long_options, &option_index); + int c = getopt_long(argc, argv, "ob:c:hkVl:d:w:u:g:", long_options, &option_index); if (c == -1) break; @@ -196,16 +233,18 @@ */ break; + case '?': + case ':': case 'h': -// show_help(); - run=false; + show_help(); + exit(0); break; case 'k': run = false; break; - case 'v': + case 'V': // show_version(); printf("Nepenthes Version %s \n",NEPENTHES_VERSION); run = false; @@ -213,10 +252,27 @@ case 'w': workingdir = optarg; + break; - case '?': - case ':': - exit(0); + case 'u': + char *ep; + + uid = strtoul(optarg, &ep, 10); + if (optarg[0] == '\0' || *ep != '\0') { + logCrit("Bad uid %s\n", optarg); + show_help(); + run = false; + } + break; + + case 'g': + gid = strtoul(optarg, &ep, 10); + if (optarg[0] == '\0' || *ep != '\0') + { + logCrit("Bad gid %s\n", optarg); + show_help(); + run = false; + } break; default: @@ -273,17 +329,18 @@ m_DialogueFactoryManager->doList(); + // this seems to be the most convinient place to drop privilegses + // since all sockets and filehandles should be set up by now + if(getuid() == 0) + droppriv(uid, gid); - + doLoop(); // getLogMgr()->log(l_crit|l_net|l_shell|l_dia, "fooo bar\n"); // getLogMgr()->logf(l_shell, "%d <-> %d\n", 42, 23); } - if(run) - doLoop(); - delete m_Config; return 0; } @@ -422,8 +479,6 @@ } } -void show_logo(); - int main(int argc, char **argv) { #ifdef WIN32 @@ -489,53 +548,135 @@ return nepenthes.run(argc, argv); } +/* Since we are processing untrusted data: + drop the privileges and verify that they got dropped + This code is based on code from Nils Provos' honeyd */ + +void droppriv(uid_t uid, gid_t gid) +{ +#ifndef WIN32 + logInfo("dropping privileges to %d:%d\n", uid, gid); + + /* Lower privileges */ +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__) || defined(HAVE_SETGROUPS) + if (setgroups(1, &gid) == -1) + logWarn("setgroups(%d) failed: %s\n", gid, strerror(errno)); +#endif +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__) || defined(HAVE_SETREGID) + if (setregid(gid, gid) == -1) + logWarn("setregid(%d) failed: %s\n", gid, strerror(errno)); +#endif + if (setegid(gid) == -1) + logWarn("setegid(%d) failed: %s\n", gid, strerror(errno)); + if (setgid(gid) == -1) + logWarn("setgid(%d) failed: %s\n", gid, strerror(errno)); +#ifdef HAVE_SETREUID + if (setrugid(uid, uid) == -1) + logWarn("setreuid(%d) failed: %s\n", uid, strerror(errno)); +#endif +#ifdef __OpenBSD__ + if (seteuid(uid) == -1) + logWarn("seteuid(%d) failed: %s\n", gid, strerror(errno)); +#endif + if (setuid(uid) == -1) + logWarn("setuid(%d) failed: %s\n", gid, strerror(errno)); + + if (getgid() != gid || getegid() != gid) + { + logCrit("could not set gid to %d\n", gid); + goto error; + } + + if (getuid() != uid || geteuid() != uid) + { + logCrit("could not set uid to %d\n", uid); + goto error; + } + + /* Make really sure that we dropped them */ + if (uid != 0 && (setuid(0) != -1 || seteuid(0) != -1)) + { + logCrit("did not successfully drop privilege\n", strerror(errno)); + goto error; + } + if (gid != 0 && (setgid(0) != -1 || setegid(0) != -1)) + { + logCrit("did not successfully drop privilege\n", strerror(errno)); + goto error; + } + + return; +error: + logCrit("terminated%s", "\n"); + exit(1); +#endif /* WIN32 */ +} + + void show_logo() { - printf("%s","# #\n"); - printf("%s"," \n"); - printf("%s"," !¦..,(' \n"); - printf("%s"," !!..,¦, \n"); - printf("%s"," !*'.,!* \n"); - printf("%s"," *!'.,!¦ \n"); - printf("%s"," '!'.,!¦ \n"); - printf("%s"," .¦,',*¦,,. \n"); - printf("%s"," ,#=%(#%#%%#%%%C \n"); - printf("%s"," .#%C=,:::::::,,5%#. \n"); - printf("%s"," (#!!,,,,,,,,,,,J7#' \n"); - printf("%s"," =#!(=,,,,,,,,:==(7! ,%###!##%'. \n"); - printf("%s"," .=#(CJ3$#%C7==¦((77 ,%##%%!#%%%#%* \n"); - printf("%s"," .#(#J#A3#$==7=J=!¦(=3' ,%##%%::::,,::%#%, '!(====((!,'. \n"); - printf("%s"," ######$@53C=(¦¦¦¦==(¦=C7 %##(::::,,,,,::%##A$$3$CCJ3CJC(7C!\n"); - printf("%s"," #(###3#'JÐ%J(¦!!!*!!J(((=J' ,##(:::,,,,,:::%##5%C' . \n"); - printf("%s"," .#3#3#$#. C5$C7¦!=¦¦¦!7=(¦(7= ;##(:,,,,,,,::%###%. \n"); - printf("%s"," '####*. 7AJC7¦!7¦(¦¦!¦((=7C. |###((,,,,,,,)%##%=C, .*¦(7! \n"); - printf("%s"," (%7C77!(==!¦!¦¦=7=C! ((%############%!(CC¦.,¦JAA%3C' \n"); - printf("%s"," ¦$C7C7=¦(=¦¦¦((=(=J= ,:%%@M;%%;.77C7(=C!¦!*!¦=!¦C(777J3$3=!,'. \n"); - printf("%s"," ,%CJJ=C(7(((((=((=JC 7####::###CC=(CC=(=¦(*!=!=¦=7=77JJ, \n"); - printf("%s"," .%J337J==(=7==C=C7C3,##J!::::77#%J=CJ==¦¦¦=!=¦===(7C7C* \n"); - printf("%s"," C$33C3C7=7C777CJJJ%7##C:,,,,,:#$3CJC==(=7(¦¦¦(=C(J$CJ* \n"); - printf("%s"," '%$333CCC3CCCCCJ%3%#%#$C:,,,:3#AJJ3C7=JC=(((((7C7C3J3! \n"); - printf("%s"," (#$$3JJJ%3J$J33$$AA33#5J:,,:A#$$$JC7CJCC7=(=(CJ$CJJ$, \n"); - printf("%s"," J#%$$%33%$5$A#$%#%CJ3#A%:35#%J3$3JJCCC$C7J77JC$J33$' \n"); - printf("%s"," .75AA%%%$AA%#A%5#%CJC#J###3#J$%3$JJCCJCC3J33$33$$A. \n"); - printf("%s"," =5555A%AA5#5@%,%CJC3J###ACJJ$5$33JJJJJJJJ%%%3%%A% \n"); - printf("%s"," .3@55##A5###='!AJCJJ3###ACJ3A#$$$%$$33333$%%%AA5! \n"); - printf("%s"," %3J%5Ð5$J=' '533CC3###ACJ$#@A%%%AA$A%$$A%AA55¦ \n"); - printf("%s"," A=(3$A'. 3A3J33###%CJ$Ð#AA55AA%5#AA%%5#5¦ \n"); - printf("%s"," .AC=¦$J 'A%$J$A##A33AAÐ555###55#5555#A! \n"); - printf("%s"," *J7==A¦ '$%$%%##A3A=.JA###555%55##5(. \n"); - printf("%s"," =JJJJ5' '(A5A#JA%! *=Ð@#%AA5553¦ \n"); - printf("%s"," J$3J$$ .55A$#* .#A$AÐ%7* \n"); - printf("%s"," .$33$%C %$JJ5. !3J(%¦. \n"); - printf("%s"," '%%%A$7 %CC75. C(J7( \n"); - printf("%s"," *A%J$A= %==73 ,J7C$' \n"); - printf("%s"," 7%$JJ@! 'A7=CC =C7CJ \n"); - printf("%s"," $J3(3#. *$77C= %(CC( \n"); - printf("%s"," .#33($J ¦7C73, '$JJC, \n"); - printf("%s"," \n"); - printf("%s","# #\n"); - printf("%s"," \n"); - printf("%s"," Nepenthes Ampullaria \n"); - printf("%s"," \n"); - printf("%s","# #\n"); + puts("# #\n" + " \n" + " !¦..,(' \n" + " !!..,¦, \n" + " !*'.,!* \n" + " *!'.,!¦ \n" + " '!'.,!¦ \n" + " .¦,',*¦,,. \n" + " ,#=%(#%#%%#%%%C \n" + " .#%C=,:::::::,,5%#. \n" + " (#!!,,,,,,,,,,,J7#' \n" + " =#!(=,,,,,,,,:==(7! ,%###!##%'. \n" + " .=#(CJ3$#%C7==¦((77 ,%##%%!#%%%#%* \n" + " .#(#J#A3#$==7=J=!¦(=3' ,%##%%::::,,::%#%, '!(====((!,'. \n" + " ######$@53C=(¦¦¦¦==(¦=C7 %##(::::,,,,,::%##A$$3$CCJ3CJC(7C!\n" + " #(###3#'JÐ%J(¦!!!*!!J(((=J' ,##(:::,,,,,:::%##5%C' . \n" + " .#3#3#$#. C5$C7¦!=¦¦¦!7=(¦(7= ;##(:,,,,,,,::%###%. \n" + " '####*. 7AJC7¦!7¦(¦¦!¦((=7C. |###((,,,,,,,)%##%=C, .*¦(7! \n" + " (%7C77!(==!¦!¦¦=7=C! ((%############%!(CC¦.,¦JAA%3C' \n" + " ¦$C7C7=¦(=¦¦¦((=(=J= ,:%%@M;%%;.77C7(=C!¦!*!¦=!¦C(777J3$3=!,'. \n" + " ,%CJJ=C(7(((((=((=JC 7####::###CC=(CC=(=¦(*!=!=¦=7=77JJ, \n" + " .%J337J==(=7==C=C7C3,##J!::::77#%J=CJ==¦¦¦=!=¦===(7C7C* \n" + " C$33C3C7=7C777CJJJ%7##C:,,,,,:#$3CJC==(=7(¦¦¦(=C(J$CJ* \n" + " '%$333CCC3CCCCCJ%3%#%#$C:,,,:3#AJJ3C7=JC=(((((7C7C3J3! \n" + " (#$$3JJJ%3J$J33$$AA33#5J:,,:A#$$$JC7CJCC7=(=(CJ$CJJ$, \n" + " J#%$$%33%$5$A#$%#%CJ3#A%:35#%J3$3JJCCC$C7J77JC$J33$' \n" + " .75AA%%%$AA%#A%5#%CJC#J###3#J$%3$JJCCJCC3J33$33$$A. \n" + " =5555A%AA5#5@%,%CJC3J###ACJJ$5$33JJJJJJJJ%%%3%%A% \n" + " .3@55##A5###='!AJCJJ3###ACJ3A#$$$%$$33333$%%%AA5! \n" + " %3J%5Ð5$J=' '533CC3###ACJ$#@A%%%AA$A%$$A%AA55¦ \n" + " A=(3$A'. 3A3J33###%CJ$Ð#AA55AA%5#AA%%5#5¦ \n" + " .AC=¦$J 'A%$J$A##A33AAÐ555###55#5555#A! \n" + " *J7==A¦ '$%$%%##A3A=.JA###555%55##5(. \n" + " =JJJJ5' '(A5A#JA%! *=Ð@#%AA5553¦ \n" + " J$3J$$ .55A$#* .#A$AÐ%7* \n" + " .$33$%C %$JJ5. !3J(%¦. \n" + " '%%%A$7 %CC75. C(J7( \n" + " *A%J$A= %==73 ,J7C$' \n" + " 7%$JJ@! 'A7=CC =C7CJ \n" + " $J3(3#. *$77C= %(CC( \n" + " .#33($J ¦7C73, '$JJC, \n" + " \n" + "# #\n" + " \n" + " Nepenthes Ampullaria \n" + " \n" + "# #\n"); +} + +void show_help() +{ + puts("\nParameters:\n" + "-b --basedir ???\n" + "-w --workingdir directory to change to before starting up\n" + "-c --config path to configuration\n" +// "-l --log" +// "-d --disk-log" + "-k --check-config check configuration file and exit\n" + "-u --uid switch to uid (default: nobody)\n" + "-g --gid switch to gid (default: nobody)\n" + "-h --help this help message\n" +// "-o --no-color" + "-V --version print version and exit\n" + "\n"); } --- nepenthes-20050807/doc/README 2005-06-09 22:16:18.000000000 +0200 +++ nepenthes-md/doc/README 2005-08-08 10:11:48.000000000 +0200 @@ -7,7 +7,7 @@ 1. What is Nepenthes? 2. How does Nepenthes work? 2.1 Why would one want to run Nepenthes? - 3. Installing Nepenthes + 3. Installing and Starting Nepenthes 4. Current Status 4.1 Nepenthes core 4.1.1 Config File @@ -95,37 +95,58 @@ ---------------------------------------- The first argument is, its free. The software is free, the viruses you can capture are free. - You can collect this annoying stuff like stamps without paying a diam. + You can collect this annoying stuff like stamps without paying a dime. The rest of the arguments are security related an discussable. Setting up a host running Nepenthes can improve network security drastically, as you can see who scans for which known vulnerabilities. -3. Installing Nepenthes ------------------------ +3. Installing and Starting Nepenthes +------------------------------------ As we dont like automake, not to say we are unable to use it ... - You have to check yourself you got the following dependencies onboard before starting to compile nepenthes + You have to check yourself you got the following dependencies onboard before + starting to compile nepenthes - g++ (3.3.* higher) - libcurl - libmagic - libpcre - On debien just do + On debian just do apt-get install libcurl3-dev apt-get install libmagic-dev apt-get install libpcre3-dev + apt-get install libpadns1-dev Then type make and mail us your building error. - If no error occurs, checkout - conf/nepenthes.conf + If no error occurs, checkout conf/nepenthes.conf + + For building Nepenthes on FreeBSD or MacOS X refer to the respective + README files in this directory. if you use submit-norman you will want to checkout modules/submit-norman/submit-norman.conf to set a valid email address - - + if you don't have PostgreSQL installed you can run + make WITHOUT_POSTGRES=yes + to skip building of the parts of Nepenthes which need PostgreSQL. + + After compiling try + ./bin/nephentes --help + + For serious use you should add an special user to run Nepenthes and create + an directory where all output should be written and where this user has + therfore write access. Then start Nepenthes with the --uid and --gid options + with the userid and group id of the nephentis user given as parameters. + If you don'tto this nephentis will drop privileges to nobody which usually + is no perfect choice. + + You also might want to fix paths in following files: + ./conf/nepenthes.conf + ./modules/download-nepenthes/download-nepenthes.conf + ./modules/log-download/log-download.conf + ./modules/submit-file/submit-file.conf 4. Current Status ----------------- @@ -477,7 +498,7 @@ and we like it getting the results via mail. 8.7 - Q: how can i autocommit to clamav? + Q: how can I autocommit to clamav? A: clamav does not want to get victim of autocommits if you use the submit-nepenthes and our central server we will commit the files for you.