Skip to content

Commit

Permalink
more specs for linux post libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
h00die committed Nov 27, 2024
1 parent b9c8c63 commit 61705db
Show file tree
Hide file tree
Showing 4 changed files with 670 additions and 21 deletions.
57 changes: 49 additions & 8 deletions lib/msf/core/post/linux/packages.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,59 @@ module Packages
# @param package The package name to check for
# @return [Rex::Version] nil if OS is not supported or package is not installed
#
def installed_package_version?(package)
def installed_package_version(package)
info = get_sysinfo

if ['ubuntu', 'debian'].include? info[:distro]
package = cmd_exec("dpkg -l #{package} | grep \'^ii\'")
return nil unless package.start_with?('ii')
if ['debian', 'ubuntu'].include?info[:distro]
package_version = cmd_exec("dpkg -l #{package} | grep \'^ii\'")
return nil unless package_version.start_with?('ii')

package = package.split(' ')[2]
package = package.gsub('+', '.')
return Rex::Version.new(package)
package_version = package_version.split(' ')[2]
package_version = package_version.gsub('+', '.')
return Rex::Version.new(package_version)
elsif ['redhat', 'fedora'].include?(info[:distro])
package_version = cmd_exec("rpm -q #{package}")
return nil if package_version.include?('is not installed')

# dnf-4.18.0-2.fc39.noarch
# remove package name at the beginning
package_version = package_version.split("#{package}-")[1]
# remove arch at the end
package_version = package_version.sub(/\.[^.]*$/, '')
return Rex::Version.new(package_version)
# XXX not tested on live system
# https://docs.oracle.com/cd/E23824_01/html/821-1451/gkunu.html
elsif ['solaris', 'oracle'].include?(info[:distro])
package_version = cmd_exec("pkg info #{package}")
return nil unless package_version.include?('State: Installed')

package_version = package_version.match(/Version: (.+)/)[1]
return Rex::Version.new(package_version)
elsif ['freebsd'].include?(info[:distro])
package_version = cmd_exec("pkg info #{package}")
return nil unless package_version.include?('Version')

package_version = package_version.match(/Version\s+:\s+(.+)/)[1]
return Rex::Version.new(package_version)
# XXX not tested on live system
elsif ['gentoo'].include?(info[:distro])
# https://wiki.gentoo.org/wiki/Equery
package_version = cmd_exec("equery --quiet list #{package}")
return nil if package_version.include?('No packages found')

package_version = package_version.split('/')[1]
# make gcc-1.1 to 1.1
package_version = package_version.sub(/.*?-/, '')
return Rex::Version.new(package_version)
# XXX not tested on live system
elsif ['arch'].include?(info[:distro])
package_version = cmd_exec("pacman -Qi #{package}")
return nil unless package_version.include?('Version')

package_version = package_version.match(/Version\s+:\s+(.+)/)[1]
return Rex::Version.new(package_version)
else
vprint_error('installed_package_version? is being called on an unsupported OS')
vprint_error('installed_package_version is being called on an unsupported OS')
end
nil
end
Expand Down
4 changes: 3 additions & 1 deletion lib/msf/core/post/linux/system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ module System
include ::Msf::Post::Common
include ::Msf::Post::File
include ::Msf::Post::Unix
include Msf::Auxiliary::Report

#
# Returns a Hash containing Distribution Name, Version and Kernel Information
#
def get_sysinfo
system_data = {}
etc_files = cmd_exec('ls /etc').split

kernel_version = cmd_exec('uname -a')
system_data[:kernel] = kernel_version

Expand Down Expand Up @@ -442,6 +442,8 @@ def get_container_type
return 'Docker'
when /lxc/i
return 'LXC'
else
return 'Unknown'
end
else
# Check for the "container" environment variable
Expand Down
64 changes: 52 additions & 12 deletions spec/lib/msf/core/post/linux/packages.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,75 @@
mod
end

describe '#installed_package_version?' do
context 'when the OS isnt supported' do
it 'returns nil' do
allow(subject).to receive(:get_sysinfo).and_return({:kernel=>"", :distro=>"foobar", :version=>""})
expect(subject.installed_package_version?('test')).to be_nil
describe '#installed_package_version' do
context 'when the OS isnt supported' do
it 'returns nil' do
allow(subject).to receive(:get_sysinfo).and_return({:kernel=>"", :distro=>"unsupported", :version=>""})
expect(subject.installed_package_version('test')).to be_nil
end
end
end

context 'when the Ubuntu package isnt installed' do
context 'when the Ubuntu/Debian package isnt installed' do
it 'returns nil' do
allow(subject).to receive(:get_sysinfo).and_return({:kernel=>"Linux ubuntu22 5.15.0-25-generic #25-Ubuntu SMP Wed Mar 30 15:54:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux", :distro=>"ubuntu", :version=>"Ubuntu 22.04.5 LTS"})
allow(subject).to receive(:cmd_exec).and_return('dpkg-query: no packages found matching example')
expect(subject.installed_package_version?('test')).to be_nil
expect(subject.installed_package_version('test')).to be_nil
end
end

context 'when the Ubuntu package is installed' do
context 'when the Ubuntu/Debian package is installed' do
it 'returns 3.5-5ubuntu2.1' do
allow(subject).to receive(:get_sysinfo).and_return({:kernel=>"Linux ubuntu22 5.15.0-25-generic #25-Ubuntu SMP Wed Mar 30 15:54:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux", :distro=>"ubuntu", :version=>"Ubuntu 22.04.5 LTS"})
allow(subject).to receive(:cmd_exec).and_return('ii needrestart 3.5-5ubuntu2.1 all check which daemons need to be restarted after library upgrades')
expect(subject.installed_package_version?('test')).to eq(Rex::Version.new('3.5-5ubuntu2.1'))
expect(subject.installed_package_version('test')).to eq(Rex::Version.new('3.5-5ubuntu2.1'))
end
end

context 'when the Ubuntu package is installed with a + in the version number' do
context 'when the Ubuntu/Debian package is installed with a + in the version number' do
it 'returns 1.34.dfsg.pre.1ubuntu0.1.22.04.2' do
allow(subject).to receive(:get_sysinfo).and_return({:kernel=>"Linux ubuntu22 5.15.0-25-generic #25-Ubuntu SMP Wed Mar 30 15:54:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux", :distro=>"ubuntu", :version=>"Ubuntu 22.04.5 LTS"})
allow(subject).to receive(:cmd_exec).and_return('ii tar 1.34+dfsg-1ubuntu0.1.22.04.2 amd64 GNU version of the tar archiving utility')
expect(subject.installed_package_version?('test')).to eq(Rex::Version.new("1.34.dfsg.pre.1ubuntu0.1.22.04.2"))
expect(subject.installed_package_version('test')).to eq(Rex::Version.new("1.34.dfsg.pre.1ubuntu0.1.22.04.2"))
end
end

context 'when distro is redhat or fedora' do
it 'returns the package version' do
allow(subject).to receive(:get_sysinfo).and_return({:kernel=>"", :distro=>"redhat", :version=>""})
allow(subject).to receive(:cmd_exec).and_return('curl-8.2.1-3.fc39.x86_64')
expect(subject.installed_package_version('curl')).to eq(Rex::Version.new('8.2.1-3.fc39'))
end
end

context 'when distro is solaris' do
it 'returns the package version' do
allow(subject).to receive(:get_sysinfo).and_return({:kernel=>"", :distro=>"solaris", :version=>""})
allow(subject).to receive(:cmd_exec).and_return('State: Installed\nVersion: 1.2.3')
expect(subject.installed_package_version('test')).to eq(Rex::Version.new('1.2.3'))
end
end

context 'when distro is freebsd' do
it 'returns the package version' do
allow(subject).to receive(:get_sysinfo).and_return({:kernel=>"", :distro=>"freebsd", :version=>""})
allow(subject).to receive(:cmd_exec).and_return('Version : 1.2.3')
expect(subject.installed_package_version('test')).to eq(Rex::Version.new('1.2.3'))
end
end

context 'when distro is gentoo' do
it 'returns the package version' do
allow(subject).to receive(:get_sysinfo).and_return({:kernel=>"", :distro=>"gentoo", :version=>""})
allow(subject).to receive(:cmd_exec).and_return('sys-devel/gcc-4.3.2-r3')
expect(subject.installed_package_version('test')).to eq(Rex::Version.new('4.3.2-r3'))
end
end

context 'when distro is arch' do
it 'returns the package version' do
allow(subject).to receive(:get_sysinfo).and_return({:kernel=>"", :distro=>"arch", :version=>""})
allow(subject).to receive(:cmd_exec).and_return('Version : 1.2.3')
expect(subject.installed_package_version('test')).to eq(Rex::Version.new('1.2.3'))
end
end
end
Expand Down
Loading

0 comments on commit 61705db

Please sign in to comment.