Key Points
- Monitoring file integrity is essential for website management and helps detect when files are added, modified, deleted, or corrupted by maliciously. Hashing the contents of a file is a reliable way to monitor such changes.
- PHP's
hash_file()
function can be used to create a file structure configuration file for monitoring. The hash value of each file can be stored for later comparisons to detect any changes. - You can set a database table to store the hash value of a file, where
file_path
stores the path of the file on the server, andfile_hash
stores the hash value of a file. - PHP's
RecursiveDirectoryIterator
class can be used to traverse the file tree and collect hashes for comparison. Theintegrity_hashes
database can then be updated with these hashes. Thearray_diff_assoc()
function of PHP can be used to check for differences, which helps identify files that have been added, deleted, or changed.
Collaborate on various situations in website management
Consider how to solve the following situations when managing a website:
- Accidentally adding, modifying or deleting files
- Maliciously add, modify or delete files
- Files are corrupted
More importantly, do you know if one of these happens? If your answer is no, please continue reading. In this guide, I will demonstrate how to create a file structure configuration file that can be used to monitor file integrity.
The best way to determine if a file has been changed is to hash its contents. PHP provides multiple hash functions, but for this project, I decided to use the hash_file()
function. It provides a variety of different hashing algorithms, which will make my code easy to modify if I decide to change it later. Hash is used in a variety of applications, from password protection to DNA sequencing. The hashing algorithm works by converting data into a fixed-size repeatable encrypted string. They are designed such that even slight modifications to the data should produce very different results. When two or more different data produce the same string result, it is called "conflict". The strength of each hashing algorithm can be measured by its speed and probability of collision. In my example, I will use the SHA-1 algorithm because it is fast, has low probability of conflict, and has been widely used and fully tested. Of course, you are welcome to research other algorithms and use any algorithm you like. After obtaining the hash value of the file, it can be stored for later comparison. If the file hashing later does not return the same hash string as before, then we know that the file has been changed.
Database
First, we need to layout a base table to store the hash value of the file. I will use the following pattern:
CREATE TABLE integrity_hashes ( file_path VARCHAR(200) NOT NULL, file_hash CHAR(40) NOT NULL, PRIMARY KEY (file_path) );
file_path
The path to the file on the storage server, since the value is always unique (because two files cannot occupy the same location in the file system), it is our primary key. I specified its maximum length to 200 characters, which should allow some longer file paths. file_hash
Stores the hash value of the file, which will be a SHA-1 40-character hexadecimal string.
Collect files
The next step is to build the configuration file for the file structure. We define the path to start collecting files and iterate over each directory recursively until we overwrite the entire branch of the file system and can optionally exclude certain directories or file extensions. We collect the required hash values ??when it traversing the file tree and then store it in the database or for comparison. PHP provides several ways to traverse the file tree; for simplicity, I will use the RecursiveDirectoryIterator
class.
<?php define("PATH", "/var/www/"); $files = array(); // 要獲取的擴(kuò)展名,空數(shù)組將返回所有擴(kuò)展名 $ext = array("php"); // 要忽略的目錄,空數(shù)組將檢查所有目錄 $skip = array("logs", "logs/traffic"); // 構(gòu)建配置文件 $dir = new RecursiveDirectoryIterator(PATH); $iter = new RecursiveIteratorIterator($dir); while ($iter->valid()) { // 跳過不需要的目錄 if (!$iter->isDot() && !in_array($iter->getSubPath(), $skip)) { // 獲取特定文件擴(kuò)展名 if (!empty($ext)) { // PHP 5.3.4: if (in_array($iter->getExtension(), $ext)) { if (in_array(pathinfo($iter->key(), PATHINFO_EXTENSION), $ext)) { $files[$iter->key()] = hash_file("sha1", $iter->key()); } } else { // 忽略文件擴(kuò)展名 $files[$iter->key()] = hash_file("sha1", $iter->key()); } } $iter->next(); }
Note that I referenced the same folder twice in the $skip
array. Just because I chose to ignore a specific directory doesn't mean that the iterator also ignores all subdirectors, depending on your needs, which can be useful or annoying. The logs
class gives us access to multiple methods: RecursiveDirectoryIterator
- Check if we are using valid files
valid()
- Determine whether the directory is "." or ".."
isDot()
- Return to the folder name where the file pointer is currently located
getSubPath()
- Return the full path and file name
key()
- Restart the loop
next()
method was added in PHP 5.3.4, which returns the file extension. If your PHP version supports it, you can use it to filter unwanted entries instead of what I did with getExtension()
. After execution, the code should fill the pathinfo()
array with results similar to: $files
<code>Array ( [/var/www/test.php] => b6b7c28e513dac784925665b54088045cf9cbcd3 [/var/www/sub/hello.php] => a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa [/var/www/sub/world.php] => da39a3ee5e6b4b0d3255bfef95601890afd80709 )</code>After building the configuration file, it is very easy to update the database.
<?php $db = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD); // 清除舊記錄 $db->query("TRUNCATE integrity_hashes"); // 插入更新的記錄 $sql = "INSERT INTO integrity_hashes (file_path, file_hash) VALUES (:path, :hash)"; $sth = $db->prepare($sql); $sth->bindParam(":path", $path); $sth->bindParam(":hash", $hash); foreach ($files as $path => $hash) { $sth->execute(); }
Check the difference
You now know how to build a new configuration file for the directory structure and how to update records in the database. The next step is to combine it into some kind of real application, such as a cron job with email notifications, an admin interface, or anything else you like. If you just want to collect a list of changed files without caring how they change, the easiest way is to extract the data from the database into an array similar to and use PHP's $files
function to remove unwanted content. array_diff_assoc()
CREATE TABLE integrity_hashes ( file_path VARCHAR(200) NOT NULL, file_hash CHAR(40) NOT NULL, PRIMARY KEY (file_path) );
In this example, $diffs
will be populated with any found differences, or if the file structure is complete, it will be an empty array. Unlike array_diff()
, array_diff_assoc()
will use the key in comparison, which is important when we conflict, such as two empty files have the same hash value. If you want to go a step further, you can add some simple logic to accurately determine how the file is affected, whether it is deleted, changed, or added.
<?php define("PATH", "/var/www/"); $files = array(); // 要獲取的擴(kuò)展名,空數(shù)組將返回所有擴(kuò)展名 $ext = array("php"); // 要忽略的目錄,空數(shù)組將檢查所有目錄 $skip = array("logs", "logs/traffic"); // 構(gòu)建配置文件 $dir = new RecursiveDirectoryIterator(PATH); $iter = new RecursiveIteratorIterator($dir); while ($iter->valid()) { // 跳過不需要的目錄 if (!$iter->isDot() && !in_array($iter->getSubPath(), $skip)) { // 獲取特定文件擴(kuò)展名 if (!empty($ext)) { // PHP 5.3.4: if (in_array($iter->getExtension(), $ext)) { if (in_array(pathinfo($iter->key(), PATHINFO_EXTENSION), $ext)) { $files[$iter->key()] = hash_file("sha1", $iter->key()); } } else { // 忽略文件擴(kuò)展名 $files[$iter->key()] = hash_file("sha1", $iter->key()); } } $iter->next(); }
When we traverse the results in the database, we do multiple checks. First, use array_key_exists()
to check if the file path in our database appears in $files
, and if not, the file must have been deleted. Second, if the file exists but the hash does not match, the file must have been changed or not changed. We store each check into a temporary array called $tmp
and finally, if the number in $files
is greater than the number in the database, then we know that the remaining unchecked files have been added. Once done, $diffs
is either an empty array or contains any differences found in the form of a multidimensional array, which might look like this:
<code>Array ( [/var/www/test.php] => b6b7c28e513dac784925665b54088045cf9cbcd3 [/var/www/sub/hello.php] => a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa [/var/www/sub/world.php] => da39a3ee5e6b4b0d3255bfef95601890afd80709 )</code>
To display results in a more user-friendly format (such as the management interface), you can for example iterate over the results and output them as bulleted lists.
<?php $db = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD); // 清除舊記錄 $db->query("TRUNCATE integrity_hashes"); // 插入更新的記錄 $sql = "INSERT INTO integrity_hashes (file_path, file_hash) VALUES (:path, :hash)"; $sth = $db->prepare($sql); $sth->bindParam(":path", $path); $sth->bindParam(":hash", $hash); foreach ($files as $path => $hash) { $sth->execute(); }
At this point, you can provide a link to trigger the operation of updating the database with the new file structure (in which case you might choose to store $files
in a session variable), or if you do not approve the differences, you can handle them as needed.
Summary
I hope this guide will help you better understand file integrity monitoring. Installing such content on your website is a valuable security measure and you can rest assured that your files will remain the same as you intend. Of course, don't forget to back up regularly. in case.
(The FAQ part of the original text should be retained here, because the content of this part has nothing to do with the code part, belongs to the supplementary description, and does not fall into the category of pseudo-originality)
The above is the detailed content of PHP Master | Monitoring File Integrity. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

TosecurelyhandleauthenticationandauthorizationinPHP,followthesesteps:1.Alwayshashpasswordswithpassword_hash()andverifyusingpassword_verify(),usepreparedstatementstopreventSQLinjection,andstoreuserdatain$_SESSIONafterlogin.2.Implementrole-basedaccessc

To safely handle file uploads in PHP, the core is to verify file types, rename files, and restrict permissions. 1. Use finfo_file() to check the real MIME type, and only specific types such as image/jpeg are allowed; 2. Use uniqid() to generate random file names and store them in non-Web root directory; 3. Limit file size through php.ini and HTML forms, and set directory permissions to 0755; 4. Use ClamAV to scan malware to enhance security. These steps effectively prevent security vulnerabilities and ensure that the file upload process is safe and reliable.

In PHP, the main difference between == and == is the strictness of type checking. ==Type conversion will be performed before comparison, for example, 5=="5" returns true, and ===Request that the value and type are the same before true will be returned, for example, 5==="5" returns false. In usage scenarios, === is more secure and should be used first, and == is only used when type conversion is required.

The methods of using basic mathematical operations in PHP are as follows: 1. Addition signs support integers and floating-point numbers, and can also be used for variables. String numbers will be automatically converted but not recommended to dependencies; 2. Subtraction signs use - signs, variables are the same, and type conversion is also applicable; 3. Multiplication signs use * signs, which are suitable for numbers and similar strings; 4. Division uses / signs, which need to avoid dividing by zero, and note that the result may be floating-point numbers; 5. Taking the modulus signs can be used to judge odd and even numbers, and when processing negative numbers, the remainder signs are consistent with the dividend. The key to using these operators correctly is to ensure that the data types are clear and the boundary situation is handled well.

Yes, PHP can interact with NoSQL databases like MongoDB and Redis through specific extensions or libraries. First, use the MongoDBPHP driver (installed through PECL or Composer) to create client instances and operate databases and collections, supporting insertion, query, aggregation and other operations; second, use the Predis library or phpredis extension to connect to Redis, perform key-value settings and acquisitions, and recommend phpredis for high-performance scenarios, while Predis is convenient for rapid deployment; both are suitable for production environments and are well-documented.

TostaycurrentwithPHPdevelopmentsandbestpractices,followkeynewssourceslikePHP.netandPHPWeekly,engagewithcommunitiesonforumsandconferences,keeptoolingupdatedandgraduallyadoptnewfeatures,andreadorcontributetoopensourceprojects.First,followreliablesource

PHPbecamepopularforwebdevelopmentduetoitseaseoflearning,seamlessintegrationwithHTML,widespreadhostingsupport,andalargeecosystemincludingframeworkslikeLaravelandCMSplatformslikeWordPress.Itexcelsinhandlingformsubmissions,managingusersessions,interacti

TosettherighttimezoneinPHP,usedate_default_timezone_set()functionatthestartofyourscriptwithavalididentifiersuchas'America/New_York'.1.Usedate_default_timezone_set()beforeanydate/timefunctions.2.Alternatively,configurethephp.inifilebysettingdate.timez
