Miscellaneous - Linux
SuckMore Shell
-
Challenge: A new Command Line based UI is given (Limited shell). Could you escape the shell to read other stuff and get flag at /flag.txt
-
Recon and Trail+Error
- Trying all basic commands,
- ls
- apt
- touch
- ps -ef
- cat
- pwd
- uname -a
- less
- more
- bash
- set
- bash
- /bin/sh -i
root@kali:~/Downloads/chirp# ssh ctf@107.21.60.114
ctf@107.21.60.114's password:
SuckMORE shell v1.0.1. Note: for POSIX support update to v1.1.0
suckmore>
suckmore>apt
bash: apt: command not found
suckmore>ls
suckmore>ll
bash: ll: command not found
suckmore>ps -ef
bash: ps: command not found
suckmore>touch
touch: missing file operand
Try 'touch --help' for more information.
suckmore>pwd
suckmore>uname -a
Linux ad8528675a00 4.15.0-1035-aws #37-Ubuntu SMP Mon Mar 18 16:15:14 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
suckmore>bash
Why would you ever want to leave suckmore shell?
suckmore>/bin/sh
suckmore>set
BASH=/bin/sh
BASHOPTS=cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="4" [2]="23" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")
BASH_VERSION='4.4.23(1)-release'
COLUMNS=101
DIRSTACK=()
DISTTAG=fcontainer
EUID=1000
FBR=f
FGC=f
GROUPS=()
HISTFILE=/home/ctf/.bash_history
HISTFILESIZE=500
HISTSIZE=500
HOME=/home/ctf
HOSTNAME=ad8528675a00
HOSTTYPE=x86_64
IFS='
'
LINES=38
MACHTYPE=x86_64-redhat-linux-gnu
MAILCHECK=60
OPTERR=1
OPTIND=1
OSTYPE=linux-gnu
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
POSIXLY_CORRECT=y
PPID=1
PS1='suckmore>'
PS2='> '
PS4='+ '
PWD=/
SHELL=/bin/sh
SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor:posix
SHLVL=3
TERM=xterm
UID=1000
_=/bin/sh
suckmore>/bin/sh -i
- Even though some commands were informative nothing was promising. The commands
more and less
sounded interesting and also linked to the challenge title –>more
suckmore>less
We are suckMORE, not suckless
suckmore>more
SuckMORE shell, v1.0.1, (c) SuckMore Software, a division of WPI Digital Holdings Ltd.
- Investigating
more
command further to read the flag. Once the shell was upgraded with/bin/sh
, more command worked in different way to escape jail and read the flag.
suckmore>more /home/ctf/flag
SuckMORE shell, v1.0.1, (c) SuckMore Software, a division of WPI Digital Holdings Ltd. /home/ctf/flag
suckmore>/bin/sh
suckmore>more
more: bad usage
Try 'more --help' for more information.
suckmore>more /home/ctf/flag
WPI{bash_sucks0194342}
suckmore>
- References
https://pleiades.ucsc.edu/hyades/SSH_Escape_Sequences
https://netsec.ws/?p=337
PseudoRandom
Solved after the CTF ended
-
Challenge Random is not really a random.
- Thoughts Obviously this had got to something with the randoms
- /dev/urandom
- /dev/random
- Looking at
/dev/urandom
we get a base64 encoded string which doesnt change. Decoding this just returned some random bytes.
sh-4.4$ cat urandom
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
- Looking at
/dev/random
we get a some string with salted keyword.
sh-4.4$ cat random
Salted__?>
[?/?=????m?k???V?SӨ?
%텤'Ϊ0KIWi?Գro?ۃ?:
e???i????|?|[V?e??=a???ȽUP?R?k??l?????1|??ϕ!?L??9??%?(?K??s$?U f_??? ?Up?%ޏ?#?Q??F?4??+??x?pc?&?-?ַ?쒓+c??њ?K??.??9?g??W??l2?`!?????>BS?G???k?de?????4?Z?2?l???$*[????S(?3m_?
?
???k????w4??`hMfbi)?H?ˠZ?!ሥ?*???Fw?Ed?aĄ???\?_???TWLBE>J??ڼ?(?"?g????0݁?@ͨ{1?oe?#??I%?O?s*?+?D{?????d??@?[?2?????F??̷&??rv Qw?Ռ$Tz?;e?3s?????=?W??i?????YV?kϿwl??`?@(???V??&i?y??|?쩷?҃+??\q><?{K-?5??1?Y? <?:?d54?hm
????E3Х?sh-4.4$
sh-4.4$
-
After this step I was out of direction on what needs to be done to move forward. I spent a long time thinking this might be a crypto challenge from here on.
-
After some long time, I tried some basic recon and got some lead
sh-4.4$
sh-4.4$ file urandom
urandom: ASCII text
sh-4.4$ file random
random: openssl enc'd data with salted password
- Using
OpenSSL
to use the urandom string as the key to decrypt the random string was the solution
sh-4.4$ openssl enc -aes-256-cbc -d -in random -kfile urandom
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
Being holy in our church means installing a wholly free operating system--GNU/Linux is a good choice--and not putting any non-free software on your computer. Join the Church of Emacs, and you too can be a saint!
And lo, it came to pass, that the neophyte encountered the Beplattered One and humbly posed the question "Oh great master, is it a sin to use vi?" And St. IGNUcuis dist thus reply unto him, "No, my young hacker friend, it is not a sin. It is a penance."
WPI{@11_Ur_d3v1c3s_r_b3l0ng_2_us}
Cryptography
JoCipher
A Crypto + Python Reversing challenge
- Challenge
- Reversing
.pyc
file to read source code - Filling in the arguments to check the output with the program
- Known Plain-text method to bypass full reversing –> Try out different values until we get format
WPI{}
- Once correct format is received skipping through similar values of t to get a flag that makes sense.
- SourceCode
# 2019.04.13 22:02:20 PDT
# Embedded file name: ./jocipher.py
import argparse, re
num = ''
first = ''
second = ''
third = ''
def setup():
global third
global second
global num
global first
num += '1'
num += '2'
num += '3'
num += '4'
num += '5'
num += '6'
num += '7'
num += '8'
num += '9'
num += '0'
first += 'q'
first += 'w'
first += 'e'
first += 'r'
first += 't'
first += 'y'
first += 'u'
first += 'i'
first += 'o'
first += 'p'
second += 'a'
second += 's'
second += 'd'
second += 'f'
second += 'g'
second += 'h'
second += 'j'
second += 'k'
second += 'l'
third += 'z'
third += 'x'
third += 'c'
third += 'v'
third += 'b'
third += 'n'
third += 'm'
def encode(string, shift):
result = ''
for i in range(len(string)):
char = string.lower()[i]
if char in num:
new_char = num[(num.index(char) + shift) % len(num)]
result += new_char
elif char in first:
new_char = first[(first.index(char) + shift) % len(first)]
if string[i].isupper():
result += new_char.upper()
else:
result += new_char
elif char in second:
new_char = second[(second.index(char) + shift) % len(second)]
if string[i].isupper():
result += new_char.upper()
else:
result += new_char
elif char in third:
new_char = third[(third.index(char) + shift) % len(third)]
if string[i].isupper():
result += new_char.upper()
else:
result += new_char
else:
result += char
print result
return 0
def decode(string, shift):
result = ''
shift = -1 * shift
for i in range(len(string)):
char = string.lower()[i]
if char in num:
new_char = num[(num.index(char) + shift) % len(num)]
result += new_char
elif char in first:
new_char = first[(first.index(char) + shift) % len(first)]
if string[i].isupper():
result += new_char.upper()
else:
result += new_char
elif char in second:
new_char = second[(second.index(char) + shift) % len(second)]
if string[i].isupper():
result += new_char.upper()
else:
result += new_char
elif char in third:
new_char = third[(third.index(char) + shift) % len(third)]
if string[i].isupper():
result += new_char.upper()
else:
result += new_char
else:
result += char
print result
return 0
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--string', '-s', type=str, required=True, help='the string to encode or decode')
parser.add_argument('--shift', '-t', type=int, required=True, help='the shift value to use')
parser.add_argument('--encode', '-e', required=False, action='store_true', help='encode the string')
parser.add_argument('--decode', '-d', required=False, action='store_true', help='decode the string')
args = parser.parse_args()
setup()
p = re.compile('[a-zA-Z0-9\\-{}]')
if p.match(args.string) is not None:
if args.encode:
ret = encode(args.string, args.shift)
elif args.decode:
ret = decode(args.string, args.shift)
if ret is not 0:
print 'Sorry, this cipher only uses the [a-zA-Z0-9\\-{}]'
else:
print 'Sorry, this cipher only uses the [a-zA-Z0-9\\-{}]'
return
if __name__ == '__main__':
main()
# okay decompyling jocipher.pyc
# decompiled 1 files: 1 okay, 0 failed, 0 verify failed
# 2019.04.13 22:02:20 PDT
Pwn
Source Pt1
-
This is my first time at blind pwning, without any source or binary
-
Challenge
- Brutforce input arguments (Password) with As as usual
- At a certain point the code is visible
Recon
(Nice Category!)
Chirp
- Given
- An image of a
bird
with filenamechirp.jpg
- An image of a
-
A mistook this for a forensics challenge and started investigation in a different way. ( Spent a lot of time )
-
Sitting back, we just have to redact and think what we see.
–> Filename: chrip.jpg
–> Picture: Bird
–> Logo: SIEGE -
====> Twitter @Siege
Reverse Engineer
Strings
- This was a very easy one as the challgen name suggested. The preliminary step in binary analsysis. Use strings to extract hardcoded strings.
Web
Web Inspect
- n00b challenge –> Inspect website source code
getAFlag
- Challenge - Just enter the password, login and get a flag
- Recon - Source code analysis. Found a harcoded base64 encoded string with a message
- The pseudocode for authentication at
/auth.php
(hint from the above message)
-
Bypass Authentication
- Inorder to bypass authentication we need to make thepasscode input
==password stored in server
-
Initially thought about bruteforce, then decided to play with the source code
- Looking at the PHP vulnerabilities
- Eliminating…
- Comparison bugs ( === vs == )
- Type Juggling etc.
- Also some timing attack stuff
- Things that seem to be very interesting are,
Extract
function which replaces the variable- https://www.w3schools.com/php/func_array_extract.asp
getContents
might befile_get_contents
in php to read the file- https://www.geeksforgeeks.org/php-file_get_contents-function/
- Eliminating…
- Redacting again to Bypass authentication
Input
is in our control alreadyPasscode
- We could replace this with aGET variable
declaration, but it is run through getContents which makes it a bit difficult as this should be a file on the server. ( We cannot write anything new on the server? )- Looking at the above reference for get Contents link –> file get contents also executes
http urls
.. Yay!
- Looking at the above reference for get Contents link –> file get contents also executes
- Test play code below
// # The passcode seems to be a ??? char/digit combination --> bruteforce?
// # * Strict comparison is used, so we cant use equality or comparison bugs
// # Before bruteforce ==> Lets check extract vuln --> we have to pass an array to the GET query
<?php
$passcode = "Hi\n";
echo "Welcome\n";
extract($_GET);
echo file_get_contents("auth.php");
echo $input;
if ($input) {
if ($input === file_get_contents($passcode, false, null, 0, 4)) {
echo "flag!\n";
} else {
echo "Invalid!\n";
}
}
?>
- Progressive Thoughts –> Looking at
Extract
we know that it replaces the variables. Also we know thatfile_get_contents
will execute the http url.Passcode Input:
We add the variableinput --> test
Server Passcode:
- We overwrite the passcode variable through GET with the url we host and serve a file with the same password as Input
- Serve
http @ ip --> pass.txt --> test
- The Setup and Action
- Serve
pass.txt
with contenttest
with Ngrok and SimpleHTTPServer - Make a auth request with
- Input == test
- Passcode == http://
/pass.txt
- Serve
-
Voila the flag
- Once the input == passcode we get flag
- I included this screen because this was returned and I thought I never got the flag. After sometime I knew that source code had the flag..