Asked  7 Months ago    Answers:  5   Viewed   37 times

I have a virus that has infected thousands of files on one of my client's server.

Fortunately, I have dealt with a lot of other malware on this guy's server and this one looks easy to do simple regex on (he put all his websites on the same account :( but I'm working with him to resolve that).

Basically though, unlike most malware I have seen where it injects php BEFORE the closing ?> of the GOOD code (making it very hard to determine whats good code/bad code), this current malware ALWAYS adds a new <?php ... malware ... ?>.

So basically, say there's good code here:

<?php
require('./wp-blog-header.php'); 
?>

Instead of adding some kind of base64_decode eval immediately after the require statement but before the ?> (which can make removal difficult when the page happens to end in a conditional/complex statement), this will always add the following code with a NEW <?php ... ?> like so:

<?php
require('./wp-blog-header.php'); 
?><?php ... malware ...?>

I don't want to put any malicious code up here but, this is how the malicious code always starts:

<?php @error_reporting(0); if (!isset($eva1fYlbakBcVSir)) {$eva1fYlbakBcVSir = "tons and tons of characters";$eva1tYlbakBcVSir = "x633514433x6f1534x70170x65";$SNIPSNIPSNIPSNIP;} ?>

I'd like to search every file for <?php @error_reporting(0); if (!isset and if it's the last PHP statement on the page, then delete everything within the

 Answers

12

Here is how you clean the entire project with pure php.

In no respect shall I incur any liability for any damages, including, but limited to, direct, indirect, special, or consequential damages arising out of, resulting from, or any way connected to the use of the code provided, whether or not based upon warranty, contract, tort, or otherwise; whether or not injury was sustained by persons or property or otherwise; and whether or not loss was sustained from, or arose out of, the results of, the use if this code. ;p

<?php 
//Enter it as it is and escape any single quotes
$find='<?php @error_reporting(0); if (!isset($eva1fYlbakBcVSir)) {$eva1fYlbakBcVSir ='';?>';

echo findString('./',$find);

function findString($path,$find){
    $return='';
    ob_start();
    if ($handle = opendir($path)) {
        while (false !== ($file = readdir($handle))) {
            if ($file != "." && $file != "..") {
                if(is_dir($path.'/'.$file)){
                    $sub=findString($path.'/'.$file,$find);
                    if(isset($sub)){
                        echo $sub.PHP_EOL;
                    }
                }else{
                    $ext=substr(strtolower($file),-3);
                    if($ext=='php'){
                        $filesource=file_get_contents($path.'/'.$file);
                        $pos = strpos($filesource, $find);
                        if ($pos === false) {
                            continue;
                        } else {
                        //The cleaning bit
                        echo "The string '".htmlentities($find)."' was found in the file '$path/$file and exists at position $pos and has been removed from the source file.<br />";
                        $clean_source = str_replace($find,'',$filesource);
                        file_put_contents($path.'/'.$file,$clean_source);
                        }
                    }else{
                        continue;
                    }
                }
            }
        }
        closedir($handle);
    }
    $return = ob_get_contents();
    ob_end_clean();
    return $return;
}
?>

Good Luck.

UPDATE (With Regex):

<?php 
error_reporting(E_ALL);
$find='<?php @error_reporting(0); if (!isset((.*?)?>';

echo findString('./',$find);

function findString($path,$find){
    $return='';
    ob_start();
    if ($handle = opendir($path)) {
        while (false !== ($file = readdir($handle))) {
            if ($file != "." && $file != "..") {
                if(is_dir($path.'/'.$file)){
                    $sub=findString($path.'/'.$file,$find);
                    if(isset($sub)){
                        echo $sub.PHP_EOL;
                    }
                }else{
                    $ext=substr(strtolower($file),-3);
                    if($ext=='php'){

                        $filesource=file_get_contents($path.'/'.$file);
                        //The cleaning bit
                        echo "The string '".htmlentities($find)."' was found in the file '$path/$file and has been removed from the source file.<br />";
                        $clean_source = preg_replace('#'.$find.'#','',$filesource);
                        // $clean_source = str_replace($find,'',$filesource);
                        file_put_contents($path.'/'.$file,$clean_source);
                    }else{
                        continue;
                    }
                }
            }
        }
        closedir($handle);
    }
    $return = ob_get_contents();
    ob_end_clean();
    return $return;
}
?>
Wednesday, March 31, 2021
 
samayo
answered 7 Months ago
89

Also I'm trying to account for punctuation at the end of a URL (so that we don't include it).

<?php

$string = "This works http://upload.wikimedia.org/wikipedia/commons/f/f2/Bill_Clinton%2C_Yitzhak_Rabin%2C_Yasser_Arafat_at_the_White_House_1993-09-13.jpg. This one should fail http://www.youtube.com/v/adlskdfjasopie. Although this one should fail as well http://youtu.be/adlkajdaslk.";

$string = preg_replace("~(?!(?:https?://(?:www.)?|www.)(?:youtu))(?:https?://(?:www.)?|www.)[^s]+[^.!?,<][)(]~i",'<a href="$0">$0</a>',$string);


?>

output

This works <a href="http://upload.wikimedia.org/wikipedia/commons/f/f2/Bill_Clinton%2C_Yitzhak_Rabin%2C_Yasser_Arafat_at_the_White_House_1993-09-13.jpg. ">http://upload.wikimedia.org/wikipedia/commons/f/f2/Bill_Clinton%2C_Yitzhak_Rabin%2C_Yasser_Arafat_at_the_White_House_1993-09-13.jpg. </a>This one should fail http://www.youtube.com/v/adlskdfjasopie. Although this one should fail as well http://youtu.be/adlkajdaslk.
Wednesday, March 31, 2021
 
Raef
answered 7 Months ago
44

You should be able to use the following:

/((http|https)://(?!www.google.co.uk)[w./-=?#]+)/ for http and https

OR

/(http://(?!www.google.co.uk)[w./-=?#]+)/ fot http only

You can then replace www.google.co.uk with your domain name (in the format that it is shown on your site).

Used on the following it will match all URLs except for http://www.google.co.uk...

A few websites to test the regex http://www.google.co.uk http://www.myspace.com http://facebook.com http://www.youtube.com/watch?v=video32 it should have matched all but the google URL.

The above regex will also match youtube videos etc. with GET strings attached and internal links (i.e. #)

Update

The following regex will replace all external links starting either http:// or www with an anchor tag to the URL opening in a new window/tab.

$string = preg_replace( "/((http://|www)(?!mydomain.com)[w./-=?#]+)/", "<a target='_blank' href='$1'>$1</a>", $string);
Wednesday, March 31, 2021
 
Gilko
answered 7 Months ago
47

Do this on your DbContext OnModelCreating:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{    
    modelBuilder.Entity<Recipe>()
        .HasMany(x => x.Members)
        .WithMany(x => x.Recipes)
    .Map(x =>
    {
        x.ToTable("Cookbooks"); // third table is named Cookbooks
        x.MapLeftKey("RecipeId");
        x.MapRightKey("MemberId");
    });
}

You can do it the other way around too, it's the same, just another side of the same coin:

modelBuilder.Entity<Member>()
    .HasMany(x => x.Recipes)
    .WithMany(x => x.Members)
.Map(x =>
{
  x.ToTable("Cookbooks"); // third table is named Cookbooks
  x.MapLeftKey("MemberId");
  x.MapRightKey("RecipeId");
});

Further examples:

http://www.ienablemuch.com/2011/07/using-checkbox-list-on-aspnet-mvc-with_16.html

http://www.ienablemuch.com/2011/07/nhibernate-equivalent-of-entity.html


UPDATE

To prevent cyclical reference on your Author property, aside from above, you need to add this:

modelBuilder.Entity<Recipe>()
    .HasRequired(x => x.Author)
    .WithMany()
    .WillCascadeOnDelete(false);

Idea sourced here: EF Code First with many to many self referencing relationship

The core thing is, you need to inform EF that the Author property(which is a Member instance) has no Recipe collections(denoted by WithMany()); that way, cyclical reference could be stopped on Author property.

These are the created tables from the Code First mappings above:

CREATE TABLE Members(
    Id int IDENTITY(1,1) NOT NULL primary key,
    Name nvarchar(128) NOT NULL
);


CREATE TABLE Recipes(
    Id int IDENTITY(1,1) NOT NULL primary key,
    Name nvarchar(128) NOT NULL,
    AuthorId int NOT NULL references Members(Id)
);


CREATE TABLE Cookbooks(
    RecipeId int NOT NULL,
    MemberId int NOT NULL,
    constraint pk_Cookbooks primary key(RecipeId,MemberId)
);
Wednesday, June 2, 2021
 
kmunky
answered 5 Months ago
66

This should do what you need...

public class Airport
{
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Route> DepartureRoutes { get; set; }
    public virtual ICollection<Route> DestinationRoutes { get; set; }
}
public class Route
{
    public int DepartureAirportID { get; set; }
    public int DestinationAirportID { get; set; }
    public Airport DestinationAirport { get; set; }
    public Airport DepartureAirport { get; set; }
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Route>()
        .HasKey(i => new { i.DepartureAirportID, i.DestinationAirportID});

    modelBuilder.Entity<Route>()
        .HasRequired(i => i.DepartureAirport)
        .WithMany(u => u.DepartureRoutes)
        .HasForeignKey(i => i.DepartureAirportID)
        .WillCascadeOnDelete(false);

    modelBuilder.Entity<Route>()
        .HasRequired(i => i.DestinationAirport)
        .WithMany(u => u.DestinationRoutes)
        .HasForeignKey(i => i.DestinationAirportID)
        .WillCascadeOnDelete(false);
}

...this creates tables like...

CREATE TABLE [Airports] (
    [ID] [int] NOT NULL IDENTITY,
    [Name] [nvarchar](4000),
    CONSTRAINT [PK_Airports] PRIMARY KEY ([ID])
)
CREATE TABLE [Routes] (
    [DepartureAirportID] [int] NOT NULL,
    [DestinationAirportID] [int] NOT NULL,
    CONSTRAINT [PK_Routes] PRIMARY KEY ([DepartureAirportID], [DestinationAirportID])
)
CREATE INDEX [IX_DestinationAirportID] ON [Routes]([DestinationAirportID])
CREATE INDEX [IX_DepartureAirportID] ON [Routes]([DepartureAirportID])
ALTER TABLE [Routes] ADD CONSTRAINT [FK_Routes_Airports_DestinationAirportID] FOREIGN KEY ([DestinationAirportID]) REFERENCES [Airports] ([ID])
ALTER TABLE [Routes] ADD CONSTRAINT [FK_Routes_Airports_DepartureAirportID] FOREIGN KEY ([DepartureAirportID]) REFERENCES [Airports] ([ID])

...and you can use it like so...

using (var db = new MyDbContext())
{
    foreach (var routeid in Enumerable.Range(1, 100))
    {
        var departure = new Airport { Name = "departure" + routeid };
        db.Airports.Add(departure);
        var destination = new Airport { Name = "destination" + routeid };
        db.Airports.Add(destination);

        var route = new Route{ DepartureAirport = departure, DestinationAirport = destination };
        db.Routes.Add(route);
    }

    int recordsAffected = db.SaveChanges();

    foreach (var route in db.Routes)
    {
        Console.WriteLine("{0}, {1}, {2}, {3}", route.DepartureAirportID, route.DestinationAirportID, route.DepartureAirport.Name, route.DestinationAirport.Name);
    }
}

...hope this helps. Note: don't use virtual on required properties (as those are indexes - and for this type of mapping will only work like that, you'll get some error I think).
Also I always add the opposite relations but you can use WithMany() blank, should work too.

Wednesday, August 4, 2021
 
Rafal
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share