├── demo └── bspe00.png ├── param-regular.cfg ├── sensitive-params.txt ├── README.md ├── LICENSE └── burp-sensitive-param-extractor.py /demo/bspe00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theLSA/burp-sensitive-param-extractor/HEAD/demo/bspe00.png -------------------------------------------------------------------------------- /param-regular.cfg: -------------------------------------------------------------------------------- 1 | id 2 | user 3 | file 4 | token 5 | f 6 | cb 7 | auth 8 | callback 9 | url 10 | flag 11 | name -------------------------------------------------------------------------------- /sensitive-params.txt: -------------------------------------------------------------------------------- 1 | userid 2 | methodid 3 | token 4 | id 5 | file 6 | cityid 7 | url 8 | cb 9 | countyid 10 | username 11 | callback 12 | user 13 | SID_1 14 | USER_NAME_COOKIE 15 | flag 16 | filename 17 | idcard 18 | authcode 19 | nickname -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # burp-sensive-param-extractor 2 | 3 | ## 概述 4 | 5 | 检测并提取请求参数中的敏感参数名,如userid,username,方便测试越权漏洞,并形成敏感参数字典。 6 | 7 | 关于该插件的实现细节,参考[burpsuite插件开发总结](https://www.lsablog.com/networksec/penetration/burpsuite-plugin-development/) 8 | 9 | ## 快速开始 10 | 11 | param-regular.cfg:参数正则配置文件,id表示请求参数中包含id的参数,如userid,idcard等。 12 | 13 | sensitive-params.txt:参数字典文件。 14 | 15 | 支持4种参数检测 16 | 17 | self.requestParamDict['urlParams'] = [] 18 | 19 | self.requestParamDict['BodyParams'] = [] 20 | 21 | self.requestParamDict['cookieParams'] = [] 22 | 23 | self.requestParamDict['jsonParams'] = [] 24 | 25 | 界面右侧的列表即参数正则,可实时增删,删除只需单击列表元素再点击删除按钮即可。 26 | 27 | ![](https://github.com/theLSA/burp-sensitive-param-extractor/raw/master/demo/bspe00.png) 28 | 29 | ## 反馈 30 | 31 | [issues](https://github.com/theLSA/burp-sensitive-param-extractor/issues) 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 LSA 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /burp-sensitive-param-extractor.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | #Author:LSA 3 | #Date:20200630 4 | #Description:sensitive parameter extractor-burpsuite extension 5 | 6 | import json 7 | import re 8 | 9 | from burp import IBurpExtender, ITab, IHttpListener 10 | from javax.swing import JPanel, JLabel, JButton, JTextArea, JTextField, JCheckBox, JTabbedPane, JScrollPane, SwingConstants, JFileChooser, JList, JOptionPane 11 | from java.awt import BorderLayout, Font, Color 12 | 13 | from java.io import PrintWriter 14 | 15 | 16 | # config 17 | paramRegularFile = "param-regular.cfg" 18 | 19 | sensitiveParamsFile = "sensitive-params.txt" 20 | 21 | # get paramRegualrList from paramRegularFile 22 | def getParamRegular(): 23 | paramRegularList = [] 24 | with open(paramRegularFile, 'r') as prf: 25 | for paramR in prf.readlines(): 26 | paramRegularList.append(paramR.strip()) 27 | return paramRegularList 28 | 29 | 30 | 31 | 32 | def getSensitiveParamsFromFile(): 33 | sensitiveParamsList = [] 34 | with open(sensitiveParamsFile, 'r') as spf: 35 | for sensitiveParam in spf.readlines(): 36 | sensitiveParamsList.append(sensitiveParam.strip()) 37 | return sensitiveParamsList 38 | 39 | class BurpExtender(IBurpExtender, ITab,IHttpListener): 40 | def registerExtenderCallbacks(self, callbacks): 41 | self._callbacks = callbacks 42 | self._helpers = callbacks.getHelpers() 43 | callbacks.setExtensionName("burp-sensitive-param-extractor") 44 | self._stdout = PrintWriter(callbacks.getStdout(), True) 45 | callbacks.registerHttpListener(self) 46 | #callbacks.registerMessageEditorTabFactory(self) 47 | print 'burp-sensitive-param-extractor loaded.\nAuthor:LSA\nhttps://github.com/theLSA/burp-sensitive-param-extractor' 48 | 49 | 50 | self.sensitiveParamR = getParamRegular() 51 | 52 | self._callbacks.customizeUiComponent(self.getUiComponent()) 53 | self._callbacks.addSuiteTab(self) 54 | #self.endColors = [] 55 | self.requestParamDict = {} 56 | self.resultSensitiveParamsDict = {} 57 | 58 | 59 | def getTabCaption(self): 60 | return 'BSPE' 61 | 62 | 63 | def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): 64 | 65 | if messageIsRequest and toolFlag==4: 66 | self.requestParamDict['urlParams'] = [] 67 | self.requestParamDict['BodyParams'] = [] 68 | self.requestParamDict['cookieParams'] = [] 69 | self.requestParamDict['jsonParams'] = [] 70 | 71 | cookieParamFlag = 0 72 | 73 | service = messageInfo.getHttpService() 74 | request = messageInfo.getRequest() 75 | analyzeReq = self._helpers.analyzeRequest(service,request) 76 | reqUrl = self._helpers.analyzeRequest(messageInfo).getUrl() 77 | reqMethod = self._helpers.analyzeRequest(messageInfo).getMethod() 78 | 79 | 80 | reqParams = analyzeReq.getParameters() 81 | 82 | 83 | 84 | for param in reqParams: 85 | paramType = param.getType() 86 | 87 | if paramType == 0: 88 | #self.outputTxtArea.append("\nurlParams-") 89 | 90 | paramName = param.getName() 91 | paramValue = param.getValue() 92 | print 'urlParams:' 93 | print paramName + ':' + paramValue 94 | #self.outputTxtArea.append("[%s]" % paramName) 95 | self.requestParamDict['urlParams'].append(paramName.strip()) 96 | 97 | 98 | if paramType == 1: 99 | #self.outputTxtArea.append("\nBodyParams-") 100 | 101 | paramName = param.getName() 102 | paramValue = param.getValue() 103 | print 'BodyParams:' 104 | print paramName + ':' + paramValue 105 | #self.outputTxtArea.append("[%s]\n" % paramName) 106 | self.requestParamDict['BodyParams'].append(paramName.strip()) 107 | 108 | if paramType == 2: 109 | #self.outputTxtArea.append("\ncookieParams-") 110 | 111 | paramName = param.getName() 112 | paramValue = param.getValue() 113 | print 'CookieParams:' 114 | print paramName + ':' + paramValue 115 | #self.outputTxtArea.append("[%s]\n" % paramName) 116 | self.requestParamDict['cookieParams'].append(paramName.strip()) 117 | cookieParamFlag = 1 118 | 119 | if paramType == 6: 120 | #self.outputTxtArea.append("\njsonParams-") 121 | 122 | paramName = param.getName() 123 | paramValue = param.getValue() 124 | print 'JsonParams:' 125 | print paramName + ':' + paramValue 126 | #self.outputTxtArea.append("[%s]\n" % paramName) 127 | self.requestParamDict['jsonParams'].append(paramName.strip()) 128 | 129 | self.resultSensitiveParamsDict = self.findSensitiveParam(self.requestParamDict) 130 | #print self.resultSensitiveParamsDict 131 | 132 | 133 | for rspdKey in self.resultSensitiveParamsDict.keys(): 134 | if self.resultSensitiveParamsDict[rspdKey] != []: 135 | print "[%s][%s]" % (reqMethod,reqUrl) 136 | self.outputTxtArea.append("\n------------------------------------------------------\n") 137 | self.outputTxtArea.append("[%s][%s]\n" % (reqMethod,reqUrl)) 138 | break 139 | 140 | for rspdKey in self.resultSensitiveParamsDict.keys(): 141 | if self.resultSensitiveParamsDict[rspdKey] != []: 142 | self.outputTxtArea.append("\n"+rspdKey+"--"+str(self.resultSensitiveParamsDict[rspdKey])) 143 | 144 | self.write2file() 145 | 146 | 147 | 148 | #pass 149 | 150 | else: 151 | return 152 | 153 | 154 | def findSensitiveParam(self,requestParamDict): 155 | #sensitiveParamR = getParamRegular() 156 | resultSensitiveParamsDict = {} 157 | resultSensitiveParamsDict['urlParams'] = [] 158 | 159 | resultSensitiveParamsDict['BodyParams'] = [] 160 | 161 | resultSensitiveParamsDict['cookieParams'] = [] 162 | 163 | resultSensitiveParamsDict['jsonParams'] = [] 164 | 165 | #print requestParamDict 166 | 167 | for spr in self.sensitiveParamR: 168 | for key in requestParamDict.keys(): 169 | for reqParam in requestParamDict[key]: 170 | if len(spr)==1: 171 | if spr == reqParam.lower(): 172 | resultSensitiveParamsDict[key].append(reqParam) 173 | else: 174 | if spr in reqParam.lower(): 175 | print spr + ' in ' + reqParam 176 | resultSensitiveParamsDict[key].append(reqParam) 177 | #print resultSensitiveParamsDict 178 | for key in resultSensitiveParamsDict.keys(): 179 | resultSensitiveParamsDict[key] = {}.fromkeys(resultSensitiveParamsDict[key]).keys() 180 | #resultSensitiveParamsDict[key] = sorted(resultSensitiveParamsDict[key],key=resultSensitiveParamsDict[key].index) 181 | #print resultSensitiveParamsDict 182 | return resultSensitiveParamsDict 183 | 184 | 185 | 186 | def write2file(self): 187 | sensitiveParamsList = getSensitiveParamsFromFile() 188 | newSensitiveParamsList = [] 189 | #print self.resultSensitiveParamsDict 190 | for rspdKey in self.resultSensitiveParamsDict.keys(): 191 | if (self.resultSensitiveParamsDict[rspdKey] != []) and (set(self.resultSensitiveParamsDict[rspdKey]).issubset(set(sensitiveParamsList)) == False): 192 | newSensitiveParamsList.extend([newSensitiveParam for newSensitiveParam in self.resultSensitiveParamsDict[rspdKey] if newSensitiveParam not in sensitiveParamsList]) 193 | #print str(newSensitiveParamsList) 194 | 195 | if newSensitiveParamsList != []: 196 | newSensitiveParamsList = {}.fromkeys(newSensitiveParamsList).keys() 197 | 198 | with open('sensitive-params.txt','a') as sps: 199 | for nsp in newSensitiveParamsList: 200 | #print 'writeNewParams:'+nsp 201 | sps.write('\n'+nsp) 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | def addAndSaveNewParamRegular(self, event): 210 | NewParamRegular = self.addAndSaveNewParamRegularTextField.getText() 211 | if NewParamRegular not in self.sensitiveParamR: 212 | self.sensitiveParamR.append(NewParamRegular) 213 | with open(paramRegularFile,'a') as prf: 214 | prf.write('\n'+NewParamRegular) 215 | self.alertSaveSuccess.showMessageDialog(self.spePanel, "Add and save success!") 216 | else: 217 | self.alertSaveSuccess.showMessageDialog(self.tab, "paramRegular existed.") 218 | 219 | self.sensitiveParamsRegularListPanel.setListData(self.sensitiveParamR) 220 | self.sensitiveParamsRegularListPanel.revalidate() 221 | 222 | #self.sensitiveParamR = getParamRegular() 223 | 224 | 225 | 226 | def delParamRegular(self,event): 227 | #delParamRegularsIndex = self.sensitiveParamsRegularListPanel.selectedIndex 228 | #if delParamRegularsIndex >= 0: 229 | # print delParamRegularsIndex 230 | # print self.sensitiveParamR[delParamRegularsIndex] 231 | for sprlp in self.sensitiveParamsRegularListPanel.getSelectedValuesList(): 232 | #print sprlp 233 | self.sensitiveParamR.remove(sprlp) 234 | 235 | #with open(paramRegularFile,'r') as prf1: 236 | # lines = prf1.readlines() 237 | 238 | with open(paramRegularFile,'w') as prf2: 239 | #print self.sensitiveParamsRegularListPanel.getSelectedValuesList() 240 | #for line in lines: 241 | # if line.strip() in self.sensitiveParamsRegularListPanel.getSelectedValuesList(): 242 | # print 'remove:'+line 243 | # lines.remove(line) 244 | #for spr1 in lines: 245 | # #print spr1 246 | # prf2.write(spr1) 247 | for spr2i, spr2 in enumerate(self.sensitiveParamR): 248 | print spr2i 249 | print spr2 250 | if spr2i == len(self.sensitiveParamR)-1: 251 | prf2.write(spr2) 252 | else: 253 | prf2.write(spr2+'\n') 254 | 255 | self.sensitiveParamsRegularListPanel.setListData(self.sensitiveParamR) 256 | self.sensitiveParamsRegularListPanel.revalidate() 257 | 258 | #self.sensitiveParamR = getParamRegular() 259 | 260 | 261 | 262 | 263 | 264 | def clearRst(self, event): 265 | self.outputTxtArea.setText("") 266 | 267 | def exportRst(self, event): 268 | chooseFile = JFileChooser() 269 | ret = chooseFile.showDialog(self.logPane, "Choose file") 270 | filename = chooseFile.getSelectedFile().getCanonicalPath() 271 | print "\n" + "Export to : " + filename 272 | open(filename, 'w', 0).write(self.outputTxtArea.text) 273 | 274 | 275 | 276 | 277 | def getUiComponent(self): 278 | self.spePanel = JPanel() 279 | self.spePanel.setBorder(None) 280 | self.spePanel.setLayout(None) 281 | 282 | self.logPane = JScrollPane() 283 | self.outputTxtArea = JTextArea() 284 | self.outputTxtArea.setFont(Font("Consolas", Font.PLAIN, 12)) 285 | self.outputTxtArea.setLineWrap(True) 286 | self.logPane.setViewportView(self.outputTxtArea) 287 | self.spePanel.add(self.logPane) 288 | 289 | self.clearBtn = JButton("Clear", actionPerformed=self.clearRst) 290 | self.exportBtn = JButton("Export", actionPerformed=self.exportRst) 291 | self.parentFrm = JFileChooser() 292 | 293 | self.spePanel.add(self.clearBtn) 294 | self.spePanel.add(self.exportBtn) 295 | 296 | self.logPane.setBounds(20,50,800,600) 297 | 298 | self.clearBtn.setBounds(20,650,100,30) 299 | self.exportBtn.setBounds(600,650,100,30) 300 | 301 | self.sensitiveParamsRegularListPanel = JList(self.sensitiveParamR) 302 | self.sensitiveParamsRegularListPanel.setVisibleRowCount(len(self.sensitiveParamR)) 303 | 304 | #self.spePanel.add(self.sensitiveParamsRegularListPanel) 305 | 306 | #self.sensitiveParamsRegularListPanel.setBounds(850,50,150,600) 307 | 308 | self.sensitiveParamsRegularListScrollPanel = JScrollPane() 309 | self.sensitiveParamsRegularListScrollPanel.setViewportView(self.sensitiveParamsRegularListPanel) 310 | self.spePanel.add(self.sensitiveParamsRegularListScrollPanel) 311 | self.sensitiveParamsRegularListScrollPanel.setBounds(850,50,150,600) 312 | 313 | self.addAndSaveNewParamRegularButton = JButton('add&&save',actionPerformed=self.addAndSaveNewParamRegular) 314 | self.spePanel.add(self.addAndSaveNewParamRegularButton) 315 | self.addAndSaveNewParamRegularButton.setBounds(1000,50,150,30) 316 | 317 | self.addAndSaveNewParamRegularTextField = JTextField('NewParamRegular') 318 | self.spePanel.add(self.addAndSaveNewParamRegularTextField) 319 | self.addAndSaveNewParamRegularTextField.setBounds(1150,50,100,30) 320 | 321 | self.alertSaveSuccess = JOptionPane() 322 | self.spePanel.add(self.alertSaveSuccess) 323 | 324 | self.delParamRegularButton = JButton("delete",actionPerformed=self.delParamRegular) 325 | self.spePanel.add(self.delParamRegularButton) 326 | self.delParamRegularButton.setBounds(1000,90,100,30) 327 | 328 | return self.spePanel --------------------------------------------------------------------------------