@@ -310,17 +310,29 @@ def validate_signature(base64_cert, soft = true)
310310 canon_string = noko_signed_info_element . canonicalize ( canon_algorithm )
311311 noko_sig_element . remove
312312
313+ # get signed info
314+ signed_info_element = REXML ::XPath . first (
315+ sig_element ,
316+ "./ds:SignedInfo" ,
317+ { "ds" => DSIG }
318+ )
313319 # get inclusive namespaces
314320 inclusive_namespaces = extract_inclusive_namespaces
315321
316322 # check digests
317- ref = REXML ::XPath . first ( sig_element , "/ /ds:Reference" , { "ds" => DSIG } )
323+ ref = REXML ::XPath . first ( signed_info_element , ". /ds:Reference" , { "ds" => DSIG } )
318324
319- hashed_element = document . at_xpath ( "//*[@ID=$id]" , nil , { 'id' => extract_signed_element_id } )
325+ reference_nodes = document . xpath ( "//*[@ID=$id]" , nil , { 'id' => extract_signed_element_id } )
326+
327+ if reference_nodes . length > 1 # ensures no elements with same ID to prevent signature wrapping attack.
328+ return append_error ( "Digest Mismatch" , soft )
329+ end
330+
331+ hashed_element = reference_nodes [ 0 ]
320332
321333 canon_algorithm = canon_algorithm REXML ::XPath . first (
322- ref ,
323- '/ /ds:CanonicalizationMethod' ,
334+ signed_info_element ,
335+ '. /ds:CanonicalizationMethod' ,
324336 { "ds" => DSIG }
325337 )
326338
@@ -330,13 +342,13 @@ def validate_signature(base64_cert, soft = true)
330342
331343 digest_algorithm = algorithm ( REXML ::XPath . first (
332344 ref ,
333- "/ /ds:DigestMethod" ,
345+ ". /ds:DigestMethod" ,
334346 { "ds" => DSIG }
335347 ) )
336348 hash = digest_algorithm . digest ( canon_hashed_element )
337349 encoded_digest_value = REXML ::XPath . first (
338350 ref ,
339- "/ /ds:DigestValue" ,
351+ ". /ds:DigestValue" ,
340352 { "ds" => DSIG }
341353 )
342354 digest_value = Base64 . decode64 ( OneLogin ::RubySaml ::Utils . element_text ( encoded_digest_value ) )
@@ -362,7 +374,7 @@ def validate_signature(base64_cert, soft = true)
362374 def process_transforms ( ref , canon_algorithm )
363375 transforms = REXML ::XPath . match (
364376 ref ,
365- "/ /ds:Transforms/ds:Transform" ,
377+ ". /ds:Transforms/ds:Transform" ,
366378 { "ds" => DSIG }
367379 )
368380
0 commit comments