JFrog披露了PJSIP -一个流行的多媒体库中的5个内存损坏漏洞

更新03/03/22-增加了关于脆弱的应用程序
JFrog的安全研究团队不断在流行的开源项目中寻找新的和以前未知的安全漏洞,以帮助改善它们的安全状况。作为这项工作的一部分,我们最近在PJSIP是一个应用广泛的开源多媒体通信库Teluu.
通过触发这些新发现的漏洞,攻击者可以在使用PJSIP库的应用程序中执行任意代码。
JFrog Security负责任地披露了这些漏洞,并与PJSIP的维护者一起验证这些报告的安全漏洞的修复。
PJSIP库的用途是什么?
PJSIP提供了IP电话应用程序(如VoIP电话和会议应用程序)可以使用的API。如今,WhatsApp和BlueJeans等世界上最流行的通信应用程序都在使用它。PJSIP还用于星号,无处不在的开源PBX(专用分支交换机)实现。
公开的PJSIP安全漏洞
| CVE ID | 描述 | 影响 | JFrog CVSS |
| cve - 2021 - 43299 | 调用PJSUA API时栈溢出pjsua_player_create |
代码执行 | 8.1 |
| cve - 2021 - 43300 | 调用PJSUA API时栈溢出pjsua_recorder_create |
代码执行 | 8.1 |
| cve - 2021 - 43301 | 调用PJSUA API时栈溢出pjsua_playlist_create |
代码执行 | 8.1 |
| cve - 2021 - 43302 | 调用PJSUA API时读取越界pjsua_recorder_create |
拒绝服务 | 5.9 |
| cve - 2021 - 43303 | 调用PJSUA API时缓冲区溢出pjsua_call_dump |
拒绝服务 | 5.9 |
谁受到PJSIP漏洞的影响?
在2.12版本之前使用PJSIP库的任何项目都可以通过attacker-controlled以下任何api的参数都是易受攻击的:
pjsua_player_create- - - - - -文件名参数必须由攻击者控制pjsua_recorder_create- - - - - -文件名参数必须由攻击者控制pjsua_playlist_create- - - - - -file_names参数必须(部分地)由攻击者控制pjsua_call_dump- - - - - -缓冲参数容量必须小于128字节
澄清一下——这意味着利用依赖于上下文——应用程序必须以特定的方式使用PJSIP库才能受到攻击,即调用上述api并将外部输入传递给来自这些api的特定参数。
JFrog的安全研究团队已经披露了库本身的漏洞,并没有声称任何特定的应用程序是脆弱的(因为我们没有研究特定的应用程序)——这包括前一节提到的应用程序,这些应用程序没有被研究(WhatsApp, BlueJeans和Asterisk)。
技术故障
PJSIP提供了一个名为PJSUA为SIP应用程序提供API。基本的PJSUA api也由面向对象的api包装。PJSUA提供了丰富的媒体操作API,我们发现了以下漏洞:
cve - 2021 - 43299发现于pjsua_player_create(OO包装器)AudioMediaPlayer: createPlayer),它创建一个文件播放器,并自动将该播放器添加到会议桥。
此函数包含堆栈溢出漏洞:
PJ_DEF(pj_status_t) pjsua_player_create(const pj_str_t *filename, unsigned options, pjsua_player_id *p_id) {unsigned slot, file_id;char路径(PJ_MAXPATH);…Pj_memcpy (path, filename->ptr, filename->slen);Path [filename->slen] = '\0';…}
文件名- > ptr正在被复制到路径不去验证文件名- > slen(文件名大小)最多为路径的分配大小为PJ_MAXPATH < c /赋>(260)。因此,传递文件名长度超过260个字符将导致堆栈溢出。
cve - 2021 - 43300和cve - 2021 - 43302被发现于pjsua_recorder_create ()(OO包装器)AudioMediaRecorder: createrecord),它创建一个文件记录器,并自动将该记录器连接到会议桥。
此函数包含堆栈溢出漏洞:
PJ_DEF(pj_status_t) pjsua_recorder_create(const pj_str_t *filename, unsigned enc_type, void *enc_param, pj_ssize_t max_size, unsigned options, pjsua_recorder_id *p_id){…char路径(PJ_MAXPATH);pj_str_t ext;…/*确定文件格式*/ ext.ptr = filename->ptr + filename->slen - 4;Ext.slen = 4;if (pj_stricmp2(&ext, ".wav") == 0) file_format = FMT_WAV;if (pj_stricmp2(&ext, ".mp3") == 0) file_format = FMT_MP3;Else{…}…… pj_memcpy(path, filename->ptr, filename->slen); path[filename->slen] = '\0'; ... }
ext.ptr设为Filename ->ptr + Filename ->slen - 4和ext.slen设为4,后来pj_stricmp2被称为ext以比较文件的扩展名与“wav”或“mp3”.
问题披露如下cve - 2021 - 43302是,pjsua_recorder_create不检查的长度文件名至少是4。如果文件名比4,pj_stricmp2将在比较字符串时导致读取越界。
cve - 2021 - 43300类似于cve - 2021 - 43299:文件名- > ptr正在被复制memcpy到路径堆栈变量而不检查它文件名- > slen最多是路径分配的大小是PJ_MAXPATH(260)。
cve - 2021 - 43301中是否发现了另一个类似的堆栈溢出漏洞pjsua_playlist_create(OO包装器)AudioMediaPlayer: createPlaylist),它创建一个文件播放列表媒体端口,并自动将该端口添加到会议桥。pjsua_playlist_create调用pjmedia_wav_playlist_create与file_names参数映射为file_list:
PJ_DEF(pj_status_t) pjmedia_wav_playlist_create(pj_pool_t *pool, const pj_str_t *port_label, const pj_str_t file_list[], int file_count, unsigned ptime, unsigned options, pj_ssize_t buff_size, pjmedia_port **p_port){…字符的文件名(PJ_MAXPATH);/*打开操作的文件名。* /…/*确保所有文件存在*/ for (index=0;指数< file_count;{PJ_ASSERT_RETURN(file_list[index]. index)< PJ_MAXPATH, PJ_ENAMETOOLONG);Pj_memcpy (filename, file_list[index].ptr, file_list[index].slen);文件名(file_list(指数)。[size] = '\0';/*检查文件是否存在。 */ if (!pj_file_exists(filename)) { PJ_LOG(4,(THIS_FILE, "WAV playlist error: file '%s' not found", filename)); return PJ_ENOTFOUND; } } ... /* ok run this for all files to be sure all are good for playback. */ for (index=file_count-1; index>=0; index--) { pjmedia_wave_hdr wavehdr; pj_ssize_t size_to_read, size_read; /* we end with the last one so we are good to go if still in function*/ pj_memcpy(filename, file_list[index].ptr, file_list[index].slen); filename[file_list[index].slen] = '\0'; ... } ... }
该函数复制来自的每个文件名file_list来文件名而不检查它的长度是否为最大值PJ_MAXPATH(260)。如果文件名长度较长-副本将溢出文件名变量并触发堆栈溢出。
cve - 2021 - 43303是否存在缓冲区溢出漏洞pjsua_call_dump-一个将调用统计数据转储到给定缓冲区的函数:
PJ_DEF(pj_status_t) pjsua_call_dump(pjsua_call_id call_id, pj_bool_t with_media, char *buffer, unsigned maxlen, const char *缩进){…char tmp [128];…/* TMP正在被填充*/…Len = (int)pj_ansi_strlen(tmp);pj_ansi_strcpy(缓冲区,tmp);…}
函数使用tmp以便临时存储统计信息,然后将其复制到输出参数缓冲没有验证maxlen最多是len(最多可达128个)。
这可能导致缓冲区溢出,如果给定的容量缓冲参数小于len.
修复漏洞
为了完全修复这些漏洞,我们建议将PJSIP升级到2.12版本。
确认
我们要感谢PJSIP维护者快速验证报告的漏洞并修复它们。
使用JFrog Xray查找易受攻击的版本
除了暴露新安全漏洞通过自动安全扫描,JFrog为开发人员和安全团队提供了方便地访问其软件的最新相关信息(包括使用PJSIP开源库版本和相关cve)JFrog Xray SCA工具.