geneva/plugins/http/client.py

103 lines
3.1 KiB
Python

"""
Run by the evaluator, tries to make a GET request to a given server
"""
import argparse
import logging
import os
import random
import socket
import sys
import time
import traceback
import urllib.request
import requests
socket.setdefaulttimeout(1)
import external_sites
import actions.utils
from plugins.plugin_client import ClientPlugin
BASEPATH = os.path.dirname(os.path.abspath(__file__))
class HTTPClient(ClientPlugin):
"""
Defines the HTTP client.
"""
name = "http"
def __init__(self, args):
"""
Initializes the HTTP client.
"""
ClientPlugin.__init__(self)
self.args = args
@staticmethod
def get_args(command):
"""
Defines required args for this plugin
"""
super_args = ClientPlugin.get_args(command)
parser = argparse.ArgumentParser(description='HTTP Client', prog="http/client.py")
parser.add_argument('--host-header', action='store', default="", help='specifies host header for HTTP request')
parser.add_argument('--injected-http-contains', action='store', default="", help='checks if injected http response contains string')
args, _ = parser.parse_known_args(command)
args = vars(args)
super_args.update(args)
return super_args
def run(self, args, logger, engine=None):
"""
Try to make a forbidden GET request to the server.
"""
fitness = 0
url = args.get("server", "")
assert url, "Cannot launch HTTP test with no server"
if not url.startswith("http://"):
url = "http://" + url
headers = {}
if args.get('host_header'):
headers["Host"] = args.get('host_header')
# If we've been given a non-standard port, append that to the URL
port = args.get("port", 80)
if port != 80:
url += ":%s" % str(port)
if args.get("bad_word"):
url += "?q=%s" % args.get("bad_word")
injected_http = args.get("injected_http_contains")
try:
res = requests.get(url, allow_redirects=False, timeout=3, headers=headers)
logger.debug(res.text)
# If we need to monitor for an injected response, check that here
if injected_http and injected_http in res.text:
fitness -= 90
else:
fitness += 100
except (requests.exceptions.ConnectionError, ConnectionResetError) as exc:
logger.exception("Connection RST.")
fitness -= 90
except urllib.error.URLError as exc:
logger.debug(exc)
fitness += -101
# Timeouts generally mean the strategy killed the TCP stream.
# HTTPError usually mean the request was destroyed.
# Punish this more harshly than getting caught by the censor.
except (requests.exceptions.Timeout, requests.exceptions.HTTPError) as exc:
logger.debug(exc)
fitness += -120
except Exception:
logger.exception("Exception caught in HTTP test to site %s.", url)
fitness += -100
return fitness * 4