centos 绕过ssl
Almost all mobile applications communicate with a backend server, whether this is transmitting app data, backups, analytics; there is some sort of back and forth of data over wireless communication channels in mobile devices.
几乎所有的移动应用程序都与后端服务器通信,无论该后端服务器正在传输应用程序数据,备份,分析; 移动设备中的无线通信通道上存在某种来回的数据。
Most developers know that they need to use HTTPS, it is 2020 after all, but in mobile applications, this doesn’t go far enough. If you don’t check the server you’re communicating with is the one you’re expecting then how do you trust that the communication is secure and not being intercepted?
大多数开发人员知道他们需要使用HTTPS,毕竟这是2020年,但是在移动应用程序中,这还远远不够。 如果您不检查与之通信的服务器是否是您所期望的服务器,那么您如何相信通信是安全的并且不会被拦截?
If you don’t verify the server is the legitimate one, how do you know user communication is secure?
如果您不验证服务器是合法服务器,您如何知道用户通信是安全的?
问题与解决方案 (Problem and Solution)
The problem is Man in the Middle (MitM) attacks, which as the name suggests refers to some sort of malicious actor sitting in the middle of communications between the client (user/app) and the server. In this position it is possible to intercept, read and modify the traffic to and from the two end devices affecting the users confidentiality, and the integrity of the data. There are numerous ways that MitM can occur, this is not just limited to smart devices, however in the context of mobile one of the biggest threats are fake Android certificates or iOS device profiles.
问题是中间人(MitM)攻击,顾名思义,这是指某种恶意行为者坐在客户端(用户/应用)与服务器之间的通信中间。 在此位置,可以拦截,读取和修改往返于两个终端设备的流量,从而影响用户的机密性和数据的完整性。 MitM可以通过多种方式发生,这不仅限于智能设备,但是在移动环境中,最大的威胁之一是伪造的Android证书或iOS设备配置文件。
Luckily there is a solution to this problem, Certificate Pinning, or Public Key Pinning as its also commonly known. Pinning is where the app developers specify particular certificates to verify the legitimacy of the servers the app is connecting with to ensure they are trusted.
幸运的是,对于此问题,有一种解决方案,即证书固定或公钥固定,这也是众所周知的。 固定是应用程序开发人员指定特定证书的地方,以验证与应用程序连接的服务器的合法性,以确保它们受到信任。
We can trust backend servers with the use of Certificate/Public Key Pinning to provide validation.
我们可以使用证书/公钥固定来信任后端服务器以提供验证。
This method actually ‘pins’ either the certificate, or the a hash of the public key into the application and uses this to determine the trust of the server that it is connecting to, the server of course holding the private key of the PKI key pair. However, we’re security professionals, while its great to understand the theory of these concepts, we want to understand how we can break these security protections in order to access the underlying API calls. If we can break the certificate pinning, generally it’s possible to gain further footholds into the backend system to obtain a myriad of user data, not just the data of one single user.
此方法实际上将证书或公钥的哈希“固定”到应用程序中,并使用此方法确定它所连接的服务器的信任度,该服务器当然拥有PKI密钥对的私钥。 但是,我们是安全专业人员,虽然非常了解这些概念的理论,但我们想了解如何才能打破这些安全保护,以便访问底层的API调用。 如果我们可以打破证书固定,通常可以在后端系统中获得进一步的立足点,以获得无数的用户数据,而不仅仅是一个用户的数据。
We’re going to take a look at two examples of implementations of certificate pinning that have left flaws in the codebase which can be leveraged by malicious users to intercept this communication and access these behind the scenes API calls.
我们将看一下证书钉扎实现的两个示例,这些示例在代码库中留下了缺陷,恶意用户可以利用这些缺陷来拦截这种通信并在后台调用API调用。
固定绕过 (Pinning Bypasses)
We should note that SSL pinning presents a difficult challenge to bypass; there are multiple different ways an app can implement it, from standard Java APIs to entire libraries built around it. Once you identify how the app implements the pinning, the smali patch can be quite different, either easier or more sophisticated in certain circumstances. We will illustrate and discuss this in our examples.
我们应该注意,SSL固定带来了难以绕开的挑战。 从标准Java API到围绕它构建的整个库,应用都有多种不同的实现方式。 确定了应用程序如何实现固定后,smali补丁可能会大不相同,在某些情况下更容易或更复杂。 我们将在示例中对此进行说明和讨论。
空信任链 (Empty Trust Chain)
Java (Java)
In our first scenario the app was partially obfuscated and used the standard Java SSL pinning. This usually means the app implements a method named “checkServerTrusted()” to validate the backend and possibly “checkClientTrusted()” if client validation is also required by using a custom Trust Manager.
在我们的第一个场景中,该应用程序被部分混淆,并使用标准的Java SSL固定。 这通常意味着该应用程序实现了一种名为“ checkServerTrusted ()”的方法来验证后端,如果使用自定义信任管理器还需要进行客户端验证,则可能实现“ checkClientTrusted ()”。
public void checkServerTrusted(X509Certificate[] cert, String str)
Essentially the method authenticates the server side of the connection. The app provides the certificate as input, usually hardcoded somewhere in the app, and the implementation builds the certificate chain to the server and if trusted, returns a positive value, or in the case of a negative value, throws an Exception.
本质上,该方法对连接的服务器端进行身份验证。 该应用程序提供证书作为输入,通常在应用程序中的某个位置进行硬编码,并且实现将证书链构建到服务器,并且如果可信,则返回正值,或者在负值的情况下抛出异常。
The below method takes an array of X509 certificates ‘x509CertificateArr’, which are then iterated through with the Issuer and Subject names extracted and appended to a certificate chain String then validated and in case of “Pinning not found” an Exception is thrown.
下面的方法采用X509证书' x509CertificateArr '的数组,然后使用颁发者名称和主题名称进行迭代,并将其附加到证书链字符串中,然后对其进行验证,如果“未发现固定”,则抛出异常。
斯马里语 (Smali)
In the smali breakdown of this code block we can see the lower level representation, there are some similarities but also some nuances to take note of.
在此代码块的细目分解中,我们可以看到较低层的表示形式,既有一些相似之处,也有一些细微之处需要注意。
The method declaration contains standard smali, however we have:
方法声明包含标准的smali,但是我们有:
‘[‘ to signify an array for the input argument.
' [ '表示输入参数的数组。
‘L’ to show that the following item is an instance or class, in this case, X509Certificate.
“ L ”表示以下项目是实例或类,在这种情况下为X509Certificate。
‘;’ separates arguments
' ; '分隔参数
a String instance, again signified with an ‘L’
一个String实例,再次用' L '表示
- The method then returns void. 然后该方法返回void。
In this case, we can simply move the ‘return void’ statement to before the SSL pinning and String construction is even done. This means the certificate chain is never built, nor verified; however this also demonstrates another issue in play and problem with the logic. There is no error checking to verify that the trust chain was valid or even not null, it blindly accepts the return call and carries on communicating.
在这种情况下,我们可以简单地将“ return void”语句移至SSL固定和String构造完成之前。 这意味着证书链永远不会建立或验证。 但是,这也证明了另一个问题和逻辑问题。 没有错误检查来验证信任链是否有效,甚至不为空,它会盲目接受返回调用并继续进行通信。
修改存储的证书 (Modification of Stored Certificates)
Java (Java)
This next scenario covers a more complex implementation, but again, one that is flawed in the way it creates the certificate chain and introduces vulnerabilities against the SSL pinning.
下一个场景涵盖了一个更复杂的实现,但是同样,它在创建证书链和引入针对SSL固定的漏洞方面存在缺陷。
The SSL pinning was found to use a class implementing a method named init().
发现SSL固定使用实现了名为init()的方法的类。
The first step of the method consists of invoking another method named getCertificates(), which is shown just few lines below; line 140
该方法的第一步包括调用另一个名为getCertificates ()的方法,下面仅显示几行; 140行
2. The method getCertificates(), reads CA certificates that are stored as raw resources and returns them in a Java list of type certificate, List<Certificate>
2.方法getCertificates (),读取存储为原始资源的CA证书,并在Java类型的证书列表List <Certificate>中返回它们。
3. Back in init(), instantiate a Java Keystore and add each certificate in the list; lines 95–105
3.返回init (),实例化一个Java Keystore并将每个证书添加到列表中; 第95–105行
4. Once this Keystore is built, it is given to a Java TrustManager that will use it to initiate the SSL negotiation with Java SSL init() method; lines 105–107
4.构建此密钥库后 ,将其提供给Java TrustManager ,它将使用它通过Java SSL init ()方法启动SSL协商; 第105–107行
The method implicitly trusts what it’s provided with whether a real certificate, or our custom fake CA.
该方法隐式信任真实证书或自定义伪造CA所提供的内容。
From a security point of view this init() method is vulnerable because it entirely trusts the certificates that it is provided with, but doesn’t actually validate what these certificates are for when it is return by the method getCertificates(). Therefore, getCertificates() may return a null value, an empty list or, as we are about to show, our custom CA for the proxy tool.
从安全角度来看,此init ()方法很容易受到攻击,因为它完全信任所提供的证书,但实际上不会通过getCertificates ()方法返回这些证书的用途。 因此, getCertificates ()可能返回一个空值,一个空列表,或者,正如我们将要显示的那样,返回用于代理工具的自定义CA。
斯马里语 (Smali)
In the first portion of the method getCertificates() we can observe the method call returning a List object, Ljava/util/List; creating a CertificateFactory called cf on lines 354–358, then creating and instantiating the ArrayList at lines 362–367.
在方法getCertificates ()的第一部分中,我们可以观察到方法调用返回了一个List对象Ljava / util / List ; 在第354-358行创建一个名为cf的CertificateFactory,然后在362-367行创建并实例化ArrayList 。
What is also important to note here is that the list of Certificates, named certificates, is stored in variable v2, line 367.
这里还要注意的重要一点是,证书列表(称为certificate )存储在变量v2的第367行中。
Further down the code we can start to notice a pattern as to what the code is doing.
在代码的更下方,我们可以开始注意到有关代码在做什么的模式。
- Put a resource ID into a local variable. 将资源ID放入局部变量。
Make a call to openRawResource() with this ID; a reference to the certificate.
使用此ID调用openRawResource (); 对证书的引用。
Read using InputStream()
使用InputStream()读取
Append to the certificates List.
追加到证书列表。
Close the InputStream()
关闭InputStream()
This same pattern is repeated for each certificate and at the end of the method, the List stored in v2 is returned.
对每个证书重复相同的模式,并在方法结束时,返回存储在v2中的列表。
So this app is taking external input based off a resource ID from the resources folder and building a list of valid “trusted” certificates. What if we were to replace one of these certificates with our attacker controlled certificate?
因此,此应用程序从资源文件夹中获取基于资源ID的外部输入,并构建有效的“受信任”证书列表。 如果我们用攻击者控制的证书替换其中一个证书怎么办?
We can replace the contents of this ‘trusted’ certificate with our own fake CA.
我们可以用我们自己的伪造CA替换此“受信任”证书的内容。
Using the resource ID value that is stored as a constant we can find out what raw file it relates to using a simple command line. Once we have found the resource name, we can locate the raw resource and replace this certificate text with our own.
使用存储为常量的资源ID值,我们可以使用简单的命令行找出与之相关的原始文件。 找到资源名称后,我们可以找到原始资源,并用我们自己的证书文本替换。
What is important to note here is that the certificate might be called .cer but actually be a Base64 encoded DER, also known as PEM; and not the raw binary form of a certificate, (DER or CER).
这里需要注意的重要一点是,该证书可能称为.cer,但实际上是Base64编码的DER,也称为PEM。 而不是证书的原始二进制格式(DER或CER)。
In order to convert between raw binary certificates, cer and der, to Base64 encoded certificates, crt or pem, we can use OpenSSL. Once it’s in the correct format, we can overwrite the existing certificate.
为了在原始二进制证书cer和der之间转换为Base64编码的证书crt或pem ,我们可以使用OpenSSL。 格式正确后,我们可以覆盖现有证书。
openssl x509 -in proxyCert.der -inform DER -out proxyCertConvert.pem
As we have a real reference to our certificate and real code, all we need to do is to adjust the original logic of the smali. We only care about our certificate being loaded and we can ignore the rest.
由于我们真正地参考了证书和真实代码,因此我们所要做的就是调整smali的原始逻辑。 我们只关心证书的加载,我们可以忽略其余的证书。
Our certificate has already been opened and read into the InputStream v0 - line 389
我们的证书已经打开,并已读入InputStream v0-第389行
Generate the certificate using the CertificateFactory method generateCertificate(), and move this into v5 - line 390–392
生成使用CertificateFactory方法generateCertificate所 ()中的证书,并移动到这个V5 -线390-392
Add our generated cert, v5, to our certificates List, v2 -line 395
将我们生成的cert v5添加到我们的证书列表v2第 395行
Close the original InputStream - line 398
关闭原始的InputStream-第398行
Return the certificates List back to the calling method - line 400.
将证书列表返回到调用方法-第400行。
The rest of the smali code continues past this, however as we’ve already returned our
其余的smali代码将继续进行下去,但是由于我们已经返回了我们的代码
certificates List object it becomes unreachable code.
certificate List对象变成了无法访问的代码。
The application will only read in the certificate with our modified content inside it before being returned; the filename remains the same, we merely swapped out the text. As its implicitly trusted, the app continues its communication as normal whilst passing everything through our proxy tool due to accepting our CA.
该应用程序将仅在证书中包含我们修改后的内容时才将其读入; 文件名保持不变,我们只是交换了文本。 作为其隐含的信任,该应用程序继续正常进行通信,同时由于接受了我们的CA而将所有内容传递给我们的代理工具。
We have detailed two examples of how to bypass different implementations of Certificate Pinning, both with errors in how the protection was implemented, but shows how the smallest of flaws could be used by an attacker to push further into the system and investigate the API calls.
我们已经详细说明了两个示例,这些示例说明了如何绕过证书固定的不同实现,但都存在保护实现方式方面的错误,但是还说明了攻击者如何利用最小的缺陷将漏洞进一步推入系统并调查API调用。
The first example demonstrated a method where the trust chain was implicitly trusted with no further verification other than what the method was passed. There was no error handling or checking what was returned allowing a void return call.
第一个示例演示了一种方法,其中信任链被隐式信任,除了通过了什么方法之外,没有其他进一步的验证。 没有错误处理或检查返回了什么,从而允许进行无效的返回调用。
The second used stored application certificates within the app package, which as the mobile application is on the malicious user’s personal device is never a good idea; because as demonstrated, these can be replaced with something completely different to take advantage of code weaknesses.
第二个使用存储在应用程序包中的应用程序证书,因为移动应用程序位于恶意用户的个人设备上,这绝不是一个好主意; 因为如所示,可以用完全不同的东西替换这些东西以利用代码弱点。
Certificate pinning if used correctly can be an extensive way to protect the backend servers as well as the communication passed in client-server requests and responses. However, it should not be relied upon fully nor used as a reason to accept insecure development practises on the API, but used as part of a layered approach to mobile app network security.
证书固定(如果正确使用)是保护后端服务器以及客户端-服务器请求和响应中传递的通信的广泛方法。 但是,不应完全依赖它,也不应该将其用作接受API上不安全的开发实践的理由,而应用作移动应用程序网络安全性分层方法的一部分。
翻译自: https://levelup.gitconnected.com/bypassing-ssl-pinning-on-android-3c82f5c51d86
centos 绕过ssl