Usage

Most of Fluid Asserts functions for the end-user are predicates regarding a specific vulnerability. In that sense, you “ask” Asserts whether a certain Target of Evaluation has an open vulnerability of some type or if it has been closed.

Asserts replies by telling you that the status of the vulnerability is OPEN or CLOSED plus additional info, such as why it thinks the flaw is or is not still there, where it is found, when it was tested, and the fingerprint (the gory details of the transaction).

SQL Injection

To verify that a SQL injection is still open, you can write a script like this:

from fluidasserts.proto import http

http.has_sqli('http://testphp.vulnweb.com/AJAX/infoartist.php?id=3%27')

Then run it:

$ asserts open_sqli.py
#    ________      _     __   ___                        __
#   / ____/ /_  __(_)___/ /  /   |  _____________  _____/ /______
#  / /_  / / / / / / __  /  / /| | / ___/ ___/ _ \/ ___/ __/ ___/
# / __/ / / /_/ / / /_/ /  / ___ |(__  |__  )  __/ /  / /_(__  )
#/_/   /_/\__,_/_/\__,_/  /_/  |_/____/____/\___/_/   \__/____/
#
# v. 19.10.21424
#  ___
# | >>|> fluid
# |___|  attacks, we hack your software
#
# Loading attack modules ...
#
---
check: fluidasserts.proto.http -> has_sqli
description: Check SQLi vulnerability by checking common SQL strings in response.
status: OPEN
message: Bad text is present in response
vulnerabilities:
- where: http://testphp.vulnweb.com/AJAX/infoartist.php?id=3%27
  source: HTTP/Response/Body
  specific: HTTP/Implementation
  fingerprint:
    verb: GET
    status: 200
    headers:
      Server: nginx/1.4.1
      Date: Wed, 06 May 1970 14:20:25 GMT
      Content-Type: text/xml
      Transfer-Encoding: chunked
      Connection: keep-alive
      X-Powered-By: PHP/5.3.10-1~lucid+2uwsgi2
    sha256: 588702eb0b53294654f934d86664956e9739db47c34ffd8d703550cd5fd670a0
parameters:
  url: http://testphp.vulnweb.com/AJAX/infoartist.php?id=3%27
  args: []
  kwargs: {}
vulnerable_incidences: 1
when: 2019-10-15T21:05:51+0000
elapsed_seconds: 0.2
test_kind: DAST
risk: high
---
summary:
  test time: 0.4708 seconds
  checks:
    total: 1 (100%)
    errors: 0 (0.00%)
    unknown: 0 (0.00%)
    closed: 0 (0.00%)
    opened: 1 (100.00%)
  risk:
    high: 1 (100.00%)
    medium: 0 (0.00%)
    low: 0 (0.00%)

To verify that a SQL injection is closed, use the same function:

from fluidasserts.proto import http

http.has_sqli('http://testphp.vulnweb.com/AJAX/infoartist.php?id=3')
$ asserts closed_sqli.py
#    ________      _     __   ___                        __
#   / ____/ /_  __(_)___/ /  /   |  _____________  _____/ /______
#  / /_  / / / / / / __  /  / /| | / ___/ ___/ _ \/ ___/ __/ ___/
# / __/ / / /_/ / / /_/ /  / ___ |(__  |__  )  __/ /  / /_(__  )
#/_/   /_/\__,_/_/\__,_/  /_/  |_/____/____/\___/_/   \__/____/
#
# v. 19.10.21424
#  ___
# | >>|> fluid
# |___|  attacks, we hack your software
#
# Loading attack modules ...
#
---
check: fluidasserts.proto.http -> has_sqli
description: Check SQLi vulnerability by checking common SQL strings in response.
status: CLOSED
message: Bad text is not present in response
secure-units:
- where: http://testphp.vulnweb.com/AJAX/infoartist.php?id=3
  source: HTTP/Response/Body
  specific: HTTP/Implementation
  fingerprint:
    verb: GET
    status: 200
    headers:
      Server: nginx/1.4.1
      Date: Wed, 06 May 1970 14:20:24 GMT
      Content-Type: text/xml
      Transfer-Encoding: chunked
      Connection: keep-alive
      X-Powered-By: PHP/5.3.10-1~lucid+2uwsgi2
    sha256: 588702eb0b53294654f934d86664956e9739db47c34ffd8d703550cd5fd670a0
parameters:
  url: http://testphp.vulnweb.com/AJAX/infoartist.php?id=3
  args: []
  kwargs: {}
vulnerable_incidences: 0
when: 2019-10-15T21:05:50+0000
elapsed_seconds: 0.26
test_kind: DAST
risk: high
---
summary:
  test time: 0.5992 seconds
  checks:
    total: 1 (100%)
    errors: 0 (0.00%)
    unknown: 0 (0.00%)
    closed: 1 (100.00%)
    opened: 0 (0.00%)
  risk:
    high: 0 (0%)
    medium: 0 (0%)
    low: 0 (0%)

Cross-Site Scripting (XSS)

The function has_xss() requires a few more parameters:

from fluidasserts.proto import http

URL = 'http://testphp.vulnweb.com/guestbook.php'
BAD_TEXT = r'<script>alert\("Hacked by FLUIDAttacks"\);<\/script>'
DATA = {
    'name': 'anonymous user',
    'submit': 'add message',
    'text': '<script>alert("Hacked by FLUIDAttacks");</script>'
}

http.has_xss(URL, BAD_TEXT, data=DATA)
$ asserts open_xss.py
#    ________      _     __   ___                        __
#   / ____/ /_  __(_)___/ /  /   |  _____________  _____/ /______
#  / /_  / / / / / / __  /  / /| | / ___/ ___/ _ \/ ___/ __/ ___/
# / __/ / / /_/ / / /_/ /  / ___ |(__  |__  )  __/ /  / /_(__  )
#/_/   /_/\__,_/_/\__,_/  /_/  |_/____/____/\___/_/   \__/____/
#
# v. 19.10.21424
#  ___
# | >>|> fluid
# |___|  attacks, we hack your software
#
# Loading attack modules ...
#
---
check: fluidasserts.proto.http -> has_xss
description: Check XSS vulnerability by checking injected string.
status: OPEN
message: Bad text is present in response
vulnerabilities:
- where: http://testphp.vulnweb.com/guestbook.php
  source: HTTP/Response/Body
  specific: HTTP/Implementation
  fingerprint:
    verb: POST
    status: 200
    headers:
      Server: nginx/1.4.1
      Date: Wed, 06 May 1970 14:20:27 GMT
      Content-Type: text/html
      Transfer-Encoding: chunked
      Connection: keep-alive
      X-Powered-By: PHP/5.3.10-1~lucid+2uwsgi2
      Content-Encoding: gzip
    sha256: ca5ded653d430a257f367269414f50814a63780a7ef0a37374519140d7c1df77
parameters:
  url: http://testphp.vulnweb.com/guestbook.php
  expect: <script>alert\("Hacked by FLUIDAttacks"\);<\/script>
  args: []
  kwargs:
    data:
      name: anonymous user
      submit: add message
      text: <script>alert("Hacked by FLUIDAttacks");</script>
vulnerable_incidences: 1
when: 2019-10-15T21:05:53+0000
elapsed_seconds: 0.19
test_kind: DAST
risk: low
---
summary:
  test time: 0.4734 seconds
  checks:
    total: 1 (100%)
    errors: 0 (0.00%)
    unknown: 0 (0.00%)
    closed: 0 (0.00%)
    opened: 1 (100.00%)
  risk:
    high: 0 (0.00%)
    medium: 0 (0.00%)
    low: 1 (100.00%)

To test if an XSS vulnerability has been closed:

from fluidasserts.proto import http

URL = 'http://testphp.vulnweb.com/guestbook.php'
BAD_TEXT = r'<script>alert\("Hacked by FLUIDAttacks"\);<\/script>'
DATA = {
    'name': 'anonymous user',
    'submit': 'add message',
    'text': 'Hacked by FLUIDAttacks'
}

http.has_xss(URL, BAD_TEXT, data=DATA)
$ asserts closed_xss.py
#    ________      _     __   ___                        __
#   / ____/ /_  __(_)___/ /  /   |  _____________  _____/ /______
#  / /_  / / / / / / __  /  / /| | / ___/ ___/ _ \/ ___/ __/ ___/
# / __/ / / /_/ / / /_/ /  / ___ |(__  |__  )  __/ /  / /_(__  )
#/_/   /_/\__,_/_/\__,_/  /_/  |_/____/____/\___/_/   \__/____/
#
# v. 19.10.21424
#  ___
# | >>|> fluid
# |___|  attacks, we hack your software
#
# Loading attack modules ...
#
---
check: fluidasserts.proto.http -> has_xss
description: Check XSS vulnerability by checking injected string.
status: CLOSED
message: Bad text is not present in response
secure-units:
- where: http://testphp.vulnweb.com/guestbook.php
  source: HTTP/Response/Body
  specific: HTTP/Implementation
  fingerprint:
    verb: POST
    status: 200
    headers:
      Server: nginx/1.4.1
      Date: Wed, 06 May 1970 14:20:26 GMT
      Content-Type: text/html
      Transfer-Encoding: chunked
      Connection: keep-alive
      X-Powered-By: PHP/5.3.10-1~lucid+2uwsgi2
      Content-Encoding: gzip
    sha256: ca5ded653d430a257f367269414f50814a63780a7ef0a37374519140d7c1df77
parameters:
  url: http://testphp.vulnweb.com/guestbook.php
  expect: <script>alert\("Hacked by FLUIDAttacks"\);<\/script>
  args: []
  kwargs:
    data:
      name: anonymous user
      submit: add message
      text: Hacked by FLUIDAttacks
vulnerable_incidences: 0
when: 2019-10-15T21:05:52+0000
elapsed_seconds: 0.21
test_kind: DAST
risk: low
---
summary:
  test time: 0.4831 seconds
  checks:
    total: 1 (100%)
    errors: 0 (0.00%)
    unknown: 0 (0.00%)
    closed: 1 (100.00%)
    opened: 0 (0.00%)
  risk:
    high: 0 (0%)
    medium: 0 (0%)
    low: 0 (0%)