CSO Security for extensions
Microsoft .NET Framework, ASP.NET, Visual C# (CSharp, C Sharp, C-Sharp) Developer Training, Visual Studio
Note: Despite how they may appear on this Web page, the PHP strings shown in the examples must actually appear on a single line. Line breaks are not permitted within a string literal.
Potentially dangerous or abusable extensions can be used on designated pages if the extension contains security checks. And, sometimes it may be desirable to restrict the use of certain extensions to certain pages for other reasons. I have detailed a few methods for restricting or securing extensions. These methods are based one one or both of the following facts:
- Only a System Administrator can install extensions.
- Only a wiki adminstrator with Sysop privileges can protect pages.
So, the approach is to code the security method in the extension itself. That way, only a system administrator can change the security by uploading a new version of the extension. It may seem a bit cumbersome; but, it is more secure because of it.
The security methods check if that tag (extension) can be used:
- on that page namespace and title (2 methods check this);
- on that page URL;
- using the specified target URL;
- using a known HTML sequence accessed by keyword.
An extension can be doubly secured by validating that the page is protected, which means that only a wiki adminstrator could have altered the article.
The security methods should be the first thing executed inside the callback rendering function. In the following examples, the rendering function is named "CSO_Render".
Contents |
Secure the page protection
This method works by checking the page protection set by a wiki administrator. If the page is protected, the extension is executed and the tag processed. If unprotected, the extension returns without processing the tag. This method is secure only if the page is protected and edited only by a wiki administrator.
function CSO_Render ($input) #parser hook callback function { if ( ! ($wgTitle->isProtected( 'edit' )) ) { return "<!-- CSO_Secure: Invalid context.-->"; } // ... }
Secure the namespace and title
These functions all have a boolean parameter ($checkProt) which indicates whether or not to check for protection in addition to the normal checking the function performs. If $checkProt is TRUE, then the function will ensure that the calling page is protected; if FALSE, there is no protection check.
Secure the namespace:title
The CSO_SecureDBkey method works by checking to see if the calling page is present in an associative array inside the extension. If it is present—is known to the extension—, then the tag is processed. If the page is unknown, then the extension returns an error string without processing the tag. If $checkProt is FALSE, the protection check is skipped.
# http://meta.wikimedia.org/wiki/Help:Namespace#List_of_namespaces # call $bool = CSO_SecureDBkey(TRUE|FALSE); function CSO_SecureDBkey ($checkProt) # security function { $validArticle[NS_MAIN.":"."Main_Page"] = 1; $validArticle[NS_TALK.":"."test3"] = 1; $validArticle[NS_MAIN.":"."Test:test1"] = 1; # Here add pages which can use this tag (extension) global $wgTitle; $bRetVal = FALSE; if ( ($checkProt == TRUE) && ( ! ($wgTitle->isProtected( 'edit' )) ) ) { return $bRetVal; } if ( ($validArticle[$wgTitle->getNamespace().":".$wgTitle->getDBkey()]) ) { $bRetVal = TRUE; } return ($bRetVal); } # end security function function CSO_Render ($input) #parser hook callback function { if (! CSO_SecureDBkey (TRUE)) { return "<!-- CSO_Secure: Invalid context.-->"; } // Here if page is protected and is listed in $validArticle }
To add a new page to the $validArticle associative array, add an entry referencing the namespace and page title, like this:
$validArticle[NS_MAIN.":"."MyPage"] = 1;
Secure the PrefixedDBkey
This method works like the Secure the namespace:title method, except the known calling pages are specified in a different manner.
This method works by checking to see if the calling page is present in an associative array inside the extension. If it is present—is known to the extension—, then the tag is processed. If the page is unknown, then the extension returns without processing the tag. If $checkProt is FALSE, the protection check is skipped.
# call $bool = CSO_SecurePrefixedDBkey(TRUE|FALSE); function CSO_SecurePrefixedDBkey ($checkProt) # security function { $validArticle["Main_Page"] = 1; $validArticle["Talk:test3"] = 1; $validArticle["Test:test1"] = 1; global $wgTitle; $bRetVal = FALSE; if ( ($checkProt == TRUE) && ( ! ($wgTitle->isProtected( 'edit' )) ) ) { return $bRetVal; } if( ($validArticle[$wgTitle->getPrefixedDBKey()]) ) { $bRetVal = TRUE; } return ($bRetVal); } # end security function function CSO_Render ($input) #parser hook callback function { if (! CSO_SecurePrefixedDBkey (TRUE)) { return "<!-- CSO_Secure: Invalid context.-->"; } // ... }
To add a new page to the $validArticle associative array, add an entry referencing the namespace and page title, like this:
$validArticle["MyPage"] = 1;
Secure the page URL
This method works by checking to see if the full calling page URL is present in an associative array inside the extension. If it is present—is known to the extension—, then the tag is processed. If the page is unknown, then the extension returns without processing the tag. If $checkProt is FALSE, the protection check is skipped.
# call $bool = CSO_SecureURL(TRUE|FALSE); function CSO_SecureURL($checkProt) # security function { $validArticle["http://www.csharp-online.net/csow/index.php?title=Main_Page"] = 1; $validArticle["http://www.csharp-online.net/csow/index.php?title=Talk:test3"] = 1; $validArticle["http://www.csharp-online.net/csow/index.php?title=Test:test1"] = 1; global $wgTitle; $bRetVal = FALSE; if ( ($checkProt == TRUE) && ( ! ($wgTitle->isProtected( 'edit' )) ) ) { return $bRetVal; } if( ($validArticle[$wgTitle->getFullURL("")]) ) { $bRetVal = TRUE; } return ($bRetVal); } # end security function function CSO_Render ($input) #parser hook callback function { if (! CSO_SecureURL(TRUE)) { return "<!-- CSO_Secure: Invalid context.-->"; } // ... }
To add a new page to the $validArticle associative array, add an entry referencing the namespace and page title, like this:
$validArticle["http://MyDomainName/index.php?title=MyPage"] = 1;
Secure by keyword
These methods work by restricting the tag to using known values hard-coded into the extension which are accessed via keywords. If the keyword between the tags is present in an associative array inside the extension, then the associated value is returned to the calling method. Both of these methods insist on checking for page protection: there is no option to skip it.
Secure the target URL by keyword
This method works by restricting the tag to known target URLs identified by keywords. If the keyword between the tags is present in an associative array inside the extension, then the associated target URL is returned to the calling method.
# Callback function to render text from between tags to article function CSO_Render ($CSO_SiteURL) { global $wgTitle; $errorMessage = "<!-- CSO_SecureTargetURL: invalid URL. -->"; $siteURLs["Help"] = "http://meta.wikimedia.org/wiki/Help:Section"; $siteURLs["Amazon"] = "http://www.amazon.com/gp/homepage.html/"; if ( $wgTitle->isProtected( 'edit' ) ) { if ($siteURLs[$CSO_SiteURL]) { return $siteURLs[$CSO_SiteURL]; } } return $errorMessage; }
To add a new page to the $siteURLs associative array, add an entry containing the target URL, like this:
$siteURLs["MyKeyWord"] = "MyURL";
Don't forget to escape any quotation marks (\") embedded in the URL string.
Secure by the HTML sequence by keyword
This method works by restricting the tag to known HTML sequences identified by keywords. If the keyword between the tags is present in an associative array inside the extension, then the associated HTML sequence is retrieved from the array and inserted in the article.
# Callback function to render text from between tags to article function CSO_Render ($CSO_SiteAd) { global $wgTitle; $errorMessage = "<!-- CSO_SiteAd: invalid site. -->"; $siteAds["SiteGround"] = "<a href=\"http://www.siteground.com/\" onClick=\"this.href='http://siteground.com/atrack.php?referrerid=xxxxx'\" target=\"offsite\"><img src=\"http://www.siteground.com/images/468x60_2.gif\" alt=\"Web hosting services\" width=468 height=60 border=0></a>"; $siteAds["PayPal"] = "<form action=\"https://www.paypal.com/cgi-bin/webscr\" method=\"post\"><input type=\"hidden\" name=\"cmd\" value=\"_s-xclick\"><input type=\"image\" src=\"https://www.paypal.com/en_US/i/btn/x-click-but21.gif\" border=\"0\" name=\"submit\" alt=\"Make payments with PayPal - it's fast, free and secure!\"><input type=\"hidden\" name=\"encrypted\" value=\"-----BEGIN PKCS7----- ... /hL5efb0wQ4RKt4XIIPemoKYi0=-----END PKCS7-----\"></form>"; if ( $wgTitle->isProtected( 'edit' ) ) { if ($siteAds[$CSO_SiteAd]) { return $siteAds[$CSO_SiteAd]; } } return $errorMessage; }
To add a new page to the $siteAds associative array, add an entry referencing the namespace and page title, like this:
$siteAds["MyKeyword"] = "MyHTMLSequence";
Don't forget to escape any quotation marks (\") embedded in the HTML string.
Testing security methods
To try and be sure of getting a page which has been updated by a new extension, follow these steps:All this—usually—results in fetching a fresh page. It is not always required to do all these steps; but, if you do not, you may think it is working when it is not or vice-versa.
- Clear your browser cache.
- Close the browser window.
- Load the page in a new browser window.
- Unprotect, then protect the page.