ColdFusion CGI Variables, Hot Linking, And Poor Documentation

Posted October 4, 2006 at 8:46 AM

Tags: ColdFusion

A HUGE part of what project Skin Spider does is use the ColdFusion CFHttp tag to grab image and video files off of public sites for local storage. For anyone who has ever tried to use CFHttp to grab an image, a good amount of time it returns with a 403 : Forbidden Access error. This is done by the remote server as a "security" feature that stops users from hot linking their photos (linking to them across domains). To over come this, you can trick the remote server into thinking that you are using it locally by supplying a fake referer CGI variable:

 Launch code in new window » Download code as text file »

  • <!---
  • Grab the remote image to save locally. In this example, we
  • are grabbing the image as a binary and then writing it to
  • disk.
  • --->
  • <cfhttp
  • url="http://matureladies.adultbouncerhost.com/0007/mat1.jpg"
  • method="GET"
  • result="objSpider"
  • resolveurl="yes"
  • useragent="#CGI.http_user_agent#"
  • getasbinary="yes"
  • throwonerror="yes">
  •  
  • <!---
  • Trick the remote server into thinking you are browsing
  • it's pages. Do this by sending a LOCAL url (local
  • relative to the remote machine) as the referer.
  • --->
  • <cfhttpparam
  • type="CGI"
  • name="http_referer"
  • value="http://matureladies.adultbouncerhost.com/0007/index.html"
  • encoded="false"
  • />
  •  
  • </cfhttp>

However, if you run that code above, you will see that it actually fails. It returns a 403 : Forbidden Access error. The generated content of the returned page is:

You must supply a local referer to get URL '/0007/mat1.jpg' from this server.

What gives? We supplied the proper HTTP_REFERER value? After all, we gave it the video gallery that the image came from. I have dealt with this a number of times and have never gotten it to work. LUCKILY, just this morning, I stumbled across an old old comment from 2002 on the Macromedia web site about CGI variables and CFHttParam tags.

The comment explains that the CGI variables sent in the CFHttpParam tag are NOT verbatim the CGI variables that are exposed by the CGI scope. Now, as someone who first learned about CGI variables from the CGI scope, this was totally news to me. Here is the comment he placed:

This page fails to mention that when passing a value for the name attribute when trying to use type="cgi", the name is NOT the same as the CGI variable name as CF exposes it. For instance, if you want to pass in a "referer", you wouldn't say CFHTTPPARAM Type="cgi" Name="http_referer" Value="somevalue".

Instead, you need to drop the "http_" and just say Name="referer". And for headers/cgi variables that have multiple parts to their name, such as HTTP_Accept_Encoding, note too that the value to use isn't just "Accept_Encoding".

Instead, you have to use the formal name for the header, as speced at the w3c site among others, http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html. In this case, you'd use Name="accept-encoding", which is typical for their multi-word values.

It would be nice for the CFMX docs to clarify this, as I'm sure many pull their hair out trying to get this to work, relying on their knowledge of these "CGI" variables solely from how they appear in the CF debugging info or a dump of the CGI scope.

Wait, what? Yeah, when you pass in a CGI value for HTTP_REFERER, all you pass in is REFERER as the CGI name. That's crazy. I checked the new MX 7 documentation and I didn't see anything about this. Thank God I found it on a page back from 2002!

So, updating the code above, we get:

 Launch code in new window » Download code as text file »

  • <!---
  • Grab the remote image to save locally. In this example, we
  • are grabbing the image as a binary and then writing it to
  • disk.
  • --->
  • <cfhttp
  • url="http://matureladies.adultbouncerhost.com/0007/mat1.jpg"
  • method="GET"
  • result="objSpider"
  • resolveurl="yes"
  • useragent="#CGI.http_user_agent#"
  • getasbinary="yes"
  • throwonerror="yes">
  •  
  • <!---
  • Trick the remote server into thinking you are browsing
  • it's pages. Do this by sending a LOCAL url (local
  • relative to the remote machine) as the referer.
  •  
  • NOTE: I am now just passing "referer", NOT the original
  • "http_referer".
  • --->
  • <cfhttpparam
  • type="CGI"
  •  
  • name="referer"
  •  
  • value="http://matureladies.adultbouncerhost.com/0007/index.html"
  • encoded="false"
  • />
  •  
  • </cfhttp>

I run that an Blam! It works like a charm. Hot linking has been circumvented and the image is now in the objSpider.FileContent as a binary object. I agree with the comment the dude make above; there are a lot of people out there, including myself, who learned about CGI from ColdFusion. I don't think it is intuitive that what ColdFusion exposes as a CGI variable is the actually CGI variable name. Hmmmph!

Also take note about the "encoded" attribute of the CFHttpParam tag. By default the CFHttpParam tag Url Encodes the passed in value. This puts in all those % characters in the value. We do NOT want this. In fact, if we allow the value in the above example to be encoded then the CFHttp will get denied via 403 again.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page




Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

Reader Comments

Rich Rein
Nov 20, 2006 at 1:54 PM // reply »
14 Comments

Thanks a ton, this post just saved me after banging my head against the wall for a good hour!!


Nov 21, 2006 at 7:40 AM // reply »
6,371 Comments

Rich,

Glad to help. Yeah, I wish this stuff was more apparent.


zmrcic
Jun 24, 2007 at 4:38 AM // reply »
3 Comments

Great work...you are only one tnat wrote something on subject....
Thats OK...but how can I manage "refer" in .NET using WebClient assembly

Thank a lot


Jun 24, 2007 at 12:53 PM // reply »
6,371 Comments

@zmrcic,

Unfortunately, I do not know enough about .NET to give you that kind of advice. Sorry.


zmrcic
Jul 3, 2007 at 6:46 AM // reply »
3 Comments

It al worked for few days...naw I get 403 forbiden again....I checked other PC...it is working on them....I cant browsw page from IE.....
any suggestions?


Jul 3, 2007 at 7:14 AM // reply »
6,371 Comments

You can't browse any pages using IE? Are you talking about using CFHTTP or just plain old browsing the internet?


zmrcic
Feb 28, 2008 at 4:43 AM // reply »
3 Comments

I have new problem, and I guess you are some kind of authority for web questions...
I'm trying to get content of webpage containing frames...url in addressbar never cahnge and I can not see full url(with query string) I have few combo boxes on that page, and when I change its values, page is reloaded, but with no query string that I can read....I guess it should be www.somepage.com?date=2008/2/2
instead I always get www.somepage.com

...How can I get full url, with query string


Feb 28, 2008 at 7:09 AM // reply »
6,371 Comments

@Zmrcic,

If you look page source of the top page, the frameset, it should show you frames and the URLs. But this will only be for the first loaded screen. If the frame has already been reloaded, try right-clicking in the frame. There might be an option somewhere for "open frame in new window" or something like that. Do that and you will be able to get the URL.

You could probably also use something like FireBug to inspect the live code.


CFCoder
Oct 8, 2009 at 3:01 PM // reply »
1 Comments

I have run into an odd situation. In reviewing some old CF code I found a variable referenced as just "query" as in #query# in its usage. I at first assumed this was a local Variable scoped variable but I couldn't find anywhere when it had it's value defined.
I then did some testing and find that <cfoutput>#query#</cfoutput> displays the same value as #cgi.query_string#. Hmmm.
I then tried #cgi.query# and again it displays the same thing. I then tried this:

<cfset query = "nothing">
cgi.Query: <cfoutput>#cgi.query#</cfoutput><br>
and again it displays the URL query string.
Now maybe I just haven't found the script that is secretyly playing this game with me but this appears to be a non-documented "feature" built into ColdFusion. We are running v.8 but it clearly did this prior to our April 2009 switch over from v.6.x at least.

Can you please explain what is going on here?


Oct 31, 2009 at 5:39 PM // reply »
6,371 Comments

@CFCoder,

When I try to dump out #query# I get an undefined value error. There must be something else in your code that is monkeying around.


Post Comment  |  Ask Ben

Recent Blog Comments
Nov 7, 2009 at 5:53 PM
Ask Ben: Javascript String Replace Method
You can find here an advanced function that prepared with javascript replace function. This can make the first letters of words, sentences, lines and whatever you define automatically: http://www.m ... read »
Andrew Neely
Nov 7, 2009 at 4:56 PM
A Moment That Touched Me - The Fountainhead
Ben, Glad you enjoyed the podcast. Yeah, the Tank Riot guys can get really chatty during the episodes, but that's part of the charm of it for me. They've covered everything from Nichola Tesla to Cha ... read »
Nov 7, 2009 at 4:43 PM
Building A Fixed-Position Bottom Menu Bar (ala FaceBook)
Is it possible to make some more MenĂ¼`s ? ... read »
Jill
Nov 7, 2009 at 11:40 AM
How To Unformat Your Code (Like A Pro)
Derek, I think you might be right - sweet! Thanks for the link :) ... read »
Nov 7, 2009 at 11:25 AM
How To Unformat Your Code (Like A Pro)
I think it would be way easier to just use this http://www.logichammer.com/html-formatter/ He just released v3 and it rocks. ... read »
Jill
Nov 7, 2009 at 7:58 AM
How To Unformat Your Code (Like A Pro)
LMAO - this was pretty funny! I have to admit - I also love to reformat code so I can read it. My boss used to tell me to leave my OCD at home. Now I don't feel so bad after reading everyone else' ... read »
Nov 6, 2009 at 10:10 PM
How To Unformat Your Code (Like A Pro)
The timing of this post is just uncanny. I spent the last 15-20 minutes manually un-formatting my "Ben Nadel" style code within a CFC of mine. I was really digging the readability a few weeks ago, bu ... read »
Roe
Nov 6, 2009 at 5:11 PM
Passing Arrays By Reference In ColdFusion - SWEEET!
ArraySort also reorders the results of these java obj's ... read »