1

We are working to avoid XSS attacks in a ColdFusion application. After adding <cfset this.scriptprotect=”all”> in our cfapplication tag, it worked only for the form input values which are now changed to InvalidTag. However it is not working for URL query string key values. Also I would like to know, why scriptprotect under the cfapplication tag is not working for URLs <script key insertion within the URL?

I come accross https://gist.github.com/learncfinaweek/4121370; I am including canonicalize in all pages for URL validations. I would like to know what are the validations that should be performed to avoid attacks post canonicalize function.

Miguel-F
  • 13,450
  • 6
  • 38
  • 63
Vishwas S L
  • 169
  • 1
  • 8
  • 4
    The page that you referenced from LearnCFInAWeek is a good resource. Be sure to read the "Additional Resources" links that the page has at the bottom (the links to OWASP). Those will likely answer your question. This site is more for specific programming questions and issues. Not general concepts. – Miguel-F Aug 07 '18 at 11:57
  • 1
    https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet – Shawn Aug 07 '18 at 15:11
  • 1
    Also, I would say that if you are using `canonicalize()` and you hit either multiple encodings or mixed encodings, then you should probably log and ban the user. There aren't really any valid reasons for a legitimate user to accidentally cross either of those cases. – Shawn Aug 07 '18 at 15:22
  • 1
    And what are you trying to pass in the URL? `scriptprotect` is _VERY_ primitive and doesn't really catch a lot of stuff. And I believe it only looks for a small set of non-canonicalized tags. It's always been something that I've turned on but not even remotely relied on. – Shawn Aug 07 '18 at 15:24

1 Answers1

1

You cannot rely on CF exclusively for XSS (or sql injection) attacks. You could write your own code in application.cfc that will look for XSS/SQL Injection attacks in each of the scopes, and run that code in the onRequest() or onRequestStart() methods, depending on how your app is setup. Here's an example (please don't use this code without knowing exactly what it does and you've tested it extensively. This is some code I grabbed out of an app, but it's possible to get false positives and I'm not 100% confident with all the tests):

This code would be in application.cfc

public boolean function onRequestStart (
    required string targetPage) {

    try {

        if (checkForAttack()) {
            location url="/" addtoken=false;
            return true;
        }

        ... do other stuff ...

    } catch (any e) {
        onError(e, "onRequestStart");
    }

    return true;

} // onRequestStart()

private boolean function checkForAttack() {

    // check for any kind of sql injection or xss attack

    var attackFound = false;

    // you could change these tests, or add more tests
    var tests = ["4445434C415245", "cast(\s|%20)*(%28|\()", "(;|%3B)(\s|%20)*DECLARE", /*"exec(\s|%20)*\(",*/ "schema\.columns|table_name|column_name|drop(\s|%20)+table|insert(\s|%20)+into|\.tables", "\.\[sysobjects\]", "\.sysobjects"];
    var ctTests = ArrayLen(tests);
    var ix = 0;
    var key = "";

    if (isDefined("CGI.query_string") && CGI.query_string != "") {
        for (ix = 1; ix <= ctTests; ix++) {
            if (REFindNocase(tests[ix], CGI.query_string) > 0) {
                CGI.query_string = "";
                attackFound = true;
                break;
            }
        }
    }

    if (isDefined("URL")) {
        for (key in URL) {
            for (ix = 1; ix <= ctTests; ix++) {
                if (REFindNocase(tests[ix], URL[key]) > 0) {
                    attackFound = true;
                    URL[key] = "";
                }
            }
        }
    }

    if (isDefined("Form")) {
        for (key in Form) {
            for (ix = 1; ix <= ctTests; ix++) {
                if (reFindNocase(tests[ix], Form[key]) > 0) {
                    attackFound = true;
                    Form[key] = "";
                }
            }
        }
    }

    if (IsDefined("Cookie")) {
        for (key in Cookie) {
            for (ix = 1; ix <= ctTests; ix++) {
                if (REFindNocase(tests[ix], Cookie[key]) > 0) {
                    attackFound = true;
                    Cookie[key] = "";
                }
            }
        }
    }

    return attackFound;

} // checkForAttack()
Redtopia
  • 4,947
  • 7
  • 45
  • 68
  • Where security is concerned, I agree that you shouldn't rely on any one tech, but CF has some pretty nice functionality built in to severely limit the bad things that can happen with XSS and SQLi. There are a few examples online of code that can do this. And with some of the native Java integration, it makes it much nicer. 1/3 – Shawn Aug 07 '18 at 19:35
  • Regarding your example, my first thought is that's a whole lot of looping to go through for each request. I know you say that additional tests can be added, but without much instruction on what these tests do, I'm afraid that many SO users might just copy/paste your solution, giving them a very false sense of security. You probably shouldn't roll your own solution to these. 2/3 – Shawn Aug 07 '18 at 19:35
  • There are utilities out there to scan nefarious inputs. This also doesn't really do much to catch multi-encoded inputs. That's one of the good things that the canonicalize operations do. And there are something close to 60 ways to encode a `script` tag alone. The code and loops to check for all the bad things would be tremendous. Again, I'd look for a pre-made solution. 3/3 – Shawn Aug 07 '18 at 19:35
  • Also, for anyone else coming to this post, I don't know that I would recommend just pushing someone back to the home page if I detected an attack. Again, there might be a few legitimate false positives for some uses, and I'll try to take those into account. But personally I'd rather not take that chance. If I detect a potential injection, XSS, or any other type of attack, that user will be logged, flagged and probably blocked. – Shawn Aug 07 '18 at 19:43
  • I agree that performance is an issue, and looping through the keys in all scopes and executing a regex on them seems like a lot of work to do. If you have any links to share, that would be helpful. This is just part of a solution that I threw together, and I am not suggesting that this is the best solution. However, I will say that I've been running code that's even more restrictive than this on heavily loaded servers, and the server response times have been good. – Redtopia Aug 07 '18 at 22:28
  • CFDocs has good definitions of the CF `encodeForX()` tags (https://cfdocs.org/encodeforhtml), which is a good place to start. OWASP has lots of docs on how to id and prevent XSS, (https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)) OWASP also has a good guide about how to perform data validation (which is necessary to help prevent XSS). (https://www.owasp.org/index.php/Data_Validation) I've used HP Fortify (http://www.ndm.net/sast/hp-fortify) in the past to scan my code for possible problems. It does a pretty good job. This quickly becomes a rabbit hole that's hard to climb out of. – Shawn Aug 08 '18 at 16:16
  • https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet <<< And that's a great resource for some interesting ways to avoid some of the filters to prevent XSS code. – Shawn Aug 08 '18 at 16:17