On Questioning Science

While science is based on questioning, “questioning” means “questioning, then developing a plan to test your new hypothesis, carrying out your test, documenting and publishing your results, then discussing those results with the scientific community”.
Questioning cannot just stop with a gut feeling, some one-off event you witnessed, or something you’re neighbor’s dog-walker’s friend overheard whilst riding the bus. You cannot just believe that the acceleration of gravity on Earth is -1.5 m/s^2. You believe it, design an experiment to measure the acceleration of gravity, measure it, and … well, find out that you’re wrong.
I have a quip that I use with Anya — she knows you’re not supposed to break laws. And she knows there are “laws of physics”. So she put it together and announced proudly that we may not break the laws of physics. (And, I expect, that meant that there were some physics police wandering around ready to fine you). I tell her she’s welcome to break the laws of physics, but then she needs to publish her proposed ‘new laws of physics’ that explain what she was able to do in a peer-reviewed journal. Because they’re not laws like a group of random politicians decided something is illegal. They’re laws like the scientific community believes it is impossible. And most of us are thrilled to learn we’re wrong and gain a better understanding of the world around us.

First Hatchling

Our first baby chick hatched today — a cross between our Green Queen an the Bresse rooster. There was an egg that pipped earlier, but that chick didn’t make it (one of the small, first eggs laid by one of the Bresse hens). This one, however, hatched overnight!

Fortify on Demand Remediation – Header Manipulation: Cookies

This is a quick one — putting user input into a cookie is bad — they can throw in CRLF’s and add extra “stuff” into the header

setcookie("ECCKTHistoryCookieSamName", $strLogonUserID, time()+86400, "/sampleTool", $cookiescope, 1);

Strip out the CR, LF, and CRLF’s:

setcookie("ECCKTHistoryCookieSamName", str_replace(array("\r\n", "\n", "\r"), ' ', $strLogonUserID), time()+86400, "/sampleTool", $cookiescope, 1);

 

Chicken Loss Redux. Redux.

What a week! The Rhode Island being snatched up by a dog kicked off a week of losses here — one of our egg layers, Tilly, died on Monday. She was one of our smaller, cuddlier chickens. One of our hives has no bees. And today another egg layer, Soaring Eagle, disappeared. Hopefully she’s out in the woods somewhere and will be by the coop in the morning. Or she made a nest out in the woods. She’s a Jersey Giant, but our smallest chicken. Instead of growing, she put her energy into being a magic chicken. And she was our very cuddliest chicken. Fingers crossed for her …

Fortify on Demand Remediation – Password Management: Hardcoded Password and Privacy Violation

These two vulnerabilities occur in the obvious case — you’ve hard coded a password or some sort of private info (e.g. SSN) and then printed it out to the browser. Don’t do that! But it also seems to occur quite frequently when Fortify on Demand doesn’t like your variable name. As an example, I have a string that provides a consistent error message when user authentication fails.

I then print the string to the screen when the user’s logon fails. Fortify says I am disclosing the user’s password. I’m obviously not. Simply renaming the variable sorts it. Now … yes, this is silly. But it’s a lot easier than trying to convince someone in Security to manually review the code, acknowledge that something about a bad password error is a totally reasonable (and descriptive) variable name, and add an exception for your code. Since bad password is error 49, I just used that in the now less descriptive variable name [ (1) Not too many people know the LDAP error codes off the top of their head, and (2) there are actually a handful of ldap bind return codes that will print this error].

Fortify on Demand Remediation – SQL Injection

This vulnerability occurs when you accept user input and then use that input in a SQL query. The basic remediation is to use oci_bind_by_name to bind variables into placeholders.

A query using an equivalence clause

The simplest case is a query with an equivalence clause.

The code:

        $strQuery = "SELECT DISTINCT EXCHANGE_CARRIER_CIRCUIT_ID, CIRCUIT_DESIGN_ID FROM circuit$strDBLink WHERE EXCHANGE_CARRIER_CIRCUIT_ID = '$strECCKT' ORDER BY CIRCUIT_DESIGN_ID";
        $stmt = oci_parse($kpiprd_conn, $strQuery);
        oci_set_prefetch($stmt, 300);
        oci_execute($stmt);

Becomes:

        $strQuery = "SELECT DISTINCT EXCHANGE_CARRIER_CIRCUIT_ID, CIRCUIT_DESIGN_ID FROM circuit$strDBLink WHERE EXCHANGE_CARRIER_CIRCUIT_ID IN :ecckt ORDER BY CIRCUIT_DESIGN_ID";
        $stmt = oci_parse($kpiprd_conn, $strQuery);
        oci_bind_by_name($stmt, ':ecckt', $strECCKT);
        oci_set_prefetch($stmt, 300);
        oci_execute($stmt);

The same placeholder can be used with the like query. Use “select something from table where columnname like :placeholdername” followed by an oci_bind_by_name($stmt, “:placeholdername”, $strPlaceholderVariable).

A query using an IN clause

– is a little tricker. You could iterate through the array of values and build :placeholder1, :placeholder2, …, :placeholdern and then iterate through the array of values again to bind each value to its corresponding placeholder. A cleaner approach is to use an Oracle collection ($coll in this example) and binding the collection to a single placeholder.

            $arrayCircuitNames = array('L101 /T1    /ELYROHU0012/ELYROHXA32C','111  /ST01  /CHMPILCPF01/CHMPILCPHH3','C102 /OC12  /PHLAPAFG-19/PHLAPAFGW22')
            $strQuery = "SELECT CIRCUIT_DESIGN_ID, EXCHANGE_CARRIER_CIRCUIT_ID  FROM circuit$strDBLink  WHERE EXCHANGE_CARRIER_CIRCUIT_ID in (SELECT column_value FROM table(:myIds))";            $stmt = oci_parse($kpiprd_conn, $strQuery);
            $coll = oci_new_collection($kpiprd_conn, 'ODCIVARCHAR2LIST','SYS');
            foreach ($arrayCircuitNames as $key) {
               $coll->append($key);
            }
            oci_bind_by_name($stmt, ':myIds', $coll, -1, OCI_B_NTY);
            oci_set_prefetch($stmt, 300);
            oci_execute($stmt);
Queries with multiple LIKE conditions

Queries with an OR’d group of LIKE clauses can be handled in a similar fashion – either iterate through the array twice or create a collection with strings that include the wildcard characters, then bind that collection to a single placeholder. Create a semi-join using an EXISTS predicate

            $arrayLocs = array('ERIEPAXE%', 'HNCKOHXA%', 'LTRKARXK%');
            $strQuery = "select location_id, clli_code from network_location$strDBLink where exists (select 1 from TABLE(:likelocs) where clli_code like column_value) order by clli_code";
            $stmt = oci_parse($kpiprd_conn, $strQuery);

            $coll = oci_new_collection($kpiprd_conn, 'ODCIVARCHAR2LIST','SYS');
            foreach ($arrayLocs as $strLocation) {
                $coll->append($strLocation);
            }
            oci_bind_by_name($stmt, ':likelocs', $coll, -1, OCI_B_NTY);
            oci_execute($stmt);
A query using DUAL

Queries where values are selected from DUAL – In some of my recursive queries, I need to include the original input in the result set (particularly, this query finds all equipment mounted under a specific equipment ID – I want to include the input equipment ID as well). Having a bunch of ‘select 12345 from dual’ is fine until I need to use placeholders. This is another place where the collection can be leveraged:

     select column_value equipment_id from TABLE(sys.ODCIVARCHAR2LIST('12345CDE', '23456BCD', '34567ABC') );

Adds each of the values to my result set.

Which means I can use a query like “select column_value as equipment_id from TABLE(:myIDs)” and bind the collection to :myIDs.

Fortify on Demand Remediation – Cookie Security: Overly Broad

Cookies are tied to hostnames and paths. This vulnerability occurs because not every site is its own hostname – when you own all of application.example.com/*, this is basically a false positive. But, if you host your app on a shared URL (e.g. look at www.rushworth.us/lisa and www.rushworth.us/scott and www.rushworth.us/owa … these are three different sites on my home web server. Scott, on is web site, could set a cookie with a path of “/” that uses the same name as a cookie I use on my site – my site would then use the stuff Scott stored through his site. Not such a problem in our scenarios, but a huge problem if you’re talking about a hundred different people’s blogs on some shared domain.

To sort the vulnerability, set the cookie path to something more than /

Fortify on Demand Remediation – LDAP Injection

If you build an LDAP search criterion from user input, it’s possible for the user to inject unexpected content into the search. If I say my username is lisa)(cn=*) or lisa)(|(cn=*) … a filter of (sAMAccountName=$strUserInput) becomes something unexpected.

In php, there’s a filter to escape LDAP search filters – use ldap_escape()

$scriteria=ldap_escape("(&($strUIDAttr=$strUserLogonID))", null, LDAP_ESCAPE_FILTER);

Chicken Loss

Yesterday, one of our Rhode Island Red’s got taken by a dog. I was walking the chickens from their coop into their tractor. Like normal, most of them cannot find the door and walk a loop around the tractor looking for a way in. I get the food sprinkled around the grass and fill up the water bowls while they work out how exactly to get themselves into the thing. I saw a light brown animal out of the corner of my eye behind our large oak tree. My instant thought was “bugger, a baby deer … we’re about to get run over by an upset mommy deer!” — and then this dog streaked over. It didn’t hesitate even when I yelled, it nabbed a chicken, and then it took off into our woods. Now I’ll have to wake Anya up so we have two people herding chickens into the tractor!

Fortify on Demand Remediation – Header Injection: Cookies

Cookie injection vulnerabilities occur when user input is stored into a cookie. It’s possible for malicious input to include newline characters that would be parsed out as new elements in the cookie. As an example, if I send my user ID as “lisa\r\nadmin: true” … I’ve got a cookie that says the userID is lisa and admin is true.

With Fortify on Demand, you cannot just filter out \r and \n characters – Fortify still says the code is vulnerable. You can, however, filter out anything apart from alpha-numeric characters (and, I assume, any oddball character that has a legit reason to be included in the user input):

$strLogonUserID = filter_var(preg_replace(‘/[^a-z\d_]/iu’, ”, $_POST[‘strUID’]), FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);