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