def payload(self): payload = bytearray() # write padding length padding_length = encode_unsigned_integer( PushPromiseFrame.__default_padding_length, PushPromiseFrame.__padding_length_length) payload.extend(padding_length) # write promised stream id promised_stream_id = encode_unsigned_integer( self.promised_stream_id, PushPromiseFrame.__promised_stream_id_length) payload.extend(promised_stream_id) # write header block fragment header_block = self.encoded_headers() payload.extend(header_block) # write padding # TODO: should it use different padding length? if PushPromiseFrame.__default_padding_length > 0: padding = [0x0] * PushPromiseFrame.__default_padding_length payload.extend(padding) else: padding = bytearray() self.verbose('write a push promise frame:', 'padding length: {0}'.format(helper.bytes2hex(padding_length)), 'promised stream id: {0}'.format(helper.bytes2hex(promised_stream_id)), 'header block: ', helper.bytes2hex(header_block), 'padding: ', helper.bytes2hex(padding)) return payload
def payload(self): payload = bytearray() # write padding length padding_length = encode_unsigned_integer( DataFrame.__default_padding_length, DataFrame.__padding_length_length) payload.extend(padding_length) # write data payload.extend(self.data) # write padding if DataFrame.__default_padding_length > 0: padding = [0x0] * DataFrame.__default_padding_length payload.extend(padding) else: padding = bytearray() self.verbose('write a data frame:', 'padding length: {0}'.format(helper.bytes2hex(padding_length)), 'data: ', helper.bytes2hex(self.data), 'padding: ', helper.bytes2hex(padding)) return payload
def encode(self, payload): data = bytearray() # write 24 bits of payload length length = len(payload) encoded_length = encode_unsigned_integer(length, self.length_length) self.verbose('create a frame: write a length ({0:d}): {1:s}' .format(length, helper.bytes2hex(encoded_length))) data.extend(encoded_length) # write a frame type (8 bits) data.extend(encode_unsigned_integer(self.frame_type, self.type_length)) # write flags (8 bits) data.extend(encode_unsigned_integer(self.flags, self.flags_length)) # write a stream id expressed as an unsigned 32-bit integer # the spec defines a stream id field at an unsigned 31-bit integer, # and 1 bit is reserved and must be set to 0 data.extend(encode_unsigned_integer(self.stream_id, self.stream_id_length)) # write payload data.extend(payload) return data
def payload(self): payload = bytearray() payload.extend(self.data) self.verbose('write a ping frame:', 'data: {0}'.format(helper.bytes2hex(self.data))) return payload
def payload(self): payload = bytearray() # write padding length padding_length = encode_unsigned_integer( HeadersFrame.__default_padding_length, HeadersFrame.__padding_length_length) payload.extend(padding_length) # write no exclusive flag, and no stream dependency stream_dependency = encode_unsigned_integer( HeadersFrame.__default_dependency, HeadersFrame.__dependency_length) payload.extend(stream_dependency) # write weight weight = encode_unsigned_integer( HeadersFrame.__default_weight, HeadersFrame.__weight_length) payload.extend(weight) # write header block fragment header_block = self.encoded_headers() payload.extend(header_block) # write padding # # according to the spec # # Padding: Padding octets that contain no application semantic value. # Padding octets MUST be set to zero when sending. A receiver is # not obligated to verify padding but MAY treat non-zero padding as # a connection error (Section 5.4.1) of type PROTOCOL_ERROR. if HeadersFrame.__default_padding_length > 0: padding = [0x0] * HeadersFrame.__default_padding_length payload.extend(padding) else: padding = bytearray() self.verbose('write a header frame:', 'padding length: {0}'.format(helper.bytes2hex(padding_length)), 'stream dependency: {0}'.format(helper.bytes2hex(stream_dependency)), 'weight: {0}'.format(helper.bytes2hex(weight)), 'header block: ', helper.bytes2hex(header_block), 'padding: ', helper.bytes2hex(padding)) return payload
def next(self, stream_id = 0x0): self.info('generate a ping frame, stream id = {0:d}'.format(stream_id)) self.random.seed(self.seed * self.test) data = bytearray() for i in range(PingFrame.opaque_data_length): data.append(self.random.randint(0, 255)) self.verbose('fuzzed data:', helper.bytes2hex(data)) return PingFrame(data).encode()
def next(self, stream_id=0x0): self.info('generate a ping frame, stream id = {0:d}'.format(stream_id)) self.random.seed(self.seed * self.test) data = bytearray() for i in range(PingFrame.opaque_data_length): data.append(self.random.randint(0, 255)) self.verbose('fuzzed data:', helper.bytes2hex(data)) return PingFrame(data).encode()
def payload(self): payload = bytearray() # write no exclusive flag, and no stream dependency stream_dependency = encode_unsigned_integer( PriorityFrame.__default_dependency, PriorityFrame.__dependency_length) payload.extend(stream_dependency) # write weight weight = encode_unsigned_integer( PriorityFrame.__default_weight, PriorityFrame.__weight_length) payload.extend(weight) self.verbose('write a priority frame:', 'stream dependency: {0}'.format(helper.bytes2hex(stream_dependency)), 'weight: {0}'.format(helper.bytes2hex(weight))) return payload
def payload(self): payload = bytearray() # write header block fragment header_block = self.encoded_headers() payload.extend(header_block) self.verbose('write a continuation frame:', 'header block: ', helper.bytes2hex(header_block)) return payload
def __init__(self, data = None, seed = 1, min_ratio = 0.01, max_ratio = 0.05, start_test = 0, ignored_symbols = ()): AbstractDumbFuzzer.__init__(self, seed, min_ratio, max_ratio, start_test) if data is None: self.data = bytearray() random_byte = random.Random() random_byte.seed(seed) for i in range(256): self.data.append(random_byte.randint(0, 255)) else: self.data = data self.verbose('original data:', helper.bytes2hex(self.data)) self.set_fuzzer(DumbByteArrayFuzzer( self.data, seed, min_ratio, max_ratio, start_test, ignored_symbols))
def run(self): self.client = connection.Client(self.host, self.port, self.is_tls) self.info('started, test range {0}:{1}'.format(self.start_test, self.end_test)) test = self.start_test successfully_sent = True while test <= self.end_test: if self.client.isconnected() is False: self.client.connect() self.info('send a client connection preface') self.client.send(http2core.getclientpreface()) self.info('send a valid settings frame') # TODO: it can be created once settings = SettingsFrame() self.client.send(settings.encode()) data = self.client.receive() try: self.info('test {0:d}: start'.format(test)) if successfully_sent: fuzzed_data = self.next() successfully_sent = False self.client.send(fuzzed_data) successfully_sent = True except socket.error as msg: # move on to next test only if current one was successfully sent out # TODO: delay? self.info( 'test {0:d}: a error occured while sending data: {1}'. format(test, msg)) self.info('test {0:d}: re-connect'.format(test)) continue try: data = self.client.receive() self.info('test {0:d}: received data:'.format(test), helper.bytes2hex(data)) except socket.error as msg: self.info( 'test {0:d}: a error occured while receiving data, ignore it: {1}' .format(test, msg)) test += 1
def run(self): self.client = connection.Client(self.host, self.port, self.is_tls) self.info('started, test range {0}:{1}' .format(self.start_test, self.end_test)) test = self.start_test successfully_sent = True while test <= self.end_test: if self.client.isconnected() is False: self.client.connect() self.info('send a client connection preface') self.client.send(http2core.getclientpreface()) self.info('send a valid settings frame') # TODO: it can be created once settings = SettingsFrame() self.client.send(settings.encode()) data = self.client.receive() try: self.info('test {0:d}: start'.format(test)) if successfully_sent: fuzzed_data = self.next() successfully_sent = False self.client.send(fuzzed_data) successfully_sent = True except socket.error as msg: # move on to next test only if current one was successfully sent out # TODO: delay? self.info('test {0:d}: a error occured while sending data: {1}' .format(test, msg)) self.info('test {0:d}: re-connect'.format(test)) continue try: data = self.client.receive() self.info('test {0:d}: received data:'.format(test), helper.bytes2hex(data)) except socket.error as msg: self.info('test {0:d}: a error occured while receiving data, ignore it: {1}' .format(test, msg)) test += 1
def handle(self, socket): self.info('send a valid settings frame') # TODO: it can be created once settings = SettingsFrame() # TODO: hack for hghtt2, the spec recommends to enable push, # but nghttp2 client doesn't work with it # can it be configured in command line? settings.disable_push() socket.send(settings.encode()) data = socket.recv(1024) # TODO: HTTP/2 server must include ":status" pseudo-header field in all # responses; otherwise, the response is malformed while (self.test <= self.end_test): try: self.info('test {0:d}: start'.format(self.test)) fuzzer = self.fuzzers[self.next_fuzzer] fuzzer.set_test(self.test) fuzzed_data = fuzzer.next() self.next_fuzzer = (self.next_fuzzer + 1) % len(self.fuzzers) socket.sendall(fuzzed_data) except OSError as msg: self.info( 'test {0:d}: a error occured while sending data: {1}'. format(self.test, msg)) self.info('test {0:d}: will be run again '.format(self.test)) break try: data = socket.recv(1024) self.info('test {0:d}: received data:'.format(self.test), helper.bytes2hex(data)) except OSError as msg: self.info( 'test {0:d}: a error occured while receiving data, ignore it: {1}' .format(self.test, msg)) self.test += 1
def handle(self, socket): self.info('send a valid settings frame') # TODO: it can be created once settings = SettingsFrame() # TODO: hack for hghtt2, the spec recommends to enable push, # but nghttp2 client doesn't work with it # can it be configured in command line? settings.disable_push() socket.send(settings.encode()) data = socket.recv(1024) # TODO: HTTP/2 server must include ":status" pseudo-header field in all # responses; otherwise, the response is malformed while (self.test <= self.end_test): try: self.info('test {0:d}: start'.format(self.test)) fuzzer = self.fuzzers[self.next_fuzzer] fuzzer.set_test(self.test) fuzzed_data = fuzzer.next() self.next_fuzzer = (self.next_fuzzer + 1) % len(self.fuzzers) socket.sendall(fuzzed_data) except OSError as msg: self.info('test {0:d}: a error occured while sending data: {1}' .format(self.test, msg)) self.info('test {0:d}: will be run again '.format(self.test)) break try: data = socket.recv(1024) self.info('test {0:d}: received data:' .format(self.test), helper.bytes2hex(data)) except OSError as msg: self.info('test {0:d}: a error occured while receiving data, ignore it: {1}' .format(self.test, msg)) self.test += 1
def payload(self): payload = bytearray() # write last stream id last_stream_id = encode_unsigned_integer( self.last_stream_id, GoAwayFrame.__last_stream_id_length) payload.extend(last_stream_id) # write error code error_code = encode_unsigned_integer( self.error_code, GoAwayFrame.__error_code_length) payload.extend(error_code) if len(self.debug_data) > 0: payload.extend(self.debug_data) self.verbose('write a goaway frame:', 'last stream id: {0}'.format(self.last_stream_id), 'error code: {0}'.format(self.error_code), 'debug data: {0}'.format(helper.bytes2hex(self.debug_data))) return payload
def __init__(self, data=None, seed=1, min_ratio=0.01, max_ratio=0.05, start_test=0, ignored_symbols=()): AbstractDumbFuzzer.__init__(self, seed, min_ratio, max_ratio, start_test) if data is None: self.data = bytearray() random_byte = random.Random() random_byte.seed(seed) for i in range(256): self.data.append(random_byte.randint(0, 255)) else: self.data = data self.verbose('original data:', helper.bytes2hex(self.data)) self.set_fuzzer( DumbByteArrayFuzzer(self.data, seed, min_ratio, max_ratio, start_test, ignored_symbols))
def next(self, stream_id = 1): self.info('generate a data frame, stream id = {0:d}'.format(stream_id)) fuzzed_data = self.fuzzer.next() self.verbose('fuzzed data:', helper.bytes2hex(fuzzed_data)) return DataFrame(stream_id, fuzzed_data).encode()
def next(self, stream_id=1): self.info('generate a data frame, stream id = {0:d}'.format(stream_id)) fuzzed_data = self.fuzzer.next() self.verbose('fuzzed data:', helper.bytes2hex(fuzzed_data)) return DataFrame(stream_id, fuzzed_data).encode()