Skip to content

Commit

Permalink
Merge pull request #1 from rodrigorato/dev
Browse files Browse the repository at this point in the history
Bringing the AST from dev unto master
  • Loading branch information
rodrigorato authored Nov 18, 2017
2 parents 03f9afa + 68659a7 commit ab14e0f
Show file tree
Hide file tree
Showing 47 changed files with 2,295 additions and 11 deletions.
32 changes: 32 additions & 0 deletions analyser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env python3

from sys import argv
from inputparser import get_input
from vulnpatterns.patternmanager import PatternManager
from jsonhandler import from_json_to_py
import pprint

from ast.nodemanager import NodeManager
from ast import *


def pretty(obj):
pprint.PrettyPrinter(indent=4).pprint(obj)


def main(args):

# Get the patterns to check for
pattern_manager = PatternManager()
patterns = pattern_manager.get_patterns()

# Get the program element from the input file
program = from_json_to_py(get_input(args))

program_node = NodeManager.build_node_from_json(program)

print(program_node)


if __name__ == '__main__':
main(argv[1:])
10 changes: 10 additions & 0 deletions ast/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

# For node files
from ast.nodes import *
from ast.cyclenodes import *
from ast.functionnodes import *
from ast.conditionalnodes import *
from ast.expressionnodes import *

# Other imports
import ast.nodemanager
7 changes: 0 additions & 7 deletions ast/ast.py

This file was deleted.

24 changes: 24 additions & 0 deletions ast/conditionalnodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from ast.nodes import *


class IfThenElseNode(ChildfulNode):
def __init__(self, kind, test, body, alternate=None):
ChildfulNode.__init__(self, kind, body)
self.test = test # An expression
self.body = body # A list of Nodes
self.alternate = alternate # A IfThenElse node or None


# A SwitchNode's child are its CaseNodes
class SwitchNode(ChildfulNode):
def __init__(self, kind, test, body):
ChildfulNode.__init__(self, kind, body)
self.test = test


class CaseNode(ChildfulNode):
def __init__(self, kind, test, body):
ChildfulNode.__init__(self, kind, body)
self.test = test


24 changes: 24 additions & 0 deletions ast/cyclenodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from ast.nodes import *


class CycleNode(ChildfulNode):
def __init__(self, kind, children, test):
ChildfulNode.__init__(kind, children)
self.test = test # Its an ExpressionNode


class WhileNode(CycleNode):
def __init__(self, kind, children, test):
CycleNode.__init__(self, kind, children, test)


class DoWhileNode(CycleNode):
def __init__(self, kind, children, test):
CycleNode.__init__(self, kind, children, test)


class ForNode(CycleNode):
def __init__(self, kind, children, test, init, increment):
CycleNode.__init__(self, kind, children, test)
self.init = init
self.increment = increment
67 changes: 67 additions & 0 deletions ast/expressionnodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from ast.nodes import *


class ExpressionNode(Node):
def __init__(self, kind):
Node.__init__(self, kind)


class AttributionNode(ExpressionNode):
def __init__(self, kind, left_expr, right_expr):
ExpressionNode.__init__(self, kind)
self.left_expr = left_expr
self.right_expr = right_expr


class UnaryExpression(ExpressionNode):
def __init__(self, kind, type, expr):
ExpressionNode.__init__(self, kind)
self.type = type # The Unary operator, like '!' and '++'
self.expr = expr # Every Unary expression has an expression associated with it


class BinaryExpression(ExpressionNode):
def __init__(self, kind, type, left_expr, right_expr):
ExpressionNode.__init__(self, kind)
self.type = type # The operator, like '+' or '*'
self.left_expr = left_expr # Every binary expression has a left expr and a..
self.right_expr = right_expr # right expression!


class TernaryExpression(ExpressionNode):
def __init__(self, kind, test, true_expr, false_expr):
ExpressionNode.__init__(self, kind)
self.test = test
self.true_expr = true_expr
self.false_expr = false_expr


# FIXME assumption - an indexation is a variable
# so $a[1] is a variable node
class VariableNode(ExpressionNode):
def __init__(self, kind, name):
ExpressionNode.__init__(self, kind)
self.name = name


# FIXME assumption - we're not handling indexation calls
# so $a[1]("ha"); isn't handled
class FunctionCallNode(ExpressionNode):
def __init__(self, kind, name, arguments):
ExpressionNode.__init__(self, kind)
self.name = name
self.arguments = arguments # arguments is a list of VariableNodes


# Stuff like $_GET and $_POST
class EntryPointNode(VariableNode):
def __init__(self, kind, name):
VariableNode.__init__(self, kind, name)
self.tainted = True
self.visited = True


class ConstantNode(ExpressionNode):
def __init__(self, kind, value):
ExpressionNode.__init__(self, kind)
self.value = value
9 changes: 9 additions & 0 deletions ast/functionnodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from ast.nodes import *


# FIXME assumption, we're ignoring type hinting
class FunctionDefinitionNode(ChildfulNode):
def __init__(self, kind, name, arguments, children):
ChildfulNode.__init__(self, kind, children)
self.name = name
self.arguments = arguments # arguments is a list of VariableNodes
38 changes: 34 additions & 4 deletions ast/nodemanager.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
class NodeManager():
from ast.nodes import *


def is_kind(json, kind_name):
return json['kind'] == kind_name


class NodeManager:

@staticmethod
def build_node_from_json(json_repr):
# TODO build proper node here
return None
def build_node_from_json(node_json):

if is_kind(node_json, 'program'):

children = []
for child in node_json['children']:
children.append(NodeManager.build_node_from_json(child))

return ProgramNode(node_json['kind'],
children)

elif 'body' in node_json and 'children' in node_json['body']:

children = []
for child in node_json['body']['children']:
children.append(NodeManager.build_node_from_json(child))

s = "childfull node not implement: " + node_json['kind']
print(s)
return ChildfulNode(s, children)

else:
s = "NODE NOT IMPLEMENTED: " + node_json['kind']
print(s)
return Node(s)
25 changes: 25 additions & 0 deletions ast/nodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class Node:
def __init__(self, kind):
self.kind = kind # This node's kind
self.tainted = True # FIXME assuming its good until an entry point is found
self.visited = False # has this node been visited already?

def __repr__(self):
return '<kind:' + self.kind + '>'


# This is just a fancy name for an abstraction of a node that has child nodes
# i.e. children somewhere, like inside a body
class ChildfulNode(Node):
def __init__(self, kind, children):
Node.__init__(self, kind)
self.children = children

def __repr__(self):
return '<kind:' + self.kind + ', children:' + self.children.__repr__() + '>'


class ProgramNode(ChildfulNode):
def __init__(self, kind, children):
ChildfulNode.__init__(self, kind, children)

16 changes: 16 additions & 0 deletions inputparser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from argparse import ArgumentParser


def validate_input(file_name):
# TODO
return file_name


def get_input(argv):
parser = ArgumentParser(description='Analyses PHP code slices for vulnerabilities.')
parser.add_argument(dest="filename",
help="input file name with json PHP code",
metavar="FILE")
# add more options, if needed
args = parser.parse_args(argv)
return args.filename
23 changes: 23 additions & 0 deletions jsonhandler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from sys import exit
from json import load, dump


def from_json_to_py(filename):
try:
file = open(filename, 'r')
except FileNotFoundError:
exit("Json Handler-File error: File could not be found.")
else:
data = load(file)
file.close()
return data


def from_py_to_json(data, filename):
try:
file = open(filename, 'w')
except FileNotFoundError:
exit("Json Handler-File error: File could not be found.")
else:
dump(data, file)
file.close()
94 changes: 94 additions & 0 deletions proj-slices/slice1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{
"kind": "program",
"children": [
{
"kind": "assign",
"operator": "=",
"left": {
"kind": "variable",
"name": "nis",
"byref": false,
"curly": false
},
"right": {
"kind": "offsetlookup",
"what": {
"kind": "variable",
"name": "_POST",
"byref": false,
"curly": false
},
"offset": {
"kind": "string",
"value": "nis",
"isDoubleQuote": false
}
}
},
{
"kind": "assign",
"operator": "=",
"left": {
"kind": "variable",
"name": "query",
"byref": false,
"curly": false
},
"right": {
"kind": "encapsed",
"value": [
{
"kind": "string",
"value": "SELECT *FROM siswa WHERE nis='",
"isDoubleQuote": false
},
{
"kind": "variable",
"name": "nis",
"byref": false,
"curly": false
},
{
"kind": "string",
"value": "'",
"isDoubleQuote": false
}
],
"type": "string"
}
},
{
"kind": "assign",
"operator": "=",
"left": {
"kind": "variable",
"name": "q",
"byref": false,
"curly": false
},
"right": {
"kind": "call",
"what": {
"kind": "identifier",
"resolution": "uqn",
"name": "mysql_query"
},
"arguments": [
{
"kind": "variable",
"name": "query",
"byref": false,
"curly": false
},
{
"kind": "variable",
"name": "koneksi",
"byref": false,
"curly": false
}
]
}
}
],
"errors": []
}
5 changes: 5 additions & 0 deletions proj-slices/slice1.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php
$nis=$_POST['nis'];
$query="SELECT *FROM siswa WHERE nis='$nis'";
$q=mysql_query($query,$koneksi);
?>
Loading

0 comments on commit ab14e0f

Please sign in to comment.