Skip to content
This repository has been archived by the owner on Mar 20, 2019. It is now read-only.

Commit

Permalink
Fixed message expiration check to also disallow post-dated timestamps.
Browse files Browse the repository at this point in the history
This is a security mitigation for those who are trying to brute force a message signature, and might otherwise give themselves a huge time window by setting a nonce date far into the future.
  • Loading branch information
AArnott committed Jul 16, 2010
1 parent e85b35a commit b6538d4
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 3 deletions.
Expand Up @@ -6,6 +6,8 @@

namespace DotNetOpenAuth.Test.Messaging.Bindings {
using System;

using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.Test.Mocks;
Expand All @@ -30,10 +32,22 @@ public class StandardExpirationBindingElementTests : MessagingTestBase {
this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, false);
}

[TestCase]
public void VerifyFutureTimestampWithinClockSkewIsAccepted() {
this.Channel = CreateChannel(MessageProtections.Expiration);
this.ParameterizedReceiveProtectedTest(DateTime.UtcNow + DotNetOpenAuthSection.Configuration.Messaging.MaximumClockSkew - TimeSpan.FromSeconds(1), false);
}

[TestCase, ExpectedException(typeof(ExpiredMessageException))]
public void VerifyBadTimestampIsRejected() {
public void VerifyOldTimestampIsRejected() {
this.Channel = CreateChannel(MessageProtections.Expiration);
this.ParameterizedReceiveProtectedTest(DateTime.UtcNow - StandardExpirationBindingElement.MaximumMessageAge - TimeSpan.FromSeconds(1), false);
}

[TestCase, ExpectedException(typeof(ProtocolException))]
public void VerifyFutureTimestampIsRejected() {
this.Channel = CreateChannel(MessageProtections.Expiration);
this.ParameterizedReceiveProtectedTest(DateTime.UtcNow + DotNetOpenAuthSection.Configuration.Messaging.MaximumClockSkew + TimeSpan.FromSeconds(1), false);
}
}
}
Expand Up @@ -83,11 +83,19 @@ internal class StandardExpirationBindingElement : IChannelBindingElement {
if (expiringMessage != null) {
// Yes the UtcCreationDate is supposed to always be in UTC already,
// but just in case a given message failed to guarantee that, we do it here.
DateTime expirationDate = expiringMessage.UtcCreationDate.ToUniversalTimeSafe() + MaximumMessageAge;
DateTime creationDate = expiringMessage.UtcCreationDate.ToUniversalTimeSafe();
DateTime expirationDate = creationDate + MaximumMessageAge;
if (expirationDate < DateTime.UtcNow) {
throw new ExpiredMessageException(expirationDate, expiringMessage);
}

// Mitigate HMAC attacks (just guessing the signature until they get it) by
// disallowing post-dated messages.
ErrorUtilities.VerifyProtocol(
creationDate <= DateTime.UtcNow + DotNetOpenAuthSection.Configuration.Messaging.MaximumClockSkew,
MessagingStrings.MessageTimestampInFuture,
creationDate);

return MessageProtections.Expiration;
}

Expand Down
9 changes: 9 additions & 0 deletions src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion src/DotNetOpenAuth/Messaging/MessagingStrings.resx
Expand Up @@ -303,4 +303,7 @@
<data name="SessionRequired" xml:space="preserve">
<value>An HttpContext.Current.Session object is required.</value>
</data>
</root>
<data name="MessageTimestampInFuture" xml:space="preserve">
<value>This message has a timestamp of {0}, which is beyond the allowable clock skew for in the future.</value>
</data>
</root>

0 comments on commit b6538d4

Please sign in to comment.