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

Commit

Permalink
Merge pull request #3 from jborean93/add-sign-seal
Browse files Browse the repository at this point in the history
Add sign seal
  • Loading branch information
jborean93 committed Aug 21, 2016
2 parents 5f6fd5c + 62e4066 commit 59c6473
Show file tree
Hide file tree
Showing 27 changed files with 2,862 additions and 1,545 deletions.
5 changes: 4 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ Initial public offering.
-------------------

* Added support for Python 3.5
* Added requirement for cryptography so we can calculate RC4 values for EncryptedRandomSessionKey and signing and sealing (can we remove this dependency?)
* Major rewrite of how python-ntlm3 handles authentication
* Added support for NTLMv2 auth and fixed up some older auth methods
* Moved code to separate classes to help cleanup the code
* Added support for channel_bindings (CBT) when supplying a certificate hash
* Added support for MIC data for authenticate messages
* Preliminary support for signing and sealing of messages. Needs to be done outside of auth messages and tested more thoroughly
* Removed some methods that weren't being used at all (most were starting to implement these features above but weren't there)
* More comments on each methods relating back to the MS-NLMP document pack on NTLM authentication for easier maintenance
* Created target_info.py to handle AV_PAIRS and putting it in the target info
* Renaming of some variables to match more closely with the Microsoft documentation, makes it easier to understand what is happening
* Rewriting of tests to accomodate these new changes and to cover the new cases
* Rewriting of tests to accommodate these new changes and to cover the new cases
* The methods `create_NTLM_NEGOTIATE_MESSAGE`, `parse_NTLM_CHALLENGE_MESSAGE`, `create_NTLM_AUTHENTICATE_MESSAGE` will no longer be supported in future version. They do not support NTLMv2 auth and are only left for compatibility
59 changes: 52 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ About this library

This library handles the low-level details of NTLM authentication. This library will create the 3 different message types in NTLM based on the input and produce a base64 encoded value to attach to the HTTP header.

The goal of this library is to offer full NTLM support including signing and sealing of messages as well as supporting MIC for message integrity but right now not all of this is implemented. Please see Features and Backlog for a list of what is and is not currently supported.
The goal of this library is to offer full NTLM support including signing and sealing of messages as well as supporting MIC for message integrity and the ability to customise and set limits on the messages sent. Please see Features and Backlog for a list of what is and is not currently supported.

Features
--------
* LM, NTLM and NTLMv2 authentication
* NTLM1 and NTLM2 extended session security
* Set the The NTLM Compatibility level when sending messages
* Channel Binding Tokens support, need to pass in the SHA256 hash of the certificate for it to work
* Support for MIC to enhance the integrity of the messages
* (To be Tested) Support for session security with signing and sealing messages after authentication happens

Installation
------------
Expand All @@ -37,9 +39,9 @@ Usage

Almost all users should use [requests-ntlm](https://github.com/requests/requests-ntlm) instead of this library. The library requests-ntlm is a plugin that uses this library under the hood and provides an easier function to use and understand.

If you are set on using python-ntlm3 directly to compute the message structures this is a very basic outline of how it can be done.
If you are set on using python-ntlm3 directly to compute the message structures this is a very basic outline of how it can be done. The code examples are psuedocode and should be adapted for your purpose.

The key difference between the different auth levels are the ntlm_compatibility variable supplied when initialising Ntlm. An overview of what each sets is below;
When initliasing the ntlm context you will have to supply the NTLM compatibility level. The key difference between the different auth levels are the ntlm_compatibility variable supplied when initialising Ntlm. An overview of what each sets is below;
* `0` - LM Auth and NTLMv1 Auth
* `1` - LM Auth and NTLMv1 Auth with Extended Session Security (NTLM2)
* `2` - NTLMv1 Auth with Extended Session Security (NTLM2)
Expand Down Expand Up @@ -110,6 +112,47 @@ authenticate_message = ntlm_context.create_authenticate_message(user_name, passw
# Attach the authenticate_message ot your NTLM_NEGOTIATE HTTP header and send to the server. You are now authenticated with NTLMv1
```

#### Signing/Sealing

All version of NTLM supports signing (integrity) and sealing (confidentiality) of message content. This function can add these improvements to a message that is sent and received from the server. While it does encrypt the data if supported by the server it is only done with RC4 with a 128-bit key which is not very secure and on older systems this key length could be 56 or 40 bit. This functionality while tested and conforms with the Microsoft documentation has yet to be fully tested in an integrated environment. Once again this has not been thoroughly tested and has only passed unit tests and their expections.

```python
import socket

from ntlm3.ntlm import Ntlm

user_name = 'User'
password = 'Password'
domain_name = 'Domain' # Can be blank if you are not in a domain
workstation = socket.gethostname().upper() # Can be blank if you wish to not send this info
msg_data = "Message to send to the server"
server_certificate_hash = '96B2FC1EC30792619286A0C7FD62863E81A6564E72829CBC0A46F7B1D5D92A18' # Can be blank if you don't want CBT sent

ntlm_context = Ntlm()
negotiate_message = ntlm_context.create_negotiate_message(domain_name, workstation).decode()

# Attach the negotiate_message to your NTLM/NEGOTIATE HTTP header and send to the server. Get the challenge response back from the server
challenge_message = http.response.headers['HEADERFIELD']

authenticate_message = ntlm_context.create_authenticate_message(user_name, password, domain_name, workstation, server_certificate_hash).decode()

if ntlm_context.session_security is None:
raise Exception("Server does not support signing and sealing")
else:
session_security = ntlm_context.session_security

# Encrypt the msg with the sealing function and send the message
msg_data, msg_signature = session_security.wrap(msg_data)
request.body = msg_data
request.header = "NTLM %s" % authenticate_message
request.send

# Receive the response the from the server
response_msg = response.body[bodyindex]
response_signature = response.body[signatureindex]
response_msg = session_security.unwrap(response_msg, response_signature)
```

Deprecated methods
------------------

Expand All @@ -120,7 +163,9 @@ Please use the Ntlm class in ntlm.py in the future as this brings supports for N

Backlog
-------
* Add support for session security signing and encryption
* Add support for MIC to enhanced the security
* Migrate test_ntlm.py and test_messages.py tests to use the Microsoft examples once the above is implemented
* Remove the old ntlm.py code that has been left there for compatibility. This does not support NTLMv2 auth
* Remove the old ntlm.py code that has been left there for compatibility in the next major version release. This does not support NTLMv2 auth
* Fully test out signing and sealing of messages over the wire with another library
* Automatically get windows version if running on windows, use default if not that case
* Add param when initialising the ntlm context to throw an exception and cancel auth if the server doesn't support 128-bit keys for sealing
* Add param when initialising the ntlm context to not send the MIC structure for older servers
* Add param to independently verify the target name returned from the server and the value passed in
2 changes: 2 additions & 0 deletions examples/simple.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#! /usr/bin/env python

"""
This method is deprecated, please avoid using this way as it does not support NTLMv2 and is not considered secure
A simple script to demonstrate how this package works.
Run with:
Expand Down
Loading

0 comments on commit 59c6473

Please sign in to comment.