ProFTPD是一款开放源代码FTP服务程序。 ProFTPD的src/support.c文件中的sreplace()函数在处理特制请求时存在单字节溢出漏洞。漏洞分析代码如下: \"\"\" char *sreplace(pool *p, char *s, ...) { va_list args; char *m,*r,*src = s,*cp; char **mptr,**rptr; char *marr[33],*rarr[33]; char buf[PR_TUNABLE_PATH_MAX] = {\'\'\0\'\'}, *pbuf = NULL; size_t mlen = 0, rlen = 0, blen; int dyn = TRUE; cp = buf; *cp = \'\'\0\'\'; memset(marr, \'\'\0\'\', sizeof(marr)); memset(rarr, \'\'\0\'\', sizeof(rarr)); blen = strlen(src) + 1; va_start(args, s); while ((m = va_arg(args, char *)) != NULL & & mlen < sizeof(marr)-1) { char *tmp = NULL; size_t count = 0; if ((r = va_arg(args, char *)) == NULL) break; /* Increase the length of the needed buffer by the difference between * the given match and replacement strings, multiplied by the number * of times the match string occurs in the source string. */ tmp = strstr(s, m); while (tmp) { pr_signals_handle(); count++; /* Be sure to increment the pointer returned by strstr(3), to * advance past the beginning of the...
ProFTPD是一款开放源代码FTP服务程序。 ProFTPD的src/support.c文件中的sreplace()函数在处理特制请求时存在单字节溢出漏洞。漏洞分析代码如下: \"\"\" char *sreplace(pool *p, char *s, ...) { va_list args; char *m,*r,*src = s,*cp; char **mptr,**rptr; char *marr[33],*rarr[33]; char buf[PR_TUNABLE_PATH_MAX] = {\'\'\0\'\'}, *pbuf = NULL; size_t mlen = 0, rlen = 0, blen; int dyn = TRUE; cp = buf; *cp = \'\'\0\'\'; memset(marr, \'\'\0\'\', sizeof(marr)); memset(rarr, \'\'\0\'\', sizeof(rarr)); blen = strlen(src) + 1; va_start(args, s); while ((m = va_arg(args, char *)) != NULL & & mlen < sizeof(marr)-1) { char *tmp = NULL; size_t count = 0; if ((r = va_arg(args, char *)) == NULL) break; /* Increase the length of the needed buffer by the difference between * the given match and replacement strings, multiplied by the number * of times the match string occurs in the source string. */ tmp = strstr(s, m); while (tmp) { pr_signals_handle(); count++; /* Be sure to increment the pointer returned by strstr(3), to * advance past the beginning of the substring for which we are * looking. Otherwise, we just loop endlessly, seeing the same * value for tmp over and over. */ tmp += strlen(m); tmp = strstr(tmp, m); } /* We are only concerned about match/replacement strings that actually * occur in the given string. */ if (count) { blen += count * (strlen(r) - strlen(m)); marr[mlen] = m; rarr[mlen++] = r; } } va_end(args); /* Try to handle large buffer situations (i.e. escaping of * PR_TUNABLE_PATH_MAX * (>2048) correctly, but do not allow very big buffer sizes, that may * be dangerous (BUFSIZ may be defined in stdio.h) in some library * functions. */ #ifndef BUFSIZ # define BUFSIZ 8192 #endif if (blen < BUFSIZ) [1] cp = pbuf = (char *) pcalloc(p, ++blen); if (!pbuf) { [2] cp = pbuf = buf; dyn = FALSE; blen = sizeof(buf); } while (*src) { for (mptr = marr, rptr = rarr; *mptr; mptr++, rptr++) { mlen = strlen(*mptr); rlen = strlen(*rptr); if (strncmp(src, *mptr, mlen) == 0) { [3] sstrncpy(cp, *rptr, blen - strlen(pbuf)); if (((cp + rlen) - pbuf + 1) > blen) { pr_log_pri(PR_LOG_ERR, \"WARNING: attempt to overflow internal ProFTPD buffers\"); cp = pbuf + blen - 1; goto done; } else { cp += rlen; } src += mlen; break; } } if (!*mptr) { [4] if ((cp - pbuf + 1) > blen) { pr_log_pri(PR_LOG_ERR, \"WARNING: attempt to overflow internal ProFTPD buffers\"); cp = pbuf + blen - 1; } *cp++ = *src++; } } done: *cp = \'\'\0\'\'; if (dyn) return pbuf; return pstrdup(p, buf); } \"\"\" blen的值是可控的,如果将其设置为小于BUFSIZ的值的话(见[1])就可以触发堆溢出,否则可以触发栈溢出(见[2])。 由于在[4]行的错误计算,攻击者可以控制pbuf最后的空字节,这样strlen(pbuf)就会大于blen。由于第三个参数为负数时sstrncpy函数仍可运行,因此[3]行的代码会使用攻击者的数据覆盖pbuf缓冲区。 目前已知至少有两种攻击方式: 1. MKD命令 2. pr_display_file