Locating Spammers

So I'm working on a guys server today, and he's been having issues with this server generating SPAM.  Not a lot, just like a couple hundred a day. 

A small enough to not really be noticed at first, so it goes on long enough that the server gets blakclisted everywhere. 

The thing with this, is that it wasn't a standard SPAM script that was getting hit, and generating spam, or a hacked email account.
This was basically EVERY domain on the server (Almost all owned by one reseller on the server) all sending one or two pieces of spam here and there from info@<customerdomain>

The mail logs would just show generic information like

Mail Control Data:

mailnull 47 12
<info@(customerdomain)>
1483750320 0
-helo_name (customerdomain)
-host_address 127.0.0.1.57428
-interface_address 127.0.0.1.25
-received_protocol esmtp
-aclc _authenticated_local_user 6
nobody
-body_linecount 16
-max_received_linelength 390
-host_lookup_failed
XX
1
(someRandom)@aol.com

This was really annoying me. 

I exhausted all of my usual Spam hunting tactics, using things like Maldet and ClamAV to look for known spam scrips and hacks and came up empty. 
So I started looking at the traffic to the server as a whole, looking for patterns. 
Eventually I started seeing that xmlrpc POSTs was really the only pattern happening to all sites. 

tail -f /usr/local/apache/domlogs/*.com | grep POST | grep xmlrpc

 

91.197.232.105 - - [07/Jan/2017:06:15:55 +0000] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
91.197.232.105 - - [07/Jan/2017:06:16:53 +0000] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
91.197.232.105 - - [07/Jan/2017:06:17:04 +0000] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
91.197.232.105 - - [07/Jan/2017:06:17:14 +0000] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
91.197.232.105 - - [07/Jan/2017:06:17:16 +0000] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
51.15.43.32 - - [07/Jan/2017:06:21:53 +0000] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
51.15.43.58 - - [07/Jan/2017:06:26:10 +0000] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
51.15.43.58 - - [07/Jan/2017:06:27:05 +0000] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
51.15.43.58 - - [07/Jan/2017:06:28:40 +0000] "POST /xmlrpc.php HTTP/1.0" 301 - "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
51.15.43.58 - - [07/Jan/2017:06:28:35 +0000] "POST /xmlrpc.php HTTP/1.0" 200 384 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
212.47.230.108 - - [07/Jan/2017:06:28:59 +0000] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
212.47.230.108 - - [07/Jan/2017:06:30:43 +0000] "POST /xmlrpc.php HTTP/1.0" 200 384 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
212.47.230.108 - - [07/Jan/2017:06:31:15 +0000] "POST /xmlrpc.php HTTP/1.0" 301 - "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
51.15.43.32 - - [07/Jan/2017:06:31:40 +0000] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
89.144.12.15 - - [07/Jan/2017:06:31:47 +0000] "POST /xmlrpc.php HTTP/1.1" 200 403 "-" "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; uk; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13"
163.172.132.253 - - [07/Jan/2017:06:31:44 +0000] "POST /xmlrpc.php HTTP/1.0" 200 370 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"


So I started comparing the POSTs to the info@ spam in the Queue
Tossed this into the server command line 

sed -i '1i <Files xmlrpc.php>\norder deny,allow\ndeny from all\n</Files>\n ' /home/*/public_html/.htaccess

And now every domain has a block  that kills access to xmlrpc.php, and prevents this ongoing spam ordeal for this customer. 

FUN!!

Blocking an account from sending mail in WHM

I had a customer today that wanted to block an account from being able to send email because they were dealing with a hacked website that was spamming. 

There is no specific feature in WHM/cPanel to just block a complete domain from being able to send mail, so I used the following process:

Created a new file called blockeddomains with the domain that I wanted to block 

echo "domain.com" > /etc/blockeddomains

Now setting the proper permissions / ownership for the file:

chown root.mail /etc/blockeddomains && chmod 640 /etc/blockeddomains

Now I have to tell EXIM to look at this file, and use it to deny email from the domains listed in it. 

Open WHM, and Browse to WHM >> Service Configuration >> EXIM Configuration Manager >> Advanced Editor
Scroll down to the Add additional configuration setting button, and click on it, and add the following: 

domainlist blocked_domains = lsearch;/etc/blockeddomains

Scroll down further to the ROUTERSTART section and add the following:

 

reject_domains:

driver = redirect
domains = +blocked_domains
allow_fail
data = :fail: SPAM Source rejected: $domain is manually blacklisted.

 

Now you can block/unblock any domains simply by editing the /etc/blockeddomains file.

 

Making WordPress more secure

WordPress is popular, Free software that can be used to quickly and easily build websites. It has great community support and a tonne of plugins that can extend it's capabilities. 

The problem is that it gets fucking hacked all the time, and abused to send billions of spam around the world.
Don't be an idiot and let yours get abused.

 

 

Securing wp-includes

A second layer of protection can be added where scripts are generally not intended to be accessed by any user. One way to do that is to block those scripts using mod_rewrite in the .htaccess file. Note: to ensure the code below is not overwritten by WordPress, place it outside the # BEGIN WordPress and # END WordPress tags in the .htaccess file. WordPress can overwrite anything between these tags.

# Block the include-only files.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>
# BEGIN WordPress

Note that this won't work well on Multisite, as RewriteRule ^wp-includes/[^/]+\.php$ - [F,L] would prevent the ms-files.php file from generating images. Omitting that line will allow the code to work, but offers less security.

 

Securing wp-config.php

You can move the wp-config.php file to the directory above your WordPress install. This means for a site installed in the root of your webspace, you can store wp-config.php outside the web-root folder.

Note that wp-config.php can be stored ONE directory level above the WordPress (where wp-includes resides) installation. Also, make sure that only you (and the web server) can read this file (it generally means a 400 or 440 permission).

If you use a server with .htaccess, you can put this in that file (at the very top) to deny access to anyone surfing for it:

<files wp-config.php>
order allow,deny
deny from all
</files>

 

Securing uploads

If file uploads are enabled, people can upload, and execute any arbitrary code, and use this to gain access to unintended areas of your site, or generate spam.
Creating a .htaccess file in the uploads folder with the following will prevent that.

<Files *.php>
deny from all
</Files>

Disable File Editing

The WordPress Dashboard by default allows administrators to edit PHP files, such as plugin and theme files. This is often the first tool an attacker will use if able to login, since it allows code execution. WordPress has a constant to disable editing from Dashboard. Placing this line in wp-config.php is equivalent to removing the 'edit_themes', 'edit_plugins' and 'edit_files' capabilities of all users:

define('DISALLOW_FILE_EDIT', true);

This will not prevent an attacker from uploading malicious files to your site, but might stop some attacks.

 

These are a few good places to start in securing your WP install. Of course keeping all updates applied to WordPress Core and any Plugins and Themes is very important as well. 

 

Injecting a WP-Admin User for testing

So sometimes we have a WordPress User that doesn't want to share Login Credentials over email because of possible Security issues with emailing passwords. 

One of the easiest ways around this request is just to Inject a new Admin User, Do what you need to do, then delete it. 

 

 

INSERT INTO `user_db`.`wp_users` (`ID`, `user_login`, `user_pass`, `user_nicename`, `user_email`, `user_url`, `user_registered`, `user_activation_key`, `user_status`, `display_name`) VALUES ('1337', 'techsupport', MD5('password'), 'Technical Support', 'tech@thecrimsonhorror.com', '', '0000-00-00 00:00:00', '', '0', 'Tech Support');
INSERT INTO `user_db`.`wp_usermeta` (`umeta_id`, `user_id`, `meta_key`, `meta_value`) VALUES (NULL, '1337', 'wp_capabilities', 'a:1:{s:13:"administrator";s:1:"1";}'), (NULL, '1337', 'wp_user_level', '10');

 

The obvious changes to this would be depending on the specifics of the Database at hand.  After the INSERT INTO you would modify the user_db to be the actual Database name 
The next parts are the wp_users and wp_usermeta These would only change if the customer has modified their Database Prefix (If this is the case, then the wp_capabilities and wp_user_level would also have the wp_ replaced with the Database Prefix)  Modify the Username/Password and email address as needed and just run as an SQL Statement in phpMyAdmin. 

 

After you're done doing the testing, you want to clean up your User so it's not another entry point for hackers

DELETE FROM `user_db`.`wp_users` WHERE `wp_users`.`ID` = 1337
DELETE FROM `user_db`.`wp_usermeta` WHERE `wp_usermeta`.`user_id` = 1337

 

Of course, the same things for this, change the Database name and Table Prefix to match the database you're working with, and all will be good. 
The UserID set to 1337 is an easy way to ensure that there are no conflicts, it's very unlikely that a user would have that many WP users.  

SQL Updates for WP

Had a customer today that fucked up his WP install. 

 

He moved from newsite.<domain> to <domain> and didn't make any updates in the WP Admin to account for the move to the new URL as per the Moving WordPress article on Codex. 

 

Figured I would repair the DB manually to get rid of all the 'newsite.' references. 

There were over 1600 references to the site name in the DB

Figured I would write up a little SQL Script that would make the update:

UPDATE wpjc_posts set guid=REPLACE(guid, 'newsite.customerdomain.com', 'customerdomain.com')
UPDATE wpjc_posts set post_content=REPLACE(post_content, 'newsite.customerdomain.com', 'customerdomain.com')
UPDATE wpjc_postmeta set meta_value=REPLACE(meta_value, 'newsite.customerdomain.com', 'customerdomain.com')
UPDATE wpjc_options set option_value=REPLACE(option_value, 'newsite.customerdomain.com', 'customerdomain.com')

Running this, updated 2000+ records referring to the old URL in a few seconds, and was literally the quickest resolution to this issue.