/usr/share/ettercap/lua/core/http.lua is in ettercap-common 1:0.8.2-2build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | ---
-- Parser and functions for HTTP requests/respnoses
--
-- Created by Ryan Linn and Mike Ryan
-- Copyright (C) 2012 Trustwave Holdings, Inc.
local packet = require("packet")
local hook_points = require("hook_points")
require("ec_string")
require("base64")
local ports = { 80, 443, 8080 }
-- http object that we'll bind all public things to
http = {}
http.hook = hook_points.http
-- parse_post
-- Use: split POST data into k/v pieces and put in a table
-- Args: POST body
-- Out: table of k:v post vars
local function parse_args(argstr)
if not argstr or argstr == "" then
return nil
end
local args = {}
kv = split(argstr,'&')
for i,val in ipairs(kv) do
local start,finish,k,v = string.find(val, '^(.-)=(.*)')
if k and v then
args[k] = v
end
end
return args
end
-- parse_headers
-- Use: parses the headers into k:v format
-- Args: headers raw string
-- Out: table of k:v headers
local function parse_headers(headers)
if headers == nil then
return nil
end
local h = {}
for hline in string.gmatch(headers,"(.-)\r?\n") do
local spos,epos,k,v = string.find(hline,"^(%S-): (.*)")
if spos and spos > 0 then
h[k] = v
end
end
return h
end
http.get_prefix = function (port)
if port == 80 then
return "http://"
elseif port == 443 then
return "https://"
elseif port == 8080 then
return "proxy://"
else
return "unknown://"
end
end
local function parse_auth(auth)
if not auth or auth == "" then
return nil
end
local start,finish,auth_type, auth_str = string.find(auth, '^(%S+) (.*)')
if auth_type == "Basic" then
return from_base64(auth_str)
end
return nil
end
-- parse_http
-- Use: parses a http packet into components
-- Args: raw packet
-- Out: nil if not a request or response
-- table with the following fields:
-- - reqest or response set
-- - for request
-- - verb
-- - url
-- - httpver
-- - post_data (TABLE IF a POST REQUEST)
-- - get_data ( TABLE IF a GET REQUEST)
-- - for post
-- - status_code
-- - status_msg
-- - http_ver
--
-- - headers
-- - body
http.parse_http = function (pkt)
local http_body = packet.read_data(pkt)
local p = {}
if (http_body == nil) then
return nil
end
local start,finish,header,body = string.find(http_body, '^(.-)\r?\n\r?\n(.*)')
if (header == nil or body == nil or header == "") then
return nil
end
if (starts_with(header,"^GET ") > 0 or starts_with(header,"^HEAD ") > 0 or starts_with(header,"^POST ") > 0 or starts_with(header,"^CONNECT ") > 0 ) then
local spos,epos, verb, url, httpver = string.find(header,'^(%S+) (.-) HTTP/(%d.%d)')
p.request= 1
p.verb = verb
p.httpver = httpver
p.headers = parse_headers(header)
p.body = body
if p.headers["Host"] then
p.url = http.get_prefix(packet.dst_port(pkt)) .. p.headers["Host"] .. url
else
p.url = http.get_prefix(packet.dst_port(pkt)) .. packet.dst_ip(pkt) .. url
end
if p.verb == 'POST' then
p.post_data = parse_args(body)
end
local spos,epos,baseurl,args = string.find(p.url,'^(.-)?(.*)')
if baseurl and args then
p.baseurl = baseurl
p.get_data = parse_args(args)
end
if p.headers['Authorization'] then
p.creds = parse_auth(p.headers['Authorization'])
end
elseif (starts_with(header,"^HTTP/%d.%d") > 0 ) then
p.response = 1
local spos,epos,httpver, code, msg = string.find(header,'^HTTP/(%d.%d) (%d+) (.-)\r?\n')
p.httpver = httpver
p.status_code = tonumber(code)
p.status_msg = msg
p.headers = parse_headers(header)
p.body = body
else
return nil
end
return p
end
http.session_id = function (p,msg)
local session_id = nil
if msg.request then
session_id = string.format("%s%d%s%d",packet.src_ip(p),packet.src_port(p),packet.dst_ip(p),packet.dst_port(p))
elseif msg.response then
session_id = string.format("%s%d%s%d",packet.dst_ip(p),packet.dst_port(p),packet.src_ip(p),packet.src_port(p))
end
return session_id
end
return http
|