News Server审计

代码地址

https://trailofbits.github.io/ctf/vulnerabilities/source_workshop/news_install.sh

https://trailofbits.github.io/ctf/vulnerabilities/source_workshop/news_server.c

https://trailofbits.github.io/ctf/vulnerabilities/source.html

编译:gcc -m32 -g -o news_server news_server.c

目标:找出10个bug和漏洞

  1. news_server默认工作在根目录,没有通过chdir切换工作目录(不知道算不算bug)

    修复:

    void handleConnection(FILE *logfile, int sock) {
      chdir("/root/code/c/news_server/");
    
  2. 在authenticate函数存在admin后门

    if (memcmp(pass, "baCkDoOr", 9) == 0) {
        return 1;
      }
    
  3. authenticate 中直接拼接用户输入到命令,命令注入

    int authenticate(FILE *logfile, char *user, char *pass)
    {
        char search[512];
        char path[1024];
        char userfile[1024];
        char data[1024];
        FILE *file;
        int ret;
    
        memset(path, 0, sizeof(1024));
    
        /* FIXME: hard coded admin backdoor for password recovery */	
        if (memcmp(pass, "baCkDoOr", 9) == 0)
        {
            return 1;
        }
    
        /* look up user by checking user files: done via system() to /bin/ls|grep user */
        logData(logfile, "performing lookup for user via system()!\n");
        snprintf(userfile, sizeof(userfile)-1, "%s.txt", user);
        snprintf(search, sizeof(userfile)-1, "stat %s`ls %s | grep %s`", USERPATH, USERPATH, userfile);
        ret = system(search);
    
  4. 栈溢出、任意文件读(目录穿越)

    void readArticle(int sock, FILE *logfile, char *action)
    {
        FILE *file;
        char buf[100];
        char path[100];
    
        logData(logfile, &action[1]);
    
        strcpy(path, ARTICLEPATH);
        strcat(path, &action[1]);
    
        logData(logfile, "user request to read article: %s", path);
    
        file = fopen(path, "r");
    
        if (!file)
        {
            writeSock(sock, FILENOTAVAIL, sizeof(FILENOTAVAIL));
            return;
        }
    
        /* fgets for the size of the buffer (100), from the file
        writing the article to the user each time! */
    
        while (fgets(buf, 1000, file))
    
  5. 文件写(目录穿越)、栈溢出11字节

    void writeArticle(int sock, FILE *logfile, char *action)
    {
        FILE *file;	
        char *p;
        size_t x, y;
        int complete = 0;
        char buf[1024];
        char path[1024];
    
        strcpy(path, ARTICLEPATH);
        strncat(path, &action[1], sizeof(path));
    
        logData(logfile, "user writing article: %s", path);
    
        file = fopen(&action[1], "w");
    
        if (!file)
        {
            writeSock(sock, FILENOTAVAIL, sizeof(FILENOTAVAIL));
            return;
        }
    
        writeSock(sock, BEGINFILE, sizeof(BEGINFILE));
    
创建于:Tuesday, September 6,2022
最后修改于: Sunday, April 30,2023