หน้าเว็บ

วันอาทิตย์ที่ 7 ธันวาคม พ.ศ. 2557

SECCON CTF 2014: Choose the number (Programming) Write-up

Description:
root@ubuntu:~# nc number.quals.seccon.jp 31337
3, 0
The maximum number? 3
3, 9, -7
The maximum number? 9
2, -9, -7, 2
The minimum number? -9
0, 2, 0, 1, -4
The minimum number? -4
-4, 3, -7, -9, 9, -9
The maximum number? 9
-2, 1, 5, 8, 1, 9, -7
The maximum number? 
Timeout, bye.
root@ubuntu:~# 
Solution:



Flag: SECCON{Programming is so fun!}

SECCON CTF 2014: Get the key (Network) Write-up

Description:
nw100.pcap
Solution: 
         Download this pcap file and open this file with Wireshark, Next step I go to menu Statistics > Protocol Hierarchy, select Hypertext Transfer Protocol (right click) > Apply as Filter > Selected



          Authorization Required to /nw/100/ ? Go to Follow TCP Stream and get username and password base64 format to decode and authen in http://133.242.224.21:6809/nw100/


Base64 Decode:
root@ubuntu:~# echo c2VjY29uMjAxNDpZb3VyQmF0dGxlRmllbGQ= | base64 --decode
seccon2014:YourBattleField
root@ubuntu:~#

          It mean username seccon2014 and password YourBattleField go to authen in http://133.242.224.21:6809/nw100/



         Access to http://133.242.224.21:6809/nw100/key.html and get a flag. :)


Flag: SECCON{Basic_NW_Challenge_Done!}

SECCON CTF 2014: Get the key.txt (Forensics) Write-up

Description:
forensic100.zip
Solution: 
         Download forensic100.zip and check file type first, It return Linux rev 1.0 ext2 filesystem data, and I find some command to mount this image and I try mount command # mount -t ext2 -o ro,loop forensic100 ./mnt, Go into mnt folder and check file type of  file 1, Result is 1: gzip compressed data, was "key.txt", key.txt!, Next step uncompress it with zcat command and I found a flag.


root@ubuntu:/home# file forensic100 
forensic100: Linux rev 1.0 ext2 filesystem data, UUID=0b92a753-7ec9-4b20-8c0b-79c1fa140869
root@ubuntu:/home# mount -t ext2 -o ro,loop forensic100 ./mnt
root@ubuntu:/home# cd /mnt
root@ubuntu:/home/mnt# ls
1    114  13   145  160  176  191  206  221  237  32  48  63  79  94
10   115  130  146  161  177  192  207  222  238  33  49  64  8   95
100  116  131  147  162  178  193  208  223  239  34  5   65  80  96
101  117  132  148  163  179  194  209  224  24   35  50  66  81  97
102  118  133  149  164  18   195  21   225  240  36  51  67  82  98
103  119  134  15   165  180  196  210  226  241  37  52  68  83  99
104  12   135  150  166  181  197  211  227  242  38  53  69  84  lost+found
105  120  136  151  167  182  198  212  228  243  39  54  7   85
106  121  137  152  168  183  199  213  229  244  4   55  70  86
107  122  138  153  169  184  2    214  23   25   40  56  71  87
108  123  139  154  17   185  20   215  230  26   41  57  72  88
109  124  14   155  170  186  200  216  231  27   42  58  73  89
11   125  140  156  171  187  201  217  232  28   43  59  74  9
110  126  141  157  172  188  202  218  233  29   44  6   75  90
111  127  142  158  173  189  203  219  234  3    45  60  76  91
112  128  143  159  174  19   204  22   235  30   46  61  77  92
113  129  144  16   175  190  205  220  236  31   47  62  78  93
root@ubuntu:/home/mnt# file 1
1: gzip compressed data, was "key.txt", from Unix, last modified: Wed Oct  1 13:00:52 2014
root@ubuntu:/home/mnt# zcat 1
SECCON{@]NL7n+-s75FrET]vU=7Z}
root@ubuntu:/home/mnt# 

Flag: SECCON{@]NL7n+-s75FrET]vU=7Z}

วันอาทิตย์ที่ 23 พฤศจิกายน พ.ศ. 2557

CSCamp CTF 2014: Brownies (Web) Write-up

Description:
Hint: think of default files when using source code management systems
Solution:
          

          Open http://178.63.58.69:8083/ and try to login several time but return Username or Password is invalid. I back to read a hint and focus "source code management systems", I maybe mean Github because I ever read some article about this How I stole source code with Directory Indexing and Git, I should request to /.git and found something.


          Try to login by user: ping and password: pong, response "Welcome ping" but not have a flag :/, Next step I look into a http header and found Cookies are so interest. Cookie: type=user; flag=df911f0151f9ef021d410b4be5060972; name=ping 
          In flag value (df911f0151f9ef021d410b4be5060972) after look this, I think this is MD5 because It have a-f0-9{32} and I should decrypt it!! on MD5 Decrypter


          Result is ping, It mean flag=md5(user) right? I back to read .git file and try encrypt "john" string to md5.

MD5 Encrypt: 

root@ubuntu:/tmp# echo -n "john" | md5sum
527bd5b5d689e2c32ae974c6229ff785  -
root@ubuntu:/tmp# 

          I back to read .git again admin: john, and in cookie value have type: user I should edit this value to admin (admin: john), I use Burp Suite to intercept and modify http request. Next step request with normal cookie and click Go.

          Not have a flag, I try to edit the cookie value to Cookie: type=admin; flag=527bd5b5d689e2c32ae974c6229ff785; name=john and click Go!!


         Finally I got a flag.!!

Flag: a012c434d1ec6db911fda4884de14fdd

CSCamp CTF 2014: Elf 1 (Reversing) Write-up

Description:
None
Solution:
          Download binary file and chmod +x binary to execute this file and program will ask for password.


          Open binary file with IDA Pro, Go to Strings tab to find some interest string, I see eWFfcmFnZWw= I think this strings is Base64 encode. Go to submit this decode string but not a flag, Next step I go to find Base64 function in this binary file and I found this.


          Find next interest strings..and I try samir to base64 encode.



           And input this result c2FtaXI= to program.


          I think I got a flag ping-pong you pasamir, Go to submit again but It wrong. :(, I try ping-pong It work. LoL

Flag: ping-pong

CSCamp CTF 2014: PE 1 (Reversing) Write-up

Description:
None
Solution:
          Download and open level1.exe file in windows, It ask for the secret key.


          Next step, open level1.exe with IDA Pro and go to Strings tab. Look around to find some interest string.


          I guess aiiaj and c(eik is a flag, I go to submit aiiajc(eik, OK It work. :O

Flag: aiiajc(eik

วันอังคารที่ 18 พฤศจิกายน พ.ศ. 2557

In-Depth Analysis: MyBB 1.8.1 <= SQL Injection

          หลังจากที่เขียนบทความวิเคราะห์ช่องโหว่ SQL Injection ของ IP.Board ออกมาไม่นานนักทาง Exploit-DB ได้มีประกาศช่องโหว่ SQL Injection และ Cross-site Scripting ของเว็บบอร์ดสำเร็จรูปชื่อดังอย่าง MyBB หรือ MyBulletinBoard ที่มีผู้ใช้งานเยอะไม่แพ้ IP.Board สำหรับเวอร์ชั่นที่มีช่องโหว่ดังกล่าวคือเวอร์ชั่น 1.8.1 หรือต่ำกว่าครับ
          สำหรับช่องโหว่ระดับรุนแรงคือช่องโหว่ SQL Injection ที่เป็นแบบ Error Based มีคนเขียนโค้ดสำหรับเจาะช่องโหว่นี้เหมือนเอาโค้ดจากช่องโหว่ IP.Board มาดัดแปลงเล็กน้อยเลย สำหรับไฟล์ที่มีช่องโหว่คือไฟล์ member.php ตัวแปร question_id ที่จะเกิดขึ้นตอนสมัครสมาชิกครับ
 if($mybb->settings['securityquestion'])
 {
  $question_id = $mybb->get_input('question_id');
  $answer = $db->escape_string($mybb->get_input('answer'));

  $query = $db->query("
   SELECT q.*, s.sid
   FROM ".TABLE_PREFIX."questionsessions s
   LEFT JOIN ".TABLE_PREFIX."questions q ON (q.qid=s.qid)
   WHERE q.active='1' AND s.sid='{$question_id}'
  ");

          จากโค้ดจะเห็นว่ามีการรับค่า $_GET มาใส่ในตัวแปร question_id ผ่านฟังก์ชั่น get_input จากนั้นจึงนำเข้ามารวมกับคิวรี่ SQL ทดสอบการการโจมตีโดย SELECT COUNT(*) FROM mybb_users โดยอ้างอิงโค้ดจาก exploit


          ทำให้ Hacker สามารถใช้ Regular Expression ตัดคำที่ต้องการออกมาจาก Error ที่เห็นได้ เมื่อตามไปดูโค้ดของฟังก์ชั่นที่ครอบ input ไว้นั่นคือฟังก์ชั่น get_input ที่อยู่ในไฟล์ /inc/class_core.php ครับ
 /**
  * Checks the input data type before usage.
  *
  * @param string $name Variable name ($mybb->input)
  * @param int $type The type of the variable to get. Should be one of MyBB::INPUT_INT, MyBB::INPUT_ARRAY or MyBB::INPUT_STRING.
  *
  * @return mixed Checked data
  */
 function get_input($name, $type = MyBB::INPUT_STRING)
 {
  switch($type)
  {
   case MyBB::INPUT_ARRAY:
    if(!isset($this->input[$name]) || !is_array($this->input[$name]))
    {
     return array();
    }
    return $this->input[$name];
   case MyBB::INPUT_INT:
    if(!isset($this->input[$name]) || !is_numeric($this->input[$name]))
    {
     return 0;
    }
    return (int)$this->input[$name];
   case MyBB::INPUT_FLOAT:
    if(!isset($this->input[$name]) || !is_numeric($this->input[$name]))
    {
     return 0.0;
    }
    return (float)$this->input[$name];
   case MyBB::INPUT_BOOL:
    if(!isset($this->input[$name]) || !is_scalar($this->input[$name]))
    {
     return false;
    }
    return (bool)$this->input[$name];
   default:
    if(!isset($this->input[$name]) || !is_scalar($this->input[$name]))
    {
     return '';
    }
    return $this->input[$name];
  }
 }

          การส่งค่าได้ส่งมาเป็น String และไม่มีการกรองค่าที่รับมาทำให้เกิดช่องโหว่ SQL Injection ได้ครับ ตอนนี้แพตช์เวอร์ชั่น 1.8.2 สำหรับแก้ไขช่องโหว่ SQL Injection และ Cross-site Scripting ได้ออกมาตั้งแต่วันที่ 13 พ.ย. ที่ผ่านมา โดยแก้ช่องโหว่ SQL Injection โดยใช้ฟังก์ชั่น escape_string ครอบเข้าไป
$question_id = $db->escape_string($mybb->get_input('question_id'));

          ตามไปดูฟังก์ชั่น escape_string
 function escape_string($string)
 {
  if($this->db_encoding == 'utf8')
  {
   $string = validate_utf8_string($string, false);
  }
  elseif($this->db_encoding == 'utf8mb4')
  {
   $string = validate_utf8_string($string);
  }

  if(function_exists("mysqli_real_escape_string") && $this->read_link)
  {
   $string = mysqli_real_escape_string($this->read_link, $string);
  }
  else
  {
   $string = addslashes($string);
  }
  return $string;
 }

          มีการครอบ mysqli_real_escape_string เข้าไปแล้ว สำหรับใครที่ใช้ MyBB อยู่ก็อัพเดทกันด้วยนะครับ :)

Ref: MyBB 1.8.X <= 1.8.1 Error based SQL Injection
Ref: MyBB 1.8.X - Multiple Vulnerabilities
Ref: MyBB 1.8.2 Released – Security Release

วันจันทร์ที่ 10 พฤศจิกายน พ.ศ. 2557

In-Depth Analysis: IP.Board <= 3.4.7 SQL Injection

          เมื่อวันที่ 9 พ.ย. ที่ผ่านมาได้มีการปล่อย Exploit SQL Injection ของ IP.Board 3.4.7 ซึ่งเป็นเวอร์ชั่นล่าสุด ในเว็บไซต์ของ Full Disclosure และได้มีการ Public โค้ด Python ที่ใช้ในการโจมตีช่องโหว่ดังกล่าวด้วย จึงเป็นที่มาของบทความนี้ครับ
          IP.Board ที่ผมเอามาลองคือเวอร์ชั่น 3.4.6 ครับจากการอ่านโค้ดนั้นเขียนด้วย PHP OOP ไฟล์ที่มีปัญหาก็คือไฟล์ ipsconnect.php ที่ส่งค่าไปยัง ipsMember.php ครับ
/**
 *
 * Map - can modify to add additional parameters, but the IPS Community Suite will only send the defaults
 *
 */
$map = array(
 'login'  => array( 'idType', 'id', 'password', 'key', 'redirect', 'redirectHash' ),
 'logout' => array( 'id', 'key', 'redirect', 'redirectHash' ),
 'register' => array( 'key', 'username', 'displayname', 'password', 'email', 'revalidateurl' ),
 'cookies' => array( 'data' ),
 'check'  => array( 'key', 'id', 'username', 'displayname', 'email' ),
 'change' => array( 'id', 'key', 'username', 'displayname', 'email', 'password', 'redirect', 'redirectHash' ),
 'validate' => array( 'id', 'key' ),
 'delete' => array( 'id', 'key' )
 );

/**
 *
 * Process Logic - do not modify
 *
 */ 
$ipsConnect = new ipsConnect();
if ( isset( $_REQUEST['act'] ) and isset( $map[ $_REQUEST['act'] ] ) )
{
 $params = array();
 foreach ( $map[ $_REQUEST['act'] ] as $k )
 {
  $params[ $k ] = $_REQUEST[ $k ];
 }

 call_user_func_array( array( $ipsConnect, $_REQUEST['act'] ), $params );
}

exit;

          จากโค้ดมีการเรียกใช้คลาส ipsConnect() ที่อยู่ในไฟล์เดียวกันผ่านฟังก์ชั่น call_user_func_array โดยมีการส่งค่าจากตัวแปร $param ซึ่งรับค่า $_REQUEST ที่เก็บไว้ส่งเข้าไปด้วย
          เมื่อนำมาประกอบกันก็จะได้เป็น
call_user_func_array(array(ipsConnect,login),$param); // $param ค่าพารามิเตอร์ส่งเข้าไปในฟังก์ชั่น login

          เป็นการเรียกฟังก์ชั่น login ที่อยู่ในคลาส ipsConnect นั่นเองไล่ไปดูฟังก์ชั่น login กัน
 public function login( $identifier, $identifierValue, $md5Password, $key, $redirect, $redirectHash )
 {
  $member = NULL;
  $statusCode = 'MISSING_DATA';
  $secondsUntilUnlock = 0;
  $revalidateUrl = '';
 
  /* Check */
  if ( in_array( $identifier, array( 'id', 'email', 'username' ) ) )
  {
   $member = IPSMember::load( $identifierValue, 'none', $identifier );
   if ( $member['member_id'] )
   {

          มีการนำค่าที่ $param (idType) ที่รับมาเก็บอยู่ในตัวแปร $identifier จากนั้นเช็คว่าค่าที่ส่งเข้ามานั้นตรงกับค่าใดค่าหนึ่งใน array หรือไม่ด้วยฟังก์ชั่น in_array (idType=id) เมื่อเป็นจริงจึงส่งตัวแปร $identifier และ $identifierValue (id=-1,id[]=-1) เข้าไปในฟังก์ชั่น load ของคลาส IPSMember ในไฟล์ ipsMember.php ครับ
          ตามไปดูฟังก์ชั่น load ในคลาส IPSMember กันครับ
static public function load( $member_key, $extra_tables='all', $key_type='' )
...[snip]...
switch( $key_type )
{
 default:
 case 'id':
  if ( is_array( $member_key ) )
  {
   $multiple_ids = $member_key;
  }
  else
  {
   $member_value = intval( $member_key );
  }
  $member_field = 'member_id';
 break;

          จะเห็นว่าค่าพารามิเตอร์ที่ 3 ($key_type) ที่ส่งเข้ามาในฟังก์ชั่น load นั้นถูกส่งไปทีี่ switch case และตกที่ case id จากนั้นเช็คว่าค่า id ที่รับมานั้นเป็น array หรือไม่ด้วยฟังก์ชั่น is_array ซึ่งการโจมตีที่เกิดขึ้นทำให้เงื่อนไขนี้เป็นจริง และเก็บค่าดังกล่าวไว้ในตัวแปร $multiple_ids ตามไปดูตัวแปรนี้กันครับ
  else if( count($multiple_ids) AND is_array($multiple_ids) )
  {
   $_totalUsers = count($multiple_ids);
   $_gotFromCache = 0;
   $_fromCache  = array();
   
   foreach( $multiple_ids as $_memberValue )
   {
    $member = self::_fetchFromCache( $_memberValue, $_usedTables );
    
    if ( $member !== FALSE )
    {
     $_fromCache[ $member['member_id'] ] = $member;
     $_gotFromCache++;
    }
   }

          เงื่อนไขนี้จะเช็คตัวแปร $multiple_ids โดยฟังก์ชั่น count นับจำนวนใน array และเช็คว่าตัวแปรนี้เป็น array หรือไม่โดยฟังก์ชั่น is_array อีกแล้ว และเมื่อเป็นจริงก็ถูกจับใส่ foreach เพื่อวนเอาค่าในตัวแปร $multiple_ids ออกมาทีละตัวใส่ในตัวแปร $_memberValue และส่งตัวแปร $_memberValue เข้าไปในฟังก์ชั่น _fetchFromCache ครับ ปัญหาอยู่ตรงนี้ครับ ถ้าค่าใน $multiple_ids ไม่ใช่ array จะถูกเข้าฟังก์ชั่น intval ก่อนนำไปคิวรี่ในฟังก์ชั่น _fetchFromCache ($member_value = intval( $member_key );)
          ทดสอบการโจมตีด้วย Firefox + HackBar เมื่อค่าในตัวแปร $multiple_ids ไม่ใช่ array


          สังเกตว่าผมใส่ id=1icheernoom แต่เวลาคิวรี่จะเหลือแค่ 1 เพราะถูกฟังก์ชั่น intval ตัดออกไปเหลือแต่ตัวเลข แต่ถ้าค่าในตัวแปร $multiple_ids เป็น array


          Array ช่องที่ 0 (id[]) คือ  1icheernoom และเมื่อนำไปคิวรี่ยังเป็น 1icheernoom อยู่เพราะไม่ได้เข้าฟังก์ชั่น intval ไว้ ช่องโหว่จึงเกิดขึ้นตรงนี้ครับ


          เมื่อนำคิวรี่ที่ผมไฮท์ไลท์ไว้ไปคิวรี่ใน phpMyAdmin ก็จะได้เป็น


          ผลลัพธ์ของ COUNT(*) FROM members คือ 1 เพราะตอนทดสอบมีแค่ admin คนเดียว และเนื่องจากช่องโหว่นี้เป็น Error based และ IP.Board ได้มีการเก็บ SQL Error ไว้ในไฟล์ /cache/sql_error_latest.cgi (อ้างอิงจากในโค้ด python) ทำให้สามารถไปดึงค่าที่ Error นั้นออกมาได้ นับถือคนเจอบัคนี้เลย ชาบูๆ (=/\=)
          ถึงตอนนี้ Patch สำหรับแก้ไขช่องโหว่ IP.Board <= 3.4.7 SQL Injection ได้ออกมาแล้วครับและแก้ปัญหานี้โดย ถ้าค่าในตัวแปร  $multiple_ids เป็น array ก็ใช้ฟังก์ชั่น intval ครอบไว้ทุกค่าใน array โดยฟังก์ชั่น array_map ครับ
$multiple_ids = array_map( 'intval', $member_key );

          เป็นการส่งฟังก์ชั่น intval เข้าไปทำกับทุกค่าใน array ของตัวแปร $member_key ครับ
Ref : IP.Board version 3.4.7 (latest) suffers from a SQL injection vulnerability.
Ref : IP.Board 3.3.x, 3.4.x Security Update
Ref : 2600 Thailand

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

picoCTF 2014: Redacted (Forensics) Write-up

Solve:
You found a letter that may shed light on recent events.
Redacted.pdf:


Hint:
That "super secret access code" looks interesting. I wonder if the info behind the black boxes is really gone for good?
Solution:
          In a letter, I have pdf file and in this file have black boxes to hidden text, It is a flag. when I read a hint, I find some tool to remove black boxes and I found Nitro PDF Professional 9 trial. It work.!!

1. Open PDF File.
2. Edit > Edit



3. Click and drag to remove black boxes, It will show the flag.



Flag: one_two_three_four

picoCTF 2014: Caesar (Cryptography) Write-up

Solve:
You find an encrypted message written on the documents. Can you decrypt it? encrypted.txt
encrypted.txt:
wkhvhfuhwsdvvskudvhlvsqfrayntyqvjpoxeqbmmtlptiktbkf
Hint:
Is there a cipher named the same as the title of this problem?
Solution:
          When I read a hint, I googling to find web tools to Caesar decode online, and I found http://planetcalc.com/1434/.

Input: wkhvhfuhwsdvvskudvhlvsqfrayntyqvjpoxeqbmmtlptiktbkf and click "Calculate".



ROT0 - ROT25
ROT23: thesecretpassphraseispncoxvkqvnsgmlubnyjjqimqfhqyhc <== Interests!!

Flag: pncoxvkqvnsgmlubnyjjqimqfhqyhc

picoCTF 2014: Substitution (Cryptography) Write-up

Solve:
There's an authorization code for some Thyrin Labs information here, along with someone's favorite song. But it's been encrypted! Find the authorization code.
encrypted.txt
encrypted.txt:
kve fqkvsnojfkosd rspe ol hebnebfnep

o deten kvsquvk vaedfl elledkofc
kveane rnqpe fdp qdlbefxfhca bcfod
hqk mfahe kveate f ucommen sz bskedkofc
oz fccoep ks ma tolosd fdp hnfod

o xdsg kvfk asqn bsgenl sz nekedkosd
fne fl gek fl f gfnkvsul hfrxlope
hqk kvorx fl asq fne bfa fkkedkosd
ma gsnpl fne f mfkken sz bnope  
...[snip]...
Hint:
You may want to look at what the relative frequencies of letters in english text are.
Solution:
          When I read a hint and solve, I see a text so interest, frequencies, substitution, That's as may be means substitution cipher. I think I should find online tool to decode some messages in encrypted.txt and I found http://rumkin.com/tools/cipher/cryptogram-solver.php and select some messages (o xdsg kvfk asqn bsgenl sz nekedkosd) input and click "Solve The Cryptogram"


          When I have the results, I select some result to search in google.com and found song lyrics of "The Lion King - Be Prepared", I back to read this problem are favorite song and I think I got a flag. :)


Flag: Be Prepared

picoCTF 2014: Javascrypt (Web Exploitation) Write-up

Solve:
Tyrin Robotics Lab uses a special web site to encode their secret messages. Can you determine the value of the secret key?
Hint:
You may want to learn how to use you browser's JavaScript console.
Solution:
          Because this problem is Web Exploitation, First step I just view-source with Google Chrome (Inspect Element) to find something maybe interest, I found javascript generateKey() function.


Next step, I want to see value in key variable because It is a flag (some variables are random, I think.), I go to http://jsfiddle.net/ and paste generateKey() function in Javascript tab. Add alert(key); under key variable and click "Run".


alert(key) !!!

Flag: flag_3633 (Flag maybe random)

picoCTF 2014: Spoof Proof (Forensics) Write-up

Solve:
The police have retrieved a network trace of some suspicious activity. Most of the traffic is users viewing their own profiles on a social networking website, but one of the users on the network downloaded a file from the Thyrin Labs VPN and spoofed their IP address in order to hide their identity. Can you figure out the last name of person that accessed the Thyrin files, and the two source IP addresses they used?
[Example valid flag format: "davis,192.168.50.6,192.168.50.7"]

PCAP file available here. You can also view it on CloudShark
Hint:
The IP address was changed, but what about the MAC Address?
Solution:
          From hint, I open traffic.pcap with wireshark and focus to IP Address and MAC Address and I found 4 person and one person accessed the Thyrin files (secretfile.txt)


Next step, What MAC Address and IP Address who accessed to secretfile.txt. (MAC: 08:00:27:2b:f7:02, IP: 192.168.50.4) 


I interested in john johnson (MAC: 08:00:27:2b:f7:02, IP: 192.168.50.3)


Go to read problem again: Can you figure out the last name of person that accessed the Thyrin files, and the two source IP addresses they used?
[Example valid flag format: "davis,192.168.50.6,192.168.50.7"]

It mean johnson,192.168.50.3,192.168.50.4

Flag: johnson,192.168.50.3,192.168.50.4

วันจันทร์ที่ 16 มิถุนายน พ.ศ. 2557

In-Depth Analysis: vBulletin 4.1.x / 5.x.x Upgrade Exploit

         

          ช่องโหว่ตัวนี้คือ vBulletin 4.1.x / 5.x.x Upgrade 0day Exploit โดย Exploit นี้จะพบได้ใน Directory ที่ติดตั้ง vBulletin ใน vBulletin เวอร์ชั่น 4.1.x และ 5.x.x ครับ
$fields = array(
 'ajax' => urlencode('1'),
 'version' => urlencode('install'),
 'checktable' => urlencode('false'),
 'firstrun' => urlencode('false'),
 'step' => urlencode('7'),
 'startat' => urlencode('0'),
 'only' => urlencode('false'),
 'customerid' => urlencode($_POST['customerid']),
 'options[skiptemplatemerge]' => urlencode('0'),
 'response' => urlencode('yes'),
 'htmlsubmit' => urlencode('1'),
 'htmldata[username]' => urlencode($_POST['username']),
 'htmldata[password]' => urlencode($_POST['password']),
 'htmldata[confirmpassword]' => urlencode($_POST['password']),
 'htmldata[email]' => urlencode($_POST['email'])
);

          จาก Exploit Code ที่เป็นภาษา PHP อ่านได้ใจความว่าเป็นการ POST ค่าพารามิเตอร์ที่เป็น username/password ไปยังไฟล์ /install/upgrade.php เมื่อสันนิษฐานได้แบบนี้ก็คิดต่อได้เลยว่า ต้องมีการ Insert User ใหม่เข้าไปใน database โดยเป็นสิทธิ์ Admin แน่นอน ผมจึงตามไปจนเจอว่าอยู่ในไฟล์ /install/includes/class_upgrade_install.php ฟังก์ชั่น step_7 ครับ

/*insert query*/
$this->db->query_write("
 INSERT INTO " . TABLE_PREFIX . "user
  (username, salt, password, email, usertitle, joindate, lastvisit, lastactivity, usergroupid, passworddate, options, showvbcode)
 VALUES (
  '" . $this->db->escape_string(htmlspecialchars_uni($data['htmldata']['username'])) . "',
  '" . $this->db->escape_string($salt) . "',
  '" . $this->db->escape_string(md5(md5($data['htmldata']['password']) . $salt)) . "',
  '" . $this->db->escape_string($data['htmldata']['email']) . "',
  '" . $this->db->escape_string($this->phrase['install']['usergroup_admin_usertitle']) . "',
  " . TIMENOW . ",
  " . TIMENOW . ",
  " . TIMENOW . ",
  6,
  FROM_UNIXTIME(" . TIMENOW . "),
  $admin_useroption,
  2
 )
");

          โดยที่ htmldata[xxx] ที่ POST มานั้นมาจาก Input Form ของหน้า Upgrade เอง สังเกตได้จากตัวแปร $html จะมี input อยู่และ name="htmldata[xxx]" ยกตัวอย่าง input username

<td class="alt1">
 <div id="ctrl_username">
  <input type="text" tabindex="1" dir="ltr" size="35" value="' . htmlspecialchars_uni($data['htmldata']['username']) . '" id="it_username_1" name="htmldata[username]" class="bginput" vbrequire="1" />
 </div>
</td>

          จากฟังก์ชั่น step_7 จะสังเกตได้อย่างที่ข้างต้นกล่าวว่า เป็นการ Insert User ลงไปใน Database จากนั้นก็จับคู่เลยว่า Field ไหน Data อะไร ยกตัวอย่าง usergroupid = 6


          เลข 6 คือกลุ่ม Administrator ในระบบ vBulletin ทำให้ข้อมูลที่ยิงเข้าไปกลายเป็น Administrator และ Login เข้าเว็บด้วยสิทธิ์ Admin ได้เลย เมื่อเป็น Admin เว็บแล้วทำอะไรได้บ้าง จินตนาการต่อเองนะครับ :P
          วิธีการแก้ไขสำหรับ vBulletin เวอร์ชั่น 4.x ให้ลบโฟลเดอร์ /install เวอร์ชั่น 5.x ให้ลบโฟลเดอร์ /core/install ครับ ส่วนมาก CMS หลังลงเสร็จจะมีเตือนให้ลบอยู่แล้ว เพราะว่าเท่าที่เห็นในการ Install จะมีการเขียนไฟล์ config.php, setting.php, etc... อาจจะโดน Bypass เขียนโค้ด PHP ลงไปแทนค่า username/password ที่ต่อกับ Database ก็เป็นได้ :),, ICheer_No0M | 2600Thailand

Ref : vBulletin 4.1.x / 5.x.x Upgrade 0day Exploit
Ref : vBulletin Manual

วันจันทร์ที่ 9 มิถุนายน พ.ศ. 2557

In-Depth Analysis: Joomla JCE Extension Exploit

       

          สวัสดีครับวันนี้มีช่องโหว่ของ Extension Joomla ตัวนึง น่าสนใจดีเลยเอามาแกะดู Extension ตัวนี้คือ JCE Editor ครับเป็นส่วนเสริมที่ทำให้เราสามารถ พิมพ์ข้อความ, ใส่ลิ้งค์, แทรกรูปภาพลงไปได้พูดง่ายๆคือ เพิ่มความสะดวกในการจัดการบทความนั่นเอง
          ช่องโหว่นี้รายละเอียดคือสามารถอัพโหลดไฟล์รูปภาพ .gif, .png, .jpg ขึ้นไปบน Web Server โดยที่เนื้อหาเป็นโค้ด PHP และเปลี่ยนชื่อให้เป็นไฟล์ .php ทำให้โค้ด PHP ดังกล่าวนั้นทำงานได้จาก Exploit Code
            
$packet  = "POST ".$p."/index.php?option=com_jce&task=plugin&plugin=imgmanager&file=imgmanager&version=1576&cid=20 HTTP/1.1\r\n"; 
$packet .= "Host: ".$host."\r\n"; 
$packet .= "User-Agent: BOT/0.1 (BOT for JCE) \r\n"; 
$packet .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"; 
$packet .= "Accept-Language: en-US,en;q=0.8\r\n"; 
$packet .= "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"; 
$packet .= "Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n"; 
$packet .= "Accept-Encoding: deflate\n"; 
$packet .= "X-Request: JSON\r\n"; 
$packet .= "Cookie: __utma=216871948.2116932307.1317632284.1317639575.1317734968.3; __utmz=216871948.1317632284.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmb=216871948.20.10.1317734968; __utmc=216871948; jce_imgmanager_dir=%2F; 6bc427c8a7981f4fe1f5ac65c1246b5f=7df6350d464a1bb4205f84603b9af182\r\n"; 
$ren ="json={\"fn\":\"folderRename\",\"args\":[\"/0day.gif\",\"0day.php\"]}"; 
$packet .= "Content-Length: ".strlen($ren)."\r\n\r\n"; 
$packet .= $ren."\r\n\r\n";
          ผมจึงลองแงะช่องโหว่ดังกล่าว พบอยู่ที่ไฟล์ /jce/libraries/classes/plugin.php ครับ ชื่อฟังก์ชั่น processXHR ครับ (บางไฟล์ชื่อ process)
        
 function processXHR($array = false) {                                        
        $json     = JRequest::getVar('json', '', 'POST', 'STRING', 2);
        $method = JRequest::getVar('method', '');
                        
        if ($method == 'form' || $json) {            
            $GLOBALS['xhrErrorHandlerText'] = '';
            set_error_handler('_xhrErrorHandler');
        
            $result = null;
            $error    = null;
            
            $fn     = JRequest::getVar('action');            
            $args     = array();
                
            if ($json) {
                $json     = $this->json_decode($json);
                $fn     = $json->fn;
                $args     = $json->args;
            }
            $func = $this->request[$fn]['fn'];

            if (array_key_exists($fn, $this->request)) {
                if (!is_array($args)) {
                    $result = call_user_func($func, $args);
                } else {
                    $result = call_user_func_array($func, $args);
                }
                if (!empty($GLOBALS['xhrErrorHandlerText'])) {            
                    $error = 'PHP Error Message: ' . addslashes($GLOBALS['xhrErrorHandlerText']);
                }
            } else {
                if ($fn) {
                    $error = 'Cannot call function '. addslashes($fn) .'. Function not registered!';
                } else {
                    $error = 'No function call specified!';
                }
            }
            $output = array(
                "result"     => $result,
                "error"     => $error
            );
            if ($json) {
                header('Content-Type: text/json');
                header('Content-Encoding: UTF-8');
                header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
                header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
                header("Cache-Control: no-store, no-cache, must-revalidate");
                header("Cache-Control: post-check=0, pre-check=0", false);
                header("Pragma: no-cache");
            }
            exit($this->json_encode($output));
        }
    }
          จาก Exploit Code จะเห็นว่ามีการส่งค่า POST มาในตัวแปร json รูปแบบเป็น json และมีการรับค่าที่บรรทัดที่ 722 เก็บไว้ในตัวแปร $json จากนั้นมีการแยกค่าซึ่งเป็นชื่อฟังก์ชั่น ไว้ในตัวแปร $fn และ อากิวเมนต์ที่ส่งไว้ในตัวแปร  $args ครับ ตอนนี้จะเท่ากับว่า $fn จะมีค่าเท่ากับ folderRename (ซึ่งจะเป็นชื่อฟังก์ชั่นอื่นก็ได้แล้วแต่เป้าหมายเช่น getItems, fileCopy, fileDelete ) และ $args จะมีค่าเป็น /0day.gif และ 0day.php ( รูปแบบของ array )
          จากนั้นตัวแปร $func ในบรรทัดต่อมาจะเป็นการเก็บชื่อฟังก์ชั่นที่จะเรียกใช้ และมีการใช้เงื่อนไข  if (!is_array($args))  เช็คว่ามีตัวแปร $args เป็น array หรือไม่ ถ้าไม่เป็น array จะไปเรียก  call_user_func แต่ถ้าเป็น array จะไปเรียก call_user_func_array แทนครับ มองภาพกันออกยังเอ่ย ว่าช่องโหว่นี้จะทำอะไรต่อไป :)
          ประกอบร่างก็จะได้เป็น Exploit Code นั้นส่งค่าดังนี้ครับ ผมเขียนเป็น PHP ให้ดูเข้าใจง่ายๆ
//call_user_func_array("folderRename", array("/0day.gif", "0day.php"));
function folderRename('/0day.gif','0day.php'){ 
//do something
}
          เป็นการโยน 0day.gif และ 0day.php ไปในฟังก์ชั่น folderRename เพื่อเปลี่ยนชื่อจาก 0day.gif ไปเป็น 0day.php ครับ เรามาตามหาฟังก์ชั่น folderRename กันพบอยู่ในไฟล์ /jce/libraries/classes/manager.php ครับ

 
function folderRename( $src, $dest ){
 jimport('joomla.filesystem.folder');
 $src = Utils::makePath( $this->getBaseDir(), rawurldecode( $src ) );
 $dir = dirname( $src );
 $dest = Utils::makePath( $dir, $dest );
 if( !JFolder::move( $src, $dest ) ){
  $this->_result['error'] = JText::_('Rename Folder Error');
 }else{
  $this->_result = $this->fireEvent('onFolderRename');
 }
 return $this->returnResult(); 
}
          มีการย้ายไฟล์ที่บรรทัดที่ 701 ด้วย JFolder::move ของ Joomla ถึงตอนสุดท้ายตามไปดูก็เจอการใช้ library rename ของ FTP ที่บรรทัด 417 และฟังก์ชั่น rename ของ PHP ที่บรรทัด 424 ครับ
public static function move($src, $dest, $path = '', $use_streams=false)
 {
  // Initialise variables.
  jimport('joomla.client.helper');
  $FTPOptions = JClientHelper::getCredentials('ftp');

  if ($path)
  {
   $src = JPath::clean($path . DS . $src);
   $dest = JPath::clean($path . DS . $dest);
  }

  if (!self::exists($src)){
   return JText::_('JLIB_FILESYSTEM_ERROR_FIND_SOURCE_FOLDER');
  }
  if (self::exists($dest)) {
   return JText::_('JLIB_FILESYSTEM_ERROR_FOLDER_EXISTS');
  }
  if($use_streams)
  {
   $stream = JFactory::getStream();
   if(!$stream->move($src, $dest)) {
    return JText::sprintf('JLIB_FILESYSTEM_ERROR_FOLDER_RENAME', $stream->getError());
   }
   $ret = true;
  }
  else
  {
   if ($FTPOptions['enabled'] == 1)
   {
    // Connect the FTP client
    jimport('joomla.client.ftp');
    $ftp = JFTP::getInstance(
     $FTPOptions['host'], $FTPOptions['port'], null,
     $FTPOptions['user'], $FTPOptions['pass']
    );

    //Translate path for the FTP account
    $src = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $src), '/');
    $dest = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dest), '/');

    // Use FTP rename to simulate move
    if (!$ftp->rename($src, $dest)) {
     return JText::_('Rename failed');
    }
    $ret = true;
   }
   else
   {
    if (!@rename($src, $dest)) {
     return JText::_('Rename failed');
    }
    $ret = true;
   }
  }
  return $ret;
 }
          มาถึงตรงนี้ไฟล์ที่ Attacker เรียกเข้ามาจาก 0day.gif ก็จะถูกเปลี่ยนเป็น 0day.php แล้วครับ ส่วนวิธีการแก้ไขช่องโหว่นี้คือ อัพเดท JCE Editor ให้เป็นเวอร์ชั่นใหม่ล่าสุด ตอนนี้น่าจะเป็นเวอร์ชั่น JCE 2.3.44 แล้วครับ.. ขอบคุณที่ตามอ่านจนจบครับ :D ,, ICheer_No0M | 2600Thailand

Ref : Joomla JCE 2.0.10 Shell Upload Exploit
Ref : JCE Joomla Extension <= 2.0.10 - Multiple Vulnerabilities
Ref : rename — Renames a file or directory
Ref : joomla-platform / libraries / joomla / filesystem / folder.php

วันเสาร์ที่ 24 พฤษภาคม พ.ศ. 2557

My first web security contest (FITWHEY + HyperHackathon)


การแข่งขัน Web Security ครั้งแรกของผม LoL ตอนแรกที่ได้อ่านรายละเอียด คิดว่าจะไปแข่งเพราะคงมีแฮกเว็บแบบเต็มที่แน่นอน เปิดมาเจอเว็บให้สอยทำไงให้ได้ shell บนเครื่องก็ว่ากันไป #แต่!!

- เหมือนมีลางสังหรณ์ว่ามันไม่ใช่แค่แฮกเว็บแน่นอน เพราะตามสเตปน่าจะตบ wifi แล้วเข้าไปแฮกเว็บต่อ .. เดินออกจากหอมาสามสี่ก้าว โดยไม่ได้หยิบ wifi adapter ที่ทำ monitor mode ได้มาด้วยก็ต้องกลับเข้าไปหยิบติดตัวมา

- มาถึงโรงแรมได้โจทย์มาให้เข้าไปในวง network เขาบอกมี network 2 วงผมก็เปิด vmware backtrack 5r3 เริ่มสอยเลย TAKUMI@1 กับ TAKUMI@2 (WPA/CCMP) ใครเห็นก็ต้องคิดว่า 2 วงนี้แน่ๆ.. แต่มารู้ทีหลังว่าของร้านอาหารชั้นล่าง #หน้าแตกแป๊ป จับ packet มาแครกตั้งนาน ถถถ

- เข้าวง network ที่เขาเตรียมไว้ให้ไม่แจก ip มาก็ set ให้เครื่องเรา ip วงเดียวกันกับ network จากนั้นก็ใช้ nmap สแกนทั้ง network 0-255 (มีเขียนสคริป perl มาสแกนยก class ด้วยว่าใครเปิด 80 ไว้แต่รันช้ามาเดี๋ยวติดๆดับๆ) มาเครื่องไหนคือเหยื่อ และเปิด port ไหนน่าสนใจบ้าง ซึ่งเครื่องผมก็เป็นหนึ่งในนั้นเพราะทั้งงานมีผมและ Issaret Prachitmutita มั้งที่ใช้ windows กันนอกนั้นเป็น mac/linux ซึ่งอย่างที่รู้ windows เปิด port อะไรไว้สแกนเจอหมดเว้นแต่ firewall เหนียว เครื่องผมก็เปิดไว้เยอะเหมือนกันแต่ปิดไว้ในส่วนของของ apache service #ทำเว็บแล้วลืมปิด -..-

- เจอเครื่อง .4 นึกว่านี่เครื่องเหยื่อแน่ๆ อะไรที่ทำให้คิดว่าเป็นเครื่องเหยื่อ 1. เจอ apache 2. phpinfo ชัดเลยเครื่อง windows กูเจาะเครื่องนี้แหละว่ะ #เปิด metasploit รอ

- scan port เจอพอร์ตเปิดอยู่เยอะเพราะเครื่อง windows แต่สนใจ port นึงเลยว่าจะเล่นที่ port นั้น

- เปิดรอแล้ว set RHOST 192.168.77.4 เตรียมยิง ยิงเท่าไรก็ไม่เข้า จึงมารู้ที่หลังว่าเครื่องของน้องข้างหลังนี่เองไม่ใช่เครื่องเหยื่อแต่อย่างใด

- สุดท้ายเขียน report ว่าทำไรไปบ้าง + capture รูปไปประมาณ 4-5 รูป

- จำได้คร่าวๆ ประมาณแค่นี้ แต่ก็ได้รางวัลมา คิดไม่ผิดที่เลือกไป -0-

งานแข่งแฮกเว็บที่ไม่มีเว็บให้แฮก มีแต่ network/system lolz



ปล. VDO สรุปทั้งงาน By พี่เล็ก

วันเสาร์ที่ 1 มีนาคม พ.ศ. 2557

แนะนำเกมส์แฮกแนว Capture The Flag (ROP Wargames)

          
(เครดิตรูปจาก พี่พีท anidear)

          แนะนำเกมส์แฮกแนว Capture The Flag (CTF) [1] ครับ แนวเกมส์เป็นการแก้โจทย์ในด่านต่างๆ เพื่อให้ได้มาซึ่ง Key หรือกุญแจที่ใช้เพื่อปลดล๊อคผ่านด่าน ซึ่งแต่ละด่านก็จะมีคะแนน (Point) ตามระดับความยากง่ายของด่านนั้นๆอยู่เช่นกัน โดยจะมีหลายรูปแบบตาม Tag ที่ใช้วัดทักษะของผู้เล่นในหลายๆด้านเช่น

Misc = Miscellaneous : ความรู้ทั่วไป
Web = Web Exploitation : ความรู้เกี่ยวกับเว็บแอพพลิเคชั่น, เทคนิคการโจมตีเว็บแอพพลิเคชั่น
RE = Reversing, Reverse Engineering : การแครกโปรแกรม
Crypto = Cryptography : การเข้ารหัส, ถอดรหัส
Network = Network : เซิฟเวอร์, โปรโตคอล, วิเคราะห์ข้อมูลที่ส่งผ่านเครือข่าย
Pwn = Pwning, Pwnable : เข้ายึดเครื่องเซิฟเวอร์ที่เตรียมไว้ให้ หรือแฮกกันจริงๆ

ใครชอบแฮก เจาะระบบ แต่ไม่มีที่ให้ทดสอบฝีมือ ลองสมัครเข้ามาเล่นกันดูครับ :)


Community :
- Facebook Fanpage : ROP Wargames
- Facebook Group : Free to Pwn
- IRC : irc.2600thailand.org:6667 [แบบ non-SSL], irc.2600thailand.org:6668 [แบบ SSL]

VDO : Introduction To Game.Rop.Sh (2600Thailand)



Reference :
1. https://ctftime.org/ctf-wtf/

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

Save all slide in slideshare.net to image. [ Perl ]

use LWP::UserAgent; 
 
if(@ARGV < 2){
 print "Usage : filename.pl <slideshare_url> <folder_name>";
 exit;
}
$url = $ARGV[0];
$folder = $ARGV[1];
$browser = LWP::UserAgent->new() or die;
$content = $browser->get($url)->content;
$i = 1;
while($content =~ m/data-normal=\"(.*?)\"/g){
        $pic = $1;
        $img = $browser->get($pic)->content;
        open OUTFILE, ">> ".$folder.'/'.$i.'.jpg';
        binmode OUTFILE;
        print OUTFILE $img;
        close OUTFILE;
        print $pic." => Saved \n";
 $i++;
}

Source : https://gist.github.com/icheerno0m/8415974