Finding Architectural Flaws Using Constraints: Online Appendix
Scoria Evaluation

Radu Vanciu      Marwan Abi-Antoun
Department of Computer Science, Wayne State University

Online appendix to the paper:
Vanciu, R. and Abi-Antoun, M. Finding Architectural Flaws Using Constraints. In IEEE/ACM Conference on Automated Software Engineering (ASE), 11p. 2013.


MSC00-J. Use SSLSocket rather than Socket for secure data exchange. 

The code uses the Socket class to implement the client-server communication over a network. However, such a communication channel does not provide encryption and the communication is vulnerable to eavesdropping.

To find a possible information disclosure, the constraint uses object provenance and checks if the same object that flows from an object of type InputStream in the domain DATA of the System class to an object of type EchoClient also flows to an object sckt:Socket. The constraint also uses indirect object provenance and checks that the object flows to the descendants or reachable objects of sckt:Socket. Indeed, the same object ss:String flows from client:EchoClient to the object out:Writer from which a descendant of sckt:Socket is reachable. The object ss also flows from server:EchoServer to a descendant of sckt:Socket. The constraint highlights these two dataflow edges as suspicious. From a suspicious dataflow edge, the architects can trace to the method invocation out.write(stdInput). There are no coding defects, however an information disclosure does exist.

If the constraint were to use the type information only and consider all objects of type OutputStream as untrusted, it would report four suspicious dataflow edges including two false positives: the dataflow edge from client to the standard output stream, and the dataflow edge from server to a child of sslSocket:SSLSocket.

 


FIO05-J. Do not expose buffers created using the wrap() or duplicate() methods to untrusted code. 

The class CharBuffer has methods that wrap an array of primitive types into an object of type CharBuffer. According to the Java documentation, modifications of an object of type CharBuffer cause the array to be modified and vice-versa. Therefore, passing the cb:CharBuffer to an untrusted object exposes the array that is reachable from cb. Instead, an object with a reference to a copy of the array should be passed.

The constraint selects the objects of type CharBuffer created in the body of wrap and duplicate methods. Next, the constraint selects the children of these objects that are of type char[]  and assigns to them IsConfidential.True. The constraint also assigns TrustLevel.Untrusted to c:Client, which represents untrusted code. The query getFlowToSink returns a suspicious edge, such that the dataflow object cb:CharBuffer has a points-to edge to the confidential object of type char[] and the destination object is c. This constraint may also consider objects of types that are similar to CharBuffer such as IntBuffer.

 

SER03-J. Do not serialize unencrypted, sensitive data. 

Serialization saves an object persistently. All the fields reachable from the object are also saved unless the developers mark them as transient. An information disclosure exists if a confidential, unencrypted object is serialized.

The CERT example uses the Serializable interface. Since other libraries can also be used for serialization, the SecGraph has the property IsTransient to keep the constraint independent from a specific library. The constraint insecureSerializations assigns TrustLevel.Untrusted to objects of type ObjectOutputStream, then assigns IsConfidential.True and IsEncrypted.False to objects of type Double in the domain OWNED of objects of type Point. Next, it assigns IsTransient.False to points-to edges from objects of type Point to objects of type Double. Finally, insecureSerializations checks if the EdgeSet returned by getFlowToSink is not empty such that the outgoing points-to edge from the dataflow object has IsTransient.False.

The constraint finds an information disclosure as a dataflow from coord to oout, where the dataflow object is p:Point that has references to value:Double. The object value:Double has the property IsConfidential.True and should not be serialized. However, the points-to edge from p to value has IsTransient.False, and serialization occurs. Next, the architects can trace to code and find the method invocation oout.writeObject(p) in the body of Coordinates.run.

By using the condition IsInDomain, the constraint assigns property values only to a subset of all the objects of type Double, i.e., it does not include children of objects of type Coordinate. If the constraint were to use the InstanceOf condition instead of IsInDomain, all the objects of type Double would be considered confidential, and insecureSerializations would return one false positive.

 

FIO13-J. Do not log sensitive information outside a trust boundary. 

Logging enables a program to collect essential information for debugging. However, logging confidential information such as IP addresses may be prohibited by law in many countries. The class Logger in Java provides basic functionality for logging.

The constraint insecureLogging checks if dataflow edges exist such that a dataflow object has IsConfidential.True and the destination has TrustLevel.Untrusted. The constraint uses reachability information to assign IsConfidential.True only to the objects of type String reachable from an object of type InetAddress. The constraint highlights a dataflow edge from srvr to log that refers to the object ip:String. The architects can trace to the line of code logger.severe(machine.getHostAddress()), which indeed logs the IP address. To assign the IsConfidential property, the architects use a condition that considers type and reachability information. If the architects were to use a condition that considers only the type information, insecureLogging would return a false positive for the expression logger.getLogger(name), where the nameargument does not refer to a confidential object.

 

IDS07-J. Do not pass untrusted, unsanitized data to the Runtime.exec() method. 

A Java program can invoke external commands provided by the operating system, such as a command that lists a folder's content. An architectural flaw exists if an attacker can tamper with the input and launch arbitrary injected commands with the privileges of the target user. As a solution, the program must sanitize untrusted objects flowing along untrusted communication.

We adapted the example from CERT where the attacker can invoke arbitrary commands on Windows by tampering with the arguments of the method Runtime.exec. The constraint commandInjections finds tampering by using object provenance, and traceability information. It uses object provenance to check if the same object that is passed as an argument to m:Main is also passed to an object of type Runtime. It also uses traceability and highlights only dataflow edges due to the method invocation Runtime.exec. The architects trace to code and find the rt.exec("cmd.exe /C dir " + dir). If the constraint were to use only information about the type of the arguments, it would also return a false positive for rt.load(filename).

 

Last Modified: Friday, November 22, 2013