Category Archives: 해킹보안

대표적인 미국의 SNS : 페이스북(facebook) 소스코드 유출!

사용자 삽입 이미지미국의 SNS 시장을 이끌고 있는 서비스로는 Myspace가 있습니다. 그 뒤로 Facebook이 있지요.

Facebook은 대학교의 인맥형성을 주제로 생겨났다가 가입자체를 공개하면서 엄청난 성장세를 보여왔습니다.

위키피디아 의 자료를 보시면 알수 있겠지만 현재 Facebook의 가입자수는 3500만명에 달합니다.

Facebook의 경우 가입자수는 한달이내로 로그인한적이 있는 Active 유저만을 계산한다고 하는군요.

위에 싸이월드도 있군요. 1500만명입니다.

저도 Facebook을 사용하고 있습니다만 친구들의 세세한 업데이트 현황까지 보여주며 또한 네트워크라는것을 통해 인맥을 형성하는데 강력한 기능을 제공한다는 점이 대단하다고 생각되어집니다.

또한 저같은 개발자들이 눈에 띄게 보게 되는것이 강력한 위젯 개발 기능을 제공하는데요.

이런 대형 서비스에서 서비스의 핵심코드까지 접근할 수 있는 강력한 기능을 일반 개발자들에게 준다는것이 저로서는 조금 이해하기 힘든 부분입니다만, 개발자의 입장에서는 정말 멋진 서비스임에 틀림이 없습니다.

다만 문제가, 사용자가 원하는 쿼리문까지 작성하여 디비에 직접 엑세스 할수 있고, 모든 자원에 접근 할수 있다는점이 문제가 아닐까 생각되는데요.

Developers에 등록을 하고, API Key를 받아야만 개발을 할수가 있습니다. 하지만 악의적인 마음을 품고 있는 사람에게 그것도 무용지물인 제제안이 될것입니다.

아니나 다를까, 해킹을 당했다고 합니다. TechCrunch에는 Facebook Source Code Leaked 라는 제목의 글이 올라왔습니다.

공식 확인된것은 아니지만 유출된 코드가 Facebook의 코드가 맞는듯 합니다.

코드를 유출한 사람은 blogspot에 facebooksecrets라는 계정을 만들고 index.php 소스내용을 올려둔 상태입니다.

과연 어떤 경로로 소스가 유출되었을까요? 솔직히 위젯 개발에서 PHP의 왠만한 함수를 접근할수 있다면 얼마든지 소스를 유출할수 있다고 생각되어집니다만, 확인해볼만큼 간이 크진 않습니다^^

확실히 생각해 볼수록 PHP로 제작된 서비스에서는 사용자가 PHP코드에 접근할수 있어서는 안되는 것이 맞다고 생각되어집니다.

[#M_ more.. | less.. |Index.php

[code type=php]include_once $_SERVER[‘PHP_ROOT’].’/html/init.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/home.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/requests.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/feed/newsfeed.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/poke.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/share.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/orientation.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/feed/newsfeed.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/mobile/register.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/forms_lib.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/contact_importer/contact_importer.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/feed/util.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/hiding_prefs.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/abtesting.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/friends.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/statusupdates.php’;

// lib/display/feed.php has to be declared here for scope issues.
// This keeps display/feed.php cleaner and easier to understand.
include_once $_SERVER[‘PHP_ROOT’].’/lib/display/feed.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/monetization_box.php’;

// require login
$user = require_login();
print_time(‘require_login’);
param_request(array( ‘react’ => $PARAM_EXISTS));

// Check and fix broken emails
// LN – disabling due to excessive can_see dirties and sets when enabled.
//check_and_fix_broken_emails($user);

// migrate AIM screenname from profile to screenname table if needed
migrate_screenname ($user);

// homepage announcement variables
$HIDE_ANNOUNCEMENT_BIT = get_site_variable(‘HIDE_ANNOUNCEMENT_BIT’);
$HIDE_INTRO_BITMASK = get_site_variable(‘HIDE_INTRO_BITMASK’);

// redirects
if (is_sponsor_user()) {
redirect(‘bizhome.php’, ‘www’);
}

include_once $_SERVER[‘PHP_ROOT’].’/lib/mesg.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/invitetool.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/grammar.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/securityq.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/events.php’;
include_once $_SERVER[‘PHP_ROOT’].’/lib/rooster/stories.php’;

// todo: password confirmation redirects here (from html/reset.php),
// do we want a confirmation message?

param_get_slashed(array(
‘feeduser’ => $PARAM_INT, //debug: gets feed for user here
‘err’ => $PARAM_STRING, // returning from a failed entry on an orientation form
‘error’ => $PARAM_STRING, // an error can also be here because the profile photo upload code is crazy
‘ret’ => $PARAM_INT,
‘success’ => $PARAM_INT, // successful profile picture upload
‘jn’ => $PARAM_INT, // joined a network for orientation
‘np’ => $PARAM_INT, // network pending (for work/address network)
‘me’ => $PARAM_STRING, // mobile error
‘mr’ => $PARAM_EXISTS, // force mobile reg view
‘mobile’ => $PARAM_EXISTS, // mobile confirmation code sent
‘jif’ => $PARAM_EXISTS, // just imported friends
‘ied’ => $PARAM_STRING, // import email domain
‘o’ => $PARAM_EXISTS, // first time orientation, passed on confirm
‘verified’ => $PARAM_EXISTS)); // verified mobile phone

param_post(array(
‘leave_orientation’ => $PARAM_EXISTS,
‘show_orientation’ => $PARAM_INT, // show an orientation step
‘hide_orientation’ => $PARAM_INT)); // skip an orientation step

// homepage actions
if ($req_react && validate_expiring_hash($req_react, $GLOBALS[‘url_md5key’])) {
$show_reactivated_message = true;
} else {
$show_reactivated_message = false;
}
tpl_set(‘show_reactivated_message’, $show_reactivated_message);

// upcoming events
events_check_future_events($user); // make sure big tunas haven’t moved around
$upcoming_events = events_get_imminent_for_user($user);

// this is all stuff that can be fetched together!
$upcoming_events_short = array();
obj_multiget_short(array_keys($upcoming_events), true, $upcoming_events_short);
$new_pokes = 0;
//only get the next N pokes for display
//where N is set in the dbget to avoid caching issues
$poke_stats = get_num_pokes($user);
get_next_pokes($user, true, $new_pokes);
$poke_count = $poke_stats[‘unseen’];

$targeted_data = array();
home_get_cache_targeted_data($user, true, $targeted_data);
$announcement_data = array();
home_get_cache_announcement_data($user, true, $announcement_data);
$orientation = 0;
orientation_get_status($user, true, $orientation);
$short_profile = array();
profile_get_short($user, true, $short_profile);
// pure priming stuff
privacy_get_network_settings($user, true);
$presence = array();
mobile_get_presence_data($user, true, $presence);
feedback_get_event_weights($user, true);
// Determine if we want to display the feed intro message
$intro_settings = 0;
user_get_hide_intro_bitmask($user, true, $intro_settings);
$user_friend_finder = true;
contact_importer_get_used_friend_finder($user, true, $used_friend_finder);
$all_requests = requests_get_cache_data($user);
// FIXME?: is it sub-optimal to call this both in requests_get_cache_data and here?
$friends_status = statusupdates_get_recent($user, null, 3);
memcache_dispatch(); // populate cache data

// Merman’s Admin profile always links to the Merman’s home
if (user_has_obj_attached($user)) {
redirect(‘mhome.php’, ‘www’);
}

if (is_array($upcoming_events)) {
foreach ($upcoming_events as $event_id => $data) {
$upcoming_events[$event_id][‘name’] = txt_set($upcoming_events_short[$event_id][‘name’]);
}
}

tpl_set(‘upcoming_events’ , $upcoming_events);

// disabled account actions
$disabled_warning = ((IS_DEV_SITE || IS_QA_SITE) && is_disabled_user($user));
tpl_set(‘disabled_warning’, $disabled_warning);

// new pokes (no more messages here, they are in the top nav!)
if (!user_is_guest($user)) {
tpl_set(‘poke_count’ , $poke_count);
tpl_set(‘pokes’ , $new_pokes);
}

// get announcement computations
tpl_set(‘targeted_data’ , $targeted_data);
tpl_set(‘announcement_data’ , $announcement_data);

// birthday notifications
tpl_set(‘birthdays’ , $birthdays = user_get_birthday_notifications($user, $short_profile));
tpl_set(‘show_birthdays’ , $show_birthdays = (count($birthdays) || !$orientation));

// user info
tpl_set(‘first_name’ , user_get_first_name(txt_set($short_profile[‘id’])));
tpl_set(‘user’ , $user);

// decide if there are now any requests to show
$show_requests = false;
foreach ($all_requests as $request_category) {
if ($request_category) {
$show_requests = true;
break;
}
}
tpl_set(‘all_requests’, $show_requests ? $all_requests : null);

$permissions = privacy_get_reduced_network_permissions($user, $user);

// status
$user_info = array(‘user’ => $user,
‘firstname’ => user_get_first_name($user),
‘see_all’ => ‘/statusupdates/?ref=hp’,
‘profile_pic’ => make_profile_image_src_direct($user, ‘thumb’),
‘square_pic’ => make_profile_image_src_direct($user, ‘square’));

if (!empty($presence) && $presence[‘status_time’] > (time() – 60*60*24*7)) {
$status = array(‘message’ => txt_set($presence[‘status’]),
‘time’ => $presence[‘status_time’],
‘source’ => $presence[‘status_source’]);
} else {
$status = array(‘message’ => null, ‘time’ => null, ‘source’ => null);
}
tpl_set(‘user_info’, $user_info);

tpl_set(‘show_status’, $show_status = !$orientation);
tpl_set(‘status’, $status);
tpl_set(‘status_custom’, $status_custom = mobile_get_status_custom($user));
tpl_set(‘friends_status’, $friends_status);

// orientation
if ($orientation) {
if ($post_leave_orientation) {
orientation_update_status($user, $orientation, 2);
notification_notify_exit_orientation($user);
dirty_user($user);
redirect(‘home.php’);
} else if (orientation_eligible_exit(array(‘uid’=>$user)) == 2) {
orientation_update_status($user, $orientation, 1);
notification_notify_exit_orientation($user);
dirty_user($user);
redirect(‘home.php’);
}
}

// timezone – outside of stealth, update user’s timezone if necessary
$set_time = !user_is_alpha($user, ‘stealth’);
tpl_set(‘timezone_autoset’, $set_time );
if ($set_time) {
$daylight_savings = get_site_variable(‘DAYLIGHT_SAVINGS_ON’);
tpl_set(‘timezone’, $short_profile[‘timezone’] – ($daylight_savings ? 4 : 5) );
}

// set next step if we can
if (!$orientation) {
user_set_next_step($user, $short_profile);
}

// note: don’t make this an else with the above statement, because then no news feed stories will be fetched if they’re exiting orientation
if ($orientation) {
extract(orientation_get_const());

require_js(‘js/dynamic_dialog.js’);
require_js(‘js/suggest.js’);
require_js(‘js/typeahead_ns.js’);
require_js(‘js/suggest.js’);
require_js(‘js/editregion.js’);
require_js(‘js/orientation.js’);
require_css(‘css/typeahead.css’);
require_css(‘css/editor.css’);

if ($post_hide_orientation && $post_hide_orientation <= $ORIENTATION_MAX) {
$orientation[‘orientation_bitmask’] |= ($post_hide_orientation * $ORIENTATION_SKIPPED_MODIFIER);
orientation_update_status($user, $orientation);
} else if ($post_show_orientation && $post_show_orientation <= $ORIENTATION_MAX) {
$orientation[‘orientation_bitmask’] &= ~($post_show_orientation * $ORIENTATION_SKIPPED_MODIFIER);
orientation_update_status($user, $orientation);
}

$stories = orientation_get_stories($user, $orientation);
switch ($get_err) {
case $ORIENTATION_ERR_COLLEGE:
$temp = array(); // the affil_retval_msg needs some parameters won’t be used
$stories[$ORIENTATION_NETWORK][‘failed_college’]=affil_retval_msg($get_ret, $temp, $temp);
break;
case $ORIENTATION_ERR_CORP:
$temp = array();
// We special case the network not recognized error here, because affil_retval_msg is retarded.
$stories[$ORIENTATION_NETWORK][‘failed_corp’] = ($get_ret == 70) ? ‘The email you entered did not match any of our supported networks. ‘ .
‘Click here to see our supported list. ‘ .
‘Go here to suggest your network for the future.’
: affil_retval_msg($get_ret, $temp, $temp);
break;
}

// photo upload error
if ($get_error) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_PROFILE]][‘upload_error’] = pic_get_error_text($get_error);
}
// photo upload success
else if ($get_success == 1) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_PROFILE]][‘uploaded_pic’] = true;
// join network success
} else if ($get_jn) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_NETWORK]][‘joined’] = array(
‘id’ => $get_jn,
‘name’ => network_get_name($get_jn));
// network join pending
} else if ($get_np) {

$stories[$ORIENTATION_ORDER[$ORIENTATION_NETWORK]][‘join_pending’] = array(
‘id’ => $get_np,
’email’ => get_affil_email_conf($user, $get_np),
‘network’ => network_get_name($get_np));
// just imported friend confirmation
} else if ($get_jif) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_NETWORK]][‘just_imported_friends’] = true;
$stories[$ORIENTATION_ORDER[$ORIENTATION_NETWORK]][‘domain’] = $get_ied;
}

// Mobile web API params
if ($get_mobile) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_MOBILE]][‘sent_code’] = true;
$stories[$ORIENTATION_ORDER[$ORIENTATION_MOBILE]][‘view’] = ‘confirm’;
}
if ($get_verified) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_MOBILE]][‘verified’] = true;
}
if ($get_me) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_MOBILE]][‘error’] = $get_me;
}
if ($get_mr) {
$stories[$ORIENTATION_ORDER[$ORIENTATION_MOBILE]][‘view’] = ‘register’;
}

if (orientation_eligible_exit($orientation)) {
tpl_set(‘orientation_show_exit’, true);
}
tpl_set(‘orientation_stories’, $stories);

//if in orientation, we hide all feed intros (all 1’s in bitmask)
$intro_settings = -1;

}
tpl_set(‘orientation’, $orientation);

// Rooster Stories
if (!$orientation &&
((get_site_variable(‘ROOSTER_ENABLED’) == 2) ||
(get_site_variable(‘ROOSTER_DEV_ENABLED’) == 2))) {
$rooster_story_count = get_site_variable(‘ROOSTER_STORY_COUNT’);
if (!isset($rooster_story_count)) {
// Set default if something is wrong with the sitevar
$rooster_story_count = 2;
}
$rooster_stories = rooster_get_stories($user, $rooster_story_count, $log_omissions = true);
if (!empty($rooster_stories) && !empty($rooster_stories[‘stories’])) {
// Do page-view level logging here
foreach($rooster_stories[‘stories’] as $story) {
rooster_log_action($user, $story, ROOSTER_LOG_ACTION_VIEW);
}
tpl_set(‘rooster_stories’, $rooster_stories);
}
}

// set the variables for the home announcement code
$hide_announcement_tpl = ($intro_settings | $HIDE_INTRO_BITMASK) & $HIDE_ANNOUNCEMENT_BIT;
// if on qa/dev site, special rules
$HIDE_INTRO_ON_DEV = get_site_variable(‘HIDE_INTRO_ON_DEV’);
if ((IS_QA_SITE || IS_DEV_SITE) && !$HIDE_INTRO_ON_DEV) {
$hide_announcement_tpl = 0;
}

tpl_set(‘hide_announcement’, $hide_announcement_tpl);
if($is_candidate = is_candidate_user($user)) {
tpl_set(‘hide_announcement’, false);
}
$home_announcement_tpl = !$hide_announcement_tpl || $is_candidate ? home_get_announcement_info($user) : 0;
tpl_set(‘home_announcement’, $home_announcement_tpl);
tpl_set(‘hide_announcement_bit’, $HIDE_ANNOUNCEMENT_BIT);

$show_friend_finder = !$orientation && contact_importer_enabled($user) && !user_get_hiding_pref($user, ‘home_friend_finder’);
tpl_set(‘show_friend_finder’, $show_friend_finder);
if ($show_friend_finder && (user_get_friend_count($user) > 20)) {
tpl_set(‘friend_finder_hide_options’, array(‘text’=>’close’,
‘onclick’=>”return clearFriendFinder()”));
} else {
tpl_set(‘friend_finder_hide_options’, null);
}

$account_info = user_get_account_info($user);
$account_create_time = $account_info[‘time’];

tpl_set(‘show_friend_finder_top’,
!$used_friend_finder);

tpl_set(‘user’, $user);

// MONETIZATION BOX
$minimize_monetization_box = user_get_hiding_pref($user, ‘home_monetization’);
$show_monetization_box = (!$orientation &&
get_site_variable(‘HOMEPAGE_MONETIZATION_BOX’));
tpl_set(‘show_monetization_box’, $show_monetization_box);
tpl_set(‘minimize_monetization_box’, $minimize_monetization_box);

if ($show_monetization_box) {
$monetization_box_data = monetization_box_user_get_data($user);
txt_set(‘monetization_box_data’, $monetization_box_data);
}

// ORIENTATION
if ($orientation) {
$network_ids = id_get_networks($user);
$network_names = multiget_network_name($network_ids);
$in_corp_network = in_array($GLOBALS[‘TYPE_CORP’], array_map(‘extract_network_type’, $network_ids));
$show_corp_search = $in_corp_network ||
get_age(user_get_basic_info_attr($user, ‘birthday’)) >= 21;
$pending_hs = is_hs_pending_user($user);
$hs_id = null;
$hs_name = null;
if ($pending_hs) {
foreach (id_get_pending_networks($user) as $network) {
if (extract_network_type($network[‘network_key’]) == $GLOBALS[‘TYPE_HS’]) {
$hs_id = $network[‘network_key’];
$hs_name = network_get_name($hs_id);
break;
}
}
}
//$orientation_people = orientation_get_friend_and_inviter_ids($user);
$orientation_people = array(‘friends’ => user_get_all_friends($user),
‘pending’ => array_keys(user_get_friend_requests($user)),
‘inviters’=> array(), // wc: don’t show inviters for now
);
$orientation_info = array_merge($orientation_people,
array(‘network_names’ => $network_names,
‘show_corp_search’ => $show_corp_search,
‘pending_hs’ => array(‘hs_id’=>$hs_id,
‘hs_name’=>$hs_name),
‘user’ => $user,
));
tpl_set(‘orientation_info’, $orientation_info);

tpl_set(‘simple_orientation_first_login’, $get_o); // unused right now
}

// Roughly determine page length for ads
// first, try page length using right-hand panel
$ads_page_length_data = 3 + // 3 for profile pic + next step
($show_friend_finder ? 1 : 0) +
($show_status ? ($status_custom ? count($friends_status) : 0) : 0) +
($show_monetization_box ? 1 : 0) +
($show_birthdays ? count($birthdays) : 0) +
count($new_pokes);

// page length using feed stories
if ($orientation) {
$ads_page_length_data = max($ads_page_length_data, count($stories) * 5);
}
tpl_set(‘ads_page_length_data’, $ads_page_length_data);

$feed_stories = null;
if (!$orientation) { // if they’re not in orientation they get other cool stuff
// ad_insert: the ad type to try to insert for the user
// (0 if we don’t want to try an insert)
$ad_insert = get_site_variable(‘FEED_ADS_ENABLE_INSERTS’);

$feed_off = false;

if (check_super($user) && $get_feeduser){
$feed_stories = user_get_displayable_stories($get_feeduser, 0, null, $ad_insert);
} else if (can_see($user, $user, ‘feed’)) {
$feed_stories = user_get_displayable_stories($user, 0, null, $ad_insert);
} else {
$feed_off = true;
}

// Friend’s Feed Selector – Requires dev.php constant
if (is_friendfeed_user($user)) {
$friendfeed = array();
$friendfeed[‘feeduser’] = $get_feeduser;
$friendfeed[‘feeduser_name’] = user_get_name($get_feeduser);
$friendfeed[‘friends’] = user_get_all_friends($user);
tpl_set(‘friendfeed’, $friendfeed);
}

$feed_stories = feed_adjust_timezone($user, $feed_stories);

tpl_set(‘feed_off’, $feed_off ? redirect(‘privacy.php?view=feeds’, null, false) : false);
}
tpl_set(‘feed_stories’, $feed_stories);

render_template($_SERVER[‘PHP_ROOT’].’/html/home.phpt’);[/code]
_M#]

웹개발자를 벌벌 떨게 만든다 – Paros Proxy

사용자 삽입 이미지수많은 사람들이 내 블로그에 접속하는 검색 키워드로 paros를 사용한다는것을 뒤늦게 알았다.

아마도 mod_security의 옵션중에 하나인 paros 차단 옵션이 검색되어진 모양이다.

검색하고 오신 분들이 크게 실망을 하였을것 같아 그분들의 기대에 부흥하는 글을 써볼까 한다.

우선 paros는 무엇일까?

Paros는 웹프록시 프로그램이다. Request를 받을 서버와 Client의 중간에 위치하며 모든 Request와 Response를 기록한다.

모든 페이지가 트리 형태로 분류되어 사이트 구조를 쉽게 파악할수 있으며 스캐너를 이용하여 웹의 취약성 스캔을 할수 있다.

또한, 옵션으로 다양한 인코딩 형식에 대하여 Hash 또는 Encoding/Decoding을 지원한다.

설치를 하여보자. 자세한 이야기는 적지 않겠다.

http://www.parosproxy.org/

에 방문하여 Download에서 Win32버젼을 다운받아 설치하자. Paros는 Java로 제작되어 JDK가 설치되어있어야 실행가능하다.

없다면 http://java.sun.com 에서 다운받아 설치하자.

Paros는 8080포트를 Listen한다. 혹시라도 같은 포트를 사용하고 있는 서비스가 있는지 확인해 보자. 예) 톰캣

그리고 웹브라우저의 프록시 서버에 파로스가 실행중인 서버의 정보를 적는다. 자신의 PC에서 돌릴경우 다음과 같이 적으면 된다.

사용자 삽입 이미지
그리고 Paros를 실행하여 보자.

사용자 삽입 이미지
위와같이 볼것없는 녀석이 보인다. 이것으로 무엇을 할수 있다는 말인가?

이제 프록시 설정을 한 브라우저를 사용하여 웹서핑을 하여보자. 로그인도 해보자.

사용자 삽입 이미지
한국 인터넷 시장을 76% 점유하고 계신다는 네이버에 로그인하여 보았습니다.
위와같이 Request와 Response가 모두 정확히 보여집니다. 이 작업을 하기위해 로딩된 모든 페이지에 대한 정보도 표시됩니다.
사이트 구조를 파악하거나, 어떤 쿼리와 어떤 작동을 하는지 파악하는데 도움이 되는 자료들일것입니다.

오늘은 Tools 메뉴에 있는 것들에 대해 간단한 소개만 할까 한다.

1. Filter : 브라우저 정보를 변조하거나, 특정 매칭되는 정보가 전송될시에 값을 바꾸어 보낸다거나 할수 있다.

2. Encode/Hash : 웹에서 사용되는 많은 Encoding들과 Hash값들을 Encode/Decode해볼수 있다. 와우해커웹게임같은데서 요긴하게 사용가능하다;

3. Manual Request Editor : 이게 정말 무서운 녀석이다. 내마음대로 Request를 만들어서 전송할수 있다. 물론 하시는분들은 간단히 C코드를 작성하여 변조된 Request를 날리시겠지만, 이것은 프로그래밍적인 사전지식이 없이도 그것을 가능하게 만든다. 어찌보면 별것 아닌 부분일지 모르겠으나, 잘 생각해 보면 정말 무서운 기능이다. 쿠키와 POST/GET의 값을 변조할수도 있다. 쿠키에 무작정 값을 담아두는 개발자들에게 경고!?

이 3가지 이외의것들은 별로 중요한것들이 아니라 넘어가겠다.

그렇다면 이 Paros로 무엇을 할수 있으며 개발자는 무엇을 조심해야 하는것일까?

사실 제목과는 달리 너무나도 당연하고 너무나도 별것아닌 내용일수 있겠으나, 수많은 개발자들이 크게 신경쓰지 않는 부분일것이라 생각해서 적어본다.(대부분의 작은 규모의 사업체들이 크게 신경쓰지 못하는 부분일것이라 생각한다)

특정 악의적인 목적을 가진 사람이 특정 사이트에 다음과 같은 값으로 로그인을 시도하였다.

[code]ID : admin
PW : ‘ or 1 = 1 –[/code]

하지만 우리 개발자도 만만치 않았다. Javascript로 해당 폼을 체크하여 숫자나 문자이외의 값이 포함되어있을 경우 잘못된 값이 들어있다는 에러를 내뿜어 주었다.

하지만 이 악의적인 분도 포기하지 않았다.

곧바로 Paros의 Manual Request Editor 기능을 사용하여, 바로 다음페이지로 POST값을 만들어내어 전송하였다.

그리고 로그인 성공…

결론은 무엇일까? 사용자적인 측면에서 Client Side의 체크는 분명히 존재해야 할것이다.
하지만 Server Side의 값 체크를 게을리 하지 말자. 어떤식으로 곧바로 어떤값이 입력될지 않수없다.

Form값의 Validate를 충실히 해야 할것이다.

마지막으로 싸이월드의 아바타 수정시에 값을 변조하여 보냈을때 결과물이다.
여러분의 서비스를 이용자가 이렇게 이용하길 바라십니까?

사용자 삽입 이미지
참고 : http://www.unixwiz.net/techtips/sql-injection.html