Monday, November 16, 2015

Agile teams and security master role

Many companies develop with agile teams, like scrum teams. In the same time  security challenges lead to adding new members in the security team. Still,  the security of the code does not improve as requested.


The pure classical approach has a problem: Security and developer do not speak the same language and misunderstand frequently.  The results is silos- acting, isolation, finger pointing etc.

 The elegant solution is to build a security master in every developer team:
  • Developer -  part of the team that can answer concrete engineering questions on daily bases
  • Doted line report to security engineering  (20%-40% of yearly goes)
  • Organic member – take an existing team member and build him to become security expert -    Security Trainings, Certification and Conferences etc.
  • The Sec Master must not be: the worst coder that the team gladly will spare for security. He must be highly credible and respected.
  • It has to report or escalate if serious security issues are coming in the developing
 Still, the you need:
  • Security engineering department for security intensive projects, like Firewalls etc 
  • Security Archotect
  • Security Quality Assurance and IT Risk 
  • Chef IT Security Officer 
  • Security Operation
  • all other security relevant departments, see ISO 27000 for more info 


How the organization is may look like, it is up to company. Here a simplified  example showing only some departments.








Sunday, October 25, 2015

Active scripts with ZAP OWASP and ECMAScript

Active scripts with ZAP OWASP are excellent extension for custom test depending on you application logic. You want to use solid test, it is better to use Java plugins. Still, if you want to make fast test without investing many efforts scripting is the best option.

Before you being you need to know some small tricks
  • if the script fails, it will be disabled. Look at the icon after the run.
  • scripts can be activated and deactivate in the policy menu. During the development it is good to disable all other rules and test only the active scripts.
  • you need to import some Java classes in Java Script (ECMAScrip Rhino). Rhino gives you  the possibility to use Java classes in you Java Script parts and this is very powerful.
  • If you don't know which Java classes you need, have look at ZAP sources
  • Like ever script most useful way is try and error. You do not have in ZAP  big debugging possibilities besides println.


I used ECMAScript (JavaSript) - Rhino but in previous blogs I used python, so feel free.

Here the important part of the script

Adding a custom header


 // set a additional Header
   httpRequestHeader = msg.getRequestHeader();
   httpRequestHeader.setHeader("additonalHeader","valueHeader");
   msg.setRequestHeader(httpRequestHeader); 

Adding a custom URL parameter

// add URL params
importClass(org.apache.commons.httpclient.URI);

 uri=httpRequestHeader.getURI();
 query=uri.getQuery();
 
   // check if query string is empty 
   if (query!="") {
     query=query+"&testParam=Values";
   } else {
     query=query+"testParam=Value"; 
 }
   newURI=org.apache.commons.httpclient.URI(uri.getScheme() , null , uri.getHost(),uri.getPort(), uri.getPath(), query, uri.getFragment());
   httpRequestHeader.setURI(newURI); 

adding a custom test (new line) to POST requests

 // append a new line to the HttpBody
importClass(org.zaproxy.zap.network.HttpRequestBody);

   if (msg.getRequestHeader().getMethod()=="POST") {
     newBody=org.zaproxy.zap.network.HttpRequestBody(msg.getRequestBody().toString() +  "\nMy Added HttpBody");
     msg.setRequestBody(newBody);
 }
After you send the packet

check if the response body contains some string


 // get response Body 
 rsp=msg.getResponseBody().toString();

 // see if conatins certain string 
 if (rsp.indexOf("Potental attack")>-1) {
  println('The response body contains the dangerous sting ""'); 
you can clone the request again and send second packet if the attack you are testing consist of multiple packets


A small example with all part can be seen below:

Enjoy 



importClass(org.zaproxy.zap.network.HttpRequestBody);
importClass(org.apache.commons.httpclient.URI);

function scanNode(as, msg) {
 // Debugging can be done using println like this


// importPackage(org.apache.commons.httpclient.URI);

 println('scan called for url=' + msg.getRequestHeader().getURI().toString());

 // Copy requests before reusing them
 msg = msg.cloneRequest();

     // set a additional Header
   httpRequestHeader = msg.getRequestHeader();
   httpRequestHeader.setHeader("additonalHeader","valueHeader");
   msg.setRequestHeader(httpRequestHeader);
 
 uri=httpRequestHeader.getURI();
 query=uri.getQuery();
 
   // check if query string is empty 
   if (query!="") {
     query=query+"&testParam=Values";
   } else {
     query=query+"testParam=Value"; 
 }
   newURI=org.apache.commons.httpclient.URI(uri.getScheme() , null , uri.getHost(),uri.getPort(), uri.getPath(), query, uri.getFragment());
   httpRequestHeader.setURI(newURI);


   // append a new line to the HttpBody
   if (msg.getRequestHeader().getMethod()=="POST") {
     newBody=org.zaproxy.zap.network.HttpRequestBody(msg.getRequestBody().toString() +  "\nMy Added HttpBody");
     msg.setRequestBody(newBody);
 }

 // sendAndReceive(msg, followRedirect, handleAntiCSRFtoken)
 as.sendAndReceive(msg, false, false);

 // get response Body 
 rsp=msg.getResponseBody().toString();

 // see if conatins certain string 
 if (rsp.indexOf("opengraphprotoco")>-1) {
  println('The response body contains the sting "opengraphprotoco"');

  // sending a second messge
  
  // Copy requests before reusing them
  msgSecond = msg.cloneRequest();

   // set a additional Header
    httpRequestHeader = msgSecond.getRequestHeader();
    httpRequestHeader.setHeader("additonalHeader-Second","valueHeader-Second");
    msgSecond.setRequestHeader(httpRequestHeader);
   
  as.sendAndReceive(msgSecond, false, false);

  // get response Header 
  rspSecond=msgSecond.getResponseHeader().toString();

  // see if conatins certain string 
  if (rspSecond.indexOf("Server: nginx")>-1) {

   // raise an Alert
   // raiseAlert(risk, int confidence, String name, String description, String uri, 
   //  String param, String attack, String otherInfo, String solution, String evidence, 
   //  int cweId, int wascId, HttpMessage msg)
   // risk: 0: info, 1: low, 2: medium, 3: high
   // confidence: 0: falsePositive, 1: low, 2: medium, 3: high, 4: confirmed

   as.raiseAlert(1, 1, 'My Test Vulnarability ', 'My Test vulnarability', msg.getRequestHeader().getURI().toString(), 
   query, 'Your attack', 'Any other info', 'The solution ', '', 0, 0, msg);
  }
 }

 // Test the responses and raise alerts as below
 msg.add
 // Check if the scan was stopped before performing lengthy tasks
 if (as.isStop()) {
  return
 }
 // Do lengthy task...
}

Saturday, October 17, 2015

TCP data dumping - troubleshooting HTTP, REST and SAOP using port forwarding

Many times, application developer needs to understand what is transmitted between client and server (trouble shooting) . This could be the case in HTTP, WS Soap, RESTful API etc. For example search for missing headers, character encoding etc. 

It is a problem if you do not have root (or sudo) on the OS, so you can not use tcpdump, wireshark, snoop etc. You can achieve this by adding application server interceptors, but this is sometimes tricky and may take time. 

An easy way to solve this - port forwarding with mirroring the transmitted data to standard out (dump to standard out).  You don't need to be root (or similar) on the OS, but only control the client application conifg

Typical set up:




In order to take the trace you need change to this constellation





You need a simple java jar that forks and dumps the datagrams/messages to the std out in parallel to forwarding them. You can download the jar here

tcpport_forwarder_dumper.jar


Since it is public git project, feel free to improve.

https://github.com/tzvetkov75/tcpport_forwarder_dumper/blob/master/build/tcpport_forwarder_dumper.jar

Here are the step:

1. Run the port forward jar at the some local port. For the example above, port 2222 at the client machine, like in this  example:  

java -jar tcpport_forwarder_dumper.jar 2222 192.168.1.2:1234   

The result is that every connection on local port 2222 is forwarded to server destination (192.168.1.2:1234 at example)


2. Change the client application to connect to tcp forwarder instead of the server. At the example port 2222 on the same machine as the client 

3. Start to communicate and you will see datagrams to the std-out

TLS (HTTPS) is is not possible to ready even you dump it out ;-)

Enjoy, here an example


/build$ java -jar tcpport_forwarder_dumper.jar 2222 www.cnet.com:80
TCP Port forwarding - content logger (dummper to stdout) v0.1 vesselin
listen on local port 2222
Forwarding to www.cnet.com:80
TCP Forwarding 127.0.0.1:39263 <--> 77.109.131.235:80 started.
------- DATAGRAM ------------
GET http://www.cnet.com/index.html HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0
Pragma: no-cache
Cache-Control: no-cache
Content-Length: 0
Host: www.cnet.com


------- DATAGRAM ------------
HTTP/1.1 301 Moved Permanently
Server: nginx
Content-Type: text/html
Location: http://www.cnet.com/
Access-Control-Allow-Origin: http://www.cnet.com
Content-Length: 178
Accept-Ranges: bytes
Date: Sun, 25 Oct 2015 19:00:29 GMT
Connection: keep-alive
Set-Cookie: fly_geo={"countryCode": "ch"}; expires=Sun, 01-Nov-2015 19:00:29 GMT; path=/; domain=.cnet.com
Set-Cookie: fly_default_edition=us; expires=Sun, 01-Nov-2015 19:00:29 GMT; path=/; domain=.cnet.com
Set-Cookie: fly_device=desktop; expires=Sun, 01-Nov-2015 19:00:29 GMT; path=/; domain=.cnet.com
Set-Cookie: fly_zip=; expires=Sun, 01-Nov-2015 19:00:29 GMT; path=/; domain=.cnet.com


301 Moved Permanently



nginx