Hawk:一个新的HTTP鉴权方案

     Hawk是一种新的http鉴权方案,它使用了MAC(message authentication code 消息鉴权码)来对http请求进行签名验证,进而起到保护http请求的目的。

     这个方案的主要目标是:

(1)在不希望或者没有条件在每次请求中使用TLS的时候,简化和改进对服务请求的HTTP鉴权,

(2)在某些情况保护凭据免于泄露,例如:当客户端使用了某种动态的配置来决定往哪里发送鉴权过的请求的时候。

(3)在某些情况保护凭据免于暴露,例如:当客户端将凭证发送给某个恶意的服务器,此时使用了未经鉴权的安全通道,因为在TLS握手中客户端没有成功地对服务器的身份进行验证。

    下面的示例代码使用了node.js和http报文。

 

Hawk is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial HTTP request cryptographic verification. For more complex use cases such as access delegation, see Oz.

Current version: 3.x

Note: 3.x and 2.x are the same exact protocol as 1.1. The version increments reflect changes in the node API.

 

Introduction

Hawk is an HTTP authentication scheme providing mechanisms for making authenticated HTTP requests with partial cryptographic verification of the request and response, covering the HTTP method, request URI, host, and optionally the request payload.

Similar to the HTTP Digest access authentication schemes, Hawk uses a set of client credentials which include an identifier (e.g. username) and key (e.g. password). Likewise, just as with the Digest scheme, the key is never included in authenticated requests. Instead, it is used to calculate a request MAC value which is included in its place.

However, Hawk has several differences from Digest. In particular, while both use a nonce to limit the possibility of replay attacks, in Hawk the client generates the nonce and uses it in combination with a timestamp, leading to less "chattiness" (interaction with the server).

Also unlike Digest, this scheme is not intended to protect the key itself (the password in Digest) because the client and server must both have access to the key material in the clear.

The primary design goals of this scheme are to:

  • simplify and improve HTTP      authentication for services that are unwilling or unable to deploy TLS for      all resources,
  • secure credentials      against leakage (e.g., when the client uses some form of dynamic      configuration to determine where to send an authenticated request), and
  • avoid the exposure of      credentials sent to a malicious server over an unauthenticated secure      channel due to client failure to validate the server's identity as part of      its TLS handshake.

In addition, Hawk supports a method for granting third-parties temporary access to individual resources using a query parameter called bewit (in falconry, a leather strap used to attach a tracking device to the leg of a hawk).

The Hawk scheme requires the establishment of a shared symmetric key between the client and the server, which is beyond the scope of this module. Typically, the shared credentials are established via an initial TLS-protected phase or derived from some other shared confidential information available to both the client and the server.

 

Replay Protection

Without replay protection, an attacker can use a compromised (but otherwise valid and authenticated) request more than once, gaining access to a protected resource. To mitigate this, clients include both a nonce and a timestamp when making requests. This gives the server enough information to prevent replay attacks.

The nonce is generated by the client, and is a string unique across all requests with the same timestamp and key identifier combination.

The timestamp enables the server to restrict the validity period of the credentials where requests occuring afterwards are rejected. It also removes the need for the server to retain an unbounded number of nonce values for future checks. By default, Hawk uses a time window of 1 minute to allow for time skew between the client and server (which in practice translates to a maximum of 2 minutes as the skew can be positive or negative).

Using a timestamp requires the client's clock to be in sync with the server's clock. Hawk requires both the client clock and the server clock to use NTP to ensure synchronization. However, given the limitations of some client types (e.g. browsers) to deploy NTP, the server provides the client with its current time (in seconds precision) in response to a bad timestamp.

There is no expectation that the client will adjust its system clock to match the server (in fact, this would be a potential attack vector). Instead, the client only uses the server's time to calculate an offset used only for communications with that particular server. The protocol rewards clients with synchronized clocks by reducing the number of round trips required to authenticate the first request.

Usage Example

 Server code:

var Http = require('http');
var Hawk = require('hawk');


// Credentials lookup function

var credentialsFunc = function (id, callback) {

    var credentials = {
        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
        algorithm: 'sha256',
        user: 'Steve'
    };

    return callback(null, credentials);
};

// Create HTTP server

var handler = function (req, res) {

    // Authenticate incoming request

    Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {

        // Prepare response

        var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!');
        var headers = { 'Content-Type': 'text/plain' };

        // Generate Server-Authorization response header

        var header = Hawk.server.header(credentials, artifacts, { payload: payload, contentType: headers['Content-Type'] });
        headers['Server-Authorization'] = header;

        // Send the response back

        res.writeHead(!err ? 200 : 401, headers);
        res.end(payload);
    });
};

// Start server

Http.createServer(handler).listen(8000, 'example.com');
View Code

 

Client code:

var Request = require('request');
var Hawk = require('hawk');


// Client credentials

var credentials = {
    id: 'dh37fgj492je',
    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
    algorithm: 'sha256'
}

// Request options

var requestOptions = {
    uri: 'http://example.com:8000/resource/1?b=1&a=2',
    method: 'GET',
    headers: {}
};

// Generate Authorization request header

var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'some-app-data' });
requestOptions.headers.Authorization = header.field;

// Send authenticated request

Request(requestOptions, function (error, response, body) {

    // Authenticate the server's response

    var isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body });

    // Output results

    console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));
});
View Code

 

Hawk utilized the SNTP module for time sync management. By default, the local machine time is used. To automatically retrieve and synchronice the clock within the application, use the SNTP 'start()' method.

Hawk.sntp.start();

 

Protocol Example

The client attempts to access a protected resource without authentication, sending the following HTTP request to the resource server:

GET /resource/1?b=1&a=2 HTTP/1.1

Host: example.com:8000

 

The resource server returns an authentication challenge.

HTTP/1.1 401 Unauthorized

WWW-Authenticate: Hawk

 

The client has previously obtained a set of Hawk credentials for accessing resources on the "http://example.com/" server. The Hawk credentials issued to the client include the following attributes:

  • Key identifier:      dh37fgj492je
  • Key:      werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn
  • Algorithm: sha256

The client generates the authentication header by calculating a timestamp (e.g. the number of seconds since January 1, 1970 00:00:00 GMT), generating a nonce, and constructing the normalized request string (each value followed by a newline character):

hawk.1.header
1353832234
j4h3g2
GET
/resource/1?b=1&a=2
example.com
8000

some-app-ext-data

 

The request MAC is calculated using HMAC with the specified hash algorithm "sha256" and the key over the normalized request string. The result is base64-encoded to produce the request MAC:

6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=

 

The client includes the Hawk key identifier, timestamp, nonce, application specific data, and request MAC with the request using the HTTP Authorization request header field:

GET /resource/1?b=1&a=2 HTTP/1.1
Host: example.com:8000
Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="

 

The server validates the request by calculating the request MAC again based on the request received and verifies the validity and scope of the Hawk credentials. If valid, the server responds with the requested resource.

 

Payload Validation

Hawk provides optional payload validation. When generating the authentication header, the client calculates a payload hash using the specified hash algorithm. The hash is calculated over the concatenated value of (each followed by a newline character):

  • hawk.1.payload
  • the content-type in      lowercase, without any parameters (e.g. application/json)
  • the request payload prior      to any content encoding (the exact representation requirements should be      specified by the server for payloads other than simple single-part ascii      to ensure interoperability)

For example:

  • Payload: Thank you for flying Hawk
  • Content Type: text/plain
  • Hash (sha256): Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=

Results in the following input to the payload hash function (newline terminated values):

hawk.1.payload
text/plain
Thank you for flying Hawk

 

Which produces the following hash value:

Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=

 

The client constructs the normalized request string (newline terminated values):

hawk.1.header
1353832234
j4h3g2

POST
/resource/1?a=1&b=2

example.com
8000


Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=
some-app-ext-data

 

Then calculates the request MAC and includes the Hawk key identifier, timestamp, nonce, payload hash, application specific data, and request MAC, with the request using the HTTP Authorization request header field:

POST /resource/1?a=1&b=2 HTTP/1.1
Host: example.com:8000
Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="

 

It is up to the server if and when it validates the payload for any given request, based solely on it's security policy and the nature of the data included.

If the payload is available at the time of authentication, the server uses the hash value provided by the client to construct the normalized string and validates the MAC. If the MAC is valid, the server calculates the payload hash and compares the value with the provided payload hash in the header. In many cases, checking the MAC first is faster than calculating the payload hash.

However, if the payload is not available at authentication time (e.g. too large to fit in memory, streamed elsewhere, or processed at a different stage in the application), the server may choose to defer payload validation for later by retaining the hash value provided by the client after validating the MAC.

It is important to note that MAC validation does not mean the hash value provided by the client is valid, only that the value included in the header was not modified. Without calculating the payload hash on the server and comparing it to the value provided by the client, the payload may be modified by an attacker.

 

Response Payload Validation

Hawk provides partial response payload validation. The server includes the Server-Authorization response header which enables the client to authenticate the response and ensure it is talking to the right server. Hawk defines the HTTP Server-Authorization header as a response header using the exact same syntax as the Authorization request header field.

The header is contructed using the same process as the client's request header. The server uses the same credentials and other artifacts provided by the client to constructs the normalized request string. The ext and hash values are replaced with new values based on the server response. The rest as identical to those used by the client.

The result MAC digest is included with the optional hash and ext values:

Server-Authorization: Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"

 

Browser Support and Considerations

A browser script is provided for including using a <script> tag in lib/browser.js. It's also a component.

Hawk relies on the Server-Authorization and WWW-Authenticate headers in its response to communicate with the client. Therefore, in case of CORS requests, it is important to consider sending Access-Control-Expose-Headers with the value "WWW-Authenticate, Server-Authorization" on each response from your server. As explained in the specifications, it will indicate that these headers can safely be accessed by the client (using getResponseHeader() on the XmlHttpRequest object). Otherwise you will be met with a "simple response header" which excludes these fields and would prevent the Hawk client from authenticating the requests.You can read more about the why and how in this article

 

Single URI Authorization

There are cases in which limited and short-term access to a protected resource is granted to a third party which does not have access to the shared credentials. For example, displaying a protected image on a web page accessed by anyone. Hawk provides limited support for such URIs in the form of a bewit - a URI query parameter appended to the request URI which contains the necessary credentials to authenticate the request.

Because of the significant security risks involved in issuing such access, bewit usage is purposely limited only to GET requests and for a finite period of time. Both the client and server can issue bewit credentials, however, the server should not use the same credentials as the client to maintain clear traceability as to who issued which credentials.

In order to simplify implementation, bewit credentials do not support single-use policy and can be replayed multiple times within the granted access timeframe.

 

Bewit Usage Example

var Http = require('http');
var Hawk = require('hawk');


// Credentials lookup function

var credentialsFunc = function (id, callback) {

    var credentials = {
        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
        algorithm: 'sha256'
    };

    return callback(null, credentials);
};

// Create HTTP server

var handler = function (req, res) {

    Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {

        res.writeHead(!err ? 200 : 401, { 'Content-Type': 'text/plain' });
        res.end(!err ? 'Access granted' : 'Shoosh!');
    });
};

Http.createServer(handler).listen(8000, 'example.com');

 Bewit code generation:

var Request = require('request');
var Hawk = require('hawk');


// Client credentials

var credentials = {
    id: 'dh37fgj492je',
    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
    algorithm: 'sha256'
}

// Generate bewit

var duration = 60 * 5;      // 5 Minutes
var bewit = Hawk.uri.getBewit('http://example.com:8080/resource/1?b=1&a=2', { credentials: credentials, ttlSec: duration, ext: 'some-app-data' });
var uri = 'http://example.com:8000/resource/1?b=1&a=2' + '&bewit=' + bewit;

 

 

Security Considerations

The greatest sources of security risks are usually found not in Hawk but in the policies and procedures surrounding its use. Implementers are strongly encouraged to assess how this module addresses their security requirements. This section includes an incomplete list of security considerations that must be reviewed and understood before deploying Hawk on the server. Many of the protections provided in Hawk depends on whether and how they are used.

 

MAC Keys Transmission

Hawk does not provide any mechanism for obtaining or transmitting the set of shared credentials required. Any mechanism used to obtain Hawk credentials must ensure that these transmissions are protected using transport-layer mechanisms such as TLS.

 

Confidentiality of Requests

While Hawk provides a mechanism for verifying the integrity of HTTP requests, it provides no guarantee of request confidentiality. Unless other precautions are taken, eavesdroppers will have full access to the request content. Servers should carefully consider the types of data likely to be sent as part of such requests, and employ transport-layer security mechanisms to protect sensitive resources.

 

Spoofing by Counterfeit Servers

Hawk provides limited verification of the server authenticity. When receiving a response back from the server, the server may choose to include a response Server-Authorization header which the client can use to verify the response. However, it is up to the server to determine when such measure is included, to up to the client to enforce that policy.

A hostile party could take advantage of this by intercepting the client's requests and returning misleading or otherwise incorrect responses. Service providers should consider such attacks when developing services using this protocol, and should require transport-layer security for any requests where the authenticity of the resource server or of server responses is an issue.

 

Plaintext Storage of Credentials

The Hawk key functions the same way passwords do in traditional authentication systems. In order to compute the request MAC, the server must have access to the key in plaintext form. This is in contrast, for example, to modern operating systems, which store only a one-way hash of user credentials.

If an attacker were to gain access to these keys - or worse, to the server's database of all such keys - he or she would be able to perform any action on behalf of any resource owner. Accordingly, it is critical that servers protect these keys from unauthorized access.

 

Entropy of Keys

Unless a transport-layer security protocol is used, eavesdroppers will have full access to authenticated requests and request MAC values, and will thus be able to mount offline brute-force attacks to recover the key used. Servers should be careful to assign keys which are long enough, and random enough, to resist such attacks for at least the length of time that the Hawk credentials are valid.

For example, if the credentials are valid for two weeks, servers should ensure that it is not possible to mount a brute force attack that recovers the key in less than two weeks. Of course, servers are urged to err on the side of caution, and use the longest key reasonable.

It is equally important that the pseudo-random number generator (PRNG) used to generate these keys be of sufficiently high quality. Many PRNG implementations generate number sequences that may appear to be random, but which nevertheless exhibit patterns or other weaknesses which make cryptanalysis or brute force attacks easier. Implementers should be careful to use cryptographically secure PRNGs to avoid these problems.

 

Coverage Limitations

The request MAC only covers the HTTP Host header and optionally the Content-Type header. It does not cover any other headers which can often affect how the request body is interpreted by the server. If the server behavior is influenced by the presence or value of such headers, an attacker can manipulate the request headers without being detected. Implementers should use the ext feature to pass application-specific information via the Authorization header which is protected by the request MAC.

The response authentication, when performed, only covers the response payload, content-type, and the request information provided by the client in it's request (method, resource, timestamp, nonce, etc.). It does not cover the HTTP status code or any other response header field (e.g. Location) which can affect the client's behaviour.

 

Future Time Manipulation

The protocol relies on a clock sync between the client and server. To accomplish this, the server informs the client of its current time when an invalid timestamp is received.

If an attacker is able to manipulate this information and cause the client to use an incorrect time, it would be able to cause the client to generate authenticated requests using time in the future. Such requests will fail when sent by the client, and will not likely leave a trace on the server (given the common implementation of nonce, if at all enforced). The attacker will then be able to replay the request at the correct time without detection.

The client must only use the time information provided by the server if:

  • it was delivered over a      TLS connection and the server identity has been verified, or
  • the tsm      MAC digest calculated using the same client credentials over the timestamp      has been verified.

 

Client Clock Poisoning

When receiving a request with a bad timestamp, the server provides the client with its current time. The client must never use the time received from the server to adjust its own clock, and must only use it to calculate an offset for communicating with that particular server.

 

Bewit Limitations

Special care must be taken when issuing bewit credentials to third parties. Bewit credentials are valid until expiration and cannot be revoked or limited without using other means. Whatever resource they grant access to will be completely exposed to anyone with access to the bewit credentials which act as bearer credentials for that particular resource. While bewit usage is limited to GET requests only and therefore cannot be used to perform transactions or change server state, it can still be used to expose private and sensitive information.

 

Host Header Forgery

Hawk validates the incoming request MAC against the incoming HTTP Host header. However, unless the optional host and port options are used with server.authenticate(), a malicous client can mint new host names pointing to the server's IP address and use that to craft an attack by sending a valid request that's meant for another hostname than the one used by the server. Server implementors must manually verify that the host header received matches their expectation (or use the options mentioned above).

 

转载于:https://www.cnblogs.com/dehai/articles/4944719.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
<?php namespace Dflydev\Hawk\Client; use Dflydev\Hawk\Credentials\Credentials; use Dflydev\Hawk\Nonce\NonceProviderInterface; use Dflydev\Hawk\Time\TimeProviderInterface; class ClientTest extends \PHPUnit_Framework_TestCase {     /**      * @test      */     public function shouldCreateBewit()     {         $client = ClientBuilder::create()->build();         $tentTestVectorsCredentials = new Credentials(             'HX9QcbD-r3ItFEnRcAuOSg',             'sha256',             'exqbZWtykFZIh2D7cXi9dA'         );         $this->assertEquals(             'ZXhxYlpXdHlrRlpJaDJEN2NYaTlkQVwxMzY4OTk2ODAwXE8wbWhwcmdvWHFGNDhEbHc1RldBV3ZWUUlwZ0dZc3FzWDc2dHBvNkt5cUk9XA',             $client->createBewit(                 $tentTestVectorsCredentials,                 'https://example.com/posts',                 0,                 array(                     'timestamp' => 1368996800,                 )             )         );     } }超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。1960年美国人Ted Nelson构思了一种通过计算机处理文本信息的方法,并称之为超文本(hypertext),这成为了HTTP超文本传输协议标准架构的发展根基。Ted Nelson组织协调万维网协会(World Wide Web Consortium)和互联网工程工作小组(Internet Engineering Task Force )共同合作研究,最终发布了一系列的RFC,其中著名的RFC 2616定义了HTTP 1.1。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值