예제 #1
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)
예제 #2
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
     )
예제 #3
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)
예제 #4
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
예제 #5
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
예제 #6
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)