从SSL对象获取SSL证书信息 - BUG? [英] Obtaining SSL certificate info from SSL object - BUG?

查看:139
本文介绍了从SSL对象获取SSL证书信息 - BUG?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Python SSL对象提供了两种从SSL证书获取信息的方法,server()和和issuer()。

证书中的实际值是ASN.1二进制格式的一系列名称/值

对。但是什么服务器()和issuer()

返回的是字符串,其中的对由/分隔。

文档位于http://docs.python.org/lib/ssl-objects.html"

说"返回包含ASN.1的字符串识别

服务器证书的专有名称。 (请参阅下面的示例,了解哪些专有名称

看起来像。)"但是,没有低于。


你实际上得到的是这样的,这是谷歌的证书:


" / C = US / ST =加州/ L =山景/ O = Google Inc / CN = www.google.com"


所以,没问题;只是拆分为/,对吧?


不幸的是,/是证书价值的合法人物。


更糟糕的是,这不仅仅是一个理论问题。 Verisign的发行人

信息如下:


" / O = VeriSign Trust Network / OU = VeriSign,Inc. / OU = VeriSign International

服务器CA - Class 3 / OU = www.verisign.com / CPS Incorp.by Ref。责任有限公司(c)97

VeriSign"。


请注意


" OU =条款在 www.verisign.com/rpa 使用(c)00


,带有/在值字段的中间。因此,您在Verisign发布的每个证书上都遇到了这个问题。糟糕。


似乎还没有办法从Python中获取证书本身

。 2002年对此进行了一些讨论

http://groups.google.com/group/comp....c124c606f56c0b <当有人写道时,
:此外,当服务器和发行者通过未记录的属性公开

时,server_cert不会。因此,没有办法手动验证证书,没有重写socketmodule.c。这是一个案例

,其中包含的电池已放置在架子上太长时间。


显然,server()和发行人()应该返回列表,而不是字符串。

将解决模糊性问题。 ASN.1是列表的表示,并且

将这些列表敲入字符串会丢失信息。


是否有解决方法?没有重建Python

并变得不兼容?

John Nagle

Animats

The Python SSL object offers two methods from obtaining
the info from an SSL certificate, "server()" and "issuer()".
The actual values in the certificate are a series of name/value
pairs in ASN.1 binary format. But what "server()" and "issuer()"
return are strings, with the pairs separated by "/". The
documentation at "http://docs.python.org/lib/ssl-objects.html"
says "Returns a string containing the ASN.1 distinguished name identifying the
server''s certificate. (See below for an example showing what distinguished names
look like.)" There is, however, no "below".

What you actually get back looks like this, which is Google''s certificate:

"/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com"

So, no problem; just split on "/", right?

Unfortunately, "/" is a legal character in certificate values.

Worse, this isn''t just a theoretical problem. Verisign''s issuer
information reads:

"/O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign International
Server CA - Class 3/OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97
VeriSign".

Note that

"OU=Terms of use at www.verisign.com/rpa (c)00"

with a "/" in the middle of the value field. So you hit this
problem on every cert issued by Verisign. Oops.

Nor does there seem to be a way to get at the certificate itself
from within Python. There was some discussion of this in 2002 at

http://groups.google.com/group/comp....c124c606f56c0b

when someone wrote: "Furthermore, while the server and issuer are exposed
through undocumented attributes, the server_cert is not. So there is no way to
validate the cert manually, short of rewriting socketmodule.c. This is one case
where the batteries included have been sitting on the shelf too long."

Clearly, "server()" and "issuer()" should return lists, not strings. That
would resolve the ambiguity. ASN.1 is a representation for lists, and
hammering those lists into strings loses information.

Is there a workaround for this? Without rebuilding Python
and becoming incompatible?

John Nagle
Animats

推荐答案

John Nagle< na *** @ animats.comwrites:
John Nagle <na***@animats.comwrites:

有解决方法吗?没有重建Python

并变得不兼容?
Is there a workaround for this? Without rebuilding Python
and becoming incompatible?



我已经通过在子进程中调用openssl来解析证书。也许这不是你想听到的。如果你真的很勤奋,你可能会扩展tlslite证书解析代码(用纯粹的

Python编写)来获取这些字段。

I''ve parsed certs by calling openssl in a subprocess. Maybe that''s
not what you wanted to hear. If you''re really industrious you might
be able to extend the tlslite cert parsing code (written in pure
Python) to get those fields out.


文章< 45 ************** @ animats.com>,

John Nagle< na * **@animats.comwrote:
In article <45**************@animats.com>,
John Nagle <na***@animats.comwrote:

Python SSL对象提供了两种从SSL证书获取信息的方法,服务器 ()"和issuer()。

证书中的实际值是ASN.1二进制格式的一系列名称/值

对。但是什么服务器()和issuer()

返回的是字符串,其中的对由/分隔。

文档位于http://docs.python.org/lib/ssl-objects.html"

说"返回包含ASN.1的字符串专有名称识别



服务器的证书。
The Python SSL object offers two methods from obtaining
the info from an SSL certificate, "server()" and "issuer()".
The actual values in the certificate are a series of name/value
pairs in ASN.1 binary format. But what "server()" and "issuer()"
return are strings, with the pairs separated by "/". The
documentation at "http://docs.python.org/lib/ssl-objects.html"
says "Returns a string containing the ASN.1 distinguished name identifying
the
server''s certificate.



....

....


" / O = VeriSign Trust Network / OU = VeriSign,Inc ./OU=VeriSign International

服务器CA - Class 3 / OU = www.verisign.com / CPS Incorp.by Ref。责任

LTD。(c)97

VeriSign"。


请注意


" OU = www.verisign.com/rpa 上的使用条款( c)00


,带有/在值字段的中间。
"/O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign International
Server CA - Class 3/OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY
LTD.(c)97
VeriSign".

Note that

"OU=Terms of use at www.verisign.com/rpa (c)00"

with a "/" in the middle of the value field.



....

....


有解决方法吗?没有重建Python

并变得不兼容?
Is there a workaround for this? Without rebuilding Python
and becoming incompatible?



实际上,我认为假设

是相当安全的,在上下文中没有包含/的值喜欢

看起来真的像X.500风格的专有名称。


所以如果你用这些术语解析那个字符串,并要求

每个key = value对都有合理的值 -

key没有嵌入空格,value的长度非零 - 那么

你应该没问题。将任何无效组件重新加入其

前任的价值。


Donn Cave,做** @ u.washington.edu


Donn Cave写道:
Donn Cave wrote:

文章< 45 ************** @ animats.com>,

John Nagle< na *** @ animats.comwrote:

In article <45**************@animats.com>,
John Nagle <na***@animats.comwrote:


> Python SSL对象提供了两种从SSL证书获取信息的方法,server()和和issuer()。
证书中的实际值是ASN.1二进制格式的一系列名称/值
对。但是什么服务器()和issuer()返回是字符串,其中的对由/分隔。
文档位于http://docs.python.org/lib/ssl-objects.html"
中说返回包含ASN.1专有名称的字符串,标识

服务器的证书。
> The Python SSL object offers two methods from obtaining
the info from an SSL certificate, "server()" and "issuer()".
The actual values in the certificate are a series of name/value
pairs in ASN.1 binary format. But what "server()" and "issuer()"
return are strings, with the pairs separated by "/". The
documentation at "http://docs.python.org/lib/ssl-objects.html"
says "Returns a string containing the ASN.1 distinguished name identifying
the
server''s certificate.



...


...


>>" / O = VeriSign Trust Network / OU = VeriSign,Inc。/ OU = VeriSign International
服务器CA - Class 3 / OU = www.verisign.com / CPS Incorp.by Ref。责任
LTD。(c)97
VeriSign"

请注意

" OU = www.verisign.com/rpa (c)00

带有 /"在值字段的中间。
>>"/O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign International
Server CA - Class 3/OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY
LTD.(c)97
VeriSign".

Note that

"OU=Terms of use at www.verisign.com/rpa (c)00"

with a "/" in the middle of the value field.



...


...


>>有解决方法吗?没有重建Python
并变得不兼容?
>>Is there a workaround for this? Without rebuilding Python
and becoming incompatible?




实际上,我认为假设

是相当安全的,没有包含的值/在像

这样的上下文中,看起来就像是X.500风格的专有名称。



As a practical matter, I think it''s fairly safe to assume
there will be no values that include / in a context like
really looks like that X.500 style distinguished name.



实际上,我们刚刚发现了一个漏洞。通过

订购带有/的低级证书在正确的

的地方,你可以创造一种错觉(至少对于像这样的有缺陷的实施
)证书

属于某人其他。只需从

GoDaddy订购证书,在名称中输入类似的内容。字段


" Myphonyname / C = US / ST =加州/ L =圣何塞/ O = eBay Inc./OU=Site

运营/ CN = signin.ebay.com"


和Python代码将被欺骗以为你是eBay。


幸运的是,浏览器不应该不使用Python代码。


实际的错误在


python / trunk / Modules / _ssl.c



if((self-> server_cert = SSL_get_peer_certificate(self-> ssl))){

X509_NAME_oneline(X509_get_subject_name) (自我> server_cert),

self->服务器,X509_NAME_MAXLEN);

X509_NAME_oneline(X509_get_issuer_name(自我> server_cert),

self-> issuer,X509_NAME_MAXLEN);


X509_name_oneline"函数采用X509_NAME结构,这是证书系统表示列表的
,并将其展平为可打印的字符串。这是一个调试功能,而不是用于

生产代码的功能。 X509_name_oneline的SSL文档说:


"函数X509_NAME_oneline()和X509_NAME_print()是传统的

函数,它们产生非标准输出形式,它们无法处理

多字符字段并且有各种怪癖和不一致。

强烈建议不要在新应用程序中使用它们。


什么OpenSSL调用者应该调用X509_NAME_entry_count()

来获取X509_NAME结构中的条目数,然后使用X509_NAME_get_entry()获取每个

条目。还有几个调用将从条目中获得名称/值对的

,作为UTF8字符串,应该将
转换为Python UNICODE字符串。


X509_NAME_oneline()无法处理Unicode;它将非ASCII

值转换为\ xnn"格式。同样,它仅适用于调试输出。


那么需要的是两个用于Python的SSL套接字的新功能来支持
替换"发行人"和服务器。新函数应该返回

代表键/值对的Unicode字符串列表。

(需要一个列表,而不是字典;两个字符串具有相同的键

既可行又常见。)


现在重要的原因是新的高保证证书,

那些告诉你网站可以信任多少,现在部署了b $ b,并且要有效地使用它们,你需要这些信息。支持

它们在Internet Explorer 7中,所以它们很快就会普及。

Python需要赶上来。


我会提交错误报告。


John Nagle

Animats

Actually, we''ve just discovered an exploit. By
ordering a low-level certificate with a "/" in the right
place, you can create the illusion (at least for flawed
implementations like this one) that the certificate
belongs to someone else. Just order a certificate from
GoDaddy, enter something like this in the "Name" field

"Myphonyname/C=US/ST=California/L=San Jose/O=eBay Inc./OU=Site
Operations/CN=signin.ebay.com"

and Python code will be spoofed into thinking you''re eBay.

Fortunately, browsers don''t use Python code.

The actual bug is in

python/trunk/Modules/_ssl.c

at

if ((self->server_cert = SSL_get_peer_certificate(self->ssl))) {
X509_NAME_oneline(X509_get_subject_name(self->server_cert),
self->server, X509_NAME_MAXLEN);
X509_NAME_oneline(X509_get_issuer_name(self->server_cert),
self->issuer, X509_NAME_MAXLEN);

The "X509_name_oneline" function takes an X509_NAME structure, which is
the certificate system''s representation of a list, and flattens it
into a printable string. This is a debug function, not one for use in
production code. The SSL documentation for "X509_name_oneline" says:

"The functions X509_NAME_oneline() and X509_NAME_print() are legacy
functions which produce a non standard output form, they don''t handle
multi character fields and have various quirks and inconsistencies.
Their use is strongly discouraged in new applications."

What OpenSSL callers are supposed to do is call X509_NAME_entry_count()
to get the number of entries in an X509_NAME structure, then get each
entry with X509_NAME_get_entry(). A few more calls will obtain
the name/value pair from the entry, as UTF8 strings, which should
be converted to Python UNICODE strings.

X509_NAME_oneline() doesn''t handle Unicode; it converts non-ASCII
values to "\xnn" format. Again, it''s for debug output only.

So what''s needed are two new functions for Python''s SSL sockets to
replace "issuer" and "server". The new functions should return
lists of Unicode strings representing the key/value pairs.
(A list is needed, not a dictionary; two strings with the same key
are both possible and common.)

The reason this now matters is that new "high assurance" certs,
the ones that tell you how much a site can be trusted, are now being
deployed, and to use them effectively, you need that info. Support for
them is in Internet Explorer 7, so they''re going to be widespread soon.
Python needs to catch up.

I''ll submit a bug report.

John Nagle
Animats


这篇关于从SSL对象获取SSL证书信息 - BUG?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆