class HTTPTamperDialog(QDialog): def __init__(self, netmanager, op, qrequest, outgoingDataList = None, parent = None): QDialog.__init__(self, parent) # passed args saved for further update, etc. self.netmanager = netmanager self.op = op self.qrequest = qrequest self.outgoingDataList = outgoingDataList # storage of the HTTPRequest self.nrequest = None # QTree widget to represent the different editable information self.request = TamperTreeWidget() self.request.setRootIsDecorated(False) self.request.setAlternatingRowColors(True) self.request.setSortingEnabled(False) self.request.setEditTriggers(QAbstractItemView.DoubleClicked) self.request.setHeaderLabels(['HTTP Header', 'value']) self.request.resizeColumnToContents(0) self.request.setWordWrap(True) QObject.connect(self.request, SIGNAL("itemChanged(QTreeWidgetItem *, int)"), self.requestChangedItemHeaders_Slot) QObject.connect(self.request, SIGNAL("addRowTreeWidget"), self.addRowTreeWidget_Slot) QObject.connect(self.request, SIGNAL("duplicateRowTreeWidget"), self.duplicateRowTreeWidget_Slot) QObject.connect(self.request, SIGNAL("deleteRowTreeWidget"), self.deleteRowTreeWidget_Slot) self.gbox = QGroupBox("&Header Tampering") self.continue_tampering = QCheckBox("&Continue Tampering") self.continue_tampering.setCheckState(Qt.Checked) self.apply_transformation = QCheckBox("&Apply These Transformations on Subsequent Requests") QObject.connect(self.continue_tampering, SIGNAL('stateChanged(int)'), self.stateChanged_ContinueTampering_Slot) QObject.connect(self.apply_transformation, SIGNAL('stateChanged(int)'), self.stateChanged_ApplyTransformation_Slot) self.refresh_values = QPushButton("&Reload Values") self.refresh_values.setEnabled(False) self.send_request = QPushButton("&Send Request") self.cancel_request = QPushButton("&Close") QObject.connect(self.refresh_values, SIGNAL('pressed()'), self.reloadRequest_Slot) QObject.connect(self.cancel_request, SIGNAL('pressed()'), self.cancel_Slot) QObject.connect(self.send_request, SIGNAL('pressed()'), self.accept_Slot) vlayout = QVBoxLayout() vlayout.addWidget(self.continue_tampering) vlayout.addWidget(self.apply_transformation) self.gbox.setLayout(vlayout) blayout = QHBoxLayout() blayout.addWidget(self.refresh_values) blayout.addWidget(self.cancel_request) blayout.addWidget(self.send_request) layout = QVBoxLayout() layout.addWidget(self.gbox) layout.addWidget(self.request) layout.addLayout(blayout) self.setModal(False) self.setLayout(layout) # fill the data self.updateRequest() self.setMinimumSize(520,300) self.resize(900,600) def updateRequest(self): self.request.setUpdatesEnabled(False) self.request.clear() url = self.qrequest.url() # process request root = QTreeWidgetItem() root.setText(0, core.network.getHTTPMethodString(self.op)) root.setText(1, url.toString(QUrl.StripTrailingSlash)) root.setFlags(root.flags() | Qt.ItemIsEditable) self.request.invisibleRootItem().addChild(root) for h in self.qrequest.rawHeaderList(): item = QTreeWidgetItem() item.setText(0, QString(h)) item.setText(1, QString(self.qrequest.rawHeader(h))) item.setFlags(item.flags() | Qt.ItemIsEditable) self.request.invisibleRootItem().addChild(item) cookies = self.netmanager.cookieJar().cookiesForUrl(url) if cookies and 0 < len(cookies): separator_0 = QTreeWidgetItem() separator_0.setText(0, '-') self.request.invisibleRootItem().addChild(separator_0) tree_cookies = QTreeWidgetItem() tree_cookies.setText(0, "Cookies") tree_cookies.setText(1, "") self.request.invisibleRootItem().addChild(tree_cookies) for elmt in cookies: item = QTreeWidgetItem() item.setText(0, QString(elmt.name())) item.setText(1, QString(elmt.toRawForm()).remove(QString(elmt.name()+' = '))) item.setFlags(item.flags() | Qt.ItemIsEditable) tree_cookies.addChild(item) self.request.expandAll() if self.outgoingDataList and 0 < len(self.outgoingDataList): separator_1 = QTreeWidgetItem() separator_1.setText(0, '-') self.request.invisibleRootItem().addChild(separator_1) tree_post = QTreeWidgetItem() tree_post.setText(0, "POST data") tree_post.setText(1, "") self.request.invisibleRootItem().addChild(tree_post) for elmts in self.outgoingDataList: item = QTreeWidgetItem() item.setText(0, elmts[0]) if 2 == len(elmts): item.setText(1, elmts[1]) item.setFlags(item.flags() | Qt.ItemIsEditable) tree_post.addChild(item) self.request.expandAll() self.request.setUpdatesEnabled(True) def getHTTPRequest(self): return self.nrequest def prepareRequest(self): # load all the components in an HTTPRequest structure if self.refresh_values.isEnabled(): # retrieve data self.nrequest = HTTPRequest() nrequest = {'method' : None, 'url' : None, 'headers' : [], 'cookies' : [], 'post' : []} request_iter = QTreeWidgetIterPy(self.request) firstiter, state = True, "headers" for elmt in request_iter: if firstiter: nrequest['method'] = elmt.text(0) nrequest['url'] = elmt.text(1) firstiter = False else: # state: headers -> cookies -> post if "-" == elmt.text(0): continue if "headers" == state: if "Cookies" == elmt.text(0): state = "cookies" continue elif "POST data" == elmt.text(0): state = "post" continue elif "cookies" == state: if "POST data" == elmt.text(0): state = "post" continue nrequest[state].append((elmt.text(0), elmt.text(1))) self.nrequest.setMethod(nrequest['method']) self.nrequest.setUrl(nrequest['url']) self.nrequest.setHeaders(nrequest['headers']) # set tampered cookies in the current cookiejar if nrequest['cookies'] and 0 < len(nrequest['cookies']): self.nrequest.setCookies(nrequest['cookies']) self.netmanager.cookieJar().setCookiesFromUrl(self.nrequest.getQtCookies(), self.nrequest.url) # process and store the POST data using post_history structure if nrequest['post'] and 0 < len(nrequest['post']): self.nrequest.setData(nrequest['post']) def reloadRequest_Slot(self): self.updateRequest() self.nrequest = None self.refresh_values.setEnabled(False) def requestChangedItemHeaders_Slot(self, item, col): self.refresh_values.setEnabled(True) def stateChanged_ApplyTransformation_Slot(self, state): pass def stateChanged_ContinueTampering_Slot(self, state): if Qt.Unchecked == state: self.netmanager.setIntercept(False) else: self.netmanager.setIntercept(True) def addRowTreeWidget_Slot(self, item): p = item.parent() new_item = QTreeWidgetItem() new_item.setText(0, "") new_item.setText(1, "") new_item.setFlags(new_item.flags() | Qt.ItemIsEditable) if p: p.addChild(new_item) else: self.request.invisibleRootItem().addChild(new_item) def duplicateRowTreeWidget_Slot(self, item): p = item.parent() new_item = QTreeWidgetItem() new_item.setText(0, item.text(0)) new_item.setText(1, item.text(1)) new_item.setFlags(new_item.flags() | Qt.ItemIsEditable) if p: p.addChild(new_item) else: self.request.invisibleRootItem().addChild(new_item) def deleteRowTreeWidget_Slot(self, item): self.request.invisibleRootItem().removeChild(item) def accept_Slot(self): self.prepareRequest() self.accept() def cancel_Slot(self): self.reject()
class TamperingData(QWidget): """ tampering data widget in dock """ def __init__(self, netmanager, parent = None): QWidget.__init__(self, parent) self.netmanager = netmanager self.current_request_id = 0 self.smartview = SmartView(self) self.smartview.hide() self.requestview = TamperTreeWidget() self.requestview.setRootIsDecorated(False) self.requestview.setAlternatingRowColors(True) self.requestview.setSortingEnabled(False) self.requestview.setEditTriggers(QAbstractItemView.DoubleClicked) self.requestview.setHeaderLabels(['HTTP Request Header', 'Value']) self.requestview.resizeColumnToContents(0) self.requestview.setWordWrap(True) QObject.connect(self.requestview, SIGNAL("itemChanged(QTreeWidgetItem *, int)"), self.requestChangedItem_Slot) QObject.connect(self.requestview, SIGNAL("addRowTreeWidget"), self.addRowTreeWidget_Slot) QObject.connect(self.requestview, SIGNAL("duplicateRowTreeWidget"), self.duplicateRowTreeWidget_Slot) QObject.connect(self.requestview, SIGNAL("deleteRowTreeWidget"), self.deleteRowTreeWidget_Slot) self.responseview = QTreeWidget() self.responseview.setRootIsDecorated(False) self.responseview.setAlternatingRowColors(True) self.responseview.setSortingEnabled(False) self.responseview.setHeaderLabels(['HTTP Response Header', 'Value']) self.responseview.resizeColumnToContents(0) self.gbox = QGroupBox("&HTTP Request") self.refresh_button = QPushButton("Refresh") self.refresh_button.setEnabled(False) QObject.connect(self.refresh_button, SIGNAL("pressed()"), self.refreshViews_Slot) self.response_button = QPushButton("HTTP response body") QObject.connect(self.response_button, SIGNAL("pressed()"), self.viewResponse_Slot) self.replay_button = QPushButton("Make request") QObject.connect(self.replay_button, SIGNAL("pressed()"), self.replayRequest_Slot) self.export_button = QPushButton("Export as...") QObject.connect(self.replay_button, SIGNAL("pressed()"), self.exportRequest_Slot) self.addTestCases_button = QPushButton("Add to test cases") QObject.connect(self.addTestCases_button, SIGNAL("pressed()"), self.addTestCaseRequest_Slot) self.addFinding_button = QPushButton("Add to findings") QObject.connect(self.addFinding_button, SIGNAL("pressed()"), self.addFindingRequest_Slot) vlayout = QVBoxLayout() vlayout.addWidget(self.response_button) vlayout.addWidget(self.refresh_button) vlayout.addWidget(self.replay_button) vlayout.addWidget(self.export_button) vlayout.addWidget(self.addTestCases_button) vlayout.addWidget(self.addFinding_button) self.gbox.setLayout(vlayout) layout = QHBoxLayout() layout.addWidget(self.gbox) layout.addWidget(self.requestview) layout.addWidget(self.responseview) self.setLayout(layout) def addRowTreeWidget_Slot(self, item): p = item.parent() new_item = QTreeWidgetItem() new_item.setText(0, "") new_item.setText(1, "") new_item.setFlags(new_item.flags() | Qt.ItemIsEditable) if p: p.addChild(new_item) else: self.requestview.invisibleRootItem().addChild(new_item) def duplicateRowTreeWidget_Slot(self, item): p = item.parent() new_item = QTreeWidgetItem() new_item.setText(0, item.text(0)) new_item.setText(1, item.text(1)) new_item.setFlags(new_item.flags() | Qt.ItemIsEditable) if p: p.addChild(new_item) else: self.requestview.invisibleRootItem().addChild(new_item) def deleteRowTreeWidget_Slot(self, item): self.requestview.invisibleRootItem().removeChild(item) def viewResponse_Slot(self): # create popup with smart document preview if 0 < self.current_request_id: self.smartview.setWindowFlags(Qt.Window) content, content_type = self.netmanager.getResponseContent(self.current_request_id) if content: self.smartview.show() self.smartview.setContent(content, content_type) def retrieveHeader(self): headers = [] self.requestview def addFindingRequest_Slot(self): if 0 < self.current_request_id: self.emit(SIGNAL('addRequestIDtoFindings_Signal'), [self.current_request_id]) def addTestCaseRequest_Slot(self): if 0 < self.current_request_id: self.emit(SIGNAL('addRequestIDtoTestCases_Signal'), [self.current_request_id]) def exportRequest_Slot(self): # if modified, send to tamper.create_request to forge the new request # else, send the request_id for a simple replay based on historical requests if self.refresh_button.isEnabled(): # retrieve data nrequest = {'method' : None, 'url' : None, 'headers' : [], 'cookies' : [], 'post' : []} request_iter = QTreeWidgetIterPy(self.requestview) firstiter, state = True, "headers" for elmt in request_iter: if firstiter: nrequest['method'] = elmt.text(0) nrequest['url'] = elmt.text(1) firstiter = False else: # state: headers -> cookies -> post if "-" == elmt.text(0): continue if "headers" == state: if "Cookies" == elmt.text(0): state = "cookies" continue elif "POST data" == elmt.text(0): state = "post" continue elif "cookies" == state: if "POST data" == elmt.text(0): state = "post" continue nrequest[state].append((elmt.text(0), elmt.text(1))) nrequest[state].append((elmt.text(0), elmt.text(1))) self.emit(SIGNAL('createHTTPRequest'), nrequest) else: self.emit(SIGNAL('createHTTPRequest'), self.current_request_id) def replayRequest_Slot(self): request_headers = self.retrieveHeader() def requestChangedItem_Slot(self, item, col): self.refresh_button.setEnabled(True) def refreshViews_Slot(self): self.setRequestResponse_Slot(self.current_request_id) self.refresh_button.setEnabled(False) @staticmethod def __create_treeitem(name, value, icon = None): if not isinstance(name, QString): name = QString(name) if not isinstance(value, QString): value = QString(value) item = QTreeWidgetItem() item.setText(0, name) if icon: item.setIcon(0, icon) item.setText(1, value) item.setFlags(item.flags() | Qt.ItemIsEditable) return item @staticmethod def __create_treeseparator(name): bgColor = QColor(0, 0, 255, 25) if not isinstance(name, QString): name = QString(name) item = QTreeWidgetItem() item.setText(0, name) item.setBackgroundColor(0, bgColor) item.setBackgroundColor(1, bgColor) return item def setRequestResponse_Slot(self, request_id): self.current_request_id = request_id info = self.netmanager.getNetworkHistory(request_id) self.requestview.setUpdatesEnabled(False) self.requestview.clear() # process request item = QTreeWidgetItem() item.setText(0, info['type']) item.setText(1, info['request']['url'].toString(QUrl.StripTrailingSlash)) item.setFlags(item.flags() | Qt.ItemIsEditable) self.requestview.invisibleRootItem().addChild(item) for h in info['request']['headers']: self.requestview.invisibleRootItem().addChild(TamperingData.__create_treeitem(h[0], h[1] if 2 == len(h) else "")) # add Cookies view for request if info['request']['cookies']: cookies = info['request']['cookies'] tree_cookies = TamperingData.__create_treeseparator("Cookies") self.requestview.invisibleRootItem().addChild(tree_cookies) for elmt in cookies: tree_cookies.addChild(TamperingData.__create_treeitem(QString(elmt.name()), QString(elmt.toRawForm()).remove(QString(elmt.name()+' = ')))) self.requestview.expandAll() # add POST data for request if info['request']['content']: post_data = QString(info['request']['content-QByteArray']) tree_post = TamperingData.__create_treeseparator("POST data") self.requestview.invisibleRootItem().addChild(tree_post) postQueryStringURL = QUrl("http://sheep") postQueryStringURL.setEncodedQuery(info['request']['content-QByteArray']) for elmts in postQueryStringURL.queryItems(): tree_post.addChild(TamperingData.__create_treeitem(QString(elmts[0]), elmts[1] if 2 == len(elmts) else "")) self.requestview.expandAll() self.requestview.setUpdatesEnabled(True) self.responseview.setUpdatesEnabled(False) self.responseview.clear() # process request for h in info['response']['headers']: item = QTreeWidgetItem() item.setText(0, QString(h[0])) if 2 == len(h): item.setText(1, QString(h[1])) self.responseview.invisibleRootItem().addChild(item) self.responseview.setUpdatesEnabled(True)
class HTTPTamperDialog(QDialog): def __init__(self, netmanager, op, qrequest, outgoingDataList=None, parent=None): QDialog.__init__(self, parent) # passed args saved for further update, etc. self.netmanager = netmanager self.op = op self.qrequest = qrequest self.outgoingDataList = outgoingDataList # storage of the HTTPRequest self.nrequest = None # QTree widget to represent the different editable information self.request = TamperTreeWidget() self.request.setRootIsDecorated(False) self.request.setAlternatingRowColors(True) self.request.setSortingEnabled(False) self.request.setEditTriggers(QAbstractItemView.DoubleClicked) self.request.setHeaderLabels(['HTTP Header', 'value']) self.request.resizeColumnToContents(0) self.request.setWordWrap(True) QObject.connect(self.request, SIGNAL("itemChanged(QTreeWidgetItem *, int)"), self.requestChangedItemHeaders_Slot) QObject.connect(self.request, SIGNAL("addRowTreeWidget"), self.addRowTreeWidget_Slot) QObject.connect(self.request, SIGNAL("duplicateRowTreeWidget"), self.duplicateRowTreeWidget_Slot) QObject.connect(self.request, SIGNAL("deleteRowTreeWidget"), self.deleteRowTreeWidget_Slot) self.gbox = QGroupBox("&Header Tampering") self.continue_tampering = QCheckBox("&Continue Tampering") self.continue_tampering.setCheckState(Qt.Checked) self.apply_transformation = QCheckBox( "&Apply These Transformations on Subsequent Requests") QObject.connect(self.continue_tampering, SIGNAL('stateChanged(int)'), self.stateChanged_ContinueTampering_Slot) QObject.connect(self.apply_transformation, SIGNAL('stateChanged(int)'), self.stateChanged_ApplyTransformation_Slot) self.refresh_values = QPushButton("&Reload Values") self.refresh_values.setEnabled(False) self.send_request = QPushButton("&Send Request") self.cancel_request = QPushButton("&Close") QObject.connect(self.refresh_values, SIGNAL('pressed()'), self.reloadRequest_Slot) QObject.connect(self.cancel_request, SIGNAL('pressed()'), self.cancel_Slot) QObject.connect(self.send_request, SIGNAL('pressed()'), self.accept_Slot) vlayout = QVBoxLayout() vlayout.addWidget(self.continue_tampering) vlayout.addWidget(self.apply_transformation) self.gbox.setLayout(vlayout) blayout = QHBoxLayout() blayout.addWidget(self.refresh_values) blayout.addWidget(self.cancel_request) blayout.addWidget(self.send_request) layout = QVBoxLayout() layout.addWidget(self.gbox) layout.addWidget(self.request) layout.addLayout(blayout) self.setModal(False) self.setLayout(layout) # fill the data self.updateRequest() self.setMinimumSize(520, 300) self.resize(900, 600) def updateRequest(self): self.request.setUpdatesEnabled(False) self.request.clear() url = self.qrequest.url() # process request root = QTreeWidgetItem() root.setText(0, core.network.getHTTPMethodString(self.op)) root.setText(1, url.toString(QUrl.StripTrailingSlash)) root.setFlags(root.flags() | Qt.ItemIsEditable) self.request.invisibleRootItem().addChild(root) for h in self.qrequest.rawHeaderList(): item = QTreeWidgetItem() item.setText(0, QString(h)) item.setText(1, QString(self.qrequest.rawHeader(h))) item.setFlags(item.flags() | Qt.ItemIsEditable) self.request.invisibleRootItem().addChild(item) cookies = self.netmanager.cookieJar().cookiesForUrl(url) if cookies and 0 < len(cookies): separator_0 = QTreeWidgetItem() separator_0.setText(0, '-') self.request.invisibleRootItem().addChild(separator_0) tree_cookies = QTreeWidgetItem() tree_cookies.setText(0, "Cookies") tree_cookies.setText(1, "") self.request.invisibleRootItem().addChild(tree_cookies) for elmt in cookies: item = QTreeWidgetItem() item.setText(0, QString(elmt.name())) item.setText( 1, QString(elmt.toRawForm()).remove( QString(elmt.name() + ' = '))) item.setFlags(item.flags() | Qt.ItemIsEditable) tree_cookies.addChild(item) self.request.expandAll() if self.outgoingDataList and 0 < len(self.outgoingDataList): separator_1 = QTreeWidgetItem() separator_1.setText(0, '-') self.request.invisibleRootItem().addChild(separator_1) tree_post = QTreeWidgetItem() tree_post.setText(0, "POST data") tree_post.setText(1, "") self.request.invisibleRootItem().addChild(tree_post) for elmts in self.outgoingDataList: item = QTreeWidgetItem() item.setText(0, elmts[0]) if 2 == len(elmts): item.setText(1, elmts[1]) item.setFlags(item.flags() | Qt.ItemIsEditable) tree_post.addChild(item) self.request.expandAll() self.request.setUpdatesEnabled(True) def getHTTPRequest(self): return self.nrequest def prepareRequest(self): # load all the components in an HTTPRequest structure if self.refresh_values.isEnabled(): # retrieve data self.nrequest = HTTPRequest() nrequest = { 'method': None, 'url': None, 'headers': [], 'cookies': [], 'post': [] } request_iter = QTreeWidgetIterPy(self.request) firstiter, state = True, "headers" for elmt in request_iter: if firstiter: nrequest['method'] = elmt.text(0) nrequest['url'] = elmt.text(1) firstiter = False else: # state: headers -> cookies -> post if "-" == elmt.text(0): continue if "headers" == state: if "Cookies" == elmt.text(0): state = "cookies" continue elif "POST data" == elmt.text(0): state = "post" continue elif "cookies" == state: if "POST data" == elmt.text(0): state = "post" continue nrequest[state].append((elmt.text(0), elmt.text(1))) self.nrequest.setMethod(nrequest['method']) self.nrequest.setUrl(nrequest['url']) self.nrequest.setHeaders(nrequest['headers']) # set tampered cookies in the current cookiejar if nrequest['cookies'] and 0 < len(nrequest['cookies']): self.nrequest.setCookies(nrequest['cookies']) self.netmanager.cookieJar().setCookiesFromUrl( self.nrequest.getQtCookies(), self.nrequest.url) # process and store the POST data using post_history structure if nrequest['post'] and 0 < len(nrequest['post']): self.nrequest.setData(nrequest['post']) def reloadRequest_Slot(self): self.updateRequest() self.nrequest = None self.refresh_values.setEnabled(False) def requestChangedItemHeaders_Slot(self, item, col): self.refresh_values.setEnabled(True) def stateChanged_ApplyTransformation_Slot(self, state): pass def stateChanged_ContinueTampering_Slot(self, state): if Qt.Unchecked == state: self.netmanager.setIntercept(False) else: self.netmanager.setIntercept(True) def addRowTreeWidget_Slot(self, item): p = item.parent() new_item = QTreeWidgetItem() new_item.setText(0, "") new_item.setText(1, "") new_item.setFlags(new_item.flags() | Qt.ItemIsEditable) if p: p.addChild(new_item) else: self.request.invisibleRootItem().addChild(new_item) def duplicateRowTreeWidget_Slot(self, item): p = item.parent() new_item = QTreeWidgetItem() new_item.setText(0, item.text(0)) new_item.setText(1, item.text(1)) new_item.setFlags(new_item.flags() | Qt.ItemIsEditable) if p: p.addChild(new_item) else: self.request.invisibleRootItem().addChild(new_item) def deleteRowTreeWidget_Slot(self, item): self.request.invisibleRootItem().removeChild(item) def accept_Slot(self): self.prepareRequest() self.accept() def cancel_Slot(self): self.reject()