Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: security

  • Command Line Cleaning WP

    Command Line Cleaning WP

    Blob-Town-The-Blob-1958-Documentary-@-Phoenixville-Pennsylvania-by-James-RolfeI’m a huge fan of the scorched earth clean up for WordPress. By which I mean when I clean up WP, I rip it out, scrub it, and reinstall. This scares the heck out of people sometimes, and if you’re doing it in a GUI, yeah, it can be sucky and time consuming. Me? I do it in 5-10 minutes, depending on if my cat wants to be petted.

    I’ve been asked ‘How do you do it that fast?’ so here are my steps for cleaning up WP, with the following assumptions:

    1. I’m working in the folder where WP is installed
    2. wp-config.php is in this folder
    3. WP is in ‘root’ (i.e. I’m not giving WP it’s own folder)

    If any of those aren’t true for you, adjust the folder locations in the commands:

    Download WP: wget -P ../ http://wordpress.org/latest.zip

    Unzip it: unzip -qq -d ../ ../latest.zip

    Backup DB: wp db export

    Pause. Here I’m using WP CLI, which makes my life way easier. If you’re not, you’ll need something like this: mysqldump --opt --user=username --password=password --host=yourMySQLHostname dbname > domain_com.sql

    Zip up the files I want to backup: zip -r ../domain.zip *.sql wp-config.php .htaccess wp-content/

    Set glob. Glob is scary, I know, but read about glob before you dismiss it (if you’re on korn, you can usually skip this): shopt -s extglob

    Delete files: rm -rf !(wp-config.php|wp-content)

    Pause. At this point, It’s probably wise to consider that my hack may be in my theme and/or plugin. If so, I want to nuke them and JUST keep my uploaded files, so I use this instead…

    Delete files: rm -rf !(wp-config.php|wp-content) wp-content/!(uploads|blogs.dir)

    Pause again. No matter what, want to scan for evil files, but this way I do it over a much smaller group of files. Either way, though, I do want to scan the folder for evil, because leaving behind hacks in themes and plugins is really common. Also it’s a good idea to delete every plugin you don’t use, and theme as well. Since you really can’t delete all themes but one on a Multisite, this gets harder. Generally I don’t delete the themes automatically, but instead go in and nuke them one at a time, so I run this…

    Delete files: rm -rf !(wp-config.php|wp-content) wp-content/!(uploads|blogs.dir|themes|mu-plugins)

    Now we can move on, knowing our personal files are clean.

    Copy it back: cp -r ../wordpress/* .

    Clean it up: rm -rf ../wordpress ../latest.zip

    And now you’re done! When you want to reinstall plugins and themes, I do via wp-cli because it’s faster: wp plugin install NAME and wp theme install NAME

    Then I activate as needed and I’m off to the races. If I deleted my mu-plugins, I copy those back from my backup zip, one at a time, checking each file for hacks.

    The best thing about this is you can apply the logic to any CMS out there. Just know what you have to delete and keep. The downside? It doesn’t touch your database. Rarely is this an issue for me, except in the case of the Pharma hack. I’ve not had a DB infected yet.

    Do you have a solid methodology for cleaning it up?

  • My Super Secret .htaccess File

    My Super Secret .htaccess File

    This came up back in April in the comments of WordPress Login Protection With .htaccess, where I remarked my .htaccess was pretty long and weird. It came up again when I was doing a MeetWP presentation about hacked sites and some security.

    So what is it? Actually less long and weird these days. I’ve been trimming stuff out. But since people ask, here it is, broken out into ‘chunks.’

    Security

    Everything in this section is for security purposes. That is, I feel it helps my site be safer.

    # Tinfoil Hat Stuff
    Options +Includes
    Options +FollowSymLinks -Indexes
    

    This is basic .htaccess stuff, says to allow includes and symlinks, but stop indexes. This means if you go to halfelf.org/wp-content/uploads/ you don’t see anything, even if I don’t have an index file.

    ### Blocking Spammers Section ###
    <files wp-config.php>
    order allow,deny
    deny from all
    </files>
    

    Now we’re into a little odder bits. This stops anyone from surfing to my wp-config.php file. It shouldn’t matter, PHP won’t let it load the content, but if my PHP is off, it protects me just in case!

    # Stop protected folders from being narked. Also helps with spammers
    ErrorDocument 401 /401.html
    

    This is because of the next section. It gives a nice error for 401s, which WP normally gets gitty over. And not the fun way.

    <IfModule mod_rewrite.c>
    # Stop spam attack logins and comments
    	RewriteEngine On
    	RewriteCond %{REQUEST_METHOD} POST
    	RewriteCond %{REQUEST_URI} .(wp-comments-post|wp-login)\.php*
    	RewriteCond %{HTTP_REFERER} !.*(ipstenu.org|halfelf.org|ipstenu.org|otherplace.net).* [OR]
    	RewriteCond %{HTTP_USER_AGENT} ^$
    	RewriteRule (.*) http://%{REMOTE_ADDR}/$ [R=301,L]
     # SVN & Git protection
    	RewriteRule ^(.*/)?(\.svn|\.git)/ - [F,L]
    	ErrorDocument 403 "Access Forbidden"
    </ifModule>
    

    Ahhh, yes. Here I say “If you’re coming to wp-comments-post OR wp-login and you are NOT refereed by one of my domains, sod off.” And then it says “Oh and if you’re looking for .svn or .git files? Go away.” This isn’t perfect, but it works for some of the botnets. The fun part is that the rewrite sends them back to themselves, which should cause annoying things to happen. Don’t want that? Redirect them to fbi.gov. Actually, if some tool had a page “Redirect botnets here…” I would use that, but generally I send them to http://lmgtfy.com/?q=wordpress+botnet because I’m that sort of kid.

    Speed and Bandwidth

    Now that I’m safer, lets speed this stuff up!

    <IfModule mod_rewrite.c>
     RewriteEngine on
    # ultimate hotlink protection
     RewriteCond %{HTTP_REFERER}     !^$
     RewriteCond %{REQUEST_FILENAME} -f
     RewriteCond %{REQUEST_FILENAME} \.(gif|jpe?g?|png)$               [NC]
     RewriteCond %{HTTP_REFERER}     !^https?://([^.]+\.)?(ipstenu.org|taffys.org|halfelf.org|poohnau.us|ipstenu.org) [NC]
     RewriteRule \.(gif|jpe?g?|png)$                                 - [F,NC,L]
    </ifModule>
    

    First up, stop the hotlinks! I got the idea from Perishable Press, and it stops you from embedding my images. This means my site is faster, as you’re not sucking up my bandwidth. I get 5G so it’s not too much of a concern right now, but it’s the principle of the thing. Don’t hotlink images!

    ### Caching Section ###
    # mod_pagespeed
    <IfModule pagespeed_module>
    	ModPagespeed on
    	ModPagespeedEnableFilters defer_javascript,combine_javascript,move_css_to_head,insert_dns_prefetch,insert_image_dimensions,inline_preview_images,resize_mobile_images
    	ModPagespeedDisallow */FOLDERNAME/*
    	ModPagespeedEnableFilters insert_ga
    	ModPagespeedAnalyticsID UA-MYCODE-4
    </IfModule>
    

    I use Pagespeed on my server, so here I’ve added in my extra rules. Not everything is active for all sites. This is my default WP rule-set though, and it works well. I have it skipping a couple non WP folders, who have their own rules inside on their own .htaccess files anyway. If you don’t have pagespeed? Skip this section.

    # Expired
    <IfModule mod_expires.c>
    <Filesmatch "\.(jp?eg|png|gif|ico|woff)$">
        ExpiresActive on
        ExpiresDefault "access 1 year"
    </Filesmatch>
    
    <Filesmatch "\.(css|js|swf|mov|mp3|mpeg|mp4|ogg|ogv|ttf|xml|svg|html)$">
        ExpiresActive on
        ExpiresDefault "access 1 month"
    </Filesmatch>
    
        ExpiresDefault "access 2 days"
    </IfModule>
    ## END EXPIRES ##
    

    Oy. There are a couple ways you can control all these things. One is the way I did (filesmatch) and the other is ExpiresByType image/jpg "access plus 1 year". Is one better than they other? I don’t know. Not that I’ve managed to see, but I find the filesmatch to be easier to read and add things too. It’s shorter. Does that make it better? Only in so far as my management goes.

    #Gzip
    <IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript text/javascript font/opentype font/truetype font/eot application/x-font-ttf
    </IfModule>
    #End Gzip
    

    Finally we have gzip, which compresses and makes things smaller and thus faster. Using gzip saves me about 80% in filesize, so it makes things faster to download and, thus, display. If you’re using this in your .htaccess, do not also try to use it in plugins/extensions for other web apps, that way likes double compression and garbage on your pages.

    Add support!

    This is a really short bit to add in support for filetypes I use that aren’t always standard:

    # Add filetypes
    AddType application/x-mobipocket-ebook mobi
    AddType application/epub+zip epub .epub
    AddType video/ogg .ogv
    AddType video/mp4 .mp4
    AddType video/webm .webm
    

    Rewrites

    In general, this is useless to everyone else, save as an example.

    ### Massive Redirect Section! ###
    <IfModule mod_rewrite.c>
    RewriteEngine On
    
    # Apple Touch Icons
    RewriteRule ^(.*)-precomposed.png /code/images/apple/$1.png [L,R=301]
    RewriteRule ^apple-touch-icon(.*) /code/images/apple/apple-touch-icon$1 [L,R=301]
    
    # Ipstenu Moves
    RewriteCond %{HTTP_HOST} ^blog\.ipstenu\.org
    RewriteRule ^(.*) https://ipstenu.org/$1 [L,R=301]
    RewriteCond %{HTTP_HOST} ^ipstenu\.org
    RewriteRule ^blog/([0-9]{4})/([0-9]{2})/(.*)$ https://ipstenu.org/$1/$3 [L,R=301]
    RewriteCond %{HTTP_HOST} ^ipstenu\.org
    RewriteRule ^blog/(.*)$ https://ipstenu.org/$1 [L,R=301]
    RewriteCond %{HTTP_HOST} ^ipstenu\.org
    RewriteRule ^wp-content/blogs.dir/1/files/(.*)$ https://ipstenu.org/wp-content/uploads/sites/1/$1 [L,R=301]
    RewriteCond %{HTTP_HOST} ^ipstenu\.org
    RewriteRule ^(.*)favicon.(ico|png)$ /code/images/favicons/ipstenu.ico [L,R=301]
    
    [NB: This sort of thing is duplicated for other domains which also had things moved around]
    </IfModule>
    

    I cut out a couple of sections, where what I did with the ‘Only redirect ipstenu.org’ stuff is repeated for each site. I built much of that after reading my 404 logs and determining what needed to be redirected. Everything is commented and in logical sections, so I can easily find and remember what the heck I was doing.

    This is the longest section, the stuff under # Ipstenu Moves and such, because they’re accounting for files that moved a million years ago. But the moves section is pretty straightforward too, as you can see where things went. I try to keep it as compact as I can. Sometimes I go through and make them more and more efficient, as I learn new tricks.

    What used to be here?

    I used to include the 5G Blacklist 2013 and/or the 2013 User Agent Blacklist (or whatever the current versions are), but now I don’t have it on all my sites because of the work I’ve been putting in on my firewall and ModSecurity instead. Every once in a while, someone tells me I’m putting too much work on Apache to handle the hackers and spammers, and I generally reply “Better Apache than WordPress.”

    Regularly, I go through my .htaccess and see what I can push over to ModSec. I also trim down my PageSpeed rules into things that work on most sites, things that only work on this site, and things that work for everything. This is why there’s no blacklisting here, it’s all handled by my firewall and mod_security and that’s that. I like to take the load off of apache and .htaccess and PHP and make the server do the work.

    Why not nginx?

    Per site configuration is still a pill. No, really that’s it. It’s a hassle to re-do everything I have in htaccess, I can’t just toss a .nginx file in there on the fly without restarting nginx, which means for shared hosts it’s just not gonna happen. Sucks. For managed hosting, where you don’t allow users to make those changes, sure, it’s great. But that’s not my use case. I may use it for a Varnish in front server one day, after I rebuild everything from scratch.

  • Don’t Fear The Auto Update

    Don’t Fear The Auto Update

    I was not surprised to see the backlash to Auto Updates. We spent a lot of time trying to figure out how to explain to people that while you can disable it, we really, really, really, really, don’t want you to, and basically ended up with a Codex page that explained how to configure it and then Nacin’s followup post that is, indeed, the definitive guide to disabling updates. But people hate it or love it, and there’s no middle ground. This was, as I implied, somewhat expected.

    No auto-updates makes me sadReasons why people hate it have varied from “I want to control my own updates!” to “This 3.7 upgrade broke something, so clearly you’re not ready!” Oh and don’t forget “You suck, I hate this! Why would you default this to on!?”

    I want to stress one really important thing here. The automatic background updates for WordPress are for minor updates only. We’re not talking about auto-upgrading people from 3.7 to 3.8, but just 3.7 to 3.7.1 – These are small, minor, updates. When someone comes to me and complains that major releases don’t always work, I have actually said, “So? We’re not talking about major releases.” And of course, “You are making good backups on these super important websites, right? Right?”

    It’s really easy to get bogged down with all the variable permutations about what updates could include and forget that WordPress started out simple. Yes, it’s defaulted to “on” because after intensive testing, and careful thought, WordPress core devs are pretty darn sure that these minor updates, which are more often than not security related, will not break a site. I’ll get back to breaking sites in a second. The point is that minor updates were picked specifically because it’s known that major upgrades can often break things.

    Why is it defaulted to on? This is my reasoning here… Because the people who wouldn’t turn it on are the people who need it most. If they don’t know it can be turned on, they won’t do it. And they need it. The people who don’t read all the nerdy things are the ones who are still running WordPress 3.4 (no I’m not kidding). I spend a lot of time debugging WP without ever seeing or really ever looking at their site. I know a lot of users don’t upgrade because of laziness, or fear, so I want to address this (see? told you I’d get back to breaking sites).

    Don’t fear updates

    Don't Fear The ReaperI said this on Twitter: If your site breaks every time you update WordPress, it’s time for a theme and plugin audit.

    So what’s an audit? How does one audit?

    It’s really simple. I have a longer presentation I give on this, but let’s go over how simple and basic this is.

    Who is the author?

    This is really obvious. With one exception, every plugin I use that’s made by core developers is updated to fix problems right away. It’s tested on versions of WordPress in the Beta stage, or even on trunk. It’s reliable because the author is reliable. Using a plugin by Mark Jaquith? No fear!

    How active is the author?

    Sometimes even I have no idea who that author is, so I look them up. And I want to see how active they are in WordPress. If someone is engaging on trac and writing plugins and themes, and posting about WordPress, yes, I take the time to read up on them. Remember, I’m auditing the plugin! So I want to see that this author is active and writes or contributes in a way that I approve of. That helps me trust them. Now I’m not expecting them to code as prolifically as Nacin, or write as frequently as Chris Lema, or even scour trac like Scribu. I have realistic expectations. One of my favorite developers is ‘try-lingual’ when it comes to CMSs, so I’ll check on her to see if she’s able to keep up with all the myriad CMSs her code works on. She knows about every release coming up? No fear!

    How popular is it?

    The more a plugin is used, the more people are banging on it in a diverse myriad of environments in ways the author probably never imagined. This is good. This means that the odds are higher than normal that the plugin will work on a bog-standard setup. It also means if I have a common server type (shared) it will probably work. The odds also go up for a more active volunteer environment. Popular plugin, used by thousands? No fear!

    How often is it updated?

    This is a careful thing. I don’t particularly worry if a plugin is old (i.e. not updated in over two years) if the plugin is simple, or made by someone very reliable. Heck, I haven’t touched the code in Impostercide in years, but I do update the readme every couple of WordPress releases to avoid people thinking it’s been abandoned. That said, I do like to see if the complicated ones are at the very least updating their readmes to say “yes, compatible up to the most recent version.” That tells me not only are they testing, but they’re aware of what’s going on in WordPress. Updates are reasonable? No fear!

    What does the code look like?

    The Reaper is Melvin'dThis is hard. This is really hard. I review plugins, and write them, and it’s just plain hard okay? If I’m lucky, I don’t actually have to do this. Examples? Okay, try StudioPress’ Genesis Theme. I don’t look at their code, unless I need to make a child theme. Even then, it’s a case of trusting them to do the best by me. I believe in their code more than mine most of the time. Another example? Anything managed by WordPress.org. But what about the rest? When it’s simple, I can read through the code, make sure it’s not doing anything nefarious and move on. When it’s not, I hire someone else to do it. You heard me. I pay people to do what I can’t because an audit of code is important. Now I don’t do this for every site. Personal/play sites? I may wing it, knowing I make good backups. But a big, company site? Oh you bet every single line of code was checked. Good code? No fear!

    Really? No fear?

    No. Not really. You have to keep in mind that none of these are absolutes. I don’t look at just one thing and say “Done, I have no fear.” I mean, I say ‘no fear’ in these explanations, but the truth is it’s the combination of these things that makes me fear less. WordPress is doing a good thing here and I’m not afraid of it.

    And in case you’re wondering, I’m using auto-updates on all my sites.

  • Polyphemus Problem Pans Out

    Polyphemus Problem Pans Out

    I use PHP in DSO mode, which is (woefully) insecure because it lives to save files as ‘nobody.’ Now, previously I found a ‘fix’ to this with WordPress, by tweaking some file permissions and a define in my wp-config.php file, and all was well. But if you know me, you know I’m polyamorus with my CMS, and WordPress ain’t the only game in town.

    I love, love, love Zenphoto for a gallery that is larger than my thumbdrive. But I’ve been having an annoyance that acrylian and sbillard have been really patient with me ranting about for a while now. See, when you upgrade Zenphoto, it narked at me that I had bad permissions:

    zenphoto-perms

    Oh how I cried. My work-around became to make those 777, upgrade, and change ’em back to 755, because that did work for nobody, but when Zenphoto moved the config file and had it be writable by the upgrader, I had to make that owned by nobody and the slippery slope was happening. This was not good. I brought it up again, but we all agreed this was very much a me-problem.

    A new PHP

    Now my choices were to deal with it, or change to a new PHP. Well there are problems with that, and neither suPHP nor FastCGI met my needs for speed and memory consumption. Also I tend to get error 500s when I try any of them on this server, which means I would have to do a total overhaul which I don’t have time for. Instead, I decided to look into why mod_php (aka DSO) likes to have nobody own this stuff. In my research, I stumbled across mod_ruid2, which is included in EasyApache.

    Gruppo_di_polifemo,_sperlonga_0In reading up on cPanel’s notes on mod_ruid2, I hit the incompatibilities list and winced. Right there near the top was MemCache. When I switched over to ZendOptimizer, I also switched to MemCache, and I really was not ready to give it up and go to XCache. Worse? It’s not compatible with mod_security. Epic fail. I absolutely cannot use this. Back to the drawing board until cPanel figures out a way to force it to work with those.

    More searching introduced me to MPM-itk. This was something categorically not supported by cPanel (they backed mod_ruid2), but they still had some directions on how to do this in their forums: Using MPM ITK as a Custom Opt Module

    I need to stress two very important things here:

    1) This is NOT supported by cPanel.

    They do include it in their Custom Mods, but they don’t support it’s use, and won’t include it by default because of issue number 2 (see below). Mind you, I’m no stranger to unsupported installs. I have ImageMagick in a higher version than they do, I installed wp-cli, and I have Pagespeed. So I pretty much run around always upgrading what I need. I am smarter than I used to be, and I have all this documented in a Word Doc called “Custom Installs on my server” which lives on Dropbox, for emergencies. Everything is written with code examples and as much copy/pasta as I can.

    2) There is a security risk with mpm-itk because it runs as root.

    I will quote the author:

    Since mpm-itk has to be able to setuid(), it runs as root (although restricted with POSIX capabilities and seccomp v2 where possible) until the request is parsed and the vhost determined. This means that any code execution hole before the request is parsed will be a potential root security hole. (The most likely place is probably in mod_ssl.) This is not likely to change in the near future, as socket passing, the most likely alternative solution, is very hard to get to work properly in a number of common use cases (e.g. SSL).

    Obviously this is a choice you need to make yourself. Perhaps ironically, by using setuid(), you’re protected from users cross-contaminating but this is not really a perfect fix for everyone. And frankly, this is not my preferred long term fix. My long term fix is this: Build a brand new server, from scratch, with FastCGI, and move sites over one at a time, testing as I go. That’s not today. Instead, it took me about an hour to figure this stuff out and install. And it worked out of the box. Well, except for one thing which I’ll get to.

    Installing mpm-itk

    These directions are pretty easy for cPanel/WHM. You install:

    cd ~/tmp
    wget http://docs.cpanel.net/twiki/pub/EasyApache3/CustomMods/MPMitk.tar.gz
    tar -C /var/cpanel/easy/apache/custom_opt_mods -xzf MPMitk.tar.gz
    

    Then you run EasyApache (/scripts/easyapache) and select mpm-itk from the Exhaustive Options list for PHP (it will give you a warning about the dangers, Will Robinson). Once the update is done, make sure all your normal settings are back in place, if you have anything special, and now you have to actually tell every virtual host what ID to use.

    mkdir -p /usr/local/apache/conf/userdata/std/2/username
    echo &quot;AssignUserID username username&quot; &gt;&gt; /usr/local/apache/conf/userdata/std/2/username/mpm.conf
    /scripts/ensure_vhost_includes --user=username
    

    Replace ‘username’ with your user name (you saw that coming, right?) and off you go. Of course, I had 10 users, so instead I scripted it:

    #!/bin/bash
    for user in `ls /var/cpanel/users`; do
        mkdir -p /usr/local/apache/conf/userdata/std/2/${user}
        echo &quot;AssignUserID ${user} ${user}&quot; &gt;&gt; /usr/local/apache/conf/userdata/std/2/${user}/mpm.conf
        /scripts/ensure_vhost_includes --user=${user}
    done
    

    Huzzah!

    Cleanup, Aisle PHP

    Once I had it installed, and it really was painless, I tested uploads on WordPress and everything worked. But I remembered what I had done back in 2011:

    The last step I had was chowning the folder for uploads and 2011 to nobody:nobody.

    This time I did it in reverse and chowned everything back to my user IDs. I did this for all sites, for all users, and all cache folders. Then I decided to look for all files and folders that were 777 (which I do at work when scanning for hacks) just in case I’d been stupid. I try to not be, but…

    find . -type d -perm 0777
    

    That listed all directories, and I was appalled to find some! That’s right. Up until recently, there were folders permission’d as 777 on my server. I bow my head in shame and embarrassment. Please forgive me, as I run this command to fix that:

    find . -type d -perm 777 -print -exec chmod 755 {} \;
    

    I also ran find . -group nobody to see if I had anything left over, and it happily came up empty. Then I went to double check everything worked. When I’d tested before, I did it on my single install of WP, my wiki, my gallery, another blog, and it worked. So I came here to post and I couldn’t upload images. Horror! Shock! I decided to scan my error log, and right away got a warning on cPanel: Out of disk quota.

    Well that was an easy fix!

    Now everything’s owned by the user it runs for, and nobody owns anything. Everything is secure (except for that ‘running setuid as root for a millisecond’ issue, and yes I’m keeping tabs on that), and everyone is happy. Especially me.

    Bonus Internet points if you get the joke with the title.

  • Separate Users Are Good

    When you create a new domain on DreamHost, you can chose to make a ‘new’ user to ‘own’ the site, or use an existing one. There are pros and cons to both, but for anyone who comes from the cPanel world (where separate accounts are de rigueur), it’s pretty normal to expect your separate site to have a separate login name and password.

    Explaining how all this works on DreamHost is a little different, because we have users and then we have users and … well let me explain.

    There’s more than one kind of user

    The first type of ‘user’ you have at DreamHost is your panel user. This user is the one you make when you sign up, and it’s usually your email. Don’t share this password with anyone, okay?

    Next we have your ‘users’ which you can find in your panel. Those users are the ones who have access to things like ‘shell’ and ‘sftp’ and so on.

    Then there are also those ‘other’ users you think of, like the login accounts on your blog, or your email, or maybe even the billing account for DreamHost.

    When I talk about separate users, I’m only talking about the ones who have access to shell and stuff.

    Users own sites

    Those user accounts own sites. That means I have a specific user who ‘owns’ the folder on the server where all my web code lives. And you can see it’s that user because there it is, in the path: /home/USERID/domain.com/

    Only one user can own, and access, a domain. However a user can own multiple domains.

    So here’s what this looks likes. One user owning multiple domains:

    one user multiple domains

    And only one user can access the domain, user two cannot:

    User 2 has no access

    This is cool because if there’s a domain under User 2, and it gets hacked, there’s no way for User 1 to get hacked, even if both users are you!(Unless there’s a server wide security flaw, which yes, can happen, but we spend a lot of time trying to prevent that.)

    Logical User/Domain Groups

    If you own 50 domains (and I’ve seen users with 200!), having them all owned by one user sure seems easier, but it means if that user gets hacked, they’re all vulnerable, and you’ll probably end up having to de-hack 50 domains at the same time. Instead, it’s wiser to group your domains ‘logically.’ For example, my elftest.net domains have subdomains, all of which are owned by the same user. However my other top-level domains are each owned by their own user. But that doesn’t work for everyone.

    Recently I was helping a customer with a hacked site, and he complained that the sites he hosted for his clients were being hacked, and his clients were pissed off. I took a look and saw that all his client sites were under one user ID. I asked him if the clients had more than one domain, or if they all had their own, and he replied that each client had 4 or 5 of the domains. After cleaning up the hack, together we made new user accounts, one for each client, and moved the domains to those accounts. If possible, I always clean before moving, but in one case the customer had 75+ hacked sites, so we moved and then cleaned each one, prioritizing the accounts on the way. It took a very long time.

    109649_D_0989 The extra benefit to this is the clients can now have FTP access to their domains and do wild and crazy stuff! But we don’t want them to have FTP.

    Moving The Domain

    Obviously first you need to setup users. When I set up a new user, the first thing I do is make it secure. That means I turn off FTP, forcing SFTP only, and if needed, give them Shell access. Personally? I love shell access, so I always leave it available. If you’re using DreamPress, we have Shell turned off by default, but you can activate it.

    Secure User Settings

    There is a downside, which is that the WebFTP app won’t work. Personally? I find 99.999% of WebFTP apps to be total drek. They’re messy, kludgy, and there are some great free apps like Cyberduck which even let you connect with DreamObjects!

    Now that you have the user, we want to move the domain. This is so easy, anyone can do it. Go into Panel, click on domains, click on edit for the domain. Go to “Users, Files, and Paths” and change the user in “Run this domain under the user:”

    Changing Users

    Really, it is that simple.

  • MeetWP: Troubleshooting

    MeetWP: Troubleshooting

    I met the guys from MeetWP when I was at WordCamp Chicago, and when they asked if I’d be interested, I thought about it for a second and said “Sure, why not.” I live in the OC, you see, and while I enjoy meetups, the two nearest me are just over an hour away. I’m a one-car home, and generally my spouse has class when these meetups are, so the timing has just be downright rotten. But a virtual meetup? Hey that has potential.

    MeetWP Logo

    What is this thing? From their site:

    MeetWP is an online WordPress Meetup. Local Meetups are a great place to learn about WordPress and meet new people in the WordPress community, but not everyone can make it to a local meetup or are in an area where a Meetup dedicated to WordPress can happen. MeetWP, the online WordPress Meetup, is here to bring together people all over the world in a virtual meetup to learn from each other.

    So yay! They’ll be posting this up on their webpage as a link with all the logs soon enough, and you’ll see me up there as MeetWP (following JJJ, Chris Lema, and Lisa Sabin-Wilson). I didn’t do slides, so you get to watch me break a site, fix it, and then show you my break-fix site (more on that later) where I have examples and plugins you can use to install, break your site, and fix it.

    There were crowdsourced notes on Google (you can read them here), and one of them is ‘Don’t be Stupid.’

    photoI try to cure myself of stupid as much as I can, because being hacked almost always boils down to someone being stupid. If I can not be the stupid, I’m in good standing.

    Oh and yes, I think SSH and SFTP are a requirement for a webhost. If they can’t do that, I’m gone.