Can anyone recommend a free and simple OCSP server for Windows or Linux?
OCSP – Free OCSP Server for Testing Purposes
certificateocspSecurity
Related Solutions
In case you are interested: here's my solution.
First I ditched OpenSSL's OCSP responder. It can't be used for certificates that have not been created with your self-signed CA.
Then I used the OpenCA libraries to create a command line utility that is capable of creating an OCSP response from an OSCP request. It works entirely file-based: you run it with a DER formatted OSCP request as input file, and it outputs a DER formatted OCSP response file.
A second argument to the command line utility is the revocation status: good, revoked or unknown. The certificate status in the response file will be the same as the passed argument. The code is based on this sample, pointed out to me by The Rook in this post.
The final step was to create a HTTP server that builds upon the command line utility. I used Ruby's Merb framework for that. A nifty feature is that the revocation status can be requested as a HTTP url, for example: http://127.0.0.1:5000/good.
Update
Since above links are broken I'll post the script contents here:
AllCommands.sh:
#################
# Create the CA #
#################
# Create folder stucture and default files
mkdir -p CA/private
mkdir -p CA/newcerts
touch CA/index.txt
echo "00" >> CA/serial
# Create the CA
openssl req -new -x509 -keyout ./CA/private/cakey.pem -out ./CA/cacert.pem -days 365 -passin pass:secret1 -passout pass:secret1 -config openssl.cnf
##############################
# Create a test certificate #
##############################
# Create the request
openssl req -batch -config ./openssl.cnf -new -keyout test-certificate.key -out test-certificate.request -days 365 -passin pass:secret1 -passout pass:secret1
# Create the certificate
openssl ca -batch -config ./openssl.cnf -policy policy_anything -passin pass:secret1 -out test-certificate.pem -infiles test-certificate.request
# Cleanup request file
rm test-certificate.request
echo "test-certificate.pem has been generated."
##################################
# Sign a third party certificate #
##################################
# Create a key
openssl genrsa -des3 -passout pass:secret1 -out tmp.key 1024
# Remove the password from the key
cp tmp.key tmp.key.old
openssl rsa -in tmp.key.old -passin pass:secret1 -passout pass:secret1 -out tmp.key
rm tmp.key.old
# Sign the certificate with this key
openssl x509 -days 365 -in thirdparty.pem -signkey tmp.key -passin pass:secret1 -text -out thirdparty-signed.pem
# Remove tempfile
rm tmp.key
########################################
# Add the signed certificate to the CA #
########################################
# Create the certs dir if it doesn't already exist
mkdir -p CA/certs
# Copy our signed third party certificate
cp thirdparty-signed.pem CA/certs
# Create the hash-link
cd CA/certs
ln -s thirdparty-signed.pem `openssl x509 -hash -noout -in thirdparty-signed.pem`.0
cd -
#################################################
# Add the signed certificate to the CA database #
#################################################
openssl ca -config openssl.cnf -policy policy_anything -passin pass:secret1 -ss_cert thirdparty-signed.pem
####################
# Start the server #
####################
# Use test-certificate.pem as response signer.
openssl ocsp -CApath ./CA/certs -index CA/index.txt -port 5000 -rkey test-certificate.key -rsigner test-certificate.pem -CA CA/cacert.pem -text
# The client request:
# $ openssl ocsp -issuer CA/cacert.pem -VAfile test-certificate.pem -cert thirdparty.pem -url http://10.5.5.247:5000
# => Response verify OK
# => thirdparty.pem: unknown
# This Update: Apr 13 13:00:59 2010 GMT
openssl.cnf:
#
# OpenSSL example configuration file.
# This is mostly being used for generation of certificate requests.
#
# This definition stops the following lines choking if HOME isn't
# defined.
HOME = $ENV::HOME
RANDFILE= $ENV::HOME/.rnd
# Extra OBJECT IDENTIFIER info:
#oid_file= $ENV::HOME/.oid
oid_section= new_oids
# To use this configuration file with the "-extfile" option of the
# "openssl x509" utility, name here the section containing the
# X.509v3 extensions to use:
# extensions=
# (Alternatively, use a configuration file that has only
# X.509v3 extensions in its main [= default] section.)
[ new_oids ]
# We can add new OIDs in here for use by 'ca' and 'req'.
# Add a simple OID like this:
# testoid1=1.2.3.4
# Or use config file substitution like this:
# testoid2=${testoid1}.5.6
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = ./CA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
new_certs_dir = $dir/newcerts# default place for new certs.
certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem# The current CRL
private_key = $dir/private/cakey.pem # The private key
RANDFILE = $dir/private/.rand # private random number file
x509_extensions = usr_cert # The extentions to add to the cert
# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
# Extension copying option: use with caution.
# copy_extensions = copy
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions = crl_ext
default_days = 365 # how long to certify for
default_crl_days = 30 # how long before next CRL
default_md = sha1 # which md to use.
preserve = no # keep passed DN ordering
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy = policy_match
# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ req ]
default_bits = 1024
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
prompt = no
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
# Passwords for private keys if not present they will be prompted for
# input_password = secret
# output_password = secret
# This sets a mask for permitted string types. There are several options.
# default: PrintableString, T61String, BMPString.
# pkix: PrintableString, BMPString.
# utf8only: only UTF8Strings.
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
# MASK:XXXX a literal mask value.
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
# so use this option with caution!
string_mask = nombstr
# req_extensions = v3_req # The extensions to add to a certificate request
[ req_attributes ]
challengePassword = A challenge password
[ req_distinguished_name ]
C=DE
ST=Oost-Vlaanderen
L=Gent
O=Corp
OU=Testing Team
CN=johnsmith
emailAddress=john.smith@corp.com
[ usr_cert ]
# These extensions are added when 'ca' signs a request.
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:TRUE
# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.
# This is OK for an SSL server.
# nsCertType = server
# For an object signing certificate this would be used.
# nsCertType = objsign
# For normal client use this is typical
# nsCertType = client, email
# and for everything including object signing:
# nsCertType = client, email, objsign
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move
# Copy subject details
# issuerAltName=issuer:copy
#nsCaRevocationUrl= http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:TRUE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v3_ca ]
# Extensions for a typical CA
# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
# This is what PKIX recommends but some broken software chokes on critical
# extensions.
#basicConstraints = critical,CA:true
# So we do this instead.
basicConstraints = CA:true
# Key usage: this is typical for a CA certificate. However since it will
# prevent it being used as an test self-signed certificate it is best
# left out by default.
# keyUsage = cRLSign, keyCertSign
# Some might want this also
# nsCertType = sslCA, emailCA
# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
# issuerAltName=issuer:copy
# DER hex encoding of an extension: beware experts only!
# obj=DER:02:03
# Where 'obj' is a standard or added object
# You can even override a supported extension:
# basicConstraints= critical, DER:30:03:01:01:FF
[ crl_ext ]
# CRL extensions.
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always,issuer:always
[ proxy_cert_ext ]
# These extensions should be added when creating a proxy certificate
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:FALSE
# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.
# This is OK for an SSL server.
# nsCertType = server
# For an object signing certificate this would be used.
# nsCertType = objsign
# For normal client use this is typical
# nsCertType = client, email
# and for everything including object signing:
# nsCertType = client, email, objsign
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer:always
# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move
# Copy subject details
# issuerAltName=issuer:copy
#nsCaRevocationUrl= http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
# This really needs to be in place for it to be a proxy certificate.
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
[ my_v3_ext ]
basicConstraints = CA:true
thirdparty.pem:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
d9:6f:db:ad:33:69:ce:63
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=DE, ST=Berlin, L=Berlin, O=AVM GmbH, OU=Euro-DOCSIS, OU=Germany, CN=AVM GmbH Cable Modem Root Certificate Authority
Validity
Not Before: Jan 20 13:28:06 2010 GMT
Not After : Jun 7 13:28:06 2037 GMT
Subject: C=DE, O=AVM GmbH, OU=Euro-DOCSIS, CN=00:04:0E:C4:AE:94
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:d5:73:b6:23:c6:23:ff:97:25:84:21:b7:25:f1:
8f:f7:c1:ae:dc:13:ea:56:69:c1:f4:9c:74:d7:b8:
50:74:2b:0b:4c:56:0f:ab:8e:b3:8e:04:26:74:e6:
7c:8d:23:2e:34:74:6c:cc:d6:d6:81:b1:ba:1a:ed:
80:fa:fd:c5:65:09:23:5e:6d:b9:15:9e:52:9f:d2:
66:f7:3d:b9:4b:2b:ef:ab:80:72:26:47:24:17:35:
c9:2a:c7:df:53:a6:15:c0:f4:b7:bc:40:37:29:51:
c5:50:9a:90:d8:af:56:42:9a:07:3c:8c:77:f0:93:
09:c8:0b:52:7a:3d:64:5f:d9
Exponent: 65537 (0x10001)
Signature Algorithm: sha1WithRSAEncryption
27:64:a3:d5:76:d2:86:32:6e:c0:e5:45:39:1f:2a:1a:04:d9:
46:d9:92:ee:71:a1:7d:07:77:ac:1a:0f:2a:e2:a1:3c:d2:aa:
13:e2:df:55:6a:3c:93:54:e4:63:b8:5d:3c:6b:97:3b:b2:2e:
e6:c0:17:6c:6b:e2:0c:ea:66:48:42:02:f3:41:d2:cc:ca:ed:
64:a6:b9:78:97:b3:df:87:75:61:fb:86:49:18:03:86:7c:4c:
89:cc:ba:6b:6d:ad:6c:4b:da:ad:1c:65:b8:42:9d:ad:c5:b1:
35:60:36:b4:e2:1f:a3:c9:74:e4:34:3a:b5:d2:d6:1c:80:97:
4d:8f:b3:ab:c4:35:95:c4:ca:e5:93:2b:dc:36:54:51:04:d3:
ea:34:c6:2f:7b:fd:7e:24:04:35:9d:c2:6b:59:e0:ef:dc:0e:
6b:27:96:d3:9c:63:87:4d:c3:17:b6:4b:24:39:25:08:4e:d8:
0e:14:8f:a9:8d:63:ff:74:d3:62:de:d7:11:71:e6:fd:fc:94:
0d:77:27:9f:a3:e5:4c:84:9b:7a:d0:4b:6e:ba:b6:d5:35:9b:
97:2f:c4:ff:b9:6b:fa:de:50:2f:38:12:4f:40:2c:55:8c:e7:
db:42:fc:df:f9:65:74:52:81:42:b0:88:c8:9b:0f:9b:09:93:
de:ae:e1:19
-----BEGIN CERTIFICATE-----
MIIC9DCCAdygAwIBAgIJANlv260zac5jMA0GCSqGSIb3DQEBBQUAMIGkMQswCQYD
VQQGEwJERTEPMA0GA1UECBMGQmVybGluMQ8wDQYDVQQHEwZCZXJsaW4xETAPBgNV
BAoTCEFWTSBHbWJIMRQwEgYDVQQLEwtFdXJvLURPQ1NJUzEQMA4GA1UECxMHR2Vy
bWFueTE4MDYGA1UEAxMvQVZNIEdtYkggQ2FibGUgTW9kZW0gUm9vdCBDZXJ0aWZp
Y2F0ZSBBdXRob3JpdHkwHhcNMTAwMTIwMTMyODA2WhcNMzcwNjA3MTMyODA2WjBS
MQswCQYDVQQGEwJERTERMA8GA1UEChMIQVZNIEdtYkgxFDASBgNVBAsTC0V1cm8t
RE9DU0lTMRowGAYDVQQDExEwMDowNDowRTpDNDpBRTo5NDCBnzANBgkqhkiG9w0B
AQEFAAOBjQAwgYkCgYEA1XO2I8Yj/5clhCG3JfGP98Gu3BPqVmnB9Jx017hQdCsL
TFYPq46zjgQmdOZ8jSMuNHRszNbWgbG6Gu2A+v3FZQkjXm25FZ5Sn9Jm9z25Syvv
q4ByJkckFzXJKsffU6YVwPS3vEA3KVHFUJqQ2K9WQpoHPIx38JMJyAtSej1kX9kC
AwEAATANBgkqhkiG9w0BAQUFAAOCAQEAJ2Sj1XbShjJuwOVFOR8qGgTZRtmS7nGh
fQd3rBoPKuKhPNKqE+LfVWo8k1TkY7hdPGuXO7Iu5sAXbGviDOpmSEIC80HSzMrt
ZKa5eJez34d1YfuGSRgDhnxMicy6a22tbEvarRxluEKdrcWxNWA2tOIfo8l05DQ6
tdLWHICXTY+zq8Q1lcTK5ZMr3DZUUQTT6jTGL3v9fiQENZ3Ca1ng79wOayeW05xj
h03DF7ZLJDklCE7YDhSPqY1j/3TTYt7XEXHm/fyUDXcnn6PlTISbetBLbrq21TWb
ly/E/7lr+t5QLzgST0AsVYzn20L83/lldFKBQrCIyJsPmwmT3q7hGQ==
-----END CERTIFICATE-----
The command line utility using OpenCA libraries is written in C:
#include <libpki/pki.h>
PKI_X509_OCSP_REQ * CreateOCSPRequest(PKI_X509_CERT * cacert, long long serial)
{
PKI_X509_OCSP_REQ *request = NULL;
request = PKI_X509_OCSP_REQ_new();
if (request == NULL )
{
printf("Memory Errorequest!");
exit(1);
}
// Adds the details about certificate (serial issued by cacert)
if (PKI_X509_OCSP_REQ_add_longlong( request, serial, cacert, NULL) == PKI_ERR)
{
printf ("Can not add serial!");
exit (1);
}
if (PKI_X509_OCSP_REQ_add_nonce(request, 0) == PKI_ERR )
{
printf ("Can not add NONCE to REQUEST!");
exit(1);
}
return request;
}
PKI_X509_OCSP_RESP * CreateOCSPResponse(PKI_X509_OCSP_REQ *request, PKI_OCSP_CERTSTATUS ocspStatus)
{
PKI_X509_OCSP_RESP * resp = NULL;
PKI_OCSP_CERTID *cid = NULL;
// Create a new OCSP response
if ((resp = PKI_X509_OCSP_RESP_new()) == NULL)
{
printf("Memory allocation errorequest!\n");
exit (1);
}
// Now, let's set the status of the response
if (PKI_X509_OCSP_RESP_set_status(resp, PKI_X509_OCSP_RESP_STATUS_SUCCESSFUL) == PKI_ERR)
{
printf("ERROR: setting response status failed.\n");
exit (1);
}
printf ("Set response status.\n");
// We now want to copy the NONCE from the request...
if (PKI_X509_OCSP_RESP_copy_nonce(resp, request) == PKI_ERR)
{
printf("ERROR::can not copy NONCE!!!\n");
exit (1);
}
printf ("Added NONCE.\n");
// We also need the Certificate Identifier from the request
if ((cid = PKI_X509_OCSP_REQ_get_cid(request, 0)) == NULL)
{
printf("Can not get CID from request!\n");
exit (1);
}
// Let's add the status of the requested certificate to the response
int ret = PKI_ERR;
if (ocspStatus == PKI_OCSP_CERTSTATUS_REVOKED)
{
PKI_TIME * revocationTime = PKI_TIME_new(0);
PKI_TIME * thisUpdate = PKI_TIME_new(100);
PKI_TIME * nextUpdate = PKI_TIME_new(200);
ret = PKI_X509_OCSP_RESP_add(resp, cid, ocspStatus, revocationTime, thisUpdate, nextUpdate, CRL_REASON_KEY_COMPROMISE, NULL);
PKI_TIME_free(revocationTime);
PKI_TIME_free(thisUpdate);
PKI_TIME_free(nextUpdate);
}
else
{
ret = PKI_X509_OCSP_RESP_add(resp, cid, ocspStatus, NULL, NULL, NULL, CRL_REASON_UNSPECIFIED, NULL);
}
if (ret == PKI_ERR)
{
printf("Add CID to response failed!\n");
exit (1);
}
printf ("Added CID.\n");
return resp;
}
PKI_X509_CERT * ReadCertificate(char * file)
{
PKI_X509_CERT * cert = NULL;
if ((cert = PKI_X509_CERT_get(file, NULL, NULL)) == NULL)
{
printf("Failed to load certificate: %s\n", file);
exit(1);
}
return cert;
}
void SignResponse(PKI_X509_OCSP_RESP * resp)
{
PKI_X509_KEYPAIR * keyPair = PKI_X509_KEYPAIR_get("root.key", NULL, NULL);
if (!keyPair)
{
printf("Obtaining keypair from root.key failed!");
exit (1);
}
PKI_X509_CERT * caCertificate = ReadCertificate("CA/cacert.pem");
PKI_X509_CERT * signerCertificate = ReadCertificate("root.pem");
PKI_X509_OCSP_RESP_sign(resp, keyPair, signerCertificate, caCertificate, NULL, NULL);
}
void genresponse(PKI_OCSP_CERTSTATUS ocspStatus)
{
PKI_X509_OCSP_REQ *request = NULL;
PKI_X509_OCSP_RESP * resp = NULL;
PKI_X509_CERT * cacert = NULL;
PKI_TOKEN * tk = NULL;
if ((request = PKI_X509_OCSP_REQ_get("req.der", NULL, NULL)) == NULL)
{
printf("ERROR, can't load req.der!\n");
exit(1);
}
resp = CreateOCSPResponse(request, ocspStatus);
// Now sign the response
SignResponse(resp);
printf("Response has been signed.\n");
PKI_X509_OCSP_RESP_put(resp, PKI_DATA_FORMAT_ASN1, "resp.der", NULL, NULL, NULL);
printf("Response file resp.der has been written.\n");
}
void genrequest(long long serial)
{
PKI_X509_OCSP_REQ *request = NULL;
PKI_X509_OCSP_RESP * resp = NULL;
PKI_X509_CERT * cacert = NULL;
if ((cacert = PKI_X509_CERT_get("cacert.pem", NULL, NULL)) == NULL)
{
printf("ERROR, can not load cacert.pem!\n");
exit(1);
}
request = CreateOCSPRequest(cacert, serial);
PKI_X509_OCSP_REQ_put(request, PKI_DATA_FORMAT_ASN1, "req.der", NULL, NULL, NULL);
printf("req.der written.\n");
}
void PrintUsage()
{
printf("Usage: ocsp { genrequest <serial> | genresponse <good | revoked | unknown> } \n");
}
/**
* Main function
*
*/
int main(int argc, char** argv)
{
PKI_init_all();
if (argc < 3)
{
PrintUsage();
exit(1);
}
if (0 == strcmp(argv[1], "genrequest"))
{
long long serial = 0;
sscanf(argv[2], "%lld", &serial);
genrequest(serial);
}
else if (0 == strcmp(argv[1], "genresponse"))
{
PKI_OCSP_CERTSTATUS certStatus = -1;
if (0 == strcmp(argv[2], "good"))
{
certStatus = PKI_OCSP_CERTSTATUS_GOOD;
}
else if (0 == strcmp(argv[2], "revoked"))
{
certStatus = PKI_OCSP_CERTSTATUS_REVOKED;
}
else if (0 == strcmp(argv[2], "unknown"))
{
certStatus = PKI_OCSP_CERTSTATUS_UNKNOWN;
}
else
{
printf("Unknown response type: %s.\n", argv[2]);
PrintUsage();
exit(1);
}
genresponse(certStatus);
}
else
{
PrintUsage();
exit(1);
}
return 0;
}
It's hard to give specific advice from what you've posted here but I do have some generic advice based on a post I wrote ages ago back when I could still be bothered to blog.
Don't Panic
First things first, there are no "quick fixes" other than restoring your system from a backup taken prior to the intrusion, and this has at least two problems.
- It's difficult to pinpoint when the intrusion happened.
- It doesn't help you close the "hole" that allowed them to break in last time, nor deal with the consequences of any "data theft" that may also have taken place.
This question keeps being asked repeatedly by the victims of hackers breaking into their web server. The answers very rarely change, but people keep asking the question. I'm not sure why. Perhaps people just don't like the answers they've seen when searching for help, or they can't find someone they trust to give them advice. Or perhaps people read an answer to this question and focus too much on the 5% of why their case is special and different from the answers they can find online and miss the 95% of the question and answer where their case is near enough the same as the one they read online.
That brings me to the first important nugget of information. I really do appreciate that you are a special unique snowflake. I appreciate that your website is too, as it's a reflection of you and your business or at the very least, your hard work on behalf of an employer. But to someone on the outside looking in, whether a computer security person looking at the problem to try and help you or even the attacker himself, it is very likely that your problem will be at least 95% identical to every other case they've ever looked at.
Don't take the attack personally, and don't take the recommendations that follow here or that you get from other people personally. If you are reading this after just becoming the victim of a website hack then I really am sorry, and I really hope you can find something helpful here, but this is not the time to let your ego get in the way of what you need to do.
You have just found out that your server(s) got hacked. Now what?
Do not panic. Absolutely do not act in haste, and absolutely do not try and pretend things never happened and not act at all.
First: understand that the disaster has already happened. This is not the time for denial; it is the time to accept what has happened, to be realistic about it, and to take steps to manage the consequences of the impact.
Some of these steps are going to hurt, and (unless your website holds a copy of my details) I really don't care if you ignore all or some of these steps, that's up to you. But following them properly will make things better in the end. The medicine might taste awful but sometimes you have to overlook that if you really want the cure to work.
Stop the problem from becoming worse than it already is:
- The first thing you should do is disconnect the affected systems from the Internet. Whatever other problems you have, leaving the system connected to the web will only allow the attack to continue. I mean this quite literally; get someone to physically visit the server and unplug network cables if that is what it takes, but disconnect the victim from its muggers before you try to do anything else.
- Change all your passwords for all accounts on all computers that are on the same network as the compromised systems. No really. All accounts. All computers. Yes, you're right, this might be overkill; on the other hand, it might not. You don't know either way, do you?
- Check your other systems. Pay special attention to other Internet facing services, and to those that hold financial or other commercially sensitive data.
- If the system holds anyone's personal data, immediately inform the person responsible for data protection (if that's not you) and URGE a full disclosure. I know this one is tough. I know this one is going to hurt. I know that many businesses want to sweep this kind of problem under the carpet but the business is going to have to deal with it - and needs to do so with an eye on any and all relevant privacy laws.
However annoyed your customers might be to have you tell them about a problem, they'll be far more annoyed if you don't tell them, and they only find out for themselves after someone charges $8,000 worth of goods using the credit card details they stole from your site.
Remember what I said previously? The bad thing has already happened. The only question now is how well you deal with it.
Understand the problem fully:
- Do NOT put the affected systems back online until this stage is fully complete, unless you want to be the person whose post was the tipping point for me actually deciding to write this article. I'm not going to link to that post so that people can get a cheap laugh, but the real tragedy is when people fail to learn from their mistakes.
- Examine the 'attacked' systems to understand how the attacks succeeded in compromising your security. Make every effort to find out where the attacks "came from", so that you understand what problems you have and need to address to make your system safe in the future.
- Examine the 'attacked' systems again, this time to understand where the attacks went, so that you understand what systems were compromised in the attack. Ensure you follow up any pointers that suggest compromised systems could become a springboard to attack your systems further.
- Ensure the "gateways" used in any and all attacks are fully understood, so that you may begin to close them properly. (e.g. if your systems were compromised by a SQL injection attack, then not only do you need to close the particular flawed line of code that they broke in by, you would want to audit all of your code to see if the same type of mistake was made elsewhere).
- Understand that attacks might succeed because of more than one flaw. Often, attacks succeed not through finding one major bug in a system but by stringing together several issues (sometimes minor and trivial by themselves) to compromise a system. For example, using SQL injection attacks to send commands to a database server, discovering the website/application you're attacking is running in the context of an administrative user and using the rights of that account as a stepping-stone to compromise other parts of a system. Or as hackers like to call it: "another day in the office taking advantage of common mistakes people make".
Why not just "repair" the exploit or rootkit you've detected and put the system back online?
In situations like this the problem is that you don't have control of that system any more. It's not your computer any more.
The only way to be certain that you've got control of the system is to rebuild the system. While there's a lot of value in finding and fixing the exploit used to break into the system, you can't be sure about what else has been done to the system once the intruders gained control (indeed, its not unheard of for hackers that recruit systems into a botnet to patch the exploits they used themselves, to safeguard "their" new computer from other hackers, as well as installing their rootkit).
Make a plan for recovery and to bring your website back online and stick to it:
Nobody wants to be offline for longer than they have to be. That's a given. If this website is a revenue generating mechanism then the pressure to bring it back online quickly will be intense. Even if the only thing at stake is your / your company's reputation, this is still going generate a lot of pressure to put things back up quickly.
However, don't give in to the temptation to go back online too quickly. Instead move with as fast as possible to understand what caused the problem and to solve it before you go back online or else you will almost certainly fall victim to an intrusion once again, and remember, "to get hacked once can be classed as misfortune; to get hacked again straight afterward looks like carelessness" (with apologies to Oscar Wilde).
- I'm assuming you've understood all the issues that led to the successful intrusion in the first place before you even start this section. I don't want to overstate the case but if you haven't done that first then you really do need to. Sorry.
- Never pay blackmail / protection money. This is the sign of an easy mark and you don't want that phrase ever used to describe you.
- Don't be tempted to put the same server(s) back online without a full rebuild. It should be far quicker to build a new box or "nuke the server from orbit and do a clean install" on the old hardware than it would be to audit every single corner of the old system to make sure it is clean before putting it back online again. If you disagree with that then you probably don't know what it really means to ensure a system is fully cleaned, or your website deployment procedures are an unholy mess. You presumably have backups and test deployments of your site that you can just use to build the live site, and if you don't then being hacked is not your biggest problem.
- Be very careful about re-using data that was "live" on the system at the time of the hack. I won't say "never ever do it" because you'll just ignore me, but frankly I think you do need to consider the consequences of keeping data around when you know you cannot guarantee its integrity. Ideally, you should restore this from a backup made prior to the intrusion. If you cannot or will not do that, you should be very careful with that data because it's tainted. You should especially be aware of the consequences to others if this data belongs to customers or site visitors rather than directly to you.
- Monitor the system(s) carefully. You should resolve to do this as an ongoing process in the future (more below) but you take extra pains to be vigilant during the period immediately following your site coming back online. The intruders will almost certainly be back, and if you can spot them trying to break in again you will certainly be able to see quickly if you really have closed all the holes they used before plus any they made for themselves, and you might gather useful information you can pass on to your local law enforcement.
Reducing the risk in the future.
The first thing you need to understand is that security is a process that you have to apply throughout the entire life-cycle of designing, deploying and maintaining an Internet-facing system, not something you can slap a few layers over your code afterwards like cheap paint. To be properly secure, a service and an application need to be designed from the start with this in mind as one of the major goals of the project. I realise that's boring and you've heard it all before and that I "just don't realise the pressure man" of getting your beta web2.0 (beta) service into beta status on the web, but the fact is that this keeps getting repeated because it was true the first time it was said and it hasn't yet become a lie.
You can't eliminate risk. You shouldn't even try to do that. What you should do however is to understand which security risks are important to you, and understand how to manage and reduce both the impact of the risk and the probability that the risk will occur.
What steps can you take to reduce the probability of an attack being successful?
For example:
- Was the flaw that allowed people to break into your site a known bug in vendor code, for which a patch was available? If so, do you need to re-think your approach to how you patch applications on your Internet-facing servers?
- Was the flaw that allowed people to break into your site an unknown bug in vendor code, for which a patch was not available? I most certainly do not advocate changing suppliers whenever something like this bites you because they all have their problems and you'll run out of platforms in a year at the most if you take this approach. However, if a system constantly lets you down then you should either migrate to something more robust or at the very least, re-architect your system so that vulnerable components stay wrapped up in cotton wool and as far away as possible from hostile eyes.
- Was the flaw a bug in code developed by you (or a contractor working for you)? If so, do you need to re-think your approach to how you approve code for deployment to your live site? Could the bug have been caught with an improved test system, or with changes to your coding "standard" (for example, while technology is not a panacea, you can reduce the probability of a successful SQL injection attack by using well-documented coding techniques).
- Was the flaw due to a problem with how the server or application software was deployed? If so, are you using automated procedures to build and deploy servers where possible? These are a great help in maintaining a consistent "baseline" state on all your servers, minimising the amount of custom work that has to be done on each one and hence hopefully minimising the opportunity for a mistake to be made. Same goes with code deployment - if you require something "special" to be done to deploy the latest version of your web app then try hard to automate it and ensure it always is done in a consistent manner.
- Could the intrusion have been caught earlier with better monitoring of your systems? Of course, 24-hour monitoring or an "on call" system for your staff might not be cost effective, but there are companies out there who can monitor your web facing services for you and alert you in the event of a problem. You might decide you can't afford this or don't need it and that's just fine... just take it into consideration.
- Use tools such as tripwire and nessus where appropriate - but don't just use them blindly because I said so. Take the time to learn how to use a few good security tools that are appropriate to your environment, keep these tools updated and use them on a regular basis.
- Consider hiring security experts to 'audit' your website security on a regular basis. Again, you might decide you can't afford this or don't need it and that's just fine... just take it into consideration.
What steps can you take to reduce the consequences of a successful attack?
If you decide that the "risk" of the lower floor of your home flooding is high, but not high enough to warrant moving, you should at least move the irreplaceable family heirlooms upstairs. Right?
- Can you reduce the amount of services directly exposed to the Internet? Can you maintain some kind of gap between your internal services and your Internet-facing services? This ensures that even if your external systems are compromised the chances of using this as a springboard to attack your internal systems are limited.
- Are you storing information you don't need to store? Are you storing such information "online" when it could be archived somewhere else. There are two points to this part; the obvious one is that people cannot steal information from you that you don't have, and the second point is that the less you store, the less you need to maintain and code for, and so there are fewer chances for bugs to slip into your code or systems design.
- Are you using "least access" principles for your web app? If users only need to read from a database, then make sure the account the web app uses to service this only has read access, don't allow it write access and certainly not system-level access.
- If you're not very experienced at something and it is not central to your business, consider outsourcing it. In other words, if you run a small website talking about writing desktop application code and decide to start selling small desktop applications from the site then consider "outsourcing" your credit card order system to someone like Paypal.
- If at all possible, make practicing recovery from compromised systems part of your Disaster Recovery plan. This is arguably just another "disaster scenario" that you could encounter, simply one with its own set of problems and issues that are distinct from the usual 'server room caught fire'/'was invaded by giant server eating furbies' kind of thing.
... And finally
I've probably left out no end of stuff that others consider important, but the steps above should at least help you start sorting things out if you are unlucky enough to fall victim to hackers.
Above all: Don't panic. Think before you act. Act firmly once you've made a decision, and leave a comment below if you have something to add to my list of steps.
Related Topic
- Security – Our security auditor is an idiot. How to give him the information he wants
- Ssh – How to get OpenSSH to use OCSP for revocation
- IIS ocsp stapling – no response
- OCSP responder not present
- Ssl – OCSP server suggests trying again later
- Online Certificate Status Protocol (OCSP) and Port 80
- OCSP – How Does OCSP Handle Deleted Certificates?
Best Answer
The best free OCSP server is in the OpenCA package. Here is an example of creating a custom OCSP message. If you like java then you should use EJBCA.
I think windows has an OCSP server in the windows 2008 enterprise edition. I know it has other parts of the PKI. This isn't free.