HI,
I've found several security issue about h323plus.
I don't think it is a good idea to config plugin directiory by environment variable, it may lead to several problem. And attackers may set malicious enviroment in some way like setenv, putenv, or something like shellshock, etc. There are a few issues related to it.
Buffer Overflow in dyna.cxx
h323plus/plugins/video/common/dyna.cxx
bool DynaLink::Open(const char *name)
{
...
// try directories specified in PTLIBPLUGINDIR
char ptlibPath[1024];
memset(ptlibPath, 0, sizeof(ptlibPath));
char * env = ::getenv("PTLIBPLUGINDIR"); << untrusted input
if (env != NULL)
strcpy(ptlibPath, env); << strcpy here may buffer overflow
...
}
bool DynaLink::InternalOpen(const char * dir, const char *name)
{
char path[1024];
memset(path, 0, sizeof(path));
// Copy the directory to "path" and add a separator if necessary
if (strlen(dir) > 0) {
strcpy(path, dir); << buffer overflow possibily here
if (path[strlen(path)-1] != DIR_SEPARATOR[0])
strcat(path, DIR_SEPARATOR); << buffer overflow possibily here
}
strcat(path, name); << buffer overflow possibily here
if (strlen(path) == 0) {
TRACE(1, _codecString << "\tDYNA\tdir '" << (dir != NULL ? dir : "(NULL)") << "', name '" << (name != NULL ? name : "(NULL)") << "' resulted in empty path");
return false;
}
#ifndef _WIN32
strcat(path, ".so"); << buffer overflow possibily here
#endif
...
}
Suggestion:
Use secure function like strcpy_s/strcat_s instead of strcpy/strcat
Dynamic Link Library Hijack
Also, untrusted source of plugin paths may lead to Dynamic Link Library hijack.
If the PTLIBPLUGINDIR is setted to some other directory with malicious dll/so with same name in it, the code in it will have a chance to be execute.
bool DynaLink::InternalOpen(const char * dir, const char *name)
{
...
// Load the Libary
#ifdef _WIN32
# ifdef UNICODE
WITH_ALIGNED_STACK({ // must be called before using avcodec lib
USES_CONVERSION;
_hDLL = LoadLibrary(A2T(path)); << may load library from untrusted path
});
# else
WITH_ALIGNED_STACK({ // must be called before using avcodec lib
_hDLL = LoadLibrary(path); << may load library from untrusted path
});
# endif /* UNICODE */
#else
WITH_ALIGNED_STACK({ // must be called before using avcodec lib
_hDLL = dlopen((const char *)path, RTLD_NOW); << may load library from untrusted path
});
#endif /* _WIN32 */
...
}
Suggestion:
Don’t trust environment variable input. Using get module path or hardcoded plugin path to locate library may be much safer, or use reliable configure file instead.
Buffer Overflow in h264-x264.cxx/h264pipe_win32.cxx
h323plus/plugins/video/H.264/h264-x264.cxx
h323plus/plugins/video/H.264/h264pipe_win32.cxx
bool H264EncCtx::findGplProcess()
{
char * env = ::getenv("PWLIBPLUGINDIR");
if (env == NULL)
env = ::getenv("PTLIBPLUGINDIR");
if (env != NULL) {
const char * token = strtok(env, DIR_TOKENISER);
while (token != NULL) {
if (checkGplProcessExists(token)) << token from untrusted environment variable
return true;
token = strtok(NULL, DIR_TOKENISER);
}
}
...
}
bool H264EncCtx::checkGplProcessExists (const char * dir)
{
struct stat buffer;
memset(gplProcess, 0, sizeof(gplProcess));
strncpy(gplProcess, dir, sizeof(gplProcess)); << strncpy here
if (gplProcess[strlen(gplProcess)-1] != DIR_SEPERATOR[0])
strcat(gplProcess, DIR_SEPERATOR); << strcat here may overflow
strcat(gplProcess, VC_PLUGIN_DIR); << strcat here may overflow
if (gplProcess[strlen(gplProcess)-1] != DIR_SEPERATOR[0])
strcat(gplProcess, DIR_SEPERATOR); << strcat here may overflow
strcat(gplProcess, GPL_PROCESS_FILENAME); << strcat here may overflow
...
}
Suggestion solution:
Don’t trust environment variable input. Hardcoded plugin path is more safer, or use reliable configure file instead.
Don’t use unsafe function like strcat. snprintf_s is recommanded.
Command Injection in h264-x264.cxx/h264pipe_win32.cxx
h323plus/plugins/video/H.264/h264-x264.cxx
h323plus/plugins/video/H.264/h264pipe_win32.cxx
bool H264EncCtx::findGplProcess()
{
char * env = ::getenv("PWLIBPLUGINDIR");
if (env == NULL)
env = ::getenv("PTLIBPLUGINDIR");
if (env != NULL) {
const char * token = strtok(env, DIR_TOKENISER);
while (token != NULL) {
if (checkGplProcessExists(token)) << token from environment variable
return true;
token = strtok(NULL, DIR_TOKENISER);
}
}
...
}
bool H264EncCtx::checkGplProcessExists (const char * dir)
{
struct stat buffer;
memset(gplProcess, 0, sizeof(gplProcess));
strncpy(gplProcess, dir, sizeof(gplProcess)); << may lead to command injection
if (gplProcess[strlen(gplProcess)-1] != DIR_SEPERATOR[0])
strcat(gplProcess, DIR_SEPERATOR);
strcat(gplProcess, VC_PLUGIN_DIR);
if (gplProcess[strlen(gplProcess)-1] != DIR_SEPERATOR[0])
strcat(gplProcess, DIR_SEPERATOR);
strcat(gplProcess, GPL_PROCESS_FILENAME);
...
}
void H264EncCtx::execGplProcess()
{
unsigned msg;
unsigned status = 0;
if (execl(gplProcess,"h264_video_pwplugin_helper", dlName,ulName, NULL) == -1) { << exec command
...
}
Suggestion:
Don’t trust environment variable input. Using get module path or hardcoded plugin path to locate library may be much safer, or use reliable configure file instead.