def send_to_repeater(self, host, payload): req = self._requests[host]['POST'] or self._requests[host][ 'PUT'] or self._requests[host]['GET'] if req and self._callbacks and self._helpers: info = req[0] body = req[1] nobody = body[:info.getBodyOffset()].tostring() rstripoffset = info.getBodyOffset() - len(nobody.rstrip()) headers = body[:info.getBodyOffset() - rstripoffset].tostring() try: self._overrideheaders[host] except KeyError: self._overrideheaders[host] = [] headers = override_headers(headers, self._overrideheaders[host]) repeater_body = StringUtil.toBytes( string_join( headers, body[info.getBodyOffset() - rstripoffset:info.getBodyOffset()].tostring(), payload)) self._callbacks.sendToRepeater( info.getUrl().getHost(), info.getUrl().getPort(), info.getUrl().getProtocol() == 'https', repeater_body, 'GraphQL #%s' % self._index) self._index += 1
def detect_type(types): """ This function will replace known GraphQL arguments types with placeholder values (useful for Burp Suite Repeater) :param types: Known types: String, Boolean, Float, Int, NOT_NULL TODO: add the support for custom objects and lists (partially handled since v4.1) :return: Returns a placeholder accordingly to the provided type """ # strip the ! character (not null symbol) before returning the type types = types.replace("!", "") # Switch between known args types if "String" in types: # needed for Burp Repeater string handling types = string_join('\\"', types, '\\"') types = types.replace("String", "asd") elif "Boolean" in types: types = types.replace("Boolean", "true") elif "Float" in types: types = types.replace("Float", "0.5") elif "Int" in types: types = types.replace("Int", "1") return types
def actionPerformed(self, e): """ Overrides ActionListener behaviour. Send current query to repeater. :param e: unused :return: None """ req = self.requests[self._host]['POST'] or self.requests[ self._host]['PUT'] or self.requests[self._host]['GET'] if req: info = req[0] body = req[1] nobody = body[:info.getBodyOffset()].tostring() rstripoffset = info.getBodyOffset() - len(nobody.rstrip()) headers = body[:info.getBodyOffset() - rstripoffset].tostring() try: self._overrideheaders[self._host] except KeyError: self._overrideheaders[self._host] = [] repeater_body = StringUtil.toBytes( string_join( override_headers(headers, self._overrideheaders[self._host]), body[info.getBodyOffset() - rstripoffset:info.getBodyOffset()].tostring(), self._payload)) self._callbacks.sendToRepeater( info.getUrl().getHost(), info.getUrl().getPort(), info.getUrl().getProtocol() == 'https', repeater_body, 'GraphQL #%s' % self._index) self._index += 1
def send_to_repeater_post_form_data_body(self, host, payload): req = self._requests[host]['POST'] or self._requests[host][ 'PUT'] or self._requests[host]['GET'] if req and self._callbacks and self._helpers: info = req[0] body = req[1] nobody = body[:info.getBodyOffset()].tostring() rstripoffset = info.getBodyOffset() - len(nobody.rstrip()) headers = body[:info.getBodyOffset() - rstripoffset].tostring() try: self._overrideheaders[host] except KeyError: self._overrideheaders[host] = [] headers = override_headers(headers, self._overrideheaders[host]) boundary = "---------------------------%s" % random_string() headers = override_headers(headers, [ ("Content-Type", "multipart/form-data, boundary=%s" % boundary) ]) headers = override_uri(headers, method="POST") content = json.loads(payload) if isinstance(content, list): content = content[0] repeater_body = StringUtil.toBytes( string_join( headers, body[info.getBodyOffset() - rstripoffset:info.getBodyOffset()].tostring(), multipart(data=querify(clean_dict(content)), boundary=boundary))) self._callbacks.sendToRepeater( info.getUrl().getHost(), info.getUrl().getPort(), info.getUrl().getProtocol() == 'https', repeater_body, 'GraphQL - POST form-data #%s' % self._index) self._index += 1
def send_to_repeater_get_query(self, host, payload): req = self._requests[host]['POST'] or self._requests[host][ 'PUT'] or self._requests[host]['GET'] if req and self._callbacks and self._helpers: info = req[0] body = req[1] nobody = body[:info.getBodyOffset()].tostring() rstripoffset = info.getBodyOffset() - len(nobody.rstrip()) metadata = body[:info.getBodyOffset() - rstripoffset].tostring() try: self._overrideheaders[host] except KeyError: self._overrideheaders[host] = [] metadata = override_headers(metadata, self._overrideheaders[host]) # remove Content-Type on GET requests metadata = re.sub(r'(?m)^Content-Type:.*\n?', '', metadata) content = json.loads(payload) if isinstance(content, list): content = content[0] metadata = override_uri(metadata, method="GET", query=urlencode( querify(clean_dict(content)))) repeater_body = StringUtil.toBytes( string_join( metadata, body[info.getBodyOffset() - rstripoffset:info.getBodyOffset()].tostring())) self._callbacks.sendToRepeater( info.getUrl().getHost(), info.getUrl().getPort(), info.getUrl().getProtocol() == 'https', repeater_body, 'GraphQL - GET query #%s' % self._index) self._index += 1
def send_to_repeater_post_urlencoded_body(self, host, payload): req = self._requests[host]['POST'] or self._requests[host][ 'PUT'] or self._requests[host]['GET'] if req and self._callbacks and self._helpers: info = req[0] body = req[1] nobody = body[:info.getBodyOffset()].tostring() rstripoffset = info.getBodyOffset() - len(nobody.rstrip()) headers = body[:info.getBodyOffset() - rstripoffset].tostring() try: self._overrideheaders[host] except KeyError: self._overrideheaders[host] = [] headers = override_headers(headers, self._overrideheaders[host]) headers = override_headers( headers, [("Content-Type", "application/x-www-form-urlencoded")]) headers = override_uri(headers, method="POST") content = json.loads(payload) if isinstance(content, list): content = content[0] repeater_body = StringUtil.toBytes( string_join( headers, body[info.getBodyOffset() - rstripoffset:info.getBodyOffset()].tostring(), urlencode(querify(clean_dict(content))))) self._callbacks.sendToRepeater( info.getUrl().getHost(), info.getUrl().getPort(), info.getUrl().getProtocol() == 'https', repeater_body, 'GraphQL - POST urlencoded #%s' % self._index) self._index += 1
#!/usr/bin/env python from __future__ import print_function from inql.introspection import main, red, reset from inql.utils import string_join if __name__ == "__main__": try: main() except KeyboardInterrupt: # Catch CTRL+C, it will abruptly kill the script print(string_join(red, "Exiting...", reset))