Security problems caused by mobile bank https certificate validity Verification
Preface:
In the actual project code audit, it is found that many mobile banking currently Use https communication, but it is only a simple call and does not verify the validity of the SSL certificate. In the opinion of the attacker, this vulnerability makes https useless and can easily obtain the plaintext communication information of mobile phone users.
In order to solve the problem of ssl Certificate error during the development process (after using the self-generated certificate, the client finds that the certificate cannot form a trust chain with the Trusted Root CA of the system, exceptions such as CertificateException occur .), All the certificates in the client are trusted in the client code:
Public static HttpClient getWapHttpClient () {try {KeyStore trustStore = KeyStore. getInstance (KeyStore. getDefaultType (); trustStore. load (null, null); SSLSocketFactory sf = new MySSLSocketFactory (trustStore); sf. setHostnameVerifier (SSLSocketFactory. ALLOW_ALL_HOSTNAME_VERIFIER); // all certificates in the mobile phone, including third-party certificates installed by the user HttpParams params = new BasicHttpParams (); HttpProtocolParams. setVersion (params, HttpVersion. HTTP_1_1); HttpProtocolParams. setContentCharset (params, HTTP. UTF_8); SchemeRegistry registry = new SchemeRegistry (); registry. register (new Scheme ("http", PlainSocketFactory. getSocketFactory (), 80); registry. register (new Scheme ("https", sf, 443); ClientConnectionManager ccm = new ThreadSafeClientConnManager (params, registry); return new DefaultHttpClient (ccm, params );} catch (Exception e) {return new DefaultHttpClient ();}}
Google's default certificate check mechanism (X509TrustManager) is overwritten on the client, and no code is provided to verify the SSL certificate validity in the Code:
Public class MySSLSocketFactory extends SSLSocketFactory {SSLContext sslContext = SSLContext. getInstance ("TLS"); public MySSLSocketFactory (KeyStore truststore) throws exception, KeyManagementException, KeyStoreException, UnrecoverableKeyException {super (truststore); TrustManager tm = new X509TrustManager () {public void checkClientTrusted (X509Certificate [] chain, String authType) throws CertificateException {} // the client does not verify the validity of the SSL certificate, the custom method is used to overwrite the self-built android verification method public void checkServerTrusted (X509Certificate [] chain, String authType) throws CertificateException {} public X509Certificate [] getAcceptedIssuers () {return null ;}}; sslContext. init (null, new TrustManager [] {tm}, null );}
The problem arises:
If a malicious certificate is installed on your mobile phone, you can intercept user communication and modify the data in the request or response through man-in-the-middle attacks.
Mobile bank man-in-the-middle attack process:
1. When the client is started, a handshake must be performed between the client and the server before data transmission. During the handshake, the password information of both parties for data transmission is encrypted.
2. In this process, the man-in-the-middle intercepts the handshake information of the client request server and simulates the client request to the server (send a set of encryption rules supported by him to the server ), the server selects a set of encryption algorithms and HASH algorithms, and sends the identity information to the client in the form of a certificate. The certificate contains the website address, the encrypted public key, and the certificate authority.
3. At this time, the man-in-the-middle will intercept the certificate information returned by the server to the client and replace it with your own certificate information.
4. After the client obtains the man-in-the-middle response, it will select the man-in-the-middle certificate for encrypted data transmission.
5. After obtaining the request data from the client, the man-in-the-middle decrypts the data with his own certificate.
6. After listening or modifying the request data, simulate the client to encrypt the request data and send it to the server. This completes the entire man-in-the-middle attack process.
The following uses the fiddler tool to simulate man-in-the-middle attacks:
1. First install the fiddler root certificate on your mobile phone:
Export the root certificate of fiddler:
Put the fiddler root certificate into the SD card of the mobile phone, and then choose "Mobile Phone settings-Security" to install the certificate from the SD card:
Install the fiddler root certificate on your mobile phone:
2. Enable fiddler on the PC side and send the mobile phone communication proxy to the port listened to by fiddler on the PC side (you can set proxy in advanced settings in wifi ), in this way, all communications of mobile banking will be monitored by fiddler.
3. Start the mobile banking client and view the plain text data of all requests in fiddler. You can modify the request and forward it. https encryption is successfully bypassed.
Protection methods:
It is feasible to use a CA to issue certificates, but if combined with the actual situation, the time and cost are too high, so this method is rarely used at present. Because the mobile banking server is actually fixed, the certificate is also fixed. You can use the "Certificate or public key lock" method to protect the certificate validity from being verified.
Specific implementation:
1. The public key is locked and the public key of the certificate is written to the client apk. During https communication, check whether the public key of the certificate is consistent with that in the apk.
Public final class PubKeyManager implements X509TrustManager {private static String PUB_KEY = "30820122300d06092a864886f70d0101" + "comment" + "Certificate" + "certificate"; // lock the certificate public Key in the apk public void checkServerTrusted (X509Certificate [] chain, String auth Type) throws CertificateException {if (chain = null) {throw new IllegalArgumentException ("checkServerTrusted: X509Certificate array is null");} if (! (Chain. length> 0) {throw new IllegalArgumentException ("checkServerTrusted: X509Certificate is empty");} if (! (Null! = AuthType & authType. equalsIgnoreCase ("RSA") {throw new CertificateException ("checkServerTrusted: AuthType is not RSA");} // Perform customary SSL/TLS checkstry {TrustManagerFactory tmf = TrustManagerFactory. getInstance ("X509"); tmf. init (KeyStore) null); for (TrustManager trustManager: tmf. getTrustManagers () {(X509TrustManager) trustManager ). checkServerTrusted (chain, authType) ;}} catch (Login T Ion e) {throw new CertificateException (e);} // Hack ahead: BigInteger and toString (). we know a DER encoded Public Key begins // with 0 × 30 (ASN.1 SEQUENCE and CONSTRUCTED), so there is no leading 0 × 00 to drop. RSAPublicKey pubkey = (RSAPublicKey) chain [0]. getPublicKey (); String encoded = new BigInteger (1/* positive */, pubkey. getEncoded ()). toString (16); // Pin it! Final boolean expected = pub_key.inclusignorecase (encoded); if (! Expected) {throw new CertificateException ("checkServerTrusted: Expected public key:" + PUB_KEY + ", got public key:" + encoded );}}}}
2 certificate lock:
A Public Key Certificate is issued to the client and stored in the mobile client. During https communication, the certificate information is fixed in the client code instead of obtained from the server.
For more information about certificate or public key locking technology, see the following link:
Https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning