From 0d47952611198ef6b1163f366dc03922d20b1475 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 09:42:04 +0200 Subject: Adding upstream version 7.94+git20230807.3be01efb1+dfsg. Signed-off-by: Daniel Baumann --- nselib/anyconnect.lua | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 nselib/anyconnect.lua (limited to 'nselib/anyconnect.lua') diff --git a/nselib/anyconnect.lua b/nselib/anyconnect.lua new file mode 100644 index 0000000..5f05d86 --- /dev/null +++ b/nselib/anyconnect.lua @@ -0,0 +1,144 @@ +--- +-- This library implements HTTP requests used by the Cisco AnyConnect VPN Client +-- +-- @author Patrik Karlsson +-- +-- @args anyconnect.group AnyConnect tunnel group (default: VPN) +-- @args anyconnect.mac MAC address of connecting client (default: random MAC) +-- @args anyconnect.version Version of connecting client (default: 3.1.05160) +-- @args anyconnect.ua User Agent of connecting client (default: AnyConnect Darwin_i386 3.1.05160) + +local http = require('http') +local stdnse = require('stdnse') +local url = require('url') +local table = require('table') +local rand = require "rand" + +local args_group= stdnse.get_script_args('anyconnect.group') or "VPN" +local args_mac= stdnse.get_script_args('anyconnect.mac') +local args_ver = stdnse.get_script_args('anyconnect.version') or "3.1.05160" +local args_ua = stdnse.get_script_args('anyconnect.ua') or ("AnyConnect Darwin_i386 %s"):format(args_ver) + +_ENV = stdnse.module("anyconnect", stdnse.seeall) + +Cisco = { + + Util = { + + generate_mac = function() + return stdnse.format_mac(rand.random_string(6)) + end, + + }, + + AnyConnect = { + + new = function(self, host, port) + local o = { host = host, port = port } + setmetatable(o, self) + self.__index = self + return o + end, + + -- generate a random hex-string of length 'length' + -- + generate_random = function(length) + return rand.random_string(length * 2, '0123456789ABCDEF') + end, + + connect = function(self) + args_mac = args_mac or Cisco.Util.generate_mac() + local headers = { + ['User-Agent'] = args_ua, + ['Accept'] = '*/*', + ['Accept-Encoding'] = 'identity', + ['X-Transcend-Version'] = 1, + ['X-Aggregate-Auth'] = 1, + ['X-AnyConnect-Platform'] = 'mac-intel' + } + + local data = ([[ + +%s +mac-intel + +%s +%s +https://%s:%s +]]):format(args_ver, self.generate_random(64), args_mac, args_group, self.host.ip, self.port.number) + + local options = { header=headers , no_cache=true, redirect_ok = function(host,port) + local c = 5 + return function(url) + if ( c==0 ) then return false end + c = c - 1 + return true + end + end + } + + local path = '/' + local response = http.head(self.host, self.port, path, options) + -- account for redirects + if response.status ~= 200 then + return false, "Failed to connect to SSL VPN server" + elseif response.location then + local u = url.parse(response.location[#response.location]) + if u.host then + self.host = u.host + end + if u.path then + path = u.path + end + end + + response = http.post(self.host, self.port, path, options, nil, data) + + if response.status ~= 200 or response.body == nil then + return false, "Not a Cisco ASA or unsupported version" + end + + local xmltags = { + 'version', + 'tunnel-group', + 'group-alias', + 'config-hash', + 'host-scan-ticket', + 'host-scan-token', + 'host-scan-base-uri', + 'host-scan-wait-uri', + 'banner' + } + + self.conn_attr = {} + for _, tag in ipairs(xmltags) do + local body = response.body:gsub('\r?\n', '') + local filter = ("<%s.->(.*)"):format(tag:gsub('-', '%%-'), tag:gsub('-', '%%-')) + local m = body:match(filter) + if m then + self.conn_attr[tag] = m + end + end + + if not self.conn_attr['version'] then + return false, "Not a Cisco ASA or unsupported version" + end + + -- in case we were redirected + self.conn_attr['host'] = stdnse.get_hostname(self.host) + return true + end, + + --- + -- Returns the version of the remote SSL VPN concentrator + -- @return table containing major, minor and rev numeric values + get_version = function(self) + local ver = {} + ver['major'], ver['minor'], ver['rev'] = self.conn_attr['version']:match('^(%d-)%.(%d-)%((.*)%)$') + return ver + end + + } +} + +return _ENV -- cgit v1.2.3