PHP File Security Risks and Prevention Explained
Files and Directories with Security Considerations in PHP - Part 6
Foreword: In this part of the series, I talk about Files and Directories with Security Considerations in PHP.
By: Chrysanthus Date Published: 19 Jan 2019
Introduction
Risks are weaknesses from PHP or from you the programmer, that you may ignore; and attackers (hackers) would take advantage of.
The fopen() Function
The syntax for this function is:
resource fopen ( string $filename , string $mode [, bool $use_include_path = FALSE [, resource $context ]] )
fopen() binds a named resource, specified by filename, to a stream.
It returns a file pointer resource on success, or FALSE on error.
Problem really occurs when you are using modes, 'r', 'r+', 'w', 'w+', 'a', 'a+'.
Different operating system families have different line-ending conventions. When you write a text file and want to insert a line break, you need to use the correct line-ending character(s) for your operating system. Unix based systems use \n as the line ending character, Windows based systems use \r\n as the line ending characters and Macintosh based systems use \r as the line ending character.
If you use the wrong line ending characters when writing your files, you might find that other applications that open those files will "look funny".
Windows offers a text-mode translation flag ('t') which will transparently translate \n to \r\n when working with the file.
Prevention: use only the 'r', 'r+', 'w', and 'a' modes and be careful how you code.
The fclose() function
The syntax is:
bool fclose ( resource $handle )
Returns TRUE on success or FALSE on failure.
When testing whether a file has been closed, do not test for 1 instead of true or test for 0 instead of false.
The fgets() function
The syntax is:
string fgets ( resource $handle [, int $length ] )
Gets the next line from file pointer.
Returns a string of up to length - 1 bytes read from the file pointed to by handle. If there is no more data to read in the file pointer, then FALSE is returned.
If an error occurs, FALSE is returned.
Problem: False is returned for no-more-data-left or error. Prevention: discard any data read when false is returned.
The fwrite() function
The syntax is:
int fwrite ( resource $handle , string $string [, int $length ] )
fwrite() writes the contents of string to the file stream pointed to by handle.
fwrite() returns the number of bytes written, or FALSE on error.
Note: Writing to a network stream may end before the whole string is written. Return value of fwrite() may be checked.
Note: On systems which differentiate between binary and text files (i.e. Windows) the file must be opened with 'b' included in fopen() mode parameter.
Note: If handle was fopen()ed in append mode, fwrite()s are atomic (unless the size of string exceeds the filesystem's block size, on some platforms, and as long as the file is on a local filesystem). That is, there is no need to flock() a resource before calling fwrite(); all of the data will be written without interruption.
Note: If writing twice to the file pointer, then the data will be appended to the end of the file content.
The fgetc() Function
The syntax is:
string fgetc ( resource $handle )
Gets the next character from the given file pointer.
Returns a string containing a single character read from the file pointed to, by handle. Returns FALSE on EOF (end-of-file).
Warning: This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE. Use the === operator for testing the return value of this function.
The ftell() Function
The syntax is:
int ftell ( resource $handle )
Returns the position of the file pointer referenced by handle as an integer; i.e., its offset into the file stream.
If an error occurs, returns FALSE.
Note: Because PHP's integer type is signed and many platforms use 32bit integers, some filesystem functions may return unexpected results for files which are larger than 2GB.
Prevention: Test for return value of FALSE with === (not to confuse with 0). Be careful how you code.
The syntax is:
bool feof ( resource $handle )
Tests for end-of-file on a file pointer.
Returns TRUE if the file pointer is at EOF or an error occurs (including socket timeout); otherwise returns FALSE. So, use your own means to detect whether it is end-of-file or socket timeout.
Warning: If a connection opened by fsockopen() wasn't closed by the server, feof() will hang. To workaround this, see later.
Warning: If the passed file pointer is not valid you may get an infinite loop, because feof() fails to return TRUE.
The glob() Function
The syntax of the glob function is:
array glob ( string $pattern [, int $flags = 0 ] )
The glob() function searches for all the pathnames matching pattern according to the rules used by the libc glob() function, which is similar to the rules used by common shells.
pattern
The pattern. No tilde expansion or parameter substitution is done.
Valid flags:
GLOB_MARK - Adds a slash to each directory returned
GLOB_NOSORT - Return files as they appear in the directory (no sorting). When this flag is not used, the pathnames are sorted alphabetically
GLOB_NOCHECK - Return the search pattern if no files matching it were found
GLOB_NOESCAPE - Backslashes do not quote metacharacters
GLOB_BRACE - Expands {a,b,c} to match 'a', 'b', or 'c'
GLOB_ONLYDIR - Return only directory entries which match the pattern
GLOB_ERR - Stop on read errors (like unreadable directories), by default errors are ignored.
Returns an array containing the matched files/directories, an empty array if no file matched or FALSE on error. So do not confuse between returned empty array and returned false
Note: On some systems it is impossible to distinguish between empty match and an error.
Note: This function will not work on remote files as the file to be examined must be accessible via the server's filesystem.
Note: This function isn't available on some systems (e.g. old Sun OS).
Note: The GLOB_BRACE flag is not available on some non GNU systems, like Solaris.
Prevention: Be careful how you code.
The file_exists() Function
bool file_exists ( string $filename )
Checks whether a file or directory exists.
filename
Path to the file or directory.
Returns TRUE if the file or directory specified by filename exists; FALSE otherwise.
Note: This function will return FALSE for symlinks pointing to non-existing files.
Warning: This function returns FALSE for files inaccessible due to safe mode restrictions. However these files still can be included if they are located in safe_mode_include_dir.
Note: The check is done using the real UID/GID instead of the effective one.
Note: Because PHP's integer type is signed and many platforms use 32bit integers, some filesystem functions may return unexpected results for files which are larger than 2GB.
Notes: The results of this function are cached.
int filesize ( string $filename )
Gets the size for the given file.
filename
Path to the file.
Returns the size of the file in bytes, or FALSE (and generates an error of level E_WARNING) in case of an error.
Note: Because PHP's integer type is signed and many platforms use 32bit integers, some filesystem functions may return unexpected results for files which are larger than 2GB.
Note: The results of this function are cached.
The is_file() Function
bool is_file ( string $filename )
Tells whether the given file is a regular file.
filename
Path to the file.
Returns TRUE if the filename exists and is a regular file, FALSE otherwise.
Note: Because PHP's integer type is signed and many platforms use 32bit integers, some filesystem functions may return unexpected results for files which are larger than 2GB.
Note: The results of this function are cached.
getcwd()
string getcwd ( void )
Gets the current working directory.
Note: On some Unix variants, getcwd() will return FALSE if any one of the parent directories does not have the readable or search mode set, even if the current directory does.
mkdir()
bool mkdir ( string $pathname [, int $mode = 0777 [, bool $recursive = FALSE [, resource $context ]]] )
Attempts to create the directory specified by pathname.
Returns TRUE on success or FALSE on failure.
Note: mode is ignored on Windows.
Note: When safe mode is enabled, PHP checks whether the directory in which the script is operating has the same UID (owner) as the script that is being executed.
chroot()
bool chroot ( string $directory )
Changes the root directory of the current process to directory, and changes the current working directory to "/".
Returns TRUE on success or FALSE on failure.
Note: This function is not implemented on Windows platforms.
That is it for this part of the series.
Chrys
Related Links
Basics of PHP with Security ConsiderationsWhite Space in PHP
PHP Data Types with Security Considerations
PHP Variables with Security Considerations
PHP Operators with Security Considerations
PHP Control Structures with Security Considerations
PHP String with Security Considerations
PHP Arrays with Security Considerations
PHP Functions with Security Considerations
PHP Return Statement
Exception Handling in PHP
Variable Scope in PHP
Constant in PHP
PHP Classes and Objects
Reference in PHP
PHP Regular Expressions with Security Considerations
Date and Time in PHP with Security Considerations
Files and Directories with Security Considerations in PHP
Writing a PHP Command Line Tool
PHP Core Number Basics and Testing
Validating Input in PHP
PHP Eval Function and Security Risks
PHP Multi-Dimensional Array with Security Consideration
Mathematics Functions for Everybody in PHP
PHP Cheat Sheet and Prevention Explained
More Related Links