A webes biztonság kérdése egyidős magával az internettel, hiszen a hálózaton elérhető adatokat felhasználók milliói tekintik meg napról-napra. Mivel a weboldalak végeredményben a kliensek gépein futnak, hamar beláthatjuk, hogy a biztonsági kérdések nem elhanyagolhatóak, és mind a klienseknek, mind a weboldalak üzemeltetőinek fontos, hogy a kiszolgált tartalom hiteles és biztonságos legyen. Tipikus támadási forma az un. XSS, amikor pl. egy az oldalba ágyazott külső Javascript próbál szenzitív információkhoz hozzájutni a böngésző valamely biztonsági hibáját kihasználva. Az ilyen és ehhez hasonló problémák megoldására jött létre 2001-ben OWASP Antisamy Project, melynek célja nyílt forrású alternatívát, és szabványt kínálni az alkalmazások megvédésére.
Mint minden 3rd party fejlesztés, ez is úgy kezdődik, hogy letöltjük a programkönyvtár lehetőleg legfrissebb verzióját. AntiSamy jelenleg az 1.4.4-es verziónál tart. A dokumentációval ellentétbe a csomag függőségeit nem lehet letölteni, rákeresve a antisamy-required-libs.zip kulcsszavakra találtam egy oldalt. A készítők szerint deprecated ami a zip-be van, de a próba erejéig megteszi, éles használatra össze kell vadászni a függőségeket. A szoftver konfigurációja eléggé bonyolult, hosszas dokumentáció olvasással és tanulással egész biztos össze lehet dobni egy normális konfig XML-t, de szerencsére több nagyobb felhasználó is rendelkezésre bocsátotta saját összeállítását, így nyugodtan mazsolázgathatunk az eBay, MySpace, vagy akár Slashdot beállításaiból.
Az általam készített tesztprogram az alábbi (belecsempészve kis Java 7-et):
import java.io.IOException; import java.net.URL; import java.nio.charset.Charset; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import org.owasp.validator.html.*; public class AntiSamyTest { public static void main(String[] args) { try { URL dirtyHtmlUrl = AntiSamyTest.class.getResource("dirtyHtml.html"); Path dirtyHtmlPath = FileSystems.getDefault().getPath(dirtyHtmlUrl.getFile()); List<String> lines = Files.readAllLines(dirtyHtmlPath, Charset.defaultCharset()); URL configXmlUrl = AntiSamyTest.class.getResource("antisamy-ebay-1.4.4.xml"); Policy policy = Policy.getInstance(configXmlUrl.getFile()); AntiSamy as = new AntiSamy(); CleanResults cleanResult = as.scan(concatString(lines), policy); System.out.println(cleanResult.getCleanHTML()); } catch (IOException | PolicyException | ScanException ex) { throw new RuntimeException(ex); } } private static String concatString(List<String> input) { StringBuilder output = new StringBuilder(); for(String line : input) output.append(line); return output.toString(); } }A dirtyHtml.html fájl tartalma szabvány HTML (HTML, HEAD, BODY). A programot futtatva láthatjuk, hogy a body tartalmán kívül minden HTML taget kidobott az AntiSamy. Azért mondom, hogy minden HTML taget, mert ha van pl. title a headbe, a tartalma bizony ottmarad, tehát csak a sallang kerül ki. Szerintem ez utóbbi működés konfigurálható (fixme).
Az elméleti ismerkedés után ideje valami komolyabb megbizatást adni Samykének. Személy szerint Liferay fejlesztő vagyok, így szinte evidens, hogy erre esett a választásom. A Liferay 6-os verziója óta létezik egy Sanitizers-nek nevezett funkcionalitás, amely, bár még nem teljeskörű, mégis segít az igényes programozónak, a kritikus user inputokat szűrni. A funkcionalitás mint írtam nem teljeskörű, ugyanis egyelőre csak a Blog bejegyzéseket tudjuk kontrollálni out-of-the-box. A dolgunk egyszerű, a portal.properties-ben van egy sanitizer.impl paraméter, amit a portal-ext.properties-ben felül tudunk definiálni. Az alapbeállítás a com.liferay.portal.sanitizer.DummySanitizerImpl osztályra mutat, ami jóformán semmit nem csinál, viszont jó kiindulási pont lehet saját Saniterünk elkészítéséhez. Létezik a Liferaynek beépített osztálya com.liferay.portal.kernel.sanitizer.SanitizerUtil képében, választhatjuk ezt is, de saját megoldást is minden további nélkül.
Miután Blog bejegyzéseinket megvédtük a sokszor óvatlan bloggerektől, sajnos nem dőlhetünk hátra nyugodtan, mivel a Liferayben is, mint minden CMS-ben, nem csak Blogot szerkesztenek a felhasználók, hanem számtalan egyéb módon is lehetőségük van HTML szöveget a rendszerbe juttatni. Mivel "gyári" támogatás még nincs ezen bejegyzésekre, nincs más lehetőségünk, mint hook-ot írni. A Plugin tárolóban van egy "antisamy hook", amely alapján könnyedén megírhatjuk saját kiterjesztésünket. A legjobb módszer un. Model Wrapper Hook készítése. Hozzunk létre egy hook-ot, majd a liferay-hook.xml fájlba írjuk be a felülírandó szervíz definícióját
<hook> <service> <service-type>com.liferay.portlet.wiki.service.WikiPageLocalService</service-type> <service-impl>com.test.hooks.SaniterWikiPageLocalService</service-impl> </service> </hook>Majd írjuk meg saját osztályjunkat
import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.exception.SystemException; import com.liferay.portal.kernel.sanitizer.SanitizerUtil; import com.liferay.portal.kernel.util.ContentTypes; import com.liferay.portal.service.ServiceContext; import com.liferay.portlet.wiki.model.WikiPage; import com.liferay.portlet.wiki.service.WikiPageLocalService; import com.liferay.portlet.wiki.service.WikiPageLocalServiceWrapper; public class SaniterWikiPageLocalService extends WikiPageLocalServiceWrapper { public SaniterWikiPageLocalService(WikiPageLocalService wikiPageLocalService) { super(wikiPageLocalService); } public WikiPage addPage( long userId, long nodeId, String title, double version, String content, String summary, boolean minorEdit, String format, boolean head, String parentTitle, String redirectTitle, ServiceContext serviceContext) throws PortalException, SystemException { String sanitizedContent = SanitizerUtil.sanitize( serviceContext.getCompanyId(), serviceContext.getScopeGroupId(), userId, WikiPage.class.getName(), 0, ContentTypes.TEXT_HTML, content); return super.addPage(userId, nodeId, title, version, sanitizedContent, summary, minorEdit, format, head, parentTitle, redirectTitle, serviceContext); } }Bár én a Wiki-t választottam példának, ez alapján bármely más szervízre megírható a szűrés.
Nincsenek megjegyzések:
Megjegyzés küldése