Popular Vulnerable Code

Spinning –Defense in Depth

Details

Affected Software:Dojo Toolkit

Fixed in Version:1.4.1

Issue Type:Defense in Depth

Original Code: Found Here

Description

This was a vulnerability affecting the Dojo toolkit.   Apparently,the dojo toolkit shipped with a SWF file that had a few vulnerabilities.  This particular vulnerability affected one of those SWF files.  First,SWF files are compiled files,however they can be decompiled.  Unlike traditional server side web application languages (PHP,ASP,JSP…etc),SWF files are downloaded and rendered on the clientside.  Decompiling the SWF file gives the attacker full access to the ActionScript source code for the SWF application.

In this particular SWF file,we see that the developers explicitly set the Security.allowDomain to “*”.  This makes it so SWF flies from other,external domains can include the Dojo toolkit SWF file and script/access its internal functionality.

The Dojo toolkit devs fixed this particular issue by removing the allowDomain call and adding an Externalinterface call checking to see if a particular wrapper was available in HTML.  If you’re interested in Flash security,an excellent presentation on Flash security given by Stefano Di Paola can be found here:

http://www.slideshare.net/guestb0af15/owasp-wasc-app-sec2007-san-jose-finding-vulnsin-flash-apps

Developers Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
public class FLVideo extends Sprite {
private var videoUrl:String;
private var video:Video;
private var connection:NetConnection;
private var autoPlay:Boolean;
private var videoStream:NetStream;
private var videoWidth:Number;
private var videoHeight:Number;
private var _currentVideo:VideoContainer;
private var preview:VideoContainer;
private var currentVolume:Number = 1;
private var isFullscreen:Boolean = false;
private var playlist:VideoPlaylist;
private var hasPlaylist:Boolean = false;
private var mode:String = "preview";

public function FLVideo() {
-    Security.allowDomain("*");
+    var secure:* = ExternalInterface.call("swfIsInHTML");
+    if(secure !== true){
+        return;
+    }
+    //Security.allowDomain("*");

stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.addEventListener(Event.RESIZE,onStageResize);
stage.addEventListener(FullScreenEvent.FULL_SCREEN ,onFullscreenChange);
stage.addEventListener(MouseEvent.CLICK,onClick);

var obj:Object = LoaderInfo(this.root.loaderInfo).parameters;
trace(obj)

if(!obj.videoUrl){
obj = {
autoPlay:true,
isDebug:true,
videoUrl:"demo_video.flv"
};
}


// ugh - booleans not coming through
if(obj.autoPlay===true || obj.autoPlay=="true"){
autoPlay = true;
}

if(obj.volume) {
currentVolume = obj.volume;
}

if(obj.isDebug===true || obj.isDebug=="true"){
console.isDebug(true);
Tracer.init({both:true})
Tracer.log("FLVideo initialized...")
}

+    Tracer.log("secure?::",secure)
MovieIdentity.identity = obj.id || "default";
this.playlist = new VideoPlaylist(autoPlay,currentVolume);

if(obj.videoUrl) {
videoUrl = obj.videoUrl;
}

preview = new VideoContainer(videoUrl,autoPlay,currentVolume);
addChild(preview);
provideCallbacks();
}


public function get currentVideo():VideoContainer{

if(mode=="playlist"&&hasPlaylist){
return this.playlist.current;
}else{
return preview;
}
}

Widths – SQL Injection

Details

Affected Software:Login LockDown for WordPress

Fixed in Version: 1.5

Issue Type:SQL Injection

Original Code: Found Here

Description

This week’s code sample comes from the “Login Lockdown” plug-in for WordPress.  It’s always interesting when “security” software ends up having serious security flaws….

This patch contained several bug fixes.  The first bug fix we see in the patch is the inclusion of nonce checking to prevent CSRF.  It’s difficult to detect CSRF vulnerabilities by looking at individual function logic and it’s ok if the reader missed these bugs.  CSRF token validation should be done at the framework level and including CSRF nonce validation in the logic of every function can quickly become unwieldy.  If an application wide CSRF solution cannot be implemented at the framework level,then auditing for CSRF must be done at a function by function level.  Personally,I prefer to check for CSRF vulnerabilities by identifying any function that performs a Create,Update,or Delete operation,mapping those functions back to the HTML markup and checking the markup to see if a nonce is passed as part of the POST or GET request.  This is of course is done after an extensive audit of the nonce validation code.

The bugs that should have been spotted by the spotthevuln reader are the SQL injection and the XSS vulnerabilities in the code.  The SQL Injection is pretty straight forward.  The “releaseme” POST parameter is taken and is eventually passed directly to a dynamically built SQL statement without any sanitization.  The developers fixed the vulnerability by utilizing the WordPress escape logic.

Finally,the last line of the code snippet actually contained an XSS vulnerability,echoing a $_SERVER variable without any sanitization.

Developers Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
function print_loginlockdownAdminPage() {
        global $wpdb;
        $table_name = $wpdb->prefix . "lockdowns";
        $loginlockdownAdminOptions = get_loginlockdownOptions();

        if (isset($_POST['update_loginlockdownSettings'])) {

+  //wp_nonce check
+  check_admin_referer('login-lockdown_update-options');

                if (isset($_POST['ll_max_login_retries'])) {
                        $loginlockdownAdminOptions['max_login_retries'] = $_POST['ll_max_login_retries'];
                }
                if (isset($_POST['ll_retries_within'])) {
                        $loginlockdownAdminOptions['retries_within'] = $_POST['ll_retries_within'];
                }
                if (isset($_POST['ll_lockout_length'])) {
                        $loginlockdownAdminOptions['lockout_length'] = $_POST['ll_lockout_length'];
                }
                if (isset($_POST['ll_lockout_invalid_usernames'])) {
                        $loginlockdownAdminOptions['lockout_invalid_usernames'] = $_POST['ll_lockout_invalid_usernames'];
                }
                if (isset($_POST['ll_mask_login_errors'])) {
                        $loginlockdownAdminOptions['mask_login_errors'] = $_POST['ll_mask_login_errors'];
                }
                update_option("loginlockdownAdminOptions",$loginlockdownAdminOptions);
                ?>
<div><p><strong><?php _e("Settings Updated.","loginlockdown");?></strong></p></div>
                <?php
        }
        if (isset($_POST['release_lockdowns'])) {

+  //wp_nonce check
+  check_admin_referer('login-lockdown_release-lockdowns');
               
  if (isset($_POST['releaseme'])) {
                        $released = $_POST['releaseme'];
                        foreach ( $released as $release_id ) {
                                $results = $wpdb->query("UPDATE $table_name SET release_date = now() ".
-                                                       "WHERE lockdown_ID = $release_id");
+                                                      "WHERE lockdown_ID = ". $wpdb->escape($release_id) . "");
                        }
                }
                update_option("loginlockdownAdminOptions",$loginlockdownAdminOptions);
                ?>
<div><p><strong><?php _e("Lockdowns Released.","loginlockdown");?></strong></p></div>
                <?php
        }
        $dalist = listLockedDown();
?>
<div>
-<form method="post"action="<?php echo $_SERVER["REQUEST_URI"];?>">
+<form method="post"action="<?php echo esc_attr($_SERVER["REQUEST_URI"]);?>">