Issues (1)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

lib/wepay-signer.rb (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
##
0 ignored issues
show
Your coding style requires you to use snake case for source file names. That is all lower case characters with underscores to seperate words.
Loading history...
2
# Copyright (c) 2015-2016 WePay.
3
#
4
# Based on a stripped-down version of the AWS Signature v4 implementation.
5
#
6
# http://opensource.org/licenses/Apache2.0
7
##
8
9 1
require 'openssl'
10
11
##
12
# The root WePay namespace.
13
##
14 1
module WePay
15
16
  ##
17
  # The Signer class is designed for those who are signing data on behalf of a public-private keypair.
18
  #
19
  # In principle, the "client party" has public key (i.e., `client_id`) has a matching private key
20
  # (i.e., `client_secret`) that can be verified by both the signer, as well as the client, but
21
  # by nobody else as we don't want to make forgeries possible.
22
  #
23
  # The "signing party" has a simple an identifier which acts as an additional piece of entropy in the
24
  # algorithm, and can help differentiate between multiple signing parties if the client party does
25
  # something like try to use the same public-private keypair independently of a signing party
26
  # (as is common with GPG signing).
27
  #
28
  # For example, in the original AWS implementation, the "self key" for AWS was "AWS4".
29
  ##
30 1
  class Signer
31
32 1
    attr_reader :self_key
33 1
    attr_reader :client_id
34 1
    attr_reader :client_secret
35 1
    attr_reader :hash_algo
36
37
    ##
38
    # Constructs a new instance of this class.
39
    #
40
    # @param client_id [String] A string which is the public portion of the keypair identifying the client party. The
41
    #     pairing of the public and private portions of the keypair should only be known to the client party and the
42
    #     signing party.
43
    # @param client_secret [String] A string which is the private portion of the keypair identifying the client party.
44
    #     The pairing of the public and private portions of the keypair should only be known to the client party and
45
    #     the signing party.
46
    # @option options [String] self_key (WePay) A string which identifies the signing party and adds additional entropy.
47
    # @option options [String] hash_algo (sha512) The hash algorithm to use for signing.
48
    ##
49 1
    def initialize(client_id, client_secret, options = {})
50
      @client_id = client_id.to_s
51
      @client_secret = client_secret.to_s
52
53
      options = {
54
        :self_key  => 'WePay',
55
        :hash_algo => 'sha512',
56
      }.merge(options)
57
58
      @self_key = options[:self_key].to_s
59
      @hash_algo = options[:hash_algo].to_s
60
    end
61
62
    ##
63
    # Sign the payload to produce a signature for its contents.
64
    #
65
    # @param payload [Hash] The data to generate a signature for.
66
    # @option payload [required, String] token The one-time-use token.
67
    # @option payload [required, String] page The WePay URL to access.
68
    # @option payload [required, String] redirect_uri The partner URL to return to once the action is completed.
69
    # @return [String] The signature for the payload contents.
70
    ##
71 1
    def sign(payload)
72
      payload = payload.merge({
73
        :client_id     => @client_id,
74
        :client_secret => @client_secret,
75
      })
76
77
      scope = create_scope
78
      context = create_context(payload)
79
      s2s = create_string_to_sign(scope, context)
80
      signing_key = get_signing_salt
81
      OpenSSL::HMAC.hexdigest(@hash_algo, signing_key, s2s)
82
    end
83
84
    ##
85
    # Signs and generates the query string URL parameters to use when making a request.
86
    #
87
    # If the `client_secret` key is provided, then it will be automatically excluded from the result.
88
    #
89
    # @param  payload [Hash] The data to generate a signature for.
90
    # @option payload [required, String] token The one-time-use token.
91
    # @option payload [required, String] page The WePay URL to access.
92
    # @option payload [required, String] redirect_uri The partner URL to return to once the action is completed.
93
    # @return [String] The query string parameters to append to the end of a URL.
94
    ##
95 1
    def generate_query_string_params(payload)
96
      payload.delete(:client_secret) if payload.has_key? :client_secret
97
98
      signed_token = sign(payload)
99
      payload[:client_id] = @client_id
100
      payload[:stoken] = signed_token
101
      qsa = []
102
103
      payload.keys.sort.each do | key |
104
        qsa.push sprintf("%s=%s", key, payload[key])
105
      end
106
107
      qsa.join("&")
108
    end
109
110 1
private
111
112
    ##
113
    # Creates the string-to-sign based on a variety of factors.
114
    #
115
    # @param scope [String] The results of a call to the `create_scope()` method.
116
    # @param context [String] The results of a call to the `create_context()` method.
117
    # @return [String] The final string to be signed.
118
    ##
119 1
    def create_string_to_sign(scope, context)
120
      scope_hash = OpenSSL::Digest.new(@hash_algo, scope)
121
      context_hash = OpenSSL::Digest.new(@hash_algo, context)
122
      sprintf "SIGNER-HMAC-%s\n%s\n%s\n%s\n%s", @hash_algo.upcase, @self_key, @client_id, scope_hash, context_hash
123
    end
124
125
    ##
126
    # An array of key-value pairs representing the data that you want to sign.
127
    # All values must be `scalar`.
128
    #
129
    # @param  payload [Hash] The data that you want to sign.
130
    # @option payload [String] self_key (WePay) A string which identifies the signing party and adds additional entropy.
131
    # @return [String] A canonical string representation of the data to sign.
132
    ##
133 1
    def create_context(payload)
134
      canonical_payload = []
135
136
      payload.keys.each do | key |
137
        val = payload[key].downcase
138
        key = key.downcase
139
        canonical_payload.push(sprintf "%s=%s\n", key, val)
140
      end
141
142
      canonical_payload.sort!
143
144
      signed_headers_string = payload.keys.sort_by {|s| s.to_s }.join(";")
145
      canonical_payload.join("") + "\n" + signed_headers_string
146
    end
147
148
    ##
149
    # Gets the salt value that should be used for signing.
150
    #
151
    # @return [String] The signing salt.
152
    ##
153 1
    def get_signing_salt
154
      self_key_sign = OpenSSL::HMAC.digest(@hash_algo, @client_secret, @self_key)
155
      client_id_sign = OpenSSL::HMAC.digest(@hash_algo, self_key_sign, @client_id)
156
      OpenSSL::HMAC.digest(@hash_algo, client_id_sign, 'signer')
157
    end
158
159
    ##
160
    # Creates the "scope" in which the signature is valid.
161
    #
162
    # @return [String] The string which represents the scope in which the signature is valid.
163
    ##
164 1
    def create_scope
165
      sprintf "%s/%s/signer", @self_key, @client_id
166
    end
167
168
  end
169
end
170