{"id":61170,"date":"2024-04-10T10:12:40","date_gmt":"2024-04-10T04:42:40","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=61170"},"modified":"2024-04-12T10:25:08","modified_gmt":"2024-04-12T04:55:08","slug":"prevent-mitm-attack-by-ssl-public-key-pinning-part-2","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/prevent-mitm-attack-by-ssl-public-key-pinning-part-2\/","title":{"rendered":"Prevent MITM Attack by SSL Public Key Pinning : Part &#8211; 2"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">In this blog, we are going to learn about public key pinning and how we can achieve it with URLSession.\u00a0<\/span><span style=\"font-weight: 400;\">Before that, let&#8217;s briefly discuss<\/span><span style=\"font-weight: 400;\">\u00a0SSL certificate pinning.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">SSL pinning is a security technique used in mobile and web applications to ensure that the client only communicates with servers via a specific SSL certificate or public key, which prevents man-in-the-middle attacks where an attacker intercepts communication between the client and the server.<\/span><\/p>\n<h2><b>How does MITM work?<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Hackers use MITM attacks to access confidential personal information by pretending to be known users or webpages. They spy on users&#8217; private meetings or confidential data and extract useful information.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-58460 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/MITM-Image.png\" alt=\"\" width=\"2835\" height=\"1749\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/09\/MITM-Image.png 2835w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/MITM-Image-300x185.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/MITM-Image-1024x632.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/MITM-Image-768x474.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/MITM-Image-1536x948.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/MITM-Image-2048x1263.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/09\/MITM-Image-624x385.png 624w\" sizes=\"(max-width: 2835px) 100vw, 2835px\" \/><\/p>\n<h2><b>Real-life Instances of MITM Attack\u00a0<\/b><\/h2>\n<p><b>In previous blog, we performed certificate pinning <span style=\"font-weight: 400;\">(<a href=\"https:\/\/www.tothenew.com\/blog\/prevent-mitm-attack-by-ssl-pinning-urlsession\/\"><span style=\"color: #ff0000;\">Check out this link for more.<\/span><\/a>)<\/span>, here are the differences and benefits:<\/b><\/p>\n<h2><b>Benefits:<\/b><\/h2>\n<ol>\n<li><span style=\"font-weight: 400;\"> Certificate Pinning : Add an SSL certificate to your app bundle and bind this certificate to your application.\u00a0<\/span><\/li>\n<\/ol>\n<ol start=\"2\">\n<li><span style=\"font-weight: 400;\"> Public Key Pinning: In this pinning method, we are going to generate a public key, which we are going to use in our application. In this method, we don\u2019t have to change the certificate if it expires.<\/span><\/li>\n<\/ol>\n<h2><b>Certificate pinning is easy to implement but has some limitations:<\/b><\/h2>\n<ol>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">When the certificate expires, we need to update it, and then we can release the app with the newer one, which results in less flexibility when we are using it.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">The app will not work when the backend or server changes the certificate on their end, unless we replace the certificate with a new one.<\/span><\/li>\n<\/ol>\n<h2><b>Let&#8217;s start:<\/b><\/h2>\n<p><b>Now, we are going to download the certificate using OpenSSL command:<\/b><\/p>\n<ol>\n<li><span style=\"font-weight: 400;\"> We need a copy of the certificate from the server, <\/span><b>isro.vercel.app.<\/b><span style=\"font-weight: 400;\"> Now we are going to use the terminal using OpenSSL commands.<\/span><\/li>\n<li><span style=\"font-weight: 400;\">It is safer to use public key pinning because it will not affect the application&#8217;s working if there is any change from the server side until the server maintains the same public key.<\/span><\/li>\n<\/ol>\n<p>Let&#8217;s check out these steps:<\/p>\n<p><span style=\"font-weight: 400;\">\u25d9 We can fetch the local certificate\u2019s public key, which has been downloaded and will be included in your code as a string. The app is going to compare the remote public key, which will be received during a network request at run time, with the local one, which is stored somewhere in the project as a string.<\/span><\/p>\n<p>\u25d9 Use this command to download this to the project bundle.<\/p>\n<pre><span style=\"color: #333333;\"><span style=\"color: #333333;\"><em><strong>openssl s_client -connect isro.vercel.app:443 -showcerts &lt; \/dev\/null | openssl x509 -outform der &gt; vercel.der<\/strong><\/em><\/span><\/span><\/pre>\n<p>Use the above command on the terminal.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-61164 size-full\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.17.56\u202fPM.png\" alt=\"\" width=\"3020\" height=\"512\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.17.56\u202fPM.png 3020w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.17.56\u202fPM-300x51.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.17.56\u202fPM-1024x174.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.17.56\u202fPM-768x130.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.17.56\u202fPM-1536x260.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.17.56\u202fPM-2048x347.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.17.56\u202fPM-624x106.png 624w\" sizes=\"(max-width: 3020px) 100vw, 3020px\" \/><\/p>\n<p>\u25d9 Then, we need to create .pem<span style=\"font-weight: 400;\">\u00a0from the downloaded <\/span><b>vercel.der<\/b><span style=\"font-weight: 400;\"> and convert it to the<\/span><b> vercel_public_key.pem<\/b><span style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"> format by extracting and saving its public key. Use the below commands to get it done.\u00a0<\/span><\/span><\/p>\n<pre><em><strong>\u00a0 openssl x509 -inform der -in vercel.der -pubkey -noout &gt;\u00a0 vercel_public_key.pem<\/strong><\/em><\/pre>\n<p><b>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0Or,<\/b><\/p>\n<pre><em><strong>\u00a0openssl x509 -inform der -in vercel.cer -pubkey -noout &gt; vercel_public_key.pem<\/strong><\/em><\/pre>\n<p><span style=\"font-weight: 400;\">\u25d9 After saving the .pem file, generate a hash and encode it using base64 encoding. Here, we can use this command, which is much easier to save and more readable. For hashing, I\u2019m going to use SHA256. Use the command below to generate the hash<\/span><\/p>\n<pre><em style=\"font-family: Consolas, Monaco, monospace;\"><strong>cat vercel_public_key.pem | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64<\/strong><\/em><\/pre>\n<p><em><strong><span style=\"color: #333333;\">Use the above command on the terminal.\u00a0<\/span><\/strong><\/em><\/p>\n<p><em><strong><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-61165\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.18.56\u202fPM.png\" alt=\"\" width=\"3046\" height=\"208\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.18.56\u202fPM.png 3046w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.18.56\u202fPM-300x20.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.18.56\u202fPM-1024x70.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.18.56\u202fPM-768x52.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.18.56\u202fPM-1536x105.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.18.56\u202fPM-2048x140.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.18.56\u202fPM-624x43.png 624w\" sizes=\"(max-width: 3046px) 100vw, 3046px\" \/>  <\/strong><\/em><\/p>\n<p><span style=\"font-weight: 400;\">Your public key will be something like this<\/span><\/p>\n<p><strong>u\/joKCLcfT2khmv\/jPpWcsbUx1mBQ1PY0QXYg5cHonE=<\/strong><\/p>\n<p><b>Or,<\/b><\/p>\n<p><span style=\"font-weight: 400;\">We can use the below command to do all these processes in one command (I have used <\/span><b>isro.vercel.app<\/b><span style=\"font-weight: 400;\"> for this sample project). It will generate the hash code from the certificate, which we will use in our demo project.<\/span><\/p>\n<pre><em><strong>openssl s_client -servername isro.vercel.app -connect\u00a0 isro.vercel.app:443 | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64<\/strong><\/em><\/pre>\n<p><em><strong><span style=\"color: #333333;\">Use the above command on the terminal. <\/span><\/strong><\/em><\/p>\n<p><em><strong><span style=\"color: #333333;\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-61166 size-full\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.50.50\u202fPM.png\" alt=\"\" width=\"3044\" height=\"582\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.50.50\u202fPM.png 3044w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.50.50\u202fPM-300x57.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.50.50\u202fPM-1024x196.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.50.50\u202fPM-768x147.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.50.50\u202fPM-1536x294.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.50.50\u202fPM-2048x392.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-03-29-at-11.50.50\u202fPM-624x119.png 624w\" sizes=\"(max-width: 3044px) 100vw, 3044px\" \/> <\/span><\/strong><\/em><\/p>\n<p><span style=\"font-weight: 400;\">Now we are ready with a hash key. It\u2019s time to write some code now. Put the code below in our <\/span><b>NetworkManagerWithPublicKey.swift<\/b><span style=\"font-weight: 400;\"> class.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-61167\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.02.12\u202fPM.png\" alt=\"\" width=\"2534\" height=\"1040\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.02.12\u202fPM.png 2534w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.02.12\u202fPM-300x123.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.02.12\u202fPM-1024x420.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.02.12\u202fPM-768x315.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.02.12\u202fPM-1536x630.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.02.12\u202fPM-2048x841.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.02.12\u202fPM-624x256.png 624w\" sizes=\"(max-width: 2534px) 100vw, 2534px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">Here,<\/span> <b>localPublicKey<\/b> <span style=\"font-weight: 400;\">is the hash key that we get from our certificate.<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">An array of unsigned integers, which indicates the algorithm and any algorithm parameters with which the public key is to be used, is represented by <\/span><b>rsa2048Asn1Header<\/b><span style=\"font-weight: 400;\">.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Let&#8217;s check this method; we used the OpenSSL-sdgst function with <\/span><b>sha256<\/b><span style=\"font-weight: 400;\"> hashing to create our hashes. To recreate the same hashes in our code, the <\/span><b>rsa2048Asn1Header<\/b><span style=\"font-weight: 400;\"> bytes are needed.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">This function will create a hash from the received Data using the <\/span><b>sha256<\/b><span style=\"font-weight: 400;\"> algorithm and return the base64 encoded representation of the hash.<\/span><\/li>\n<\/ol>\n<p><span style=\"font-weight: 400;\">And now, we have to implement the URLSessionDelegate function. Please see the code below. Please check out the screenshots attached.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-61168 size-full\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.03.37\u202fPM.png\" alt=\"\" width=\"1836\" height=\"1796\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.03.37\u202fPM.png 1836w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.03.37\u202fPM-300x293.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.03.37\u202fPM-1024x1002.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.03.37\u202fPM-768x751.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.03.37\u202fPM-1536x1503.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.03.37\u202fPM-624x610.png 624w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.03.37\u202fPM-24x24.png 24w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.03.37\u202fPM-48x48.png 48w\" sizes=\"(max-width: 1836px) 100vw, 1836px\" \/> <img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-61169\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.05.10\u202fPM.png\" alt=\"\" width=\"1834\" height=\"1188\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.05.10\u202fPM.png 1834w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.05.10\u202fPM-300x194.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.05.10\u202fPM-1024x663.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.05.10\u202fPM-768x497.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.05.10\u202fPM-1536x995.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2024\/04\/Screenshot-2024-04-01-at-11.05.10\u202fPM-624x404.png 624w\" sizes=\"(max-width: 1834px) 100vw, 1834px\" \/><\/p>\n<p><b>Summary:<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Nowadays, it is mandatory to implement SSL\/TLS while communicating with the server. We rely on a chain of trust to verify the identity of the client or server, which is not enough; MITM (Man in the Middle) attacks may still be a possibility. So what we do is add layer of protection by adding a certificate or public key, which is needed on the other side as well. We&#8217;ve learned how to extract a server key and implement pinning on iOS.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">I have written the code in <\/span><b>Swift<\/b><span style=\"font-weight: 400;\"> language. Feel free to comment below with any queries. You can access the complete code at <\/span><span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/github.com\/Vibhashkumar2022\"><b>GitHub<\/b><\/a><\/span><span style=\"font-weight: 400;\"><span style=\"color: #ff0000;\">.<\/span> You can check this URL:\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Part-1 Certificate Pinning: <\/span><span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/github.com\/Vibhashkumar2022\/SSLPinningUsingURLSession\"><b>https:\/\/github.com\/Vibhashkumar2022\/SSLPinningUsingURLSession.<\/b><\/a><b>\u00a0<\/b><\/span><\/p>\n<p><span style=\"font-weight: 400;\">Part-2 Public Key Pinning:<\/span><span style=\"font-weight: 400;\">\u00a0 <\/span><span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/github.com\/Vibhashkumar2022\/MITM-Project-Part-2\"><b>https:\/\/github.com\/Vibhashkumar2022\/MITM-Project-Part-2<\/b><\/a><\/span><\/p>\n<p><b>Note: The certificate added in my repository can expire, so if you are not able to get a response from API, then check for the certificate and get a new one by following the above steps<\/b><span style=\"color: #333333;\"><em><strong><br \/>\n<\/strong><\/em><\/span><\/p>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>In this blog, we are going to learn about public key pinning and how we can achieve it with URLSession.\u00a0Before that, let&#8217;s briefly discuss\u00a0SSL certificate pinning. SSL pinning is a security technique used in mobile and web applications to ensure that the client only communicates with servers via a specific SSL certificate or public key, [&hellip;]<\/p>\n","protected":false},"author":1630,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":115},"categories":[2026,1400,1772],"tags":[5797,5796,2574,5794,5795],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/61170"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1630"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=61170"}],"version-history":[{"count":2,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/61170\/revisions"}],"predecessor-version":[{"id":61264,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/61170\/revisions\/61264"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=61170"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=61170"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=61170"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}