The following is a list of things that can, and probably should, be done in order to secure an OpenSSH server. This list isn’t necessarily complete, but what is here can significantly improve the server’s defenses against attackers. Continue reading
I recently switched my blog from my own programming to using WordPress. I have long recognized WordPress as good a software project and it has stood the test of time. Not only has the software been around since 2003, it has continued to improve. The improvements to WordPress have allow the software to run more and more projects (although it’s still used, in my opinion, too often where it doesn’t fit right).
For my needs I thought it would work well. I’m running a business while attending university and keeping up with certifications, so I didn’t want to spend the time to make it easier to post to my blog — which had been on my to do list — so I just installed WordPress. The installation took a matter of minuets and after a bit of time looking though themes I quickly had my site up and running with the CMS and looking decent with a freely available theme.
I wanted to add a table to my site that shows the books I’ve read. I wanted the book’s title to be displayed along with the author(s) and a picture of the book. I did not want to write out the HTML each time and the WordPress interface doesn’t make working with tables easy.
I’m a member of paperbackswap.com, and on their site they maintain a list of books that I’ve read. I can export this list as a CSV file. I thought it would be nice to place this CSV file in my site’s directory structure and have a PHP script parse the file and generate the desired table. This lead me to ask the following questions:
- How do I add a custom page to WordPress?
- How do I control that page with PHP?
First, I created a directory for my custom pages in the WordPress directory structure named
my-pages. Then, I uploaded the CSV file from paperbackswap into this directory. I named the file
readBooks.csv. The fields of the CSV file were: title, ISBN10, and ISBN13. I really don’t need the ISBNs for my purposes but it didn’t hurt to leave them there (I may use them in the future, and I can always leave those fields blank when adding to the list), but I was going to need a field for the book’s cover image. I decided that would become the first field of the CSVs.
Next, I created the new page by following Adam’s instructions. To make things easier, I linked to this page (which is in the WordPress themes directory) into the
my-pages directory and named the page
books.php; my directory looked like so:
$> ls -hal lrwxrwxrwx 1 jason www-data 35 Oct 11 20:20 books.php -> ../wp-content/themes/vito/books.php -rwxrwxr-x 1 jason www-data 4.1K Oct 13 02:03 readBooks.csv
books.php page is a copy of my theme’s template, and contains its PHP code. I thought it would be too messy to insert my code directly into this template so I created a “controller” for it which contains the page specific PHP. Then I included the controller in the page so that I can call the function needed to print the books table. Here’s the
$> head books.php <?php /* * Template Name: books */ require_once(ABSPATH.'my-pages/booksController.php'); ?>
At this point, I started drafting the code that would parse the CSV file and print my table. I found that it was advantageous to create a Book class that would serve as a constructor. I would give the new Book object’s constructor an associative array containing the fields parsed from the CSV file. The Book objects would also provide a
__toString method which would return an HTML table row containing the given book’s data. The function that instantiates the Books would take care of generating the rest of the HTML table.
By now the
my-pages directory structure looked like this:
ls -F classes/ img/ booksController.php* books.php@ readBooks.csv*
I added the
classes directory to hold the definition of the Book class (and future classes, should I decide to create new pages) and the
img directory to contain the book covers. With all this in place, when I want to add a book to the Books page, I simply upload the cover image to the img directory and enter the book’s details in the
readBooks.csv file and voilà, the book would be added to the books table.
In SQL, the standard aggregation operators are
COUNT and we can apply them to the attributes of relations. For example we have a schema
employee(eid, name, dob, hired_date, salary), which holds records on each of a company’s employees. We can
COUNT and see how many employees the company has with the following query:
SELECT COUNT(*) FROM employee;
* is an argument to the count operator and means to count all tuples in the relation. With the
DISTINCT operator we eliminate duplicates for the query result, so if we wanted to see if any of the employees had the same name we could compare the previous query with the following:
SELECT COUNT(DISTINCT name) FROM employee;
If the first count is larger than the second, then the company has at least two employees with the same name.
COUNT also does not count tuple attributes with
NULL value, and
SUM don’t factor them in when calculating either. We can use
AVG to find the average salary of our employees and
SUM to calculate the total amount paid for employee salaries with these queries:
SELECT AVG(salary) FROM (employee); SELECT SUM(salary) FROM (employee);
A grouping query is executed on a relation with the
GROUP BY clause.
GROUP BY is followed by an attribute list and the resulting tuples are grouped successively according to the list. To see how grouping works, let’s say that the company from our earlier examples is a shipping company and owns trucks. The company keeps track of truck purchases and their usage with the following relations:
truck(tid, make, model, year, purch_year, purch_quarter, cost). In a simple example we could query the database and ask which years the company purchased trucks:
SELECT purch_year FROM truck GROUP BY purch_year;
GROUP BY would come after a
WHERE clause, but in this case we didn’t need one so it was omitted. The result of this query would be a single attribute relation (a single column table) with values reflecting the years in which the company purchased at least one truck. If the company purchased more that one truck in that year that purchase would be aggregated with all others in that year.
Only the attributes that are listed in the
GROUP BY clause can appear unaggregated in the
SELECT clause. The next two queries would tell the company which years and in which quarters they purchased trucks and the total amount spent in each quarter.
SELECT purch_year, quarter FROM truck GROUP BY year, quarter ORDER BY quarter, year; SELECT purch_year, SUM(cost) as annualcost FROM truck GROUP BY purch_year;
The first query would return a relation of 2-tuples with the first element being
purch_year and the second
quarter (the result is also first sorted by quarter, then by year). The second query would also return a 2-tuple but the elements would be
annualcost which is the aggregated (by simple addition in this case) cost of trucks for each year. Because
cost is not in the
GROUP BY clause, it must be aggregated.
The HAVING Clause
In our last set of queries, we asked for the costs of trucks purchased on an annual basis. Suppose for some reason the company wanted to find the average cost spent in a year only in years where every truck purchased in that year cost over $15,000. To ask this question we can use the
SELECT purch_year, AVG(cost) as avgcost FROM truck GROUP BY purch_year HAVING MIN(cost) > 15000;
HAVING clause applies to each group. In this case,
MIN is calculated on the attribute
cost for each purchase year (
purch_year) then compared to 15,000. If the minimum value for all costs in a purchase year are greater that 15,000 then the
purch_year shows up in the query result (a 2-tuple
Using Public Key Cryptography and SSH Tools for Smooth Log In
To log in to an SSH server without the needing to enter a password each time can be done in different ways. One way is to to configure your server to allow certain users (or certain users from certain hosts/networks/ip addresses [or ranges]) but another preferred method I am going to demonstrate involves encryption keys and the Diffi-Helmen Key Exchange.
(See also PKI)
Primarily one needs an encryption key to verify his or her identity. There are different algorithms that exist by which a key can be created (I won’t go into them here), but a popular and often recommended one is the RSA algorithm which I will use in my example.
On a POSIX (Unix/Unix Like) system with an SSH server in a typical configuration, this is the process to create an rsa encryption key:
> ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/user/.ssh/id_rsa): Created directory '/home/user/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/user/.ssh/id_rsa. Your public key has been saved in /home/user/.ssh/id_rsa.pub. The key fingerprint is: a9:9d:f8:df:63:64:68:11:00:13:f1:bb:2d:76:5d:5b user@gnu-linux
Once our key has been created (client side), we need to copy our public key into the proper directory on the SSH server. DO NOT DISTRIBUTE YOUR PRIVATE KEY, KEEP IT SAFE! When performing public key authentication, by default the server checks in the users home directory (
$HOME) for a directory named ‘.ssh’. Inside that directory the server is looking for a file named ‘authorized_keys’. This file is where we place a copy of our public key, on a single new line.
The public key can be distributed automatically with the
> ssh-copy-id Usage: /usr/bin/ssh-copy-id [-h|-?|-n] [-i [identity_file]] [-p port] [[-o
] ...] [user@]hostname > > ssh-copy-id email@example.com
To do it manually:
---In the home directory on the client machine--- > cat .ssh/id_rsa.pub > pubkey > scp pubkey firstname.lastname@example.org: ---output omitted--- > ssh email@example.com ---output omitted--- ---On server in home directory--- > cat pubkey >> .ssh/authorized_keys > exit
Okay. This takes care of half of the puzzle. This will allow our server to use our rsa key to verify our identity, but (assuming a passphrase was entered when prompted above) we will still need to enter the passphrase for this key each time we attempt to log into the server. What we can do to get around this is utilize the
ssh-agent which is part of the SSH client.
Our key can be added to the ssh-agent one time and future requests for access to SSH servers will be handled by the agent. When our rsa key was created, we opted to store it in the default location. The ssh-agent will likewise by default look in the default storage location for our encryption keys. So all one needs to do to load their key into the ssh-agent is issue the
ssh-add command – Windows users can setup a profile in Putty to accomplish the same result.
> ssh-add Enter passphrase for /home/user/.ssh/id_rsa: Identity added: /home/user/.ssh/id_rsa (/home/user/.ssh/id_rsa)
Now with our key loaded into the ssh-agent, we can access any SSH server where our public key is authorized without needing to enter our passphrase.
The Original Version Control System
What is SCCS?
SCCS stands for Source Code Control System; it is a suite of programs that are used together to manage the development of source code which is eventually compiled into usable software. SCCS can be used to manage other classes of text files (not only source code), but the reason it was created and its predominate use is to mange changes made to source code files.
What is meant by development/changes?
Source code is generally recorded in plain (non-formatted) text files called source files and collectively the source code for a particular piece of software. The source code itself must then be transformed from text into the binary that a CPU understands. This transformation is done via compilation, as is the case with C and Java, or it is translated as is true of PHP and Python source code.
If a programmer wants to fix, add features, or otherwise improve the functionality of her program she would open her source code with a standard text editor, make the desired changes, and then compile (or run through a translator) the source code. Once every thing is working correctly she can then release a new version of the program with the improvement. This is essentially software development in a nut shell.
Okay, so where does SCCS come in?
As stated, SCCS is used to mange the process described in the last section. The most simple case of software development is a single programmer maintaining and improving a single program. Again the general procedure would be:
- Create/Edit a source file.
- Save edits to that file.
- Compile source into the executable program.
If all edits were done in a single sitting, and each edit make was completely correct, then development would happen linearly and management would be similarly straightforward. But making improvements to source code very often requires more than a single editing session. New bugs are regularly found. And making things more complicated, code added as an improvement sometimes introduces new bugs. Because of this the need arises to keep track of changes.
For example, a developer can be working on a program and he makes an couple of improvements. Then he discovers one of the changes made actually crashes the program under certain circumstances. With SCCS, or pretty much any other version control system, the programmer can view a history of the changes made to track down when the bug was introduced. Necessary changes to the source code can then be made to implement a fix, or if required, the entire set of changes that were made can be removed from the source code.
This use of SCCS, or more generally version control systems, is definitely an advantage to programmers working individually as well as in teams. Yet, as with just about anything else, things get more complicated the more people are involved.
Initially SCCS requires that programmers import their source code into the system. To bring these files in, the user must create a directory named SCCS. Each source file becomes an
sfile in the SCCS directory (i.e.
s.source.c). After that, working within the system one interacts with these sfiles – and not the source files themselves – when performing maintenance or development. From then on, the program and the programmer(s) use the system keep track of all changes.
To edit a file in the system it needs to be ‘checked out.’ This places a lock on the file so that no one else can work on the file at the same time. The programmer would then make edits and once they are satisfied with the changes (and the program runs correctly*) the would then
delta, or merge, their changes back into the sfile. At each delta the programmer writes (or ought to write) a comment on the changes made. (Note that only changes are written to the sfile, a full copy is not made). The deltas are and normalized and serialized. With the deltas, and their accompanying programmer comments, the project is managed.
The sfile is like a database file. The original source code is imported with the admin program and transformed into the sfile format. These files are then stored in a directory named
SCCS. Changes are recorder at each merge with programmer comments and other useful meta data.
To edit a file the programmer uses the
get program with the
-e flag, or the
edit command. A copy of the requested version of the file is then returned to the programmer. The sfile for the file being edited is then locked for any user other than the programmer who checked the file out. After the desired modifications are made (and the program compiles and runs correctly), the changes must be merged back into the sfile. If one wishes to discard their changes they can use the unedit command to back out of any changes made.
To write the changes made to the source code, one must merge the changes with the delta program. This writes the changes to the sfile. Upon issue the
sccs delta command, the programmer will be prompted to comment on the changes; this comment will be appended to meta data containing an
SID (SCCS ID), or version number which is of the form
r is the ‘release’ number and
l is the ‘level’ – which I think of as major and minor version number.
According to Eric Allman of the University of California at Berkeley’s “An Introduction to the Source Code Control System” (available at: http://sccs.sourceforge.net/man/sccs.me.html):
“A good technique is to edit the files you need, make all necessary changes and tests, compiling and editing as often as necessary without making deltas. When you are satisfied that you have a working version, delta everything being edited, re-get them, and recompile everything.”
To get a file for compilation use the
sccs get [file] command. This returns a read only copy of the current version of the file that can be used for compilation. To grab all the source files use the
sccs get SCCS/ command in the directory containing your SCCS directory.
Example project: address book program.
$> ls -F addrBookUI* bld/ inc/ makefile README src/
bld/ object files
inc/ header files
src/ source files
Initializing the SCCS
To initialize the SCCS using bash:
- Create an SCCS directory
- Import source files into sfiles
$> cd src $> ls actions.c addrBookUI.c helpers.c $> mkdir SCCS save $> for x in $(ls);do > sccs admin -i$x $x > mv $x save/ > done No id keywords (cm7) No id keywords (cm7) No id keywords (cm7) $>
No id keywords (cm7) is related to the consept of ID keywords, which I won’t cover, but this is just a warning (generated for each source file imported into the system). After issuing the above set of commands our source code has been transformed into sfiles (i.e. s.helpers.c) and can be found in the SCCS directory. The original .c files were moved to save for archiving or disposal.
$> ls save SCCS $> ls SCCS s.actions.c s.addrBookUI.c s.helpers.c
To work on a source file, it must be checked out of the system with the
get program using the
-e option, or using the edit command.
$> sccs get -e helpers.c 1.1 new delta 1.2 88 lines $> sccs edit actions.c 1.1 new delta 1.2 396 lines $> ls actions.c helpers.c save SCCS
As you can see the two source files have been made available for editing. To back out of editing use the
sccs unedit [file].
Merging a file
After edits have been made, they need to be merged into the project (recorded in the sfile).
$> sccs delta actions.c comments? Moved a comment No id keywords (cm7) 1.2 2 inserted 1 deleted 395 unchanged
Make sure all edits have been make and recorded in the sfile.
For individual files
$> sccs get helpers.c 1.2 88 lines No id keywords (cm7) $> gcc -c helpers.c $> sccs clean
For the entire source code
$> sccs get SCCS SCCS/s.actions.c: 1.2 397 lines No id keywords (cm7) SCCS/s.helpers.c: 1.2 88 lines No id keywords (cm7) SCCS/s.addrBookUI.c: 1.1 263 lines No id keywords (cm7) $> make addrBookUI clean ---output omitted-- $> sccs clean
The following commands can be use to tell which files are being edited and by which users:
$> sccs info Nothing being edited $> sccs info -ujason Nothing being edited by jason $> sccs get -e helpers.c $> sccs check helpers.c: being edited: 1.2 1.3 jason 14/09/27 19:10:47
prt program is use to get information on what changes have been made to a particular file.
$> sccs prt helpers.c SCCS/s.helpers.c: D 1.2 14/09/27 20:40:13 jason 2 1 00000/00000/00088 D 1.1 14/09/27 19:50:38 jaosn 1 0 00088/00000/00000 date and time created 14/09/27 19:50:38 by jason
get with the
-p options to get a detailed history of when changes were made.
$> sccs get -m -p helpers.c 1.2 1.1 /********************************************************************** 1.1 // 1.1 // AUTHOR: Jason Favrod 1.1 // 1.1 // DATE: 17 Sept 2014 1.1 // 1.1 // FILE: helpers.c 1.1 // 1.1 // DESCRIPTION: A collection of helper functions. 1.1 // 1.2 // New Comment 1.1 ***********************************************************************/ 1.1 #include "helpers.h" 1.1 1.1 1.1 /********************************************************************* ---output omitted---
Otherwise known as a LAMP server, the LAMP software stack consists of GNU\Linux as the operating system, Apache as the Web server, MySql for a database, and PHP (or possibly Pearl or Python) as the programming language used to host a Web application.
I’m going to assume a minimal install (I’ll be using debian-7.6.0-i386-CD-1.iso)
First we’ll need to make sure we have all the necessary repos in our
/etc/apt/sources.list file. If you installed from a complete
installation image you probably won’t need to mess with this, but
cat out the sources list and make sure you have the following or
root@debian32-base:# cat /etc/apt/sources.list deb http://ftp.us.debian.org/debian stable main contrib non-free deb http://ftp.debian.org/debian/ wheezy-updates main contrib non-free deb http://security.debian.org/ wheezy/updates main contrib non-free
Okay, now update
apt and install our software packages.
You will need to set a password for MySql’s root user.
root@debian32-base:# apt-get update ---output omitted--- root@debian32-base:~# apt-get install apache2 mysql-client mysql-server php5 libapache2-mod-php5 Reading package lists... Done Building dependency tree Reading state information... Done The following extra packages will be installed: apache2-mpm-prefork apache2-utils apache2.2-bin apache2.2-common libaio1 libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libdbd-mysql-perl libdbi-perl libhtml-template-perl libmysqlclient18 libonig2 libqdbm14 mysql-client-5.5 mysql-common mysql-server-5.5 mysql-server-core-5.5 php5-cli php5-common ssl-cert Suggested packages: apache2-doc apache2-suexec apache2-suexec-custom php-pear libipc-sharedcache-perl libterm-readkey-perl tinyca openssl-blacklist The following NEW packages will be installed: apache2 apache2-mpm-prefork apache2-utils apache2.2-bin apache2.2-common libaio1 libapache2-mod-php5 libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libdbd-mysql-perl libdbi-perl libhtml-template-perl libmysqlclient18 libonig2 libqdbm14 mysql-client mysql-client-5.5 mysql-common mysql-server mysql-server-5.5 mysql-server-core-5.5 php5 php5-cli php5-common ssl-cert 0 upgraded, 27 newly installed, 0 to remove and 2 not upgraded. Need to get 16.1 MB of archives. After this operation, 115 MB of additional disk space will be used. Do you want to continue [Y/n]? Get:1 http://security.debian.org/ wheezy/updates/main mysql-common all 5.5.38-0+wheezy1 [78.6 kB] ---output omited---
Right about now, you get hit with the ncurses screen
And then the installation will finish uninterrupted
---output omitted--- Creating config file /etc/php5/apache2/php.ini with new version [ ok ] Restarting web server: apache2 ... waiting . Setting up libhtml-template-perl (2.91-1) ... Setting up mysql-client (5.5.38-0+wheezy1) ... Setting up mysql-server (5.5.38-0+wheezy1) ... Setting up php5 (5.4.4-14+deb7u12) ... Setting up php5-cli (5.4.4-14+deb7u12) ... Creating config file /etc/php5/cli/php.ini with new version update-alternatives: using /usr/bin/php5 to provide /usr/bin/php (php) in auto mode Setting up ssl-cert (1.0.32) ... root@debian32-base:~#
Now you should be able to navigate to the server with a Web Browser. Just type
the computer’s IP address into the address bar.
What we don’t know for sure at this point is if PHP is working. Let’s rename
index.html file to a PHP file (
(FYI: to rename in the terminal, we use the move
Then we can open it with a text editor and add some PHP code and see if it’s
root@debian32-base:~# mv /var/www/index.html /var/www/index.php root@debian32-base:~# vim /var/www/index.php
<html><body><h1>It works!</h1> <p>This is the default web page for this server.</p <p>The web server software is running but no content has been added, yet.</p> </body> <?php echo('Hello World'); ?> </html>