Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Have attacker rerun all requests, update xfail test #44

Merged
merged 8 commits into from
Apr 10, 2020
26 changes: 16 additions & 10 deletions fuzz_lightyear/plugins/idor.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,19 @@ def is_vulnerable(
request_sequence: List[FuzzingRequest],
response_sequence: List[Any],
) -> bool:
last_request = request_sequence[-1]
try:
last_request.send(
auth=get_abstraction().get_attacker_session(), # type: ignore
should_log=False,
)

return True
except (HTTPError, SwaggerMappingError, ValidationError):
return False
# We have the attacker execute the same request sequence with different
# values except for the last request.
for request in request_sequence[:-1]:
if request.fuzzed_input:
for query_key in request.fuzzed_input:
request.fuzzed_input[query_key] += 1
tanx16 marked this conversation as resolved.
Show resolved Hide resolved
for request in request_sequence:
try:
request.send(
auth=get_abstraction().get_attacker_session(), # type: ignore
should_log=False,
)

except (HTTPError, SwaggerMappingError, ValidationError):
return False
return True
tanx16 marked this conversation as resolved.
Show resolved Hide resolved
7 changes: 7 additions & 0 deletions testing/vulnerable_app/views/models/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@
'id': fields.Integer(required=True),
},
)

thing_model = api.model(
'Thing',
{
'id': fields.Integer(required=True),
},
)
tanx16 marked this conversation as resolved.
Show resolved Hide resolved
48 changes: 48 additions & 0 deletions testing/vulnerable_app/views/sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,51 @@ def get(self, id, user):
return {
'id': widget_id,
}


@ns.route('/side-effect-safe/create')
class CreateWithSideEffectSafe(Resource):
tanx16 marked this conversation as resolved.
Show resolved Hide resolved
@api.doc(security='apikey')
@api.response(200, 'Success', model=widget_model)
@requires_user
def post(self, user):

with database.connection() as session:
entry = Widget()

session.add(entry)
session.commit()

widget_id = entry.id

user.created_resource = [entry.id]
user.save()

return {
'id': widget_id,
}


@ns.route('/side-effect-safe/get/<int:id>')
class GetWithSideEffectSafe(Resource):
@api.doc(security='apikey')
@api.response(200, 'Success', model=widget_model)
@api.response(404, 'Not Found')
@requires_user
def get(self, id, user):
if id not in user.created_resource:
abort(403)

with database.connection() as session:
try:
entry = session.query(Widget).filter(
Widget.id == id,
).one()
except NoResultFound:
abort(404)

widget_id = entry.id

return {
'id': widget_id,
}
30 changes: 25 additions & 5 deletions tests/integration/plugins/idor_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import pytest

from fuzz_lightyear.request import FuzzingRequest
from fuzz_lightyear.response import ResponseSequence
from fuzz_lightyear.runner import run_sequence
Expand Down Expand Up @@ -36,9 +34,6 @@ def test_skipped_due_to_no_inputs(mock_client):
assert responses.test_results == {}


@pytest.mark.xfail(
reason='https://github.com/Yelp/fuzz-lightyear/issues/11',
)
def test_side_effect(mock_api_client):
responses = run_sequence(
[
Expand All @@ -62,3 +57,28 @@ def test_side_effect(mock_api_client):

assert responses.responses[1].has_created_resource
assert responses.test_results['IDORPlugin']


def test_side_effect_safe(mock_api_client):
responses = run_sequence(
[
FuzzingRequest(
tag='sequence',
operation_id='post_create_with_side_effect_safe',
),
FuzzingRequest(
tag='user',
operation_id='get_get_user',
),

# This goes last, to test for IDOR.
FuzzingRequest(
tag='sequence',
operation_id='get_get_with_side_effect_safe',
),
],
ResponseSequence(),
)

assert responses.responses[1].created_resource
assert not responses.test_results['IDORPlugin']