0
All Posts By

Miro Hristov

Plesk: FTP error retrieving directory list

By Plesk, Security No Comments

Problem:

error: Connection timed out after 20 seconds of inactivity
error: Error retrieving directory listing

Solution 1:

In SSH Terminal run the following:

echo ip_nat_ftp > /etc/modules-load.d/iptables.conf
echo ip_conntrack_ftp >> /etc/modules-load.d/iptables.conf
service xinetd restart

Source: https://unix.stackexchange.com/questions/240044/on-centos7-firewalld-overwrite-iptables-modules

Solution 2:

iptables -A INPUT -m state –state RELATED,ESTABLISHED -j ACCEPT
iptables -I INPUT 2 -p tcp –match multiport –dports 49152:65535 -j ACCEPT
service iptables save
service xinetd restart

Source: https://support.plesk.com/hc/en-us/articles/213902285–How-to-configure-the-passive-ports-range-for-ProFTPd-on-a-Plesk-server-behind-a-firewall

Install Chrome from CMD without using Edge or IE

By Uncategorized No Comments

Run the following command in CMD:

curl https://dl.google.com/tag/s/appguid%3D%7B8A69D345-D564-463C-AFF1-A69D9E530F96%7D%26iid%3D%7B76A2C945-CBE6-0B7D-6007-6630B78D3F61%7D%26lang%3Den%26browser%3D4%26usagestats%3D0%26appname%3DGoogle%2520Chrome%26needsadmin%3Dprefers%26ap%3Dx64-stable-statsdef_1%26installdataindex%3Dempty/update2/installers/ChromeSetup.exe > ChromeSetup.exe && ChromeSetup.exe

//ChromeSetup.exe will start automatically after download.

DigitalOcean: “Server sent command exit status 1” in WinSCP

By Uncategorized No Comments

Solution:

TLDR: Login using the built-in console to change the default password. Use the new password to SSH.

The reason you’re getting this error is because you’re trying to SSH into DigitalOcean using the default root password.

Open the Droplet back-end and find the Console button:

Now login from here with root and your default password (Paste it with Ctrl+V). It will ask you to change the password immediately. You’ll have to paste in the default password one more time. Now type in a new password twice. That’s it. You should be able to SSH with WinSCP or PuTTy without issues now using the new password. Enjoy!

How to Make Cloudflare Cache S3 Files

By Uncategorized No Comments

After 3 days of trying to figure it out, it turned out simpler than I originally thought. The documentation and other articles are very poor and don’t have examples. In this article, I’m using a domain illozoo.com as a real life example to show you how I did it.

The whole trick with CloudFlare caching S3 files is to trick it you’re serving your S3 files from your own domain or, at least, sub-domain. There is no setting or anything special to be done in Cloudflare after that. Once you setup your custom sub-domain, CloudFlare will automatically start cacheing your files because they are on the same domain. The tricky part is setting it up.

How to Setup:

  1. You must setup custom sub-domain for S3. (using CNAME in DNS)
  2. You must (re)name your S3 bucket “cdn.domain.com“.
  3. (For wordpress: Change your CDN plugin settings)

Instead of serving files from [bucket].s3.amazonaws.com you’ll be using cdn.domain.com

The good news is it’s easy and free to setup ūüôā . The bad news is you’ll need to rename your bucket if it already exists and there’s no rename bucket command in AWS (in 2019, hopefully they’ll add it in the future).

If you already created the bucket and it has content, you’ll need to create a new bucket and move the content to the new one ūüôĀ

1. Setting up custom CDN sub-domain:

All you need to do to serve files from cdn.domain.com is add the following DNS record in Cloudflare.
Type: CNAME
Name: cdn
Content: s3.amazonaws.com

No, you do not need to add the bucket name in front of content. Originally, I thought it should be [bucket].[region].s3.amazonaws.com but it’s really not needed. It will still work but anything you add in front of .s3 will be omitted.

You can now test to see if the cname works by going to https://cdn.domain.com. If you haven’t yet created the bucket you’ll get NoSuchBucket. If you did create the bucket but it’s empty you’ll get AccessDenied.

Hint: This is how I found out that the bucket name should be cdn.domain.com

2. Re-naming your bucket

This is probably the most dissapointing part, since there is no easy way to rename a bucket. The bucket name must be cdn.domain.com.

If you’re starting fresh then there’s nothing to worry about. Just name your bucket that. However, if you’ve already have a bucket full of objects then you’ll have to copy the content to a new one. Create a new empty bucket named cdn.domain.com. Then, you’ll need aws-cli to run the following command and copy all the contents to the new one.
aws s3 sync s3://[old-bucket] s3://[new-bucket]

In my case, it was copying with around 9MB/s so on 15GB it will take about 30mins. Alternatively, you can use:
aws s3 mv s3://old-bucket s3://new-bucket --recursive

This will move the files from one bucket to the other, instead of coping, so you won’t have to delete the old bucket. It will end up empty.

3. Change Plugin Settings

Finally, if you’re using WordPress don’t forget to change your CDN plugin settings. In my case, I’m using Media Cloud so I had to change the bucket name and add CDN Base URL.

Notes: Keep in mind that you don’t have to use “cdn” as your subdomain. It could be anything you like — “files”, “s3”, “data” you name it. Just make sure matches your bucket name and CNAME. Hope this helps!

Thanks,
Let me know how it goes for you.

My CloudFlare Account Got Hacked and a Site 301 Redirected

By Security No Comments

The Damage

I came back home from a friend at around midnight to an inbox full of worrisome emails. First, was the email from the owner of illozoo.com asking what happened to the site. When I visited the site, it was getting redirected to some other malware site which wants you to download a “missing font pack”. ¬†It was pretty embarrassing and the worst part about it was that we found out because visitors complained. I was freaking out.

 

A chrome plugin called Redirect Path came in handy in finding out what’s going on:

After making sure that everything on my server was fine, I saw these 2 identical emails from Cloudflare warning about suspicious activity on the account and it all clicked together.

To top it off, I didn’t get these emails on time because my phone has died 3 hours earlier and my friend didn’t have USB-C charger nor did I bring mine. A series of unfortunate events.

The clean-up

I quickly logged into Cloudflare, enabled developer mode which bypasses everything, and after going through the settings I found two 301 Redirects to a bit.do shortening service. ( with wildcards to cover the entire domain, sub-domains, dirs, www and non-www version — pretty simple and evil)

 

301 Redirect = Nightmare from hell

If you’ve ever dealt with a permanent 301 redirect, you probably know it’s the Devil’s work. Once a browser caches a 301 Redirect it does cache it permanently… as in forever. It’s amazing that browsers to this day behave in this way. ¬†The only way to “refresh” a cached 301 redirect is to clear your browser cache. Not just force refresh using Shift+F5 since there is no way you can press theses buttons while on the domain. It will get redirected before you press it. You’d need to clear cached images and files (Using Ctrl+Shift+Del on Chrome on Win). Requiring every affected visitor to do this just to fix your website is unacceptable. That’s how a hacker can completely toast a high-traffic domain name overnight without ever getting a hold of the domain. Fortunately for me, browsers also honor the expiry date of a redirect and Cloudflare has their set at a fixed 1 hour. This is the only thing that saved me.

To summarize, the clean-up was pretty straight-forward:

  1. Remove the 301 redirects from Cloudflare.
  2. Change password and enable 2-factor authentication on the account.
  3. Wait 1 hour for the cached redirects to expire.
  4. Disable developer mode

The Virus

Although I didn’t have the balls to run the¬†fontpack.exe file from the malicious website¬†on my machine, I ran an online test using virustotal.com and sure enough it was packed with “goodies”. (Notice that from the time of making the screenshot until the day of writing this article more antivirus groups have caught up to it)

  

Finally, I wrote a quick note to bit.do and they were kind enough to remove the shortened URL from their service:

Cloudflare’s fault?

My initial reaction was to blame it on #cloudbleed but after getting familiar with what it affects, it seems like this may be unrelated to it. Could it be that it’s just my account that got affected due to weak password? I highly doubt it. I’m using LastPass¬†to randomly generate 16-bit alpha-numeric with special characters passwords and if my lastpass master pass was compromised, a lot more damage would have been done. What I’m definitely blaming Cloudflare for is being unable to require some additional identification upon identifying the suspicious login activity. Sending an email is simply not enough. Lastly, once they identify suspicious login why would they allow them to set up 301 redirect on the entire domain? This could have been thought out more thoroughly. Even if it was really me doing it, I wouldn’t mind having to confirm this action over email. I don’t know… I’m not a security expert but I’m not the only one with this problem and i’m sure they’re aware of it:

http://hakanu.net/dns/2017/01/19/my-site-is-hacked-through-cloudflare-page-rules/

Oh, and 2 factor auth is not bullet-proof apprently:

https://techcrunch.com/2012/06/04/cloudflare-security-breach-the-result-of-smart-social-engineering-flaw-in-googles-account-recovery-system/

 

InkLnk Wireframes & Logo

By Uncategorized No Comments

Front page

inklnk-loading-anim

The gallery

section2.4

Filters

section3.2

Artist Stats

  1. Earnings + Graph
  2. Today’s bookings + options to text or call (or more?)
  3. Calendar – the idea with the circles is the bigger the circles the more booking on that day.

section4

Artist Storefront

  1. Slider with featured images of artist
  2. About the artist
  3. Hours and Location

section5-screenshot

Place an order

  1. Area selection on 3d model
  2. Estimated Total
  3. Click on available date (will ask you for time also)
  4. Upload images
  5. Checkout

section6

Automatically Install WordPress and Create Database on Plesk

By WordPress No Comments

Overview

This code was inspired, well, by laziness.

It automatically creates a MySql database and User using the provided information; Downloads the latest version of WP and unzips it; Changes your config-wp.php to work with the newly created database. Uses SSH2 to connect to shell.

Feel free to use it as is or modify it to your needs. Please report bugs and fixes.

Tested on Plesk 12.0.18.

Requirements

  1. Odin (former Parallels) Plesk
  2. Root access
  3. PHP 5+

Download ZIP

<?php

///////////////////////
// CONFIG
///////////////////////

$rootuser = "root";     // the root user
$rootpass = "PASSWORD"; // the root password
$domainspath = "/var/www/vhosts"; //path to all your domains

///////////////////////
///////////////////////

$db_name = $_REQUEST['db'];
$domain = $_REQUEST['domain'];
$dir = $_REQUEST['dir'];
$user = $_REQUEST['user'];
$pass = $_REQUEST['pass'];
$del = $_REQUEST['del'];
?>

<style>
body {
font-family:sans-serif;
margin:1em;
font-size:1.2em;
color:grey
}

input {
font-size:1.2em;
padding:.3em;
border-radius:4px;
border:1px solid #DEDEDE
}

label {
margin-top:1em
}

input[type='text'] {
width:600px
}

label,input {
display:block
}

.small {
font-size:.5em;
text-transform:uppercase
}

input[type='submit'] {
padding:.5em 1em;
margin:1em 0;
background:#7c3
}

input[type='checkbox'] {
display:inline;
width:.8em;
height:.8em
}
</style>

<h1>Install WordPress &amp; Create Database</h1>
<form id="doit" method="post">
  <label>
    Create Database
    <input id="db" name="db" type="text" />
  </label>
  <label>
    Domain
    <input id="domain" name="domain" type="text" />
  </label>
  <label>
    Directory
    <input id="dir" name="dir" type="text" />
  </label>
  <label>
    Username
    <input id="user" name="user" type="text" />
  </label>
  <label>
    Password
    <input id="pass" name="pass" type="text" />
    <span class="small">(Must not contain username)</span>
  </label>
  <label>
    Delete folder contents? <input type="checkbox" name="del" value="Yes" />
  </label>
  <input type="submit" value="Install WP">
</form>

<?php

echo "<pre>";

if(empty($domain)){ die("API usage syntax example: ?db=mydb&domain=domain.com&dir=projects/company&user=user&pass=pass"); }
 

//////////////////////////////
// Connect to SSH
//////////////////////////////

//Incude SSH2 phpseclib to use shell commands
set_include_path(get_include_path() . 'SSH2' . PATH_SEPARATOR . 'phpseclib');
include('SSH2/Net/SSH2.php');
$ssh = new Net_SSH2('localhost');
if (!$ssh->login($rootuser, $rootpass)) {
    exit('SSH2 Login Failed');
}


/////////////////////////////
// CREATE USER
/////////////////////////////
echo $ssh->exec("/usr/sbin/useradd -g psacln -d /var/www/vhosts/".$domain."/httpdocs/".$dir." ".$user);
//CHMOD to User
echo $ssh->exec("chown -R ".$user.":psacln /var/www/vhosts/".$domain."/httpdocs/".$dir); 
//echo $ssh->exec("chown -R apache:psaserv /var/www/vhosts/".$domain."/httpdocs/".$dir); //CHMOD to Apache
echo $ssh->exec("chmod 775 /var/www/vhosts/".$domain."/httpdocs/".$dir);

/////////////////////////////
// Change Password
/////////////////////////////

$ssh->write("passwd ".$user."\n");
echo $ssh->read('New UNIX password:');
$ssh->write($pass."\n");
echo $ssh->read('Retype new UNIX password:');
$ssh->write($pass."\n");
echo $ssh->read('passwd: all authentication tokens updated successfully.');

echo "<p>===== End Create User =====</p>";

//////////////////////////
// Plesk DB Create
//////////////////////////

echo $ssh->exec('cd '.$domainspath);

echo $ssh->exec('/usr/local/psa/bin/database --create '.$db_name.' -domain '.$domain.' -print-id -server localhost -type mysql');
echo $ssh->exec('/usr/local/psa/bin/database --update '.$db_name.' -add_user '.$user.' -passwd '.$pass);
echo "<p>===== End DB Create =====</p>";
echo die();

////////////////////////////////////
// Download and Untar wordpress
////////////////////////////////////
$c = 'cd '.$domainspath.'/'.$domain.'/httpdocs/;';

if(!empty($dir)){
    $c .= 'mkdir -p '.$dir.';'
    .'cd '.$dir.';';
}

if(isset($del) && $del == 'Yes'){
    $c .='rm * -r;';  //DELETES EVEYTHING INSIDE 
}

$c .='wget --no-check-certificate https://www.wordpress.org/latest.tar.gz;'
    .'tar xfvz latest.tar.gz;'
    .'mv wordpress/* .;'
    .'rmdir wordpress;'
    .'rm latest.tar.gz;'
    .'cp wp-config-sample.php wp-config.php;'
    .'perl -pi -e "s/database_name_here/'.$db_name.'/g" wp-config.php;'
    .'perl -pi -e "s/username_here/'.$user.'/g" wp-config.php;'
    .'perl -pi -e "s/password_here/'.$pass.'/g" wp-config.php;'
    .'mkdir wp-content/uploads;'
    .'chmod 777 wp-content/uploads;';


$pc = str_replace(';', ';<br>', $c);
echo '<br>$ '.$pc;
echo $ssh->exec($c);

echo "<p>===== End WP download & wp-config =====</p>";
?>
</pre>

 

How to Save Protected Images from Websites (Bookmarklet)

By Bookmarklets, Javascript 3 Comments

Have you ever wanted to really save an image from a site but couldn’t because:

  1.  they removed the right-click context menu and an annoying copyrights pop-up box showed up instead.
  2. ¬†the context menu is there but there is no “Save Image As…” option.
  3. ¬†the image only appears when your mouse is over something so you can’t really right-click on it.
  4. ¬†you’re too lazy to open up the Resources¬†tab in Chrome’s Developer¬†Tools and sift trough all the images.

Well, we have the perfect solution for you!

Introducing the Save Any Image Bookmarklet:

Drag this button to your bookmarks

Save Any Image

Click it while¬†on a website¬†which doesn’t allow you to save images.

A new tab will open with a list of all the images on that site.

Yes CSS Background Images too!

Just like that…

save any image bookmarklet

(If you don’t see your bookmark bar press Ctrl+Shift+B to show it.)

 

Click the bookmark and Voila!

show-all-images-bookmarklet-preview

You can now¬†right-click and “Save Image As…”¬†like a boss!

Damn, I sound like a cheesy infomercial¬†ūüôā