Skip to content

Instantly share code, notes, and snippets.

@razvn
Created April 27, 2021 09:56
Show Gist options
  • Save razvn/f92c6063b6314956d4f0d56809e8c807 to your computer and use it in GitHub Desktop.
Save razvn/f92c6063b6314956d4f0d56809e8c807 to your computer and use it in GitHub Desktop.
Http4k WebSocket remote shell

Based on http4k, creates a server that lets exposes the server's shell through websocket.

Put the index.html page in ressources/static

Start the app and go to http://:8080/index.html

Enter the password pwd!1 in order to be allowed to send commands to the servher

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Remote terminal</title>
<style>
textarea {
background-color: #000;
border: 1px solid #000;
color: #00ff00;
padding: 8px;
font-family: courier new, monospace;
font-size: 16pt;
}
input {
padding: 5px;
margin: 10px;
font-size: 14pt;
}
</style>
</head>
<body>
<div>
<label for="adminPwd">Admin password</label><input id="adminPwd" size="50" type="password" placeholder="password"/>
<input type="button" onclick="connect()" value="Connect"/>
<input type="button" onclick="disconnect()" value="Disconnect"/>
</div>
<div>
<label for="command">Input</label>
<textarea id="command" rows="5" cols="80" onkeypress="checkEnter(event)" autocapitalize="off" spellcheck="false"></textarea>
</div>
<div>
<label for="response">Output</label><textarea id="response" rows="25" cols="80"></textarea>
</div>
<script>
var websocket
function connect() {
let pwd = document.getElementById('adminPwd')
let host = window.location.hostname
let port = window.location.port
let protocol = window.location.protocol.replace("http", "ws")
let url = protocol + "//" + host + ":" + port + "/ws?pwd="+pwd.value
// console.log("connect url", url)
websocket = new WebSocket(url)
websocket.onopen = function (evt) {
onOpen(evt)
};
websocket.onmessage = function (evt) {
onMessage(evt)
};
websocket.onerror = function (evt) {
onError(evt)
};
}
function disconnect() {
if (websocket !== undefined) {
websocket.disconnect()
output.value = "DISCONNECTED";
}
}
let output = document.getElementById("response");
function checkEnter(e) {
if (e.keyCode === 13) {
sendMessage()
}
}
function sendMessage() {
let msg = document.getElementById("command").value
let lastLine = msg.substr(msg.lastIndexOf("\n") + 1)
console.log("Sending:", lastLine, "msg:", msg)
websocket.send(lastLine)
}
function onOpen(evt) {
output.value = "CONNECTED";
}
function onMessage(evt) {
console.log("Incoming message", evt)
output.value = evt.data
}
function onError(evt) {
output.value = "!!! Websocket error: " + evt
}
document.getElementById("command").addEventListener(onkeypress())
</script>
</body>
</html>
fun App(): Http4kServer {
val contexts = RequestContexts()
val app = = ServerFilters.CatchLensFailure()
.then(ServerFilters.Cors(CorsPolicy.UnsafeGlobalPermissive))
.then(ServerFilters.InitialiseRequestContext(contexts))
.then(
routes(
"/" bind static(ResourceLoader.Classpath("static")),
)
)
return PolyHandler(app, WebSocketServer()).asServer(Jetty(8080)).start()
}
fun main() {
val server = App()
server.block()
}
object WebSocketServer {
operator fun invoke(): WsHandler {
return websockets(
"/ws" bind websocketTerminal()
)
}
fun WsMessage.bodyStrings() = with(this.bodyString()) {
if (this.startsWith("rm ") || this.contains(" rm ")) "echo Nope \uD83D\uDE00" else this
}
private fun websocketTerminal() =
{ ws: Websocket ->
val pwd = ws.upgradeRequest.query("pwd")
if (pwd != "pwd!1") {
ws.send(WsMessage("!! Authentification error !!"))
ws.close(WsStatus.REFUSE)
}
ws.onMessage {
// println("Input message: $it")
val inputMsg = it.bodyStrings()
if (inputMsg.isBlank()) ws.send(
WsMessage("(please, don't send empty inputs)")
) else {
val resp = try {
Runtime.getRuntime()
.exec(inputMsg)
.inputStream.reader().readText()
.let { r ->
if (r.isBlank()) {
"(empty response)"
} else r
}
} catch (e: Exception) {
"(exception thrown on las command: ${e.message})"
}
ws.send(
WsMessage(resp)
)
}
}
ws.onClose {
// println("WebSocket closed")
}
ws.onError {
// println("WebSocket error: ${it.message}")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment