{"id":6805,"date":"2022-12-20T19:33:40","date_gmt":"2022-12-20T22:33:40","guid":{"rendered":"http:\/\/lode.uno\/linux-man\/index.php\/2022\/12\/20\/iosocketsslintercept-man3\/"},"modified":"2022-12-20T19:33:40","modified_gmt":"2022-12-20T22:33:40","slug":"iosocketsslintercept-man3","status":"publish","type":"post","link":"https:\/\/lode.uno\/linux-man\/2022\/12\/20\/iosocketsslintercept-man3\/","title":{"rendered":"IO::Socket::SSL::Intercept (man3)"},"content":{"rendered":"<h1 align=\"center\">IO::Socket::SSL::Intercept<\/h1>\n<p> <a href=\"#NAME\">NAME<\/a><br \/> <a href=\"#SYNOPSIS\">SYNOPSIS<\/a><br \/> <a href=\"#DESCRIPTION\">DESCRIPTION<\/a><br \/> <a href=\"#How Intercepting SSL Works\">How Intercepting SSL Works<\/a><br \/> <a href=\"#METHODS\">METHODS<\/a><br \/> <a href=\"#AUTHOR\">AUTHOR<\/a> <\/p>\n<hr>\n<h2>NAME <a name=\"NAME\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">IO::Socket::SSL::Intercept \u2212\u2212 SSL interception (man in the middle)<\/p>\n<h2>SYNOPSIS <a name=\"SYNOPSIS\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">use IO::Socket::SSL::Intercept; <br \/> # create interceptor with proxy certificates <br \/> my $mitm = IO::Socket::SSL::Intercept\u2212>new( <br \/> proxy_cert_file => &#8216;proxy_cert.pem&#8217;, <br \/> proxy_key_file => &#8216;proxy_key.pem&#8217;, <br \/> &#8230; <br \/> ); <br \/> my $listen = IO::Socket::INET\u2212>new( LocalAddr => .., Listen => .. ); <br \/> while (1) { <br \/> # TCP accept new client <br \/> my $client = $listen\u2212>accept or next; <br \/> # SSL connect to server <br \/> my $server = IO::Socket::SSL\u2212>new( <br \/> PeerAddr => .., <br \/> SSL_verify_mode => &#8230;, <br \/> &#8230; <br \/> ) or die &#8220;ssl connect failed: $!,$SSL_ERROR&#8221;; <br \/> # clone server certificate <br \/> my ($cert,$key) = $mitm\u2212>clone_cert( $server\u2212>peer_certificate ); <br \/> # and upgrade client side to SSL with cloned certificate <br \/> IO::Socket::SSL\u2212>start_SSL($client, <br \/> SSL_server => 1, <br \/> SSL_cert => $cert, <br \/> SSL_key => $key <br \/> ) or die &#8220;upgrade failed: $SSL_ERROR&#8221;; <br \/> # now transfer data between $client and $server and analyze <br \/> # the unencrypted data <br \/> &#8230; <br \/> }<\/p>\n<h2>DESCRIPTION <a name=\"DESCRIPTION\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">This module provides functionality to clone certificates and sign them with a proxy certificate, thus making it easy to intercept <small>SSL<\/small> connections (man in the middle). It also manages a cache of the generated certificates.<\/p>\n<h2>How Intercepting SSL Works <a name=\"How Intercepting SSL Works\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">Intercepting <small>SSL<\/small> connections is useful for analyzing encrypted traffic for security reasons or for testing. It does not break the end-to-end security of <small>SSL,<\/small> e.g. a properly written client will notice the interception unless you explicitly configure the client to trust your interceptor. Intercepting <small>SSL<\/small> works the following way:<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p>\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"83%\">\n<p>Create a new <small>CA<\/small> certificate, which will be used to sign the cloned certificates. This proxy <small>CA<\/small> certificate should be trusted by the client, or (a properly written client) will throw error messages or deny the connections because it detected a man in the middle attack. Due to the way the interception works there no support for client side certificates is possible.<\/p>\n<\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">Using openssl such a proxy <small>CA<\/small> certificate and private key can be created with:<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">openssl genrsa \u2212out proxy_key.pem 1024 <br \/> openssl req \u2212new \u2212x509 \u2212extensions v3_ca \u2212key proxy_key.pem \u2212out proxy_cert.pem <br \/> # export as PKCS12 for import into browser <br \/> openssl pkcs12 \u2212export \u2212in proxy_cert.pem \u2212inkey proxy_key.pem \u2212out proxy_cert.p12<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p style=\"margin-top: 1em\">\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"83%\">\n<p style=\"margin-top: 1em\">Configure client to connect to use intercepting proxy or somehow redirect connections from client to the proxy (e.g. packet filter redirects, <small>ARP<\/small> or <small>DNS<\/small> spoofing etc).<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p>\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"83%\">\n<p>Accept the <small>TCP<\/small> connection from the client, e.g. don\u2019t do any <small>SSL<\/small> handshakes with the client yet.<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p>\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"83%\">\n<p>Establish the <small>SSL<\/small> connection to the server and verify the servers certificate as usually. Then create a new certificate based on the original servers certificate, but signed by your proxy <small>CA.<\/small> This is the step where IO::Socket::SSL::Intercept helps.<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p>\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"83%\">\n<p>Upgrade the <small>TCP<\/small> connection to the client to <small>SSL<\/small> using the cloned certificate from the server. If the client trusts your proxy <small>CA<\/small> it will accept the upgrade to <small>SSL.<\/small><\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p>\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"83%\">\n<p>Transfer data between client and server. While the connections to client and server are both encrypted with <small>SSL<\/small> you will read\/write the unencrypted data in your proxy application.<\/p>\n<\/td>\n<\/tr>\n<\/table>\n<h2>METHODS <a name=\"METHODS\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">IO::Socket::SSL::Intercept helps creating the cloned certificate with the following methods: <b><br \/> $mitm = IO::Socket::SSL::Intercept\u2212>new(%args)<\/b><\/p>\n<p style=\"margin-left:17%;\">This creates a new interceptor object. %args should be <br \/> proxy_cert X509 | proxy_cert_file filename<\/p>\n<p style=\"margin-left:29%;\">This is the proxy certificate. It can be either given by an X509 object from Net::SSLeays internal representation, or using a file in <small>PEM<\/small> format.<\/p>\n<p style=\"margin-left:17%;\">proxy_key <small>EVP_PKEY<\/small> | proxy_key_file filename<\/p>\n<p style=\"margin-left:29%;\">This is the key for the proxy certificate. It can be either given by an <small>EVP_PKEY<\/small> object from Net::SSLeays internal representation, or using a file in <small>PEM<\/small> format. The key should not have a passphrase.<\/p>\n<p style=\"margin-left:17%;\">pubkey <small>EVP_PKEY<\/small> | pubkey_file filename<\/p>\n<p style=\"margin-left:29%;\">This optional argument specifies the public key used for the cloned certificate. It can be either given by an <small>EVP_PKEY<\/small> object from Net::SSLeays internal representation, or using a file in <small>PEM<\/small> format. If not given it will create a new public key on each call of &#8220;new&#8221;.<\/p>\n<p style=\"margin-left:17%;\">serial INTEGER|CODE<\/p>\n<p style=\"margin-left:29%;\">This optional argument gives the starting point for the serial numbers of the newly created certificates. If not set the serial number will be created based on the digest of the original certificate. If the value is code it will be called with &#8220;serial(original_cert,CERT_asHash(original_cert))&#8221; and should return the new serial number.<\/p>\n<p style=\"margin-left:17%;\">cache <small>HASH<\/small> | <small>SUBROUTINE<\/small><\/p>\n<p style=\"margin-left:29%;\">This optional argument gives a way to cache created certificates, so that they don\u2019t get recreated on future accesses to the same host. If the argument ist not given an internal <small>HASH<\/small> ist used.<\/p>\n<p style=\"margin-left:29%; margin-top: 1em\">If the argument is a hash it will store for each generated certificate a hash reference with &#8220;cert&#8221; and &#8220;atime&#8221; in the hash, where &#8220;atime&#8221; is the time of last access (to expire unused entries) and &#8220;cert&#8221; is the certificate. Please note, that the certificate is in Net::SSLeays internal X509 format and can thus not be simply dumped and restored. The key for the hash is an &#8220;ident&#8221; either given to &#8220;clone_cert&#8221; or generated from the original certificate.<\/p>\n<p style=\"margin-left:29%; margin-top: 1em\">If the argument is a subroutine it will be called as &#8220;$cache\u2212>(ident,sub)&#8221;. This call should return either an existing (cached) &#8220;(cert,key)&#8221; or call &#8220;sub&#8221; without arguments to create a new &#8220;(cert,key)&#8221;, store it and return it. If called with &#8220;$cache\u2212>(&#8216;type&#8217;)&#8221; the function should just return 1 to signal that it supports the current type of cache. If it reutrns nothing instead the older cache interface is assumed for compatibility reasons.<\/p>\n<p style=\"margin-left:11%;\"><b>($clone_cert,$key) = $mitm\u2212>clone_cert($original_cert,[ $ident ])<\/b><\/p>\n<p style=\"margin-left:17%;\">This clones the given certificate. An ident as the key into the cache can be given (like &#8220;host:port&#8221;), if not it will be created from the properties of the original certificate. It returns the cloned certificate and its key (which is the same for alle created certificates).<\/p>\n<p style=\"margin-left:11%;\"><b>$string = $mitm\u2212>serialize<\/b><\/p>\n<p style=\"margin-left:17%;\">This creates a serialized version of the object (e.g. a string) which can then be used to persistantly store created certificates over restarts of the application. The cache will only be serialized if it is a <small>HASH.<\/small> To work together with Storable the &#8220;STORABLE_freeze&#8221; function is defined to call &#8220;serialize&#8221;.<\/p>\n<p style=\"margin-left:11%;\"><b>$mitm = IO::Socket::SSL::Intercept\u2212>unserialize($string)<\/b><\/p>\n<p style=\"margin-left:17%;\">This restores an Intercept object from a serialized string. To work together with Storable the &#8220;STORABLE_thaw&#8221; function is defined to call &#8220;unserialize&#8221;.<\/p>\n<h2>AUTHOR <a name=\"AUTHOR\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">Steffen Ullrich<\/p>\n<hr>\n","protected":false},"excerpt":{"rendered":"<p>  IO::Socket::SSL::Intercept \u2212\u2212 SSL interception (man in the middle) <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[3173,3007],"class_list":["post-6805","post","type-post","status-publish","format-standard","hentry","category-sin-categoria","tag-iosocketsslintercept","tag-man3"],"gutentor_comment":0,"_links":{"self":[{"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/posts\/6805","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/comments?post=6805"}],"version-history":[{"count":0,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/posts\/6805\/revisions"}],"wp:attachment":[{"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/media?parent=6805"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/categories?post=6805"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/tags?post=6805"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}