Please note that this is not in any way an attack on Hypem. All work done here is done with great love to Hypem. Hypem have been notified about the exploits before this release in order to patch these. This is more of an exercise for myself.
So the last couple of days I’ve been fooling around with Hypem, both looking into finding their mp3 files and some of the mechanics in that. Moreover I did a quick look for some simple exploits as well. I’ll present my findings starting with the mechanics of finding their mp3 files and hereafter I’ll get to some exploits and some cookie stealing/session hijacking when going over some of their javascript.
If you don’t know what Hypem are then you have been living under a rock. But, this is how they describe themself: “The Hype Machine keeps track of what music bloggers write about. We handpick a set of kickass music blogs and then present what they discuss for easy analysis, consumption and discovery. This way, your odds of stumbling into awesome music or awesome blogs are high.” - http://hypem.com/about. Their rank on Alexa can be found here: http://www.alexa.com/siteinfo/hypem.com
Finding Hypem mp3 files
So I first wanted to be able to download the awesome music from Hypem which is why I downloaded some plugin for FF in order to do so. But the plugin was bad, I had to go through every song and press download or use another plugin which messed up the naming of the files. Therefore I broke down the plugin in order to find out how they got the files in the first place.
Basicly the url of the mp3 files can be found in two ways (found the second one later on):
http://hypem.com/serve/play/[id]/[key]
http://hypem.com/serve/source/[id]/[key]
The /serve/play one will do a redirect to the mp3 file which then can be downloaded. The /serve/source one on the other hand will give you a bit of JSON data with the id of the track, the url to the mp3 and a bool final which allways seems to be true (what I’ve seen so far). The JSON for one of the tracks is shown below (You don’t need to try to download the file, the link is broken on purpose)
{
itemid: "gmef"
url: "http://t01a.hypem.com/sec/5e3cf3001fck75d3bb1de182b959a89b/51ed41f1/archive/614/10/1eaca15ec90abcde181efk144d146d8b.mp3"
final: true
}
Getting this far is quite easy when being in a browser (which is maybe why there are no standalone programs that I could find) which takes care of cookies etc etc. But when I was doing my own program in C# as a program on the side I ran into a couple of problems.
I started by getting the Hypem pages after remembering to add a User-Agent in the headers of the HTTP request. Otherwise I wouldn’t get any real content. Getting the ids and keys for the URLs was next on the agenda, luckily Hypem got all of that in their source in a format like this:
trackList[document.location.href].push({
type:'normal',
id:'ad5sf',
postid:'1539980',
posturl:'http://www.themusicninja.com/folk-st-vincent-surgeon/',
time:'265',
ts: '1311368622',
fav:'0',
key: '63f38d627b20d16aad38c67cbe1ed2b6',
imeem_id:'',
artist:'St. Vincent',
song:'Surgeon',
amazon:'',
itunes:'',
emusic:'',
exact_track_avail:'0'
});
So I created a function which took the input in form of a Hypem HTML source and returned a list of Track objects which all had been extracted from the source. The extraction was quite simple; select all <script> tags where trackList[document.location.href].push({ was to find in the tags innerText. Then parsing the innerText of the selected tags using a couple of RegEx’s to extract the values. Fx. extracting the key could be done using this RegEx (returning the hex value of into the group keyValue):
\skey\:\s?\'(?<keyValue>([a-fA-F0-9])*)\'\,
From there I just needed to download the files, right? Almost, since the keys are uniqe to the AUTH cookie I first had to pretend being a browser by getting a AUTH cookie on my first request to Hypem (Header Set-Cokokie was recieved from the HTTP response) and then using it in the future requests including getting the download URLs. Here you can see the Set-Cookie header recieved, we’ll come back to that later on:
Set-Cookie: AUTH=03%3Adaae3967194bfaa0232a8b0e0aa0a331%3A1311612064%3A1047226477%3A07-DK; expires=Wed, 21-Jul-2027 16:41:04 GMT; path=/; domain=hypem.com
Otherwise I would get URLs that I could’t download. This is properly made in order prevent users from sharing the /serve/* URLs or some other reason that I havn’t found yet. When getting the download URLs I used the /serve/play option then following the HTTP 302, redirecting me to the right download URL.
So if you want to create your own fun little program for surfing Hypem remember to
- Set your User-Agent header
- Reuse your AUTH cookie
Another fun little thing with Hypem’s HTTP headers is the header X-Hacker:
X-hacker: Hey, if you're reading this, you should drop us an email at hypem.com/contact, maybe we can work together!
Exploits and other fun investigation
While I was at it I did a quick look for things like SQLi and XSS’s. I didn’t find any SQLi’s (so far), but I did found a couple of XSS’s:
http://hypem.com/soundcloud-embed.php?set=planningtorock/sets/w-hype-machine-exclusive/s-8ev0R';alert(document.cookie);var x='
http://hypem.com/search/"><script>alert(document.cookie)</script><div class="/1/


Well these I think speak for themselves. Easy to do a lot of fun with and with some of Hypem’s custom JS functions it’s even easier if you want to automate the process. Hypem godt a HUGE (~2600 lines beautified) JS file with their own functions, helpers etc. If you want to have a look for yourself it’s here (minified): http://static-ak.hypem.net/rev_1311597164/js/hype_functions_min.js. These are some of the most fun I think:
- get_cookie(name)
- set_cookie(name, value, expires, path, domain, secure)
You can of misuse these two functions in an XSS, using get_cookie(‘AUTH’) (or just document.cookie) and send it to your own server for later use. Then XSS yourself and using the set_cookie(…) function to easily set the AUTH cookie. The path, domain etc. you could find in the Set-Cookie header gotten earlier. Mind that the expires variable indicates how many days from the current time the cookie should be set, you can really set it to whatever. An example use of set_cookie(…):
set_cookie('AUTH', '03:32ceca302374836fd91f11eb76e0bad9:1311506102:1047226477:07-DK', 10, 'hypem.com', '/', false);
Fixing the XSS’s is rather trivial, escape the strings properly in taking into account where the strings are being echoed and then that’s that. No more XSS and no more session hijacking.
I full list of functions you have here:
function set_ad_vars()
function dfp_extras_var_passthru()
function dfp_extras_passback(country)
function refresh_user_menu()
function page_url_state_init()
function load_url(url, action_src)
function check_hash_change()
function rewrite_links()
function get_cookie(name)
function set_cookie(name, value, expires, path, domain, secure)
function get_visitorid_from_cookie()
function hide_notice(cookie_key)
function set_site_queue(queueItems)
function get_site_queue()
function getQueryVariable(variable)
function load_search()
function urlencode_kinda(str)
function load_random_search(forced)
function load_random_track()
function trim(str)
function get_unix_time()
function sec_to_str(nSec)
function toggleLayer(whichLayer)
function getOffX(o)
function sm_onload()
function sm_onplay()
function sm_onresume()
function sm_onpause()
function sm_onfinish()
function sm_whileplaying()
function sm_whileloading()
function sm_start_drag(evt)
function sm_follow_volume_drag(evt)
function sm_follow_progress_drag(evt)
function sm_end_drag(evt)
function sm_update_volume(evt, t_elt, morph)
function sm_update_progress(evt, t_elt)
function sm_toggle_mute()
function loadNextTrack(skip)
function retryLoadTrack()
function beginFadeTransition()
function fadeInSound(soundObj, amount, ms_delay)
function fadeOutSound(soundObj, amount, ms_delay)
function is_fade_enabled()
function is_html5_history_compat()
function update_current_play_ctrl(mode)
function togglePlayByItemid(itemid, evt)
function is_spy_page()
function is_shuffle_page()
function togglePlaySimple()
function togglePlay(id, evt)
function stopTrack()
function playTrack(skip_prompts)
function nextTrack(clicked_obj)
function prevTrack(clicked_obj)
function set_track_bg(fileid, color)
function set_now_playing_info()
function toggle_favorite(type, id, gray, skip_prompt)
function show_all_tracks(elt)
function show_buy(pos)
function expand_hyped(list_parent)
function enable_notification_check()
function check_notification()
function disable_notification_check()
function enable_playback_check()
function playback_check()
function disable_playback_check()
function toggle_item_activity(type, fileid, page)
function update_item_activity(type, fileid, page)
function load_item_activity(type, id, pos, page)
function toggle_item_graph(id, force, pos)
function load_item_graph(id)
function show_sidebar_info(uid, method, section)
function set_nav_item_active(eltid)
function setup_player_bar()
function hide_player_bar()
function show_player_bar()
function blog_search()
function blog_search_keyup()
function blog_directory_switch(tab)
function radio_update()
function load_gs_player(pos, gs_id)
function next_review(pos)
function prev_review(pos)
function show_review(pos)
function updateUrl(value)
function checkEmail()
function create_account(type, id, form_type)
function user_login(type, id)
function post_login(type, id)
function post_username_change()
function cancel_iframe_dialog(redir_to)
function checkPw()
function change_password(old_pw, newpw, key)
function change_username(pw, new_username)
function change_email(pw, email)
function user_logout()
function user_forgot()
function display_twitter_score()
function save_location()
function UploadToS3()
function lightbox_close_handler(lightbox_url)
function contact_show_tips()
function save_account()
function request_confirmation()
function unlink_twitter()
function save_twitter()
function unlink_lastfm()
function save_lastfm()
function show_lightbox(type, url, arg1)
Also there is the wonderful function debug(q, w, e, r) defined like this:
window.debug = function(q, w, e, r) {
if (!document.location.href.match(/dev.hypem.com/)) {
return false;
}
try {
if (typeof console != 'undefined') {
console.log.apply(console, arguments);
}
} catch(err) {
if (typeof console != 'undefined') {
console.log(q, w, e, r);
}
}
};
This function is great, if you are a dev or someone interested in get a deeper look at the inside of Hypem. Unfortunately I’m not a Hypem dev (hint, hint) and the dev.hypem.com requires username/password, so I’ll just redefine the function with this:
function debug(q,w,e,r){
if (do_debug==false) {
return true;
}
try{
if(typeof console!='undefined'){
console.log.apply(console,arguments);
}
} catch(err){
if(typeof console!='undefined'){
console.log(q,w,e,r);
}
}
}
I introduced the variable do_debug, a bool enabling the debug in the console. You should really take a look at the debug messages, a lot of fun stuff to see actually.
Needless to say there are a lot of fun XHR requests going on at all times on Hypem which you’ll find out when debugging the site and looking at the XHR requests. Logging action, radio fun etc. etc. etc. All of this is kind of expected with a site like Hypem where almost all of the stuff is happening via AJAX in order to keep the music playing.
The site also got a bit of fun variables when being logged in and logged out. Without going into depth with all of them here’s the list:
var trackList = {};
var activeList = document.location.href;
var currentTrack = 0;
var currentPlayerObj = Array();
var activeItem;
var currentUrl;
var prevUrl;
var is_logged_in;
var logged_in_username;
var playback_allowed;
var dragging_position = false;
var dragging_x;
var isReady = 0;
var playerStatus = "";
var playerDisplayed = "normal";
var playback_event_timeout = 0;
var playback_event_count = 0;
var playback_manual = 0;
var player_position;
var player_duration;
var player_volume = 50;
var page_updater;
var notificationTimeout = 0;
var updateSpy = 1;
var album_rs = Array();
var album_r_curr = Array();
var autosearch_blogs;
var radio_timeout = 0;
var radio_now_fileid = 0;
var radio_now_data = {};
var radio_counter = 0;
var radio_notificationTimeout = 0;
var master_ord;
var master_passback;
var ad_feedback_code;
var ad_feedback_position;
I think all of the variable names makes so much sense that I don’t want to explain what each of them do, you’ll have to have fun with that yourself.
Domains, servers etc. etc.
Here’s just a little bit of info from a quick look at the server, domains and subdomains at Hypem. Not that interesting but there you have it.
Hypem.com is hosted at 205.251.139.43 (US) together with 2 other domains: buymusic.org and hypem.mobi. Properly a VPS for their main stuff I guess. 5 DNS servers from dnsmadeeasy.com used, some load balancing there also. (http://www.robtex.com/dns/hypem.com.html, http://toolbar.netcraft.com/site_report?url=http://hypem.com)
The subdomain dev.hypem.com is hosted at 205.251.142.11 (US). No sharing on that server, properly just an isolated test server for lulz. (http://www.robtex.com/dns/dev.hypem.com.html).
Subdomain blog.hypem.com is over at 69.163.207.2 (US). Sharing the IP with a couple of weird domains besides from thehypemachine.net.
Hypem uses a S3 bucket for their users profile pictures, that’s here: http://faces-s3.hypem.com/.
Furthermore they got (maybe) 8 servers for hosting their mp3 files at http://t01a.hypem.com/ –> http://t08a.hypem.com/. There are other hosting servers also I’m sure, maybe some soundcloud thingy.
I think that’s it for now, I’m going to beeed.