Machform javascript embed form in wordpress post

If one have a form in Machform, one can add the form in a WordPress Post or Page with a simple javascript embed:
[javascript]


[/javascript] Which will give the form: [raw]



[/raw]

Finding spam users

We had a lot of spam users in our multisite wordpress system. This was because we had self-registration enabled for a period. Not a smart thing to do…

anyway, I wrote a bash script in order to find which users id’s from the Mysql database that could potentially be spam users. With this list of ID’s I would run another SQL directly where I would set the “spam” to the number “1”. This would make sure the user could not log in, and after a month or so, the user could be deleted.

As you can see from one of the sql’s, the “%uib.no” is the trusted emails from our organization.

 

[bash]
#!/bin/bash

# Which one of all the users in the multisite blog system are spamusers?
# If the user doesn’t have any relations in users_blogg, most likely the user is a spam user.
# But the user can have a meta_value in wp_usermeta table like source_domain.
# These are valid users, and should not be marked as spam

# Find all users ID’s
dbquery=$(mysql -u root -p`cat /root/mysql` -e “use blog; select ID from wp_users;”)
array=($(for i in $dbquery; do echo $i; done))

# echo ${array[@]}

# for all the users, do:
for i in ${array[@]}
do
dbquery2=$(mysql -u root -p`cat /root/mysql` -e “use blog;SELECT wp_bp_user_blogs.id FROM wp_bp_user_blogs WHERE wp_bp_user_blogs.user_id = $i”;)
array2=($(for j in $dbquery2; do echo $j; done))
if [ ${#array2[@]} -eq 0 ];then
dbquery3=$(mysql -u root -p`cat /root/mysql` -e “use blog; select user_email from wp_users WHERE ID = $i and user_email not like ‘%uib.no’;”)
dbquery4=$(mysql -u root -p`cat /root/mysql` -e “use blog; select meta_value from wp_usermeta WHERE user_id = $i and meta_key like ‘source_domain’;”)
array4=($(for r in $dbquery4; do echo $r; done))
for n in ${array4[@]}
do
echo “User $i has a blogg with name $n! Please don’t delete this user.”
done

array3=($(for k in $dbquery3; do echo $k; done))
for m in ${array3[@]}
do
echo “User $i with email $m is not connected to any blog and should be marked as a spam user!”
done
fi
done
[/bash]

WP CLI

WordPress command line is a must-to-have if you are running a WordPress site or multisite.

If you know a bit about crontab and bash scripting, you can easily make an automated  job that will upgrade all your plugins and themes on a regular basis.
But be aware, some plugins and themes might break, so you might want to have some testing and checking after an upgrade.

We installed it on our server, and it makes our job much easier:

http://wp-cli.org/

In order to upgrade all plugins:
wp plugin update-all

Upgrade a specific theme:
wp theme update themename

To get more information about a command:
wp help theme status

WordPress Brute Force attack spring 2013

For those who are running a WordPress site today at May 2013, you should know about this on-going BruteForce attack against many WordPress sites around the world.
http://www.bbc.co.uk/news/technology-22152296

Here at University of Bergen, we are also working on to protect our multisite WordPress installation.

How is this “attack” performed?

There is a so-called “botnet”, where around 90 000 computers are involved.

These “attacks” are made in a way that a computer taken by a cracker, in the botnet, is sending a POST request to a WordPress site to wp-login.php, where a suggested username and password is sent. If the username and password is correct, the user is logged in. Then the attackers have access to your WordPress site. Most of the posted username is “admin”.

We installed something to our server called ‘fail2ban”, which is a python script that runs as a daemon, and will implement Iptables (firewall) rules on the fly, after parsing the access-log.

This worked for us, because we realized that the “botnet” bruteforce attack was using the same “user-agent” string in all wp-login.php attempts.

Now, I see the potential danger of telling the “secret” of this attack, but let me just give you some data from the last number of entries in our Apache httpd log: access_log since 19th of May:

48514 "Mozilla/5.0 (Windows NT 6.1; rv:19.0) Gecko/20100101 Firefox/19.0"
5696 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0"
2494 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0"

Here I have counted the numbers of user-agents in our httpd-log files.

As you can see, the attack is mainly based on one type of user-agent, the one which has 48514 entries. Clearly it is reasonable to block these clients that have this agent.

Our block solution is made that if a client has a suggested user-agent as shown above "Mozilla/5.0 (Windows NT 6.1; rv:19.0) Gecko/20100101 Firefox/19.0", and that client is trying to perform more than 3 wp-login.php call in a certain time, it is blocked out for 12 hours in our case. If the client is performing a similar attempt within an hour, the bantime is expanded.

Our fail2ban jail.conf file has this section:


[apache-wp-login]
enabled = true
port = http,https
filter = apache-wp-login
action = iptables-multiport[name=APACHE-WP, port="http,https", protocol=tcp]
logpath = /var/log/httpd/access_log
maxretry = 3
findtime = 3600
bantime = 43200

So, then we decided to make a script that could test which useragents are involved in making a lot of POST to wp-login.php, and then compare them to “our” clients, the “friendly” ones.

From that we could make a simple failregex in fail2ban filter.d/apache-wp-login.conf:

[Definition]
failregex = ^<HOST> -.*] "POST /wp-login.php .* "Mozilla/5.0 [(]Windows NT 6.1; rv:19.0[)] Gecko/20100101 Firefox/19.0"$
            ^<HOST> -.*] "POST /wp-login.php .* "Mozilla/5.0 [(]Windows NT 6.1; WOW64; rv:18.0[)] Gecko/20100101 Firefox/18.0"$
ignoreregex =

This useragent string is taken from the apache log file (access_log). Our idea is that if you hav 5000 or more log in attempts from the same useragent, this useragent could be banned.

In order to see that our bann was successfull we counted the number of entries in iptable:

service iptables status | grep DROP | wc -l

We see the potential that the people responsible for this attack easily could implement a random useragent in the POST for each login attempt to wp-login.php.
So far, it looks like they still use the same useragent for all POST against wp-login.php.

Our next approach:
If user-agents change rapid and POST to wp-login.php still happens in a big scale, we will concider a two-step user validation for our WordPress installation.

bbPress plugin is adding admin to all blogs

After we upgraded our test wordpress multisite to 3.5 we realized that that both the ‘admin’ user and the other siteadmin users where suddenly added as a ‘participant’ to all the wp sites we had.
Siteadmin shouldn’t be a member or participant to any blog in a multisite wordpress installation we think.
The biggest problem was that the working as ‘admin’ or as a siteadmin user with 100-200 blogs attached, made everything go really slow. 10-15 seconds per click in average.

We found that bbPress was causing the issue, because we could do a test when the bbPress plugin was not installed, nothing happened. After the plugin was activated, sure, the same problem happened again.

We want to dig more into to the issue. At this moment bbPress plugin is disabled in our wordpress 3.5 Elvin system. And it will be also disabled when we upgrade our main production system.

Alert Blog Admin php script

I had to send emails to all the Blog admins in our WordPress Multisite installation. This is how I did it:

[code lang=”php”]
<?php
# Alert Blog Admin php script
# connect to blog db, select from, find all blog admin email adresses
# get subject, body from pre-created local files, send the email

# how to run the script
# php alertblogadmin.php -s subjecttext.txt -b bodytext.txt

$mysqlserver="localhost";
$mysqluser="dbuser";
$mysqlpassword="XXXXXXX";
$database="blog";

$ERROR=0;

# This script require arguments
$arguments = getopt("s:b:f:dr");

# Test if array $arguments as at least s,b and r
# maybe to make sure that $arguments array contains at least 3 items?
if ( count($arguments) < 3 ){
echo "Missing arguments…\n";
echo "Usage: php alertblogadmin.php -s subjecttext.txt -b bodytext.txt\n";
die;
}

# 2 text files need to exist
if ( !file_exists($arguments["s"])) {
echo "File $arguments[s] does not exist?\n";
$ERROR=1;
}
if ( !file_exists($arguments["b"])) {
echo "File $arguments[b] does not exist?\n";
$ERROR=1;
}

if ($ERROR == "1"){
die;
}

$link = mysql_connect($mysqlserver, $mysqluser, $mysqlpassword);
if (!$link) {
die(‘Could not connect: ‘ . mysql_error());
}
mysql_select_db ($database,$link);

# collect blogs
$sql="SELECT blog_id from wp_blogs where deleted not like ‘1’";
$result=mysql_query($sql,$link);
if (!$result) {
die(‘Invalid query: ‘ . mysql_error());
}

$i = "0";
$emailarray = array();

while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
$blog_id = $row[0];
$table = "wp_" . $blog_id . "_options";

# Find email adresses to admins in each blog in the system
$sql2="SELECT option_value FROM $table WHERE option_name = ‘admin_email’";
$result2=mysql_query($sql2,$link);
while ($row2 = mysql_fetch_array($result2, MYSQL_NUM)) {
$emailarray[$i] = $row2[0];
}
$i++;
}

# sort the email array and find unique emails
asort($emailarray);
$emailarray = array_unique($emailarray);

$emails = "";
foreach ($emailarray as $email) {
$emails .= $email.",";
}

$emails = substr($emails,0,-1);

# Could be smart to see who you will be sending your email to
echo $emails;

# open subject and body text files
$subject = file_get_contents($arguments["s"]);
$body = file_get_contents($arguments["b"]);
$from = $arguments["r"];

# Use this one to test before you actuelly send to $emails, which is a variabel that might contain hundreds of emails.
# You really would like to test first
$bcc = "user1@something.com,user2@something.net";
//$bcc = $emails; # uncomment this one, when you are ready to go

$headers = "From: noreply@something.com" . "\r\n" .
"Reply-To: noreply@something.com" . "\r\n" .
"Bcc: $bcc" . "\r\n" .
"X-Mailer: PHP/" . phpversion();
$header_ = ‘MIME-Version: 1.0’ . "\r\n" . ‘Content-type: text/plain; charset=UTF-8’ . "\r\n";

mail(”, ‘=?UTF-8?B?’.base64_encode($subject).’?=’, $body, $header_ . $headers);
mysql_close($link);
?>

[/code]