Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!


Inject question (PHP)
New on LowEndTalk? Please Register and read our Community Rules.

All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.

Inject question (PHP)

netomxnetomx Moderator, Veteran
edited November 2012 in General

I'm making a webpage, and want to send a variable with GET, it will be a number.

is this "inject-proof" enough?

if (isset($_GET['id'])) if(is_numeric($_GET['id']))

«1

Comments

  • Depends what you're trying to do. If this is going into a database query, then use PDO's prepare. If you specifically need an integer, use filter_var with FILTER_VALIDATE_INT - is_numeric returns true for decimal numbers (1.41), numbers in scientific notation (1.41e9), and hex (0xFF).

  • netomxnetomx Moderator, Veteran

    It is for this:
    $archivo = file_get_contents($_GET['id'].".txt");

    that's why I call: is numeric?

  • dont do like that;

    • parse GET parameter into a variable: intval
    • use the variable value.
      It will have no harm either with data, post back or like what you are doing.
  • netomxnetomx Moderator, Veteran

    @tinyray said: dont do like that;

    • parse GET parameter into a variable: intval

    why not? It will first check that it is set (so no warnings on the log)
    then, will check if it is numeric. if it is, will use it

  • I can send a parameter to your app that is_numeric function says YES but you get a content from my own server that way. :)

  • netomxnetomx Moderator, Veteran

    @tinyray said: I can send a parameter to your app that is_numeric function says YES but you get a content from my own server that way. :)

    hmm... any example?

  • NexusNexus Member
    edited November 2012

    That code is just checking if it's a numerical value.

    Just do something like

    $number = isset($_GET['number']) ? intval($_GET['number']) : 0;

    Then check for negatives/etc/etc/

  • netomxnetomx Moderator, Veteran

    I finished with this:

    if (isset($_GET['id'])) { $id = intval($_GET['id']); if($id>0) {

  • You could just put (int) behind it? I do that when I'm wanting just an integer from the user.

  • @Roph said: You could just put (int) behind it? I do that when I'm wanting just an integer from the user.

    Exactly. Just do if(isset()) and after that file_get_contents(((int) $_GET['id']) . '.txt'))

  • @netomx

    is_numeric is indeed the best way.
    Always use is_... or a regular expression and you'll be safe from injection.
    Or just check if basedir of new path equals to the directory it's allowed to access.

  • You could use this:

    if (ctype_digit($var)) {
    // code here
    }

    Just make sure $var is a string

  • @BronzeByte said: is_numeric is indeed the best way

    is_numeric will accept + and . in some cases

  • Ultra safe way is to use regex.

  • @soluslabs said: Ultra safe way is to use regex.

    But slow i might add!

  • @soluslabs

    Nah, everything at PHP is slow but it's minimal and you would only notice it on really busy sites/apps.

  • @netomx said: I finished with this:

    intval will still accept - "minus"

  • @BronzeByte said: Nah, everything at PHP is slow but it's minimal and you would only notice it on really busy sites/apps.

    I mean compared to the alternatives

  • filter_var with FILTER_VALIDATE_INT gives you more options than is_int (such as setting a min and max) and doesn't fail on form input.

    $_GET and $_POST data is always treated as a string. If your URL is /index.php?id=23 is_int($_GET['id']) will be false, unless you cast it to an int first (in which case, why are you using is_int on it anyways?).

    is_numeric can lead to unexpected or unwanted results if your input is something like "1.54e9", especially if you're expecting a plain old int.

    Forcing the input to an integer using intval can also lead to unintended results, especially if a true string is passed instead of a numeric string. intval("23") will return 23, as expected, but intval(1e10) will give you 1410065408, intval("1e10") will give you 1, and intval of an array will give you 1 or 0 depending on whether or not the array has any items in it.

    Is this particularly dangerous? Not really. Will it lead to unintended results? It certainly will if you're relying on intval to make sure you've got an integer. If a user asks for record "1e10", they're certainly not expecting to get record 1.

    The point I'm trying to make here is that rather than forcing anything to an integer and possibly getting wrong results, or using functions that don't effectively identify an integer, especially if you're using data from $_GET or $_POST, use filter_var($_GET['id'], FILTER_VALIDATE_INT) instead, and if you don't have an integer, throw an error. FILTER_VALIDATE_INT is the easiest way to be sure that user submitted data is an integer, and if you are expecting an integer, you shouldn't continue if the user submits anything other than an integer.

  • Also the regex:

    if (preg_match("/^[0-9]+$/", $var)) { // only numbers found }

  • +1 to @soluslabs for creativity. -10 to @soluslabs for abuse of regex.

  • @NickM said: +1 to @soluslabs for creativity. -10 to @soluslabs for abuse of regex.

    LOL

  • So will FILTER_VALIDATE_INT work if the GET value was 27692495999674839385 ?

  • @soluslabs said: So will FILTER_VALIDATE_INT work if the GET value was 27692495999674839385 ?

    It will return FALSE if the input is larger than the operating system's maximum integer, which in most cases is OK, since your database is going to have the same constraint. In OP's case, it's also fine, because if you're working with integers that large, you're probably doing something wrong (or stupid).

  • @NickM said: It will return FALSE if the input is larger than the operating system's maximum integer, which in most cases is OK, since your database is going to have the same constraint. In OP's case, it's also fine, because if you're working with integers that large, you're probably doing something wrong (or stupid).

    He just mentions numbers and no maximum value (8 byte integer etc..). Thats the reason ctype_digit would suit him better.

  • typical PHP problem ... one problem, ten almost similar solutions...

    ctype_digit is probabably the best solution but probably not even php developers know why did they invent so many different core commands for one problem.

  • netomxnetomx Moderator, Veteran

    I will have at max 1000 files, so it will be 1000.txt

    Thanks everyone for the suggestions, it seems regex is the safest way.

    Thabks @soluslabs and everyone!

  • netomxnetomx Moderator, Veteran

    Guys, another thing. To clean a string variable, do I just use striphtmltags ? I will receive text from a textbox and then display it on a webpage.

  • joepie91joepie91 Member, Patron Provider
    edited November 2012

    @netomx said: Guys, another thing. To clean a string variable, do I just use striphtmltags ? I will receive text from a textbox and then display it on a webpage.

    You'll want to use htmlspecialchars().

    EDIT: Also, be very careful with using input in a call to something like file_get_contents - it's pretty easy to screw up at a later point in time if not documented right.

    EDIT2: @netomx, using regex for something like this is a bad idea as it's relatively heavy. Use the suggestion that @NickM gave. Also, regex is quite easy to mess up.

  • @netomx said: Thanks everyone for the suggestions, it seems regex is the safest way.

    Your best off with ctype_digit($var)

    • regex is slower
    • filter_var($var ,FILTER_VALIDATE_INT) is not really what you want because you just need to find out if the variable is all numbers. This function will return true if the variable is negative (-12345)
Sign In or Register to comment.