Skip to contentSkip to conversation

cifs: Bypass windows extended security for ntlmv2 negotiate

PATCH Applied Namjae Jeon 7 participants 9 messages Aug 20, 2014 – Aug 22, 2014 3 messages not in the archive

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/7 cifs: Bypass windows extended security for ntlmv2 negotiate

Windows machine has extended security feature which refuse to allow authentication when there is time difference between server time and client time when ntlmv2 negotiation is used. This problem is prevalent in embedded enviornment where system time is set to default 1970.

We don't know yet the exact threshold for the time difference at which the connection is refused but one comment in cifs code suggest that it is around 5 minutes.

This patch tries to solve this problem by sending the received server time during negotiate process as the current client time.

---
 fs/cifs/cifsencrypt.c |    4 ++--
 fs/cifs/cifsglob.h    |    2 ++
 fs/cifs/cifssmb.c     |    2 ++
 fs/cifs/smb2pdu.c     |    1 +
 4 files changed, 7 insertions(+), 2 deletions(-)
fs/cifs/cifsencrypt.c +2 -2
index 4934347..d5cec81 100644
@@ -671,8 +671,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 			(ses->auth_key.response + CIFS_SESS_KEY_SIZE);
 	ntlmv2->blob_signature = cpu_to_le32(0x00000101);
 	ntlmv2->reserved = 0;
-	/* Must be within 5 minutes of the server */
-	ntlmv2->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+	/* Hack to get around windows extended security */
+	ntlmv2->time = cpu_to_le64(ses->serverTime);
 	get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
 	ntlmv2->reserved2 = 0;
 
fs/cifs/cifsglob.h +2 -0
index ce24c1f..9344c94 100644
@@ -796,6 +796,8 @@ struct cifs_ses {
 	enum securityEnum sectype; /* what security flavor was specified? */
 	bool sign;		/* is signing required? */
 	bool need_reconnect:1; /* connection reset, uid now invalid */
+	__u64   serverTime;	/* Keeps a track of server time sent by server
+				   during negotiate response */
 #ifdef CONFIG_CIFS_SMB2
 	__u16 session_flags;
 	char smb3signingkey[SMB3_SIGN_KEY_SIZE]; /* for signing smb3 packets */
fs/cifs/cifssmb.c +2 -0
index 86a2aa5..ead2da0 100644
@@ -584,6 +584,8 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 	if (rc != 0)
 		goto neg_err_exit;
 
+	ses->serverTime = le32_to_cpu(pSMBr->SystemTimeLow);
+	ses->serverTime |= ((__u64)le32_to_cpu(pSMBr->SystemTimeHigh) << 32);
 	server->dialect = le16_to_cpu(pSMBr->DialectIndex);
 	cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
 	/* Check wct = 1 error case */
fs/cifs/smb2pdu.c +1 -0
index ed42234..a40f492 100644
@@ -381,6 +381,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
 	if (rc != 0)
 		goto neg_exit;
 
+	ses->serverTime = le64_to_cpu(rsp->SystemTime);
 	cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode);
 
 	/* BB we may eventually want to match the negotiated vs. requested
Signature · 1 line
1.7.7
#1 lore raw

PATCH 1/7 cifs: Bypass windows extended security for ntlmv2 negotiate

This is an unusual sounding issue. Any comments on this from the auth experts?

Seems better to investigate this more if we end up enforcing a "must be within 5 minutes" threshold instead of this patch. Have we done a dochelp on this before?

---------- Forwarded message ----------
From: Namjae Jeon <[email protected]>
Date: Wed, Aug 20, 2014 at 5:39 AM
Subject: [PATCH 1/7] cifs: Bypass windows extended security for ntlmv2 negotiate
To: Steve French <[email protected]>
Cc: Shirish Pargaonkar <[email protected]>, Pavel Shilovsky <[email protected]>, [email protected], Ashish Sangwan <[email protected]>

Windows machine has extended security feature which refuse to allow authentication when there is time difference between server time and client time when ntlmv2 negotiation is used. This problem is prevalent in embedded enviornment where system time is set to default 1970.

We don't know yet the exact threshold for the time difference at which the connection is refused but one comment in cifs code suggest that it is around 5 minutes.

This patch tries to solve this problem by sending the received server time during negotiate process as the current client time.

---
 fs/cifs/cifsencrypt.c |    4 ++--
 fs/cifs/cifsglob.h    |    2 ++
 fs/cifs/cifssmb.c     |    2 ++
 fs/cifs/smb2pdu.c     |    1 +
 4 files changed, 7 insertions(+), 2 deletions(-)
fs/cifs/cifsencrypt.c +0 -0
index 4934347..d5cec81 100644
@@ -671,8 +671,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const

struct nls_table *nls_cp)

                        (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
        ntlmv2->blob_signature = cpu_to_le32(0x00000101);
        ntlmv2->reserved = 0;
-       /* Must be within 5 minutes of the server */
-       ntlmv2->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+       /* Hack to get around windows extended security */
+       ntlmv2->time = cpu_to_le64(ses->serverTime);
        get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
        ntlmv2->reserved2 = 0;
fs/cifs/cifsglob.h +2 -0
index ce24c1f..9344c94 100644
@@ -796,6 +796,8 @@ struct cifs_ses {
        enum securityEnum sectype; /* what security flavor was specified? */
        bool sign;              /* is signing required? */
        bool need_reconnect:1; /* connection reset, uid now invalid */
+       __u64   serverTime;     /* Keeps a track of server time sent by server
+                                  during negotiate response */
 #ifdef CONFIG_CIFS_SMB2
        __u16 session_flags;
        char smb3signingkey[SMB3_SIGN_KEY_SIZE]; /* for signing smb3 packets */
fs/cifs/cifssmb.c +0 -0
index 86a2aa5..ead2da0 100644
@@ -584,6 +584,8 @@ CIFSSMBNegotiate(const unsigned int xid, struct

cifs_ses *ses)

        if (rc != 0)
                goto neg_err_exit;

+ ses->serverTime = le32_to_cpu(pSMBr->SystemTimeLow);

+       ses->serverTime |= ((__u64)le32_to_cpu(pSMBr->SystemTimeHigh) << 32);
        server->dialect = le16_to_cpu(pSMBr->DialectIndex);
        cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
        /* Check wct = 1 error case */
fs/cifs/smb2pdu.c +1 -0
index ed42234..a40f492 100644
@@ -381,6 +381,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
        if (rc != 0)
                goto neg_exit;
 
+       ses->serverTime = le64_to_cpu(rsp->SystemTime);
        cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode);
 
        /* BB we may eventually want to match the negotiated vs. requested

--
1.7.7

Signature · 3 lines
Thanks,

Steve
#2 lore raw
Quoted 5 lines · Steve French

This is an unusual sounding issue. Any comments on this from the auth experts?

Seems better to investigate this more if we end up enforcing a "must be within 5 minutes" threshold instead of this patch. Have we done a dochelp on this before?

I am certainly nervous about this patch, as I've not ever seen this before. The thing that makes me feel particularly odd about this is
that: In general, NTLMSSP clients don't have the server's time, and certainly don't have the domain controller's time. (That CIFS provides this does not mean we should use it, NTLMSSP is a general protocol and adding CIFS-specific hacks indicates we are understanding it wrong, in my experience).

BTW, the domain controller is the only element here that could check the embedded time, but I'll grant that typically servers are better in sync with each other than this embedded device might be.

The 5 mins stuff probably refers to Kerberos, which does have such a time limit. I've never seen NTLMSSP fail against windows due to clock skew.

I would like to see much more investigation here before this is done, because if you just trust the server's time and if you need to, to pass a security check, you override that check. We need to understand why it is in place.

Thanks,

Andrew Bartlett

Signature · 4 lines
Andrew Bartlett
http://samba.org/~abartlet/
Authentication Developer, Samba Team  http://samba.org
Samba Developer, Catalyst IT          http://catalyst.net.nz/services/samba
#3 lore raw
Quoted 10 lines · Andrew Bartlett
Quoted 5 lines · Steve French

This is an unusual sounding issue. Any comments on this from the auth experts?

Seems better to investigate this more if we end up enforcing a "must be within 5 minutes" threshold instead of this patch. Have we done a dochelp on this before?

I am certainly nervous about this patch, as I've not ever seen this before. The thing that makes me feel particularly odd about this is
that: In general, NTLMSSP clients don't have the server's time,

This is simply false.
Modern servers send the server timestamp in the TargetInfo Av_Pair structure in the challenge message [see MS-NLMP 2.2.2.1].

In [MS-NLMP 3.1.5.1.2] it is explicitly mentioned that the client must use the provided (from the server) timestamp if present or current time if it is not.

Not only a modern server *should* send a timestamp, but a modern client, on seeing that a timestamp is available should provide a MIC in the Authentication message [MS-NLMP 3.1.5.1.2].

Unfortunately samba at the moment has a very limited and incomplete implementation of the NTLM protocol and doesn't do much with targetinfo except mocking it up a little.

An implementation that is very close to implementing all of the MS-NLMP specification is here:
https://git.samba.org/?p=idra/gss-ntlmssp.git;a=summary
or here: https://fedorahosted.org/gss-ntlmssp/
and I hope to make samba use it eventually, when we have a more decent set of interfaces to connect to DCs (the current winbind interfacing is suboptimal but fixable).

Quoted 1 line

and certainly don't have the domain controller's time.

This is true but not a problem today were servers are supposed to have the time in sync with the KDC/Domain Controller anyway.

Quoted 5 lines

(That CIFS provides
this does not mean we should use it, NTLMSSP is a general protocol and adding CIFS-specific hacks indicates we are understanding it wrong, in my experience).

Quoted 7 lines

BTW, the domain controller is the only element here that could check the embedded time, but I'll grant that typically servers are better in sync with each other than this embedded device might be.

The 5 mins stuff probably refers to Kerberos, which does have such a time limit. I've never seen NTLMSSP fail against windows due to clock skew.

That's becasue a client is supposed to use the time provided by the server, so no clockskew is really possible,

Quoted 4 lines

I would like to see much more investigation here before this is done, because if you just trust the server's time and if you need to, to pass a security check, you override that check. We need to understand why it is in place.

Sorry but this makes no sense, if you can bypass a "security mechanism" in the client, then there is *no* security mechanism.

The reason why a timestamp is provided by the server is (most probably) to mitigate replay attacks when the client uses a MIC (as it should) when the timestamp is provided.

Simo.

A message that is not in the archive (sent off-list or not yet received): 1408681047.11134.15.camel-fj0lwfvWodpMy5p6ylGyhR2eb7JE58TQ@public.gmane.org

#5 lore raw

Am 22.08.2014 um 06:17 schrieb Simo:

Quoted 12 lines · Andrew Bartlett
Quoted 10 lines · Steve French
Quoted 5 lines

This is an unusual sounding issue. Any comments on this from the auth experts?

Seems better to investigate this more if we end up enforcing a "must be within 5 minutes" threshold instead of this patch. Have we done a dochelp on this before?

I am certainly nervous about this patch, as I've not ever seen this before. The thing that makes me feel particularly odd about this is
that: In general, NTLMSSP clients don't have the server's time,

Quoted 7 lines

This is simply false.
Modern servers send the server timestamp in the TargetInfo Av_Pair structure in the challenge message [see MS-NLMP 2.2.2.1].

In [MS-NLMP 3.1.5.1.2] it is explicitly mentioned that the client must use the provided (from the server) timestamp if present or current time if it is not.

I talks about the MsvAvTimestamp from CHALLENGE_MESSAGE.TargetInfo.Value not the timestamp from smb negprot.

I think it would make sense to skip the timestamp if the client doesn't find the server time in CHALLENGE_MESSAGE.TargetInfo.Value and notices that the local time isn't correct. E.g. the date is before the year 2000.

metze

#6 lore raw
Quoted 17 lines · Stefan (metze) Metzmacher

Am 22.08.2014 um 06:17 schrieb Simo:

Quoted 16 lines · Andrew Bartlett
Quoted 10 lines · Steve French
Quoted 5 lines

This is an unusual sounding issue. Any comments on this from the auth experts?

Seems better to investigate this more if we end up enforcing a "must be within 5 minutes" threshold instead of this patch. Have we done a dochelp on this before?

I am certainly nervous about this patch, as I've not ever seen this before. The thing that makes me feel particularly odd about this is
that: In general, NTLMSSP clients don't have the server's time,

This is simply false.
Modern servers send the server timestamp in the TargetInfo Av_Pair structure in the challenge message [see MS-NLMP 2.2.2.1].

Quoted 6 lines
Quoted 3 lines

In [MS-NLMP 3.1.5.1.2] it is explicitly mentioned that the client must use the provided (from the server) timestamp if present or current time if it is not.

I talks about the MsvAvTimestamp from CHALLENGE_MESSAGE.TargetInfo.Value not the timestamp from smb negprot.

Sure, the point is that the server *does* send a timestamp that the client is supposed to use.

Quoted 4 lines

I think it would make sense to skip the timestamp if the client doesn't find the server time in CHALLENGE_MESSAGE.TargetInfo.Value and notices that the local time isn't correct. E.g. the date is before the year 2000.

IT probably shouldn't use the timestamp at all if the challenge message does not have it because it means the server doesn't know what to do about it anyway.
However using the timestamp found in the smb packet is as good as anything else, it won't hurt anything, unless the server has its time completely off and relay the authentication to a DC while the client had the clock right.

Simo.

A message that is not in the archive (sent off-list or not yet received): CAH2r5muT0jBfh_K230dtNW5ZkVFx+evHiDA=+yoeG_PvDkCxmA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org

#8 lore raw
Quoted 5 lines · Steve French

This is an unusual sounding issue. Any comments on this from the auth experts?

Seems better to investigate this more if we end up enforcing a "must be within 5 minutes" threshold instead of this patch. Have we done a dochelp on this before?

No we have not. I'd feel happier if you could add some test code to smbtorture that showed NTLM authentication succeeding with correct time, and it failing with a large time drift, that passes against a Windows server.

Jeremy.

#9 lore raw
In reply to Namjae Jeon
Quoted 67 lines · Namjae Jeon

Windows machine has extended security feature which refuse to allow authentication when there is time difference between server time and client time when ntlmv2 negotiation is used. This problem is prevalent in embedded enviornment where system time is set to default 1970.

We don't know yet the exact threshold for the time difference at which the connection is refused but one comment in cifs code suggest that it is around 5 minutes.

This patch tries to solve this problem by sending the received server time during negotiate process as the current client time.

---
 fs/cifs/cifsencrypt.c |    4 ++--
 fs/cifs/cifsglob.h    |    2 ++
 fs/cifs/cifssmb.c     |    2 ++
 fs/cifs/smb2pdu.c     |    1 +
 4 files changed, 7 insertions(+), 2 deletions(-)
fs/cifs/cifsencrypt.c +2 -2
index 4934347..d5cec81 100644
@@ -671,8 +671,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
 			(ses->auth_key.response + CIFS_SESS_KEY_SIZE);
 	ntlmv2->blob_signature = cpu_to_le32(0x00000101);
 	ntlmv2->reserved = 0;
-	/* Must be within 5 minutes of the server */
-	ntlmv2->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+	/* Hack to get around windows extended security */
+	ntlmv2->time = cpu_to_le64(ses->serverTime);
 	get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
 	ntlmv2->reserved2 = 0;
 
fs/cifs/cifsglob.h +2 -0
index ce24c1f..9344c94 100644
@@ -796,6 +796,8 @@ struct cifs_ses {
 	enum securityEnum sectype; /* what security flavor was specified? */
 	bool sign;		/* is signing required? */
 	bool need_reconnect:1; /* connection reset, uid now invalid */
+	__u64   serverTime;	/* Keeps a track of server time sent by server
+				   during negotiate response */
 #ifdef CONFIG_CIFS_SMB2
 	__u16 session_flags;
 	char smb3signingkey[SMB3_SIGN_KEY_SIZE]; /* for signing smb3 packets */
fs/cifs/cifssmb.c +2 -0
index 86a2aa5..ead2da0 100644
@@ -584,6 +584,8 @@ CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
 	if (rc != 0)
 		goto neg_err_exit;
 
+	ses->serverTime = le32_to_cpu(pSMBr->SystemTimeLow);
+	ses->serverTime |= ((__u64)le32_to_cpu(pSMBr->SystemTimeHigh) << 32);
 	server->dialect = le16_to_cpu(pSMBr->DialectIndex);
 	cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
 	/* Check wct = 1 error case */
fs/cifs/smb2pdu.c +0 -0
index ed42234..a40f492 100644

fs/cifs/smb2pdu.c SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) · line 387

Quoted 7 lines
fs/cifs/smb2pdu.c +1 -0
@@ -381,6 +381,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
 	if (rc != 0)
 		goto neg_exit;
 
+	ses->serverTime = le64_to_cpu(rsp->SystemTime);
 	cifs_dbg(FYI, "mode 0x%x\n", rsp->SecurityMode);
 
 	/* BB we may eventually want to match the negotiated vs. requested

This patch is not addressing the problem in the correct way. The server should send the time in the challenge message targetinfo data (see MS-NLMP and search for MsvAvTimestamp in 2.2.2.1 and 3..5.1.2), only if it is not available the currentime should be used (if you have to pick the current time I guess you can employ tricks to try to get one as close as possible to the server time by other means).

It is not clear to me whether the code parses the challenge messages's targetinfo field, if it doesn't it should.

Simo.

A message that is not in the archive (sent off-list or not yet received): 1408681626.11134.20.camel-fj0lwfvWodpMy5p6ylGyhR2eb7JE58TQ@public.gmane.org

#11 lore raw
Quoted 10 lines

This patch is not addressing the problem in the correct way. The server should send the time in the challenge message targetinfo data (see MS-NLMP and search for MsvAvTimestamp in 2.2.2.1 and 3..5.1.2), only if it is not available the currentime should be used (if you have to pick the current time I guess you can employ tricks to try to get one as close as possible to the server time by other means).

It is not clear to me whether the code parses the challenge messages's targetinfo field, if it doesn't it should.

Okay, I will check your point.

Thanks for your reply :)

Quoted 2 lines

Simo.