AverageSecurityGuy

Security, Programming, Pentesting

About

Mastodon

Linked In

Projects

Cheat Sheets

Book

Open Question to Yankee Candle

Our local Yankee Candle store at the mall has a policy of asking for an email address and phone number with every transaction. I typically decline to provide the information and if they push I give them obviously false information. Yesterday, my family and I were shopping at Yankee Candle and while my wife and kids were roaming through the store I stood at the door watching. My 11 year old approached the counter to make a purchase. He went through the typical process, the clerk rang up the items and told him the amount, he gave her money and she provided change. Then she asked him for a phone number. At this point my son looks at me, still standing at the door, and says do I give her mama's phone number. I told him, that he is not to give any strange adult a phone number because he is a minor. (I've trained my children not to provide personal info as a general rule. They even have codenames for those stupid restaurants that demand a name with every order.)

Once I told my son he was not allowed to provide information to the clerk, she asked me for a phone number and email address saying it was REQUIRED for the receipt. I gave her an obviously fake phone number and email address and she rolled her eyes and said I could have just opted out. I'm sorry but "REQUIRED for the receipt" and "Could have just opted out" are mutually exclusive. I will keep shopping at Yankee Candle because they have the candles my wife loves but I won't ever give them valid information and I will train my children to give false information when asked by a strange adult.

My question to Yankee Candle is this, if there is an opt out option, why is it not used automatically for minors? Why are you putting 11 year olds in the position of giving complete strangers their phone numbers and email addresses?

Pentesting Redis Servers

Redis is an in-memory key/value data store used to handle backend data for many web applications. Often, Redis is used to store configuration information, session information, and user profile information. By default the Redis server does not require authentication for client access. This is not a problem if Redis is only listening on localhost but often it is not.

Finding Redis Servers

By default Redis listens on port 6379, which is not in the Nmap top 1000 port list or the /etc/services list used by Nessus. You will need to scan specifically for this service if you want to find it.

Interacting with Redis

The easiest way to interact with Redis is to use the Redis CLI client, redis-cli. On Kali2 you can install the client by installing the redis-tools package with apt-get. After installing redis-cli you can connect to the Redis server using redis-cli -h <hostname> -p <port>.

Once connected you can use the following commands to gather data from the server:

  • info - Outputs server data including version, number of databases, and the number of keys in each database.
  • select <n> - Select a database to work with. By default Redis has 16 databases available, 0 - 15. Typically, only 0 is used.
  • keys <pattern> - Display all keys matching the regex pattern. To see all keys use *.
  • type <key> - Displays the type of the value stored in the key, string, hash, set.
  • get <key> - Print the value of the string key.
  • hgetall <key> - Get all of the field/value pairs stored in the hash key.
  • hget <field> <key> - Get the value of the specified field in the hash key.

The full list of supported commands can be found here: http://redis.io/commands. This list is all of the commands supported in the latest version of Redis. Some of the commands may not work in older versions.

In addition to redis-cli, you can also access a Redis server using a number of programming languages. A full list of Redis clients by language is available here: http://redis.io/clients.

Simple Python Example

To use the example script below you will need to install the redis-py library using pip install redis. If Pip is not installed you can install it on Kali using apt-get install python-pip.

import redis
db = redis.StrictRedis(host='127.0.0.1', port=6379)

# If we have a hash key, print all of the fields and values.
for key in db.keys():
    if db.type(key) == ‘hash’:
        r = db.hgetall(key)
        print('--------')
        for k in r:
            print('Field: {0} Value: {1}'.format(k, r['k']))
        print('--------')

Update

If you come across a Redis server that is password protected, there is an NSE script that can be used to brute force the password. Once you find the password you can connect to the server using redis-cli -h <host> -p <port> -a <password>.

Update 2015/09/18

Thanks @bonsaiviking for pointing out the redis-info NSE script. So if you are hunting specifically for Redis servers you can use something like this:

nmap -p 6379 --script=redis-info 127.0.0.1 --open

Which should yield results like this:

Starting Nmap 6.49BETA4 ( https://nmap.org ) at 2015-09-18 12:02 EDT
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000062s latency).
PORT     STATE SERVICE
6379/tcp open  unknown
| redis-info: 
|   Version            2.8.17
|   Operating System   Linux 4.0.0-kali1-amd64 x86_64
|   Architecture       64 bits
|   Process ID         8020
|   Used CPU (sys)     0.04
|   Used CPU (user)    0.06
|   Connected clients  1
|   Connected slaves   0
|   Used memory        491.84K
|_  Role               master

Nmap done: 1 IP address (1 host up) scanned in 0.45 seconds

You can also scan for Redis servers using Metasploit with the auxiliary/scanner/misc/redis_server.

Beginner's Guide to Pentesting

A while back I wrote a book called "Hack Yourself First." I put the book up on LuLu and sold 29 copies. I appreciate all the folks who bought my book and I hope you found it worth the price.

Over the last few years I've made an attempt at selling software, selling consulting services, and selling this book but I've learned that I'm not a salesman. I have no desire to try to convince you that you need the services or products that I offer. It's just not in me. So, like other projects that I have created with the intention of selling, I've decided this project should open sourced.

My book is no longer for sale on LuLu, instead it is available as a Word document from this site. The book is released under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International license. Feel free to use the book as is for learning or teaching penetration testing. You can also modify the book as long as you give proper attribution, aren't making money off the sale of the book, and share your modifications under the same license.

I hope you enjoy the book, you can download it as a Word document or as a PDF.

Analysis of a Spam Link

This weekend I received a spam message that wanted to sell me tickets to a comedy show in Louisville, KY. This spam message caught my eye because it made it past Google's spam filters and I'm planning to go to Derbycon in Louisville next week. I decided to explore the link in the email a bit and see what I could find.

The original link sent in the email was this.

http://www.emergingcomics.com/special.php?j=eyJ1IjoiRDk1QUI
0RUQzODAzRjVBOTU3NDJDQzE5NEUzQzEzOTIiLCJpIjoiQU1BWk9OJTIwU0
VTIiwiciI6ImciLCJ0IjoiYUp0Zml0aEhRUHRzUXV0YXRFeHNvSkZ1eEZEb
2h5ZyIsImwiOiJodHRwJTNBJTJGJTJGJTIwZ29vLmdsJTJGQTdYT0pIIiwi
diI6IjguNjkuMC4xNjEifQ==&r=0.720967122353613

The first thing I noticed was the base64 encoded data in the "j" parameter. I decoded the data and got the following JSON object.

{"u":"D95AB4ED3803F5A95742CC194E3C1392","i":"AMAZON%20SES",
"r":"g","t":"aJtfithHQPtsQutatExsoJFuxFDohyg","l":"http%3A%
2F%2F%20goo.gl%2FA7XOJH","v":"8.69.0.161"}

Looking at the "l" key in the JSON object, I decided the special.php page was probably a redirect script so I opened the link using curl -I to get the headers.

HTTP/1.1 302 Moved Temporarily
Date: Mon, 22 Sep 2014 17:37:27 GMT
Server: Apache mod_fcgid/2.3.10-dev
X-Powered-By: PHP/5.4.31
Location: http://atmst.net/utr64.php?j=eyJ1IjoiRDk1QUI0RUQz
ODAzRjVBOTU3NDJDQzE5NEUzQzEzOTIiLCJpIjoiQU1BWk9OJTIwU0VTIiw
iciI6ImciLCJ0IjoiYUp0Zml0aEhRUHRzUXV0YXRFeHNvSkZ1eEZEb2h5Zy
IsImwiOiJodHRwJTNBJTJGJTJGJTIwZ29vLmdsJTJGQTdYT0pIIiwidiI6I
jguNjkuMC4xNjEifQ%3D%3D
Content-Type: text/html

Sure enough, the special.php page gave me a 302 response and sent me to atmst.net/utr.php. I also noticed that the base64 data in the "j" parameter was passed to this new page but was URL encoded.

I again used curl -I to get the page at atmst.net assuming it was a redirect script as well.

HTTP/1.1 302 Found
Server: nginx/1.0.4
Date: Mon, 22 Sep 2014 17:39:29 GMT
Content-Type: text/html
Connection: keep-alive
Keep-Alive: timeout=20
X-Powered-By: PHP/5.2.17
Location: http:// goo.gl/A7XOJH
Cache-Control: max-age=259200
Expires: Thu, 25 Sep 2014 17:39:29 GMT

Once again, I've been redirected, this time to the URL referenced in the "l" key in the base64 encoded JSON object.

After doing a bit of research on atmst.net I found that it is used by AtomPark Software as part of its Atomic Email Tracker software. I'm not sure what all of the keys in the JSON object represent but based on the information here, hxxp://www.massmailsoftware.com/tracker/integration.htm the "u" key is most likely the MD5 hash of the email address of the user account.

I decided to play around with the parameters a bit and see if all of the parameters were required for the redirect to be successful.

With the exception of the "l" key, I replaced all of the values in the JSON object with the letter "a." For the "l" key I changed the URL to http%3A%2F%2F%20arbitrary.test so that my JSON object now looked like this.

{"u":"a","i":"a","r":"g","t":"a","l":"http%3A%2F%2F%20arbit
rary.test","v":"a"}

I then base64 encoded the JSON object and once again used curl -I to see what would happen.

curl -I http://atmst.net/utr64.php?j=eyJ1IjoiYSIsImkiOiJhIi
wiciI6ImciLCJ0IjoiYSIsImwiOiJodHRwJTNBJTJGJTJGJTIwYXJiaXRyY
XJ5LnRlc3QiLCJ2IjoiYSJ9

HTTP/1.1 302 Found
Server: nginx/1.0.4
Date: Mon, 22 Sep 2014 17:45:49 GMT
Content-Type: text/html
Connection: keep-alive
Keep-Alive: timeout=20
X-Powered-By: PHP/5.2.17
Location: http:// arbitrary.test
Cache-Control: max-age=259200
Expires: Thu, 25 Sep 2014 17:45:49 GMT

This time I was redirected to the URL I chose but I did not have to provide a valid user id. This shows the atmst.net server is an open redirect. Further testing showed that only the "r" and "l" keys were required in the JSON object and that it was not necessary to URL encode the target URL.

So if we base64 encode the following JSON object and pass it as the "j" parameter to atmst.net/utr64.php we will be redirected to google.com

{"r":"g","l":"http://google.com"}

Further research found two other domains run by the same company that are also vulnerable to the open redirect.

atrstat.com
etrstat.com
atmst[1-5].net

Derbycon Hacknight

***Update***

We will be meeting in the main lobby of the Hyatt. The Friday night after party starts at 9:00 so I expect there will be plenty of room in the lobby. If not we can break into smaller groups and split up.

What

This is an opportunity for developers and wannabe developers to talk about projects and write some code. If you want to discuss your latest idea, need help with a current project, or want to learn how to program, this is the place for you.

When

Friday night, September 26th from 9:00PM - Until

What should I bring?

  • A laptop with a text editor and a compiler/parser for the language of your choice
  • Ideas for a project or a desire to help on an existing project.
  • Desire to write code (No one is going to write it for you.)

Where

TBD - Keep an eye on my Twitter account (@averagesecguy)

What language are you coding in?

I primarily write in Python but can help out with Ruby and PHP. Depending on who else shows up, PowerShell, Ruby, Python, PHP, and C/C++/C# should be well represented.