Skip to content
This repository has been archived by the owner on Jul 24, 2021. It is now read-only.

Commit

Permalink
Update mkpasswd to be slightly more secure
Browse files Browse the repository at this point in the history
Try to ensure that the mkpasswd command run in ssh sessions only echos to
ssh client running that command. This gives us slightly more security
against other session users seeing the hashed password.

Fixed console sending with some of the APIs

Updated version to 1.3.7 to match for next spigot + bungeecord release.
  • Loading branch information
Justasic committed Oct 11, 2019
1 parent ec1ed8c commit 170a96e
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 82 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
Spigot-SSHD
Minecraft-SSHD
===========

[![Build Status](https://travis-ci.org/Justasic/Spigot-SSHD.svg?branch=master)](https://travis-ci.org/Justasic/Spigot-SSHD)
[![Release](https://img.shields.io/github/release/Justasic/Spigot-SSHD.svg?label=Release&maxAge=60)](https://github.com/Justasic/Spigot-SSHD/releases/latest)
[![GitHub license](https://img.shields.io/github/license/Justasic/Spigot-SSHD)](https://github.com/Justasic/Spigot-SSHD/blob/master/LICENSE)
[![Build Status](https://travis-ci.org/Justasic/Minecraft-SSHD.svg?branch=master)](https://travis-ci.org/Justasic/Minecraft-SSHD)
[![Release](https://img.shields.io/github/release/Justasic/Minecraft-SSHD.svg?label=Release&maxAge=60)](https://github.com/Justasic/Minecraft-SSHD/releases/latest)
[![GitHub license](https://img.shields.io/github/license/Justasic/Minecraft-SSHD)](https://github.com/Justasic/Minecraft-SSHD/blob/master/LICENSE)

<img align="left" width="140" height="140" src="docs/ssh_logo.png?raw=true" hspace="5" vspace="5" alt="diskover"><br/>

**Have you ever wished you could remotely access your server's admin console without having to setup a complex remote access system? Now you can with SSHD.**
**Have you ever wished you could remotely access your server's admin console without having to setup a complex remote access system? Now you can with Minecraft-SSHD!**

SSHD securely exposes your BungeeCord admin console and the server filesystem using the SSH protocol - the same protocol that serves as the secure foundation for nearly all remote server administration.<br/>
Minecraft-SSHD securely exposes your BungeeCord admin console and the server filesystem using the SSH protocol - the same protocol that serves as the secure foundation for nearly all remote server administration.<br/>

- Compatible with all ssh clients, regardless of operating system.
- Remotely view your server log in real-time.
Expand All @@ -20,7 +20,7 @@ SSHD securely exposes your BungeeCord admin console and the server filesystem us
- Run Spigot without using screen or tmux (by adding `-noconsole`)
- Remotely script your server by issuing one-off console commands with ssh.

### Why should I use SSHD?
### Why should I use Minecraft-SSHD?

- You are in a shared hosting environment that only gives you access to the - log files.
- You want to share access to your server console, but don't want to give anybody access to the machine its running on.
Expand Down Expand Up @@ -93,8 +93,8 @@ mkpasswd supports the following hash algorithms:

`sshd.mkpasswd` - Checks if the in-game user has access to run the mkpasswd command.

SSHD uses cryptographic certificates or a secure username and password to verify remote access.
Minecraft-SSHD uses cryptographic certificates or a secure username and password to verify remote access.


## Source Code
[Get the source on GitHub](https://github.com/Justasic/Spigot-SSHD "Source Code")
[Get the source on GitHub](https://github.com/Justasic/Minecraft-SSHD "Source Code")
5 changes: 3 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

<groupId>com.ryanmichela</groupId>
<artifactId>sshd</artifactId>
<version>1.3.6.1</version>
<url>https://github.com/Justasic/Bukkit-SSHD/</url>
<description>Minecraft-SSHD: The SSH daemon for Minecraft servers.</description>
<version>1.3.7</version>
<url>https://github.com/Justasic/Minecraft-SSHD/</url>

<properties>
<java.version>1.8</java.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public String format(LogRecord logrecord)
stringbuilder.append(stringwriter.toString());
}

return stringbuilder.toString();
return stringbuilder.toString().replace("\n", "\r\n");
}

private void colorize(LogRecord logrecord)
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ public void run()
if (command.equals("cls"))
{
this.ConsoleReader.clearScreen();
this.ConsoleReader.drawLine();
this.ConsoleReader.flush();
continue;
}
// Hide the mkpasswd command input from other users.
Expand All @@ -152,10 +154,18 @@ public void run()
}
else
{
// Don't send our mkpasswd command output. This will echo passwords back
// to the console for all to see. This command is strictly between
// our plugin and the connected client.
if (!mkpasswd)
{
SshdPlugin.instance.getLogger().info("<" + this.Username + "> " + command);

Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
}
else
{
Bukkit.dispatchCommand(this.SshdCommandSender, command);
}
}
});
}
Expand Down
117 changes: 55 additions & 62 deletions src/main/java/com/ryanmichela/sshd/MkpasswdCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,88 +12,81 @@

class MkpasswdCommand implements CommandExecutor
{
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args)
// Because Spigot's failed syntax API is really less than ideal (you should be required to add a
// SendSyntax function override), we're just always going to return true even for syntax failures
// as we will handle the syntax message internally. This also lets us send the messages more
// securely to the client without people knowing we're using the command. This prevents password
// or hash leakages from the user to other connected users. Plus this syntax will show how
// to both use the command and what hashes we support which is important for people who don't
// know how to RTFM. - Justin
private void SendSyntax(CommandSender sender, boolean invalid)
{
if (invalid)
sender.sendMessage("\u00A7cInvalid Syntax\u00A7r");
sender.sendMessage("\u00A7a/mkpasswd <help|hash> <password>\u00A7r");
sender.sendMessage("\u00A79Supported Hashes: SHA256, PBKDF2, BCRYPT, PLAIN\u00A7r");
}

@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args)
{
// If we're not mkpasswd, just fuck off.
if (!label.equalsIgnoreCase("mkpasswd"))
return false;

String algoritm, password;
try
{
// Stupid bukkit, we have to concatenate the arguments together if they're using
// spaces in their passwords otherwise it won't be as strong as it should be.
algoritm = args[0];
password = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
if (password.trim().isEmpty()) // Shortcut to the catch statement below.
throw new ArrayIndexOutOfBoundsException();
}
catch (ArrayIndexOutOfBoundsException e)
{
// ignore it.
return false;
this.SendSyntax(sender, true);
return true;
}

// If they're console, allow regardless.
if (!(sender instanceof Player))
{
if (label.equalsIgnoreCase("mkpasswd"))
boolean hasperm = (sender instanceof Player) ? ((Player)sender).hasPermission("sshd.mkpasswd") : true;

if (hasperm)
{
try
{
try
String hash = "";
// Dumb but whatever. Some people are really dense.
if (algoritm.equalsIgnoreCase("PLAIN"))
{
// Dumb but whatever. Some people are really dense.
if (algoritm.equalsIgnoreCase("PLAIN"))
{
// I mean c'mon...
sender.sendMessage("Bro really? it's literally your unencrypted password...");
}
else if (algoritm.equalsIgnoreCase("pbkdf2"))
sender.sendMessage("Your hash: " + Cryptography.PBKDF2_HashPassword(password));
else if (algoritm.equalsIgnoreCase("bcrypt"))
sender.sendMessage("Your hash: " + Cryptography.BCrypt_HashPassword(password));
else if (algoritm.equalsIgnoreCase("sha256"))
sender.sendMessage("Your hash: " + Cryptography.SHA256_HashPassword(password));
else if (algoritm.equalsIgnoreCase("help"))
sender.sendMessage("Supported hash algorithms: pbkdf2, bcrypt, sha256, plain");
else
return false;
// I mean c'mon...
sender.sendMessage("Bro really? it's literally your unencrypted password...");
return true;
}
catch (Exception e)
else if (algoritm.equalsIgnoreCase("pbkdf2"))
hash = Cryptography.PBKDF2_HashPassword(password);
else if (algoritm.equalsIgnoreCase("bcrypt"))
hash = Cryptography.BCrypt_HashPassword(password);
else if (algoritm.equalsIgnoreCase("sha256"))
hash = Cryptography.SHA256_HashPassword(password);
else
{
// We're console, just print the stack trace.
e.printStackTrace();
return false;
this.SendSyntax(sender, !algoritm.equalsIgnoreCase("help"));
return true;
}
return true;

sender.sendMessage("\u00A79Your Hash: " + hash + "\u00A7r");
}
}
else
{
Player player = (Player) sender;
if (label.equalsIgnoreCase("mkpasswd"))
catch (Exception e)
{
try
{
if (player.hasPermission("sshd.mkpasswd"))
{
// Dumb but whatever. Some people are really dense.
if (algoritm.equalsIgnoreCase("PLAIN"))
sender.sendMessage(password);
else if (algoritm.equalsIgnoreCase("pbkdf2"))
sender.sendMessage(Cryptography.PBKDF2_HashPassword(password));
else if (algoritm.equalsIgnoreCase("bcrypt"))
sender.sendMessage(Cryptography.BCrypt_HashPassword(password));
else if (algoritm.equalsIgnoreCase("sha256"))
sender.sendMessage(Cryptography.SHA256_HashPassword(password));
else
return false;
}
}
catch (Exception e)
{
// since this is a player, send a failure message
sender.sendMessage("An error occured, please check console.");
e.printStackTrace();
return false;
}
return true;
}
// We're console, just print the stack trace.
e.printStackTrace();
sender.sendMessage("\u00A7cAn error occured. Please check console for details.\u00A7r");
}
}
return false;
}

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,23 @@
import org.bukkit.plugin.Plugin;

import com.ryanmichela.sshd.ConsoleShellFactory;
import com.ryanmichela.sshd.ConsoleLogFormatter;

import java.io.IOException;
import java.util.Arrays;
import java.util.Set;
import java.util.logging.Level;

public class SSHDCommandSender implements ConsoleCommandSender, CommandSender {

public class SSHDCommandSender implements ConsoleCommandSender, CommandSender
{
private final PermissibleBase perm = new PermissibleBase(this);
private final SSHDConversationTracker conversationTracker = new SSHDConversationTracker();
// Set by the upstream allocating function
public ConsoleShellFactory.ConsoleShell console;

public void sendMessage(String message) {
this.sendRawMessage(message);
public void sendMessage(String message)
{
this.sendRawMessage(message + "\r");
}

public void sendRawMessage(String message)
Expand All @@ -40,7 +42,18 @@ public void sendRawMessage(String message)
return;
try
{
this.console.ConsoleReader.println(ChatColor.stripColor(message));
this.console.ConsoleReader.println(ConsoleLogFormatter.ColorizeString(message).replace("\n", "\n\r"));
this.console.ConsoleReader.print(this.console.ConsoleReader.RESET_LINE + "");
this.console.ConsoleReader.flush();
try
{
this.console.ConsoleReader.drawLine();
}
catch (Throwable ex)
{
this.console.ConsoleReader.getCursorBuffer().clear();
}
this.console.ConsoleReader.flush();
}
catch (IOException e)
{
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: SSHD
version: ${project.version}
author: Ryan Michela, Haarolean, toxuin, Justin Crawford
author: Ryan Michela, Haarolean, toxuin, Justin Crawford, Zachery Coleman
main: com.ryanmichela.sshd.SshdPlugin
load: STARTUP
commands:
Expand Down

0 comments on commit 170a96e

Please sign in to comment.