Skip to content

Instantly share code, notes, and snippets.

@austinginder
Last active May 4, 2020 13:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save austinginder/783802bd617fb9d18fd0ac0c716304ea to your computer and use it in GitHub Desktop.
Save austinginder/783802bd617fb9d18fd0ac0c716304ea to your computer and use it in GitHub Desktop.
Concept using Phpseclib to run Rclone from WordPress backend. See https://anchor.host/using-phpseclib-instead-of-disallowed-php-exec/.
<?php
/**
* Plugin Name: Rclone Concept
* Plugin URI: https://anchor.host/using-phpseclib-instead-of-disallowed-php-exec/
* Description: Concept using Phpseclib to run Rclone from WordPress backend.
* Author: Austin Ginder
* Author URI: https://austinginder.com
* Text Domain: rclone-concept
* Domain Path: /languages
* Version: 0.1.0
*
* @package Rclone_Concept
*/
require __DIR__ . '/vendor/autoload.php';
use phpseclib\Net\SSH2;
function run_rclone_command( $command, $username, $password ) {
$ssh = new SSH2( '127.0.0.1' );
if ( !$ssh->login( $username, $password ) ) {
exit( "Login Failed" );
}
return $ssh->exec( "cd private/rclone-v*/; ./rclone $command --config rclone.conf" );
}
// Process ajax events
add_action( 'wp_ajax_rclone_concept_ajax', 'rclone_concept_ajax' );
function rclone_concept_ajax() {
global $wpdb; // this is how you get access to the database
// Only proceed if logged in user is an administrator
if ( ! current_user_can('administrator') ) {
return true;
wp_die();
}
$request = (object) $_POST['value'];
$response = run_rclone_command( $request->command, $request->username, $request->password );
echo json_encode( $response );
wp_die(); // this is required to terminate immediately and return a proper response
}
add_action( 'admin_menu', 'rclone_concept_add_admin_menu' );
function rclone_concept_add_admin_menu() {
add_options_page( 'Rclone Concept', 'Rclone Concept', 'manage_options', 'rclone_concept', 'rclone_concept_options_page' );
}
function rclone_concept_options_page() { ?>
<script src="https://unpkg.com/qs@6.5.2/dist/qs.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.2.23/dist/vuetify.css" rel="stylesheet">
<style>
/* WordPress Admin Vuetify Reset */
input[type="color"], input[type="date"], input[type="datetime-local"], input[type="datetime"], input[type="email"], input[type="month"], input[type="number"], input[type="password"], input[type="search"], input[type="tel"], input[type="text"], input[type="time"], input[type="url"], input[type="week"], select, textarea {
border: 0px;
background-color: transparent;
}
input[type="checkbox"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime-local"]:focus, input[type="datetime"]:focus, input[type="email"]:focus, input[type="month"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="radio"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="time"]:focus, input[type="url"]:focus, input[type="week"]:focus, select:focus, textarea:focus {
box-shadow: none;
}
input.readonly, input[readonly], textarea.readonly, textarea[readonly] {
background-color: transparent;
}
.v-textarea textarea {
font-size:13px;
line-height:1.1em;
font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;'
}
</style>
<h2>Rclone Concept</h2>
<div id="app">
<v-app style="background:transparent;">
<v-content class="mr-6">
<v-row>
<v-col cols="12" md="6">
<v-text-field label="Rclone Subcommand" v-model="command"></v-text-field>
</v-col>
<v-col cols="12" md="3">
<v-text-field label="SSH Username" v-model="username" type="password"></v-text-field>
</v-col>
<v-col cols="12" md="3">
<v-text-field label="SSH Password" v-model="password" type="password"></v-text-field>
</v-col>
</v-row>
<v-btn color="primary" @click="runCommand()">Run Command</v-btn>
<v-textarea label="Response" auto-grow solo readonly v-model="response" class="mt-5"></v-textarea>
</v-content>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.2.23/dist/vuetify.js"></script>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
username: "",
password: "",
command: "",
response: ""
},
methods: {
runCommand() {
// Prep AJAX request
var data = {
'action': 'rclone_concept_ajax',
'command': "toggle-rclone-remote",
'value': {
'command': this.command,
'username': this.username,
'password': this.password,
}
}
// update server
axios.post( '/wp-admin/admin-ajax.php', Qs.stringify( data ) )
.then( response => {
this.command = ""
this.response = response.data
})
.catch(error => {
console.log(error.response)
});
}
}
})
</script>
<?php
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment