SignatureDoesNotMatch error with Amazon S3 and ColdFusion PutObject request - security

Probably simple issue but pulling hair out trying to figure it out.
This code to generate a signature and make a rest post to s3 works perfectly:
<cfset cs = "PUT\n\n#arguments.contentType#\n#dateTimeString#\nx-amz-acl:#arguments.acl#\nx-amz-storage-class:#arguments.storageClass#\n/#arguments.bucketName#/#arguments.keyName#">
...
<cfhttp method="PUT" url="https://s3.amazonaws.com/#arguments.bucketName#/#arguments.keyName#" timeout="#arguments.HTTPtimeout#">
<cfhttpparam type="header" name="Authorization" value="AWS #variables.accessKeyId#:#signature#">
<cfhttpparam type="header" name="Content-Type" value="#arguments.contentType#">
<cfhttpparam type="header" name="Date" value="#dateTimeString#">
<cfhttpparam type="header" name="x-amz-acl" value="#arguments.acl#">
<cfhttpparam type="header" name="x-amz-storage-class" value="#arguments.storageClass#">
<cfhttpparam type="body" value="#binaryFileData#">
</cfhttp>
But I want to add s3 managed AES256 encryption which if I understand right should be as simple as adding the x-amz-server-side​-encryption header with the value of AES256 but this does not work:
<cfset cs = "PUT\n\n#arguments.contentType#\n#dateTimeString#\nx-amz-acl:#arguments.acl#\nx-amz-storage-class:#arguments.storageClass#\nx-amz-server-side​-encryption:aes256\n/#arguments.bucketName#/#arguments.keyName#">
...
<cfhttp method="PUT" url="https://s3.amazonaws.com/#arguments.bucketName#/#arguments.keyName#" timeout="#arguments.HTTPtimeout#">
<cfhttpparam type="header" name="Authorization" value="AWS #variables.accessKeyId#:#signature#">
<cfhttpparam type="header" name="Content-Type" value="#arguments.contentType#">
<cfhttpparam type="header" name="Date" value="#dateTimeString#">
<cfhttpparam type="header" name="x-amz-acl" value="#arguments.acl#">
<cfhttpparam type="header" name="x-amz-storage-class" value="#arguments.storageClass#">
<cfhttpparam type="header" name="x-amz-server-side​-encryption" value="aes256">
<cfhttpparam type="body" value="#binaryFileData#">
</cfhttp>
The signature method is:
<cffunction name="createSignature" returntype="string" access="public" output="false">
<cfargument name="stringIn" type="string" required="true" />
<!--- Replace "\n" with "chr(10) to get a correct digest --->
<cfset var fixedData = replace(arguments.stringIn,"\n","#chr(10)#","all")>
<!--- Calculate the hash of the information --->
<cfset var digest = HMac(fixedData, variables.secretAccessKey, "HMACSHA1", "utf-8")>
<!--- fix the returned data to be a proper signature --->
<cfset var signature = ToBase64( binaryDecode(digest, "hex" ) )>
<cfreturn signature>
</cffunction>
When trying to use encryption I get "The request signature we calculated does not match the signature you provided. Check your key and signing method."
Its not the keys themselves since I can add/remove/list just fine. I just can't add the encryption header.
Anybody tell me what is wrong?
...And I tried both 'AES256' and 'aes256' as values.

Turns out it was stupid...and it took much digging to find a single line mention it in the docs.
The Amazon headers need to be listed in alphabetical order.
Moving x-amz-server-side​-encryption above x-amz-storage-class and using AES256 solved the problem.

Related

Bing Translator API with Coldfusion

In my coldfusion application im using Microsoft Bing Translation API.
To be honest I don't know where to start? let me write what I have already done.
Registered (https://datamarket.azure.com/account)
Got 3 things from Microsoft
Primary Account Key Eg(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)
Customer ID Eg(xxxxxxxxxxxxx)
App ID Eg(mynameid)
What I have already tried OR Failed Attempts :
ColdFusion:
<cfhttp url="http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=mynameid&from=en&to=de&text=HELLO" result="rs" method="post"></cfhttp>
OUTPUT:
'to' must be a valid language Parameter name
<cfhttp url="http://api.microsofttranslator.com/v2/Http.svc/Translate" result="rs" method="post">
<cfhttpparam name="appId" type="header" value="mynameid" />
<cfhttpparam type="header" name="method" value="POST" />
<cfhttpparam type="header" name="from" value="en" />
<cfhttpparam type="header" name="to" value="de" />
<cfhttpparam type="header" name="text" value="HELLO" />
</cfhttp>
<cfdump var="#rs#">

Query optimization in liferay

I have created a portlet where I want to print the list of users based on some parameter. So for showing list of users I use the following code,
<liferay-ui:search-container delta="10" emptyResultsMessage="no-users-were-found">
<liferay-ui:search-container-results
results="<%= UserLocalServiceUtil.getUsers(0, UserLocalServiceUtil.getUsersCount())%>"
/>
<liferay-ui:search-container-row
className="com.liferay.portal.model.User"
keyProperty="userId"
modelVar="user"
>
<liferay-ui:search-container-column-text
name="name"
value="<%= user.getFullName() %>"
/>
<liferay-ui:search-container-column-text
name="first-name"
property="firstName"
/>
</liferay-ui:search-container-row>
<liferay-ui:search-iterator />
</liferay-ui:search-container>
<liferay-ui:search-container delta="10" emptyResultsMessage="no-users-were-found">
But i don't want all the users list. I need only the list of users whose facebookId = 12345. How can query the condition? Any suggestions please..
Thanks in advance

Should a forbidden page always respond with a 403 code?

I have a ColdFusion website that programmatically handles "forbidden"/"unauthorized" requests in onrequeststart() in Application.cfc based on the logged in user's attributes. For example (FYI: SESSION.User is initialized in onSessionStart():
<cffunction name="onRequestStart" returnType="Boolean" output="false">
<cfargument name="targetPage" type="string" required="true">
<cfparam name="REQUEST.MinSecurityLevel" default="0" />
<cfparam name="REQUEST.IsLoginRequired" default="false" />
<cfif REQUEST.IsLoginRequired AND NOT SESSION.User.isLoggedIn()>
<cfscript>
SESSION.LoginMessage =
"Your session has timed out. Please log in again.";
SESSION.LastPageVisited =
getPageContext().getRequest().getRequestURI();
if (Len(Trim(getPageContext().getRequest().getQueryString())))
SESSION.LastPageVisited =
SESSION.LastPageVisited
& "?"
& getPageContext().getRequest().getQueryString();
</cfscript>
<cflocation url="/user/login/" addtoken="false" />
<cfelseif SESSION.User.getSecurityLevel() LT REQUEST.MinSecurityLevel>
<cfheader statuscode="403" statustext="Forbidden" />
</cfif>
<cfreturn true />
</cffunction>
In IIS (version 7), I have an error page setting with Type "Execute URL" and my custom 403 page path.
I am able to trigger this, and it properly displays my custom 403 page, but it returns a HTTP Response Code 200.
Shouldn't this return a 403?
It seems as though I found a solution in my response to #Miguel-F above. I simply mimicked part of what I'm doing to handle 404 errors:
/missing-template/index.cfm:
<cfheader statuscode="404" statustext="Not Found" />
/not-authorized/index.cfm:
<cfheader statuscode="403" statustext="Forbidden" />
I thought that adding a 403 header to the 403 handler page would result in an endless loop, but it works fine.
I also added in onRequestStart() since there's no need for further processing once the 403 is triggered:
<cfelseif SESSION.User.getSecurityLevel() LT REQUEST.MinSecurityLevel>
<cfheader statuscode="403" statustext="Forbidden" />
<cfreturn false />
</cfif>

Nillable SOAP headers

I would like to allow some of my SOAP header elements to be nillable. This is possible for body elements, but I am not sure if it is allowed from header elements.
In the sample message below, I would like to allow the MessageDateTime to be null.
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://mycompany.com/repositoryservice">
<types>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
attributeFormDefault="qualified"
elementFormDefault="qualified"
targetNamespace="http://mycompany.com/repositoryservice">
<element name="MessageDateTime" type="dateTime" />
<element name="SaveRequest">
<!-- complexType -->
</element>
</schema>
</types>
<message name="SaveRequest_Headers">
<part name="MessageDateTime" element="tns:MessageDateTime" />
</message>
<message name="SaveRequest">
<part name="parameters" element="tns:SaveRequest" />
</message>
<binding name="RepositoryServiceBinding" type="tns:IRepositoryService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="Save">
<soap:operation soapAction="http://mycompany.com/repositoryservice/Save" style="document" />
<input name="SaveRequest">
<soap:header message="tns:SaveRequest_Headers" part="MessageDateTime" use="literal" />
<soap:body use="literal" />
</input>
</operation>
</binding>
<!-- service, portType -->
</definitions>
It is allowed as long as the definition allows for it. In your case, all you have to do is add the nillable="true" to the element's definition. The result on .NET w/ WCF would look something like this:
[System.ServiceModel.MessageHeaderAttribute(Namespace="...")]
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
public System.Nullable<System.DateTime> MessageDateTime;

DocumentDB: Coldfusion Returning 401 Authorization error

I am trying to connect Azure DocumentDB/CosmosDB through the coldfusion but receiving 401 authorization error. I already installed the certificates but still having the same issue. I tried with PHP, Nodejs, both are performing well except ColdFusion. Also tried using coldfusion script but the error remains same. Here is the code what I wrote:
<cfset x_ms_date="#GetHttpTimeString(now())#"/>
<cfset br = "#chr(13)##chr(10)#">
<cfset signStr="GET#br#dbs#br##br##x_ms_date##br##br#" />
<cfset strBase64ValueKey="BASE64_ENCODED_MASTER_KEY" />
<cfset key=ToString(ToBinary(strBase64ValueKey))/>
<cfset x=ToBase64(hmac(LCase(signStr),LCase(key),"HMACSHA256"))>
<cfhttp method="GET" url="https://APP_URL.documents.azure.com/dbs" throwonerror="Yes">
<cfhttpparam name="Authorization" type="header" value="#URLEncodedFormat("type=master&ver=1.0&sig="&x)#">
<cfhttpparam name="x-ms-date" type="header" value="#x_ms_date#">
<cfhttpparam name="x-ms-version" type="header" value="2017-02-22">
</cfhttp>
<cfoutput>
#cfhttp.fileContent#
</cfoutput>
Here is the response from the above code:
{"code":"Unauthorized","message":"The input authorization token can't
serve the request. Please check that the expected payload is built as
per the protocol, and check the key being used. Server used the
following payload to sign: 'get\ndbs\n\nthu, 08 feb 2018 19:52:03
gmt\n\n'\r\nActivityId: aab94428-63a0-4eb7-807b-SOMETHING,
Microsoft.Azure.Documents.Common/1.20.186.1"}
What is the wrong with that code? Thanks in advance
This would work if you change the code to something like this:
<cfset x_ms_date = GetHttpTimeString(now()) />
<cfset strBase64ValueKey = "BASE64_ENCODED_MASTER_KEY" />
<cfset br = chr(10)>
<cfset signStr = "GET#br#dbs#br##br##x_ms_date##br##br#" />
<cfset secret = createObject('java', 'javax.crypto.spec.SecretKeySpec' ).Init(BinaryDecode(strBase64ValueKey, "Base64"), 'HmacSHA256')/>
<cfset mac = createObject('java', "javax.crypto.Mac")/>
<cfset mac = mac.getInstance("HmacSHA256")/>
<cfset mac.init(secret)/>
<cfset x = mac.doFinal(LCase(signStr).GetBytes())>
<cfset sig = BinaryEncode(x, "Base64")>
<cfset token = URLEncodedFormat("type=master&ver=1.0&sig=#sig#")>
<cfhttp method="GET" url="https://APP_URL.documents.azure.com/dbs" throwonerror="Yes">
<cfhttpparam name="Authorization" type="header" value="#token#">
<cfhttpparam name="x-ms-date" type="header" value="#x_ms_date#">
<cfhttpparam name="x-ms-version" type="header" value="2017-02-22">
</cfhttp>
<cfoutput>
#cfhttp.fileContent#
</cfoutput>

Resources