Scan file or folder with bad permissions - php

I'd just like to see a list of files and folders where folder <> 755 and file <> 644
Is there a script that can recursively scan all files/folders on my web server for this info?
My site got hacked, a bunch of files were set to 200 permissions, its a Joomla 1.5 site, so many files/folders, will take for ever to do this manually.
Host at 1and1 and is a linux shared server
I'm looking for a PHP script
SOLUTION (thanks Robert for info)
For some reason on windows and linux folders return 55
I got the function for perms from http://php.net/manual/en/function.fileperms.php
<?php
$path = realpath('.');
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path),RecursiveIteratorIterator::SELF_FIRST);
$c = 0;
foreach($files as $name => $f){
$perm = file_perms($f);
if ($perm!="644" && $perm!="755" && $perm!="55") {
$c++;
echo "<b>".$perm."</b> :: ";
echo $f->getPathname()."<br>";
if ($c==200) {exit();}
}
}
function file_perms($file, $octal = false)
{
if(!file_exists($file)) return false;
$perms = fileperms($file);
$cut = $octal ? 2 : 3;
return substr(decoct($perms), $cut);
}
?>

You can use php with chmod() function and resursive directory iterator
To check file permissions you can use fileperms() function. It returns the file's permissions as a numeric mode. You can use resursive directory iterator + this checking with fileperms() and you can set permissions with chmod(). With Directory Iterator you can also use getPerms() method.
Example:
$path = realpath('/path/to/dic');
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path),RecursiveIteratorIterator::SELF_FIRST);
foreach($files as $name => $f){
if($f->getPerms() != 775 && $f->isFile()) {
chmod($fileinfo->getPathname(), 0775);
echo getPathname();
}
}
This will set chmod to 775 for files that have different permissions. You can also use 3 methods to check read/write/exec permmisions:
DirectoryIterator::isExecutable() - Determine if current DirectoryIterator item is executable
DirectoryIterator::isReadable() - Determine if current DirectoryIterator item can be read
DirectoryIterator::isWritable() - Determine if current DirectoryIterator item can be written to

You should upgrade to more recent Joomla! version as soon as possible. Otherwise, you'll face more and more successful attacks in the future, because Joomla! 1.5 has reached EOL (end of life) a long time ago.
Generally it is a good idea to use a tool like Akeeba Admin Tools, which can do exactly what you asked for, and a lot of other useful stuff to harden your Jommla! installation.

find /home/*/public_html -type d -perm 755

Related

How do I keep the most recent OPcache folder only?

I'm new to using OPcache on php 8 and I have some questions. So my folder structure looks like this:
https://i.stack.imgur.com/vb93u.png
Within each folder is the exact same thing, it's the structure of my website.
Why does OPcache generate multiple folders with the same content?
What is the best way to keep only the most recent folder and delete the others? Is there a check that can be done every so often or a setting that overwrites older files with new ones?
I'm fast approaching the file limit with my hosting and need to clear up some space.
I've read the docs but I don't have a lot of knowledge working with servers so any help is greatly appreciated!
Oh and these are the settings in my php.ini:
zend_extension=opcache.so;
opcache.enable=1;
opcache.memory_consumption=32;
opcache.interned_strings_buffer=8;
opcache.max_accelerated_files=3000;
opcache.revalidate_freq=180;
opcache.fast_shutdown=0;
opcache.enable_cli=0;
opcache.revalidate_path=0;
opcache.validate_timestamps=1;
opcache.max_file_size=0;
opcache.file_cache=/mywebsitepath/.opcache;
opcache.file_cache_only=1;
Just in case anyone else has the same problem, this is what I ended up doing. First I tried to use the Wordpress cron manager but I was having issues getting a simple function to work. Instead, in my hosting you can create a cron job and link it to a php file, so I went that route instead. Here's the contents of the cron-jobs.php file which I put in my OPcache folder. Basically it sorts the folders by date modified then deletes the old ones while keeping the fresh one. If anyone has suggestions for improvements, be my guest!
function opcache_clean($dir) {
$folders = array();
foreach (scandir($dir) as $file) {
//we only want the folders, not files
if ( strpos($file, '.') === false ) {
$folders[$file] = filemtime($dir . '/' . $file);
}
}
//only delete the old folders if there is more than one
if (count($folders) > 1) {
arsort($folders);
$folders = array_keys($folders);
//keep the first folder (most recent directory at index 0)
$deletions = array_slice($folders, 1);
foreach($deletions as $delete) {
echo "deleting $delete <br>";
system("rm -rf ".escapeshellarg($delete));
}
}
else {
echo "No folders to delete!";
}
}
//clean the current directory
opcache_clean ( dirname(__FILE__) );

PHP is_dir defective

Strange behaviour, exentially:
(the name of the folder depends on the date - the purpose is a hit counter of the website, broken down by day)
if (!is_dir($folder)) { // first access in the day
mkdir($folder);
}
Well: on the server in internet all works well.
But when i try in local, with the server simulator of Easy PHP, happens that:
(a) The first time, no problem. The folder doesn't exists and it is created.
(b) subsequently, for example to a page refresh, the program flow again goes in the IF (!!!) generating the error (at line of mkdir) of kind: "Warning: mkdir(): No such file or directory in [...]".
All parent part of the directory $folder exists.
Thanks
.
Try using a recursive directory creation function:
function mkdir_r($dirName, $rights = 0777)
{
$dirs = explode(DIRECTORY_SEPARATOR , $dirName);
$dir = '';
if (strpos($dirs[count($dirs) - 1], '.')) {
array_pop($dirs);
}
foreach ($dirs as $part) {
$dir .= $part . DIRECTORY_SEPARATOR ;
if (!is_dir($dir) && strlen($dir) > 0) {
mkdir($dir, $rights);
}
}
}
This way all directories up to the directry you wanted to create are created if they don't exist.
mkdir doesn't work recursively unfortunately.
If anyone faces the issue; Use the native clearstatcache() function after you delete the file.
I'm quoting the interesting part of the original documentation
You should also note that PHP doesn't cache information about non-existent files. So, if you call file_exists() on a file that doesn't exist, it will return false until you create the file. If you create the file, it will return true even if you then delete the file. However unlink() clears the cache automatically.
For further information here is the documentation page: https://www.php.net/manual/en/function.clearstatcache.php

PHP function 'scandir' not working on WordPress hosted on windows

When i am using scandir function i get different results on linux and windows.
Windows i see only folder name
Linux it does the job under
I run a check if WordPress files has been changed ?
function find_all_files($dir, $deep)
{
if(strpos($dir,"wp-content") == false){
$root = scandir($dir);
foreach($root as $value)
{
if($value === '.' || $value === '..') {continue;}
if(is_file("$dir/$value")) {
$tmpFile = "$dir/$value";
if(5000000>#filesize($tmpFile)){
$result[]="$tmpFile";
}
continue;
}
$tmp = "$dir/$value";
if(strpos($tmp,"wp-content") == false){
if($deep == true){
foreach(#$this->find_all_files("$dir/$value",true) as $value)
{
$tmpFile = $value;
if(5000000>#filesize($tmpFile)){
$result[]="$tmpFile";
}
}
}
}
}
//var_dump($result);
return $result;
}
}
I had a similar issue and it all came down to:
1) if you mean "running on windows" OS you need to include, and start from the drive directory (where server is installed) in $dir to scan.
2) Windows might be picky about separators, compare your $dir with Wordpress ABSPATH and try to use PHP constant DIRECTORY_SEPARATOR instead of your own '/' separators.
3) And I asume you working with paths, not urls (http://localhost/wordpress/...plugin/dir/). This is working for me on Windows 7, running Uniserver (LAMP):
$rootfolder = 'startfolder';
$dir = plugin_dir_path(dirname( __FILE__ )).DIRECTORY_SEPARATOR.$rootfolder;
$files = array_slice(scandir($dir), 2);
However, you need to cut down the path end begin in the install dir with ABSPATH or something. But I recommend to test where your filescript is, like plugins folder, to not consume a huge stall on errors while working with this kind of stuff.
Hint!
The PHP docs about scandir has a lot off contributed functions about reading, retriving, scanning functions and issues. Take a look at: http://php.net/manual/en/function.scandir.php
Important!
Do not start messing with windows folder access, and if you do, take a RAW copy of whole www directory first, otherwise exported Worpdress installs could get messy on a Apache server live.
Remember, did you manage to install a new plugin from the Wordpress
admin, you propably dont have a folder access issue.
Hop this helps!

PHP Count through different directories and see which ones have 0 files in them

I have the following folder structure:
images/photo-gallery/2e/
72/
rk/
u3/
va/
yk/
... and so on. Basically, each time an image is uploaded it hashes the name and then creates a folder with the first two letters. So inside of 2e is 2e0gpw1p.jpg
Here's the thing... if I delete an image, it will delete the file but it will keep the folder that it's in. Now when I have a TON of images uploaded, that will be fine since a lot of images will share the same folder.. but until then, I will end up having a bunch of empty directories.
What I want to do is search through the photo-gallery folder and go through each directory and see which folders are empty.. if there are any empty folders then it will remove it.
I know how to do that for a single directory, like the 2e folder. But how would I do it for all the folders inside the photo-gallery folder?
The PHP function rmdir() will throw a warning if the directory is not empty, so you can use it on non-empty directories without risking deleting them. Combine that with scandir() and array_slice (to remove . and ..), and you can do this:
foreach(array_slice(scandir('images/photo-gallery'),2) as $dir) {
#rmdir('images/photo-gallery/' . $dir); // use # to silence the warning
}
while you could do with with php, i'm inclined to use the os for such a task. Of course you can call the below with php
find <parent-dir> -depth -type d -empty -exec rmdir -v {} \;
PLEASE READ THIS WARNING I DID NOT TEST BUT HAVE USED SIMILAR CODE DOZENS OF TIMES. FAMILURIZE YOURSELF WITH THIS AND DO NOT USE IF YOU DO NOT UNDERSTAND WHAT IT IS DOING THIS COULD POTENTIALLY WIPE YOUR SITE FROM THE SERVER.
EDIT BACKUP EVERYTHING BEFORE TRYING THIS YOUR FIRST TIME THE PATH IS VERY VERY IMPORTANT!
Ok with that said this is quite easy :)
<?php
function recursiveDelete($path){
$ignore = array(
'cgi-bin',
'.',
'..'
); // Directories to ignore
$dh = opendir($path); // Open the directory
while(false !== ($file = readdir($dh))){ // Loop through the directory
if(!in_array($file, $ignore)){ // Check that this file is not to be ignored
if(is_dir($path."/".$file)){ // Its a directory, keep going
if(!iterator_count(new DirectoryIterator($path."/".$file)))
rmdir($path."/".$file); // its empty delete it
} else {
recursiveDelete($path."/".$file);// Recursive call to self
}
}
}
}
closedir($dh); // All Done close the directory
}
// WARNING IMPROPERLY USED YOU CAN DUMP YOUR ENTIRE SERVER USE WITH CAUTION!!!!
// I WILL NOT BE HELD RESPONSIBLE FOR MISUSE
recursiveDelete('/some/directoy/path/to/your/gallery');
?>

Moving a file to the Recycle Bin (PHP)

This question is related to a Windows install of PHP5.
Doing a file unlink() makes it difficult for recovery.
Instead I would like to move the file to the Recycle Bin (without doing an exec()).
Do you have any idea?
Thanks for your help.
This is the only solution that works and it's portable in all drives.
function Recycle($filename)
{
if (is_file($filename) === true)
{
$filename = realpath($filename);
$recycle = glob(current(explode('\\', $filename, 2)) . '\\RECYCLER\\*', GLOB_ONLYDIR);
if (is_array($recycle) === true)
{
return rename($filename, current($recycle) '\\' . basename($filename));
}
}
return false;
}
Deleted files are correctly moved to for instance:
O:\RECYCLER\S-1-5-21-1715567821-1390067357-1417001333-1003
Restore from the Recycle Bin should be possible, however I've not tested it.
EDIT: I just updated this function to work with files that have relative paths.
why dont you just create one folder and name it "Recycle Bin" .. then instead of doing an unlink() .. just move the files to this "Recycle Bin" folder??
If you wish to move a file, use the rename() php function.
Then later you can run a cron script which checks the time of the files and then you can delete files, say, older than 10 days etc.
I hope this helps.
This works for me, using MaDdoGs CmdUtils, under Win7 x64, php 5.4.24. Also with large files, odd filenames, ...
function recycle($filename)
{
if ( !is_file($filename) )
return false;
system( __DIR__.'/third-party/Recycle.exe -f "'.$filename.'"', $r );
return $r;
}

Categories