man-pages/man3/IO::Socket::SSL::Intercept.3pm.html
2021-03-31 01:06:50 +01:00

254 lines
9.2 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML><HEAD><TITLE>Man page of IO::Socket::SSL::Intercept</TITLE>
</HEAD><BODY>
<H1>IO::Socket::SSL::Intercept</H1>
Section: User Contributed Perl Documentation (3pm)<BR>Updated: 2020-02-14<BR><A HREF="#index">Index</A>
<A HREF="/cgi-bin/man/man2html">Return to Main Contents</A><HR>
<A NAME="lbAB">&nbsp;</A>
<H2>NAME</H2>
IO::Socket::SSL::Intercept -- SSL interception (man in the middle)
<A NAME="lbAC">&nbsp;</A>
<H2>SYNOPSIS</H2>
<PRE>
use IO::Socket::SSL::Intercept;
# create interceptor with proxy certificates
my $mitm = IO::Socket::SSL::Intercept-&gt;new(
proxy_cert_file =&gt; 'proxy_cert.pem',
proxy_key_file =&gt; 'proxy_key.pem',
...
);
my $listen = IO::Socket::INET-&gt;new( LocalAddr =&gt; .., Listen =&gt; .. );
while (1) {
# TCP accept new client
my $client = $listen-&gt;accept or next;
# SSL connect to server
my $server = IO::Socket::SSL-&gt;new(
PeerAddr =&gt; ..,
SSL_verify_mode =&gt; ...,
...
) or die &quot;ssl connect failed: $!,$SSL_ERROR&quot;;
# clone server certificate
my ($cert,$key) = $mitm-&gt;clone_cert( $server-&gt;peer_certificate );
# and upgrade client side to SSL with cloned certificate
IO::Socket::SSL-&gt;start_SSL($client,
SSL_server =&gt; 1,
SSL_cert =&gt; $cert,
SSL_key =&gt; $key
) or die &quot;upgrade failed: $SSL_ERROR&quot;;
# now transfer data between $client and $server and analyze
# the unencrypted data
...
}
</PRE>
<A NAME="lbAD">&nbsp;</A>
<H2>DESCRIPTION</H2>
This module provides functionality to clone certificates and sign them with a
proxy certificate, thus making it easy to intercept <FONT SIZE="-1">SSL</FONT> connections (man in the
middle). It also manages a cache of the generated certificates.
<A NAME="lbAE">&nbsp;</A>
<H2>How Intercepting SSL Works</H2>
Intercepting <FONT SIZE="-1">SSL</FONT> connections is useful for analyzing encrypted traffic for
security reasons or for testing. It does not break the end-to-end security of
<FONT SIZE="-1">SSL,</FONT> e.g. a properly written client will notice the interception unless you
explicitly configure the client to trust your interceptor.
Intercepting <FONT SIZE="-1">SSL</FONT> works the following way:
<DL COMPACT>
<DT id="1">&bull;<DD>
Create a new <FONT SIZE="-1">CA</FONT> certificate, which will be used to sign the cloned certificates.
This proxy <FONT SIZE="-1">CA</FONT> 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>
Using openssl such a proxy <FONT SIZE="-1">CA</FONT> certificate and private key can be created with:
<P>
<PRE>
openssl genrsa -out proxy_key.pem 1024
openssl req -new -x509 -extensions v3_ca -key proxy_key.pem -out proxy_cert.pem
# export as PKCS12 for import into browser
openssl pkcs12 -export -in proxy_cert.pem -inkey proxy_key.pem -out proxy_cert.p12
</PRE>
<DT id="2">&bull;<DD>
Configure client to connect to use intercepting proxy or somehow redirect
connections from client to the proxy (e.g. packet filter redirects, <FONT SIZE="-1">ARP</FONT> or <FONT SIZE="-1">DNS</FONT>
spoofing etc).
<DT id="3">&bull;<DD>
Accept the <FONT SIZE="-1">TCP</FONT> connection from the client, e.g. don't do any <FONT SIZE="-1">SSL</FONT> handshakes with
the client yet.
<DT id="4">&bull;<DD>
Establish the <FONT SIZE="-1">SSL</FONT> 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 <FONT SIZE="-1">CA.</FONT>
This is the step where IO::Socket::SSL::Intercept helps.
<DT id="5">&bull;<DD>
Upgrade the <FONT SIZE="-1">TCP</FONT> connection to the client to <FONT SIZE="-1">SSL</FONT> using the cloned certificate
from the server. If the client trusts your proxy <FONT SIZE="-1">CA</FONT> it will accept the upgrade
to <FONT SIZE="-1">SSL.</FONT>
<DT id="6">&bull;<DD>
Transfer data between client and server. While the connections to client and
server are both encrypted with <FONT SIZE="-1">SSL</FONT> you will read/write the unencrypted data in
your proxy application.
</DL>
<A NAME="lbAF">&nbsp;</A>
<H2>METHODS</H2>
IO::Socket::SSL::Intercept helps creating the cloned certificate with the
following methods:
<DL COMPACT>
<DT id="7"><B></B>$mitm<B> = IO::Socket::SSL::Intercept-&gt;new(%args)</B><DD>
This creates a new interceptor object. <TT>%args</TT> should be
<DL COMPACT><DT id="8"><DD>
<DL COMPACT>
<DT id="9">proxy_cert X509 | proxy_cert_file filename<DD>
This is the proxy certificate.
It can be either given by an X509 object from Net::SSLeays internal
representation, or using a file in <FONT SIZE="-1">PEM</FONT> format.
<DT id="10">proxy_key <FONT SIZE="-1">EVP_PKEY</FONT> | proxy_key_file filename<DD>
This is the key for the proxy certificate.
It can be either given by an <FONT SIZE="-1">EVP_PKEY</FONT> object from Net::SSLeays internal
representation, or using a file in <FONT SIZE="-1">PEM</FONT> format.
The key should not have a passphrase.
<DT id="11">pubkey <FONT SIZE="-1">EVP_PKEY</FONT> | pubkey_file filename<DD>
This optional argument specifies the public key used for the cloned certificate.
It can be either given by an <FONT SIZE="-1">EVP_PKEY</FONT> object from Net::SSLeays internal
representation, or using a file in <FONT SIZE="-1">PEM</FONT> format.
If not given it will create a new public key on each call of <TT>&quot;new&quot;</TT>.
<DT id="12">serial INTEGER|CODE<DD>
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 <TT>&quot;serial(original_cert,CERT_asHash(original_cert))&quot;</TT> and should
return the new serial number.
<DT id="13">cache <FONT SIZE="-1">HASH</FONT> | <FONT SIZE="-1">SUBROUTINE</FONT><DD>
This optional argument gives a way to cache created certificates, so that they
don't get recreated on future accesses to the same host.
If the argument ist not given an internal <FONT SIZE="-1">HASH</FONT> ist used.
<P>
If the argument is a hash it will store for each generated certificate a hash
reference with <TT>&quot;cert&quot;</TT> and <TT>&quot;atime&quot;</TT> in the hash, where <TT>&quot;atime&quot;</TT> is the time of
last access (to expire unused entries) and <TT>&quot;cert&quot;</TT> 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 <TT>&quot;ident&quot;</TT> either given to <TT>&quot;clone_cert&quot;</TT> or generated
from the original certificate.
<P>
If the argument is a subroutine it will be called as <TT>&quot;$cache-&gt;(ident,sub)&quot;</TT>.
This call should return either an existing (cached) <TT>&quot;(cert,key)&quot;</TT> or
call <TT>&quot;sub&quot;</TT> without arguments to create a new <TT>&quot;(cert,key)&quot;</TT>, store it
and return it.
If called with <TT>&quot;$cache-&gt;('type')&quot;</TT> 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.
</DL>
</DL>
<DL COMPACT><DT id="14"><DD>
</DL>
<DT id="15"><B>($clone_cert,$key) = </B>$mitm<B>-&gt;clone_cert($original_cert,[ </B>$ident<B> ])</B><DD>
This clones the given certificate.
An ident as the key into the cache can be given (like <TT>&quot;host:port&quot;</TT>), 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).
<DT id="16"><B></B>$string<B> = </B>$mitm<B>-&gt;serialize</B><DD>
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 <FONT SIZE="-1">HASH.</FONT>
To work together with Storable the <TT>&quot;STORABLE_freeze&quot;</TT> function is defined to
call <TT>&quot;serialize&quot;</TT>.
<DT id="17"><B></B>$mitm<B> = IO::Socket::SSL::Intercept-&gt;unserialize($string)</B><DD>
This restores an Intercept object from a serialized string.
To work together with Storable the <TT>&quot;STORABLE_thaw&quot;</TT> function is defined to
call <TT>&quot;unserialize&quot;</TT>.
</DL>
<A NAME="lbAG">&nbsp;</A>
<H2>AUTHOR</H2>
Steffen Ullrich
<P>
<HR>
<A NAME="index">&nbsp;</A><H2>Index</H2>
<DL>
<DT id="18"><A HREF="#lbAB">NAME</A><DD>
<DT id="19"><A HREF="#lbAC">SYNOPSIS</A><DD>
<DT id="20"><A HREF="#lbAD">DESCRIPTION</A><DD>
<DT id="21"><A HREF="#lbAE">How Intercepting SSL Works</A><DD>
<DT id="22"><A HREF="#lbAF">METHODS</A><DD>
<DT id="23"><A HREF="#lbAG">AUTHOR</A><DD>
</DL>
<HR>
This document was created by
<A HREF="/cgi-bin/man/man2html">man2html</A>,
using the manual pages.<BR>
Time: 00:05:46 GMT, March 31, 2021
</BODY>
</HTML>