Wednesday, November 26, 2014

Bash Scripting: Runaway Check

Runaway Check Tutorial
TheCAT
11/26/2014

Objective: automate the process of examining all running processes on a list of linux/unix based servers and obtaining a list of processes that fall outside guidelines. These guidelines can be found on internal documentation like the DCM, but basically indicate there are cutoffs for CPU use, memory use and so on. The results should indicate which user and what process and machine are involved. At that point further consideration can be given on a case by case basis.

The goal of this lecture is to give you some legos to build things with. The legos you get here today will be most of the legos you need to build a runaway script with, but these legos can be used for other things. Cause who doesn't like legos; except unseen legos in the middle of the night with barefeet.

Minimum Command Requirements:

ssh
ps

Optional Command Requirements:

netgrouplist
ssh-keygen
ssh-agent
ssh-add
uptime
grep
echo
awk
sed
cut
>>
>

Possible Syntax:

for do done
if then else
` `
$

Tools:
vim/emacs/nano


Likely the end results of this script will be more complicated than the previous lesson's results. Again, when considering functionality examine the guidelines for runaway scripts in our in-house documentation.


Overview:

One way to tackle this is to use an ssh for-loop. Basically we set up a for-loop with every computer involved and ssh to that machine get the desired output, parse it to our satisfaction, and dump the results into a RESULTS.txt. From there as previously indicated we would examine things on a case by case basis.

Recall we will need some starting syntax at the top of our file:

#! /bin/bash

and we will ultimately need to chmod our script to be executable:

me@machine$ chmod 700 my_script.bash

That being said let's talk about keys.


Keys:

If you haven't got an ssh-key you will need one. Currently there are over 50 machines that need to be examined and you can't be entering in your password every time you run the script ... for each machine.

So, ssh to your favorite machine, I recommend  a cs compute powerhouse not an irc box or lab box. Once there,  generate an ssh-key if you don't have one.

yourname@machine$ ssh-keygen -t rsa -b 4096

and when prompted for a passphrase, give it a decent one that you can remember. Accept the default file name given.

Now let's get your key onto machines where it has to go. The thing is though your key has a passphrase associated with it, so every time you use your key you now have to answer the passphrase - so how is that different than just entering the password to the machine?

We can use an agent to bypass that. The agent will store our passphrase for us so we don't have to enter it over and over.

yourname@machine$ ssh-agent bash
yourname@machine$ ssh-add -t 3600
Enter passphrase for /u/yourname/.ssh/id_rsa:
yourname@machine$

First we started an agent with a new bash shell. Go ahead and up-arrow. All your previous commands are gone. If you type exit (don't do this now) it will appear that nothing happened, but actually it closes the agent shell.  Then we allowed the agent to have access to our key for 3,600 seconds. The clock is ticking.

So now let's transfer our public key to the machines we want to get to. We are going to do this in a for-loop on the command line to practice our syntax.

yourname@machine$ for machine in aaa bbb ccc; do ssh-copy-id yourname@$machine; done

We will still have to enter our password to ssh to those machines, but only one last time. Why did I pick those three machines? Hint: NFS mounted directories.

Since our directories are NFS mounted, did we actually have to use ssh-copy-id at all?

Now we can get around without passwords as long as we have an agent running. You need to remember the agent when running/ testing your script.


But what machines to use? This is in the DCM but we'll go over it a bit more here.

From your favorite machine:

yourname@machine$ netgrouplist -l

This gives you a listing of all our machines grouped by various categories. We are concerned with the following three: linux-login-sys, ece-secure-sys and cs-secure-sys.

yourname@machine$ netgrouplist cs-secure-sys

Because our inventory and the names of machines changes constantly, we want to make certain we use whatever is most current. As such we are either going to (A) dynamically import this list of machines from these three lists straight into our script or (B) put them all in one list and use the contents of that list in our
script. Remember the name of each machine is part of a for-loop just like it was in our command line example.

Here is how you could get a list into the script, you use backticks:

#! /bin/bash
for list in `netgrouplist -l`; do
     echo $list
done

Go ahead make this script, chmod it accordingly and run it. How would you change it to get a list of machines instead of a list of lists? How would you change it to get three lists of machines?

What if you want to put the list results in a file? There are many commands that put their results at stdout (the screen). But what if you want those results in a file?

Change the above script as follows:

#! /bin/bash
for machine in `netgrouplist cs-secure-sys`; do
     echo $machine >> RESULTS.out
done

Now run it

yourname@machine$ ./your_script.bash
yourname@machine$ ls
RESULTS.out

We could have gotten the same thing as follows:

yourname@machine$ netgrouplist cs-secure-sys >> MYRESULTS.out

The >> is called a redirection operator and it redirects stdout to a file of your choosing, specifically it appends data to that file - it doesn't over write it. If no file by that name exists, it is created.

The > operator is very similar EXCEPT that it overwrites data. Any old data in the file will be lost.


Now that we can get to machines let's get that data about those processes.

yourname@machine$ ps
yourname@machine$ ps -ef
yourname@machine$ man ps

As you can see ps is a very powerful tool. Once you have a chance to read the man pagea bit, take a look at the examples portion. You should be able to get some ideas about how to construct your ps.

I am specifically NOT going to tell you what the flags are for ps that you will want. You should read the man page and get some ideas, then experiment with the results locally, and incorporate that into your script.

Look at the requirements document (DCM) and see what matches in the man page. Once you have built your script and come up with ideas that work (on your own) I will be happy to answer any questions about how to make it better.

For now we will practice the fundamentals with ps -ef

But ps gives us some out put and we want to be able to separate that output based on results. One thing we can do to eliminate some out put is with grep.  Grep stands for Grab REgular exPressions. No, I am lying, but it should.

So we can use grep to exclude things - like maybe anything that is a daemon or root (if we want), with -v ie

yourname@machine$ ps -ef | grep -v root > test.out

In reality, if we are looking for runaway processes, do we really want to reject a process because it is being run by root? What if that process owned by root is busted or worse - shouldn't be running as a root process. I would want to know about a process consuming 100% cpu even if it is run by root.

Now we know how to get some results to play with, let's do that.


#! /bin/bash
for machine in `netgrouplist cs-secure-sys`; do
     ssh $machine ps -ef >> temp.out
done
awk '($1 !~/USER/) && ($2 > 32000)' temp.out >> RESULTS.out
rm temp.out

What did we get?

yourname@machine$ cat RESULTS.out

You now have most of the tools you need to construct a runaway script. You will need to spend more time with ps and awk (or sed) to actually get the info you need and parse it. Consider adding uptime as well.







 





Wednesday, November 19, 2014

Bash Scripting: Printer Test Script


Print Script Tutorial Lecture
TheCAT
11/19/2014

Objective: Send a printer test page to a group of networked printers. Ideally, the test page has a date and user name. Additionally it should be in color and span the depth and breadth of the page. This script can then be used in conjunction with lab checks to ensure that the printers in the labs are in good working order and so that an individual that encounters the page can understand its purpose.


Minimum Command Requirements:
man
lp or lpr
chmod

Optional Commands:
date
cat
convert
lpoptions
& many more possible


Possible Syntax:
for, do, done
if then else fi
case esac
exit
shift

Tools:
nano/vim/emacs
a .jpg or two


Side note: A print script can range from 5 lines to 150 or more. You can use any language and there are no hard and fast rules beyond the objectives – which are more of a guideline.


First let's look at what lp and lpr do.

user@machine$ man lp

user@machine$ man lpr

While I personally think that lp is a little more versatile offering a lot of options I actually used lpr for my script – no real rhyme or reason there so consider either one a viable alternative.

So you can see that you are ultimately going to have to provide some data to the command like the name of the printer and the file to print.

But what to do when there is more than one printer?

Well, we could just run the command multiple times, each time updating the name of the printer to reflect the next printer on our list of printers. In fact that is exactly what we are going to do, but we aren't going to do it by hand, we are going to put it in a script.

One method for doing something a lot of times is to put it in a for-loop. In this case each iteration of the loop corresponds to printing the same file to a new printer.

You now have the foundation for the entire script; the rest is just refining the bits of what we discussed so far. And for that we will work individually... more on this at the very end. Other questions to ask yourself



* What are the printers?

       - do these live in the script?

       - do they live in a separate file?

* What file to use?

       - do I create my own image?

       - Text or picture?

* How to get the date on it?

* How to get a name on it?

* Do I test all the printers at once?


But before we start coding (and after we finish solving the problem) let's start with something we will need at the top of any script: the magic cookie. No not that chocolate yummy thing. This is a line at the top of our file that reads as follows:


#! /bin/bash

This tells kernel to run the script in a bash shell. So when you run a command from the command line, there is a fork command that creates and entirely new shell which is an exact copy of the shell currently running. We want to make certain that when the script is run, that the new shell is also a bash shell. This falls under the execve command that follows (but we now we are way out of scope)...

Lastly let's discuss chmod. Change file mode allows us to set permissions for a file. On our systems when you create a new file the permissions default to: -rw------- meaning only we can read and write to it, but cannot execute. For a text file this isn't terrible, but since we are building a script we will want to make it executable. Additionally there is the consideration of whether we want other people to run our script. Do you want to let other cats run it? Or anyone at all? For now let's assume that we want to make it so that only we can run it. When we are done, we will want to:


chmod 700 my_script 

Now let's get to work and start thinking about how to set up what we need based on the previous bullet point questions....


For Loop Syntax

for item in apple banana cherry; do
    echo $item
done


for number in {1..9}; do
    echo $number
done

for f in `ls`; do 
    echo $f
done



Monday, November 10, 2014

Microcorruption - Montevideo


Again, they have the same strange add 0x10 to the stack pointer at the very end of the execution of login. This allows us, as before, to overflow the buffer and inject a return address that we want. If this were a software version the address we could put in there would be “unlock door” but since this is a hardware version we have to again get 0x7F into the SR and call 0x10 <_trap_interrupt> to open the lock. Pretty much the same as before, so let's try the same code.

Of course it doesn't work, and as we can see they have added strcpy into the mix which effectively copies all information up to and including the null terminator – but it stops there. So we only get one occurrence of 00 and it has to be at the end.

But other than that our methodology should be intact, we just have to adjust the code. We can still have the filler up front, then the re-deirect to our code as before, but we have to be a little more creative to work around the 00 entries in our password.

Ideas:

So we have some filler, the address to our shell code, another bit of filler and then our code:

3f40 fffe mv #xfffe, r15 ← load fffe into register 15
1f53 increment r15 ← increment to ff00
024f mv r15, sr ← move to status register
b012 1000 call 0x10 ← has to be the last thing

So putting it together we have the following parts:

41414242434344444545464647474848 filler
0244 address to our
4141 filler
3f40fffe1f53024fb0121000 injected shell code

41414242434344444545464647474848024441413f40fffe1f53024fb0121000

Wow, that's a really long password. Perhaps we can think of something shorter?

So rather than inject our shell code after the password, why not make our shell code the password itself? At the end we can redirect the program counter (instruction pointer) to the start of our shell code. Of course we will need to watch out for null terminators which means we can't call 0x10 from inside, but the provided code already does for us at address 455c. All we have to do is jump there.

So, instead of starting our code with 4141 (AA) let's start with the injected code and as the filler. We also change the jump to address (to an address within the code that does it for itself). The last portion is the address where the beginning of the password is stored. Here's an entry that works and is much shorter.

3f40fffe1f53024fb0125c45   41414141    ee43

←           shell code          → ←  filler   → ← starting address of shell code →

Tuesday, November 4, 2014

Microcorruption - Whitehorse


I probably should have read the manual (right, who does that?) before now. But better late than never. The manual on pages on 4 and 5 talks about how 0x7F is the code to unlock the door – not a function call but basically a hardware interrupt that accomplishes the same thing. Additionally there is mention of 0x7D and 0x7E which set a byte in memory if the entered password matches. Look for those to come into play at some point. We actually already saw these in Cusco, although that knowledge wasn't fully necessary at that point.

As in a Cusco, there is still an instruction (after the password has been checked and after the “wrong password” message is displayed) that adds 10 to the stack pointer. So the stack pointer jumps forward x10 to address 3cc6, and the next instruction is to return to the value held at the address 3cc6. The assumption is apparently that you have not entered a password longer than x10 bytes and put your own value in that address. But as the saying goes: when you assume you make an 'ass' out of 'u' and 'me'..

So we can put what we want in 3cc6 because nothing prevents us from entering a longer password than 16 characters – that is nothing prevents us from overflowing the buffer. Last time we did this we put the starting address of the “unlock door” function. This time however there is no unlock door function, but there is ample room to put code that we write in assembly.

So first we want to get control of the instruction pointer. Put the address at that point to the area of the buffer that we have overflowed, that is point the instruction pointer at the code we are overflowing into the buffer. This is called injecting code.

So what do we want to do? As you may recall from Cusco, hardware interrupt x7e when placed in the SR (stack register) and called with the interrupt trap causes the password to be checked. Hardware interrupt x7d sets a password in memory indicating that the password was correct, and x7f straight up unlocks the door.

Let's do the following:
Point the instruction pointer at memory we control.
Get x7f into the SR **
Call the interrupt trap.

We can look at the existing instructions in the code to cobble the bits and pieces together – or if you want a project you can learn this version of assembly and roll your own. But the basic structure of the code we can use is as follows

3e40 007f mv #x7f00, r14
0f4e mv r14, r15
024f mv r15, sr
32d0 0080 bis (highbit), sr **
b012 1000 call 0x10

**Note: the manual says x7F opens the door, but on my version of the game they had an extra part in there that set the high bit to 1 yielding xFF as the value required to unlock the door. The only way you figured this out was by looking at the code within <INT>


453e:  32d0 0080      bis       #0x8000, sr
so while you were examining <conditional_unlock> where it loads x7e onto the stack and calls <INT> you can see as you step through it that x7e gets loaded into the SR (from r15) and they flip the high bit on and then call the trap.

You can trim down the code above if you work through it – I don't want to take all the fun out – but a successful entry based on the code above can look like:

41414242434344444545464647474848c83c3e40007f0f4e024f32d00080b0121000

Microcorruption - REYKEYAVIC


In the end, one line of code shows you how to open the lock. Security through obscurity ... isn't. Sure don't be the tallest nail near the hammer, but that shouldn't be your entire game plan.

What follows is my thought process while analyzing the code, scroll to the end for the facepalm. 

do_clear – writes 00 to x100 bytes starting at x247c to initialize that portion of memory to x0 values. While I personally feel that initializing things like variables and pointers is good, safe practice in coding, it does serve to highlight that this area of memory may be important to the encryption/ decryption/ password recognition process.

Main – puts x4520 into r14 and then into r15. If this is meant as an address it puts you halfway into “do_nothing”. Then promptly overwrites r14 with xf8 and r15 with 2400. Then calls ENC.

ENC – begins by writing values 0 to x100 in sequential order to bytes starting at x247C and rising. Given that we just spent all that time writing zeros to them, only to then re-initialize them all again with specific values is … uh … part of the game I guess. Moving along then....

44a4: R8 = 0
… an algorithm?
44b0: references troll text: “ThisIsSecureRight?” and puts “T” (x54) in R10
44b4: sign extend R10 … this shouldn't produce any result on an ascii character as the highest is x7f. However if a non ascii character is entered there may be things.
44b6: R10+R13->R13 (54, 54)
44b8: Set high order bits to zero, resulting in new byte. So if we sign extend, then add, then overflow the register and set the high order bits back to zero, we can get a new ascii character. Adding xffff to x53, then anding with xff yields x52.

x247c: There appears to be something being put starting here again...

444a: call 2400 program is now executing code that it appears to have generated in the previous portions.

Then I see it, the snippet of code that says: Compare d7c5 <---- this is the password for opening the door. 

Face, palm.