Incorrect Resource Transfer Between Spheres
Description
Incorrect Resource Transfer Between Spheres occurs when a product transfers a resource to another sphere in a way that violates the intended security boundaries. This includes transferring sensitive data to untrusted contexts, importing malicious content into trusted contexts, or crossing trust boundaries without proper validation. Examples include passing user input to system commands, deserializing untrusted data, and embedding user content in privileged contexts.
Risk
Untrusted data executed in privileged context. Sensitive information leaked to unauthorized spheres. Malicious code imported through deserialization. Cross-domain data theft via improper transfers. Command injection from user input in system calls. SQL injection from untrusted data in queries.
Solution
Validate and sanitize data crossing trust boundaries. Use safe APIs that don't mix data and control. Implement proper encoding when transferring data. Avoid deserializing untrusted data. Use parameterized interfaces. Apply principle of least privilege to transferred resources.
Common Consequences
| Impact | Details |
|---|---|
| Integrity | Scope: Code Execution Malicious data executed in trusted context. |
| Confidentiality | Scope: Information Disclosure Sensitive data transferred to untrusted sphere. |
| Authorization | Scope: Privilege Escalation User-controlled data gains privileged access. |
Example Code + Solution Code
Vulnerable Code
// VULNERABLE: Incorrect resource transfer between spheres
import java.io.*;
// VULNERABLE: User input transferred to command execution sphere
public class VulnerableTransfer {
public void executeCommand(String userInput) {
// VULNERABLE: User data transferred to OS command sphere
Runtime.getRuntime().exec("ls " + userInput);
}
// VULNERABLE: Deserializing untrusted data
public Object deserializeFromNetwork(InputStream networkInput) throws Exception {
ObjectInputStream ois = new ObjectInputStream(networkInput);
// VULNERABLE: Untrusted data transferred to object sphere
return ois.readObject(); // Remote code execution possible
}
// VULNERABLE: User input transferred to SQL sphere
public void queryDatabase(String userInput, Connection conn) throws SQLException {
Statement stmt = conn.createStatement();
// VULNERABLE: User data mixed with SQL commands
stmt.executeQuery("SELECT * FROM users WHERE name = '" + userInput + "'");
}
// VULNERABLE: User data transferred to logging sphere
public void logUserAction(String username) {
// VULNERABLE: CRLF injection possible - user data in log
logger.info("User logged in: " + username);
// Could inject fake log entries
}
// VULNERABLE: Sensitive data transferred to client sphere
public void sendResponse(HttpServletResponse response, User user) throws IOException {
// VULNERABLE: Internal data transferred to client
response.getWriter().write(user.toJson()); // Includes password hash!
}
}
// VULNERABLE: File path transfer from untrusted source
public class VulnerableFileTransfer {
public void copyUserFile(String userFilePath, String destination) throws IOException {
// VULNERABLE: User-controlled path transferred to file system sphere
Files.copy(Paths.get(userFilePath), Paths.get(destination));
// Path traversal: "../../../etc/passwd"
}
}
# VULNERABLE: Python incorrect resource transfers
import pickle
import subprocess
import os
# VULNERABLE: User input to subprocess sphere
def process_file_vulnerable(filename):
# VULNERABLE: User data transferred to shell
os.system(f"cat {filename}") # Command injection
# VULNERABLE: Pickle deserialization of untrusted data
def load_data_vulnerable(network_data):
# VULNERABLE: Network data transferred to object sphere
return pickle.loads(network_data) # Remote code execution
# VULNERABLE: User input transferred to eval sphere
def calculate_vulnerable(expression):
# VULNERABLE: User math transferred to code execution
return eval(expression) # Any Python code executed
# VULNERABLE: Sensitive data transferred to template sphere
from jinja2 import Template
def render_vulnerable(user_content):
# VULNERABLE: User content transferred to template execution sphere
template = Template(user_content)
return template.render() # SSTI - server-side template injection
# VULNERABLE: Database credentials transferred to error message
def connect_vulnerable():
try:
db = connect(f"postgresql://admin:secret@localhost/mydb")
except Exception as e:
# VULNERABLE: Sensitive data transferred to error sphere
raise Exception(f"Connection failed: {e}") # Exposes credentials
# VULNERABLE: User data transferred to file path sphere
def read_file_vulnerable(user_path):
# VULNERABLE: User path directly used
with open(f"/var/data/{user_path}", 'r') as f:
return f.read() # Path traversal possible
// VULNERABLE: JavaScript incorrect resource transfers
const { exec } = require('child_process');
// VULNERABLE: User input transferred to shell sphere
function runCommand(userInput) {
// VULNERABLE: User data mixed with command
exec(`grep ${userInput} /var/log/app.log`, (err, stdout) => {
console.log(stdout);
});
}
// VULNERABLE: User input transferred to eval sphere
function calculate(expression) {
// VULNERABLE: User math executed as code
return eval(expression);
}
// VULNERABLE: Untrusted HTML transferred to DOM sphere
function displayMessage(userContent) {
// VULNERABLE: User content transferred to DOM (XSS)
document.getElementById('message').innerHTML = userContent;
}
// VULNERABLE: Sensitive data transferred to client sphere
app.get('/api/user/:id', (req, res) => {
const user = getUser(req.params.id);
// VULNERABLE: Internal user object sent to client
res.json(user); // Includes passwordHash, internalNotes, etc.
});
// VULNERABLE: User data transferred to database query sphere
app.get('/api/search', (req, res) => {
const query = req.query.q;
// VULNERABLE: User input in MongoDB query
db.collection('users').find({ $where: `this.name == '${query}'` });
// NoSQL injection
});
// VULNERABLE: User path transferred to file system sphere
app.get('/files/:filename', (req, res) => {
const filename = req.params.filename;
// VULNERABLE: User path used directly
res.sendFile(`/var/uploads/${filename}`);
});
// VULNERABLE: Cross-origin data transfer
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
// VULNERABLE: Any origin can access sensitive data
next();
});
// VULNERABLE: C incorrect resource transfers
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// VULNERABLE: User input transferred to system command sphere
void process_input_vulnerable(const char* user_input) {
char command[256];
// VULNERABLE: User data mixed with command
sprintf(command, "echo %s", user_input);
system(command); // Command injection
}
// VULNERABLE: Network data transferred to format string sphere
void log_message_vulnerable(const char* network_data) {
// VULNERABLE: Network data used as format string
printf(network_data); // Format string vulnerability
}
// VULNERABLE: User buffer transferred to fixed buffer
void copy_data_vulnerable(const char* user_data) {
char buffer[64];
// VULNERABLE: Unbounded copy from user sphere
strcpy(buffer, user_data); // Buffer overflow
}
// VULNERABLE: Network data transferred to memory operations
void process_packet_vulnerable(const char* packet, int user_length) {
char buffer[1024];
// VULNERABLE: User-controlled length in memory operation
memcpy(buffer, packet, user_length); // Overflow if length > 1024
}
// VULNERABLE: User index transferred to array access sphere
int get_item_vulnerable(int* array, int user_index) {
// VULNERABLE: User index used directly
return array[user_index]; // Out-of-bounds access
}
Fixed Code
// SAFE: Proper resource transfer between spheres
import java.io.*;
import java.util.*;
public class SafeTransfer {
// SAFE: Don't transfer user input to command sphere directly
public void executeCommand(String userInput) {
// Option 1: Whitelist allowed commands
String[] allowed = {"list", "status", "help"};
if (Arrays.asList(allowed).contains(userInput)) {
ProcessBuilder pb = new ProcessBuilder("myapp", userInput);
pb.start();
}
// Option 2: Use ProcessBuilder with arguments
ProcessBuilder pb = new ProcessBuilder("ls", "-la");
pb.directory(new File("/safe/directory"));
pb.start();
}
// SAFE: Use safe deserialization
public Object deserializeFromNetwork(InputStream networkInput) {
// Option 1: Use JSON/XML with schema validation
ObjectMapper mapper = new ObjectMapper();
// Enable safe defaults
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
return mapper.readValue(networkInput, SafeDTO.class);
// Option 2: If Java serialization required, use filter
// ObjectInputFilter filter = ...
// ois.setObjectInputFilter(filter);
}
// SAFE: Parameterized query
public void queryDatabase(String userInput, Connection conn) throws SQLException {
// SAFE: Parameters never transferred to SQL sphere
PreparedStatement stmt = conn.prepareStatement(
"SELECT * FROM users WHERE name = ?");
stmt.setString(1, userInput);
stmt.executeQuery();
}
// SAFE: Sanitize before logging
public void logUserAction(String username) {
// SAFE: Remove control characters before transfer to log sphere
String sanitized = username.replaceAll("[\\r\\n]", "_");
logger.info("User logged in: {}", sanitized); // Parameterized logging
}
// SAFE: Filter before transferring to client sphere
public void sendResponse(HttpServletResponse response, User user) throws IOException {
// SAFE: Create DTO with only public fields
UserDTO dto = new UserDTO(user.getId(), user.getUsername(), user.getEmail());
// No password hash, no internal data
response.getWriter().write(objectMapper.writeValueAsString(dto));
}
}
// SAFE: Validate before file operations
public class SafeFileTransfer {
private static final Path SAFE_BASE = Paths.get("/var/uploads").toRealPath();
public void copyUserFile(String userFilePath, String destination) throws IOException {
// SAFE: Validate path doesn't escape base directory
Path sourcePath = SAFE_BASE.resolve(userFilePath).normalize();
Path destPath = SAFE_BASE.resolve(destination).normalize();
if (!sourcePath.startsWith(SAFE_BASE) || !destPath.startsWith(SAFE_BASE)) {
throw new SecurityException("Path traversal attempted");
}
Files.copy(sourcePath, destPath);
}
}
# SAFE: Python proper resource transfers
import subprocess
import json
import os
from pathlib import Path
# SAFE: Use list arguments, not shell string
def process_file_safe(filename):
# SAFE: Arguments separated, not transferred to shell
allowed_chars = set('abcdefghijklmnopqrstuvwxyz0123456789._-')
if not all(c in allowed_chars for c in filename.lower()):
raise ValueError("Invalid filename")
# Use list form - no shell interpolation
result = subprocess.run(['cat', filename], capture_output=True, text=True)
return result.stdout
# SAFE: Use JSON instead of pickle
def load_data_safe(network_data):
# SAFE: JSON can't execute code
return json.loads(network_data)
# SAFE: Use safe expression evaluation
import ast
import operator
SAFE_OPERATORS = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
}
def calculate_safe(expression):
# SAFE: Parse and evaluate only math operations
tree = ast.parse(expression, mode='eval')
def eval_node(node):
if isinstance(node, ast.Num):
return node.n
elif isinstance(node, ast.BinOp):
op = SAFE_OPERATORS.get(type(node.op))
if not op:
raise ValueError("Unsupported operation")
return op(eval_node(node.left), eval_node(node.right))
else:
raise ValueError("Unsupported expression")
return eval_node(tree.body)
# SAFE: Use autoescape for templates
from jinja2 import Environment, select_autoescape
env = Environment(autoescape=select_autoescape())
def render_safe(template_name, **context):
# SAFE: Load predefined template, escape user data
template = env.get_template(template_name)
return template.render(**context)
# SAFE: Don't expose sensitive data in errors
def connect_safe(connection_string):
try:
return connect(connection_string)
except Exception as e:
# SAFE: Generic error, no sensitive data
raise Exception("Database connection failed") from None
# SAFE: Validate file paths
UPLOAD_DIR = Path('/var/data').resolve()
def read_file_safe(user_path):
# SAFE: Validate path stays within allowed directory
full_path = (UPLOAD_DIR / user_path).resolve()
if not str(full_path).startswith(str(UPLOAD_DIR)):
raise ValueError("Invalid path")
with open(full_path, 'r') as f:
return f.read()
// SAFE: JavaScript proper resource transfers
const { spawn } = require('child_process');
const path = require('path');
// SAFE: Use spawn with array arguments
function runCommand(userInput) {
// Whitelist allowed search terms
const sanitized = userInput.replace(/[^a-zA-Z0-9]/g, '');
// SAFE: Use spawn with arguments as array
const grep = spawn('grep', [sanitized, '/var/log/app.log']);
grep.stdout.on('data', (data) => {
console.log(data.toString());
});
}
// SAFE: Use safe expression parser
const mathjs = require('mathjs');
function calculate(expression) {
// SAFE: mathjs doesn't execute arbitrary code
return mathjs.evaluate(expression);
}
// SAFE: Use textContent or sanitization
function displayMessage(userContent) {
// SAFE: textContent doesn't execute HTML/JS
document.getElementById('message').textContent = userContent;
// Or use DOMPurify for HTML
const clean = DOMPurify.sanitize(userContent);
document.getElementById('message').innerHTML = clean;
}
// SAFE: Transfer only needed fields to client
app.get('/api/user/:id', (req, res) => {
const user = getUser(req.params.id);
// SAFE: Only transfer public fields
res.json({
id: user.id,
username: user.username,
email: user.email
// No passwordHash, no internalNotes
});
});
// SAFE: Parameterized MongoDB query
app.get('/api/search', (req, res) => {
const query = req.query.q;
// SAFE: User input as data, not code
db.collection('users').find({ name: query });
});
// SAFE: Validate file path
const UPLOAD_DIR = path.resolve('/var/uploads');
app.get('/files/:filename', (req, res) => {
const filename = req.params.filename;
const fullPath = path.resolve(UPLOAD_DIR, filename);
// SAFE: Verify path is within allowed directory
if (!fullPath.startsWith(UPLOAD_DIR)) {
return res.status(403).send('Forbidden');
}
res.sendFile(fullPath);
});
// SAFE: Restrictive CORS
const corsOptions = {
origin: ['https://myapp.com'],
methods: ['GET', 'POST'],
credentials: true
};
app.use(cors(corsOptions));
// SAFE: C proper resource transfers
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// SAFE: Don't transfer user input to system()
void process_input_safe(const char* user_input) {
// Option 1: Whitelist
const char* allowed[] = {"list", "status", NULL};
int valid = 0;
for (int i = 0; allowed[i]; i++) {
if (strcmp(user_input, allowed[i]) == 0) {
valid = 1;
break;
}
}
// Option 2: Use execve with arguments
if (valid) {
pid_t pid = fork();
if (pid == 0) {
char* args[] = {"myapp", (char*)user_input, NULL};
execve("/usr/bin/myapp", args, NULL);
exit(1);
}
}
}
// SAFE: Don't use network data as format string
void log_message_safe(const char* network_data) {
// SAFE: Data is argument, not format
printf("%s", network_data);
}
// SAFE: Bounded copy
void copy_data_safe(const char* user_data, size_t user_len) {
char buffer[64];
// SAFE: Limit size
size_t copy_len = user_len < sizeof(buffer) - 1 ? user_len : sizeof(buffer) - 1;
memcpy(buffer, user_data, copy_len);
buffer[copy_len] = '\0';
}
// SAFE: Validate before memory operation
void process_packet_safe(const char* packet, int user_length) {
char buffer[1024];
// SAFE: Validate length before transfer
if (user_length > 0 && user_length <= sizeof(buffer)) {
memcpy(buffer, packet, user_length);
}
}
// SAFE: Bounds check before array access
int get_item_safe(int* array, size_t array_size, int user_index) {
// SAFE: Validate index before transfer to array access
if (user_index >= 0 && (size_t)user_index < array_size) {
return array[user_index];
}
return -1; // Error value
}
Exploited in the Wild
Deserialization Attacks
Java/Python pickle RCE via untrusted deserialization.
Command Injection
User input transferred to shell causing system compromise.
SQL/NoSQL Injection
User data improperly transferred to database queries.
Tools to test/exploit
-
Burp Suite for injection testing.
-
ysoserial for Java deserialization.
-
SQLMap for database injection.
CVE Examples
-
CVE-2015-4852: Java deserialization (WebLogic).
-
CVE-2017-5638: Struts2 OGNL injection.
References
-
MITRE. "CWE-669: Incorrect Resource Transfer Between Spheres." https://cwe.mitre.org/data/definitions/669.html
-
OWASP Injection Prevention.