Advertisement
Guest User

Untitled

a guest
Jun 22nd, 2017
933
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.06 KB | None | 0 0
  1. /*
  2.    NYU Polytechnic Institute
  3.    CS6573: Penetration Testing and Vulnerability Analysis
  4.    Code Auditing, Homework Assignment 2
  5.    Written by Brandon Edwards
  6.    drraid@gmail.com
  7.  
  8.    There are a number of security holes in this network service,
  9.    but your assignment is to only find 3.
  10.    They could be both architectural or implementation problems.
  11.    Look for bad logic and memory mismanagement.
  12. */
  13.  
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <unistd.h>
  17. #include <stdlib.h>
  18. #include <stdarg.h>
  19. #include <signal.h>
  20. #include <sys/wait.h>
  21.  
  22. #include <netinet/in.h>
  23. #include <arpa/inet.h>
  24. #include <sys/socket.h>
  25. #include <sys/types.h>
  26. #include <netdb.h>
  27.  
  28. #define PORT 9090
  29. #define USERNAME 0x01
  30. #define PASSWORD 0x02
  31. #define BADUSER "\x33\x44 BAD USERNAME!"
  32. #define BADPASS "\x33\x45 BAD PASSWORD!"
  33. #define READY   "\x41\x41 READY!"
  34. #define USERPATH "./users/"
  35. #define ARTICLEPATH "./articles/"  
  36. #define LISTCOMMAND "ls ./articles/ > list.txt"
  37. #define FILENOTAVAIL "\x33\x31 FILE NOT AVAILABLE!"
  38. #define BEGINFILE "\x41\x41 BEGIN FILE: END WITH '!!!'"
  39. #define ARTICLEWROTE "\x41\x42 ARTICLE HAS BEEN WRITTEN!"
  40. #define LIST_ARTICLES 0x22
  41. #define READ_ARTICLE 0x23
  42. #define WRITE_ARTICLE 0x24
  43. #define COMMAND 0x25
  44. #define ADD_USER 0x26
  45.  
  46. void logData(FILE *logfile, char *format, ...);
  47. int setupSock(FILE *logf, unsigned short port);
  48. int writeSock(int sock, char *buf, size_t len);
  49. int readSock(int sock, char *buf, size_t len);
  50. void mainLoop(FILE *logf, int sock);
  51. void handleConnection(FILE *logfile, int sock);
  52. int userFunctions(FILE *logfile, int sock, char *user);
  53. char *findarg(char *argbuf, char argtype);
  54. int authenticate(FILE *logfile, char *user, char *pass);
  55.  
  56. int writeSock(int sock, char *buf, size_t len)
  57. {
  58.     ssize_t byteswrote = 0;
  59.     ssize_t ret = 0;
  60.  
  61.     while (byteswrote < len)
  62.     {
  63.         ret = send(sock, buf + byteswrote, len - byteswrote, 0);
  64.        
  65.         if (ret < 0)
  66.         {
  67.             return -1;
  68.         }
  69.  
  70.         if (ret == 0)
  71.         {
  72.             break;
  73.         }
  74.        
  75.         byteswrote += ret;
  76.     }
  77.  
  78.     return byteswrote;
  79. }
  80.  
  81. int readSock(int sock, char *buf, size_t len)
  82. {
  83.     ssize_t ret = 0;
  84.     ssize_t bytesread = 0; // why have a signed variable, should never have negative bytes read?????????????? does it return negative?
  85.  
  86.     while (bytesread < len)
  87.     {
  88.         ret = recv(sock, buf + bytesread, len - bytesread, 0);
  89.  
  90.         if (ret == 0)
  91.         {
  92.             break;
  93.         }  
  94.  
  95.         if (ret < 0)
  96.         {
  97.             return -1;
  98.         }
  99.  
  100.         bytesread += ret;
  101.     }
  102.    
  103.     return bytesread;  
  104. }
  105.  
  106. void writeArticle(int sock, FILE *logfile, char *action)
  107. {
  108.     FILE *file;
  109.     char *p;
  110.     size_t x, y;
  111.     int complete = 0;
  112.     char buf[1024];
  113.     char path[1024];
  114.  
  115.     strcpy(path, ARTICLEPATH);
  116.     strncat(path, &action[1], sizeof(path) - strlen(path)-1);
  117.  
  118.     logData(logfile, "user writing article: %s", path);
  119.  
  120.     file = fopen(&action[1], "w");
  121.  
  122.     if (!file)
  123.     {
  124.         writeSock(sock, FILENOTAVAIL, sizeof(FILENOTAVAIL));
  125.         return;
  126.     }
  127.  
  128.     writeSock(sock, BEGINFILE, sizeof(BEGINFILE));
  129.  
  130.     while (1)
  131.     {
  132.         memset(buf, 0, sizeof(buf));
  133.         x = readSock(sock, buf, sizeof(buf)-1);
  134.         for (y = 0; y < x; ++y)
  135.         {
  136.             if (buf[y] == '!')
  137.             {
  138.                 if (buf[y+1] == '!' && buf[y+2] == '!')
  139.                 {
  140.                     buf[y] = 0x0;
  141.                     complete = 1;
  142.                 }
  143.             }
  144.         }  
  145.         fputs(buf, file);
  146.         if (complete)
  147.         {
  148.             break;
  149.         }
  150.     }
  151.  
  152.     writeSock(sock, ARTICLEWROTE, sizeof(ARTICLEWROTE));
  153.     fclose(file);
  154. }
  155.  
  156.  
  157. void readArticle(int sock, FILE *logfile, char *action)
  158. {
  159.     FILE *file;
  160.     char buf[100];
  161.     char path[100];
  162.  
  163.     logData(logfile, &action[1]);
  164.  
  165.     strcpy(path, ARTICLEPATH);
  166.     strcat(path, &action[1]);
  167.  
  168.     logData(logfile, "user request to read article: %s", path);
  169.  
  170.     file = fopen(path, "r");
  171.  
  172.     if (!file)
  173.     {
  174.         writeSock(sock, FILENOTAVAIL, sizeof(FILENOTAVAIL));
  175.         return;
  176.     }
  177.    
  178.     /* fgets for the size of the buffer (100), from the file
  179.        writing the article to the user each time! */
  180.  
  181.     while (fgets(buf, 1000, file))
  182.     {
  183.         writeSock(sock, buf, strlen(buf));
  184.     }
  185.  
  186.     fclose(file);
  187.  
  188.     return;
  189. }
  190.  
  191. void listArticles(int sock, FILE *logfile, char *action)
  192. {
  193.     char buf[100];
  194.     FILE *list;
  195.  
  196.     logData(logfile, "user has requested a list of articles");
  197.  
  198.     /* i wish i had more time! i wouldnt have to write
  199.        this code using system() to call things! */
  200.  
  201.     memset(buf, 0, sizeof(buf));
  202.     system(LISTCOMMAND);
  203.  
  204.     list = fopen("list.txt", "r");
  205.  
  206.     while (fgets(buf, sizeof(buf)-1, list))
  207.     {
  208.         writeSock(sock, buf, strlen(buf)); 
  209.     }
  210.  
  211.     fclose(list);
  212.     return;
  213. }
  214.  
  215. void command(FILE *log, int sock, char *action)
  216. {
  217.     logData(log, "executing command: %s", &action[1]);
  218.     system(&action[1]);
  219. }
  220.  
  221. void addUser(FILE *log, int sock, char *action)
  222. {
  223.     char *p;
  224.     char buf[1024];
  225.  
  226.     p = strchr(&action[1], ':');
  227.  
  228.     if (!p)
  229.     {
  230.         return;
  231.     }
  232.  
  233.     *p = 0x0;
  234.     logData(log, "Adding user: %s with pass: %s", &action[1], &p[1]);  
  235.     snprintf(buf, sizeof(buf)-1, "echo %s > %s%s.txt", &p[1], USERPATH, &action[1]);
  236.     return;
  237. }
  238.  
  239. int adminFunctions(FILE *logfile, int sock)
  240. {
  241.     char action[1024];
  242.     size_t len;
  243.     while (1)
  244.     {
  245.         writeSock(sock, READY, sizeof(READY));
  246.         memset(action, 0, sizeof(action));
  247.         len = readSock(sock, action, sizeof(action));  
  248.    
  249.         if (action[0] == ADD_USER)
  250.         {
  251.             addUser(logfile, sock, action);
  252.         }
  253.         else if (action[0] == COMMAND)
  254.         {
  255.             command(logfile, sock, action);
  256.         }
  257.         else
  258.         {
  259.             logData(logfile, "unknown action: %x", action[0]);
  260.         }
  261.     }
  262.  
  263. }
  264.  
  265. int userFunctions(FILE *logfile, int sock, char *user)
  266. {
  267.     char action[1024];
  268.     size_t len;
  269.  
  270.     if (0 == strncmp(user, "admin", 5))
  271.     {
  272.         adminFunctions(logfile, sock);
  273.         return 0;
  274.     }
  275.    
  276.     while (1)
  277.     {
  278.         writeSock(sock, READY, sizeof(READY));
  279.         memset(action, 0, sizeof(action));
  280.         len = readSock(sock, action, sizeof(action));  
  281.    
  282.         if (action[0] == LIST_ARTICLES)
  283.         {
  284.             listArticles(sock, logfile, action);
  285.         }
  286.         else if (action[0] == READ_ARTICLE)
  287.         {
  288.             readArticle(sock, logfile, action);
  289.         }
  290.         else if (action[0] == WRITE_ARTICLE)
  291.         {
  292.             writeArticle(sock, logfile, action);
  293.         }
  294.         else
  295.         {
  296.             logData(logfile, "unknown action %x", action[0]);
  297.             return;
  298.         }
  299.     }
  300.  
  301.     return 0;
  302. }
  303.  
  304. /* return 1 for success, 2 on bad username, 3 on bad password */
  305. int authenticate(FILE *logfile, char *user, char *pass)
  306. {
  307.     char search[1024];
  308.     char path[1024];
  309.     char userfile[1024];
  310.     char data[1024];
  311.     FILE *file;
  312.     int ret;
  313.  
  314.     memset(path, 0, sizeof(1024));
  315.  
  316.     /* FIXME: hard coded admin backdoor for password recovery */   
  317.     if (memcmp(pass, "baCkDoOr", 9) == 0)
  318.     {
  319.         return 1;
  320.     }
  321.    
  322.     /* look up user by checking user files: done via system() to /bin/ls|grep user */
  323.     logData(logfile, "performing lookup for user via system()!\n");
  324.     snprintf(userfile, sizeof(userfile)-1, "%s.txt", user);
  325.     snprintf(search, sizeof(search)-1, "stat %s`ls %s | grep %s`", USERPATH, USERPATH, userfile);
  326.     ret = system(search);
  327.  
  328.     if (ret != 0)
  329.     {
  330.         return 2;
  331.     }
  332.  
  333.     snprintf(path, sizeof(path)-1, "%s%s", USERPATH, userfile);
  334.        
  335.     /* open file and check if contents == password */
  336.     file = fopen(path, "r");
  337.  
  338.     if (!file)
  339.     {
  340.         logData(logfile, "fopen for userfile failed\n");
  341.         return 2;
  342.     }
  343.  
  344.     logData(logfile, "getting userfile info\n");
  345.     fgets(data, sizeof(data)-1, file);
  346.    
  347.     fclose(file);
  348.  
  349.     /* woW i'm tired. I hope i make the deadlines */
  350.     if (memcmp(data, pass, 3))
  351.     {
  352.         return 3;
  353.     }
  354.  
  355.     return 1;
  356. }
  357.  
  358. char *findarg(char *argbuf, char argtype)
  359. {
  360.     char *ptr1;
  361.     char *found = NULL;
  362.     char type = 0;
  363.     size_t size;
  364.  
  365.     ptr1 = argbuf;
  366.  
  367.     while (1)
  368.     {  
  369.         memcpy((char *)&size, ptr1, 4);
  370.         if (size == 0)
  371.         {
  372.             break;
  373.         }  
  374.         if (ptr1[4] == argtype)
  375.         {
  376.             found = &ptr1[5];
  377.             break;
  378.         }
  379.         ptr1 += size;
  380.     }
  381.  
  382.     return found;
  383. }
  384.  
  385. void handleConnection(FILE *logfile, int sock)
  386. {
  387.     char buffer[1024];
  388.     char argbuf[1024];
  389.     char *user = NULL;
  390.     char *pass = NULL;
  391.     int len = 0;
  392.     int ret = 0;
  393.     size_t segloop;
  394.     size_t segmentcount;
  395.     size_t segnext;
  396.     size_t argsize;
  397.     char *ptr1;
  398.     char *ptr2;
  399.  
  400.     /* read in data */
  401.     memset(buffer, 0, sizeof(buffer));
  402.     len = readSock(sock, buffer, sizeof(buffer));  
  403.     logData(logfile, "handling connection");
  404.  
  405.     if (len == -1)
  406.     {
  407.         return;
  408.     }
  409.    
  410.     /* parse protocol */
  411.     ptr1 = buffer;
  412.     ptr2 = argbuf;
  413.  
  414.     /* get count of segments */
  415.     memcpy((char *)&segmentcount, ptr1, 4); // first thing that comes is an int, segmentcount
  416.  
  417.     logData(logfile, "Segment count is %i", segmentcount);
  418.    
  419.     /* make sure there aren't too many segments!
  420.        so the count * 8(bytes) should be the max */
  421.     if (segmentcount * 8 > sizeof(argbuf)) // * 8 should be able to get something to wrap back around, <-- YES!!!
  422.     {
  423.         logData(logfile, "bad segment count");
  424.         return;
  425.     }
  426.  
  427.     ptr1 += 4;
  428.  
  429.     memset(argbuf, 0, sizeof(argbuf));
  430.  
  431.     for (segloop = 0; segloop < segmentcount; ++segloop)
  432.     {
  433.         logData(logfile, "adding segment %i", segloop+1);
  434.         memcpy((char *)&segnext, ptr1, 4);
  435.         logData(logfile, "next segment offset %i", segnext);
  436.         ptr1 += 4;
  437.         memcpy((char *)&argsize, ptr1, 4); 
  438.         logData(logfile, "argsize: %i", argsize);
  439.         memcpy(ptr2, ptr1, argsize);
  440.         ptr2 += argsize;
  441.         ptr1 += segnext;
  442.     }
  443.  
  444.     logData(logfile, "looking up user args");
  445.  
  446.     user = findarg(argbuf, USERNAME);
  447.     pass = findarg(argbuf, PASSWORD);
  448.  
  449.     snprintf(buffer, sizeof(buffer)-1, "User attempting to authenticate: %s", user);
  450.     logData(logfile, buffer);
  451.  
  452.     logData(logfile, "calling authenticate");
  453.     ret = authenticate(logfile, user, pass);
  454.     logData(logfile, "returned from authenticate");
  455.  
  456.     if (ret != 1)
  457.     {
  458.        
  459.         if (ret == 2)
  460.         {
  461.             writeSock(sock, BADUSER, sizeof(BADUSER)); 
  462.         }  
  463.    
  464.         if (ret == 3)
  465.         {
  466.             writeSock(sock, BADPASS, sizeof(BADPASS));
  467.         }
  468.  
  469.         snprintf(buffer, sizeof(buffer)-1,"user: %s failed to login with password %s", user, pass);
  470.         logData(logfile, buffer);
  471.         return;
  472.     }
  473.  
  474.     logData(logfile, "user %s authenticated!", user);
  475.    
  476.     userFunctions(logfile, sock, user);
  477.  
  478.     return;
  479. }
  480.  
  481. void mainLoop(FILE *logf, int sock)
  482. {
  483.     int clientfd = 0;
  484.     struct sockaddr_in client;
  485.     socklen_t clientlen = 0;
  486.     pid_t offspring = 0;
  487.  
  488.     memset((char *)&client, 0, sizeof(client));
  489.    
  490.     logData(logf, "entering main loop...");
  491.  
  492.     while (1)
  493.     {
  494.         clientfd = accept(sock, (struct sockaddr *)&client, &clientlen);
  495.         if (clientfd == -1)
  496.         {
  497.             continue;
  498.         }
  499.  
  500.         offspring = fork();
  501.    
  502.         if (offspring == -1)
  503.         {
  504.             continue;
  505.         }
  506.  
  507.         if (offspring == 0)
  508.         {
  509.             handleConnection(logf, clientfd);
  510.             close(clientfd);
  511.             exit(0);
  512.         }
  513.  
  514.         close(clientfd);
  515.     }
  516. }
  517.  
  518. void spawnhandler(int signumber)
  519. {
  520.     pid_t pid;
  521.     int stat;
  522.  
  523.     while ((pid = waitpid(-1, &stat, WNOHANG))>0)
  524.     {
  525.         printf("circle of life completed for %i\n", pid);  
  526.     }
  527. }
  528.  
  529. int setupSock(FILE *logf, unsigned short port)
  530. {
  531.     int sock = 0;
  532.     struct sockaddr_in sin;
  533.     int opt = 0;
  534.  
  535.     if (signal(SIGCHLD, spawnhandler)== SIG_ERR)
  536.     {
  537.         perror("fork() spawn handler setup failed!");
  538.         return -1;
  539.     }
  540.    
  541.     memset((char *)&sin, 0, sizeof(sin));
  542.  
  543.     sin.sin_family = AF_INET;
  544.     sin.sin_port = htons(port);
  545.    
  546.     sock = socket(AF_INET, SOCK_STREAM, 0);
  547.  
  548.     if (sock == -1)
  549.     {
  550.         logData(logf, "socket() failed");
  551.         return -1;
  552.     }
  553.  
  554.     opt = 1;
  555.  
  556.     if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1)
  557.     {
  558.         logData(logf,"setsockopt() failed");
  559.         return -1;
  560.     }
  561.  
  562.     if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1)
  563.     {
  564.         logData(logf, "bind() failed");
  565.         return -1;
  566.     }
  567.  
  568.     if (listen(sock, 10) == -1)
  569.     {
  570.         logData(logf, "listen() failed");
  571.         return -1;
  572.     }
  573.  
  574.     return sock;
  575. }
  576.  
  577. int main(int argc, char *argv[])
  578. {
  579.     int sock;
  580.     FILE *logf;
  581.  
  582.     /* setup log file */
  583.     logf = fopen("logfile.txt", "w");
  584.  
  585.     if (!logf)
  586.     {
  587.         perror("unable to open log file\n");
  588.         exit(1);
  589.     }
  590.  
  591.     /* go daemon */
  592.     daemon(0,0);
  593.    
  594.     /* setup socket */
  595.     sock = setupSock(logf, PORT);
  596.    
  597.     if (sock == -1)
  598.     {
  599.         logData(logf, "failed to setup socket, exiting");
  600.         exit(1);
  601.     }
  602.  
  603.     logData(logf, "intial socket setup complete");
  604.    
  605.     mainLoop(logf, sock);  
  606.  
  607.     /* this should never execute */
  608.     exit(0);
  609. }
  610.  
  611. /* printf-style data logging */
  612. void logData(FILE *logfile, char *format, ...)
  613. {
  614.     char buffer[4096];
  615.     va_list arguments;
  616.     va_start(arguments, format);
  617.     vsnprintf(buffer, sizeof(buffer)-1, format, arguments);
  618.     va_end(arguments);
  619.     fprintf(logfile, "LoggedData [Proccess:%i]: %s\n", getpid(), buffer);
  620.     fflush(logfile);
  621. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement