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>
Related
Trying to record "Page Loads" for custom CMS.
On page load, I invoke a CFC that saves page and user information. Works on interior pages but not Homepage.
Every "Homepage Click" records a "visit" to the homepage and then immediately records a link from the homepage to 404 Error. This means that the 404 Page is being loaded (in the background?) and firing the CFC. The verification of this is what is saved in the database. I have no idea how this is happening.
I have researched several posts here - trying varied approaches:
I have tried removing all includes - this did not fix it.
I have tried IIS Mappings - removing all rewrites and redirects - (from /index.cfm to /) - and this did not fix it.
Code as follows:`
<cfinvoke
Component="components.Page_Count"
Method="RecordPageView"
PageID="0"
Title="Homepage"
LinkName="/index.cfm"
IPAddress="#cgi.remote_addr#"
ThisUserAgent="#CGI.HTTP_USER_AGENT#"
Returnvariable="PageLinkRecorded"
>
CFC Code:
<cffunction
name="RecordPageView"
access="public"
returntype="any">
<cfargument name="PageID" type="string" required="no">
<cfargument name="Title" type="string" required="no">
<cfargument name="LinkName" type="string" required="no">
<cfargument name="IPAddress" type="string" required="no">
<cfargument name="ThisUserAgent" type="string" required="no">
<cfparam name="var.ESID" default="">
<cfparam name="var.CookieID" default="0">
<cfparam name="var.Referer" default="">
<cfparam name="var.VisitDate" default="#Now()#">
<cfparam name="var.IPAddress" default="#cgi.remote_addr#">
<cfparam name="var.IsThisABot" default="FALSE">
<cfif arguments.Title NEQ "">
<cfset variables.MyCookieName = Application.CompanyName>
<!--- remove ALL Special Characters --->
<cfset variables.MyCookieName = "#REReplace(variables.MyCookieName,"[^0-9A-Za-z ]","","all")#" />
<!--- remove ALL spaces from the string --->
<cfset variables.MyCookieName = ReReplace(variables.MyCookieName, "[[:space:]]","","ALL")>
<cfif isDefined("COOKIE.#variables.MyCookieName#_UUID") AND Evaluate("COOKIE.#variables.MyCookieName#_UUID") NEQ "">
<cfset VAR.CookieID = Evaluate("COOKIE.#variables.MyCookieName#_UUID")>
<cfelse>
<cfset VAR.CookieID = CreateUUID()>
<cfcookie name="#variables.MyCookieName#_UUID" value="#VAR.CookieID#" expires="NEVER" />
</cfif>
<cfif Len(arguments.ThisUserAgent) GT 0>
<cfloop list="bot\b,crawl,\brss,feed,news,blog,reader,syndication,coldfusion,slurp,google,zyborg,emonitor,jeeves,Googlebot,Google,duckduckbot,Baiduspider,YandexBot,exabot,Sogou,facebot,facebookexternalhit,ia_archiver" index="bot" delimiters=",">
<cfif FindNoCase(bot, arguments.ThisUserAgent)>
<cfset VAR.IsThisABot="TRUE" />
<cfelse>
<cfset VAR.IsThisABot="FALSE" />
</cfif>
</cfloop>
<cfelse>
<cfset VAR.IsThisABot="TRUE" />
</cfif>
<cfif IsDefined("SESSION.Auth.ESID")>
<cfset var.ESID = SESSION.Auth.ESID>
</cfif>
<cfif IsDefined("CGI.script_name")>
<cfset var.ThisPage = CGI.script_name>
</cfif>
<cfif IsDefined("CGI.http_referer") AND CGI.http_referer NEQ "">
<cfset var.Referer = CGI.http_referer>
<cfif FindNoCase(".css", CGI.http_referer)>
<cfset VAR.IsThisABot="TRUE">
</cfif>
<cfelse>
<cfset var.Referer = CGI.QUERY_STRING>
</cfif>
<cfif VAR.IsThisABot EQ "FALSE">
<cfquery datasource="#Application.DSN#" username="#Application.username#" password="#Application.password#" result="CountSaved">
INSERT INTO content_track (PageID,PageTitle,LinkName,ESID,CookieID,Referer,IPAddress)
VALUES (
<cfif arguments.PageID NEQ "">
<cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.PageID#">
<cfelse>
0
</cfif>
,
<cfif arguments.Title NEQ "">
<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.Title#">
<cfelse>
NULL
</cfif>
,
<cfif arguments.LinkName NEQ "">
<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.LinkName#">
<cfelse>
NULL
</cfif>
,
<cfif var.ESID NEQ "">
<cfqueryparam cfsqltype="cf_sql_integer" value="#var.ESID#">
<cfelse>
0
</cfif>
,
<cfif var.CookieID NEQ "">
<cfqueryparam cfsqltype="cf_sql_varchar" value="#var.CookieID#">
<cfelse>
0
</cfif>
,
<cfif var.Referer NEQ "">
<cfqueryparam cfsqltype="cf_sql_varchar" value="#var.Referer#">
<cfelse>
NULL
</cfif>
,
<cfif var.IPAddress NEQ "">
<cfqueryparam cfsqltype="cf_sql_varchar" value="#var.IPAddress#">
<cfelse>
NULL
</cfif>
)
</cfquery>
</cfif>
</cfif>
<cfset PageRecorded = VAR>
<cfreturn PageRecorded>
</cffunction>
My IIS Rules
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<directoryBrowse enabled="false" />
<urlCompression doStaticCompression="true" doDynamicCompression="true" />
<rewrite>
<rules>
<rule name="RedirectWwwToNonWww" stopProcessing="false">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern="^(www\.)(.*)$" />
</conditions>
<action type="Redirect" url="https://{C:2}{REQUEST_URI}" redirectType="Permanent" />
</rule>
<rule name="Imported Rule 1" stopProcessing="true">
<match url="index.cfm" ignoreCase="true" />
<conditions logicalGrouping="MatchAny">
<add input="{URL}" pattern="^.*\.(cfm|cfc|css|gif|png|jpg|jpeg|js|svg)$" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<fileExtensions>
<add fileExtension=".pl" allowed="false" />
</fileExtensions>
</requestFiltering>
</security>
<httpErrors errorMode="DetailedLocalOnly">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" subStatusCode="-1" prefixLanguageFilePath="" path="/Content/404-Error.cfm" responseMode="ExecuteURL" />
</httpErrors>
<staticContent>
<remove fileExtension=".scss" />
<mimeMap fileExtension=".scss" mimeType="text/css" />
</staticContent>
</system.webServer>
</configuration>
I have created a WebTest via Fiddler which POST's to a public endpoint using the basic Authorization method. The call works fine in Fiddler/Postman however when I upload the following webtest as an Azure's Availablity test it fails, giving me a 411 error.
The Web Test:
<?xml version="1.0" encoding="utf-8"?>
<TestCase Name="FiddlerGeneratedWebTest" Id="" Owner="" Description="" Priority="0" Enabled="True" CssProjectStructure="" CssIteration="" DeploymentItemsEditable="" CredentialUserName="" CredentialPassword="" PreAuthenticate="True" Proxy="" RequestCallbackClass="" TestCaseCallbackClass="">
<Items>
<Request Method="POST" Version="1.1" Url="https://myapp.scm.azurewebsites.net/api/triggeredwebjobs/mywebjob/run" ThinkTime="0" Timeout="60" ParseDependentRequests="True" FollowRedirects="True" RecordResult="True" Cache="False" ResponseTimeGoal="0" Encoding="utf-8">
<Headers>
<Header Name="Authorization" Value="Basic JGRldi1sb2NhbGl0eS13ZWItam9iphYVJSN1o0QjlmUXBNZlhjcXJKSHd1RFpYNW1xWlE4MTNzRnRMMUpOc2JFNXVna3l2aWVhQ3pBNXJvYzg=" />
<Header Name="Content-Length" Value="0" />
</Headers>
<QueryStringParameters>
<QueryStringParameter Name="arguments" Value="health" UrlEncode="True" UseToGroupResults="False" />
</QueryStringParameters>
</Request>
</Items>
</TestCase>
The Error
Returned once the availability test fails:
> 1 primary requests, 0 dependant requests and 0 conditional rules failed
> Http Error (subtype '411 - LengthRequired') occured at 09/06/2018
> 05:49:45 (UTC) for Uri
> 'https://myapp.scm.azurewebsites.net/api/triggeredwebjobs/mywebjob/run?arguments=health',
> step #1 with the error '411 - LengthRequired'.
Any help would be greatly appreciated!
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.
I have a problem with disabling ribbon button via javascript custom rule.
The action for that I want to add "enable rule" is called Mscrm.AddExistingRecordFromSubGridAssociated -> which is displayed when subgrid gets focus.
I use the ribbon workbench solution and I almost sure I did everything fine, but it doesn't work.
javascript:
utils.ribbon.isAddExistingDisabled = function(grid) {
return false; //just for test I wrote always false, but it's enabled anyway :/
}
CommandDef:
<CommandDefinition Id="Mscrm.AddExistingRecordFromSubGridAssociated">
<EnableRules>
<EnableRule Id="Mscrm.AppendToPrimary" />
<EnableRule Id="Mscrm.EntityFormIsEnabled" />
<EnableRule Id="my.incident.addMainCause.EnableRule" />
</EnableRules>
<DisplayRules>
<DisplayRule Id="Mscrm.AddExisting" />
<DisplayRule Id="Mscrm.ShowForManyToManyGrids" />
<DisplayRule Id="Mscrm.AppendToPrimary" />
<DisplayRule Id="Mscrm.AppendSelected" />
</DisplayRules>
<Actions>
<JavaScriptFunction FunctionName="Mscrm.GridRibbonActions.addExistingFromSubGridAssociated" Library="/_static/_common/scripts/RibbonActions.js">
<CrmParameter Value="SelectedEntityTypeCode" />
<CrmParameter Value="SelectedControl" />
</JavaScriptFunction>
</Actions>
</CommandDefinition>
Enable rule def:
<EnableRule Id="my.incident.addMainCause.EnableRule">
<CustomRule FunctionName="utils.ribbon.isAddExistingDisabled" Library="$webresource:my_js/incident/common.js" InvertResult="false">
<CrmParameter Value="SelectedControl" />
</CustomRule>
</EnableRule>
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>