basic authentication decode is ignoring the wrong padding

Not applicable

Today I noticed, basic authentication decode policy is ignoring the extra padding of characters. I found because of that even I am sending some extra random character in the Authorization header it is getting successfully validate whereas I expect an error to be thrown.

I had to write custom code to fix this.

Solved Solved
0 2 1,427
1 ACCEPTED SOLUTION

Not applicable

I just wrote a python script to check this, and it works as expected.

import base64


 


try :


    encoded = flow.getVariable("request.header.Authorization")


    encoded2 = encoded[6:]


    data = base64.b64decode(encoded2)


    encoded1 = base64.b64encode(data)

    flow.setVariable("encoded1",encoded1)
    flow.setVariable("encoded2",encoded2)


    if encoded1 != encoded2 :
       flow.setVariable("pass",'')

except :
   flow.setVariable("pass",'')

View solution in original post

2 REPLIES 2

I've tested this and observed the same. The BasicAuthentication policy behaves as you describe - it tolerates "extra characters" that have been appended after the final padding character.

Base64 uses the equals sign as padding. Padding is used to signal to the decoding side the end of the encoded input. It's not strictly necessary as the decoding side can determine the correct length of the input and output deterministically without considering padding. Padding is most useful when concatenating base64 streams to indicate the end of one, and the start of another.

I think what you're seeing is a side effect of the base64 decoded used in Apigee, which strips and ignores all padding characters and anything that follows. This doesn't open any security vulnerability. In other words, you may not need to care that the Authorization header with extra characters is treated as valid.

If you don't like this behavior and don't want to write custom JavaScript code to handle that case, you can use the decodeBase64 function which is available in the MessageTemplate to decode a Basic Authentication header. It might look like this:

<AssignMessage name='AM-DecodeBasicAuth'>
  <AssignVariable>
    <Name>visible</Name>
    <Ref>request.header.authorization</Ref>
  </AssignVariable>


  <AssignVariable>
    <Name>six</Name>
    <Value>6</Value>
  </AssignVariable>


  <AssignVariable>
    <Name>blob</Name>
    <Template>{substring(visible,six)}</Template>
  </AssignVariable>


  <AssignVariable>
    <Name>decoded_blob</Name>
    <Template>{decodeBase64(blob)}</Template>
  </AssignVariable>


</AssignMessage>


This will return the empty string for the decoded_blob, indicating a failure to decode, if extra characters have been appended. You would have to split the resulting decoded blob in order to recover the constituent username and password. You can use JS for that:

    var d = context.getVariable('decoded_blob');
    var parts = d.split(':');
    if (parts.length>1) {
      context.setVariable('decoded_username', parts[0]);
      context.setVariable('decoded_password', parts[1]);
    }

Not applicable

I just wrote a python script to check this, and it works as expected.

import base64


 


try :


    encoded = flow.getVariable("request.header.Authorization")


    encoded2 = encoded[6:]


    data = base64.b64decode(encoded2)


    encoded1 = base64.b64encode(data)

    flow.setVariable("encoded1",encoded1)
    flow.setVariable("encoded2",encoded2)


    if encoded1 != encoded2 :
       flow.setVariable("pass",'')

except :
   flow.setVariable("pass",'')