diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a318744
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+# Gradle
+.gradle
+gradle**
+# Eclipse, Idea, ...
+.settings
+.idea
+bin
+build
+doc
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..826fb36
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,16 @@
+# Changelog
+
+All notable changes to this project will are documented in this changelog file.
+
+## [1.0.0] - 2022-01-01
+### Added
+- common functionality
+- server and client implementation
+- 7 basic challenges
+ - Buffer Over-read (simulated)
+ - Command Execution
+ - SQL Injection
+ - Enumeration
+ - XML
+ - Horizontal Access Control
+ - Vertical Access Control
\ No newline at end of file
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..2fb2e74
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,675 @@
+### GNU GENERAL PUBLIC LICENSE
+
+Version 3, 29 June 2007
+
+Copyright (C) 2007 Free Software Foundation, Inc.
+
+
+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.
+
+
+ Copyright (C)
+
+ 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 .
+
+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:
+
+ Copyright (C)
+ 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 .
+
+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 .
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..534721c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,41 @@
+# ![Vulnerable Client-Server Application (VuCSA)](http://vucsa.warxim.com/img/logo.png)
+# Vulnerable Client-Server Application (VuCSA)
+Vulnerable client-server application (VuCSA) is made for learning/presenting how to perform penetration tests of non-http thick clients.
+It is written in Java (with JavaFX graphical user interface).
+
+Currently the vulnerable application contains the following challenges:
+1. Buffer Over-read (simulated)
+2. Command Execution
+3. SQL Injection
+4. Enumeration
+5. XML
+6. Horizontal Access Control
+7. Vertical Access Control
+
+If you want to know how to solve these challenges, take a look at the [PETEP website](http://petep.warxim.com/methodology/),
+which describes how to use the open-source tool PETEP to exploit them.
+
+**Tip:** Before you start hacking, do not forget to check the data structure of messages bellow.
+
+## How to Run
+In order to run the vulnerable server and client, you can use one of releases on GitHub
+or run gradle assemble, which creates distribution packages (for both Windows and Unix).
+These packages contain sh/bat scripts that will run the server and client using JVM.
+
+## Project Structure
+Project is divided into three modules:
+- **vulnerable-common** - common functionality for both client and server (including protocol processing utilities)
+- **vulnerable-client** - vulnerable client with JavaFX GUI
+- **vulnerable-server** - vulnerable server for terminal use
+
+## Data Structure
+Messages transmitted between server and client have the following simple format:
+
+ [type][target][length][payload]
+ 32b 32b 32b ???
+
+These four parts have the following meaning:
+- **type** - type of the message (used for serialization/deserialization)
+- **target** - target handler that will receive the message
+- **length** - length of the payload
+- **payload** - data serialized into bytes
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..b7e2185
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,42 @@
+plugins {
+ id 'java'
+ id 'application'
+}
+
+group 'com.warxim'
+version '1.0'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ compile project(":vucsa-common")
+ compile project(":vucsa-client")
+ compile project(":vucsa-server")
+}
+
+distributions {
+ main {
+ distributionBaseName = "vucsa"
+ contents {
+ from("LICENSE.md") {
+ into ""
+ }
+
+ from("CHANGELOG.md") {
+ into ""
+ }
+
+ from("scripts") {
+ into ""
+ }
+
+ from("vucsa-server/server") {
+ into "server"
+ }
+
+ startScripts.onlyIf {false}
+ }
+ }
+}
\ No newline at end of file
diff --git a/scripts/client.bat b/scripts/client.bat
new file mode 100644
index 0000000..760cf3d
--- /dev/null
+++ b/scripts/client.bat
@@ -0,0 +1,12 @@
+@echo off
+set JAVA_EXE=java.exe
+set JAVAW_EXE=javaw.exe
+set DIRNAME=%~dp0
+set APP_HOME=%DIRNAME%
+set CMD_LINE_ARGS=%*
+set DEFAULT_JVM_OPTS=
+set CLASSPATH=%APP_HOME%\lib\*
+set MAIN_CLASS="com.warxim.vucsa.client.Main"
+
+rem Start Vulnerable Client with GUI (without console).
+start "" /b "%JAVAW_EXE%" %DEFAULT_JVM_OPTS% -classpath "%CLASSPATH%" %MAIN_CLASS% %CMD_LINE_ARGS%
diff --git a/scripts/client.sh b/scripts/client.sh
new file mode 100644
index 0000000..0a1bac4
--- /dev/null
+++ b/scripts/client.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+JAVA="java"
+APP_HOME="`pwd`"
+DEFAULT_JVM_OPTS=
+CMD_LINE_ARGS=$@
+CLASSPATH=$APP_HOME/lib/*
+MAIN_CLASS="com.warxim.vucsa.client.Main"
+LOG_FILE=client.log
+
+nohup $JAVA -cp "$CLASSPATH" $MAIN_CLASS $CMD_LINE_ARGS > $LOG_FILE &
diff --git a/scripts/server.bat b/scripts/server.bat
new file mode 100644
index 0000000..5a4ee28
--- /dev/null
+++ b/scripts/server.bat
@@ -0,0 +1,12 @@
+@echo off
+set JAVA_EXE=java.exe
+set JAVAW_EXE=javaw.exe
+set DIRNAME=%~dp0
+set APP_HOME=%DIRNAME%
+set CMD_LINE_ARGS=%*
+set DEFAULT_JVM_OPTS=
+set CLASSPATH=%APP_HOME%\lib\*
+set MAIN_CLASS="com.warxim.vucsa.server.Main"
+
+rem Start Vulnerable Server without GUI (let console open).
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% -classpath "%CLASSPATH%" %MAIN_CLASS% %CMD_LINE_ARGS%
diff --git a/scripts/server.sh b/scripts/server.sh
new file mode 100644
index 0000000..1117140
--- /dev/null
+++ b/scripts/server.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+JAVA="java"
+APP_HOME="`pwd`"
+DEFAULT_JVM_OPTS=
+CMD_LINE_ARGS=$@
+CLASSPATH=$APP_HOME/lib/*
+MAIN_CLASS="com.warxim.vucsa.server.Main"
+LOG_FILE=server.log
+
+$JAVA -cp "$CLASSPATH" $MAIN_CLASS $CMD_LINE_ARGS
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..a180b54
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,6 @@
+rootProject.name = 'VuCSA'
+
+include 'vucsa-common'
+include 'vucsa-client'
+include 'vucsa-server'
+
diff --git a/vucsa-client/build.gradle b/vucsa-client/build.gradle
new file mode 100644
index 0000000..8c29067
--- /dev/null
+++ b/vucsa-client/build.gradle
@@ -0,0 +1,59 @@
+plugins {
+ id 'java-library'
+ id 'java'
+ id 'eclipse'
+ id 'application'
+ id 'org.openjfx.javafxplugin' version '0.0.13'
+}
+
+javafx {
+ version = "11.0.2"
+ modules = ['javafx.controls', 'javafx.fxml', 'javafx.web']
+}
+
+group 'com.warxim'
+version '1.0'
+mainClassName = 'com.warxim.vucsa.client.Main'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation project(':vucsa-common')
+
+ compileOnly 'org.projectlombok:lombok:1.18.24'
+ annotationProcessor 'org.projectlombok:lombok:1.18.24'
+
+ implementation group: 'org.openjfx', name: 'javafx-base', version: javafx.version, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-base', version: javafx.version, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-base', version: javafx.version, classifier: 'linux'
+ implementation group: 'org.openjfx', name: 'javafx-controls', version: javafx.version, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-controls', version: javafx.version, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-controls', version: javafx.version, classifier: 'linux'
+ implementation group: 'org.openjfx', name: 'javafx-fxml', version: javafx.version, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-fxml', version: javafx.version, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-fxml', version: javafx.version, classifier: 'linux'
+ implementation group: 'org.openjfx', name: 'javafx-graphics', version: javafx.version, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-graphics', version: javafx.version, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-graphics', version: javafx.version, classifier: 'linux'
+ implementation group: 'org.openjfx', name: 'javafx-media', version: javafx.version, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-media', version: javafx.version, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-media', version: javafx.version, classifier: 'linux'
+ implementation group: 'org.openjfx', name: 'javafx-web', version: javafx.version, classifier: 'win'
+ implementation group: 'org.openjfx', name: 'javafx-web', version: javafx.version, classifier: 'mac'
+ implementation group: 'org.openjfx', name: 'javafx-web', version: javafx.version, classifier: 'linux'
+}
+
+// Export com.sun.javafx.css (for css editing)
+application {
+ applicationDefaultJvmArgs = [
+ "--add-opens=javafx.graphics/com.sun.javafx.css=ALL-UNNAMED"
+ ]
+ executableDir = ''
+}
+
+// Set run working directory to build/run
+File runningDir = new File('build/run')
+runningDir.mkdirs()
+tasks.run.workingDir = runningDir
\ No newline at end of file
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/Bundle.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/Bundle.java
new file mode 100644
index 0000000..31c234b
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/Bundle.java
@@ -0,0 +1,63 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client;
+
+import com.warxim.vucsa.client.core.ClientManager;
+import lombok.Getter;
+
+/**
+ * Singleton for client assets.
+ */
+@Getter
+public final class Bundle {
+ /**
+ * Singleton instance.
+ */
+ private static volatile Bundle instance;
+
+ /**
+ * Client manager
+ */
+ private final ClientManager clientManager;
+
+ private Bundle() {
+ clientManager = new ClientManager();
+ }
+
+ /**
+ * Creates instance of bundle or returns existing instance if it exists.
+ * @return Bundle instance
+ */
+ public static Bundle getInstance() {
+ if (instance == null) {
+ synchronized(Bundle.class) {
+ if (instance == null) {
+ instance = new Bundle();
+ }
+ }
+ }
+
+ return instance;
+ }
+
+ /**
+ * Destroys the bundle.
+ */
+ public void destroy() {
+ // nothing to destroy
+ }
+}
\ No newline at end of file
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/Main.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/Main.java
new file mode 100644
index 0000000..67f9593
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/Main.java
@@ -0,0 +1,49 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client;
+
+import com.warxim.vucsa.client.gui.GuiApplication;
+import com.warxim.vucsa.client.gui.GuiBundle;
+import com.warxim.vucsa.client.gui.dialog.Dialogs;
+import javafx.application.Application;
+
+/**
+ * Main client application class.
+ */
+public final class Main {
+ public static void main(String... args) {
+ init();
+ launch();
+ }
+
+ /**
+ * Initializes GUI bundle.
+ */
+ private static void init() {
+ var guiBundle = GuiBundle.getInstance();
+ Dialogs.setDefaultIcon(guiBundle.getLogo());
+ }
+
+ /**
+ * Launches GUI application.
+ */
+ private static void launch() {
+ Application.launch(GuiApplication.class);
+ }
+
+ private Main() {}
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/ChallengeController.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/ChallengeController.java
new file mode 100644
index 0000000..aacbb9c
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/ChallengeController.java
@@ -0,0 +1,35 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge;
+
+import com.warxim.vucsa.client.Bundle;
+import com.warxim.vucsa.common.message.Message;
+
+/**
+ * Base class of challenge controllers.
+ */
+public abstract class ChallengeController {
+ /**
+ * Sends message using client manager.
+ * @param message Message to be sent
+ * @return {@code true} if the message has been successfully sent
+ */
+ protected boolean sendMessage(Message message) {
+ var clientManager = Bundle.getInstance().getClientManager();
+ return clientManager.sendMessage(message);
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/ChallengeWrapper.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/ChallengeWrapper.java
new file mode 100644
index 0000000..0ef3c69
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/ChallengeWrapper.java
@@ -0,0 +1,39 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge;
+
+import com.warxim.vucsa.common.connection.listener.ConnectionListener;
+import javafx.scene.Node;
+import lombok.Builder;
+import lombok.Value;
+
+/**
+ * Wrapper for keeping JavaFX node and controller of a challenge.
+ */
+@Value
+@Builder
+public class ChallengeWrapper implements ConnectionListener {
+ /**
+ * Challenge node, which is displayed in the tab.
+ */
+ Node node;
+
+ /**
+ * Controller for controlling the challenge GUI.
+ */
+ ChallengeController controller;
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/bufferoverread/BufferOverreadController.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/bufferoverread/BufferOverreadController.java
new file mode 100644
index 0000000..5696e7e
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/bufferoverread/BufferOverreadController.java
@@ -0,0 +1,131 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.bufferoverread;
+
+import com.warxim.vucsa.client.Bundle;
+import com.warxim.vucsa.client.challenge.ChallengeController;
+import com.warxim.vucsa.client.gui.dialog.Dialogs;
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.message.bufferoverread.StringListMessage;
+import javafx.application.Platform;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.ContextMenu;
+import javafx.scene.control.ListView;
+import javafx.scene.control.MenuItem;
+
+import java.net.URL;
+import java.util.List;
+import java.util.ResourceBundle;
+
+/**
+ * Buffer over-read controller handles buffer over-read challenge, which uses simple echo with transformation of input
+ * to simulate buffer over-read vulnerability.
+ */
+public class BufferOverreadController extends ChallengeController implements Initializable {
+ private final BufferOverreadHandler handler = new BufferOverreadHandler(this);
+
+ @FXML
+ private ListView requestInput;
+ @FXML
+ private ListView responseInput;
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ initHandler();
+ initDefaultItems();
+ initContextMenu();
+ }
+
+ /**
+ * Sets items to the input component.
+ * @param items Items to be set
+ */
+ public void setItems(List items) {
+ Platform.runLater(() -> responseInput.getItems().setAll(items));
+ }
+
+ /**
+ * Sends items to server.
+ */
+ @FXML
+ private void onSendClick(ActionEvent event) {
+ var items = requestInput.getItems();
+ var message = StringListMessage.builder()
+ .target(ChallengeConstant.BUFFER_OVERREAD_TARGET)
+ .items(items)
+ .build();
+ sendMessage(message);
+ }
+
+ /**
+ * Adds new item.
+ */
+ @FXML
+ private void onAddItemClick(ActionEvent event) {
+ var maybeValue = Dialogs.createTextInputDialog("Add Item", "Value");
+ if (maybeValue.isEmpty()) {
+ return;
+ }
+ requestInput.getItems().add(maybeValue.get());
+ }
+
+ /**
+ * Removes existing item.
+ */
+ @FXML
+ private void onRemoveItemClick(ActionEvent event) {
+ var selected = requestInput.getSelectionModel().getSelectedIndex();
+ if (selected < 0) {
+ return;
+ }
+
+ requestInput.getItems().remove(selected);
+ }
+
+ /**
+ * Initializes buffer over-read message handler.
+ */
+ private void initHandler() {
+ Bundle.getInstance().getClientManager().registerHandler(ChallengeConstant.BUFFER_OVERREAD_TARGET, handler);
+ }
+
+ /**
+ * Initializes default items in the challenge GUI.
+ */
+ private void initDefaultItems() {
+ requestInput.getItems().add("Item 1");
+ requestInput.getItems().add("Item 2");
+ requestInput.getItems().add("Item 3");
+ }
+
+ /**
+ * Initializes context menu of request input.
+ */
+ private void initContextMenu() {
+ var menu = new ContextMenu();
+ var addItem = new MenuItem("Add");
+ addItem.setOnAction(this::onAddItemClick);
+ var removeItem = new MenuItem("Remove");
+ removeItem.setOnAction(this::onRemoveItemClick);
+
+ menu.getItems().add(addItem);
+ menu.getItems().add(removeItem);
+ requestInput.setContextMenu(menu);
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/bufferoverread/BufferOverreadHandler.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/bufferoverread/BufferOverreadHandler.java
new file mode 100644
index 0000000..96e523d
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/bufferoverread/BufferOverreadHandler.java
@@ -0,0 +1,42 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.bufferoverread;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.bufferoverread.StringListMessage;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Handler for handling messages for buffer over-read challenge.
+ */
+@RequiredArgsConstructor
+public class BufferOverreadHandler implements MessageHandler {
+ private final BufferOverreadController controller;
+
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof StringListMessage;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ controller.setItems(((StringListMessage) message).getItems());
+ return true;
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/commandexecution/CommandExecutionController.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/commandexecution/CommandExecutionController.java
new file mode 100644
index 0000000..3abc517
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/commandexecution/CommandExecutionController.java
@@ -0,0 +1,89 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.commandexecution;
+
+import com.warxim.vucsa.client.Bundle;
+import com.warxim.vucsa.client.challenge.ChallengeController;
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.message.commandexecution.request.PingRequest;
+import javafx.application.Platform;
+import javafx.beans.value.ObservableValue;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.TextArea;
+import javafx.scene.control.TextField;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+
+/**
+ * Command execution controller handles command execution challenge.
+ *
Requests server to do PING command and shows output.
+ */
+public class CommandExecutionController extends ChallengeController implements Initializable {
+ private final CommandExecutionHandler handler = new CommandExecutionHandler(this);
+
+ @FXML
+ private TextField hostInput;
+ @FXML
+ private TextArea resultOutput;
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ initHandler();
+ hostInput.textProperty().addListener(this::onHostInputChange);
+ }
+ /**
+ * Sets output to the text area.
+ * @param output Output to be set
+ */
+ public void setOutput(String output) {
+ Platform.runLater(() -> resultOutput.setText(output));
+ }
+
+ /**
+ * Sends ping request to server.
+ */
+ @FXML
+ private void onPingClick(ActionEvent event) {
+ var message = PingRequest.builder()
+ .target(ChallengeConstant.COMMAND_EXECUTION_TARGET)
+ .host(hostInput.getText())
+ .build();
+ sendMessage(message);
+ }
+
+ /**
+ * Initializes command execution message handler.
+ */
+ private void initHandler() {
+ Bundle.getInstance().getClientManager().registerHandler(ChallengeConstant.COMMAND_EXECUTION_TARGET, handler);
+ }
+
+ /**
+ * Removes invalid characters from host input on change.
+ */
+ private void onHostInputChange(
+ ObservableValue extends String> observable,
+ String oldValue,
+ String newValue) {
+ if (!newValue.matches("0-9a-zA-Z\\.-")) {
+ hostInput.setText(newValue.replaceAll("[^0-9a-zA-Z.-]", ""));
+ }
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/commandexecution/CommandExecutionHandler.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/commandexecution/CommandExecutionHandler.java
new file mode 100644
index 0000000..260a0d2
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/commandexecution/CommandExecutionHandler.java
@@ -0,0 +1,39 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.commandexecution;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.commandexecution.response.PingResponse;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class CommandExecutionHandler implements MessageHandler {
+ private final CommandExecutionController controller;
+
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof PingResponse;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ controller.setOutput(((PingResponse) message).getOutput());
+ return true;
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/enumeration/EnumerationController.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/enumeration/EnumerationController.java
new file mode 100644
index 0000000..7a963df
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/enumeration/EnumerationController.java
@@ -0,0 +1,94 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.enumeration;
+
+import com.warxim.vucsa.client.Bundle;
+import com.warxim.vucsa.client.challenge.ChallengeController;
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.message.enumeration.LoginStatus;
+import com.warxim.vucsa.common.message.enumeration.request.LoginRequest;
+import javafx.application.Platform;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.Label;
+import javafx.scene.control.PasswordField;
+import javafx.scene.control.TextField;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+
+/**
+ * Enumeration controller handles enumeration challenge.
+ *
Simulates user login and displays result.
+ */
+public class EnumerationController extends ChallengeController implements Initializable {
+ private final EnumerationHandler handler = new EnumerationHandler(this);
+
+ @FXML
+ private TextField usernameInput;
+ @FXML
+ private PasswordField passwordInput;
+ @FXML
+ private Label resultLabel;
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ initHandler();
+ }
+
+ /**
+ * Sets login result to the GUI.
+ * @param status Login status
+ * @param userSecret Secret of logged user
+ */
+ public void setResult(LoginStatus status, String userSecret) {
+ Platform.runLater(() -> {
+ switch (status) {
+ case SUCCESS:
+ resultLabel.setText("Successfully logged in! Your secret is: \"" + userSecret + "\"");
+ break;
+ case WRONG_USERNAME:
+ resultLabel.setText("Wrong username!");
+ break;
+ case WRONG_PASSWORD:
+ resultLabel.setText("Wrong password!");
+ break;
+ }
+ });
+ }
+
+ /**
+ * Sends login request to the server.
+ */
+ @FXML
+ private void onLoginClick(ActionEvent event) {
+ var message = LoginRequest.builder()
+ .target(ChallengeConstant.ENUMERATION_TARGET)
+ .username(usernameInput.getText())
+ .password(passwordInput.getText())
+ .build();
+ sendMessage(message);
+ }
+
+ /**
+ * Initializes enumeration message handler.
+ */
+ private void initHandler() {
+ Bundle.getInstance().getClientManager().registerHandler(ChallengeConstant.ENUMERATION_TARGET, handler);
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/enumeration/EnumerationHandler.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/enumeration/EnumerationHandler.java
new file mode 100644
index 0000000..fc4a0d0
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/enumeration/EnumerationHandler.java
@@ -0,0 +1,43 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.enumeration;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.enumeration.response.LoginResponse;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Handler for login response messages for enumeration challenge.
+ */
+@RequiredArgsConstructor
+public class EnumerationHandler implements MessageHandler {
+ private final EnumerationController controller;
+
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof LoginResponse;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ var loginResponse = ((LoginResponse) message);
+ controller.setResult(loginResponse.getStatus(), loginResponse.getUserSecret());
+ return true;
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/horizontalaccesscontrol/DocumentItem.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/horizontalaccesscontrol/DocumentItem.java
new file mode 100644
index 0000000..2ef7ea5
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/horizontalaccesscontrol/DocumentItem.java
@@ -0,0 +1,35 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.horizontalaccesscontrol;
+
+import lombok.Builder;
+import lombok.Value;
+
+/**
+ * Document item for displaying user's documents overview.
+ */
+@Builder
+@Value
+public class DocumentItem {
+ int id;
+ String name;
+
+ @Override
+ public String toString() {
+ return name;
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/horizontalaccesscontrol/HorizontalAccessControlController.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/horizontalaccesscontrol/HorizontalAccessControlController.java
new file mode 100644
index 0000000..3fdf5ab
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/horizontalaccesscontrol/HorizontalAccessControlController.java
@@ -0,0 +1,98 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.horizontalaccesscontrol;
+
+import com.warxim.vucsa.client.Bundle;
+import com.warxim.vucsa.client.challenge.ChallengeController;
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.message.horizontalaccesscontrol.request.DocumentContentRequest;
+import javafx.application.Platform;
+import javafx.beans.value.ObservableValue;
+import javafx.fxml.Initializable;
+import javafx.fxml.FXML;
+import javafx.scene.control.ListView;
+import javafx.scene.control.TextArea;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+
+/**
+ * Horizontal access controller handles horizontal access challenge.
+ *
Simulates document management of logged user and allows him to download document content of his documents.
+ */
+public class HorizontalAccessControlController extends ChallengeController implements Initializable {
+ private final HorizontalAccessControlHandler handler = new HorizontalAccessControlHandler(this);
+
+ @FXML
+ private ListView documentInput;
+ @FXML
+ private TextArea contentOutput;
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ initHandler();
+ initDocuments();
+ }
+
+ /**
+ * Sets document content to GUI.
+ * @param content Content of the document
+ */
+ public void setDocument(String content) {
+ Platform.runLater(() -> contentOutput.setText(content));
+ }
+
+ /**
+ * Initializes horizontal access control message handler.
+ */
+ private void initHandler() {
+ Bundle.getInstance().getClientManager().registerHandler(ChallengeConstant.HORIZONTAL_ACCESS_CONTROL_DOCUMENT_CONTENT_TARGET, handler);
+ }
+
+ /**
+ * Initializes document overview.
+ */
+ private void initDocuments() {
+ documentInput.getItems().add(DocumentItem.builder()
+ .id(8435)
+ .name("My first secret document")
+ .build());
+ documentInput.getItems().add(DocumentItem.builder()
+ .id(12002)
+ .name("Favorite books")
+ .build());
+ documentInput.getSelectionModel().selectedItemProperty().addListener(this::onDocumentSelectionChange);
+ }
+
+ /**
+ * Sends request for document content to the server, when document gets selected.
+ */
+ private void onDocumentSelectionChange(
+ ObservableValue extends DocumentItem> observable,
+ DocumentItem oldValue,
+ DocumentItem newValue
+ ) {
+ if (newValue == null) {
+ return;
+ }
+
+ sendMessage(DocumentContentRequest.builder()
+ .target(ChallengeConstant.HORIZONTAL_ACCESS_CONTROL_DOCUMENT_CONTENT_TARGET)
+ .documentId(newValue.getId())
+ .build());
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/horizontalaccesscontrol/HorizontalAccessControlHandler.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/horizontalaccesscontrol/HorizontalAccessControlHandler.java
new file mode 100644
index 0000000..4f2ece5
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/horizontalaccesscontrol/HorizontalAccessControlHandler.java
@@ -0,0 +1,43 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.horizontalaccesscontrol;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.horizontalaccesscontrol.response.DocumentContentResponse;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Handler for document content response for horizontal access control challenge.
+ */
+@RequiredArgsConstructor
+public class HorizontalAccessControlHandler implements MessageHandler {
+ private final HorizontalAccessControlController controller;
+
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof DocumentContentResponse;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ var documentContentResponse = ((DocumentContentResponse) message);
+ controller.setDocument(documentContentResponse.getContent());
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/sqlinjection/SqlInjectionController.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/sqlinjection/SqlInjectionController.java
new file mode 100644
index 0000000..8bf129f
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/sqlinjection/SqlInjectionController.java
@@ -0,0 +1,110 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.sqlinjection;
+
+import com.warxim.vucsa.client.Bundle;
+import com.warxim.vucsa.client.challenge.ChallengeController;
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.message.sqlinjection.request.SearchRequest;
+import com.warxim.vucsa.common.message.sqlinjection.FoodEntity;
+import javafx.application.Platform;
+import javafx.beans.value.ObservableValue;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.TextField;
+import javafx.scene.control.cell.PropertyValueFactory;
+
+import java.net.URL;
+import java.util.List;
+import java.util.ResourceBundle;
+
+/**
+ * SQL Injection Controller handles SQL injection challenge.
+ *
Simulates food menu search and displays found food.
+ */
+public class SqlInjectionController extends ChallengeController implements Initializable {
+ private final SqlInjectionHandler handler = new SqlInjectionHandler(this);
+
+ @FXML
+ private TextField searchInput;
+ @FXML
+ private TableView resultTable;
+ @FXML
+ private TableColumn idColumn;
+ @FXML
+ private TableColumn nameColumn;
+ @FXML
+ private TableColumn descriptionColumn;
+ @FXML
+ private TableColumn priceColumn;
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ initHandler();
+ initTable();
+ searchInput.textProperty().addListener(this::onSearchInputChange);
+ }
+
+ /**
+ * Sets items to the table.
+ * @param items Items to be set
+ */
+ public void setItems(List items) {
+ Platform.runLater(() -> resultTable.getItems().setAll(items));
+ }
+
+ @FXML
+ private void onSearchClick(ActionEvent event) {
+ var message = SearchRequest.builder()
+ .target(ChallengeConstant.SQL_INJECTION_TARGET)
+ .search(searchInput.getText())
+ .build();
+ sendMessage(message);
+ }
+
+ /**
+ * Initializes sql injection message handler.
+ */
+ private void initHandler() {
+ Bundle.getInstance().getClientManager().registerHandler(ChallengeConstant.SQL_INJECTION_TARGET, handler);
+ }
+
+ /**
+ * Initializes table columns.
+ */
+ private void initTable() {
+ idColumn.setCellValueFactory(new PropertyValueFactory<>("id"));
+ nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
+ descriptionColumn.setCellValueFactory(new PropertyValueFactory<>("description"));
+ priceColumn.setCellValueFactory(new PropertyValueFactory<>("price"));
+ }
+
+ /**
+ * Removes invalid characters from search input on change.
+ */
+ private void onSearchInputChange(
+ ObservableValue extends String> observable,
+ String oldValue,
+ String newValue) {
+ if (!newValue.matches("\\s0-9a-zA-Z\\.-")) {
+ searchInput.setText(newValue.replaceAll("[^\\s0-9a-zA-Z.-]", ""));
+ }
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/sqlinjection/SqlInjectionHandler.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/sqlinjection/SqlInjectionHandler.java
new file mode 100644
index 0000000..d8bce1d
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/sqlinjection/SqlInjectionHandler.java
@@ -0,0 +1,42 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.sqlinjection;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.sqlinjection.response.SearchResponse;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Handler for search responses for SQL injection challenge.
+ */
+@RequiredArgsConstructor
+public class SqlInjectionHandler implements MessageHandler {
+ private final SqlInjectionController controller;
+
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof SearchResponse;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ controller.setItems(((SearchResponse) message).getEntities());
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/verticalaccesscontrol/VerticalAccessControlController.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/verticalaccesscontrol/VerticalAccessControlController.java
new file mode 100644
index 0000000..cb9b60c
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/verticalaccesscontrol/VerticalAccessControlController.java
@@ -0,0 +1,138 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.verticalaccesscontrol;
+
+import com.warxim.vucsa.client.Bundle;
+import com.warxim.vucsa.client.challenge.ChallengeController;
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.UserRole;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.request.SecretRequest;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.request.UserInfoRequest;
+import javafx.application.Platform;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.Label;
+import javafx.scene.layout.AnchorPane;
+
+import java.net.URL;
+import java.util.ResourceBundle;
+
+/**
+ * Vertical access controller handles vertical access challenge.
+ *
Simulates sending of user info from the server to the client about his session.
+ */
+public class VerticalAccessControlController extends ChallengeController implements Initializable {
+ private final VerticalAccessControlUserInfoHandler userInfoHandler = new VerticalAccessControlUserInfoHandler(this);
+ private final VerticalAccessControlSecretHandler secretHandler = new VerticalAccessControlSecretHandler(this);
+
+ @FXML
+ private Label usernameLabel;
+ @FXML
+ private Label roleLabel;
+
+ @FXML
+ private AnchorPane guestPane;
+ @FXML
+ private AnchorPane userPane;
+ @FXML
+ private AnchorPane adminPane;
+ @FXML
+ private Label secretLabel;
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ initHandler();
+ initPanes();
+ }
+
+ /**
+ * Sets user to the GUI.
+ * @param username Name of the user
+ * @param role Role of the user
+ */
+ public void setUser(String username, UserRole role) {
+ Platform.runLater(() -> {
+ usernameLabel.setText(username);
+ roleLabel.setText(role.name());
+
+ if (role.equals(UserRole.GUEST)) {
+ guestPane.setVisible(true);
+ userPane.setVisible(false);
+ adminPane.setVisible(false);
+ secretLabel.setText("-");
+ } else if (role.equals(UserRole.USER)) {
+ guestPane.setVisible(false);
+ userPane.setVisible(true);
+ adminPane.setVisible(false);
+ secretLabel.setText("-");
+ } else if (role.equals(UserRole.ADMIN)) {
+ guestPane.setVisible(false);
+ userPane.setVisible(false);
+ adminPane.setVisible(true);
+ secretLabel.setText("-");
+ }
+ });
+ }
+
+ /**
+ * Sets user secret to the GUI.
+ * @param secret Secret to be set
+ */
+ public void setSecret(String secret) {
+ Platform.runLater(() -> secretLabel.setText(secret));
+ }
+
+ /**
+ * Sends request for user info to the server.
+ */
+ @FXML
+ private void onRefreshClick(ActionEvent event) {
+ var message = UserInfoRequest.builder()
+ .target(ChallengeConstant.VERTICAL_ACCESS_CONTROL_USER_INFO_TARGET)
+ .build();
+ sendMessage(message);
+ }
+
+ /**
+ * Sends request for downloading secret to the server.
+ */
+ @FXML
+ private void onDownloadSecretClick(ActionEvent event) {
+ var message = SecretRequest.builder()
+ .target(ChallengeConstant.VERTICAL_ACCESS_CONTROL_SECRET_TARGET)
+ .build();
+ sendMessage(message);
+ }
+
+ /**
+ * Initializes vertical access control message handlers.
+ */
+ private void initHandler() {
+ Bundle.getInstance().getClientManager().registerHandler(ChallengeConstant.VERTICAL_ACCESS_CONTROL_USER_INFO_TARGET, userInfoHandler);
+ Bundle.getInstance().getClientManager().registerHandler(ChallengeConstant.VERTICAL_ACCESS_CONTROL_SECRET_TARGET, secretHandler);
+ }
+
+ /**
+ * Hides all panes.
+ */
+ private void initPanes() {
+ guestPane.setVisible(false);
+ userPane.setVisible(false);
+ adminPane.setVisible(false);
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/verticalaccesscontrol/VerticalAccessControlSecretHandler.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/verticalaccesscontrol/VerticalAccessControlSecretHandler.java
new file mode 100644
index 0000000..e3666fe
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/verticalaccesscontrol/VerticalAccessControlSecretHandler.java
@@ -0,0 +1,43 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.verticalaccesscontrol;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.response.SecretResponse;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Handler for secret response for vertical access control challenge.
+ */
+@RequiredArgsConstructor
+public class VerticalAccessControlSecretHandler implements MessageHandler {
+ private final VerticalAccessControlController controller;
+
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof SecretResponse;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ var secretResponse = ((SecretResponse) message);
+ controller.setSecret(secretResponse.getSecret());
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/verticalaccesscontrol/VerticalAccessControlUserInfoHandler.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/verticalaccesscontrol/VerticalAccessControlUserInfoHandler.java
new file mode 100644
index 0000000..d70ae8c
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/verticalaccesscontrol/VerticalAccessControlUserInfoHandler.java
@@ -0,0 +1,43 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.verticalaccesscontrol;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.response.UserInfoResponse;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Handler for user info response for vertical access control challenge.
+ */
+@RequiredArgsConstructor
+public class VerticalAccessControlUserInfoHandler implements MessageHandler {
+ private final VerticalAccessControlController controller;
+
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof UserInfoResponse;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ var info = ((UserInfoResponse) message);
+ controller.setUser(info.getUsername(), info.getRole());
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/xml/XmlController.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/xml/XmlController.java
new file mode 100644
index 0000000..7ec5fb1
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/xml/XmlController.java
@@ -0,0 +1,156 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.xml;
+
+import com.warxim.vucsa.client.Bundle;
+import com.warxim.vucsa.client.challenge.ChallengeController;
+import com.warxim.vucsa.client.gui.dialog.Dialogs;
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.message.xml.StorageItem;
+import com.warxim.vucsa.common.message.xml.StorageMessage;
+import javafx.application.Platform;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.ContextMenu;
+import javafx.scene.control.MenuItem;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.cell.PropertyValueFactory;
+
+import java.net.URL;
+import java.util.List;
+import java.util.ResourceBundle;
+
+/**
+ * XML controller handles XML challenge.
+ *
This challenge acts like a simple ECHO functionality (simulates "storage"), but with vulnerable deserialization implementation.
+ */
+public class XmlController extends ChallengeController implements Initializable {
+ private final XmlHandler handler = new XmlHandler(this);
+
+ @FXML
+ private TableView requestTable;
+ @FXML
+ private TableColumn requestKeyColumn;
+ @FXML
+ private TableColumn requestValueColumn;
+ @FXML
+ private TableView responseTable;
+ @FXML
+ private TableColumn responseKeyColumn;
+ @FXML
+ private TableColumn responseValueColumn;
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ initHandler();
+ initDefaultItems();
+ initTable();
+ initContextMenu();
+ }
+
+ /**
+ * Sets storage items to the GUI.
+ * @param items Items to be set
+ */
+ public void setItems(List items) {
+ Platform.runLater(() -> responseTable.getItems().setAll(items));
+ }
+
+ /**
+ * Sends storage items to server to "save" them.
+ */
+ @FXML
+ private void onSendClick(ActionEvent event) {
+ var message = StorageMessage.builder()
+ .target(ChallengeConstant.XML_TARGET)
+ .items(requestTable.getItems())
+ .build();
+ sendMessage(message);
+ }
+
+ /**
+ * Adds new item.
+ */
+ @FXML
+ private void onAddItemClick(ActionEvent event) {
+ var maybePair = Dialogs.createTextPairDialog("Add Item", "Key", "Value");
+ if (maybePair.isEmpty()) {
+ return;
+ }
+ var pair = maybePair.get();
+ requestTable.getItems().add(StorageItem.builder()
+ .key(pair.getKey())
+ .value(pair.getValue())
+ .build());
+ }
+
+ /**
+ * Removes existing item.
+ */
+ @FXML
+ private void onRemoveItemClick(ActionEvent event) {
+ var selected = requestTable.getSelectionModel().getSelectedIndex();
+ if (selected < 0) {
+ return;
+ }
+
+ requestTable.getItems().remove(selected);
+ }
+
+ /**
+ * Initializes buffer over-read message handler.
+ */
+ private void initHandler() {
+ Bundle.getInstance().getClientManager().registerHandler(ChallengeConstant.XML_TARGET, handler);
+ }
+
+ /**
+ * Initializes default items in the challenge GUI.
+ */
+ private void initDefaultItems() {
+ requestTable.getItems().add(StorageItem.builder().key("Item 1").value("VALUE 1").build());
+ requestTable.getItems().add(StorageItem.builder().key("Item 2").value("VALUE 2").build());
+ requestTable.getItems().add(StorageItem.builder().key("Item 3").value("VALUE 3").build());
+ }
+
+ /**
+ * Initializes table columns.
+ */
+ private void initTable() {
+ requestKeyColumn.setCellValueFactory(new PropertyValueFactory<>("key"));
+ requestValueColumn.setCellValueFactory(new PropertyValueFactory<>("value"));
+ responseKeyColumn.setCellValueFactory(new PropertyValueFactory<>("key"));
+ responseValueColumn.setCellValueFactory(new PropertyValueFactory<>("value"));
+ }
+
+ /**
+ * Initializes context menu of request input.
+ */
+ private void initContextMenu() {
+ var menu = new ContextMenu();
+ var addItem = new MenuItem("Add");
+ addItem.setOnAction(this::onAddItemClick);
+ var removeItem = new MenuItem("Remove");
+ removeItem.setOnAction(this::onRemoveItemClick);
+
+ menu.getItems().add(addItem);
+ menu.getItems().add(removeItem);
+ requestTable.setContextMenu(menu);
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/xml/XmlHandler.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/xml/XmlHandler.java
new file mode 100644
index 0000000..7a61d04
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/challenge/xml/XmlHandler.java
@@ -0,0 +1,42 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.challenge.xml;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.xml.StorageMessage;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Handler for storage messages from server for XML challenge.
+ */
+@RequiredArgsConstructor
+public class XmlHandler implements MessageHandler {
+ private final XmlController controller;
+
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof StorageMessage;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ controller.setItems(((StorageMessage) message).getItems());
+ return true;
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/core/Client.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/core/Client.java
new file mode 100644
index 0000000..4461a39
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/core/Client.java
@@ -0,0 +1,58 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.core;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.connection.listener.ConnectionListener;
+import com.warxim.vucsa.common.message.MessageHandler;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Client, which is used to communicate with the server.
+ *
The client is created through ClientManager, when user starts it in the Settings tab.
+ */
+public class Client extends Connection {
+ private final ClientConfig config;
+
+ public Client(
+ ClientConfig config,
+ ConnectionListener connectionListener,
+ MessageHandler messageHandler) {
+ super(1, connectionListener, messageHandler);
+ this.config = config;
+ }
+
+ @Override
+ protected boolean handleBeforeStart() {
+ if (!super.handleBeforeStart()) {
+ return false;
+ }
+
+ try {
+ socket = new Socket(config.getServerHost(), config.getServerPort());
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not start client socket!", e);
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/core/ClientConfig.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/core/ClientConfig.java
new file mode 100644
index 0000000..a9e5688
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/core/ClientConfig.java
@@ -0,0 +1,37 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.core;
+
+import lombok.Builder;
+import lombok.Value;
+
+/**
+ * Client configuration.
+ */
+@Value
+@Builder
+public class ClientConfig {
+ /**
+ * Server host (127.0.0.1, www.example.org, ...)
+ */
+ String serverHost;
+
+ /**
+ * Server port (8765, ...)
+ */
+ int serverPort;
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/core/ClientManager.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/core/ClientManager.java
new file mode 100644
index 0000000..24597db
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/core/ClientManager.java
@@ -0,0 +1,128 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.core;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.connection.ConnectionState;
+import com.warxim.vucsa.common.connection.listener.ConnectionListener;
+import com.warxim.vucsa.common.connection.listener.ConnectionListenerManager;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.MessageHandlerManager;
+
+/**
+ * Client manager for managing client connection.
+ *
Wraps all required components and handles client creation, start, stop, ...
+ */
+public class ClientManager implements ConnectionListener {
+ private final ConnectionListenerManager connectionListenerManager;
+ private final MessageHandlerManager messageHandlerManager;
+ private Client client;
+
+ public ClientManager() {
+ this.connectionListenerManager = new ConnectionListenerManager();
+ this.messageHandlerManager = new MessageHandlerManager();
+ connectionListenerManager.registerListener(this);
+ }
+
+ /**
+ * Creates and starts client core.
+ * @param config Client configuration
+ */
+ public synchronized void start(ClientConfig config) {
+ if (client != null) {
+ return;
+ }
+
+ client = new Client(config, connectionListenerManager, messageHandlerManager);
+ client.start();
+ }
+
+ /**
+ * Stops client core.
+ */
+ public synchronized void stop() {
+ if (client == null) {
+ return;
+ }
+
+ client.stop();
+ }
+
+ /**
+ * Obtains client core state.
+ * @return Connection state
+ */
+ public synchronized ConnectionState getState() {
+ if (client == null) {
+ return ConnectionState.STOPPED;
+ }
+
+ return client.getState();
+ }
+
+ /**
+ * Sends message using the client if it is available.
+ *
If the client is not available, does nothing.
+ * @return {@code true} if the message was sent
+ */
+ public synchronized boolean sendMessage(Message message) {
+ if (client != null && getState() == ConnectionState.STARTED) {
+ client.sendMessage(message);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Registers connection listener.
+ * @param clientListener Listener to be registered
+ */
+ public void registerConnectionListener(ConnectionListener clientListener) {
+ connectionListenerManager.registerListener(clientListener);
+ }
+
+ /**
+ * Unregisters connection listener.
+ * @param clientListener Listener to be unregistered
+ */
+ public void unregisterConnectionListener(ConnectionListener clientListener) {
+ connectionListenerManager.unregisterListener(clientListener);
+ }
+
+ /**
+ * Registers message handler.
+ * @param target Target identifier of the handler
+ * @param messageHandler Handler to be registered
+ */
+ public void registerHandler(int target, MessageHandler messageHandler) {
+ messageHandlerManager.registerHandler(target, messageHandler);
+ }
+
+ /**
+ * Unregisters message handler.
+ * @param target Target identifier of the handler
+ */
+ public void unregisterHandler(int target) {
+ messageHandlerManager.unregisterHandler(target);
+ }
+
+ @Override
+ public void onConnectionStop(Connection connection) {
+ client = null;
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/GuiApplication.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/GuiApplication.java
new file mode 100644
index 0000000..562fd73
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/GuiApplication.java
@@ -0,0 +1,67 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.gui;
+
+import com.sun.javafx.css.StyleManager;
+import com.warxim.vucsa.client.Bundle;
+import com.warxim.vucsa.common.Constant;
+import com.warxim.vucsa.common.connection.ConnectionState;
+import com.warxim.vucsa.client.gui.controller.ApplicationController;
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+
+/**
+ * Client GUI application.
+ *
Starts Vulnerable Client GUI.
+ */
+public class GuiApplication extends Application {
+ @Override
+ public void start(Stage stage) throws Exception {
+ Application.setUserAgentStylesheet(Application.STYLESHEET_MODENA);
+ StyleManager.getInstance().addUserAgentStylesheet(getClass().getResource(GuiConstant.MAIN_CSS_PATH).toString());
+
+ var fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/Application.fxml"));
+ fxmlLoader.setController(new ApplicationController());
+
+ Parent root = fxmlLoader.load();
+
+ var scene = new Scene(root);
+ stage.setTitle("VuCSA Client v" + Constant.VERSION);
+ stage.getIcons().add(GuiBundle.getInstance().getLogo());
+ stage.setWidth(1200);
+ stage.setHeight(900);
+ stage.setScene(scene);
+
+ stage.show();
+ }
+
+ @Override
+ public void stop() throws Exception {
+ super.stop();
+
+ var clientManager = Bundle.getInstance().getClientManager();
+ if (clientManager != null && clientManager.getState() != ConnectionState.STOPPED) {
+ clientManager.stop();
+ }
+
+ Bundle.getInstance().destroy();
+ GuiBundle.getInstance().destroy();
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/GuiBundle.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/GuiBundle.java
new file mode 100644
index 0000000..5bafba1
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/GuiBundle.java
@@ -0,0 +1,87 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.gui;
+
+import com.warxim.vucsa.client.gui.controller.ApplicationController;
+import javafx.scene.image.Image;
+import lombok.Getter;
+
+import java.util.Objects;
+
+/**
+ * Singleton for client GUI assets.
+ */
+@Getter
+public final class GuiBundle {
+ /**
+ * Singleton instance.
+ */
+ private static volatile GuiBundle instance;
+
+ /**
+ * Logo icon
+ */
+ private final Image logo;
+
+ /**
+ * Application controller
+ */
+ private ApplicationController applicationController;
+
+ private GuiBundle() {
+ logo = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/img/Logo.png")));
+ }
+
+ /**
+ * Creates instance of bundle or returns existing instance if it exists.
+ * @return Bundle instance
+ */
+ public static GuiBundle getInstance() {
+ if (instance == null) {
+ synchronized(GuiBundle.class) {
+ if (instance == null) {
+ instance = new GuiBundle();
+ }
+ }
+ }
+
+ return instance;
+ }
+
+ /**
+ * Obtains application controller, which handles main application window UI
+ * @return Application controller
+ */
+ public ApplicationController getApplicationController() {
+ return applicationController;
+ }
+
+ /**
+ * Sets application controller, which handles main application window UI
+ * @param controller Application controller
+ */
+ public void setApplicationController(ApplicationController controller) {
+ applicationController = controller;
+ }
+
+ /**
+ * Destroys the bundle.
+ */
+ public void destroy() {
+ // no action needed
+ }
+}
\ No newline at end of file
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/GuiConstant.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/GuiConstant.java
new file mode 100644
index 0000000..5a0d856
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/GuiConstant.java
@@ -0,0 +1,30 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.gui;
+
+public final class GuiConstant {
+ /**
+ * Path to main CSS file of the application
+ */
+ public static final String MAIN_CSS_PATH = "/css/Main.css";
+
+ public static final int LOG_TAB_ORDER = 1;
+ public static final int SETTINGS_TAB_ORDER = 2;
+ public static final int CHALLENGES_TAB_ORDER = 10;
+
+ private GuiConstant() {}
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/controller/ApplicationController.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/controller/ApplicationController.java
new file mode 100644
index 0000000..70c90f0
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/controller/ApplicationController.java
@@ -0,0 +1,195 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.gui.controller;
+
+import com.warxim.vucsa.client.Bundle;
+import com.warxim.vucsa.client.challenge.commandexecution.CommandExecutionController;
+import com.warxim.vucsa.client.challenge.enumeration.EnumerationController;
+import com.warxim.vucsa.client.challenge.verticalaccesscontrol.VerticalAccessControlController;
+import com.warxim.vucsa.client.challenge.ChallengeController;
+import com.warxim.vucsa.client.challenge.ChallengeWrapper;
+import com.warxim.vucsa.client.challenge.bufferoverread.BufferOverreadController;
+import com.warxim.vucsa.client.challenge.horizontalaccesscontrol.HorizontalAccessControlController;
+import com.warxim.vucsa.client.challenge.sqlinjection.SqlInjectionController;
+import com.warxim.vucsa.client.challenge.xml.XmlController;
+import com.warxim.vucsa.client.gui.GuiBundle;
+import com.warxim.vucsa.client.gui.GuiConstant;
+import com.warxim.vucsa.client.gui.dialog.AboutDialog;
+import com.warxim.vucsa.client.util.GuiUtils;
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.connection.ConnectionState;
+import com.warxim.vucsa.common.connection.listener.ConnectionListener;
+import javafx.application.Platform;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.fxml.Initializable;
+import javafx.scene.Node;
+import javafx.scene.control.TabPane;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Main application controller, which handles the whole application.
+ */
+public class ApplicationController implements Initializable, ConnectionListener {
+ private final List challengeWrappers = new LinkedList<>();
+
+ @FXML
+ private TabPane tabs;
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ GuiBundle.getInstance().setApplicationController(this);
+ Bundle.getInstance().getClientManager().registerConnectionListener(this);
+
+ initApplicationTabs();
+ initChallengeTabs();
+
+ Logger.getGlobal().info("Application initialized!");
+ }
+
+ /**
+ * Exits application dialog.
+ */
+ @FXML
+ private void onExitMenuClick(ActionEvent event) {
+ Platform.exit();
+ }
+ /**
+ * Shows application about dialog.
+ */
+
+ @FXML
+ private void showAbout(ActionEvent e) {
+ AboutDialog.show();
+ }
+
+ @Override
+ public void onConnectionStart(Connection connection) {
+ Platform.runLater(() ->
+ challengeWrappers.forEach(challengeWrapper -> challengeWrapper.getNode().setDisable(false))
+ );
+ }
+
+ @Override
+ public void onConnectionStop(Connection connection) {
+ Platform.runLater(() ->
+ challengeWrappers.forEach(challengeWrapper -> challengeWrapper.getNode().setDisable(true))
+ );
+ }
+
+ /**
+ * Registers new tab to main tabs.
+ * @param title Title of the tab
+ * @param node Node to be added as a child into the tab
+ * @param order Order of the tab (where should the tab be placed)
+ */
+ private void registerTab(String title, Node node, int order) {
+ GuiUtils.addTabToTabPane(tabs, title, node, order);
+ }
+
+ /**
+ * Initializes application tab.
+ */
+ private void initApplicationTab(String title, String template, Object controller, int order) {
+ try {
+ var fxmlLoader = new FXMLLoader(getClass().getResource(template));
+ fxmlLoader.setController(controller);
+ registerTab(title, fxmlLoader.load(), order);
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not add settings tab", e);
+ }
+ }
+
+ /**
+ * Initializes challenge tab and saves it to {@code challengeWrappers}.
+ */
+ private void initChallengeTab(String title, String template, ChallengeController controller, int order) {
+ try {
+ var fxmlLoader = new FXMLLoader(getClass().getResource(template));
+ fxmlLoader.setController(controller);
+ var node = (Node) fxmlLoader.load();
+ var wrapper = ChallengeWrapper.builder()
+ .controller(controller)
+ .node(node)
+ .build();
+ challengeWrappers.add(wrapper);
+ node.setDisable(Bundle.getInstance().getClientManager().getState() == ConnectionState.STOPPED);
+ registerTab(title, node, order);
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not add settings tab", e);
+ }
+ }
+
+ /**
+ * Initializes main application tabs.
+ */
+ private void initApplicationTabs() {
+ initApplicationTab("Log", "/fxml/tab/LogTab.fxml", new LogController(), GuiConstant.LOG_TAB_ORDER);
+ initApplicationTab("Settings", "/fxml/tab/SettingsTab.fxml", new SettingsController(), GuiConstant.SETTINGS_TAB_ORDER);
+ }
+
+ /**
+ * Initializes challenge tabs.
+ *
Creates challenges and adds them to the tab pane.
+ */
+ private void initChallengeTabs() {
+ var tabOrder = GuiConstant.CHALLENGES_TAB_ORDER;
+ initChallengeTab(
+ "Buffer Over-read",
+ "/fxml/challenge/bufferoverread/BufferOverreadTab.fxml",
+ new BufferOverreadController(),
+ ++tabOrder);
+ initChallengeTab(
+ "SQL Injection",
+ "/fxml/challenge/sqlinjection/SqlInjectionTab.fxml",
+ new SqlInjectionController(),
+ ++tabOrder);
+ initChallengeTab(
+ "Enumeration",
+ "/fxml/challenge/enumeration/EnumerationTab.fxml",
+ new EnumerationController(),
+ ++tabOrder);
+ initChallengeTab(
+ "Command Execution",
+ "/fxml/challenge/commandexecution/CommandExecutionTab.fxml",
+ new CommandExecutionController(),
+ ++tabOrder);
+ initChallengeTab(
+ "XML",
+ "/fxml/challenge/xml/XmlTab.fxml",
+ new XmlController(),
+ ++tabOrder);
+ initChallengeTab(
+ "Horizontal Access Control",
+ "/fxml/challenge/horizontalaccesscontrol/HorizontalAccessControlTab.fxml",
+ new HorizontalAccessControlController(),
+ ++tabOrder);
+ initChallengeTab(
+ "Vertical Access Control",
+ "/fxml/challenge/verticalaccesscontrol/VerticalAccessControlTab.fxml",
+ new VerticalAccessControlController(),
+ ++tabOrder);
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/controller/LogController.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/controller/LogController.java
new file mode 100644
index 0000000..bd8b328
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/controller/LogController.java
@@ -0,0 +1,150 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.gui.controller;
+
+import javafx.application.Platform;
+import javafx.css.PseudoClass;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.text.Font;
+import javafx.scene.text.FontWeight;
+import javafx.scene.text.Text;
+import javafx.scene.text.TextFlow;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.ResourceBundle;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+/**
+ * Log tab controller.
+ *
Displays logs from {@link Logger#getGlobal()}.
+ */
+public final class LogController extends Handler implements Initializable {
+ /**
+ * Maximum number of Text elements in text flow.
+ */
+ private static final int LIMIT_LOG_CHILDREN = 150;
+
+ private static final PseudoClass INFO_PSEUDO_CLASS = PseudoClass.getPseudoClass("info");
+ private static final PseudoClass SEVERE_PSEUDO_CLASS = PseudoClass.getPseudoClass("severe");
+ private static final PseudoClass WARNING_PSEUDO_CLASS = PseudoClass.getPseudoClass("warning");
+ private static final PseudoClass FINE_PSEUDO_CLASS = PseudoClass.getPseudoClass("fine");
+ private static final PseudoClass CONFIG_PSEUDO_CLASS = PseudoClass.getPseudoClass("config");
+ private static final PseudoClass OTHER_PSEUDO_CLASS = PseudoClass.getPseudoClass("other");
+
+ /**
+ * Text flow for logs.
+ */
+ @FXML
+ private TextFlow logFlow;
+ /**
+ * Scroll pane containing text flow.
+ */
+ @FXML
+ private ScrollPane scrollPane;
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ Logger.getGlobal().addHandler(this);
+ }
+
+ @Override
+ public void publish(LogRecord logRecord) {
+ Platform.runLater(() -> this.addLogRecord(logRecord));
+ }
+
+ @Override
+ public void flush() {
+ // No action needed.
+ }
+
+ @Override
+ public void close() {
+ // No action needed.
+ }
+
+ /**
+ * Adds log logRecord to the flow.
+ */
+ private void addLogRecord(LogRecord logRecord) {
+ // Level.
+ var level = logRecord.getLevel();
+
+ Text levelText;
+ if (level == Level.INFO) {
+ levelText = new Text("[INFO] ");
+ levelText.pseudoClassStateChanged(INFO_PSEUDO_CLASS, true);
+ } else if (level == Level.SEVERE) {
+ levelText = new Text("[SEVERE] ");
+ levelText.pseudoClassStateChanged(SEVERE_PSEUDO_CLASS, true);
+ } else if (level == Level.WARNING) {
+ levelText = new Text("[WARNING] ");
+ levelText.pseudoClassStateChanged(WARNING_PSEUDO_CLASS, true);
+ } else if (level == Level.FINE) {
+ levelText = new Text("[FINE] ");
+ levelText.pseudoClassStateChanged(FINE_PSEUDO_CLASS, true);
+ } else if (level == Level.CONFIG) {
+ levelText = new Text("[CONFIG] ");
+ levelText.pseudoClassStateChanged(CONFIG_PSEUDO_CLASS, true);
+ } else {
+ levelText = new Text("[OTHER] ");
+ levelText.pseudoClassStateChanged(OTHER_PSEUDO_CLASS, true);
+ }
+ levelText.getStyleClass().add("log-logRecord");
+ levelText.setFont(Font.font(null, FontWeight.BOLD, 11));
+
+ // Message.
+ var messageText = new Text(logRecord.getMessage());
+
+ logFlow.getChildren().add(levelText);
+ logFlow.getChildren().add(messageText);
+
+ // Exception.
+ if (logRecord.getThrown() != null) {
+ var exception = new StringWriter();
+ exception.append(System.lineSeparator());
+ exception.append("\tException:");
+ exception.append(System.lineSeparator());
+ exception.append("\t");
+ logRecord.getThrown().printStackTrace(new PrintWriter(exception));
+ var exceptionText = new Text(exception.toString());
+ logFlow.getChildren().add(exceptionText);
+ }
+
+ // Separator.
+ var logSeparator = new Text(System.lineSeparator());
+ logSeparator.setFont(Font.font(null, FontWeight.NORMAL, 1));
+ logSeparator.setLineSpacing(0);
+ logFlow.getChildren().add(logSeparator);
+
+ // Limit children.
+ var size = logFlow.getChildren().size();
+ if (size > LIMIT_LOG_CHILDREN) {
+ logFlow.getChildren().remove(0, size - LIMIT_LOG_CHILDREN);
+ }
+
+ // Scroll down automatically.
+ scrollPane.layout();
+ scrollPane.setVvalue(1D);
+ }
+}
\ No newline at end of file
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/controller/SettingsController.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/controller/SettingsController.java
new file mode 100644
index 0000000..c9fa53f
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/controller/SettingsController.java
@@ -0,0 +1,152 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.gui.controller;
+
+import com.warxim.vucsa.client.Bundle;
+import com.warxim.vucsa.client.core.ClientConfig;
+import com.warxim.vucsa.client.gui.dialog.Dialogs;
+import com.warxim.vucsa.common.Constant;
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.connection.ConnectionState;
+import com.warxim.vucsa.common.connection.listener.ConnectionListener;
+import javafx.application.Platform;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+
+import java.net.URL;
+import java.util.Optional;
+import java.util.ResourceBundle;
+
+/**
+ * Controller for settings tab.
+ */
+public class SettingsController implements Initializable, ConnectionListener {
+ private static final String CONNECT_TEXT = "CONNECT";
+ private static final String DISCONNECT_TEXT = "DISCONNECT";
+
+ @FXML
+ private TextField serverHostInput;
+ @FXML
+ private TextField serverPortInput;
+ @FXML
+ private Label statusLabel;
+ @FXML
+ private Label serverHostLabel;
+ @FXML
+ private Label serverPortLabel;
+ @FXML
+ private Button startStopButton;
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ serverHostInput.setText(Constant.DEFAULT_SERVER_HOST);
+ serverPortInput.setText(String.valueOf(Constant.DEFAULT_SERVER_PORT));
+ startStopButton.setText(CONNECT_TEXT);
+ onConnectionStop(null);
+ var clientManager = Bundle.getInstance().getClientManager();
+ clientManager.registerConnectionListener(this);
+ }
+
+ @Override
+ public void onConnectionStart(Connection connection) {
+ Platform.runLater(() -> {
+ statusLabel.getStyleClass().add("status-connected");
+ statusLabel.getStyleClass().removeAll("status-disconnected");
+ statusLabel.setText("CONNECTED");
+ startStopButton.setText(DISCONNECT_TEXT);
+ });
+ }
+
+ @Override
+ public void onConnectionStop(Connection connection) {
+ Platform.runLater(() -> {
+ statusLabel.getStyleClass().removeAll("status-connected");
+ statusLabel.getStyleClass().add("status-disconnected");
+ statusLabel.setText("DISCONNECTED");
+ startStopButton.setText(CONNECT_TEXT);
+ });
+ }
+
+ /**
+ * Starts or stops client using client manager.
+ */
+ @FXML
+ private void onStartStopClick(ActionEvent event) {
+ var clientManager = Bundle.getInstance().getClientManager();
+ var clientState = clientManager.getState();
+ if (clientState == ConnectionState.STARTED) {
+ clientManager.stop();
+ startStopButton.setText(CONNECT_TEXT);
+ } else if (clientState == ConnectionState.STOPPED) {
+ var settings = validateAndGetSettings();
+ if (settings.isEmpty()) {
+ return;
+ }
+ var config = ClientConfig.builder()
+ .serverHost(serverHostInput.getText())
+ .serverPort(Integer.parseInt(serverPortInput.getText()))
+ .build();
+ clientManager.start(config);
+ serverHostLabel.setText(serverHostInput.getText());
+ serverPortLabel.setText(serverPortInput.getText());
+ startStopButton.setText(DISCONNECT_TEXT);
+ }
+ }
+
+ /**
+ * Checks if the settings is valid and returns the settings if it is valid.
+ */
+ private Optional validateAndGetSettings() {
+ var serverHost = serverHostInput.getText();
+ var serverPort = serverPortInput.getText();
+ if (serverHost.isBlank()) {
+ Dialogs.createErrorDialog(
+ "Server host required",
+ "You have to specify server host!");
+ return Optional.empty();
+ }
+
+ if (serverPort.isBlank() || !isInteger(serverPort)) {
+ Dialogs.createErrorDialog(
+ "Server port required",
+ "You have to specify server port!");
+ return Optional.empty();
+ }
+
+ var settings = ClientConfig.builder()
+ .serverHost(serverHost)
+ .serverPort(Integer.parseInt(serverPort))
+ .build();
+ return Optional.of(settings);
+ }
+
+ /**
+ * Returns true if the value is a valid integer.
+ */
+ private static boolean isInteger(String value) {
+ try {
+ Integer.parseInt(value);
+ return true;
+ } catch(NumberFormatException e){
+ return false;
+ }
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/dialog/AboutDialog.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/dialog/AboutDialog.java
new file mode 100644
index 0000000..d2b6c58
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/dialog/AboutDialog.java
@@ -0,0 +1,115 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.gui.dialog;
+
+import com.warxim.vucsa.client.gui.GuiBundle;
+import com.warxim.vucsa.common.Constant;
+import javafx.event.ActionEvent;
+import javafx.geometry.Insets;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Hyperlink;
+import javafx.scene.control.Label;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.GridPane;
+import javafx.stage.Stage;
+
+import java.awt.*;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * About dialog.
+ */
+public final class AboutDialog {
+ private AboutDialog() {
+ }
+
+ /**
+ * Shows about dialog.
+ */
+ public static void show() {
+ var alert = new Alert(Alert.AlertType.INFORMATION);
+
+ alert.setTitle("About VuCSA");
+ alert.setHeaderText("VuCSA v" + Constant.VERSION);
+
+ var icon = GuiBundle.getInstance().getLogo();
+
+ var image = new ImageView(icon);
+ image.setFitWidth(50);
+ image.setFitHeight(50);
+ alert.setGraphic(image);
+
+ ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().add(icon);
+
+ // Info
+ var infoLabel = new Label("Vulnerable client-server application (VuCSA) is made for learning/presenting how to perform penetration tests of non-http thick clients.");
+
+ // Version
+ var versionLabel = new Label("Version:");
+ versionLabel.getStyleClass().add("input-label");
+ var versionValueLabel = new Label(Constant.VERSION);
+
+ // Link
+ var linkLabel = new Label("Website: ");
+ linkLabel.getStyleClass().add("input-label");
+ var link = new Hyperlink(Constant.WEB);
+ link.setOnAction(AboutDialog::onWebClick);
+
+ // Copyright
+ var copyrightLabel = new Label("Copyright (C) Michal Valka, 2022, all rights reserved.");
+
+ // Grid
+ var grid = new GridPane();
+ grid.setMaxWidth(Double.MAX_VALUE);
+ grid.setHgap(10);
+ grid.setVgap(10);
+ grid.setPadding(new Insets(20, 150, 10, 10));
+
+ // Info
+ grid.add(infoLabel, 0, 0, 2, 1);
+
+ // Version
+ grid.add(versionLabel, 0, 1);
+ grid.add(versionValueLabel, 1, 1);
+
+ // Link
+ grid.add(linkLabel, 0, 2);
+ grid.add(link, 1, 2);
+
+ // Copyright
+ grid.add(copyrightLabel, 0, 3, 2, 1);
+
+ alert.getDialogPane().setContent(grid);
+
+ alert.showAndWait();
+ }
+
+ /**
+ * Opens VuCSA website.
+ */
+ private static void onWebClick(ActionEvent event) {
+ try {
+ Desktop.getDesktop().browse(new URI(Constant.WEB));
+ } catch (IOException | URISyntaxException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not open VuCSA link.");
+ }
+ }
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/dialog/Dialogs.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/dialog/Dialogs.java
new file mode 100644
index 0000000..276300d
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/gui/dialog/Dialogs.java
@@ -0,0 +1,298 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.gui.dialog;
+
+import javafx.geometry.Insets;
+import javafx.scene.control.*;
+import javafx.scene.control.Alert.AlertType;
+import javafx.scene.image.Image;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.Priority;
+import javafx.stage.Stage;
+import javafx.util.Pair;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Dialog helper.
+ */
+public final class Dialogs {
+ private static Image defaultIcon;
+
+ /**
+ * Gets default icon of PETEP.
+ * @return JavaFX image object
+ */
+ public static Image getDefaultIcon() {
+ return defaultIcon;
+ }
+
+ /**
+ * Sets default icon of PETEP.
+ * @param icon Icon to be used through the whole PETEP.
+ */
+ public static void setDefaultIcon(Image icon) {
+ defaultIcon = icon;
+ }
+
+ /**
+ * Creates simple error dialog (with error icon).
+ * @param title Dialog title
+ * @param message Dialog content message
+ */
+ public static void createErrorDialog(String title, String message) {
+ var alert = new Alert(AlertType.ERROR);
+ alert.setTitle(title);
+ alert.setHeaderText(title);
+ alert.setContentText(message);
+ ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon);
+ alert.showAndWait();
+ }
+
+ /**
+ * Creates simple success dialog (with info icon).
+ * @param title Dialog title
+ * @param message Dialog content message
+ */
+ public static void createInfoDialog(String title, String message) {
+ var alert = new Alert(AlertType.INFORMATION);
+ alert.setTitle(title);
+ alert.setHeaderText(title);
+ alert.setContentText(message);
+ ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon);
+ alert.showAndWait();
+ }
+
+ /**
+ * Creates simple exception dialog.
+ * @param title Dialog title
+ * @param message Dialog content message
+ * @param exception Exception to be displayed in textarea.
+ */
+ public static void createExceptionDialog(String title, String message, Exception exception) {
+ var alert = new Alert(AlertType.ERROR);
+ alert.setTitle(title);
+ alert.setHeaderText(title);
+ alert.setContentText(message);
+
+ ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon);
+
+ var stringWriter = new StringWriter();
+ var printWriter = new PrintWriter(stringWriter);
+ exception.printStackTrace(printWriter);
+ var exceptionText = stringWriter.toString();
+
+ var textArea = new TextArea(exceptionText);
+ textArea.setEditable(false);
+ textArea.setWrapText(true);
+
+ textArea.setMaxWidth(Double.MAX_VALUE);
+ textArea.setMaxHeight(Double.MAX_VALUE);
+ GridPane.setVgrow(textArea, Priority.ALWAYS);
+ GridPane.setHgrow(textArea, Priority.ALWAYS);
+
+ var label = new Label("The exception stacktrace was:");
+
+ var expContent = new GridPane();
+ expContent.setMaxWidth(Double.MAX_VALUE);
+ expContent.add(label, 0, 0);
+ expContent.add(textArea, 0, 1);
+
+ alert.getDialogPane().setExpandableContent(expContent);
+
+ alert.showAndWait();
+ }
+
+ /**
+ * Creates simple yes / no / cancel dialog.
+ * @param title Dialog title
+ * @param message Dialog content message
+ * @return {@code Optional.of(true)} if yes has been clicked;
+ * {@code Optional.of(false)} if no has been clicked;
+ * {@code Optional.empty()} otherwise
+ */
+ public static Optional createYesOrNoOrCancelDialog(String title, String message) {
+ var alert = new Alert(AlertType.CONFIRMATION, message, ButtonType.YES, ButtonType.NO, ButtonType.CANCEL);
+ alert.setTitle(title);
+ alert.setHeaderText(title);
+ ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon);
+
+ alert.showAndWait();
+
+ var result = alert.getResult();
+ if (result == ButtonType.YES) {
+ return Optional.of(Boolean.TRUE);
+ } else if (result == ButtonType.NO) {
+ return Optional.of(Boolean.FALSE);
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * Creates simple yes / no dialog.
+ * @param title Dialog title
+ * @param message Dialog content message
+ * @return {@code true} if yes has been clicked;
+ * {@code false} if no has been clicked
+ */
+ public static boolean createYesOrNoDialog(String title, String message) {
+ var alert = new Alert(AlertType.CONFIRMATION, message, ButtonType.YES, ButtonType.NO);
+ alert.setTitle(title);
+ alert.setHeaderText(title);
+ ((Stage) alert.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon);
+
+ alert.showAndWait();
+
+ return alert.getResult() == ButtonType.YES;
+ }
+
+ /**
+ * Creates simple text input dialog. (Empty default value.)
+ * @param title Dialog title
+ * @param message Dialog content message
+ * @return Entered value. (Empty optional if the dialog has been closed/canceled.]
+ */
+ public static Optional createTextInputDialog(String title, String message) {
+ return createTextInputDialog(title, message, "");
+ }
+
+ /**
+ * Creates simple text input dialog.
+ * @param title Dialog title
+ * @param message Dialog content message
+ * @param value Default input value
+ * @return Entered value. (Empty optional if the dialog has been closed/canceled.)
+ */
+ public static Optional createTextInputDialog(String title, String message, String value) {
+ var dialog = new TextInputDialog(value);
+ dialog.setTitle(title);
+ dialog.setHeaderText(title);
+ dialog.setContentText(message);
+
+ ((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon);
+
+ return dialog.showAndWait();
+ }
+
+ /**
+ * Creates simple choice dialog.
+ * @param title Dialog title
+ * @param message Dialog content message
+ * @param choices Choices to display in dialog
+ * @param value Default selected choice
+ * @return Chosen value. (Empty optional if the dialog has been closed/canceled.)
+ */
+ public static Optional createChoiceDialog(String title, String message, List choices, T value) {
+ var dialog = new ChoiceDialog<>(value, choices);
+ dialog.setTitle(title);
+ dialog.setHeaderText(title);
+ dialog.setContentText(message);
+
+ ((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon);
+
+ return dialog.showAndWait();
+ }
+
+ /**
+ * Creates simple choice dialog.
+ * @param title Dialog title
+ * @param message Dialog content message
+ * @param choices Choices to display in dialog
+ * @return Chosen value. (Empty optional if the dialog has been closed/canceled.)
+ */
+ public static Optional createChoiceDialog(String title, String message, List choices) {
+ return createChoiceDialog(title, message, choices, null);
+ }
+
+ /**
+ * Creates dialog for text pair input.
+ *
Lets user enter two string values.
+ * @param title Dialog title
+ * @param firstLabel Label of first input
+ * @param secondLabel Label of second input
+ * @return Entered values. (Empty optional if the dialog has been closed/canceled.)
+ */
+ public static Optional> createTextPairDialog(
+ String title,
+ String firstLabel,
+ String secondLabel) {
+ return createTextPairDialog(title, firstLabel, secondLabel, "", "");
+ }
+
+ /**
+ * Creates dialog for text pair input with default values.
+ *
Lets user enter two string values.
+ * @param title Dialog title
+ * @param firstLabel Label of first input
+ * @param secondLabel Label of second input
+ * @param firstValue Default value for first input
+ * @param secondValue Default value for second input
+ * @return Entered values. (Empty optional if the dialog has been closed/canceled.)
+ */
+ public static Optional> createTextPairDialog(
+ String title,
+ String firstLabel,
+ String secondLabel,
+ String firstValue,
+ String secondValue) {
+ var dialog = new Dialog>();
+ dialog.setTitle(title);
+ dialog.setHeaderText(title);
+
+ ((Stage) dialog.getDialogPane().getScene().getWindow()).getIcons().add(defaultIcon);
+
+ dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
+
+ var keyLabel = new Label(firstLabel);
+ var keyInput = new TextField(firstValue);
+ keyInput.setMaxWidth(Double.MAX_VALUE);
+
+ var valueLabel = new Label(secondLabel);
+ var valueInput = new TextField(secondValue);
+ valueInput.setMaxWidth(Double.MAX_VALUE);
+
+ var grid = new GridPane();
+ grid.setMaxWidth(Double.MAX_VALUE);
+ grid.setHgap(10);
+ grid.setVgap(10);
+ grid.setPadding(new Insets(20, 150, 10, 10));
+
+ grid.add(keyLabel, 0, 0);
+ grid.add(keyInput, 1, 0);
+ GridPane.setHgrow(keyInput, Priority.ALWAYS);
+
+ grid.add(valueLabel, 0, 1);
+ grid.add(valueInput, 1, 1);
+ GridPane.setHgrow(valueInput, Priority.ALWAYS);
+
+ dialog.getDialogPane().setContent(grid);
+
+ dialog.setResultConverter(buttonType -> {
+ if (buttonType == ButtonType.OK) {
+ return new Pair<>(keyInput.getText(), valueInput.getText());
+ }
+ return null;
+ });
+
+ return dialog.showAndWait();
+ }
+
+ private Dialogs() {}
+}
diff --git a/vucsa-client/src/main/java/com/warxim/vucsa/client/util/GuiUtils.java b/vucsa-client/src/main/java/com/warxim/vucsa/client/util/GuiUtils.java
new file mode 100644
index 0000000..a93e6ea
--- /dev/null
+++ b/vucsa-client/src/main/java/com/warxim/vucsa/client/util/GuiUtils.java
@@ -0,0 +1,60 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.client.util;
+
+import javafx.scene.Node;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.control.Tab;
+import javafx.scene.control.TabPane;
+
+/**
+ * GUI utils.
+ */
+public final class GuiUtils {
+ private GuiUtils() {
+ }
+
+ /**
+ * Adds tab(node) to specified tab pane using the specified order.
+ * (Wraps the node to a scroll pane, creates new tab and adds it to the tabPane.)
+ * @param tabPane Tab pane to which to add the tab
+ * @param title Text of the tab title
+ * @param node Content node, which will be a content of the tab
+ * @param order Order to use when adding the tab
+ * @return Created tab
+ */
+ public static Tab addTabToTabPane(TabPane tabPane, String title, Node node, Integer order) {
+ var scrollPane = new ScrollPane(node);
+
+ scrollPane.setFitToHeight(true);
+ scrollPane.setFitToWidth(true);
+ var tab = new Tab(title, scrollPane);
+ tab.setUserData(order);
+
+ var tabs = tabPane.getTabs();
+ var index = 0;
+ for (; index < tabs.size(); ++index) {
+ var currentOrder = tabs.get(index).getUserData();
+ if (currentOrder == null || (Integer) currentOrder > order) {
+ break;
+ }
+ }
+ tabPane.getTabs().add(index, tab);
+ return tab;
+ }
+
+}
diff --git a/vucsa-client/src/main/resources/css/Main.css b/vucsa-client/src/main/resources/css/Main.css
new file mode 100644
index 0000000..dda8ff1
--- /dev/null
+++ b/vucsa-client/src/main/resources/css/Main.css
@@ -0,0 +1,79 @@
+{
+ -fx-font-size: 12px;
+ -fx-color-background-light: #fff;
+ -fx-color-text-primary: #000;
+ -fx-fill: -fx-color-text-primary;
+}
+
+.h1,
+.h1 .text {
+ -fx-font-size: 15px;
+ -fx-font-weight: 700;
+}
+
+.h2,
+.h2 .text {
+ -fx-font-size: 14px;
+ -fx-font-weight: 700;
+}
+
+.h3,
+.h3 .text {
+ -fx-font-size: 13px;
+ -fx-font-weight: 700;
+}
+
+.input-label {
+ -fx-font-weight: 700;
+}
+
+
+/*
+ LOG FLOW
+*/
+
+.log-flow {
+ -fx-padding: 5px;
+ -fx-border-style: solid;
+ -fx-border-width: 1;
+ -fx-background-color: -fx-color-background-light;
+}
+
+.log-flow .log-record:info {
+ -fx-fill: -fx-color-text-primary;
+}
+
+.log-flow .log-record:severe {
+ -fx-fill: #a93226;
+}
+
+.log-flow .log-record:warning {
+ -fx-fill: #CA6F1E;
+}
+
+.log-flow .log-record:fine {
+ -fx-fill: #229954;
+}
+
+.log-flow .log-record:other {
+ -fx-fill: #344051;
+}
+
+.log-flow .log-record:config {
+ -fx-fill: #2471A3;
+}
+
+
+/*
+ STATUS LABEL
+*/
+
+.status-connected,
+.status-connected .text {
+ -fx-fill: #048b04;
+}
+
+.status-disconnected,
+.status-disconnected .text {
+ -fx-fill: #970202;
+}
\ No newline at end of file
diff --git a/vucsa-client/src/main/resources/fxml/Application.fxml b/vucsa-client/src/main/resources/fxml/Application.fxml
new file mode 100644
index 0000000..fa4db21
--- /dev/null
+++ b/vucsa-client/src/main/resources/fxml/Application.fxml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vucsa-client/src/main/resources/fxml/challenge/bufferoverread/BufferOverreadTab.fxml b/vucsa-client/src/main/resources/fxml/challenge/bufferoverread/BufferOverreadTab.fxml
new file mode 100644
index 0000000..7a6fe7e
--- /dev/null
+++ b/vucsa-client/src/main/resources/fxml/challenge/bufferoverread/BufferOverreadTab.fxml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vucsa-client/src/main/resources/fxml/challenge/commandexecution/CommandExecutionTab.fxml b/vucsa-client/src/main/resources/fxml/challenge/commandexecution/CommandExecutionTab.fxml
new file mode 100644
index 0000000..c644d13
--- /dev/null
+++ b/vucsa-client/src/main/resources/fxml/challenge/commandexecution/CommandExecutionTab.fxml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vucsa-client/src/main/resources/fxml/challenge/enumeration/EnumerationTab.fxml b/vucsa-client/src/main/resources/fxml/challenge/enumeration/EnumerationTab.fxml
new file mode 100644
index 0000000..6846f10
--- /dev/null
+++ b/vucsa-client/src/main/resources/fxml/challenge/enumeration/EnumerationTab.fxml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vucsa-client/src/main/resources/fxml/challenge/horizontalaccesscontrol/HorizontalAccessControlTab.fxml b/vucsa-client/src/main/resources/fxml/challenge/horizontalaccesscontrol/HorizontalAccessControlTab.fxml
new file mode 100644
index 0000000..c97c3a4
--- /dev/null
+++ b/vucsa-client/src/main/resources/fxml/challenge/horizontalaccesscontrol/HorizontalAccessControlTab.fxml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vucsa-client/src/main/resources/fxml/challenge/sqlinjection/SqlInjectionTab.fxml b/vucsa-client/src/main/resources/fxml/challenge/sqlinjection/SqlInjectionTab.fxml
new file mode 100644
index 0000000..f3174d1
--- /dev/null
+++ b/vucsa-client/src/main/resources/fxml/challenge/sqlinjection/SqlInjectionTab.fxml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vucsa-client/src/main/resources/fxml/challenge/verticalaccesscontrol/VerticalAccessControlTab.fxml b/vucsa-client/src/main/resources/fxml/challenge/verticalaccesscontrol/VerticalAccessControlTab.fxml
new file mode 100644
index 0000000..f745662
--- /dev/null
+++ b/vucsa-client/src/main/resources/fxml/challenge/verticalaccesscontrol/VerticalAccessControlTab.fxml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vucsa-client/src/main/resources/fxml/challenge/xml/XmlTab.fxml b/vucsa-client/src/main/resources/fxml/challenge/xml/XmlTab.fxml
new file mode 100644
index 0000000..4a4f7f9
--- /dev/null
+++ b/vucsa-client/src/main/resources/fxml/challenge/xml/XmlTab.fxml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vucsa-client/src/main/resources/fxml/tab/LogTab.fxml b/vucsa-client/src/main/resources/fxml/tab/LogTab.fxml
new file mode 100644
index 0000000..7da4469
--- /dev/null
+++ b/vucsa-client/src/main/resources/fxml/tab/LogTab.fxml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vucsa-client/src/main/resources/fxml/tab/SettingsTab.fxml b/vucsa-client/src/main/resources/fxml/tab/SettingsTab.fxml
new file mode 100644
index 0000000..20316ae
--- /dev/null
+++ b/vucsa-client/src/main/resources/fxml/tab/SettingsTab.fxml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vucsa-client/src/main/resources/img/Logo.png b/vucsa-client/src/main/resources/img/Logo.png
new file mode 100644
index 0000000..9fa5599
Binary files /dev/null and b/vucsa-client/src/main/resources/img/Logo.png differ
diff --git a/vucsa-common/build.gradle b/vucsa-common/build.gradle
new file mode 100644
index 0000000..88adb1f
--- /dev/null
+++ b/vucsa-common/build.gradle
@@ -0,0 +1,24 @@
+plugins {
+ id 'java'
+}
+
+group 'com.warxim'
+version '1.0'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ compileOnly 'org.projectlombok:lombok:1.18.24'
+ annotationProcessor 'org.projectlombok:lombok:1.18.24'
+ implementation 'com.google.code.gson:gson:2.9.0'
+
+ testImplementation 'org.testng:testng:7.6.0'
+ testImplementation 'org.assertj:assertj-core:3.23.1'
+ testImplementation 'org.mockito:mockito-inline:4.6.1'
+}
+
+test {
+ useTestNG()
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/ChallengeConstant.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/ChallengeConstant.java
new file mode 100644
index 0000000..977e9ba
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/ChallengeConstant.java
@@ -0,0 +1,35 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common;
+
+/**
+ * Constants for challenges.
+ */
+public final class ChallengeConstant {
+ public static final int BUFFER_OVERREAD_TARGET = 1001;
+ public static final int SQL_INJECTION_TARGET = 1002;
+ public static final int ENUMERATION_TARGET = 1003;
+ public static final int COMMAND_EXECUTION_TARGET = 1004;
+ public static final int XML_TARGET = 1005;
+ public static final int VERTICAL_ACCESS_CONTROL_USER_INFO_TARGET = 1006;
+ public static final int VERTICAL_ACCESS_CONTROL_SECRET_TARGET = 1007;
+ public static final int HORIZONTAL_ACCESS_CONTROL_DOCUMENT_CONTENT_TARGET = 1008;
+
+ public static final String CHALLENGES_DIRECTORY = "server/challenge/";
+
+ private ChallengeConstant() {}
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/Constant.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/Constant.java
new file mode 100644
index 0000000..d630acf
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/Constant.java
@@ -0,0 +1,32 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common;
+
+/**
+ * Global constants.
+ */
+public final class Constant {
+ public static final String VERSION = "1.0.0";
+ public static final String WEB = "http://vucsa.warxim.com";
+
+ public static final String DEFAULT_SERVER_HOST = "127.0.0.1";
+ public static final int DEFAULT_SERVER_PORT = 8765;
+
+ public static final String SERVER_CONFIG_PATH = "server.json";
+
+ private Constant() {}
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/connection/Connection.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/connection/Connection.java
new file mode 100644
index 0000000..75f5278
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/connection/Connection.java
@@ -0,0 +1,225 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.connection;
+
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.connection.listener.ConnectionListener;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageQueue;
+import com.warxim.vucsa.common.util.MessageUtils;
+import lombok.RequiredArgsConstructor;
+
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Connection representing single connection between client and server.
+ *
Implementation has to set socket.
+ */
+@RequiredArgsConstructor
+public abstract class Connection {
+ /**
+ * Connection identifier.
+ */
+ protected final int id;
+
+ /**
+ * Connection listener for reporting connection start/stop events.
+ */
+ protected final ConnectionListener listener;
+
+ /**
+ * Message handler for handling messages, which the connection read from the input stream.
+ */
+ protected final MessageHandler messageHandler;
+
+ /**
+ * Executor service for running read and write threads.
+ */
+ protected final ExecutorService executor = Executors.newFixedThreadPool(2);
+
+ /**
+ * Flag determining if the connection is already in closing state or not.
+ */
+ protected final AtomicBoolean closing = new AtomicBoolean(false);
+
+ /**
+ * Queue for message, which the connection will send using the output stream.
+ */
+ protected final MessageQueue outgoingQueue = new MessageQueue();
+
+ /**
+ * Connection socket, which has to be provided by the implementation.
+ */
+ protected Socket socket;
+
+ /**
+ * Connection state.
+ */
+ protected ConnectionState state;
+
+ /**
+ * Starts the connection.
+ *
If the start fails, it is automatically stopped.
+ */
+ public void start() {
+ Logger.getGlobal().info("Starting connection...");
+ state = ConnectionState.STARTING;
+ if (!handleBeforeStart()) {
+ stop();
+ }
+
+ executor.execute(this::doRead);
+ executor.execute(this::doWrite);
+ executor.execute(this::stop);
+
+ if (!handleAfterStart()) {
+ stop();
+ }
+ state = ConnectionState.STARTED;
+ Logger.getGlobal().info("Connection started.");
+
+ listener.onConnectionStart(this);
+ }
+
+ /**
+ * Stops the connection.
+ */
+ public void stop() {
+ if (!closing.compareAndSet(false, true)) {
+ return;
+ }
+
+ Logger.getGlobal().info("Stopping connection...");
+ state = ConnectionState.STOPPING;
+ handleBeforeStop();
+
+ executor.shutdownNow();
+ if (socket != null) {
+ try {
+ socket.close();
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not close connection socket.", e);
+ }
+ }
+
+ state = ConnectionState.STOPPED;
+ handleAfterStop();
+ Logger.getGlobal().info("Connection stopped.");
+
+ listener.onConnectionStop(this);
+ }
+
+ /**
+ * Sends message using the socket.
+ * @param message Message to be sent
+ */
+ public void sendMessage(Message message) {
+ this.outgoingQueue.add(message);
+ }
+
+ /**
+ * Obtains connection state.
+ * @return Connection state
+ */
+ public ConnectionState getState() {
+ return state;
+ }
+
+ /**
+ * Obtains connection identifier.
+ * @return Connection identifier
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Runs before the connection starts.
+ * @return {@code true} if everything went well; {@code false} if the connection should be stopped
+ */
+ protected boolean handleBeforeStart() {
+ return true;
+ }
+
+ /**
+ * Runs after the connection starts.
+ * @return {@code true} if everything went well; {@code false} if the connection should be stopped
+ */
+ protected boolean handleAfterStart() {
+ return true;
+ }
+
+ /**
+ * Runs before the connection stops.
+ */
+ protected void handleBeforeStop() {}
+
+ /**
+ * Runs after the connection stops.
+ */
+ protected void handleAfterStop() {}
+
+ /**
+ * Reads messages from input stream and sends them to the handler.
+ */
+ private void doRead() {
+ try (var in = new DataInputStream(socket.getInputStream())) {
+ while (!closing.get()) {
+ var maybeMessage = MessageUtils.readMessageFromInputStream(in);
+ if (maybeMessage.isEmpty()) {
+ continue;
+ }
+ var message = maybeMessage.get();
+ if (messageHandler.supports(message)) {
+ messageHandler.handleMessage(this, message);
+ }
+ }
+ } catch (SocketException | EOFException e) {
+ // Connection closed
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "IO exception occurred durring connection read.", e);
+ }
+ }
+
+ /**
+ * Gets messages from outgoing queue and sends them using output stream.
+ */
+ private void doWrite() {
+ try (var out = socket.getOutputStream()) {
+ Message message;
+ while (!closing.get() && (message = outgoingQueue.take()) != null) {
+ MessageUtils.writeMessageToOutputStream(message, out);
+ }
+ } catch (SocketException e) {
+ // Connection closed
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "IO exception occurred durring connection write.", e);
+ } catch (InterruptedException e) {
+ // Interrupted
+ Thread.currentThread().interrupt();
+ }
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/connection/ConnectionState.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/connection/ConnectionState.java
new file mode 100644
index 0000000..7e29e6b
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/connection/ConnectionState.java
@@ -0,0 +1,39 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.connection;
+
+/**
+ * State of connection.
+ */
+public enum ConnectionState {
+ /**
+ * Connection is starting
+ */
+ STARTING,
+ /**
+ * Connection is running
+ */
+ STARTED,
+ /**
+ * Connection is stopping
+ */
+ STOPPING,
+ /**
+ * Connection is offline
+ */
+ STOPPED
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/connection/listener/ConnectionListener.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/connection/listener/ConnectionListener.java
new file mode 100644
index 0000000..0889fa7
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/connection/listener/ConnectionListener.java
@@ -0,0 +1,39 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.connection.listener;
+
+import com.warxim.vucsa.common.connection.Connection;
+
+/**
+ * ConnectionListener allows code to listen for connection start/stop events.
+ *
+ * All event handlers should be called from ConnectionManager.
+ *
+ */
+public interface ConnectionListener {
+ /**
+ * Event for connection start.
+ * @param connection Connection that started
+ */
+ default void onConnectionStart(Connection connection) {}
+
+ /**
+ * Event for connection stop.
+ * @param connection Connection that stopped
+ */
+ default void onConnectionStop(Connection connection) {}
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/connection/listener/ConnectionListenerManager.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/connection/listener/ConnectionListenerManager.java
new file mode 100644
index 0000000..c9818bd
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/connection/listener/ConnectionListenerManager.java
@@ -0,0 +1,36 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.connection.listener;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.listener.ListenerManager;
+
+/**
+ * Listener manager that allows modules to register their own listener (aggregates listeners).
+ *
Based on {@link ListenerManager}
+ */
+public final class ConnectionListenerManager extends ListenerManager implements ConnectionListener {
+ @Override
+ public void onConnectionStart(Connection connection) {
+ parallelCall(listener -> listener.onConnectionStart(connection));
+ }
+
+ @Override
+ public void onConnectionStop(Connection connection) {
+ parallelCall(listener -> listener.onConnectionStop(connection));
+ }
+}
\ No newline at end of file
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/listener/ListenerManager.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/listener/ListenerManager.java
new file mode 100644
index 0000000..f8e3e7c
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/listener/ListenerManager.java
@@ -0,0 +1,102 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.listener;
+
+import java.lang.ref.WeakReference;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Consumer;
+
+/**
+ * Listener Manager for managing multiple listeners.
+ *
+ * Uses WeakReference, so that the listener resources are automatically freed,
+ * when the reference becomes weakly reachable.
+ * (To prevent leaks caused by forgotten unregister call.)
+ *
+ *
+ * Listeners have to be stored as strong reference.
+ *
+ */
+public class ListenerManager {
+ protected final CopyOnWriteArrayList> listeners;
+
+ public ListenerManager() {
+ listeners = new CopyOnWriteArrayList<>();
+ }
+
+ /**
+ * Register listener
+ *
Stores weak reference to the listener.
+ * @param listener Listener to be registered
+ */
+ public void registerListener(L listener) {
+ listeners.add(new WeakReference<>(listener));
+ }
+
+ /**
+ * Unregister listener
+ *
Removes listener weak reference from the manager.
+ * @param listener Listener to be unregistered
+ */
+ public void unregisterListener(L listener) {
+ listeners.removeIf(reference -> listener.equals(reference.get()));
+ }
+
+ /**
+ * Call the specified consumer for all listeners
+ *
+ * Calls {@link Consumer#accept(Object)} for each listener (listener as a parameter).
+ *
+ * @param consumer Consumer for handling the listener call
+ */
+ protected void call(Consumer consumer) {
+ listeners.forEach(reference -> callListener(reference, consumer));
+ }
+
+ /**
+ * Call the specified consumer for all listeners in parallel
+ *
+ * Calls {@link Consumer#accept(Object)} for each listener (listener as a parameter) using parallel stream.
+ *
+ * @param consumer Consumer for handling the listener call
+ */
+ protected void parallelCall(Consumer consumer) {
+ listeners.parallelStream().forEach(reference -> callListener(reference, consumer));
+ }
+
+ /**
+ * Removes all listeners.
+ */
+ public void clear() {
+ listeners.clear();
+ }
+
+ /**
+ * Call the consumer with the listener as parameter (if it is still referenced)
+ *
Removes the listener reference from listeners, if it does not exist.
+ * @param reference Listener reference
+ * @param consumer Consumer for handling the listener call
+ */
+ private void callListener(WeakReference reference, Consumer consumer) {
+ var listener = reference.get();
+ if (listener == null) {
+ listeners.remove(reference);
+ return;
+ }
+ consumer.accept(listener);
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/Message.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/Message.java
new file mode 100644
index 0000000..c0a27be
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/Message.java
@@ -0,0 +1,43 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Message base class.
+ *
+ * Message is a protocol data unit in vulnerable application.
+ *
+ */
+@EqualsAndHashCode
+@Getter
+@RequiredArgsConstructor
+public abstract class Message {
+ /**
+ * Identifier of target handler.
+ */
+ private final int target;
+
+ /**
+ * Obtains type of the message.
+ * @return Message type
+ */
+ public abstract MessageType getType();
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageDeserializer.java
new file mode 100644
index 0000000..70ff12a
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageDeserializer.java
@@ -0,0 +1,31 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message;
+
+import java.util.Optional;
+
+/**
+ * Message deserializer for deserializing bytes into specific message object.
+ */
+public interface MessageDeserializer {
+ /**
+ * Deserializes serialized message into specific message object.
+ * @param serializedMessage Serialized message to be deserialized
+ * @return Message or empty optional if the deserialization failed
+ */
+ Optional deserializeMessage(SerializedMessage serializedMessage);
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageHandler.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageHandler.java
new file mode 100644
index 0000000..2550224
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageHandler.java
@@ -0,0 +1,40 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message;
+
+import com.warxim.vucsa.common.connection.Connection;
+
+/**
+ * Endpoint for handling messages.
+ *
Represents "endpoint" for messages.
+ */
+public interface MessageHandler {
+ /**
+ * Checks whether the given message is supported by the handler.
+ * @param message Message to be checked
+ * @return {@code true} if the message is supported
+ */
+ boolean supports(Message message);
+
+ /**
+ * Handles message in the handler
+ * @param connection Connection, which sent the message
+ * @param message Message to be handled
+ * @return {@code true} if the message has been correctly handled
+ */
+ boolean handleMessage(Connection connection, Message message);
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageHandlerManager.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageHandlerManager.java
new file mode 100644
index 0000000..e241f00
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageHandlerManager.java
@@ -0,0 +1,73 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message;
+
+import com.warxim.vucsa.common.connection.Connection;
+import lombok.RequiredArgsConstructor;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Logger;
+
+/**
+ * Message handler manager aggregates message managers registered for specific target identifiers.
+ */
+@RequiredArgsConstructor
+public class MessageHandlerManager implements MessageHandler {
+ /**
+ * Handlers registered for certain message target.
+ */
+ private final ConcurrentHashMap handlers = new ConcurrentHashMap<>();
+
+ /**
+ * Registers message handler.
+ * @param target Target identifier of the handler
+ * @param messageHandler Handler to be registered
+ */
+ public void registerHandler(int target, MessageHandler messageHandler) {
+ this.handlers.putIfAbsent(target, messageHandler);
+ }
+
+ /**
+ * Unregisters message handler.
+ * @param target Target identifier of the handler
+ */
+ public void unregisterHandler(int target) {
+ this.handlers.remove(target);
+ }
+
+ @Override
+ public boolean supports(Message message) {
+ return true;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ var target = message.getTarget();
+ var handler = this.handlers.get(target);
+ if (handler == null) {
+ Logger.getGlobal().severe(() -> String.format("No handler found with id [%d]...", target));
+ return false;
+ }
+
+ if (!handler.supports(message)) {
+ Logger.getGlobal().severe(() -> String.format("Handler [%d] does not support message! Ignoring message...", target));
+ return false;
+ }
+
+ return handler.handleMessage(connection, message);
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageQueue.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageQueue.java
new file mode 100644
index 0000000..1bc0a9e
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageQueue.java
@@ -0,0 +1,79 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message;
+
+import java.util.Optional;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * Queue of messages.
+ */
+public class MessageQueue {
+ private final BlockingQueue queue;
+
+ public MessageQueue() {
+ queue = new LinkedBlockingQueue<>();
+ }
+
+ /**
+ * Add message to queue.
+ * @param message Message to be added to the queue
+ */
+ public void add(Message message) {
+ queue.add(message);
+ }
+
+ /**
+ * Returns message from queue (blocks until there is message).
+ * @return Message from queue
+ */
+ public Message take() throws InterruptedException {
+ return queue.take();
+ }
+
+ /**
+ * Retrieves and removes the head of the queue.
+ * @return Message from queue or empty optional if the queue is empty
+ */
+ public Optional poll() {
+ return Optional.ofNullable(queue.poll());
+ }
+
+ /**
+ * Get queue size.
+ * @return Size of the queue
+ */
+ public int size() {
+ return queue.size();
+ }
+
+ /**
+ * Clears queue.
+ */
+ public void clear() {
+ queue.clear();
+ }
+
+ /**
+ * Checks if the queue is empty.
+ * @return {@code true} if the queue is empty
+ */
+ public boolean isEmpty() {
+ return queue.isEmpty();
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageSerializer.java
new file mode 100644
index 0000000..0070b13
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageSerializer.java
@@ -0,0 +1,31 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message;
+
+import java.util.Optional;
+
+/**
+ * Message serializer for serializing message into bytes.
+ */
+public interface MessageSerializer {
+ /**
+ * Serializes message into deserialized message.
+ * @param message Message to be serialized
+ * @return Serialized message or empty optional if the serialization failed
+ */
+ Optional serializeMessage(Message message);
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageType.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageType.java
new file mode 100644
index 0000000..fbf3f31
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/MessageType.java
@@ -0,0 +1,115 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message;
+
+import com.warxim.vucsa.common.message.commandexecution.request.PingRequestDeserializer;
+import com.warxim.vucsa.common.message.commandexecution.response.PingResponseDeserializer;
+import com.warxim.vucsa.common.message.commandexecution.response.PingResponseSerializer;
+import com.warxim.vucsa.common.message.horizontalaccesscontrol.request.DocumentContentRequest;
+import com.warxim.vucsa.common.message.horizontalaccesscontrol.response.DocumentContentResponse;
+import com.warxim.vucsa.common.message.sqlinjection.response.SearchResponseDeserializer;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.request.*;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.response.*;
+import com.warxim.vucsa.common.message.bufferoverread.StringListMessageDeserializer;
+import com.warxim.vucsa.common.message.bufferoverread.StringListMessageSerializer;
+import com.warxim.vucsa.common.message.bufferoverread.StringListMessage;
+import com.warxim.vucsa.common.message.commandexecution.request.PingRequest;
+import com.warxim.vucsa.common.message.commandexecution.request.PingRequestSerializer;
+import com.warxim.vucsa.common.message.commandexecution.response.PingResponse;
+import com.warxim.vucsa.common.message.enumeration.request.LoginRequest;
+import com.warxim.vucsa.common.message.enumeration.request.LoginRequestDeserializer;
+import com.warxim.vucsa.common.message.enumeration.request.LoginRequestSerializer;
+import com.warxim.vucsa.common.message.enumeration.response.LoginResponse;
+import com.warxim.vucsa.common.message.enumeration.response.LoginResponseDeserializer;
+import com.warxim.vucsa.common.message.enumeration.response.LoginResponseSerializer;
+import com.warxim.vucsa.common.message.horizontalaccesscontrol.request.DocumentContentRequestDeserializer;
+import com.warxim.vucsa.common.message.horizontalaccesscontrol.request.DocumentContentRequestSerializer;
+import com.warxim.vucsa.common.message.horizontalaccesscontrol.response.DocumentContentResponseDeserializer;
+import com.warxim.vucsa.common.message.horizontalaccesscontrol.response.DocumentContentResponseSerializer;
+import com.warxim.vucsa.common.message.plain.PlainMessage;
+import com.warxim.vucsa.common.message.plain.PlainMessageDeserializer;
+import com.warxim.vucsa.common.message.plain.PlainMessageSerializer;
+import com.warxim.vucsa.common.message.sqlinjection.request.SearchRequest;
+import com.warxim.vucsa.common.message.sqlinjection.request.SearchRequestDeserializer;
+import com.warxim.vucsa.common.message.sqlinjection.request.SearchRequestSerializer;
+import com.warxim.vucsa.common.message.sqlinjection.response.SearchResponse;
+import com.warxim.vucsa.common.message.sqlinjection.response.SearchResponseSerializer;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.request.*;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.response.*;
+import com.warxim.vucsa.common.message.xml.StorageMessage;
+import com.warxim.vucsa.common.message.xml.StorageMessageDeserializer;
+import com.warxim.vucsa.common.message.xml.StorageMessageSerializer;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Message type.
+ */
+@Getter
+@RequiredArgsConstructor
+public enum MessageType {
+ PLAIN(1, PlainMessage.class, new PlainMessageSerializer(), new PlainMessageDeserializer()),
+ BUFFER_OVERREAD_STRING_LIST_MESSAGE(2, StringListMessage.class, new StringListMessageSerializer(), new StringListMessageDeserializer()),
+ SQL_INJECTION_SEARCH_REQUEST(3, SearchRequest.class, new SearchRequestSerializer(), new SearchRequestDeserializer()),
+ SQL_INJECTION_SEARCH_RESPONSE(4, SearchResponse.class, new SearchResponseSerializer(), new SearchResponseDeserializer()),
+ ENUMERATION_CHALLENGE_LOGIN_REQUEST(5, LoginRequest.class, new LoginRequestSerializer(), new LoginRequestDeserializer()),
+ ENUMERATION_CHALLENGE_LOGIN_RESPONSE(6, LoginResponse.class, new LoginResponseSerializer(), new LoginResponseDeserializer()),
+ COMMAND_EXECUTION_PING_REQUEST(7, PingRequest.class, new PingRequestSerializer(), new PingRequestDeserializer()),
+ COMMAND_EXECUTION_PING_RESPONSE(8, PingResponse.class, new PingResponseSerializer(), new PingResponseDeserializer()),
+ XML_STORAGE_MESSAGE(9, StorageMessage.class, new StorageMessageSerializer(), new StorageMessageDeserializer()),
+ VERTICAL_ACCESS_CONTROL_USER_INFO_REQUEST(10, UserInfoRequest.class, new UserInfoRequestSerializer(), new UserInfoRequestDeserializer()),
+ VERTICAL_ACCESS_CONTROL_USER_INFO_RESPONSE(11, UserInfoResponse.class, new UserInfoResponseSerializer(), new UserInfoResponseDeserializer()),
+ VERTICAL_ACCESS_CONTROL_SECRET_REQUEST(12, SecretRequest.class, new SecretRequestSerializer(), new SecretRequestDeserializer()),
+ VERTICAL_ACCESS_CONTROL_SECRET_RESPONSE(13, SecretResponse.class, new SecretResponseSerializer(), new SecretResponseDeserializer()),
+ HORIZONTAL_ACCESS_CONTROL_DOCUMENT_CONTENT_REQUEST(14, DocumentContentRequest.class, new DocumentContentRequestSerializer(), new DocumentContentRequestDeserializer()),
+ HORIZONTAL_ACCESS_CONTROL_DOCUMENT_CONTENT_RESPONSE(15, DocumentContentResponse.class, new DocumentContentResponseSerializer(), new DocumentContentResponseDeserializer()),
+ ;
+
+ /**
+ * Serialized value of message type (unique).
+ */
+ private final int value;
+
+ /**
+ * Class representing the message.
+ */
+ private final Class extends Message> clazz;
+
+ /**
+ * Serializer for serializing given message type.
+ */
+ private final MessageSerializer serializer;
+
+ /**
+ * Deserializer for deserializing given message type.
+ */
+ private final MessageDeserializer deserializer;
+
+ /**
+ * Converts serialized message type to enum message type.
+ * @return Message type or empty optional if message for given type was not found
+ */
+ public static Optional of(int value) {
+ return Arrays.stream(values())
+ .filter(type -> type.getValue() == value)
+ .findAny();
+ }
+
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/SerializedMessage.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/SerializedMessage.java
new file mode 100644
index 0000000..74f5bb5
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/SerializedMessage.java
@@ -0,0 +1,47 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message;
+
+import lombok.Builder;
+import lombok.Value;
+
+/**
+ * Serialized message used for transmitting the message over network.
+ */
+@Builder
+@Value
+public class SerializedMessage {
+ /**
+ * Type of the message
+ */
+ MessageType type;
+
+ /**
+ * Target identifier of target handler
+ */
+ int target;
+
+ /**
+ * Length of the payload
+ */
+ int length;
+
+ /**
+ * Payload length
+ */
+ byte[] payload;
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/bufferoverread/StringListMessage.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/bufferoverread/StringListMessage.java
new file mode 100644
index 0000000..55e475e
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/bufferoverread/StringListMessage.java
@@ -0,0 +1,49 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.bufferoverread;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageType;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Message for buffer over-read challenge containing list of items.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class StringListMessage extends Message {
+ /**
+ * List of strings for buffer overread challenge.
+ */
+ List items;
+
+ @Builder
+ public StringListMessage(int target, List items) {
+ super(target);
+ this.items = Collections.unmodifiableList(items);
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.BUFFER_OVERREAD_STRING_LIST_MESSAGE;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/bufferoverread/StringListMessageDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/bufferoverread/StringListMessageDeserializer.java
new file mode 100644
index 0000000..a7020c3
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/bufferoverread/StringListMessageDeserializer.java
@@ -0,0 +1,99 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.bufferoverread;
+
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.Optional;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Pseudo-vulnerable message deserializer for {@link StringListMessage}.
+ */
+public class StringListMessageDeserializer implements MessageDeserializer {
+ private static final int RANDOM_DATA_LENGTH = 64;
+ private static final String SECRET_DATA = "Congratulations, you have successfully exploited buffer over-read!";
+
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ var payload = serializedMessage.getPayload();
+ var length = serializedMessage.getLength();
+ var items = new LinkedList();
+ var in = new DataInputStream(new ByteArrayInputStream(payload));
+
+ try {
+ var read = 0;
+ while (length > read) {
+ var itemLength = in.readInt();
+ read += 4;
+
+ var buffer = new byte[itemLength];
+ if (itemLength > (length - read)) {
+ // Simulate read of fake memory
+ var fakeMemory = generateFakeMemory();
+
+ // Read as many bytes as possible
+ int actualLength = in.read(buffer);
+
+ // Calculate remaining length (missing bytes)
+ int remainingLength = itemLength - actualLength;
+
+ // Fill in the buffer using fake memory
+ System.arraycopy(fakeMemory, 0, buffer, actualLength, Math.min(remainingLength, fakeMemory.length));
+ } else {
+ in.readFully(buffer);
+ }
+ read += itemLength;
+
+ items.add(new String(buffer));
+ }
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "IO exception occurred during read of payload.");
+ }
+
+ return Optional.of(StringListMessage.builder()
+ .target(serializedMessage.getTarget())
+ .items(items)
+ .build());
+ }
+
+ /**
+ * Generates fake memory content bytes.
+ */
+ private byte[] generateFakeMemory() {
+ var buffer = ByteBuffer.allocate(RANDOM_DATA_LENGTH + SECRET_DATA.getBytes().length + RANDOM_DATA_LENGTH);
+ var bytes = new byte[RANDOM_DATA_LENGTH];
+ ThreadLocalRandom.current().nextBytes(bytes);
+ buffer.put(bytes);
+
+ buffer.put(SECRET_DATA.getBytes());
+
+ ThreadLocalRandom.current().nextBytes(bytes);
+ buffer.put(bytes);
+
+ return buffer.array();
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/bufferoverread/StringListMessageSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/bufferoverread/StringListMessageSerializer.java
new file mode 100644
index 0000000..998912b
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/bufferoverread/StringListMessageSerializer.java
@@ -0,0 +1,65 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.bufferoverread;
+
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+
+import java.nio.ByteBuffer;
+import java.util.Optional;
+
+/**
+ * Serializer for {@link StringListMessage}.
+ *
+ */
+public class StringListMessageSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof StringListMessage)) {
+ return Optional.empty();
+ }
+
+ var stringListMessage = (StringListMessage) message;
+ var items = stringListMessage.getItems();
+
+ // Calculate size of the buffer
+ var size = 0;
+ for (var item : items) {
+ var bytes = item.getBytes();
+ size += bytes.length;
+ size += 4;
+ }
+
+ // Generate the buffer
+ var buffer = ByteBuffer.allocate(size);
+ for (var item : items) {
+ var bytes = item.getBytes();
+ buffer.putInt(bytes.length);
+ buffer.put(bytes);
+ }
+
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(size)
+ .payload(buffer.array())
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/request/PingRequest.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/request/PingRequest.java
new file mode 100644
index 0000000..0920b5e
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/request/PingRequest.java
@@ -0,0 +1,43 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.commandexecution.request;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageType;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+/**
+ * Ping request for Command Execution challenge.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class PingRequest extends Message {
+ String host;
+
+ @Builder
+ public PingRequest(int target, String host) {
+ super(target);
+ this.host = host;
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.COMMAND_EXECUTION_PING_REQUEST;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/request/PingRequestDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/request/PingRequestDeserializer.java
new file mode 100644
index 0000000..2620cb8
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/request/PingRequestDeserializer.java
@@ -0,0 +1,38 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.commandexecution.request;
+
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+
+import java.util.Optional;
+
+/**
+ * Deserializer for {@link PingRequest}.
+ */
+public class PingRequestDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ var host = new String(serializedMessage.getPayload(), 0, serializedMessage.getLength());
+
+ return Optional.of(PingRequest.builder()
+ .target(serializedMessage.getTarget())
+ .host(host)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/request/PingRequestSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/request/PingRequestSerializer.java
new file mode 100644
index 0000000..ce50c31
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/request/PingRequestSerializer.java
@@ -0,0 +1,44 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.commandexecution.request;
+
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+
+import java.util.Optional;
+
+/**
+ * Serializer for {@link PingRequest}.
+ */
+public class PingRequestSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof PingRequest)) {
+ return Optional.empty();
+ }
+ var pingRequest = (PingRequest) message;
+ var bytes = pingRequest.getHost().getBytes();
+
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(bytes.length)
+ .payload(bytes)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/response/PingResponse.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/response/PingResponse.java
new file mode 100644
index 0000000..5a06d7a
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/response/PingResponse.java
@@ -0,0 +1,46 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.commandexecution.response;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageType;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+/**
+ * Ping response for Command Execution challenge.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class PingResponse extends Message {
+ /**
+ * Output for ping command
+ */
+ String output;
+
+ @Builder
+ public PingResponse(int target, String output) {
+ super(target);
+ this.output = output;
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.COMMAND_EXECUTION_PING_RESPONSE;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/response/PingResponseDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/response/PingResponseDeserializer.java
new file mode 100644
index 0000000..fbbdcb2
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/response/PingResponseDeserializer.java
@@ -0,0 +1,38 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.commandexecution.response;
+
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+
+import java.util.Optional;
+
+/**
+ * Deserializer for {@link PingResponse}.
+ */
+public class PingResponseDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ var output = new String(serializedMessage.getPayload(), 0, serializedMessage.getLength());
+
+ return Optional.of(PingResponse.builder()
+ .target(serializedMessage.getTarget())
+ .output(output)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/response/PingResponseSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/response/PingResponseSerializer.java
new file mode 100644
index 0000000..a8f36f5
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/commandexecution/response/PingResponseSerializer.java
@@ -0,0 +1,44 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.commandexecution.response;
+
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+
+import java.util.Optional;
+
+/**
+ * Serializer for {@link PingResponse}.
+ */
+public class PingResponseSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof PingResponse)) {
+ return Optional.empty();
+ }
+ var pingResponse = (PingResponse) message;
+ var bytes = pingResponse.getOutput().getBytes();
+
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(bytes.length)
+ .payload(bytes)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/LoginStatus.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/LoginStatus.java
new file mode 100644
index 0000000..bf3e082
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/LoginStatus.java
@@ -0,0 +1,46 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.enumeration;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Status describing login result
+ */
+@Getter
+@RequiredArgsConstructor
+public enum LoginStatus {
+ SUCCESS(1),
+ WRONG_USERNAME(2),
+ WRONG_PASSWORD(3);
+
+ private final int value;
+
+ /**
+ * Converts int value to login status.
+ * @return Login status or empty optional if the value is not representing any status
+ */
+ public static Optional of(int value) {
+ return Arrays.stream(values())
+ .filter(loginStatus -> loginStatus.value == value)
+ .findAny();
+ }
+}
\ No newline at end of file
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/request/LoginRequest.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/request/LoginRequest.java
new file mode 100644
index 0000000..00b6605
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/request/LoginRequest.java
@@ -0,0 +1,45 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.enumeration.request;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageType;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+/**
+ * Login request for Enumeration challenge.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class LoginRequest extends Message {
+ String username;
+ String password;
+
+ @Builder
+ public LoginRequest(int target, String username, String password) {
+ super(target);
+ this.username = username;
+ this.password = password;
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.ENUMERATION_CHALLENGE_LOGIN_REQUEST;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/request/LoginRequestDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/request/LoginRequestDeserializer.java
new file mode 100644
index 0000000..427134e
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/request/LoginRequestDeserializer.java
@@ -0,0 +1,45 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.enumeration.request;
+
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+
+import java.util.Optional;
+import java.util.logging.Logger;
+
+/**
+ * Deserializer for {@link LoginRequest}.
+ */
+public class LoginRequestDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ var string = new String(serializedMessage.getPayload(), 0, serializedMessage.getLength());
+ var data = string.split(":", 2);
+ if (data.length != 2) {
+ Logger.getGlobal().severe("Serialized message does not contain username and password.");
+ return Optional.empty();
+ }
+
+ return Optional.of(LoginRequest.builder()
+ .target(serializedMessage.getTarget())
+ .username(data[0])
+ .password(data[1])
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/request/LoginRequestSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/request/LoginRequestSerializer.java
new file mode 100644
index 0000000..63c070b
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/request/LoginRequestSerializer.java
@@ -0,0 +1,47 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.enumeration.request;
+
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+
+import java.util.Optional;
+
+/**
+ * Serializer for {@link LoginRequest}.
+ */
+public class LoginRequestSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof LoginRequest)) {
+ return Optional.empty();
+ }
+ var loginRequest = (LoginRequest) message;
+ var username = loginRequest.getUsername().replaceAll("[^a-zA-Z0-9-_.]","");
+ var password = loginRequest.getPassword();
+ var data = username + ':' + password;
+ var bytes = data.getBytes();
+
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(bytes.length)
+ .payload(bytes)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/response/LoginResponse.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/response/LoginResponse.java
new file mode 100644
index 0000000..72981ac
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/response/LoginResponse.java
@@ -0,0 +1,53 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.enumeration.response;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageType;
+import com.warxim.vucsa.common.message.enumeration.LoginStatus;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+/**
+ * Login response for Enumeration challenge.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class LoginResponse extends Message {
+ /**
+ * Status of user login
+ */
+ LoginStatus status;
+
+ /**
+ * User's secret (null if login failed)
+ */
+ String userSecret;
+
+ @Builder
+ public LoginResponse(int target, LoginStatus status, String userSecret) {
+ super(target);
+ this.status = status;
+ this.userSecret = userSecret;
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.ENUMERATION_CHALLENGE_LOGIN_RESPONSE;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/response/LoginResponseDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/response/LoginResponseDeserializer.java
new file mode 100644
index 0000000..4415375
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/response/LoginResponseDeserializer.java
@@ -0,0 +1,57 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.enumeration.response;
+
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+import com.warxim.vucsa.common.message.enumeration.LoginStatus;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+/**
+ * Deserializer for {@link LoginResponse}.
+ */
+public class LoginResponseDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ if (serializedMessage.getLength() < 4) {
+ Logger.getGlobal().severe("Serialized message does not contain enough bytes.");
+ return Optional.empty();
+ }
+
+ var value = ByteBuffer.wrap(serializedMessage.getPayload(), 0, 4).getInt();
+ var maybeStatus = LoginStatus.of(value);
+ if (maybeStatus.isEmpty()) {
+ Logger.getGlobal().severe("Invalid login status detected in message.");
+ return Optional.empty();
+ }
+ var status = maybeStatus.get();
+
+ var secretBytes = Arrays.copyOfRange(serializedMessage.getPayload(), 4, serializedMessage.getLength());
+ var secret = new String(secretBytes);
+
+ return Optional.of(LoginResponse.builder()
+ .target(serializedMessage.getTarget())
+ .status(status)
+ .userSecret(secret)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/response/LoginResponseSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/response/LoginResponseSerializer.java
new file mode 100644
index 0000000..5850d13
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/enumeration/response/LoginResponseSerializer.java
@@ -0,0 +1,58 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.enumeration.response;
+
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+
+import java.nio.ByteBuffer;
+import java.util.Optional;
+
+/**
+ * Serializer for {@link LoginResponse}.
+ */
+public class LoginResponseSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof LoginResponse)) {
+ return Optional.empty();
+ }
+ var loginResponse = (LoginResponse) message;
+ var value = loginResponse.getStatus().getValue();
+
+ byte[] bytes;
+ if (loginResponse.getUserSecret() == null) {
+ bytes = ByteBuffer.allocate(4)
+ .putInt(value)
+ .array();
+ } else {
+ var secretBytes = loginResponse.getUserSecret().getBytes();
+ bytes = ByteBuffer.allocate(4 + secretBytes.length)
+ .putInt(value)
+ .put(secretBytes)
+ .array();
+ }
+
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(bytes.length)
+ .payload(bytes)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/request/DocumentContentRequest.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/request/DocumentContentRequest.java
new file mode 100644
index 0000000..54ac98e
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/request/DocumentContentRequest.java
@@ -0,0 +1,43 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.horizontalaccesscontrol.request;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageType;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+/**
+ * Document content request for Horizontal Access Control challenge.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class DocumentContentRequest extends Message {
+ int documentId;
+
+ @Builder
+ public DocumentContentRequest(int target, int documentId) {
+ super(target);
+ this.documentId = documentId;
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.HORIZONTAL_ACCESS_CONTROL_DOCUMENT_CONTENT_REQUEST;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/request/DocumentContentRequestDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/request/DocumentContentRequestDeserializer.java
new file mode 100644
index 0000000..1da2fc9
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/request/DocumentContentRequestDeserializer.java
@@ -0,0 +1,44 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.horizontalaccesscontrol.request;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+
+import java.nio.ByteBuffer;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+/**
+ * Deserializer for {@link DocumentContentRequest}.
+ */
+public class DocumentContentRequestDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ if (serializedMessage.getLength() != 4) {
+ Logger.getGlobal().severe("Serialized message does not contain expected number of bytes.");
+ return Optional.empty();
+ }
+ var documentId = ByteBuffer.wrap(serializedMessage.getPayload(), 0, 4).getInt();
+
+ return Optional.of(DocumentContentRequest.builder()
+ .target(serializedMessage.getTarget())
+ .documentId(documentId)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/request/DocumentContentRequestSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/request/DocumentContentRequestSerializer.java
new file mode 100644
index 0000000..a9047c3
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/request/DocumentContentRequestSerializer.java
@@ -0,0 +1,47 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.horizontalaccesscontrol.request;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+
+import java.nio.ByteBuffer;
+import java.util.Optional;
+
+/**
+ * Serializer for {@link DocumentContentRequest}.
+ */
+public class DocumentContentRequestSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof DocumentContentRequest)) {
+ return Optional.empty();
+ }
+ var documentContentResponse = (DocumentContentRequest) message;
+ var bytes = ByteBuffer.allocate(4)
+ .putInt(documentContentResponse.getDocumentId())
+ .array();
+
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(bytes.length)
+ .payload(bytes)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/response/DocumentContentResponse.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/response/DocumentContentResponse.java
new file mode 100644
index 0000000..8f1e69a
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/response/DocumentContentResponse.java
@@ -0,0 +1,43 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.horizontalaccesscontrol.response;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageType;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+/**
+ * Document content response for Horizontal Access Control challenge.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class DocumentContentResponse extends Message {
+ String content;
+
+ @Builder
+ public DocumentContentResponse(int target, String content) {
+ super(target);
+ this.content = content;
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.HORIZONTAL_ACCESS_CONTROL_DOCUMENT_CONTENT_RESPONSE;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/response/DocumentContentResponseDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/response/DocumentContentResponseDeserializer.java
new file mode 100644
index 0000000..1803b80
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/response/DocumentContentResponseDeserializer.java
@@ -0,0 +1,38 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.horizontalaccesscontrol.response;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+
+import java.util.Optional;
+
+/**
+ * Deserializer for {@link DocumentContentResponse}.
+ */
+public class DocumentContentResponseDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ var content = new String(serializedMessage.getPayload(), 0, serializedMessage.getLength());
+
+ return Optional.of(DocumentContentResponse.builder()
+ .target(serializedMessage.getTarget())
+ .content(content)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/response/DocumentContentResponseSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/response/DocumentContentResponseSerializer.java
new file mode 100644
index 0000000..d25a543
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/horizontalaccesscontrol/response/DocumentContentResponseSerializer.java
@@ -0,0 +1,44 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.horizontalaccesscontrol.response;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+
+import java.util.Optional;
+
+/**
+ * Serializer for {@link DocumentContentResponse}.
+ */
+public class DocumentContentResponseSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof DocumentContentResponse)) {
+ return Optional.empty();
+ }
+ var documentContentResponse = (DocumentContentResponse) message;
+ var bytes = documentContentResponse.getContent().getBytes();
+
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(bytes.length)
+ .payload(bytes)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/plain/PlainMessage.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/plain/PlainMessage.java
new file mode 100644
index 0000000..6ab0831
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/plain/PlainMessage.java
@@ -0,0 +1,45 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.plain;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageType;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+/**
+ * Plain message containing byte array payload.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class PlainMessage extends Message {
+ int length;
+ byte[] payload;
+
+ @Builder
+ public PlainMessage(int target, int length, byte[] payload) {
+ super(target);
+ this.length = length;
+ this.payload = payload;
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.PLAIN;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/plain/PlainMessageDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/plain/PlainMessageDeserializer.java
new file mode 100644
index 0000000..d5f782f
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/plain/PlainMessageDeserializer.java
@@ -0,0 +1,37 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.plain;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+
+import java.util.Optional;
+
+/**
+ * Deserializer for {@link PlainMessage}.
+ */
+public class PlainMessageDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ return Optional.of(PlainMessage.builder()
+ .target(serializedMessage.getTarget())
+ .length(serializedMessage.getLength())
+ .payload(serializedMessage.getPayload())
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/plain/PlainMessageSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/plain/PlainMessageSerializer.java
new file mode 100644
index 0000000..3012683
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/plain/PlainMessageSerializer.java
@@ -0,0 +1,42 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.plain;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+
+import java.util.Optional;
+
+/**
+ * Serializer for {@link PlainMessage}.
+ */
+public class PlainMessageSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof PlainMessage)) {
+ return Optional.empty();
+ }
+ var plain = (PlainMessage) message;
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(plain.getLength())
+ .payload(plain.getPayload())
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/FoodEntity.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/FoodEntity.java
new file mode 100644
index 0000000..99482f0
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/FoodEntity.java
@@ -0,0 +1,32 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.sqlinjection;
+
+import lombok.Builder;
+import lombok.Value;
+
+/**
+ * Food entity representing result of search query.
+ */
+@Builder
+@Value
+public class FoodEntity {
+ int id;
+ String name;
+ String description;
+ double price;
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/request/SearchRequest.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/request/SearchRequest.java
new file mode 100644
index 0000000..d43e5a7
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/request/SearchRequest.java
@@ -0,0 +1,46 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.sqlinjection.request;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageType;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+/**
+ * Request in SQL Injection challenge for searching data.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class SearchRequest extends Message {
+ /**
+ * Search query
+ */
+ String search;
+
+ @Builder
+ public SearchRequest(int target, String search) {
+ super(target);
+ this.search = search;
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.SQL_INJECTION_SEARCH_REQUEST;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/request/SearchRequestDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/request/SearchRequestDeserializer.java
new file mode 100644
index 0000000..a438eab
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/request/SearchRequestDeserializer.java
@@ -0,0 +1,36 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.sqlinjection.request;
+
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+
+import java.util.Optional;
+
+/**
+ * Deserializer for {@link SearchRequest}.
+ */
+public class SearchRequestDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ return Optional.of(SearchRequest.builder()
+ .target(serializedMessage.getTarget())
+ .search(new String(serializedMessage.getPayload(), 0, serializedMessage.getLength()))
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/request/SearchRequestSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/request/SearchRequestSerializer.java
new file mode 100644
index 0000000..d41b364
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/request/SearchRequestSerializer.java
@@ -0,0 +1,43 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.sqlinjection.request;
+
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+
+import java.util.Optional;
+
+/**
+ * Serializer for {@link SearchRequest}.
+ */
+public class SearchRequestSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof SearchRequest)) {
+ return Optional.empty();
+ }
+ var searchRequest = (SearchRequest) message;
+ var bytes = searchRequest.getSearch().getBytes();
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(bytes.length)
+ .payload(bytes)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/response/SearchResponse.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/response/SearchResponse.java
new file mode 100644
index 0000000..7f26365
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/response/SearchResponse.java
@@ -0,0 +1,46 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.sqlinjection.response;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageType;
+import com.warxim.vucsa.common.message.sqlinjection.FoodEntity;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+import java.util.List;
+
+/**
+ * Response in SQL Injection challenge with list of food entities.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class SearchResponse extends Message {
+ List entities;
+
+ @Builder
+ public SearchResponse(int target, List entities) {
+ super(target);
+ this.entities = entities;
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.SQL_INJECTION_SEARCH_RESPONSE;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/response/SearchResponseDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/response/SearchResponseDeserializer.java
new file mode 100644
index 0000000..5838f2b
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/response/SearchResponseDeserializer.java
@@ -0,0 +1,45 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.sqlinjection.response;
+
+import com.google.gson.reflect.TypeToken;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+import com.warxim.vucsa.common.message.sqlinjection.FoodEntity;
+import com.warxim.vucsa.common.util.GsonUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Deserializer for {@link SearchResponse}.
+ */
+public class SearchResponseDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ var gson = GsonUtils.getGson();
+ var json = new String(serializedMessage.getPayload(), 0, serializedMessage.getLength());
+ var entitiesType = new TypeToken>() {}.getType();
+ List entities = gson.fromJson(json, entitiesType);
+ return Optional.of(SearchResponse.builder()
+ .target(serializedMessage.getTarget())
+ .entities(entities)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/response/SearchResponseSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/response/SearchResponseSerializer.java
new file mode 100644
index 0000000..0c5c4b4
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/sqlinjection/response/SearchResponseSerializer.java
@@ -0,0 +1,48 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.sqlinjection.response;
+
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.util.GsonUtils;
+
+import java.util.Optional;
+
+/**
+ * Serializer for {@link SearchResponse}.
+ */
+public class SearchResponseSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof SearchResponse)) {
+ return Optional.empty();
+ }
+ var gson = GsonUtils.getGsonLight();
+
+ var searchResponse = (SearchResponse) message;
+ var entities = searchResponse.getEntities();
+ var json = gson.toJson(entities);
+ var bytes = json.getBytes();
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(bytes.length)
+ .payload(bytes)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/UserRole.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/UserRole.java
new file mode 100644
index 0000000..96fda33
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/UserRole.java
@@ -0,0 +1,46 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Role of the user
+ */
+@Getter
+@RequiredArgsConstructor
+public enum UserRole {
+ GUEST(1),
+ USER(3),
+ ADMIN(5);
+
+ private final int value;
+
+ /**
+ * Converts int value to user role.
+ * @return User role of empty optional if the value is not used by any role
+ */
+ public static Optional of(int value) {
+ return Arrays.stream(values())
+ .filter(role -> role.value == value)
+ .findAny();
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/SecretRequest.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/SecretRequest.java
new file mode 100644
index 0000000..d991de0
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/SecretRequest.java
@@ -0,0 +1,40 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol.request;
+
+import com.warxim.vucsa.common.message.MessageType;
+import com.warxim.vucsa.common.message.Message;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+/**
+ * Secret request (requests server to send secret to the client).
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class SecretRequest extends Message {
+ @Builder
+ public SecretRequest(int target) {
+ super(target);
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.VERTICAL_ACCESS_CONTROL_SECRET_REQUEST;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/SecretRequestDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/SecretRequestDeserializer.java
new file mode 100644
index 0000000..12c284b
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/SecretRequestDeserializer.java
@@ -0,0 +1,35 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol.request;
+
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+
+import java.util.Optional;
+
+/**
+ * Deserializer for {@link SecretRequest}.
+ */
+public class SecretRequestDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ return Optional.of(SecretRequest.builder()
+ .target(serializedMessage.getTarget())
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/SecretRequestSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/SecretRequestSerializer.java
new file mode 100644
index 0000000..3a66a84
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/SecretRequestSerializer.java
@@ -0,0 +1,39 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol.request;
+
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+
+import java.util.Optional;
+
+/**
+ * Serializer for {@link SecretRequest}.
+ */
+public class SecretRequestSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof SecretRequest)) {
+ return Optional.empty();
+ }
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/UserInfoRequest.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/UserInfoRequest.java
new file mode 100644
index 0000000..9abcf4a
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/UserInfoRequest.java
@@ -0,0 +1,40 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol.request;
+
+import com.warxim.vucsa.common.message.MessageType;
+import com.warxim.vucsa.common.message.Message;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+/**
+ * User info request.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class UserInfoRequest extends Message {
+ @Builder
+ public UserInfoRequest(int target) {
+ super(target);
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.VERTICAL_ACCESS_CONTROL_USER_INFO_REQUEST;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/UserInfoRequestDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/UserInfoRequestDeserializer.java
new file mode 100644
index 0000000..96b7f1b
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/UserInfoRequestDeserializer.java
@@ -0,0 +1,35 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol.request;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+
+import java.util.Optional;
+
+/**
+ * Deserializer for {@link UserInfoRequest}.
+ */
+public class UserInfoRequestDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ return Optional.of(UserInfoRequest.builder()
+ .target(serializedMessage.getTarget())
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/UserInfoRequestSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/UserInfoRequestSerializer.java
new file mode 100644
index 0000000..ac6bf46
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/request/UserInfoRequestSerializer.java
@@ -0,0 +1,39 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol.request;
+
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+
+import java.util.Optional;
+
+/**
+ * Serializer for {@link UserInfoRequest}.
+ */
+public class UserInfoRequestSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof UserInfoRequest)) {
+ return Optional.empty();
+ }
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/SecretResponse.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/SecretResponse.java
new file mode 100644
index 0000000..dd4140f
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/SecretResponse.java
@@ -0,0 +1,43 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol.response;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageType;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+/**
+ * Secret response.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class SecretResponse extends Message {
+ String secret;
+
+ @Builder
+ public SecretResponse(int target, String secret) {
+ super(target);
+ this.secret = secret;
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.VERTICAL_ACCESS_CONTROL_SECRET_RESPONSE;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/SecretResponseDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/SecretResponseDeserializer.java
new file mode 100644
index 0000000..7d2f4ba
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/SecretResponseDeserializer.java
@@ -0,0 +1,37 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol.response;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+
+import java.util.Optional;
+
+/**
+ * Deserializer for {@link SecretResponse}.
+ */
+public class SecretResponseDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ var secret = new String(serializedMessage.getPayload(), 0, serializedMessage.getLength());
+ return Optional.of(SecretResponse.builder()
+ .target(serializedMessage.getTarget())
+ .secret(secret)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/SecretResponseSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/SecretResponseSerializer.java
new file mode 100644
index 0000000..998810f
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/SecretResponseSerializer.java
@@ -0,0 +1,43 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol.response;
+
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.SerializedMessage;
+
+import java.util.Optional;
+
+/**
+ * Serializer for {@link SecretResponse}.
+ */
+public class SecretResponseSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof SecretResponse)) {
+ return Optional.empty();
+ }
+ var secretResponse = (SecretResponse) message;
+ var bytes = secretResponse.getSecret().getBytes();
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(bytes.length)
+ .payload(bytes)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/UserInfoResponse.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/UserInfoResponse.java
new file mode 100644
index 0000000..4a2a2c5
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/UserInfoResponse.java
@@ -0,0 +1,48 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol.response;
+
+import com.warxim.vucsa.common.message.MessageType;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.UserRole;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+/**
+ * User info response.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class UserInfoResponse extends Message {
+ int id;
+ UserRole role;
+ String username;
+
+ @Builder
+ public UserInfoResponse(int target, int id, UserRole role, String username) {
+ super(target);
+ this.id = id;
+ this.role = role;
+ this.username = username;
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.VERTICAL_ACCESS_CONTROL_USER_INFO_RESPONSE;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/UserInfoResponseDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/UserInfoResponseDeserializer.java
new file mode 100644
index 0000000..c18a2a3
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/UserInfoResponseDeserializer.java
@@ -0,0 +1,59 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol.response;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.UserRole;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+/**
+ * Deserializer for {@link UserInfoResponse}.
+ */
+public class UserInfoResponseDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ if (serializedMessage.getLength() < 8) {
+ Logger.getGlobal().severe("Serialized message does not contain enough bytes.");
+ return Optional.empty();
+ }
+
+ var id = ByteBuffer.wrap(serializedMessage.getPayload(), 0, 4).getInt();
+ var roleValue = ByteBuffer.wrap(serializedMessage.getPayload(), 4, 8).getInt();
+ var maybeRole = UserRole.of(roleValue);
+ if (maybeRole.isEmpty()) {
+ Logger.getGlobal().severe("Invalid user role detected in message.");
+ return Optional.empty();
+ }
+ var role = maybeRole.get();
+
+ var usernameBytes = Arrays.copyOfRange(serializedMessage.getPayload(), 8, serializedMessage.getLength());
+ var username = new String(usernameBytes);
+
+ return Optional.of(UserInfoResponse.builder()
+ .target(serializedMessage.getTarget())
+ .id(id)
+ .role(role)
+ .username(username)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/UserInfoResponseSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/UserInfoResponseSerializer.java
new file mode 100644
index 0000000..a079b36
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/verticalaccesscontrol/response/UserInfoResponseSerializer.java
@@ -0,0 +1,53 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.verticalaccesscontrol.response;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+
+import java.nio.ByteBuffer;
+import java.util.Optional;
+
+/**
+ * Serializer for {@link UserInfoResponse}.
+ */
+public class UserInfoResponseSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof UserInfoResponse)) {
+ return Optional.empty();
+ }
+ var userInfoResponse = (UserInfoResponse) message;
+ var id = userInfoResponse.getId();
+ var role = userInfoResponse.getRole().getValue();
+
+ var usernameBytes = userInfoResponse.getUsername().getBytes();
+ var bytes = ByteBuffer.allocate(4 + 4 + usernameBytes.length)
+ .putInt(id)
+ .putInt(role)
+ .put(usernameBytes)
+ .array();
+
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(bytes.length)
+ .payload(bytes)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/xml/StorageItem.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/xml/StorageItem.java
new file mode 100644
index 0000000..32593a8
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/xml/StorageItem.java
@@ -0,0 +1,30 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.xml;
+
+import lombok.Builder;
+import lombok.Value;
+
+/**
+ * Storage item represents KEY-VALUE pair in storage.
+ */
+@Builder
+@Value
+public class StorageItem {
+ String key;
+ String value;
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/xml/StorageMessage.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/xml/StorageMessage.java
new file mode 100644
index 0000000..2ec543b
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/xml/StorageMessage.java
@@ -0,0 +1,46 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.xml;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageType;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Message for XML challenge containing list of storage items.
+ */
+@Value
+@EqualsAndHashCode(callSuper = true)
+public class StorageMessage extends Message {
+ List items;
+
+ @Builder
+ public StorageMessage(int target, List items) {
+ super(target);
+ this.items = Collections.unmodifiableList(items);
+ }
+
+ @Override
+ public MessageType getType() {
+ return MessageType.XML_STORAGE_MESSAGE;
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/xml/StorageMessageDeserializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/xml/StorageMessageDeserializer.java
new file mode 100644
index 0000000..0da8b36
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/xml/StorageMessageDeserializer.java
@@ -0,0 +1,123 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.xml;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.MessageDeserializer;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Deserializer for {@link StorageMessage}.
+ */
+public class StorageMessageDeserializer implements MessageDeserializer {
+ @Override
+ public Optional deserializeMessage(SerializedMessage serializedMessage) {
+ var xml = new String(serializedMessage.getPayload(), 0, serializedMessage.getLength());
+ var items = parseXmlStorage(xml);
+ return Optional.of(StorageMessage.builder()
+ .target(serializedMessage.getTarget())
+ .items(items)
+ .build());
+ }
+
+ /**
+ * Parses XML to list of storage items.
+ */
+ private List parseXmlStorage(String xml) {
+ try {
+ // Create XML parsers with insecure configuration
+ var documentBuilderFactory = createDocumentBuilderFactory();
+ var documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ var document = documentBuilder.parse(new InputSource(new StringReader(xml)));
+
+ var storage = new LinkedList();
+ var list = document.getElementsByTagName("item");
+ for (var i = 0; i < list.getLength(); ++i) {
+ var node = list.item(i);
+ var maybeItem = parseStorageItem(node);
+ if (maybeItem.isPresent()) {
+ storage.add(maybeItem.get());
+ }
+ }
+ return storage;
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not parse XML!", e);
+ }
+ return Collections.emptyList();
+ }
+
+ /**
+ * Parses XML node into storage item.
+ */
+ private Optional parseStorageItem(Node node) {
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ return Optional.empty();
+ }
+ var element = (Element) node;
+
+ var itemKeyElement = element.getElementsByTagName("key");
+ if (itemKeyElement.getLength() != 1) {
+ return Optional.empty();
+ }
+ var itemKey = itemKeyElement.item(0).getTextContent();
+
+ var itemValueElement = element.getElementsByTagName("value");
+ if (itemKeyElement.getLength() != 1) {
+ return Optional.empty();
+ }
+ var itemValue = itemValueElement.item(0).getTextContent();
+
+ return Optional.of(StorageItem.builder()
+ .key(itemKey)
+ .value(itemValue)
+ .build());
+ }
+
+ /**
+ * Creates vulnerable document builder factory.
+ *
Allows multiple vulnerabilities to be exploited!
+ */
+ private DocumentBuilderFactory createDocumentBuilderFactory() throws ParserConfigurationException {
+ var dbf = DocumentBuilderFactory.newInstance();
+ // Extreme insecure feature configuration
+ dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
+ dbf.setExpandEntityReferences(true);
+ dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl",false);
+ dbf.setFeature("http://xml.org/sax/features/external-general-entities",true);
+ dbf.setFeature("http://xml.org/sax/features/external-parameter-entities",true);
+ dbf.setNamespaceAware(true);
+ dbf.setXIncludeAware(true);
+ return dbf;
+ }
+
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/message/xml/StorageMessageSerializer.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/xml/StorageMessageSerializer.java
new file mode 100644
index 0000000..8c517a4
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/message/xml/StorageMessageSerializer.java
@@ -0,0 +1,58 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.message.xml;
+
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageSerializer;
+import com.warxim.vucsa.common.message.SerializedMessage;
+
+import java.util.Optional;
+
+/**
+ * Serializer for {@link StorageMessage}.
+ */
+public class StorageMessageSerializer implements MessageSerializer {
+ @Override
+ public Optional serializeMessage(Message message) {
+ if (!(message instanceof StorageMessage)) {
+ return Optional.empty();
+ }
+
+ var storageMessage = (StorageMessage) message;
+ var items = storageMessage.getItems();
+
+ var builder = new StringBuilder("");
+ for (var item : items) {
+ builder
+ .append("")
+ .append("").append(item.getKey()).append("")
+ .append("").append(item.getValue()).append("")
+ .append("");
+ }
+ builder.append("");
+
+ var xml = builder.toString();
+ var bytes = xml.getBytes();
+
+ return Optional.of(SerializedMessage.builder()
+ .type(message.getType())
+ .target(message.getTarget())
+ .length(bytes.length)
+ .payload(bytes)
+ .build());
+ }
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/util/GsonUtils.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/util/GsonUtils.java
new file mode 100644
index 0000000..ae69360
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/util/GsonUtils.java
@@ -0,0 +1,56 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.util;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * Utils for using GSON library.
+ */
+public final class GsonUtils {
+ /**
+ * GSON instance for serializing/deserializing in the application.
+ */
+ private static final Gson GSON = new GsonBuilder()
+ .setPrettyPrinting()
+ .create();
+
+ /**
+ * GSON instance for serializing/deserializing in the application (for light purposes, e.g. network communication).
+ */
+ private static final Gson GSON_LIGHT = new GsonBuilder()
+ .create();
+
+ /**
+ * Obtains GSON instance.
+ * @return GSON instance used throughout the whole application
+ */
+ public static Gson getGson() {
+ return GSON;
+ }
+
+ /**
+ * Obtains GSON instance for light JSON creation (without pretty printing).
+ * @return GSON instance used throughout the whole application
+ */
+ public static Gson getGsonLight() {
+ return GSON_LIGHT;
+ }
+
+ private GsonUtils() {}
+}
diff --git a/vucsa-common/src/main/java/com/warxim/vucsa/common/util/MessageUtils.java b/vucsa-common/src/main/java/com/warxim/vucsa/common/util/MessageUtils.java
new file mode 100644
index 0000000..7231b88
--- /dev/null
+++ b/vucsa-common/src/main/java/com/warxim/vucsa/common/util/MessageUtils.java
@@ -0,0 +1,90 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common.util;
+
+import com.warxim.vucsa.common.message.MessageType;
+import com.warxim.vucsa.common.message.SerializedMessage;
+import com.warxim.vucsa.common.message.Message;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+/**
+ * Utils for working with messages.
+ */
+public final class MessageUtils {
+ /**
+ * Writes message to output stream.
+ *
Serializes the message and writes it to given output stream.
+ * @param message Message to be written
+ * @param out Output stream
+ */
+ public static boolean writeMessageToOutputStream(Message message, OutputStream out) throws IOException {
+ var serializer = message.getType().getSerializer();
+ var maybeSerializedMessage = serializer.serializeMessage(message);
+ if (maybeSerializedMessage.isEmpty()) {
+ return false;
+ }
+ var serializedMessage = maybeSerializedMessage.get();
+ var buffer = ByteBuffer.allocate(4 * 3 + serializedMessage.getLength()); // 3x INT + payload length
+ buffer.putInt(serializedMessage.getType().getValue());
+ buffer.putInt(serializedMessage.getTarget());
+ buffer.putInt(serializedMessage.getLength());
+ if (serializedMessage.getPayload() != null) {
+ buffer.put(serializedMessage.getPayload(), 0, serializedMessage.getLength());
+ }
+ out.write(buffer.array());
+ return true;
+ }
+
+ /**
+ * Reads message from input stream.
+ * @param in Input stream
+ * @return Message or empty optional if the message could not be read or deserialized
+ */
+ public static Optional readMessageFromInputStream(DataInputStream in) throws IOException {
+ var typeValue = in.readInt();
+ var target = in.readInt();
+ var length = in.readInt();
+
+ var payload = new byte[length];
+ in.readFully(payload);
+
+ var maybeType = MessageType.of(typeValue);
+ if (maybeType.isEmpty()) {
+ Logger.getGlobal().severe(() -> String.format("Unrecognized message type [%d]!", typeValue));
+ return Optional.empty();
+ }
+ var type = maybeType.get();
+
+ var serializedMessage = SerializedMessage.builder()
+ .type(type)
+ .target(target)
+ .length(length)
+ .payload(payload)
+ .build();
+
+ var deserializer = type.getDeserializer();
+ return deserializer.deserializeMessage(serializedMessage);
+ }
+
+ private MessageUtils() {}
+}
diff --git a/vucsa-common/src/test/java/com/warxim/vucsa/common/MessageHandlerManagerTest.java b/vucsa-common/src/test/java/com/warxim/vucsa/common/MessageHandlerManagerTest.java
new file mode 100644
index 0000000..0becfde
--- /dev/null
+++ b/vucsa-common/src/test/java/com/warxim/vucsa/common/MessageHandlerManagerTest.java
@@ -0,0 +1,71 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.common;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.MessageHandlerManager;
+import com.warxim.vucsa.common.message.plain.PlainMessage;
+import org.testng.annotations.Test;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+public class MessageHandlerManagerTest {
+ @Test
+ public void typeMessagePrioritizationTest() {
+ var manager = new MessageHandlerManager();
+
+ var handler1 = createMessageHandlerMock();
+ var handler2 = createMessageHandlerMock();
+
+ var message1 = PlainMessage.builder()
+ .target(12)
+ .length(3)
+ .payload(new byte[] {0x01, 0x02, 0x03})
+ .build();
+ var message2 = PlainMessage.builder()
+ .target(12)
+ .length(5)
+ .payload(new byte[] {0x05, 0x04, 0x06, 0x04, 0x05})
+ .build();
+ var message3 = PlainMessage.builder()
+ .target(4)
+ .length(5)
+ .payload(new byte[] {0x05, 0x04, 0x06, 0x04, 0x05})
+ .build();
+ var connection = mock(Connection.class);
+
+ manager.registerHandler(12, handler1);
+ manager.registerHandler(4, handler2);
+
+ manager.handleMessage(connection, message1);
+ manager.handleMessage(connection, message2);
+ manager.handleMessage(connection, message3);
+
+ verify(handler1, times(1)).handleMessage(connection, message1);
+ verify(handler1, times(1)).handleMessage(connection, message2);
+ verify(handler2, times(1)).handleMessage(connection, message3);
+ }
+
+ private MessageHandler createMessageHandlerMock() {
+ var handler = mock(MessageHandler.class);
+ when(handler.handleMessage(any(), any())).thenReturn(true);
+ when(handler.supports(any())).thenReturn(true);
+ return handler;
+ }
+}
diff --git a/vucsa-server/build.gradle b/vucsa-server/build.gradle
new file mode 100644
index 0000000..0d56a14
--- /dev/null
+++ b/vucsa-server/build.gradle
@@ -0,0 +1,42 @@
+plugins {
+ id 'java'
+ id 'application'
+}
+
+group 'com.warxim'
+version '1.0'
+mainClassName = 'com.warxim.vucsa.server.Main'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation project(':vucsa-common')
+
+ compileOnly 'org.projectlombok:lombok:1.18.24'
+ annotationProcessor 'org.projectlombok:lombok:1.18.24'
+ implementation 'com.google.code.gson:gson:2.9.0'
+ implementation 'org.xerial:sqlite-jdbc:3.36.0.3'
+
+ testImplementation 'org.testng:testng:7.6.0'
+ testImplementation 'org.assertj:assertj-core:3.23.1'
+}
+
+test {
+ useTestNG()
+}
+
+application {
+ executableDir = ''
+
+ copy {
+ from './server'
+ into 'build/run/server'
+ }
+}
+
+// Set run working directory to build/run
+File runningDir = new File('build/run')
+runningDir.mkdirs()
+tasks.run.workingDir = runningDir
\ No newline at end of file
diff --git a/vucsa-server/server/challenge/horizontalaccesscontrol/document/1.txt b/vucsa-server/server/challenge/horizontalaccesscontrol/document/1.txt
new file mode 100644
index 0000000..dde6d4e
--- /dev/null
+++ b/vucsa-server/server/challenge/horizontalaccesscontrol/document/1.txt
@@ -0,0 +1,2 @@
+Administrator's file!
+Important password, do not forget it: 123456789
\ No newline at end of file
diff --git a/vucsa-server/server/challenge/horizontalaccesscontrol/document/1001.txt b/vucsa-server/server/challenge/horizontalaccesscontrol/document/1001.txt
new file mode 100644
index 0000000..371d2b9
--- /dev/null
+++ b/vucsa-server/server/challenge/horizontalaccesscontrol/document/1001.txt
@@ -0,0 +1,11 @@
+Shopping list:
+- tofu
+- chickpeas
+- beans
+- bulgur
+- rice
+- apples
+- bananas
+- oranges
+- avocados
+- coffee
\ No newline at end of file
diff --git a/vucsa-server/server/challenge/horizontalaccesscontrol/document/11011.txt b/vucsa-server/server/challenge/horizontalaccesscontrol/document/11011.txt
new file mode 100644
index 0000000..404be8c
--- /dev/null
+++ b/vucsa-server/server/challenge/horizontalaccesscontrol/document/11011.txt
@@ -0,0 +1,4 @@
+I have to write this down, so I do not forget it...
+
+User: super-alien-farmer
+Password: AllAnimalsAreEqualButSomeAnimalsAreMoreEqualThanOthers
diff --git a/vucsa-server/server/challenge/horizontalaccesscontrol/document/12002.txt b/vucsa-server/server/challenge/horizontalaccesscontrol/document/12002.txt
new file mode 100644
index 0000000..9908553
--- /dev/null
+++ b/vucsa-server/server/challenge/horizontalaccesscontrol/document/12002.txt
@@ -0,0 +1,4 @@
+Not a Real Book
+Book Which Was Never Written
+Almost Real Book Name
+Book About Books About Books
\ No newline at end of file
diff --git a/vucsa-server/server/challenge/horizontalaccesscontrol/document/2222.txt b/vucsa-server/server/challenge/horizontalaccesscontrol/document/2222.txt
new file mode 100644
index 0000000..fca982a
--- /dev/null
+++ b/vucsa-server/server/challenge/horizontalaccesscontrol/document/2222.txt
@@ -0,0 +1 @@
+This is a super secret message!
\ No newline at end of file
diff --git a/vucsa-server/server/challenge/horizontalaccesscontrol/document/5406.txt b/vucsa-server/server/challenge/horizontalaccesscontrol/document/5406.txt
new file mode 100644
index 0000000..07c6144
--- /dev/null
+++ b/vucsa-server/server/challenge/horizontalaccesscontrol/document/5406.txt
@@ -0,0 +1 @@
+All animals are equal, but some animals are more equal than others.
diff --git a/vucsa-server/server/challenge/horizontalaccesscontrol/document/8435.txt b/vucsa-server/server/challenge/horizontalaccesscontrol/document/8435.txt
new file mode 100644
index 0000000..3ab2013
--- /dev/null
+++ b/vucsa-server/server/challenge/horizontalaccesscontrol/document/8435.txt
@@ -0,0 +1 @@
+Mj csy xipp xli xvyxl, csy hsr'x lezi xs viqiqfiv ercxlmrk.
\ No newline at end of file
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/Main.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/Main.java
new file mode 100644
index 0000000..9bc8ea8
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/Main.java
@@ -0,0 +1,30 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server;
+
+import com.warxim.vucsa.server.bootstrap.ConsoleBootstrap;
+
+/**
+ * Main server application class.
+ */
+public final class Main {
+ public static void main(String[] args) {
+ new ConsoleBootstrap().start();
+ }
+
+ private Main() {}
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/bootstrap/ConsoleBootstrap.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/bootstrap/ConsoleBootstrap.java
new file mode 100644
index 0000000..11f1572
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/bootstrap/ConsoleBootstrap.java
@@ -0,0 +1,141 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.bootstrap;
+
+import com.warxim.vucsa.server.configuration.Configuration;
+import com.warxim.vucsa.server.configuration.ConfigurationException;
+import com.warxim.vucsa.server.configuration.ConfigurationLoader;
+import com.warxim.vucsa.server.core.ServerConfig;
+import com.warxim.vucsa.server.core.ServerManager;
+import com.warxim.vucsa.server.core.ServerState;
+import com.warxim.vucsa.common.Constant;
+import com.warxim.vucsa.server.challenge.ChallengeManager;
+
+import java.util.Scanner;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Console bootstrap for running the server in console.
+ */
+public class ConsoleBootstrap {
+ private Configuration configuration;
+ private ServerManager serverManager;
+
+ /**
+ * Starts the server and user input loop.
+ */
+ public void start() {
+ try {
+ configuration = ConfigurationLoader.loadOrDefault(
+ Constant.SERVER_CONFIG_PATH,
+ () -> Configuration.builder()
+ .network(ServerConfig.builder()
+ .serverHost(Constant.DEFAULT_SERVER_HOST)
+ .serverPort(Constant.DEFAULT_SERVER_PORT)
+ .build())
+ .build());
+ } catch (ConfigurationException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not load/save configuration!", e);
+ return;
+ }
+
+ serverManager = new ServerManager();
+ var challengeManager = new ChallengeManager();
+ challengeManager.load(serverManager);
+ serverManager.start(configuration.getNetwork());
+
+ printHelp();
+ runInputLoop();
+
+ challengeManager.unload(serverManager);
+ serverManager.stop();
+ }
+
+ /**
+ * Runs user input loop (waits for commands and executes them).
+ */
+ private void runInputLoop() {
+ var scanner = new Scanner(System.in);
+ while (true) {
+ if (!scanner.hasNextLine()) {
+ try {
+ Thread.sleep(100);
+ continue;
+ } catch (InterruptedException e) {
+ Logger.getGlobal().log(Level.INFO, "Interrupted, quiting...", e);
+ Thread.currentThread().interrupt();
+ return;
+ }
+ }
+
+ var line = scanner.nextLine().trim();
+ switch (line) {
+ case "stop":
+ case "quit":
+ case "exit":
+ case "shutdown":
+ serverManager.stop();
+ waitForServerTermination(serverManager);
+ return;
+ case "restart":
+ serverManager.stop();
+ waitForServerTermination(serverManager);
+ serverManager.start(configuration.getNetwork());
+ break;
+ default:
+ printHelp();
+ }
+ }
+ }
+
+ /**
+ * Prints help to the command line.
+ */
+ private void printHelp() {
+ var out = System.out;
+ printSeparator();
+ out.println("\tHELP");
+ printSeparator();
+ out.println("Control server");
+ out.println("\trestart - restart the server");
+ out.println("\tstop - close the server");
+ }
+
+ /**
+ * Prints separator to the command line.
+ */
+ private void printSeparator() {
+ System.out.println("# ------------------------------------------ #");
+ }
+
+
+ /**
+ * Waits till the PETEP core stops.
+ */
+ private void waitForServerTermination(ServerManager serverManager) {
+ while (serverManager.getState() != ServerState.STOPPED) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // Interrupted.
+ Thread.currentThread().interrupt();
+ break;
+ }
+ }
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/Challenge.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/Challenge.java
new file mode 100644
index 0000000..a7bab8a
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/Challenge.java
@@ -0,0 +1,72 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge;
+
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.server.core.ServerManager;
+
+import java.io.File;
+import java.util.logging.Logger;
+
+/**
+ * Base class for challenges.
+ */
+public abstract class Challenge {
+ /**
+ * Loads challenge.
+ *
+ * @param serverManager Server manager
+ */
+ public abstract void unload(ServerManager serverManager);
+
+ /**
+ * Initializes challenge directory.
+ */
+ protected void initChallengeDirectory() {
+ var directory = new File(getChallengeDirectory());
+ if (directory.exists()) {
+ return;
+ }
+ if (!directory.mkdir()) {
+ Logger.getGlobal().severe("Could not create challenge directory, server might not work correctly.");
+ }
+ }
+
+ /**
+ * Obtains challenge directory name.
+ *
Example: challenges/SuperChallenge/
+ */
+ protected String getChallengeDirectory() {
+ return ChallengeConstant.CHALLENGES_DIRECTORY
+ + removeSuffix(getClass().getSimpleName().toLowerCase(), "challenge")
+ + "/";
+ }
+
+ private static String removeSuffix(String string, String suffix) {
+ if (string != null && suffix != null && string.endsWith(suffix)) {
+ return string.substring(0, string.length() - suffix.length());
+ }
+ return string;
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/ChallengeManager.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/ChallengeManager.java
new file mode 100644
index 0000000..d313f9f
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/ChallengeManager.java
@@ -0,0 +1,80 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge;
+
+import com.warxim.vucsa.server.challenge.bufferoverread.BufferOverreadChallenge;
+import com.warxim.vucsa.server.challenge.commandexecution.CommandExecutionChallenge;
+import com.warxim.vucsa.server.challenge.enumeration.EnumerationChallenge;
+import com.warxim.vucsa.server.challenge.horizontalaccesscontrol.HorizontalAccessControlChallenge;
+import com.warxim.vucsa.server.challenge.sqlinjection.SqlInjectionChallenge;
+import com.warxim.vucsa.server.challenge.verticalaccesscontrol.VerticalAccessControlChallenge;
+import com.warxim.vucsa.server.challenge.xml.XmlChallenge;
+import com.warxim.vucsa.server.core.ServerManager;
+import com.warxim.vucsa.common.ChallengeConstant;
+
+import java.io.File;
+import java.util.List;
+import java.util.logging.Logger;
+
+/**
+ * Simple static helper class for registering all challenge handlers.
+ */
+public class ChallengeManager {
+ private final List challenges;
+
+ public ChallengeManager() {
+ initDirectory();
+ challenges = List.of(
+ new BufferOverreadChallenge(),
+ new SqlInjectionChallenge(),
+ new EnumerationChallenge(),
+ new CommandExecutionChallenge(),
+ new XmlChallenge(),
+ new HorizontalAccessControlChallenge(),
+ new VerticalAccessControlChallenge()
+ );
+ }
+
+ /**
+ * Loads challenges using given server manager.
+ * @param serverManager Server manager
+ */
+ public void load(ServerManager serverManager) {
+ challenges.forEach(challenge -> challenge.load(serverManager));
+ }
+
+ /**
+ * Unloads challenges using given server manager.
+ * @param serverManager Server manager
+ */
+ public void unload(ServerManager serverManager) {
+ challenges.forEach(challenge -> challenge.unload(serverManager));
+ }
+
+ /**
+ * Initializes directory for challenges.
+ */
+ private void initDirectory() {
+ var directory = new File(ChallengeConstant.CHALLENGES_DIRECTORY);
+ if (directory.exists()) {
+ return;
+ }
+ if (!directory.mkdir()) {
+ Logger.getGlobal().severe("Could not create challenge directory, server might not work correctly.");
+ }
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/bufferoverread/BufferOverreadChallenge.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/bufferoverread/BufferOverreadChallenge.java
new file mode 100644
index 0000000..239ec27
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/bufferoverread/BufferOverreadChallenge.java
@@ -0,0 +1,36 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.bufferoverread;
+
+import com.warxim.vucsa.server.challenge.Challenge;
+import com.warxim.vucsa.server.core.ServerManager;
+import com.warxim.vucsa.common.ChallengeConstant;
+
+/**
+ * Buffer over-read challenge
+ */
+public class BufferOverreadChallenge extends Challenge {
+ @Override
+ public void load(ServerManager serverManager) {
+ serverManager.registerHandler(ChallengeConstant.BUFFER_OVERREAD_TARGET, new BufferOverreadHandler());
+ }
+
+ @Override
+ public void unload(ServerManager serverManager) {
+ serverManager.unregisterHandler(ChallengeConstant.BUFFER_OVERREAD_TARGET);
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/bufferoverread/BufferOverreadHandler.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/bufferoverread/BufferOverreadHandler.java
new file mode 100644
index 0000000..aabdc58
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/bufferoverread/BufferOverreadHandler.java
@@ -0,0 +1,56 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.bufferoverread;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.bufferoverread.StringListMessage;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.stream.Collectors;
+
+/**
+ * Handler for buffer over-read challenge
+ *
Transforms string list:
+ *
+ *
reverses item order,
+ *
converts items to upper case.
+ *
+ */
+public class BufferOverreadHandler implements MessageHandler {
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof StringListMessage;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ var bufferOverreadMessage = (StringListMessage) message;
+ var items = bufferOverreadMessage.getItems()
+ .stream()
+ .map(String::toUpperCase)
+ .collect(Collectors.toCollection(ArrayList::new));
+ Collections.reverse(items);
+ connection.sendMessage(StringListMessage.builder()
+ .target(bufferOverreadMessage.getTarget())
+ .items(items)
+ .build());
+ return true;
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/commandexecution/CommandExecutionChallenge.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/commandexecution/CommandExecutionChallenge.java
new file mode 100644
index 0000000..a43c461
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/commandexecution/CommandExecutionChallenge.java
@@ -0,0 +1,36 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.commandexecution;
+
+import com.warxim.vucsa.server.challenge.Challenge;
+import com.warxim.vucsa.server.core.ServerManager;
+import com.warxim.vucsa.common.ChallengeConstant;
+
+/**
+ * Command execution challenge
+ */
+public class CommandExecutionChallenge extends Challenge {
+ @Override
+ public void load(ServerManager serverManager) {
+ serverManager.registerHandler(ChallengeConstant.COMMAND_EXECUTION_TARGET, new CommandExecutionHandler());
+ }
+
+ @Override
+ public void unload(ServerManager serverManager) {
+ serverManager.unregisterHandler(ChallengeConstant.COMMAND_EXECUTION_TARGET);
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/commandexecution/CommandExecutionHandler.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/commandexecution/CommandExecutionHandler.java
new file mode 100644
index 0000000..5814c34
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/commandexecution/CommandExecutionHandler.java
@@ -0,0 +1,122 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.commandexecution;
+
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.commandexecution.request.PingRequest;
+import com.warxim.vucsa.common.message.commandexecution.response.PingResponse;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Handler for command execution challenge
+ *
Executes ping command on host specified by user in vulnerable way, which allows the user to cause command execution.
+ */
+public class CommandExecutionHandler implements MessageHandler {
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof PingRequest;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ var pingRequest = (PingRequest) message;
+ if (pingRequest.getHost().isBlank()) {
+ connection.sendMessage(PingResponse.builder()
+ .target(ChallengeConstant.COMMAND_EXECUTION_TARGET)
+ .output("You have to specify host!")
+ .build());
+ return true;
+ }
+ var output = ping(pingRequest.getHost());
+ connection.sendMessage(PingResponse.builder()
+ .target(ChallengeConstant.COMMAND_EXECUTION_TARGET)
+ .output(output)
+ .build());
+ return true;
+ }
+
+ /**
+ * Pings host and returns output.
+ */
+ private static String ping(String host) {
+ if (isWindows()) {
+ return executeCommand(new String[] {"cmd.exe", "/C", "ping " + host});
+ } else {
+ return executeCommand(new String[] {"sh", "-c", "ping -c 4 " + host});
+ }
+ }
+
+ /**
+ * Vulnerable command execution.
+ */
+ private static String executeCommand(String[] cmd) {
+ Process process = null;
+ try {
+ var processBuilder = new ProcessBuilder(cmd);
+ processBuilder.redirectErrorStream(true);
+
+ process = processBuilder.start();
+ if (!process.waitFor(30, TimeUnit.SECONDS)) {
+ process.destroy();
+ if (!process.waitFor(30, TimeUnit.SECONDS)) {
+ process.destroyForcibly();
+ }
+ return "Process did not finish in time!";
+ }
+ var builder = new StringBuilder();
+ try (var reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
+ String line;
+ while ((line = reader.readLine()) != null){
+ builder.append(line).append('\n');
+ }
+ }
+ return builder.toString();
+ } catch (IOException e) {
+ Logger.getGlobal().log(
+ Level.SEVERE,
+ e,
+ () -> String.format("Could not execute command '%s'!", String.join(" ", cmd)));
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ Logger.getGlobal().log(
+ Level.SEVERE,
+ e,
+ () -> String.format("Interrupted command execution '%s'!", String.join(" ", cmd)));
+ } finally {
+ if (process != null) {
+ process.destroy();
+ }
+ }
+ return "";
+ }
+
+ /**
+ * Checks, whether the current platform is Windows or not.
+ */
+ private static boolean isWindows() {
+ return System.getProperty("os.name").toLowerCase().contains("windows");
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/enumeration/AuthService.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/enumeration/AuthService.java
new file mode 100644
index 0000000..b19188a
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/enumeration/AuthService.java
@@ -0,0 +1,106 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.enumeration;
+
+import com.warxim.vucsa.common.message.enumeration.LoginStatus;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Value;
+
+import java.security.MessageDigest;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * In-memory authentication service.
+ */
+public class AuthService {
+ /**
+ * Users mapped by username.
+ */
+ private Map users;
+
+ public AuthService() {
+ var tempUsers = List.of(
+ User.builder().username("guest").password("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855").secret("No secret.").build(),
+ User.builder().username("test").password("65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5").secret("I like blue color.").build(),
+ User.builder().username("admin").password("5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8").secret("I use weak passwords.").build(),
+ User.builder().username("user").password("e4ad93ca07acb8d908a3aa41e920ea4f4ef4f26e7f86cf8291c5db289780a5ae").secret("My favorite number is 42.").build(),
+ User.builder().username("root").password("bcb15f821479b4d5772bd0ca866c00ad5f926e3580720659cc80d39c9d09802a").secret("I love PETEP tool.").build(),
+ User.builder().username("super-alien-farmer").password("64681e853e24c842cf75a79239bf3f740064139be7592f6e3fab305f171d65cb").secret("The creatures outside looked from pig to man, and from man to pig, and from pig to man again; but already it was impossible to say which was which.").build()
+ );
+ users = tempUsers.stream()
+ .collect(Collectors.toMap(
+ User::getUsername,
+ Function.identity())
+ );
+ }
+
+ /**
+ * Simulates user login.
+ * @param username Username
+ * @param password User password
+ * @return Result of authentication
+ */
+ public AuthResult login(String username, String password) {
+ var user = users.get(username);
+ if (user == null) {
+ return AuthResult.builder().status(LoginStatus.WRONG_USERNAME).build();
+ }
+
+ var passwordHash = sha256(password);
+ if (!user.getPassword().equals(passwordHash)) {
+ return AuthResult.builder().status(LoginStatus.WRONG_PASSWORD).build();
+ }
+
+ return AuthResult.builder().user(user).status(LoginStatus.SUCCESS).build();
+ }
+
+ /**
+ * Hashes password using sha256
+ */
+ private static String sha256(final String password) {
+ try {
+ var hash = MessageDigest.getInstance("SHA-256")
+ .digest(password.getBytes());
+ var hexString = new StringBuilder();
+ for (var hashByte : hash) {
+ var hex = Integer.toHexString(0xff & hashByte);
+ if (hex.length() == 1) {
+ hexString.append('0');
+ }
+ hexString.append(hex);
+ }
+ return hexString.toString();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Authorization result
+ */
+ @Getter
+ @Value
+ @Builder
+ public static class AuthResult {
+ LoginStatus status;
+ User user;
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/enumeration/EnumerationChallenge.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/enumeration/EnumerationChallenge.java
new file mode 100644
index 0000000..1fa8113
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/enumeration/EnumerationChallenge.java
@@ -0,0 +1,40 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.enumeration;
+
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.server.challenge.Challenge;
+import com.warxim.vucsa.server.core.ServerManager;
+
+/**
+ * Enumeration challenge
+ */
+public class EnumerationChallenge extends Challenge {
+ private AuthService authService;
+
+ @Override
+ public void load(ServerManager serverManager) {
+ authService = new AuthService();
+ serverManager.registerHandler(ChallengeConstant.ENUMERATION_TARGET, new EnumerationHandler(authService));
+ }
+
+ @Override
+ public void unload(ServerManager serverManager) {
+ serverManager.unregisterHandler(ChallengeConstant.ENUMERATION_TARGET);
+ authService = null;
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/enumeration/EnumerationHandler.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/enumeration/EnumerationHandler.java
new file mode 100644
index 0000000..ae6b39a
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/enumeration/EnumerationHandler.java
@@ -0,0 +1,51 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.enumeration;
+
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.enumeration.request.LoginRequest;
+import com.warxim.vucsa.common.message.enumeration.response.LoginResponse;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Handler for enumeration challenge
+ *
Simulates user authentication using {@link AuthService}.
+ */
+@RequiredArgsConstructor
+public class EnumerationHandler implements MessageHandler {
+ private final AuthService authService;
+
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof LoginRequest;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ var loginRequest = (LoginRequest) message;
+ var result = authService.login(loginRequest.getUsername(), loginRequest.getPassword());
+ connection.sendMessage(LoginResponse.builder()
+ .target(ChallengeConstant.ENUMERATION_TARGET)
+ .status(result.getStatus())
+ .userSecret(result.getUser() == null ? null : result.getUser().getSecret())
+ .build());
+ return true;
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/enumeration/User.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/enumeration/User.java
new file mode 100644
index 0000000..2e757e3
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/enumeration/User.java
@@ -0,0 +1,31 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.enumeration;
+
+import lombok.Builder;
+import lombok.Value;
+
+/**
+ * User model
+ */
+@Builder
+@Value
+public class User {
+ String username;
+ String password;
+ String secret;
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/horizontalaccesscontrol/HorizontalAccessControlChallenge.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/horizontalaccesscontrol/HorizontalAccessControlChallenge.java
new file mode 100644
index 0000000..7b22e2d
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/horizontalaccesscontrol/HorizontalAccessControlChallenge.java
@@ -0,0 +1,38 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.horizontalaccesscontrol;
+
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.server.challenge.Challenge;
+import com.warxim.vucsa.server.core.ServerManager;
+
+/**
+ * Horizontal access control challenge
+ */
+public class HorizontalAccessControlChallenge extends Challenge {
+ @Override
+ public void load(ServerManager serverManager) {
+ serverManager.registerHandler(
+ ChallengeConstant.HORIZONTAL_ACCESS_CONTROL_DOCUMENT_CONTENT_TARGET,
+ new HorizontalAccessControlHandler(getChallengeDirectory()));
+ }
+
+ @Override
+ public void unload(ServerManager serverManager) {
+ serverManager.unregisterHandler(ChallengeConstant.HORIZONTAL_ACCESS_CONTROL_DOCUMENT_CONTENT_TARGET);
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/horizontalaccesscontrol/HorizontalAccessControlHandler.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/horizontalaccesscontrol/HorizontalAccessControlHandler.java
new file mode 100644
index 0000000..b620f42
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/horizontalaccesscontrol/HorizontalAccessControlHandler.java
@@ -0,0 +1,68 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.horizontalaccesscontrol;
+
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.horizontalaccesscontrol.request.DocumentContentRequest;
+import com.warxim.vucsa.common.message.horizontalaccesscontrol.response.DocumentContentResponse;
+import lombok.RequiredArgsConstructor;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Handler for horizontal access control challenge
+ *
Handles document management.
+ */
+@RequiredArgsConstructor
+public class HorizontalAccessControlHandler implements MessageHandler {
+ private static final String DOCUMENT_PATH = "document/%d.txt";
+ private final String challengeDirectory;
+
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof DocumentContentRequest;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ var documentContentRequest = (DocumentContentRequest) message;
+ var documentId = documentContentRequest.getDocumentId();
+ var content = loadDocumentContent(documentId);
+ connection.sendMessage(DocumentContentResponse.builder()
+ .target(ChallengeConstant.HORIZONTAL_ACCESS_CONTROL_DOCUMENT_CONTENT_TARGET)
+ .content(content)
+ .build());
+ return true;
+ }
+
+ /**
+ * Loads document content by identifier.
+ */
+ protected String loadDocumentContent(int documentId) {
+ var path = challengeDirectory + String.format(DOCUMENT_PATH, documentId);
+ try (var in = new FileInputStream(path)) {
+ return new String(in.readAllBytes(), StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ return String.format("File '%s' not found!", path);
+ }
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/sqlinjection/SqlDatabase.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/sqlinjection/SqlDatabase.java
new file mode 100644
index 0000000..5291251
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/sqlinjection/SqlDatabase.java
@@ -0,0 +1,164 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.sqlinjection;
+
+import lombok.Getter;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Vulnerable SQL Database for SQL Injection challenge.
+ */
+@Getter
+public class SqlDatabase implements AutoCloseable {
+ private Connection connection;
+
+ /**
+ * Constructs database with given url.
+ * @param url Path to database file
+ */
+ public SqlDatabase(String url) throws SQLException {
+ connection = DriverManager.getConnection(url);
+
+ init();
+ autofillDatabase();
+ }
+
+ @Override
+ public void close() {
+ if (connection != null) {
+ try {
+ connection.close();
+ } catch (SQLException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not close database connection!", e);
+ }
+ }
+ }
+
+ /**
+ * Obtain result by executing query.
+ *
Totally wrong and insecure use of SQLite database.
+ * @param sql SQL to be executed
+ * @return Result of given generic type
+ */
+ public Optional selectOne(String sql, Function transformation) {
+ try (var stmt = connection.createStatement()) {
+ var resultSet = stmt.executeQuery(sql);
+ return Optional.ofNullable(transformation.apply(resultSet));
+ } catch (SQLException e) {
+ logQueryException(e);
+ }
+ return Optional.empty();
+ }
+
+ /**
+ *
+ *
Totally wrong and insecure use of SQLite database.
+ * @param sql SQL to be executed
+ * @return Result list of given generic type
+ */
+ public Optional> selectList(String sql, Function transformation) {
+ try (var stmt = connection.createStatement()) {
+ var results = new LinkedList();
+ var resultSet = stmt.executeQuery(sql);
+ while (resultSet.next()) {
+ results.add(transformation.apply(resultSet));
+ }
+ return Optional.of(results);
+ } catch (SQLException e) {
+ logQueryException(e);
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * Totally wrong and insecure use of SQLite database.
+ * @param sql SQL to be executed
+ * @return {@code true} if the execution was successfull
+ */
+ public boolean execute(String sql) {
+ try (var stmt = connection.createStatement()) {
+ stmt.execute(sql);
+ return true;
+ } catch (SQLException e) {
+ logQueryException(e);
+ }
+ return false;
+ }
+
+ /**
+ * Creates all history tables.
+ */
+ private void init() throws SQLException {
+ try (var stmt = connection.createStatement()) {
+ stmt.execute("CREATE TABLE IF NOT EXISTS food ("
+ + "id INTEGER PRIMARY KEY,"
+ + "name TEXT NOT NULL,"
+ + "description TEXT NOT NULL,"
+ + "price REAL NOT NULL"
+ + ");");
+
+ stmt.execute("CREATE TABLE IF NOT EXISTS user ("
+ + "id INTEGER PRIMARY KEY,"
+ + "email TEXT NOT NULL,"
+ + "password TEXT NOT NULL,"
+ + "name TEXT NOT NULL"
+ + ");");
+ }
+ }
+
+ /**
+ * Automatically fills database with data.
+ */
+ private void autofillDatabase() {
+ Function countTransformer = resultSet -> {
+ try {
+ return resultSet.getInt(1);
+ } catch (SQLException throwables) {
+ return null;
+ }
+ };
+
+ var maybeCount = selectOne("SELECT COUNT(*) FROM food", countTransformer);
+ if (maybeCount.isPresent() && maybeCount.get() == 0) {
+ execute("INSERT INTO food (id, name, description, price) VALUES (1, 'Pizza Margherita', 'Tomato sauce, Mozzarella, Basil, Oregano', 6.50);");
+ execute("INSERT INTO food (id, name, description, price) VALUES (2, 'Pizza Hawaii', 'Cream, Mozzarella, Ham, Pineapple', 7.50);");
+ execute("INSERT INTO food (id, name, description, price) VALUES (3, 'Pizza Salami', 'Tomato sauce, Mozzarella, Salami', 8.50);");
+ execute("INSERT INTO food (id, name, description, price) VALUES (4, 'BBQ Burger', 'Ground beef, Bacon, Cheddar, BBQ sauce, Onion, Lettuce', 9.49);");
+ }
+
+ maybeCount = selectOne("SELECT COUNT(*) FROM user", countTransformer);
+ if (maybeCount.isPresent() && maybeCount.get() == 0) {
+ execute("INSERT INTO user (id, email, password, name) VALUES (1, 'admin@petep.com', 'd033e22ae348aeb5660fc2140aec35850c4da997', 'Admin Nimda');");
+ execute("INSERT INTO user (id, email, password, name) VALUES (2, 'john@example.com', '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8', 'John Example');");
+ execute("INSERT INTO user (id, email, password, name) VALUES (3, 'hitchhiker@example.com', '92cfceb39d57d914ed8b14d0e37643de0797ae56', 'The Hitchhiker');");
+ }
+ }
+
+ private void logQueryException(SQLException e) {
+ Logger.getGlobal().log(Level.SEVERE, "SQL exception occurred during query execution!", e);
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/sqlinjection/SqlInjectionChallenge.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/sqlinjection/SqlInjectionChallenge.java
new file mode 100644
index 0000000..8e233a4
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/sqlinjection/SqlInjectionChallenge.java
@@ -0,0 +1,49 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.sqlinjection;
+
+import com.warxim.vucsa.server.challenge.Challenge;
+import com.warxim.vucsa.server.core.ServerManager;
+import com.warxim.vucsa.common.ChallengeConstant;
+
+import java.sql.SQLException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * SQL injection challenge
+ */
+public class SqlInjectionChallenge extends Challenge {
+ private SqlDatabase database;
+
+ @Override
+ public void load(ServerManager serverManager) {
+ initChallengeDirectory();
+ try {
+ database = new SqlDatabase("jdbc:sqlite:" + getChallengeDirectory() + "database.db");
+ serverManager.registerHandler(ChallengeConstant.SQL_INJECTION_TARGET, new SqlInjectionHandler(database));
+ } catch (SQLException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not create database for SQL Injection challenge!", e);
+ }
+ }
+
+ @Override
+ public void unload(ServerManager serverManager) {
+ serverManager.unregisterHandler(ChallengeConstant.SQL_INJECTION_TARGET);
+ database.close();
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/sqlinjection/SqlInjectionHandler.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/sqlinjection/SqlInjectionHandler.java
new file mode 100644
index 0000000..ad51e1b
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/sqlinjection/SqlInjectionHandler.java
@@ -0,0 +1,75 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.sqlinjection;
+
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.sqlinjection.request.SearchRequest;
+import com.warxim.vucsa.common.message.sqlinjection.FoodEntity;
+import com.warxim.vucsa.common.message.sqlinjection.response.SearchResponse;
+import lombok.RequiredArgsConstructor;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Handler for SQL injection challenge
+ *
Uses SQL database to query for food menu in vulnerable way, so that user can cause SQL injection.
+ */
+@RequiredArgsConstructor
+public class SqlInjectionHandler implements MessageHandler {
+ private final SqlDatabase database;
+
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof SearchRequest;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ var sqlInjectionRequest = (SearchRequest) message;
+ var search = sqlInjectionRequest.getSearch();
+ // Query for food entities using vulnerable approach
+ var maybeFoodEntities = database.selectList(
+ "SELECT id, name, description, price FROM food WHERE name LIKE '%' || '" + search + "' || '%'",
+ resultSet -> {
+ try {
+ return FoodEntity.builder()
+ .id(resultSet.getInt(1))
+ .name(resultSet.getString(2))
+ .description(resultSet.getString(3))
+ .price(resultSet.getDouble(4))
+ .build();
+ } catch (SQLException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not search food, because SQL exception occurred!", e);
+ }
+ return null;
+ }
+ );
+ var entities = maybeFoodEntities.orElseGet(Collections::emptyList);
+ var response = SearchResponse.builder()
+ .target(ChallengeConstant.SQL_INJECTION_TARGET)
+ .entities(entities)
+ .build();
+ connection.sendMessage(response);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/verticalaccesscontrol/VerticalAccessControlChallenge.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/verticalaccesscontrol/VerticalAccessControlChallenge.java
new file mode 100644
index 0000000..7a20bff
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/verticalaccesscontrol/VerticalAccessControlChallenge.java
@@ -0,0 +1,38 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.verticalaccesscontrol;
+
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.server.challenge.Challenge;
+import com.warxim.vucsa.server.core.ServerManager;
+
+/**
+ * Vertical access control challenge
+ */
+public class VerticalAccessControlChallenge extends Challenge {
+ @Override
+ public void load(ServerManager serverManager) {
+ serverManager.registerHandler(ChallengeConstant.VERTICAL_ACCESS_CONTROL_USER_INFO_TARGET, new VerticalAccessControlUserInfoHandler());
+ serverManager.registerHandler(ChallengeConstant.VERTICAL_ACCESS_CONTROL_SECRET_TARGET, new VerticalAccessControlSecretHandler());
+ }
+
+ @Override
+ public void unload(ServerManager serverManager) {
+ serverManager.unregisterHandler(ChallengeConstant.VERTICAL_ACCESS_CONTROL_SECRET_TARGET);
+ serverManager.unregisterHandler(ChallengeConstant.VERTICAL_ACCESS_CONTROL_USER_INFO_TARGET);
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/verticalaccesscontrol/VerticalAccessControlSecretHandler.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/verticalaccesscontrol/VerticalAccessControlSecretHandler.java
new file mode 100644
index 0000000..cf091ea
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/verticalaccesscontrol/VerticalAccessControlSecretHandler.java
@@ -0,0 +1,44 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.verticalaccesscontrol;
+
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.request.SecretRequest;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.response.SecretResponse;
+
+/**
+ * Handler for secret for vertical access control challenge
+ *
Sends secret response to user that requested it.
+ */
+public class VerticalAccessControlSecretHandler implements MessageHandler {
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof SecretRequest;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ connection.sendMessage(SecretResponse.builder()
+ .target(ChallengeConstant.VERTICAL_ACCESS_CONTROL_SECRET_TARGET)
+ .secret("Congratulations! Now you know that the secret message is: 42!")
+ .build());
+ return true;
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/verticalaccesscontrol/VerticalAccessControlUserInfoHandler.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/verticalaccesscontrol/VerticalAccessControlUserInfoHandler.java
new file mode 100644
index 0000000..551a0ac
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/verticalaccesscontrol/VerticalAccessControlUserInfoHandler.java
@@ -0,0 +1,47 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.verticalaccesscontrol;
+
+import com.warxim.vucsa.common.ChallengeConstant;
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.UserRole;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.request.UserInfoRequest;
+import com.warxim.vucsa.common.message.verticalaccesscontrol.response.UserInfoResponse;
+
+/**
+ * Handler for user info for vertical access control challenge
+ *
Sends user info response to user that requested it.
+ */
+public class VerticalAccessControlUserInfoHandler implements MessageHandler {
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof UserInfoRequest;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ connection.sendMessage(UserInfoResponse.builder()
+ .target(ChallengeConstant.VERTICAL_ACCESS_CONTROL_USER_INFO_TARGET)
+ .id(1)
+ .username("Guest")
+ .role(UserRole.GUEST)
+ .build());
+ return true;
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/xml/XmlChallenge.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/xml/XmlChallenge.java
new file mode 100644
index 0000000..b9da35f
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/xml/XmlChallenge.java
@@ -0,0 +1,36 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.xml;
+
+import com.warxim.vucsa.server.challenge.Challenge;
+import com.warxim.vucsa.server.core.ServerManager;
+import com.warxim.vucsa.common.ChallengeConstant;
+
+/**
+ * XML challenge
+ */
+public class XmlChallenge extends Challenge {
+ @Override
+ public void load(ServerManager serverManager) {
+ serverManager.registerHandler(ChallengeConstant.XML_TARGET, new XmlHandler());
+ }
+
+ @Override
+ public void unload(ServerManager serverManager) {
+ serverManager.unregisterHandler(ChallengeConstant.XML_TARGET);
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/xml/XmlHandler.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/xml/XmlHandler.java
new file mode 100644
index 0000000..aa66e6c
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/challenge/xml/XmlHandler.java
@@ -0,0 +1,40 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.challenge.xml;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.message.Message;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.xml.StorageMessage;
+
+/**
+ * Handler for XML challenge
+ *
Acts as ECHO server, since the vulnerability is present in deserializer.
+ */
+public class XmlHandler implements MessageHandler {
+ @Override
+ public boolean supports(Message message) {
+ return message instanceof StorageMessage;
+ }
+
+ @Override
+ public boolean handleMessage(Connection connection, Message message) {
+ // Echo, vulnerability is implemented in deserializer
+ connection.sendMessage(message);
+ return true;
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/configuration/Configuration.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/configuration/Configuration.java
new file mode 100644
index 0000000..348fa85
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/configuration/Configuration.java
@@ -0,0 +1,30 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.configuration;
+
+import com.warxim.vucsa.server.core.ServerConfig;
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * Configuration
+ */
+@Builder
+@Data
+public class Configuration {
+ private ServerConfig network;
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/configuration/ConfigurationException.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/configuration/ConfigurationException.java
new file mode 100644
index 0000000..6493b6c
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/configuration/ConfigurationException.java
@@ -0,0 +1,33 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.configuration;
+
+/**
+ * Configuration exception for configuration errors
+ * (configuration does not exist, cannot be accessed, invalid fields, ...)
+ */
+public final class ConfigurationException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public ConfigurationException(String message) {
+ super(message);
+ }
+
+ public ConfigurationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/configuration/ConfigurationLoader.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/configuration/ConfigurationLoader.java
new file mode 100644
index 0000000..0ae8f8b
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/configuration/ConfigurationLoader.java
@@ -0,0 +1,55 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.configuration;
+
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonReader;
+import com.warxim.vucsa.common.util.GsonUtils;
+
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.file.NoSuchFileException;
+import java.util.function.Supplier;
+
+/**
+ * Static class for configuration loading.
+ */
+public class ConfigurationLoader {
+ private ConfigurationLoader() { }
+
+ /**
+ * Loads configuration from specified path or get default and save it as configuration if it does not exist.
+ * @param path Path to configuration file
+ * @return Loaded configuration
+ */
+ public static Configuration loadOrDefault(String path, Supplier defaultSupplier) throws ConfigurationException {
+ try (var reader = new JsonReader(new FileReader(path))) {
+ return GsonUtils.getGson()
+ .fromJson(JsonParser.parseReader(reader), Configuration.class);
+ } catch (JsonParseException e) {
+ throw new ConfigurationException("Could not parse configuration!", e);
+ } catch (NoSuchFileException | FileNotFoundException e) {
+ var configuration = defaultSupplier.get();
+ ConfigurationSaver.save(path, configuration);
+ return configuration;
+ } catch (IOException e) {
+ throw new ConfigurationException("Could not load configuration!", e);
+ }
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/configuration/ConfigurationSaver.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/configuration/ConfigurationSaver.java
new file mode 100644
index 0000000..946f8fb
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/configuration/ConfigurationSaver.java
@@ -0,0 +1,47 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.configuration;
+
+import com.warxim.vucsa.common.util.GsonUtils;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.NoSuchFileException;
+
+/**
+ * Static class for configuration saving.
+ */
+public class ConfigurationSaver {
+ private ConfigurationSaver() { }
+
+ /**
+ * Saves configuration to specified path.
+ * @param path Path to configuration file
+ * @param configuration Configuration to be stored
+ */
+ public static void save(String path, Configuration configuration) throws ConfigurationException {
+ var gson = GsonUtils.getGson();
+
+ try (var writer = gson.newJsonWriter(new FileWriter(path))) {
+ gson.toJson(gson.toJsonTree(configuration), writer);
+ } catch (NoSuchFileException e) {
+ throw new ConfigurationException("Could not found configuration!", e);
+ } catch (IOException e) {
+ throw new ConfigurationException("Could not save configuration!", e);
+ }
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/core/Server.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/Server.java
new file mode 100644
index 0000000..688e56e
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/Server.java
@@ -0,0 +1,155 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.core;
+
+import com.warxim.vucsa.server.core.connection.ConnectionManager;
+import com.warxim.vucsa.server.core.listener.ServerListener;
+import com.warxim.vucsa.common.connection.listener.ConnectionListener;
+import com.warxim.vucsa.common.message.MessageHandler;
+import lombok.RequiredArgsConstructor;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.SocketException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Server core.
+ */
+@RequiredArgsConstructor
+public class Server {
+ /**
+ * Configuration of the server.
+ */
+ private final ServerConfig config;
+
+ /**
+ * Server listener for reporting server events.
+ */
+ private final ServerListener serverListener;
+
+ /**
+ * Connection listener for reporting connection events.
+ */
+ private final ConnectionListener connectionListener;
+
+ /**
+ * Message handler for handling received messages.
+ */
+ private final MessageHandler messageHandler;
+
+ /**
+ * State of the server core.
+ */
+ private ServerState state;
+
+ /**
+ * Core thread for accepting connections.
+ */
+ private Thread thread;
+
+ /**
+ * Core server socket.
+ */
+ private ServerSocket serverSocket;
+
+ /**
+ * Manager of connections.
+ */
+ private ConnectionManager connectionManager;
+
+ /**
+ * Starts the server core.
+ */
+ public void start() {
+ Logger.getGlobal().info("Server starting...");
+ state = ServerState.STARTING;
+ serverListener.beforeStart();
+
+ connectionManager = new ConnectionManager(connectionListener, messageHandler);
+ thread = new Thread(this::run);
+ thread.start();
+ }
+
+ /**
+ * Stops the server core.
+ */
+ public void stop() {
+ if (thread != null) {
+ thread.interrupt();
+ closeSocket();
+ }
+ }
+
+ /**
+ * Obtains state of the server.
+ * @return Server state
+ */
+ public ServerState getState() {
+ return state;
+ }
+
+ /**
+ * Runs server core and accepts connections.
+ */
+ private void run() {
+ Logger.getGlobal().info("Server started.");
+ state = ServerState.STARTED;
+ serverListener.afterStart();
+
+ try {
+ serverSocket = new ServerSocket(config.getServerPort(), 4, InetAddress.getByName(config.getServerHost()));
+ while (state == ServerState.STARTED) {
+ var clientSocket = serverSocket.accept();
+ connectionManager.create(clientSocket);
+ }
+ } catch (SocketException e) {
+ // Socket closed
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "IO exception occurred during server socket processing!", e);
+ }
+
+ Logger.getGlobal().info("Server stopping...");
+ state = ServerState.STOPPING;
+ serverListener.beforeStop();
+
+ connectionManager.stop();
+
+ closeSocket();
+
+ Logger.getGlobal().info("Server stopped.");
+ state = ServerState.STOPPED;
+ serverListener.afterStop();
+ }
+
+ /**
+ * Try to close socket.
+ */
+ private void closeSocket() {
+ if (serverSocket == null) {
+ return;
+ }
+
+ try {
+ serverSocket.close();
+ } catch (IOException e) {
+ Logger.getGlobal().log(Level.SEVERE, "Could not close server socket!", e);
+ }
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/core/ServerConfig.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/ServerConfig.java
new file mode 100644
index 0000000..d703257
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/ServerConfig.java
@@ -0,0 +1,37 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.core;
+
+import lombok.Builder;
+import lombok.Value;
+
+/**
+ * Server configuration.
+ */
+@Value
+@Builder
+public class ServerConfig {
+ /**
+ * Server host (127.0.0.1, www.example.org, ...)
+ */
+ String serverHost;
+
+ /**
+ * Server port (8765, ...)
+ */
+ int serverPort;
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/core/ServerManager.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/ServerManager.java
new file mode 100644
index 0000000..fcea93c
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/ServerManager.java
@@ -0,0 +1,120 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.core;
+
+import com.warxim.vucsa.server.core.listener.ServerListenerManager;
+import com.warxim.vucsa.common.connection.listener.ConnectionListenerManager;
+import com.warxim.vucsa.common.message.MessageHandler;
+import com.warxim.vucsa.common.message.MessageHandlerManager;
+import com.warxim.vucsa.server.core.listener.ServerListener;
+
+/**
+ * Server manager for managing server core.
+ *
Wraps all required components and handles server creation, start, stop, ...
+ */
+public class ServerManager implements ServerListener {
+ private final ServerListenerManager serverListenerManager;
+ private final ConnectionListenerManager connectionListenerManager;
+ private final MessageHandlerManager messageHandlerManager;
+ private Server server;
+
+ public ServerManager() {
+ this.serverListenerManager = new ServerListenerManager();
+ this.connectionListenerManager = new ConnectionListenerManager();
+ this.messageHandlerManager = new MessageHandlerManager();
+ serverListenerManager.registerListener(this);
+ }
+
+ /**
+ * Creates and starts server core.
+ * @param config Server configuration
+ */
+ public synchronized void start(ServerConfig config) {
+ if (server != null) {
+ return;
+ }
+
+ server = new Server(
+ config,
+ serverListenerManager,
+ connectionListenerManager,
+ messageHandlerManager
+ );
+ server.start();
+ }
+
+ /**
+ * Stops server core.
+ */
+ public synchronized void stop() {
+ if (server == null) {
+ return;
+ }
+
+ server.stop();
+ }
+
+ /**
+ * Obtains server core state.
+ * @return Connection state
+ */
+ public synchronized ServerState getState() {
+ if (server == null) {
+ return ServerState.STOPPED;
+ }
+
+ return server.getState();
+ }
+
+ /**
+ * Registers server listener.
+ * @param serverListener Listener to be registered
+ */
+ public void registerServerListener(ServerListener serverListener) {
+ serverListenerManager.registerListener(serverListener);
+ }
+
+ /**
+ * Unregisters server listener.
+ * @param serverListener Listener to be unregistered
+ */
+ public void unregisterServerListener(ServerListener serverListener) {
+ serverListenerManager.unregisterListener(serverListener);
+ }
+
+ /**
+ * Registers message handler.
+ * @param target Target identifier of the handler
+ * @param messageHandler Handler to be registered
+ */
+ public void registerHandler(int target, MessageHandler messageHandler) {
+ messageHandlerManager.registerHandler(target, messageHandler);
+ }
+
+ /**
+ * Unregisters message handler.
+ * @param target Target identifier of the handler
+ */
+ public void unregisterHandler(int target) {
+ messageHandlerManager.unregisterHandler(target);
+ }
+
+ @Override
+ public void afterStop() {
+ server = null;
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/core/ServerState.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/ServerState.java
new file mode 100644
index 0000000..7799314
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/ServerState.java
@@ -0,0 +1,39 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.core;
+
+/**
+ * State of server.
+ */
+public enum ServerState {
+ /**
+ * Server is starting
+ */
+ STARTING,
+ /**
+ * Server is running
+ */
+ STARTED,
+ /**
+ * Server is stopping
+ */
+ STOPPING,
+ /**
+ * Server is offline
+ */
+ STOPPED
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/core/connection/ConnectionManager.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/connection/ConnectionManager.java
new file mode 100644
index 0000000..f550aae
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/connection/ConnectionManager.java
@@ -0,0 +1,94 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.core.connection;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.connection.listener.ConnectionListener;
+import com.warxim.vucsa.common.message.MessageHandler;
+import lombok.RequiredArgsConstructor;
+
+import java.net.Socket;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Connection manager for handling all active connections.
+ */
+@RequiredArgsConstructor
+public class ConnectionManager implements ConnectionListener {
+ /**
+ * External connection listener for reporting connection events.
+ */
+ private final ConnectionListener connectionListener;
+
+ /**
+ * Message handler for connections.
+ */
+ private final MessageHandler messageHandler;
+
+ /**
+ * Internal counter for generating connection identifiers.
+ */
+ private final AtomicInteger counter = new AtomicInteger();
+
+ /**
+ * Map of connections (mapped by identifier).
+ */
+ private final ConcurrentHashMap connections = new ConcurrentHashMap<>();
+
+ /**
+ * Obtains connection with given identifier.
+ * @return Connection or empty optional if it does not exist
+ */
+ public Optional get(int id) {
+ return Optional.ofNullable(connections.get(id));
+ }
+
+ /**
+ * Creates server connection and persists it in the manager.
+ * @param socket Client socket
+ * @return Created server connection
+ */
+ public ServerConnection create(Socket socket) {
+ var connection = new ServerConnection(generateId(), socket, this, messageHandler);
+ connection.start();
+ connections.put(connection.getId(), connection);
+ connectionListener.onConnectionStart(connection);
+ return connection;
+ }
+
+ /**
+ * Stops connection manager with all its connections.
+ */
+ public void stop() {
+ connections.values().forEach(ServerConnection::stop);
+ }
+
+ @Override
+ public void onConnectionStop(Connection connection) {
+ connections.remove(connection.getId());
+ connectionListener.onConnectionStop(connection);
+ }
+
+ /**
+ * Generates new connection identifier.
+ */
+ private int generateId() {
+ return counter.incrementAndGet();
+ }
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/core/connection/ServerConnection.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/connection/ServerConnection.java
new file mode 100644
index 0000000..22f9256
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/connection/ServerConnection.java
@@ -0,0 +1,34 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.core.connection;
+
+import com.warxim.vucsa.common.connection.Connection;
+import com.warxim.vucsa.common.connection.listener.ConnectionListener;
+import com.warxim.vucsa.common.message.MessageHandler;
+
+import java.net.Socket;
+
+/**
+ * Server connection representing connection between client and server.
+ */
+public class ServerConnection extends Connection {
+ public ServerConnection(int id, Socket socket, ConnectionListener listener, MessageHandler handler) {
+ super(id, listener, handler);
+ this.socket = socket;
+ }
+}
+
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/core/listener/ServerListener.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/listener/ServerListener.java
new file mode 100644
index 0000000..982d5cd
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/listener/ServerListener.java
@@ -0,0 +1,42 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.core.listener;
+
+/**
+ * Server listener for listening for server events.
+ */
+public interface ServerListener {
+ /**
+ * Event before start step is processed (server is starting).
+ */
+ default void beforeStart() {}
+
+ /**
+ * Event after start step is processed (server is running).
+ */
+ default void afterStart() {}
+
+ /**
+ * Event before stop step is processed (server is stopping).
+ */
+ default void beforeStop() {}
+
+ /**
+ * Event before stop step is processed (server is offline).
+ */
+ default void afterStop() {}
+}
diff --git a/vucsa-server/src/main/java/com/warxim/vucsa/server/core/listener/ServerListenerManager.java b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/listener/ServerListenerManager.java
new file mode 100644
index 0000000..0a68d2c
--- /dev/null
+++ b/vucsa-server/src/main/java/com/warxim/vucsa/server/core/listener/ServerListenerManager.java
@@ -0,0 +1,45 @@
+/*
+ * Vulnerable Client-Server Application (VuCSA)
+ *
+ * Copyright (C) 2021 Michal Válka
+ *
+ * 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 .
+ */
+package com.warxim.vucsa.server.core.listener;
+
+import com.warxim.vucsa.common.listener.ListenerManager;
+
+/**
+ * Listener manager that allows modules to register their own listener (aggregates listeners).
+ *