最近HackerOne上公开了几个GitLab的漏洞,奖金还不低,一些漏洞细节也已经公开,大多是业务逻辑漏洞,学习下。
漏洞一:issue迁移导致跨目录读取任意文件
【漏洞利用过程】
1、创建两个项目
2、在第一个项目中添加issue,描述内容如下:
代码语言:javascript复制![a](/uploads/11111111111111111111111111111111/../../../../../../../../../../../../../../etc/passwd)
3、将issue迁移至第二个项目
4、链接中的文件将被复制过去,用户可直接下载到/etc/passwd文件
【漏洞成因】
问题出在UploadsRewriter这个类中,在迁移issue时,它会重写markdown链接用来上传文件,漏洞出现在 lib/gitlab/gfm/uploads_rewriter.rb 中(居然是用ruby写的),对复制文件时未考虑到跨目录问题,导致可以上传任意文件到对应的链接上,进而被下载:
代码语言:javascript复制 @text.gsub(@pattern) do |markdown|
file = find_file(@source_project, $~[:secret], $~[:file])
break markdown unless file.try(:exists?)
klass = target_parent.is_a?(Namespace) ? NamespaceFileUploader : FileUploader
moved = klass.copy_to(file, target_parent)
...
def find_file(project, secret, file)
uploader = FileUploader.new(project, secret: secret)
uploader.retrieve_from_store!(file)
uploader
end
【漏洞修复】
修复也很简单,添加对路径遍历的情况的检测就好:
漏洞二:Wiki附件上传导致任意文件读取
【漏洞利用过程】
1、创建新项目
2、创建wiki页面
3、在gitlab服务器创建测试文件:echo hello > /tmp/ggg;
4、攻击者本地创建垃圾文件:echo unused > /tmp/lala.txt
5、伪造参数上传wiki文件:
bash curl -g -XPOST -v -H "Authorization: Bearer
6、粘贴上面的markdown参数内容到wiki页面,然后下载文件
【漏洞成因】
GitLab Workhorse作为智能反向代理,专用于处理数据量大的请求,比如文件上传下载,它定义一组路由用来拦截对GitLab rails应用程序的访问, 也就是说,所有对 Rails 组件的请求都得经过 Workhorse,但有时也可能被绕过。
比如这里的用来上传wifi附件的漏洞CGI,正常情况下是指定本地文件路径参数file,但当你把这参数的字段名改成下面这些原本不存在的字段名时:
;file
[file]
file]
;file]
file]]
file;;
就会触发rewrite_filed的字段重置动作,导致原有字段file为nil空值,这会造成hash签名绕过,与此同时Multipart::Handler会去使用get参数中的file.path路径上传文件供下载,而不是特殊构造的[file]参数值。最终允许用户指定allowd_paths中的路径给rails组件处理,导致可以访问到以下路径范围内的本地磁盘文件:
代码语言:javascript复制 def allowed_paths
[
::FileUploader.root,
Gitlab.config.uploads.storage_path,
JobArtifactUploader.workhorse_upload_path,
File.join(Rails.root, 'public/uploads/tmp')
]
end
作者是利用wiki中的上传文件链接来实现任意文件读取的,他使用 /proc/pid/fd/xx的方法读取其它用户的数据。
【漏洞修复】
如果gitlab把file.path参数放在post中应该也能防御,最后他们是添加对字段的检查判断,必须是顶级参数,而不是foo[bar]这种嵌套方式。
漏洞三:Git命令注入
【漏洞利用过程】
1、创建wiki页面,在commit消息中写入打算覆盖的文件内容,比如伪造ssh key
2、伪造ref参数发送请求,去篡改authorized_keys文件内容:
curl --header "PRIVATE-TOKEN: $TOKEN" 'http://gitlab-vm.local/api/v4/projects/5/search?scope=wiki_blobs&search=page&ref=--output=/var/opt/gitlab/.ssh/authorized_keys'
3、使用创建的ssh key登陆gitlab
【漏洞成因】
原因比较简单,就是ref参数直接被带入git命令中:
/opt/gitlab/embedded/bin/git --git-dir /var/opt/gitlab/git-data/repositories/@hashed/4b/22/4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a.wiki.git log --max-count=1 --output=/tmp/file
【漏洞修复】
很暴力简单,直接限制ref参数为--no-index,用户不再可控。
漏洞四:Issue评论附件SSRF漏洞
【漏洞利用过程】
1、创建新项目
2、创建issue
3、添加评论
4、导出项目
5、修改notes中的remote_attachment_url
6、重新打包导入
7、浏览评论,点击附件
【漏洞成因】
issue评论功能有添加附件下载的功能,这些下载地址正是由导出项目的project.json中的漏洞参数remote_attachment_url决定的,修改后重新导入会使其生效,再点击下载时就触发伪造请求,访问到内部服务。
【漏洞修复】
添加了remote_attachment_request_header的散列值,并将其添加到AttributeCleaner
方法中,使得攻击者无法添加去伪造请求。
总结
多个gitlab漏洞都是基于对业务功能的了解,手工测试 代码审计挖到的可能性较大,每个功能与业务功能逻辑关系很紧密,像漏洞一,似乎你不看代码都不知道有拷贝文件,自然更然想到这个攻击点。像挖这种偏业务逻辑漏洞的,很大程度上取决你对业务功能和安全边界的理解,也耗体力,又看见是ruby写的,我瞬间都没想法了。