Find all sites on server by IP address

I don’t advocate using the following to hack other sites. I found it interesting that my host was serving pornography from the same box I was using, so I switched to my own cloud server. There are two ways to go about finding other sites on your server. If you don’t know your server IP, you can search

whois yourdomain.com

and there are plenty of sites that will expose the server domain.

Bing IP Search

This seems to be pretty reliable and up-to-date. Bing has an IP operator that allows you to specify an IP address when searching.

Example Search:

ip:70.32.68.69

Hackers will use this operator to find sites running WordPress using the images tab. Once they identify several domains, they can easily ascertain your WP version with the generator meta tag. A hacker can know all of the WordPress installations and versions of those sites without leaving a probing footprint. If there is a known vulnerability with one of your versions, it’s a cinch to attack it. Keep your software up-to-date and your back-doors closed friends. Bing is not your friend with this horrid search operator.

Example Search:

ip:70.32.68.69 wp-content

Reverse IP Domain Check Tool

This is less than desirable when searching a largely populated box. If the customer turnover is pretty high, the stale entries still appear in a gargantuan list of sites. For smaller boxes, this works well. http://www.yougetsignal.com/tools/web-sites-on-web-server/

These are tools hackers use to aid in passive mapping of a server without ever hitting the IP directly. If you’re wondering how multiple WordPress installations on your server keep getting hacked, this is most likely the starting point for Mr. or Mrs. Hacker.

Create a WordPress admin user with MySQL

If you’ve ever been locked out of a WordPress installation, but have access to the database, here’s a nifty snippet to grant you administrator-level access. There are a couple of things you need to do before using this MySQL code. First, set the variables to your own information. Next, if your WordPress installation is based on a non-standard wp_ table prefix, you must find/replace ‘wp_’ with your current table prefix.

SET @id = 99;
SET @user = 'username';
SET @pass = 'password';
SET @email = 'email@ddress';
SET @name = 'Your Name';

INSERT INTO  wp_users (ID, user_login, user_pass, user_nicename, user_email, user_url, user_registered, user_activation_key, user_status, display_name) VALUES (@id, @user, MD5(@pass), @name, @email, '', '2013-06-20 00:00:00', '', '0', @name);
INSERT INTO  wp_usermeta (umeta_id, user_id, meta_key, meta_value) VALUES (NULL, @id, 'wp_capabilities', 'a:1:{s:13:"administrator";s:1:"1";}');
INSERT INTO  wp_usermeta (umeta_id, user_id, meta_key, meta_value) VALUES (NULL, @id, 'wp_user_level', '10');
INSERT INTO  wp_usermeta (umeta_id, user_id, meta_key, meta_value) VALUES (NULL, @id, 'active', '1');

Mac: Copy the current SVN URL to the clipboard from command line

If you are still using SVN (WHY HAVEN’T YOU SWITCHED TO GIT??), here’s a simple alias you can drop into your ~/.bash_profile . Then type `source ~/.bash_profile` on any current terminal windows to load the alias. Here’s how it works. Navigate to your SVN working copy and type `svnurl` and viola! it’s copied to your clipboard. This is extremely useful for copying/deleting/switching/merging branches via command line.

alias svnurl="svn info | sed -ne 's/URL: //p' | tr -d '\n' | pbcopy"

Generate a custom _s (underscores) WordPress theme from command line

I’m building out a new theme for my blog using the _s theme. It’s an exercise in building out a responsive grid. _s is a great theme starter. Underscores.me has a nifty little tool to generate the starter theme with namespaced functions, title, description, etc… for the theme. I wanted to generate the theme directly from command line. Here’s what I used to generate the theme directory with one line (your pwd should be wp-content/themes/):

curl --data "underscoresme_generate=1&underscoresme_name=Coderrr&underscoresme_slug=coderrr&underscoresme_author=Brian+Fegter&underscoresme_author_uri=http%3A%2F%2Fcoderrr.com&underscoresme_description=A+custom+theme+for+coderrr.com." http://underscores.me >> coderrr.zip; unzip coderrr.zip; rm coderrr.zip;

There are four things that happen here:

  • Curl http://underscores.me and send post data
  • Tell Linux to place all returned data into a zip file
  • Unzip that file and create the theme directory
  • Remove the zip file

If you don’t want to format your URL encoded data, visit underscores.me and fill out the advanced form. You can extract your post data by using the Google Chrome Dev Tools network tab.

_s

Why My ISP Kicked Me Out

UPDATE: Before reading this, I wanted to note that the ISP made good on a refund. I was refunded the entire amount of installation and two months of service ($686.09). They actually corrected their error and gave me back my cash. I’m satisfied with their actions.

It was early Saturday morning and I was working on some personal projects when my connection started flaking out. I took to my Verizon tethering via iPad and didn’t think much of it until I tried logging back into my home wifi. Everything seemed in order until I tried to browse the web. I was redirected to a hacker radio website and all Google searches were popping off a 404 error at another malicious website. I tried browsing on several devices and the same thing was happening on each. I immediately disconnected all devices from the internet thinking my router had been compromised.

I quickly unplugged my router from WAN and flashed it with a fresh load of DD-WRT. I knew that would destroy whatever was hijacking the router. After about 40 minutes I plugged back in and to my shock, the same thing happened again. I check my /etc/hosts and nothing was out of the ordinary. So, I pulled out my dusty Windows laptop which hadn’t been used in ages and plugged it directly into the ethernet connection from my ISP. The same thing happened on the laptop. I should have started with that, but now I knew that it was coming from WAN.

I contacted my ISP and their 24 hour support line sent me to a voicemail several times. I sent an email to them (via tethering) and went to bed. I woke up at 7:30am and it was still redirecting to malicious websites. I sent another email and asked for a callback. At about 10:00am, the manager called and left a messaging saying they had an ‘outage’. I contacted several people I knew who use this ISP and they confirmed the same at all of their locations. For over 9-10 hours all customers in my city were being redirected to malicious websites from this ISP.

I sent another email asking them to inform their customers of the following:

  • Was handed over to the proper authorities?
  • What happened?
  • How was it fixed?

I received an email back stating that Internet security is the responsibility of the ‘individual’. This volley went on for a couple more emails. I received another email stating that the “Internet breaks at times”. When I could not even get acknowledgement that this event ever occurred, I finally started typing in caps. I said, “YOU MISSED THE POINT! YOU WERE HACKED!”. I noted that my usage of caps was me yelling. I never used an expletive. I also gave a condescending math equation for finding a common denominator. If customer A has this happening at their location, and customer B has this happening and customer C has this happening, what can we deduce from this? Apparently that hurt the manager’s feelings.

The next email I received made my head explode. “If you continue to yell at me, I will be forced to discontinue your service.”. I quickly replied “You do that and you’ll be hearing from an attorney.” (Insert email silence for a long period of time) I wrote back saying there’s nothing in the contract that I could see that included yelling and disagreeing as grounds for breaking the contract. I also called this behavior ‘fascist’. It was snarky I know, but I was upset.

After no reply, I called the manager and he happily said that his legal team was reviewing my ‘threatening’ (ALL CAPS) email and will give a reply back soon. I had to hang up on the guy so I didn’t say something foolish. In a few short minutes, the CTO of the company emailed me berating me for threatening her manager with legal action and that they would not tolerate disrespect of their employees. Again, I was a bit dumbfounded as I had not disrespected the manager outside of my CAPS and petty mathematical equation.

She included a clause of the contract, which I missed because it was fine print, that stated they can terminate me for any reason at any time at their discretion. She said I would need to find another ISP and to let them know when I found one so they could terminate the contract. She was ‘kind’ enough to allow me to leave without paying penalties. I was also told to leave the equipment on the porch as they didn’t want me conversing with their tech. I was left out in the cold and the arbitrary clause left me without any form of recourse.

They stated it’s because they are a family-owned business that they can do this. It doesn’t sound like any family I want to be a part of. This was the worst customer service experience I’ve ever had in my 32 years of living. My wife asked me, “Aren’t companies supposed to try to keep customers instead of pushing them away?” Yes, that’s what I thought. What ever happened to the customer is always right? Apparently that’s old-fashioned in this post-modern world.

I still don’t understand why they dropped me. It has to be for one of the following reasons:

  • They were covering up that they were actually hacked and I was pressing some hot buttons.
  • They were nursing their manager’s broken heart
  • They don’t like people disagreeing with them or calling their bluff

Since I live in the boonies in Texas, there are very limited options for connection. This ISP (4G) was the best and only reliable option. I had to purchase a $550 apparatus tripod and receiver that was installed on my roof. It’s 10 feet high and the signal was okay for about 95% of the time. We paid two months of service at $65/per month. The $550 is non-refundable. So, averaging out my total costs, I paid this ISP $340/month for two months of Internet usage on a two year contract. I searched all over town to try to find DSL or Cable and these services come within 800 feet of my house, but not to my house. Since I work on the web, this leaves me in a huge bind.

Thankfully, I have a Verizon 4GLTE device that will get me through month-to-month. We are getting rid of Netflix and other bandwidth sucking apps until there is a more stable Internet connection. This might be a blessing in disguise to get us more focused with a new baby coming.

The lessons I’m taking from this are many, but I’ll note a few. NEVER USE CAPS WHEN CONTACTING SUPPORT. Never give condescending arithmetic lessons to a mad person. Read the contract thoroughly before signing. Stop calling people fascist when they are exhibiting fascist behavior. When moving to a house in the country, check Internet connectivity first (The cattle ranch across the street should have been a clue).

Finally, I’m going to do what the Bible teaches and do good to those who are my enemies. After much honest, soul-searching on this, I determined that I have been the victim of an injustice for sure. I’m sending the manager and CTO a small gift card for Starbucks. I’m hoping this act of kindness will spur their conscience to not treat other customers as they treated me.

And that’s the story of my ISP kicking me out of their pond. I purposely left out their company name as they have threatened to sue me for writing about this.

Setting Proper WordPress Unix Permissions

One of the biggest black boxes of WordPress for newbies is file ownership/permissions. I’ve had numerous people ask me why they can’t use the default theme editor or install new plugins directly from wp-admin. The symptoms usually range from getting the FTP credentials screen to error messages that WordPress cannot create a specific directory, and more.

It took me a while to grasp the concept, so I hope the following explanation will help you. This, in no way, is a security tutorial. It is a simple tutorial on Unix users/groups and file permissions. You should also read Hardening WordPress. If you’re not sure about file permissions, read this article first.

Groups and Users

The first order of business is making sure you have the proper user/groups setup. I typically create one unix group per site that I host. This allows me to have granular control over who’s allowed to work in that site directory.

Add a new user

useradd newusername

Add the user to your site group

usermod -a -G domainnamegroup newusername

Find the Apache user
This is typically ‘apache’ or ‘www-data’. Note this for the next step.

ps aux | grep apache

File ownership

Now that we have a user in a group, we need to assign that group to our WordPress install. It’s critical at this point to decide whether these users can only operate in wp-content or the entire docroot. Let’s say we only want to give this group dev access to themes/plugins/uploads/etc… You will keep ownership of the core files (including wp-config.php and .htaccess) with your personal username.

Change all file ownership to your personal user and group
This is the basis for restricting users from working on core files.

cd /path/to/your/docroot
chown -R yourusername:yourusername

Change wp-content file ownership to the apache user and new domain group
This gives Apache and your dev group access to these files

cd /path/to/wp-content/
chown -R %APACHE_USERNAME%:domainnamegroup

Change file permissions

Go to your docroot

cd /path/to/your/docroot

Change all file permissions to 0664. This sets core files to read/write for your personal user and personal group and read only for the rest. This also sets user/group permissions for the wp-content directory as well.

find . -type f -exec chmod 0664 {} \;

Go to wp-content and change all directory permissions so dev users can add/delete/modify files within. This keeps WordPress from flashing the FTP credentials screen. For plugins like W3TC, you might need to add a 0755 permission temporarily to wp-content itself so the plugin can build out the file structure it needs.

cd path/to/wp-content
#Allow apache and your dev users to add/modify/delete files within wp-content directories
find . -type d -exec chmod 0755 {} \;

Automatic Core Upgrades

I’m not a big fan of allowing automatic core upgrades if there are other WP admins using the site. I prefer to keep control of this and not have unmitigated disasters (with older plugins and themes) because someone is trigger happy. The setup I described above will not all for automatic upgrades. I typically upgrade manually to keep file permissions static. However, if you want to allow for auto upgrades temporarily, you can do the following:

cd /path/to/docroot
#Allow all directories except wp-content to be modified
find . -type d \( -iname "*wp-*" ! -iname "wp-content*" \) -exec chmod 0755 {} \;

#Add the apache user group to all files
#This allows temporarily locks out your dev group while the upgrade takes place
chown -R yourusername:%APACHE_USERNAME%

#Run the upgrade
#Revert permissions back

#Make all directories except wp-content writeable
find . -type d \( -iname "*wp-*" ! -iname "wp-content*" \) -exec chmod 0644 {} \;

#All core files belong to you
chown -R yourusername:yourusername

#Give your dev group access to wp-content directories/files again
cd /path/to/wp-content/
chown -R %APACHE_USERNAME:newdomaingroup

Caveat

Not all systems are created equal. These settings might not work well on a shared environment. Contact your host if standard permissions don’t work. Command line gives you much power, use it wisely. I take no responsibility for your command line work.

Recursive FTP get for command line

If you’re like me, you hate using a FTP GUI for doing simple gets. Sometimes, GUIs get in the way and bog the transfer down. I prefer to take out the middle man and use command line. Here’s a nifty snippet I picked up along the way that lets you recursively download entire directories. The files are stored in their identical structure in your working directory.

wget -r --user %user% --password %password% ftp://%server%/full/path

If you want to stick with pure FTP commands, you can use the following:

#Turn off confirmation for getting each file
ftp>prompt
ftp>mget *

WordPress Rewrites Without Duplicate Content

There are times when you need to surface content in a different context. For instance, you might have an events section and you want to have your related live-blog posts reside within the context of that specific event URI structure. The problem lies in surfacing the same content in the original location and in a rewritten location. Search engines frown on this. You can easily sidestep this and stay search engine friendly by setting up simple redirects.

Continue…

Automatic git status emails

This is a basic, elementary script to audit a git working copy. This is useful to keep a watchful eye on cowboy coding on a client server.

Save the following inside your git repo as .git-status.sh. Make sure to add ‘.git-status.sh’ to your .gitignore file.

#!/bin/sh
DOMAIN = "http://whatever.com"
SENDTO = "your@email.com"
MODIFICATIONS=`git status -s`
if [ ! -z "$MODIFICATIONS" ]
then
        SUBJECT = "git changes from $DOMAIN"
        EMAIL = "$SENDTO"
        BODY = "/tmp/emailbody.txt"
        echo "Changes found on the following paths:\n" > $EMAILBODY
        echo "$MODIFICATIONS" >> $EMAILBODY
        mail -s "$SUBJECT" "$EMAIL" < $EMAILBODY
        echo "$MODIFICATIONS"
fi

To automate, add a crontab:

30 15 * * * /path/to/your/script/.git-status.sh 2>&1>> /dev/null

Continue...

Send a WordPress Auth Cookie with HTTP API Requests

This snippet I created lets you hit your site with a remote request that includes your current auth cookie. I use this to circumvent caching plugins that use output buffering when I need to store a page load for analysis.

Could not embed GitHub Gist 4419756: API rate limit exceeded for 54.83.137.232. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)