#$%$#$%$#$%$#$%$#$%$#$%$#$%$#$%$#$%$#$%$# $% CERN 3.0A Heap overflow advisory %$ #$%$#$%$#$%$#$%$#$%$#$%$#$%$#$%$#$%$#$%$# $% By Scrippie %$ #$ Phreak.nl $# $%$#$%$#$%$#$%$#$%$#$%$#$%$#$%$#$%$#$%$#$ #$ Love To: Maja, Dopey, Hester $# $%$#$%$#$%$#$%$#$%$#$%$#$%$#$%$#$%$#$%$#$ there is a heap overflow that wastes memory space in the CERN/3.0A webserver. Offending source code file is: Daemon/Implememtation/HTScript.c Offending function is: PUBLIC int HTCallScript ARGS1(HTRequest *, req) Offending Code snippet: else { /* Try replacing unknown suffix with .pp */ char *test = (char*)malloc(strlen(HTReqScript) + 4); char *s; CTRACE(stderr, "Trying...... to find executable by appending .pp\n"); strcpy(test, HTReqScript); s = strrchr(test, '.'); strcat(test, ".pp"); /* Try appending .pp */ CTRACE(stderr, "Trying...... \"%s\"\n", test); if (-1==access(test, X_OK)) { /* Then try replacing suffix with .pp */ if (s) { *s = 0; strcat(s, ".pp"); CTRACE(stderr, "Bad luck.... now trying \"%s\"\n", test); if (-1==access(test, X_OK)) { /* INVALID */ if (!(msg = (char*)malloc(3*strlen(test) + 100))) outofmem(__FILE__, "HTCallScript"); sprintf(msg, "Bad script request -- none of '%s' and '%s.pp' is executable", HTReqScript, test ); free(test); So we see that test is malloced to hold HTReqScript + ".pp\0" after which HTReqScript is copied to test, the dot is located and .pp is appended. We note that strcat() does not just append ".pp" to the string, but rather ".pp\0". Now, if the HTReqScript did contain a suffix CERN will go and use the char pointer s to overwrite the suffix of HtReqScript. If the HtRequest with the new ".pp" suffix cannot be found we print an error message. It seems CERN allocates 3*strlen(test) + 100 bytes for our error string... Probabely some 100 for our static string and the rest for HtReqScript and test. Sadly, the strcat on test will have limited the lenght of the test string, but NOT of HtReqScript, so making sure we have a lot of characters after our seperating dot overflows the heap. Consider a HtReqScript of 1 A a dot and 50000 A's - now we get something like: HtReqScript - somewhere around 50000 bytes (50003) Test - the same as HtReqScript + 4 (50007) After putting ".pp\0" into place however in our test array we get: strlen(test) - 1 A, 1 dot, pp - hmmm, 3 bytes Now our msg will be: 3*3+100=109 - by far enough to hold test, but by far NOT enough to hold HtReqScript. Close to 50000 bytes of the heap will be ruined! It's unlikely that this flaw is exploitable, since there is nothing on the heap after the malloced msg, but I'd sure like to hear any ideas. /* Scrip kids DoS attack section */ iLikeDossing# lynx http://www.lart.org/cgi-bin/A.`perl -e 'print"A" x 50000'` Repeat several times and see memory usage jump to remarkable heights :) /* End of script kiddies section */ A lot of thanks go to dvorak for pointing out to me that most webservers seem to suffer some sort of flaw in their script parsing routines and for telling me to take a look at HTScript.c A quick patch: --- HTScript.back Wed Jan 26 22:18:44 2000 +++ HTScript.c Wed Jan 26 22:19:52 2000 @@ -894,7 +894,7 @@ strcat(s, ".pp"); CTRACE(stderr, "Bad luck.... now trying \"%s\"\n", test); if (-1==access(test, X_OK)) { /* INVALID */ - if (!(msg = (char*)malloc(3*strlen(test) + 100))) + if (!(msg = (char*)malloc(strlen(HTReqScript)+strlen(test) + 100))) outofmem(__FILE__, "HTCallScript"); sprintf(msg, (Isn't a unified diff a beautifull thing :-) A big hooray to: #phreak.nl A lots of love to: Dopey, Maja, Hester Thanks to: dvorak Cheers, Scrippie - ronald@grafix.nl