I'm preserving my procedure because I may want to do it again, and it may even help others who want to do it right.
I wrote these instructions for Ubuntu 16.04 Server. I also did this successfully on Kali 2018.1 and Ubuntu 17.10 Server with the same procedure.
Setting up SAML requires these tasks:
1. Installing Apache and PHP
2. Configuring DNS Records
3. Configuring Virtual Servers
4. Set Up Service Provider
5. Set Up Identity Provider
6. Making an App
7. Breaking Security
sudo apt-get update
sudo apt-get install php libapache2-mod-php php-xml
sudo service apache2 restart
To test it, I made a file named
/var/www/html/phpinfo.php
with these contents:
<?php
phpinfo();
?>
In a Web browser, I went to:
http://samlol.samsclass.info/phpinfo.php
and saw the PHP info page, showing that everything
was OK. It's a good practice to remove that page
later, but I am making a deliberately insecure
server for students to hack, so I didn't.
My two virtual servers will be named "idp.samsclass.info" and "sp.samsclass.info".
These commands make home folders for each server:
sudo mkdir -p /var/www/idp.samsclass.info/public_html
sudo mkdir -p /var/www/sp.samsclass.info/public_html
I used the nano text editor to make a home page for the
IDP:
sudo nano /var/www/idp.samsclass.info/public_html/index.html
I put only the letters "IDP" in that file.
I used the nano text editor to make a home page for the SP:
sudo nano /var/www/sp.samsclass.info/public_html/index.html
It contains the letters "SP".
Next, I make the configuration file for the IDP:
sudo nano /etc/apache2/sites-available/idp.samsclass.info.conf
Here is the contents of that file:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName idp.samsclass.info
DocumentRoot /var/www/idp.samsclass.info/public_html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Next, I make the configuration file for the SP:
sudo nano /etc/apache2/sites-available/sp.samsclass.info.conf
Here is the contents of that file:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName sp.samsclass.info
DocumentRoot /var/www/sp.samsclass.info/public_html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Executing these commands enables the sites:
sudo a2ensite idp.samsclass.info.conf
sudo a2ensite sp.samsclass.info.conf
sudo systemctl reload apache2
Now the two test pages are visible:
cd /tmp
wget https://simplesamlphp.org/download?latest
These commands extract it into the SP's
home folder and give it a handy directory name:
cd /var/www/sp.samsclass.info/public_html
sudo tar xvzf /tmp/download?latest
sudo mv simplesamlphp-1.15.4 simplesamlphp
I need to edit this Apache file to make the
virtual directory "simplesaml", which
simplesamlphp expects:
sudo nano /etc/apache2/sites-available/sp.samsclass.info.conf
Add this before the </VirtualHost> line:
Alias /simplesaml /var/www/sp.samsclass.info/public_html/simplesamlphp/www
<Directory "/var/www/sp.samsclass.info/public_html/simplesamlphp/www">
Order deny,allow
Allow from all
</Directory>
Reload Apache:
sudo systemctl reload apache2
Now this page loads in a browser, showing a
simplesamphp installation page:
http://sp.samsclass.info/simplesaml
To make it functional, you must edit this file:
cd /var/www/sp.samsclass.info/public_html/simplesamlphp
sudo nano config/config.php
Change 'auth.adminpassword' and
'secretsalt' to non-default values.
These commands extract it into the IDP's home folder:
cd /var/www/idp.samsclass.info/public_html
sudo tar xvzf /tmp/download?latest
sudo mv simplesamlphp-1.15.4 simplesamlphp
Again, you must edit this Apache file to make the
virtual directory "simplesaml", which
simplesamlphp expects:
sudo nano /etc/apache2/sites-available/idp.samsclass.info.conf
Add this before the
Alias /simplesaml /var/www/idp.samsclass.info/public_html/simplesamlphp/www
<Directory "/var/www/idp.samsclass.info/public_html/simplesamlphp/www">
Order deny,allow
Allow from all
</Directory>
Reload Apache:
sudo systemctl reload apache2
Now this page loads in a browser, showing a
simplesamphp installation page:
http://idp.samsclass.info/simplesaml
To make it functional, you must edit this file:
cd /var/www/idp.samsclass.info/public_html/simplesamlphp
sudo nano config/config.php
As before, you must change 'auth.adminpassword' and
'secretsalt' to non-default values.
But this time, you must also set enable.saml20-idp to true -- to make this instance of simplesamlphp an Identity Provider. To enable authentication do this:
cd /var/www/idp.samsclass.info/public_html/simplesamlphp
sudo touch modules/exampleauth/enable
Now you need a data source for valid usernames
and passwords. A database like MySql is the
usual choice, but for my purposes a simple
file containing hard-coded credentials is
good enough, so I did this:
cd /var/www/idp.samsclass.info/public_html/simplesamlphp
sudo nano config/authsources.php
I added this inside the $config object.
This makes two users:
'example-userpass' => array(
'exampleauth:UserPass',
'user1:pwd' => array(
'uid' => array('user1'),
'mail' => 'user1@test.com',
'first_name' => 'User',
'last_name' => 'One'
),
'user2:pwd' => array(
'uid' => array('user2'),
'mail' => 'user2@test.com',
'first_name' => 'User',
'last_name' => 'Two'
)
),
These commands make the RSA key needed for signatures:
cd /var/www/idp.samsclass.info/public_html/simplesamlphp
cd cert
sudo openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -out server.crt -keyout server.pem
Now you need to edit this file to tell the Identity
Provider where your code-signing keys are:
cd /var/www/idp.samsclass.info/public_html/simplesamlphp
sudo nano metadata/saml2-idp-hosted.php
Put this text into that file:
$metadata['__DYNAMIC:1__'] = array(
/*
* The hostname of the server (VHOST) that will use this SAML entity.
*
* Can be '__DEFAULT__', to use this entry by default.
*/
'host' => '__DEFAULT__',
/* X.509 key and certificate. Relative to the cert directory. */
'privatekey' => 'server.pem',
'certificate' => 'server.crt',
/*
* Authentication source to use. Must be one that is configured in
* 'config/authsources.php'.
*/
'auth' => 'example-userpass',
/* Uncomment the following to use the uri NameFormat on attributes. */
/*
'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
'authproc' => array(
// Convert LDAP names to oids.
100 => array('class' => 'core:AttributeMap', 'name2oid'),
),
*/
);
You need to edit this file to tell the Identity
Provider where your passwords are:
cd /var/www/sp.samsclass.info/public_html/simplesamlphp
sudo nano config/authsources.php
Edit the default-sp section to look like this. The only three
lines to add are the ones beginning with 'entityID', 'idp', and
'ssoPortalUrl'. Delete or comment out the existing lines
beginning with 'entityID' and 'idp'.
'default-sp' => array(
'saml:SP',
'entityID' => 'http://idp.samsclass.info',
'idp' => 'http://idp.samsclass.info/simplesaml/saml2/idp/metadata.php',
'ssoPortalUrl'=> 'http://idp.samsclass.info/simplesaml/saml2/idp/SSOService.php',
// The URL to the discovery service.
// Can be NULL/unset, in which case a builtin discovery service will be used.
'discoURL' => null,
...
In a browser, go to
http://idp.samsclass.info/simplesaml
Click the Federation Tab.
Log in as admin with the password you specified earlier.
You should see a SAML 2.0 IdP Metadata line, click on the [show metadata] link below it. The metadata should appear!
Scroll down to the "SimpleSAMLphp flat file format" and paste it in the file metadata/saml20-idp-remote.php of your SP.
Troubleshooting
If the metadata will not load, look in the syslog withIf you see "SimpleSAML_Error_Exception: Error 1 - Class 'DOMDocument' not found", you probably don't have the php-xml library installed, or there is a conflict with two versions of PHP installed at once. I found that this can be fixed by completely removing all old PHP files and then installing PHP 7.0 or 7.2, including php-xml or php7.2-xml.
tail -f /var/log/syslogSyslog may show this error: "SimpleSAML_Error_Exception: Error 2 - session_set_cookie_params(): Cannot change session cookie parameters when session is active". If so, just ignore it. It seems harmless.
You can test the metadata script from the command line with these commands:
The reply contains a lot of errors like this: "SimpleSAML_Error_Exception: Error 8 - Undefined index: REQUEST_URI"
cd /var/www/idp.example.com/public_html/simplesamlphp cd www/saml2/idp php metadata.phpI spent a long time trying to fix that, but finally realized that it doesn't matter. Just ignore it. The server works fine anyway.
cd /var/www/sp.samsclass.info/public_html/simplesamlphp
sudo cp metadata/saml20-idp-remote.php metadata/saml20-idp-remote.php.bak
sudo nano metadata/saml20-idp-remote.php
Append the $metadata at the end, like this:
$metadata['http://idp.samsclass.info/simplesaml/saml2/idp/metadata.php'] = array (
'metadata-set' => 'saml20-idp-remote',
'entityid' => 'http://idp.samsclass.info/simplesaml/saml2/idp/metadata.php',
'SingleSignOnService' =>
array (
0 =>
array (
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => 'http://idp.samsclass.info/simplesaml/saml2/idp/SSOService.php',
),
),
'SingleLogoutService' =>
array (
0 =>
array (
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => 'http://idp.samsclass.info/simplesaml/saml2/idp/SingleLogoutService.php',
),
),
'certData' => 'MIIDXTCCAkWgAwIBAgIJAJK3x7G6tuOEMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTgwNDAxMTYyNDE4WhcNMjgwMzMxMTYyNDE4WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyf4AHwhNDxXD4Mi/GkuV48ZJKdwK9xcXty0kM3vj2pye//RGaYvcl7jGZyoP0Nfl01dRTHf5TDxY/192Zxlmn9LupoiuuoenkA0EHcsYNFe8aoJ/CIyXGZbTDgK+ZbR2g264h6x3FrqTbwN1pV7en/KwQJ226T9fGDzWraGopqliSINTGMk2cXxEEo0+W6TkxmGktL7h+It0vsxZX7T0dK/nXk5ClKb/Cr+gYQ5qRWOuNyjDYNPIWC1WMdwSEJxN8WB0TNAlzZXxZA35DMsOzLaFRiNlqF1iv7SWaMU3AoBPf9703fTheFVD379qddrukehmirhBHs2s0BgByksY5wIDAQABo1AwTjAdBgNVHQ4EFgQUT8J76xFu9666xXwVgnxs9bhk3gUwHwYDVR0jBBgwFoAUT8J76xFu9666xXwVgnxs9bhk3gUwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAaKPVRNbjYZEPfbH51YeGEGV2jcaMrGvVEZSuWLM7t8aoYBzEPC9fCi2iC4BWgUKzdJPSlwvd5BCwkqciCoOYTncxU7oi+GwbpvjNSGjf8OW259OoI0lUItTCKjJmjj07i+syo4b63o51pGP2lSCQQtoPrG8ObRX7lKXFVKdwkXxz2p4TcRP7+yUpqd9b3vZTW3ApdNGRDHMLVBZlI78i3lCf5y1mF3xLkT7nhAV8mVjfpg+uFFJjkbO7vRj8IxM+AsVEmNWaUwsD8o6DzA/U0xNQMRndhyupjLTuN5ACoXnfGSoerqb5Us3euGJwDrHqoQbTX60yxir0t6yMUGFFFw==',
'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
);
You also need to edit this file:
cd /var/www/idp.samsclass.info/public_html/simplesamlphp
sudo cp metadata/saml20-sp-remote.php metadata/saml20-sp-remote.php.bak
sudo nano metadata/saml20-sp-remote.php
In a browser, open
http://sp.samsclass.info/simplesaml
Click the Federation tab, and login as admin with the password you chose previously.
Click on the [show metadata] link for your default-sp.
Scroll down, copy the content of the "SimpleSAMLphp flat file format" box and paste it in the IdP metadata/saml20-sp-remote.php file.
Replace the metadata with this:
$metadata['http://idp.samsclass.info'] = array (
'SingleLogoutService' =>
array (
0 =>
array (
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
'Location' => 'http://sp.samsclass.info/simplesaml/module.php/saml/sp/saml2-logout.php/default-sp',
),
),
'AssertionConsumerService' =>
array (
0 =>
array (
'index' => 0,
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
'Location' => 'http://sp.samsclass.info/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp',
),
1 =>
array (
'index' => 1,
'Binding' => 'urn:oasis:names:tc:SAML:1.0:profiles:browser-post',
'Location' => 'http://sp.samsclass.info/simplesaml/module.php/saml/sp/saml1-acs.php/default-sp',
),
2 =>
array (
'index' => 2,
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact',
'Location' => 'http://sp.samsclass.info/simplesaml/module.php/saml/sp/saml2-acs.php/default-sp',
),
3 =>
array (
'index' => 3,
'Binding' => 'urn:oasis:names:tc:SAML:1.0:profiles:artifact-01',
'Location' => 'http://sp.samsclass.info/simplesaml/module.php/saml/sp/saml1-acs.php/default-sp/artifact',
),
),
);
To test it,
in a browser, go to
http://sp.samsclass.info/simplesaml
You should be logged in as administrator
Click on the authentication tab. Click on the link "Test configured authentication sources" and click on "default-sp"
Log in as user1 pwd
You should see a page showing your User ID, Mail, etc.
/var/www/sp.samsclass.info/public_html/simplesamlphp/www/win.php
Here's its code:
<html>
<head>
<title>
SAMLOL Challenge
</title>
</head>
<body bgcolor="#cccccc">
<h1 align="center">
SAMLOL Challenge
</h1>
<blockquote><table border=5 cellpadding=10 align="center"><tr><td>
<?php
require_once('../lib/_autoload.php');
$as = new \SimpleSAML\Auth\Simple('default-sp');
$attrs = $as->getAttributes();
if (!isset($attrs['uid'][0])) {
print "<h2 align='center'>You are not logged in!</h2>";
print "<img src='sleep2.png'><p>";
print "<p align='center'>You can use these accounts: <b>user1</b> <b>pwd</b> and <b>user2</b> <b>pwd</b></p>";
$url = $as->getLoginURL();
print "<b><p align='center'><a href='" . htmlspecialchars($url) . "'>Login</a></b></p>";
print "<p align='center'>The 1337 kids are on the <a href='http://samlol.samsclass.info/tmp/samlol-winners.htm'><b>WINNERS PAGE</b></a>.</p>";
print "<p align='center'><a href='https://samsclass.info/129S/proj/p16saml.htm'><b>Explanation and Instructions</b></a>.</p>";
} else {
$name = $attrs['uid'][0];
if ($name != 'admin') {
print "<h1 align='center'>UNAUTHORIZED</h1>";
print "<h2 align='center'>You are logged in as <i>" . htmlspecialchars($name) . "</i></h2>";
print "<h2 align='center'>You must be <i>admin</i> to win!</h2>";
print "<img src='hiss.png'><p>";
$url = $as->getLogoutURL();
print "<p align='center'><b><a href='" . htmlspecialchars($url) . "'>Logout</a></b></p>";
// $url = ".../simplesaml/module.php/core/as_logout.php?AuthId=default-sp&ReturnTo=win.php";
// print('<a href="' . htmlspecialchars($url) . '">Logout</a>');
} else {
print "<h1 align='center'>YOU WIN</h1>";
print "<h2 align='center'>You are logged in as <i>" . htmlspecialchars($name) . "</i></h2>";
print "<img src='happy.jpg'><p>";
print "Use the form below to put your name on the <a href='http://samlol.samsclass.info/tmp/samlol-winners.htm'>";
print "<b>WINNERS PAGE</b></a>.";
print "<blockquote><form action='win-board.php' method='post'>";
print "<table cellpadding=5 border=10><tr><td>";
print "<table cellpadding=5 align='center'>";
print "<tr><td><big><b>Your Name:</b></big></td>";
print " <td><textarea name='u' rows='1' cols='25'></textarea></td></tr>";
print "<tr><td colspan=2 align='center'><big><b>";
print "<input type='submit' value='SUBMIT'></td></tr>";
print "</table>";
print "</td></tr></table>";
print "</form>";
print "</blockquote>";
$url = $as->getLogoutURL();
print "<p align='center'><b><a href='" . htmlspecialchars($url) . "'>Logout</a></b></p>";
}
}
?>
</td></tr></table>
</blockquote>
</body>
</html>
/var/www/sp.samsclass.info/public_html/simplesamlphp/modules/saml/www/sp/saml1-acs.php
/var/www/sp.samsclass.info/public_html/simplesamlphp/modules/saml/www/sp/saml2-acs.php
/var/www/sp.samsclass.info/public_html/simplesamlphp/modules/saml/lib/Message.php
/var/www/sp.samsclass.info/public_html/simplesamlphp/modules/saml/www/sp/saml1-acs.php
Around line 63, I changed it to this, to make it accept responses with no signatures:
} elseif (array_key_exists('SAMLResponse', $_REQUEST)) {
$responseXML = $_REQUEST['SAMLResponse'];
$responseXML = base64_decode($responseXML);
$isValidated = TRUE; /* CHANGED BY SAM TO BREAK SECURITY 3-31-18 Must check signature on response. */
/* $isValidated = FALSE; Must check signature on response. */
/var/www/sp.samsclass.info/public_html/simplesamlphp/modules/saml/www/sp/saml2-acs.php
It had the number "60" in line 158,
to make it accept time discrepancies up to
60 seconds. I changed that to 6000, so it now looks
like this:
$notOnOrAfter = $assertion->getNotOnOrAfter();
if ($notOnOrAfter === null) {
$notOnOrAfter = time() + 24 * 60 * 60;
} else {
$notOnOrAfter += 6000; // CHANGED FROM 60 to 6000 BY SAM TO BREAK SECURITY we allow 60 seconds clock skew, so add it here also
}
$store->set('saml.AssertionReceived', $aID, true, $notOnOrAfter);
}
/var/www/sp.samsclass.info/public_html/simplesamlphp/modules/saml/lib/Message.php
Around line 613, I changed it to this, to make it accept responses with no signatures,
and to allow time discrepancies up to 6000 seconds:
/* SIGNATURE CHECK COMMENTED OUT BY SAM TO BREAK SECURITY
if (!self::checkSign($idpMetadata, $assertion)) {
if (!$responseSigned) {
throw new SimpleSAML_Error_Exception('Neither the assertion nor the response was signed.');
}
} // at least one valid signature found
*/
$currentURL = \SimpleSAML\Utils\HTTP::getSelfURLNoQuery();
// check various properties of the assertion
$notBefore = $assertion->getNotBefore();
/* 60 changed to 6000 by SAM to BREAK SECURITY */
if ($notBefore !== null && $notBefore > time() + 6000) {
throw new SimpleSAML_Error_Exception(
'Received an assertion that is valid in the future. Check clock synchronization on IdP and SP.'
);
}
That's it. This produces the broken application here:
Posted 4-1-18 1:29 pm
Minor fix 4-4-18 7 am