G'day:
I'm back into the work swing of things now - having been remote for the last month - so have the usual 1h before work starts to knock out some blog bumpf. I'll not get this article finished in that time, but maybe at lunchtime. We'll see.
Anyway, a week or so ago I decided to start learning PHP, as you will know if you follow this blog with any sort of regularity. I promised to blog my progress, and it really seems like there hasn't been much yet. However I did dive in straight away and do some tutorials, I've just not had a chance (or motivation) to write anything about my findings yet.
But here I am now.
Tuesday, 30 April 2013
Monday, 29 April 2013
PHP: built-in web server
G'day:
This is a real quick one as I have only 20min before I'm due to start work. And I need to go to the supermarket yet to get my breakfast.
So far I'm messed around with running PHP on Apache and IIS, and I think I lamented that PHP didn't seem to have a built-in web server option (although whether this made it into an article I'm not sure: I can't find it). Well whilst reading some docs during my KL to London flight last week, I saw mention of a built-in web server, so I decided I'd better look into this at some stage.
This is a real quick one as I have only 20min before I'm due to start work. And I need to go to the supermarket yet to get my breakfast.
So far I'm messed around with running PHP on Apache and IIS, and I think I lamented that PHP didn't seem to have a built-in web server option (although whether this made it into an article I'm not sure: I can't find it). Well whilst reading some docs during my KL to London flight last week, I saw mention of a built-in web server, so I decided I'd better look into this at some stage.
Labels:
PHP
Tuesday, 23 April 2013
ColdFusion REST: is this a bug (in either CF or just my understanding)?
G'day:
(And, no, this is not a case of Betteridge's Law... I'm actually asking a question 'cos I don't know the answer).
I was having a mess around REST stuff this afternoon, half-heartedly trying to work out what the question actually was that someone asked on Twitter, and came across some puzzling behaviour. I don't really know REST from Adam (as it were) so this is definitely a question, not a statement.
(And, no, this is not a case of Betteridge's Law... I'm actually asking a question 'cos I don't know the answer).
I was having a mess around REST stuff this afternoon, half-heartedly trying to work out what the question actually was that someone asked on Twitter, and came across some puzzling behaviour. I don't really know REST from Adam (as it were) so this is definitely a question, not a statement.
Labels:
Bugs,
CFML,
ColdFusion 10,
REST
CFML compilation into Java .class files
G'day:
Once again, Stack Overflow is my muse. Today a person called David Mulder is asking a question the answer to which relates to how CFML source code is processed into a Java .class file before the class file is then executed.
David's question was basically why this code doesn't behave how one might hope:
Once again, Stack Overflow is my muse. Today a person called David Mulder is asking a question the answer to which relates to how CFML source code is processed into a Java .class file before the class file is then executed.
David's question was basically why this code doesn't behave how one might hope:
<!---test.cfm --->
<cfset msg = "G'day World">
<cfoutput>
<cfinclude template="incNoOutput.cfm">
</cfoutput>
<cfinclude template="incWithOutput.cfm">
<!--- incNoOutput.cfm --->
#msg#<br>
<!--- incWithOutput.cfm --->
<cfoutput>#msg#</cfoutput><br>
Labels:
CFML,
ColdFusion,
David Mulder,
StackOverflow
Saturday, 20 April 2013
Completely useless information about a quirk in ColdFusion's CFML
G'day:
I'm just preparing to return to the UK on Tuesday evening (I'm currently in NZ), and as I do not intend to set foot back on these shores for a long time, there's been a lot of beer-drinking with NZ-based mates for the last few days. I was at the pub from 3pm until [I have no recollection of leaving, really] yesterday, and am about to head off to another pub to drink again with some different mates (and some of the same mates again). We're mustering at 1pm. I'm still feeling the rigors of yesterday's effort, and am trying to steel myself to start again. I have about an hour before I need to head out, so this is a very quick and silly article.
I'm just preparing to return to the UK on Tuesday evening (I'm currently in NZ), and as I do not intend to set foot back on these shores for a long time, there's been a lot of beer-drinking with NZ-based mates for the last few days. I was at the pub from 3pm until [I have no recollection of leaving, really] yesterday, and am about to head off to another pub to drink again with some different mates (and some of the same mates again). We're mustering at 1pm. I'm still feeling the rigors of yesterday's effort, and am trying to steel myself to start again. I have about an hour before I need to head out, so this is a very quick and silly article.
Labels:
CFML,
Sean Corfield
More bugs that annoy me: CFHEADER & restSetResponse() (and CFCONTENT, whilst I'm about it)
G'day:
This came up whilst I was writing the code for the last article. In my Application.cfc, I had this onRequest() interceptor:
Note how I'm raising an exception if the template is a "restricted" one. This sends a "500 Internal Server Error" back to the client. This is incorrect, as the server hasn't had one of those. What I should be returning is a "403 Forbidden", because that best describes the response.
But how am I to do this in a script-based CFC?
I can't use the script equivalent of <cfheader> because there isn't one (bug 3350715). I recalled there is a function restSetResponse(), but that only works in REST responses (and even then, it hardly works in a useful fashion). I have since raised a bug relating to this: 3546046.
Thinking about it further... why is it restSetResponse()? Why is it not just setResponse()? If there's a rationale for this functionality in the response from a REST request, then the same rationale exists for any other sort of request response. This function deals with HTTP, it's nothing specific to REST. I've raised another bug for this too: 3546047 (it's a bug, because it's a stupid inplementation, even if it's by design).
And while I'm about it: there's no script equivalent of <cfcontent> either. And that pisses me off too (bug 3133316). Come on Adobe... you need to get all this stuff over into CFScript quick smart.
--
Adam
This came up whilst I was writing the code for the last article. In my Application.cfc, I had this onRequest() interceptor:
public void function onRequest(required string requestedFile){
writelog(file="requests",text=arguments.requestedFile);
if (arguments.requestedFile does not contain "restricted"){
include arguments.requestedFile;
writelog(file="requests", text="#arguments.requestedFile# Completed OK");
}else{
writelog(file="requests", text="#arguments.requestedFile# Blocked", type="warning");
throw(type="InvalidFileException");
}
}
Note how I'm raising an exception if the template is a "restricted" one. This sends a "500 Internal Server Error" back to the client. This is incorrect, as the server hasn't had one of those. What I should be returning is a "403 Forbidden", because that best describes the response.
But how am I to do this in a script-based CFC?
I can't use the script equivalent of <cfheader> because there isn't one (bug 3350715). I recalled there is a function restSetResponse(), but that only works in REST responses (and even then, it hardly works in a useful fashion). I have since raised a bug relating to this: 3546046.
Thinking about it further... why is it restSetResponse()? Why is it not just setResponse()? If there's a rationale for this functionality in the response from a REST request, then the same rationale exists for any other sort of request response. This function deals with HTTP, it's nothing specific to REST. I've raised another bug for this too: 3546047 (it's a bug, because it's a stupid inplementation, even if it's by design).
And while I'm about it: there's no script equivalent of <cfcontent> either. And that pisses me off too (bug 3133316). Come on Adobe... you need to get all this stuff over into CFScript quick smart.
--
Adam
It's easy to create a security hole in your application with onCfcRequest()
G'day:
Man... PHP continues to take a back seat with me, as interesting ColdFusion stuff keeps cropping up. Well: my definition of "interesting", anyhow.
Today on Stackoverflow I was reminded of a potential "gotcha" that onCfcRequest() brings to the table. One that has bitten me on the bum in the past, has done so with the person on S/O too, and has probably bitten other people too. And the "gotcha" creates quite a gaping security hole in the application if one doesn't deal with it.
I've not seen much coverage of this, so I'll detail it here.
First some background.
When Application.cfc was implemented back in CFMX7 (?), one of the methods added was a request interceptor, onRequest(). Instead of the requested file being run, onRequest() was run instead. This gives one's application a chance to do [something] regarding the requested template before, after and/or instead of running the template. An example would be this:
If I browse to each of publicFile.cfm and restrictedFile.cfm, I get the expected results on the screen, and this in the log:
So that's quite cool.
However note how the requested file is included. This approach won't be suitable for remote method requests, so for those, there is a method onCfcRequest(). This works the same way, but invokes the CFC & method, passing in the specified arguments:
(Obviously the same logic as per the onRequest() method could be used here too, but I've omitted it for the sake af clarity).
OK, great. What's the problem?
Well consider this CFC:
Which methods are intended to be called here? Just the remote one. But here's the thing... a method call is only "remote" if it's being called from outwith the application. And when using onCfcRequest(), where is the method actually being called from? From this statement:
Which is inside the application. It's not registered as a remote call, because it's not being called remotely! This means that as well as all remote methods, one can also actually access all public methods too (package and private ones are still secure). This is something people don't necessarily realise, so one might inadvertently expose a helluva lot more of one's API than is the intent. YIKES.
So what's the mitigation here? Well one needs to do something similar to the logic we employed in onRequest() to block restricted files, but the problem is tricky to work around than that. One needs to do this:
Basically one needs to look at the object's metadata and check to see if the method being called is remote. If so: all good; if not: block it.
So make sure you do this in your onCfcRequest(). Otherwise you could be leaving yourself a bit open.
--
Adam
Man... PHP continues to take a back seat with me, as interesting ColdFusion stuff keeps cropping up. Well: my definition of "interesting", anyhow.
Today on Stackoverflow I was reminded of a potential "gotcha" that onCfcRequest() brings to the table. One that has bitten me on the bum in the past, has done so with the person on S/O too, and has probably bitten other people too. And the "gotcha" creates quite a gaping security hole in the application if one doesn't deal with it.
I've not seen much coverage of this, so I'll detail it here.
First some background.
When Application.cfc was implemented back in CFMX7 (?), one of the methods added was a request interceptor, onRequest(). Instead of the requested file being run, onRequest() was run instead. This gives one's application a chance to do [something] regarding the requested template before, after and/or instead of running the template. An example would be this:
// Application.cfc
component {
public void function onRequest(required string requestedFile){
writelog(file="requests",text=arguments.requestedFile);
if (arguments.requestedFile does not contain "restricted"){
include arguments.requestedFile;
writelog(file="requests", text="#arguments.requestedFile# Completed OK");
}else{
writelog(file="requests", text="#arguments.requestedFile# Blocked", type="warning");
throw(type="InvalidFileException");
}
}
}
<!---publicFile.cfm --->
This is the public file
<!--- restrictedFile.cfm --->
Should not be able to access this!
If I browse to each of publicFile.cfm and restrictedFile.cfm, I get the expected results on the screen, and this in the log:
/shared/git/blogExamples/onRequest/publicFile.cfm
/shared/git/blogExamples/onRequest/publicFile.cfm Completed OK
/shared/git/blogExamples/onRequest/restrictedFile.cfm
/shared/git/blogExamples/onRequest/restrictedFile.cfm Blocked
So that's quite cool.
However note how the requested file is included. This approach won't be suitable for remote method requests, so for those, there is a method onCfcRequest(). This works the same way, but invokes the CFC & method, passing in the specified arguments:
public any function onCfcRequest(required string cfc, required string method, required struct args){
return invoke(cfc, method, args);
}
(Obviously the same logic as per the onRequest() method could be used here too, but I've omitted it for the sake af clarity).
OK, great. What's the problem?
Well consider this CFC:
component {
remote string function remoteMethod(){
return "From remoteMethod()";
}
public string function publicMethod(){
return "From publicMethod()";
}
package string function packageMethod(){
return "From packageMethod()";
}
private string function privateMethod(){
return "From rivateMethod()";
}
}
Which methods are intended to be called here? Just the remote one. But here's the thing... a method call is only "remote" if it's being called from outwith the application. And when using onCfcRequest(), where is the method actually being called from? From this statement:
return invoke(cfc, method, args);
Which is inside the application. It's not registered as a remote call, because it's not being called remotely! This means that as well as all remote methods, one can also actually access all public methods too (package and private ones are still secure). This is something people don't necessarily realise, so one might inadvertently expose a helluva lot more of one's API than is the intent. YIKES.
So what's the mitigation here? Well one needs to do something similar to the logic we employed in onRequest() to block restricted files, but the problem is tricky to work around than that. One needs to do this:
public any function onCfcRequest(required string cfc, required string method, required struct args){
var o = createObject(arguments.cfc);
var metadata = getMetadata(o[method]);
if (structKeyExists(metadata, "access") && metadata.access == "remote"){
return invoke(o, method, args);
}else{
throw(type="InvalidMethodException", message="Invalid method called", detail="The method #method# does not exists or is inaccessible remotely");
}
}
Basically one needs to look at the object's metadata and check to see if the method being called is remote. If so: all good; if not: block it.
So make sure you do this in your onCfcRequest(). Otherwise you could be leaving yourself a bit open.
--
Adam
Labels:
Application.cfc,
CFML
Subscribe to:
Posts (Atom)