OWASP Enterprise Security API
(ESAPI)
Zehra Saadet Öztürk Oksijen ARGE
2 12 June 2012
ESAPI nedir?
>
Web uygulamaları için güvenlik kontrol kütüphanesi
> Güvenlik problemlerini gidermek için arayüzleri sağlar
> Java, .Net, ASP, PHP, Phyton, Javascript,C , CPP sürümleri vardır
> Ücretsiz, açık kaynak kodlu
ESAPI
Custom Enterprise Web Application
Enterprise Security API
A u th en ti ca tor U se r A cc es sCon tr ol le r A cc es sR efe re n ce M a p V a lid a tor E n cod er H T T P U ti lit ie s E n cr yp tor E n cr yp te d P rop er ti es R a n d omi ze r E x ce p ti on Ha n d lin g Log g er In tr u si on D et ec tor S ec u ri ty Con fi g u ra ti o n
ESAPI Girdi Doğrulama
> W hite List Validation
> Canonicalize
> Intrusion Detection
> Örnek metodlar > getValidSafeHTML > getValidDate > getValidNumber > getValidFileContent > getValidFileName > getValidCreditCard > isValidFileUpload > isValidHTTPRequestParameterSet 12 June 2012ESAPI Girdi Doğrulama
<
Percent Encoding %3c %3C HTML Entity Encoding < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < &lT &Lt < < &lT; ≪ < JavaScript Escape \< \x3c \U003C CSS Escape \3c \03c \003c \0003c \00003c \3C \03C \003C \0003C \00003C Overlong UTF-8 %c0%bc %e0%80%bc %f0%80%80%bc %f8%80%80%80%bc %fc%80%80%80%80 %bc US-ASCII ¼ESAPI Girdi Doğrulama
> getValidInput > validation.properties > Validator.MSISDN=^(9054[0-9]{8}|9050[0-9]{8}|9053[0-9]{8}|9055[0-9]{8})$ > Validator.employeeID=^([A-Za-z0-9]{20,50})$ +isValidInput() +...() «interface» Validator +isValidInput() +...() +isValidEmployeeID() MyValidator +isValidInput() +...()DefaultValidator ESAPI reference
implementation (does not include a
“isValidEmployeeID” function) ESAPI interface
Your implementation (has additional and/or perhaps changed functions compared to reference implementation)
May also be modified
try {
String cleanMarkup = ESAPI.validator().getValidSafeHTML(
"htmlInput", htmlInput, 1000, true);
String cleanMsisdn = ESAPI.validator().getValidInput(
"msisdn:"+msisdnInput, msisdnInput, "MSISDN", 12, false);
String cleanPassword = ESAPI.validator().getValidInput(
"pwd:" + pwdInput, pwdInput, "pwdWhiteList", 15, true);
} catch (ValidationException e) {
logger.error("[Validation Failed]" + e.getMessage());
} catch (IntrusionException e) {
logger.error("[Intrusion] " + e.getMessage());
}
ESAPI Çıktı Kodlama (Output Encoding)
>Çıktı Kodlaması yaparken...> Hedef Yorumlayıcı & doğru kodlama metodu > Hangi karakterler? > Double encoding! > encodeForJavaScript(String input) > encodeForHTML(String input) > encodeForCSS(String input) > encodeForLDAP(String input) > encodeForXPath(String input) > encodeForXML(String input) > String canonicalize(String input)
Rule #0 : Never Insert Untrusted Data Except Allowed Locations
Rule #1: HTML escape in HTML Element Content
ESAPI.encoder.
encodeForHTML(input)
Rule #2: Atribute escape in HTML Common Attributes
ESAPI.encoder.
encodeForHTMLAttribute(input)
Rule #3: Javascript Escape in HTML Javascript Data Values
ESAPI.encoder.
encodeForJavaScript(input)
Rule #4: CSS Escape HTML Style Property Values
ESAPI.encoder.
encodeForCSS(input)
Rule #5: URL Escape HTML URL Attributes
ESAPI.encoder.
encodeForURL(input)
<script> x=<%=request.getParameter( "input")%> </script> <Table> <TR> <TD>Full Name:</TD> <TD><%=user.getFirstName()%> <%=user.getLastName()%></TD> <TD> <a href= ‘sendMessage?userId= <%=user.getId()%> >Send Message</a> </TD>
ESAPI Çıktı kodlama – XSS
<script> x=<%=ESAPI.encoder() .encodeForJavaScript( request.getParameter( "input"))%> </script> <Table><TR> <TD> Full Name:</TD> <TD> <%=ESAPI.encodeForHTML( user.getFirstName())%> <%= ESAPI.encodeForHTML( user.getLastName())%></TD> <TD><a href= ‘sendMessage?userId= <%=ESAPI.encoder().encodeFor URL(user.getId()%>)’ >Send Message</a> </TD> 12 June 2012ESAPI Kodlama – Örnek: SQL Injection
> encodeForSQL tavsiye edilmeyen bir yöntem
>
Asıl yapılması gereken PreparedStatement kullanmak
String query = "SELECT account_balance FROM user_data WHERE
user_name = " + request.getParameter("customerName");
String query = "SELECT account_balance FROM user_data WHERE
user_name = " + ESAPI.encoder().encodeForSQL(new
12 12 June 2012
Kullanıcı Doğrulama (Authentication)
> ESAPI.properties
– ESAPI.Authenticator=org.owasp.esapi.reference.FileBasedAuthenticator – ESAPI.Authenticator=com.vodafone.myapp.auth.MyAuthenticator +login() +...() «interface» Authenticator +login() +...() MyAuthenticator +login() +...() DefaultAuthenticator ESAPI reference implementation ESAPI interface Your implementation (has the same functions as reference implementation)Kullanıcı Doğrulama (Authentication)
>
Kullanıcı yaratma
– Kullanıcı adı ve şifre güçlülüğünü sınama
– Password hash (sha2 hash & username salt )
User user =
ESAPI.
authenticator().createUser(
"saadet"
,
"Password1?"
,
"Password1?"
);
14 12 June 2012
Kullanıcı Doğrulama (Authentication)
> Login
– Ip değişikliği yakalama
– Session Id değiştirilmesi
– Fazla denemede hesap kilitleme
– Beni hatırla
– not POST, non-SSL
User user =
ESAPI.
authenticator().login(httpServletRequest,
httpServletResponse);
Kullanıcı Doğrulama (Authentication)
ESAPI.
authenticator().getUser(
"saadet"
).lock();
ESAPI.
authenticator().getUser(
"saadet"
).disable();
ESAPI.
authenticator().verifyPasswordStrength(
"oldP
assword"
,
"newPassword"
,
ESAPI.authenticator().getUser(
"saadet"
));
16 12 June 2012
Erişim Kontrolleri (Access Control)
> assertAuthorizedForURL(java.lang.String url)
> assertAuthorizedForFunction(java.lang.String functionName)
> assertAuthorizedForService(java.lang.String serviceName)
> Indirect Object reference
Erişim Kontrolleri (Access Control)
URLAccessRules.txt
/MyApp/userList.action | any | allow | /MyApp/userEdit.action | admin | allow | /MyApp/userDelete.action | standart | deny |
try {
ESAPI.accessController().assertAuthorizedForURL(
request.getRequestURI());
return actionInvocation.invoke(); } catch (AccessControlException e) {
logger.info(null, "[AuthorizationInterceptor] User is
not authorized for url:" + request.getRequestURI());
> Linke CSRF token ekleme
><a
href='<%=ESAPI.httpUtilities().addCSRFToken(‘/myapp’)%>
' target="_blank">Transfer Funds</a>
>
Linke tıklandığında CSRF token doğrulama
try {
ESAPI.httpUtilities().verifyCSRFToken();
logger.debug("CSRF Token Validated ");
} catch (IntrusionException e) {
logger.fatal(Logger.SECURITY_FAILURE, "[Intrusion]
CSRF Token Not Validated "+e.getLogMessage());
return e.getUserMessage(); }
12 June 2012 18
Oturum Yönetimi
> Oturum Sabitleme (Session Fixation) Zaafiyeti
>
Oturum anahtarının saldırgan tarafından kullanıcıya kabul
ettirilmesi
20 ESAPI 12 June 2012
ESAPI Kriptorafi
Encryptor Interface
> String hash(String plainText, String salt) (sha-2) > CipherText encrypt(SecretKey key, PlainText plain)
> CipherText encrypt(PlainText plain) ( Masterkey in ESAPI.prop) > PlainText decrypt(CipherText ciphertext)
> PlainText decrypt(SecretKey key, CipherText ciphertext) > String seal(java.lang.String data, long timestamp)
> String unseal(java.lang.String seal)
ESAPI Kriptorafi
Randomizer Interface
> boolean getRandomBoolean()
> String getRandomFilename(String extension) > String getRandomGUID()
> int getRandomInteger(int min, int max) > long getRandomLong()
> loat getRandomReal(float min, float max)
22 12 June 2012
ESAPI Loglama
private static final Logger logger = ESAPI.getLogger(TransferFunds.class);
logger.fatal(Logger.SECURITY_FAILURE, "[Intrusion] CSRF Token Not Validated "+e.getLogMessage());
>Etiketleme mekanizması: SECURITY_SUCCESS, SECURITY_FAILURE, EVENT_SUCCESS, EVENT_FAILURE
> Encode CRLF
> Encode HTML characters
ESAPI HTTP Utilities
> ESAPI.httpUtilities().setNoCacheHeaders() > Reader.readLine() -> Validator.safeReadLine() > Math.Random.* -> Randomizer.* > ServletResponse.setContentType() -> HTTPUtilities.setContentType() > ServletResponse.sendRedirect() -> HTTPUtilities.sendSafeRedirect() > RequestDispatcher.forward() -> HTTPUtilities.sendSafeForward() > ServletResponse.addHeader() -> HTTPUtilities.addSafeHeader() > ServletResponse.addCookie() -> HTTPUtilities.addSafeCookie() > ServletRequest.isSecure() -> HTTPUtilties.isSecureChannel()> ServletResponse.encodeURL -> HTTPUtilities.safeEncodeURL (better not to use at all)
> ServletResponse.encodeRedirectURL -> HTTPUtilities.safeEncodeRedirectURL (better not to use at all)
26 12 June 2012
ESAPI Girdi Doğrulama
> getValidSafeHTML(String context, String input, int maxLength, boolean allowNull)
> getValidDate(String context, String input, java.text.DateFormat format, boolean allowNull)
> getValidNumber(String context, String input, long minValue, long maxValue, boolean allowNull)
> getValidFileContent(String context, byte[] input, int maxBytes, boolean allowNull) > getValidFileName(String context, String input, boolean allowNull)
> boolean getValidCreditCard(String context, String input, boolean allowNull) > isValidFileUpload(String context, String filepath, String filename, byte[] content,
ESAPI Girdi & Çıktı Denetimi
Backend
Controller Business
Functions
User Data Layer
Validator Encoder encodeForURL
encodeForJavaScript encodeForVBScript encodeForDN encodeForHTML encodeForHTMLAttribute encodeForLDAP encodeForSQL encodeForXML encodeForXMLAttribute encodeForXPath getValidDirectoryPath getValidCreditCard getValidDirectoryPath getValidFileContent getValidFileName getValidInput getValidRedirectLocation getValidDate getValidPrintable safeReadLine Canonicalization
Double Encoding Protection Normalization