329
|
1 |
<stránka
|
|
2 |
xmlns="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/strana"
|
|
3 |
xmlns:m="https://trac.frantovo.cz/xml-web-generator/wiki/xmlns/makro">
|
|
4 |
|
|
5 |
<nadpis>Exploring content of X.509 certificates</nadpis>
|
|
6 |
<perex>open and query common SSL/TLS certificates or other ASN.1 data encoded in BER/DER/CER</perex>
|
|
7 |
<m:pořadí-příkladu>05000</m:pořadí-příkladu>
|
|
8 |
|
|
9 |
<text xmlns="http://www.w3.org/1999/xhtml">
|
|
10 |
|
|
11 |
<p>
|
|
12 |
X.509 certificates and keys used for SSL/TLS (HTTPS, POP3S, IMAPS etc.) are usually distributed as files either with <code>.pem</code> or <code>.der</code> extension.
|
|
13 |
Or bundled together in a PKCS#12 container as a <code>.p12</code> file.
|
|
14 |
The „text“ PEM format is often considered more „accessible“ or „friendly“ than the binary DER.
|
|
15 |
However PEM is just Base64 encoded DER original and is actually less legible to the naked eye than DER,
|
|
16 |
because in DER we can spot at least some strings like common and domain names or validity/expiration dates or recognize certain data structures in a HEX editor.
|
|
17 |
Base64 just obfuscates everything. PEM can be easily copied through clipboard, which is probably the only advantage of this format (but it can also more likely leak).
|
|
18 |
</p>
|
|
19 |
|
|
20 |
<!-- Indeed, Base64 is evil. Use hexadecimal encoding where ASCII representaion of binary data is necessary. -->
|
|
21 |
|
|
22 |
<p>
|
|
23 |
So our first step is to get rid of the annoying Base64 pseudo-plain-text encoding – we use one of these commands:
|
|
24 |
</p>
|
|
25 |
|
|
26 |
<m:pre jazyk="text"><![CDATA[cat certificate.pem | grep -v ^--- | base64 -d > certificate.der
|
|
27 |
cat certificate.pem | openssl x509 -inform PEM -outform DER > certificate.der]]></m:pre>
|
|
28 |
|
|
29 |
<p>
|
|
30 |
Telco veterans could now start reading the DER file with <code>hd</code> or <code>xxd</code>, jumping over the offsets and traversing the sequences and sets…
|
|
31 |
However most people would appreciate some software that helps them parsing the ASN.1 BER encoding (the superset of DER and CER).
|
|
32 |
Such software is e.g. Wireshark or dumpasn1. These programs are good for ad-hoc inspection or quick check.
|
|
33 |
</p>
|
|
34 |
|
|
35 |
<p>
|
|
36 |
In <m:name/> <m:a href="release-v0.18">v0.18</m:a> we have (early and bit raw) support for ASN.1 BER encoding and thus we can get the structured data in a machine-readable form
|
|
37 |
– which is good for further processing, conversion to other formats or use in scripts.
|
|
38 |
Because the ASN.1 data model is not relational – actually it is a tree – this format is supported in the <code>relpipe-in-asn1table</code>
|
|
39 |
command that is modelled after the well-known <code>XMLTable()</code> database function that allows translating arbitrary tree structures to relations using the XPath expressions.
|
|
40 |
So in <code>relpipe-in-asn1table</code> we can write XPath expressions to query the ASN.1 tree data structures and extract relations, records and attributes
|
|
41 |
from X.509 certificates, keys or other cryptographic artifacts, LDAP or SNMP packets or any other ASN.1 BER data.
|
|
42 |
</p>
|
|
43 |
|
|
44 |
<p>
|
|
45 |
But how do we know what XPath expressions should we run?
|
|
46 |
It is useful to see the XML representation of whole source data.
|
|
47 |
There is a simple trick to do this – use <code>"/"</code> as the XPath for selecting records (is always selects the single record, single node – the root)
|
|
48 |
and use <code>"."</code> as the XPath to select a single attribute (it always select the root element)
|
|
49 |
and add <code>--mode raw-xml</code>, so we get the raw XML source instead of the text content of given elements.
|
|
50 |
We do not have to write this routine by hand – just create a symlink to the example script:
|
|
51 |
</p>
|
|
52 |
<m:pre jazyk="bash"><![CDATA[ln -s …/relpipe-in-xmltable.cpp/examples/2xml.sh asn12xml # in ~/bin or somewhere]]></m:pre>
|
|
53 |
<p>
|
|
54 |
This example is generic and works also for other formats supported by the <code>relpipe-in-*table</code> commands.
|
|
55 |
</p>
|
|
56 |
|
|
57 |
<p>
|
|
58 |
Then we can analyze X.509 DER certificates stored on our disk or we can fetch some from live servers.
|
|
59 |
The <code>openssl</code> command helps us with that:
|
|
60 |
</p>
|
|
61 |
|
|
62 |
|
|
63 |
<m:pre jazyk="bash"><![CDATA[fetch_x509_certificate() {
|
|
64 |
echo \
|
|
65 |
| openssl s_client -connect $1:${2:-443} 2>/dev/null \
|
|
66 |
| openssl x509 -inform PEM -outform DER;
|
|
67 |
}]]></m:pre>
|
|
68 |
|
|
69 |
<p>Now put both commands together in a pipeline:</p>
|
|
70 |
|
|
71 |
<m:pre jazyk="bash"><![CDATA[fetch_x509_certificate "gnu.org" | asn12xml # HTTPS port (443) is used as default]]></m:pre>
|
|
72 |
|
|
73 |
<p>and get this XML representation of the ASN.1 X.509 tree:</p>
|
|
74 |
|
|
75 |
<m:pre jazyk="xml" src="examples/x509-gnu.org.xml"/>
|
|
76 |
|
|
77 |
|
|
78 |
<p>Once we know the structure, we can easily hack together a function that extracts parts of the tree as relations:</p>
|
|
79 |
|
|
80 |
<m:pre jazyk="bash"><![CDATA[parse_x509_certificate() {
|
|
81 |
relpipe-in-asn1table \
|
|
82 |
--relation 'validity' \
|
|
83 |
--records '//sequence[date-time][1]' \
|
|
84 |
--attribute 'from' string 'date-time[1]' \
|
|
85 |
--attribute 'to' string 'date-time[2]' \
|
|
86 |
--relation 'alternative_name' \
|
|
87 |
--records '//sequence[oid="2.5.29.17"][1]/encapsulated/sequence/specific' \
|
|
88 |
--attribute 'name' string '.';
|
|
89 |
}]]></m:pre>
|
|
90 |
|
|
91 |
<p>Everything put together:</p>
|
|
92 |
|
|
93 |
<m:pre jazyk="bash"><![CDATA[fetch_x509_certificate "gnu.org" | parse_x509_certificate | relpipe-out-tabular]]></m:pre>
|
|
94 |
|
|
95 |
<p>will print:</p>
|
|
96 |
|
|
97 |
<m:pre jazyk="text" src="examples/x509-gnu.org.txt"/>
|
|
98 |
|
|
99 |
<p>
|
|
100 |
The function above is just a „hello world“ example.
|
|
101 |
Please note that the XPath expressions need to be carefully crafted with respect to the given format in order to match exactly what we want.
|
|
102 |
</p>
|
|
103 |
|
|
104 |
<p>
|
|
105 |
Instead of printing a table, we can use the <code>relpipe-out-nullbyte</code> tool + the <code>read_nullbyte</code> function
|
|
106 |
and shell loop over the records (alternative names) and e.g. <code>ping</code> each domain or fetch given root web page using <code>wget</code> or <code>curl</code>.
|
|
107 |
We can also write a simple script that checks the validity of our own certificates and notifies us in advance when some of them are going to expire.
|
|
108 |
</p>
|
|
109 |
|
|
110 |
<p>
|
|
111 |
Later versions of <code>relpipe-in-asn1table</code> will probably support OID names, so it will not be necessary to use the numeric object identifiers.
|
|
112 |
</p>
|
|
113 |
|
|
114 |
<p>
|
|
115 |
n.b. there is also the <code>relpipe-in-asn1</code> – this tool reads data generated by its counterpart, the <code>relpipe-out-asn1</code> (or other ASN.1 BER capable software)
|
|
116 |
i.e. it is not as universal as <code>relpipe-in-asn1table</code>, it has simpler interface, needs no configuration and expects certain ASN.1 structures (relations serialized in BER format).
|
|
117 |
</p>
|
|
118 |
|
|
119 |
</text>
|
|
120 |
|
|
121 |
</stránka>
|