Example #1
0
 def test_generate_report(self):
     num_clickables = {
         'unexamined': 5,
         'true':  10,
         'false': 30
     }
     form1 = FormField('form1')
     form1.add_input(InputField('username', '//*[@id="username"]', 'castman'))
     form1.add_input(InputField('password', '', 'p@ssw0rd'))
     form_list = [{
         'state': 1,
         'form': form1,
         'execution_seq': [Clickable('exe1', '//html/body/button[1]'), Clickable('exe2', '//html/body/button[1]')],
         'clickable': [Clickable('btn1', '//html/body/button[1]'), Clickable('btn2', '//html/body/button[1]')]
     }]
     inv_violation = [{
         'state': 2,
         'name': '{"name": "file-not-found"}',
         'sequence': [Clickable('inv-btn1', '//html/body/button[1]'), Clickable('inv-btn2', '//html/body/button[1]')]
     }]
     Visualizer.generate_report(
         'web',
         'trace/example-app-4-webide',
         'automata.json',
         3, num_clickables, form_list, inv_violation, 9.987
     )
Example #2
0
    def setUp(self):
        dom1 = '''
            <!DOCTYPE html>
            <html lang="en">
            <head> <meta charset="UTF-8"> <title></title> </head>
            <body>dom1</body>
            </html>
        '''
        state = State(dom1)
        self.automata = Automata()
        self.automata.add_state(state)
        self.assertEqual(len(self.automata.get_states()), 1)
        self.assertEqual(self.automata.get_initial_state().get_id(), self.automata.get_current_state().get_id())
        self.assertEqual(self.automata.get_current_state().get_id(), '0')

        # test adding and removing inputs and forms
        form1 = FormField('form1')
        form1.add_input(InputField('username', '//*[@id="username"]', 'castman'))
        form1.add_input(InputField('password', '', 'p@ssw0rd'))
        form1.add_input(InputField('password', '', 'p@ssw0rd'))
        self.assertEqual(len(form1.get_inputs()), 2)
        form1.remove_input(InputField('username', '//*[@id="username"]', 'castman'))
        self.assertEqual(len(form1.get_inputs()), 1)

        form2 = FormField('', '//*[@id="lst-ib"]')
        clickable = Clickable('', '//*[@id="btn1"]')
        clickable.add_form(form1)
        clickable.add_form(FormField('form1'))
        clickable.add_form(form2)
        self.assertEqual(len(clickable.get_forms()), 2)
        clickable.remove_form(FormField('', '//*[@id="lst-ib"]'))
        self.assertEqual(len(clickable.get_forms()), 1)

        # add the clickable into state 0
        self.automata.get_current_state().add_clickable(clickable)
 def get_inputs(cls, dom):
     soup = BeautifulSoup(dom, 'html5lib')
     soup = cls.soup_visible(soup)
     inputs_list = []
     for input_type in cls._input_types:
         inputs = soup.find_all('input', attrs={'type': input_type})
         for my_input in inputs:
             input_id = cls.make_id(my_input.get('id'))
             input_name = my_input.get('name') if my_input.has_attr(
                 'name') else input_id
             inputs_list.append(
                 InputField(input_id, input_name, cls._get_xpath(my_input),
                            input_type))
     return inputs_list
Example #4
0
 def __init__(self, fname=None, load_dom=False):
     self._states = []
     self._edges = []
     self._initial_state = None
     self._current_state = None
     if fname:
         assert os.path.isfile(fname) and os.path.exists(fname)
         t_start = time.time()
         with open(fname) as f:
             data = json.load(f)
             for state in data['state']:
                 if load_dom:
                     with open(
                             os.path.join(
                                 os.path.dirname(os.path.realpath(fname)),
                                 state['dom_path']), 'r') as df:
                         s = State(df.read())
                 else:
                     s = State(state['id'])
                 s.set_id(state['id'])
                 for form in state['form']:
                     f = FormField(form['id'], form['xpath'])
                     for the_input in form['input']:
                         f.add_input(
                             InputField(the_input['id'], the_input['xpath'],
                                        the_input['type'],
                                        the_input['value']))
                     s.add_form(f)
                 for clickable in state['clickable']:
                     c = Clickable(clickable['id'], clickable['xpath'],
                                   clickable['tag'])
                     for form in clickable['form']:
                         f = s.get_form_by_id(form['id'])
                         assert f
                         c.add_form(f)
                     s.add_clickable(c)
                 self.add_state(s)
             for edge in data['edge']:
                 from_state = self.get_state_by_id(edge['from'])
                 to_state = self.get_state_by_id(edge['to'])
                 clickable = from_state.get_clickable_by_id(
                     edge['clickable'])
                 assert from_state and to_state and clickable
                 self.add_edge(from_state, to_state, clickable)
         logger.info('automata loaded. loading time: %f sec',
                     time.time() - t_start)
 def build_trace(self, data):
     try:
         edges = []
         for edge in data['edges']:
             state_from = edge['from']
             state_to = edge['to']
             c = edge['clickable']
             clickable = Clickable(c['id'], c['name'], c['xpath'], c['tag'])
             inputs = []
             for i in edge['inputs']:
                 inputs.append(
                     InputField(i['id'], i['name'], i['xpath'], i['type'],
                                i['value']))
             selects = []
             for s in edge['selects']:
                 selects.append(
                     SelectField(s['id'], s['name'], s['xpath'], s['value'],
                                 s['selected']))
             checkboxes = []
             for c_field in edge['checkboxes']:
                 c_list = []
                 for c in c_field['checkbox_list']:
                     c_list.append(
                         Checkbox(c['id'], c['name'], c['xpath'],
                                  c['value']))
                 checkboxes.append(
                     CheckboxField(c_list, c_field['checkbox_name'],
                                   c_field['checkbox_selected_list']))
             radios = []
             for r_field in edge['radios']:
                 r_list = []
                 for r in r_field['radio_list']:
                     r_list.append(
                         Radio(r['id'], r['name'], r['xpath'], r['value']))
                 radios.append(
                     RadioField(r_list, r_field['radio_name'],
                                r_field['radio_selected']))
             iframe_list = edge['iframe_list']
             edges.append(
                 Edge(state_from, state_to, clickable, inputs, selects,
                      checkboxes, radios, iframe_list))
         return edges
     except Exception as e:
         logging.error('can not build trace: %s', str(e))
Example #6
0
    def get_clickables(cls, dom, prev_dom=None):
        # only return newly discovered clickables and forms, i.e. clickables not in prev_clickables
        prev_clickables = []
        prev_forms = []
        if prev_dom:
            prev_soup = BeautifulSoup(prev_dom, 'html.parser')
            for tag in cls._clickable_tags:
                if tag.get_attr():
                    for attr, value in tag.get_attr().items():
                        prev_clickables += prev_soup.find_all(
                            tag.get_name(), attrs={attr: value})
                else:
                    prev_clickables += prev_soup.find_all(tag.get_name())
            prev_forms = prev_soup.find_all('form')
        soup = BeautifulSoup(dom, 'html.parser')
        forms = soup.find_all('form')
        clickables = []
        # clickables with forms and inputs attached
        for form in forms:
            if form in prev_forms:
                continue
            form_id = form.get('id')
            if not form_id:
                form_id = cls.serial_prefix + str(cls._serial_num)
                cls._serial_num += 1
            f = FormField(form_id, cls._get_xpath(form))
            for input_type in cls.input_types:
                inputs = form.find_all('input', attrs={'type': input_type})
                for my_input in inputs:
                    data_set = InlineDataBank.get_data(input_type)
                    if data_set:
                        value = random.choice(list(data_set))
                    else:
                        value = ''.join(
                            random.choice(string.lowercase) for i in xrange(8))
                    input_id = my_input.get('id')
                    if not input_id:
                        input_id = cls.serial_prefix + str(cls._serial_num)
                        cls._serial_num += 1
                    f.add_input(
                        InputField(input_id, cls._get_xpath(my_input),
                                   input_type, value))
            for tag in cls._clickable_tags:
                if tag.get_attr():
                    for attr, value in tag.get_attr().items():
                        candidate_clickables = form.find_all(
                            tag.get_name(), attrs={attr: value})
                else:
                    candidate_clickables = form.find_all(tag.get_name())
                for candidate_clickable in candidate_clickables:
                    if candidate_clickable in prev_clickables:
                        continue
                    clickable_id = candidate_clickable.get('id')
                    if not clickable_id:
                        clickable_id = cls.serial_prefix + str(cls._serial_num)
                        cls._serial_num += 1
                    c = Clickable(clickable_id,
                                  cls._get_xpath(candidate_clickable),
                                  tag.get_name())
                    c.add_form(f)
                    clickables.append(c)

        # other clickables
        for tag in cls._clickable_tags:
            if tag.get_attr():
                for attr, value in tag.get_attr().items():
                    candidate_clickables = soup.find_all(tag.get_name(),
                                                         attrs={attr: value})
            else:
                candidate_clickables = soup.find_all(tag.get_name())
            for candidate_clickable in candidate_clickables:
                #print candidate_clickable
                if candidate_clickable in prev_clickables:
                    continue
                if not cls._is_duplicate(clickables, candidate_clickable):
                    clickable_id = candidate_clickable.get('id')
                    if not clickable_id:
                        clickable_id = cls.serial_prefix + str(cls._serial_num)
                        cls._serial_num += 1
                    clickables.append(
                        Clickable(clickable_id,
                                  cls._get_xpath(candidate_clickable),
                                  tag.get_name()))
        return clickables