*) Made sure that only files with appropriate file endings are listed as skin or language files.

*) Introduced protection against directory traversal attacks in configuration servlets for skin and language configuration. Files can only be deleted if they are contained in a list of files which has been read by the servlet first.


Until now it was possible to delete any data on a system YaCy is running on and which can be deleted by the user who's account has been used to start YaCy. Most of the times a user of YaCy is also the owner of the machine the peer is running on, but this might not always be the case and not even the owner of the machine should be able to use YaCy as a replacement for "rm" or "del".

git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@6423 6c8d7289-2bf4-0310-a012-ef5d649a1542
pull/1/head
low012 16 years ago
parent 3434ca381f
commit f5656b2ae1

@ -166,9 +166,9 @@ public class Blacklist_p {
return prop;
}
final File BlackListFile = new File(listManager.listsPath, blacklistToUse);
if(!BlackListFile.delete()) {
Log.logWarning("Blacklist", "file "+ BlackListFile +" could not be deleted!");
final File blackListFile = new File(listManager.listsPath, blacklistToUse);
if(!blackListFile.delete()) {
Log.logWarning("Blacklist", "file "+ blackListFile +" could not be deleted!");
}
for (int blTypes=0; blTypes < supportedBlacklistTypes.length; blTypes++) {

@ -48,6 +48,8 @@
<dd><input type="checkbox" name="use_skin" id="use_url" value="on" checked="checked" /></dd>
<dd><input type="submit" name="install_button" value="Install" /></dd>
</dl>
<p>Make sure that you only download data from trustworthy sources. The new language file
might overwrite existing data if a file of the same name exists already.</p>
</fieldset>
</form>

@ -52,6 +52,8 @@ import java.util.Collections;
public class ConfigAppearance_p {
private final static String SKIN_FILENAME_FILTER = "^.*\\.css$";
public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) {
final serverObjects prop = new serverObjects();
final Switchboard sb = (Switchboard) env;
@ -61,26 +63,42 @@ public class ConfigAppearance_p {
prop.put("currentskin", "");
prop.put("status", "0"); // nothing
List<String> skinFiles = listManager.getDirListing(skinPath);
List<String> skinFiles = listManager.getDirListing(skinPath, SKIN_FILENAME_FILTER);
if (skinFiles == null) {
return prop;
}
if (post != null) {
if (post.containsKey("use_button") && post.get("skin") != null) {
// change skin
changeSkin(sb, skinPath, post.get("skin"));
String selectedSkin = post.get("skin");
if (post.containsKey("use_button") && selectedSkin != null) {
/* Only change skin if filename is contained in list of filesnames
* read from the skin directory. This is very important to prevent
* directory traversal attacks!
*/
if (skinFiles.contains(selectedSkin)) {
changeSkin(sb, skinPath, selectedSkin);
}
}
if (post.containsKey("delete_button")) {
// delete skin
final File skinfile = new File(skinPath, post.get("skin"));
/* Only delete file if filename is contained in list of filesname
* read from the skin directory. This is very important to prevent
* directory traversal attacks!
*/
if (skinFiles.contains(selectedSkin)) {
final File skinfile = new File(skinPath, selectedSkin);
FileUtils.deletedelete(skinfile);
}
}
if (post.containsKey("install_button")) {
// load skin from URL
final String url = post.get("url");
final File skinFile = new File(skinPath, url.substring(url.lastIndexOf("/"), url.length()));
Iterator<String> it;
try {
final DigestURI u = new DigestURI(url, null);
@ -93,7 +111,6 @@ public class ConfigAppearance_p {
return prop;
}
try {
final File skinFile = new File(skinPath, url.substring(url.lastIndexOf("/"), url.length()));
final BufferedWriter bw = new BufferedWriter(new PrintWriter(new FileWriter(skinFile)));
while (it.hasNext()) {
@ -112,7 +129,7 @@ public class ConfigAppearance_p {
}
// reread skins
skinFiles = listManager.getDirListing(skinPath);
skinFiles = listManager.getDirListing(skinPath, SKIN_FILENAME_FILTER);
Collections.sort(skinFiles);
int count = 0;
for (String skinFile : skinFiles) {

@ -51,6 +51,8 @@
</dd>
<dd><input type="submit" value="Install" /></dd>
</dl>
<p>Make sure that you only download data from trustworthy sources. The new language file
might overwrite existing data if a file of the same name exists already.</p>
</fieldset>
</form>
#(status)#

@ -54,8 +54,10 @@ import java.util.Collections;
public class ConfigLanguage_p {
private final static String LANG_FILENAME_FILTER = "^.*\\.lng$";
public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) {
//listManager.switchboard = (plasmaSwitchboard) env;
final serverObjects prop = new serverObjects();
final String langPath = env.getConfigPath("locale.work", "DATA/LOCALE/locales").getAbsolutePath();
@ -63,20 +65,35 @@ public class ConfigLanguage_p {
//prop.put("currentlang", ""); //is done by Translationtemplate
prop.put("status", "0");//nothing
List<String> langFiles = listManager.getDirListing(langPath);
List<String> langFiles = listManager.getDirListing(langPath, LANG_FILENAME_FILTER);
if(langFiles == null){
return prop;
}
if (post != null){
String selectedLanguage = post.get("language");
//change language
if(post.containsKey("use_button") && post.get("language") != null){
translator.changeLang(env, langPath, post.get("language"));
if(post.containsKey("use_button") && selectedLanguage != null){
/* Only change language if filename is contained in list of filesnames
* read from the language directory. This is very important to prevent
* directory traversal attacks!
*/
if (langFiles.contains(selectedLanguage)) {
translator.changeLang(env, langPath, selectedLanguage);
}
//delete language file
}else if(post.containsKey("delete")){
final File langfile= new File(langPath, post.get("language"));
/* Only delete file if filename is contained in list of filesnames
* read from the language directory. This is very important to prevent
* directory traversal attacks!
*/
if (langFiles.contains(selectedLanguage)) {
final File langfile= new File(langPath, selectedLanguage);
FileUtils.deletedelete(langfile);
}
//load language file from URL
} else if (post.containsKey("url")){
@ -111,7 +128,7 @@ public class ConfigLanguage_p {
}
//reread language files
langFiles = listManager.getDirListing(langPath);
langFiles = listManager.getDirListing(langPath, LANG_FILENAME_FILTER);
Collections.sort(langFiles);
final HashMap<String, String> langNames = translator.langMap(env);
String langKey, langName;
@ -123,7 +140,6 @@ public class ConfigLanguage_p {
int count = 0;
for(String langFile : langFiles){
if(langFile.endsWith(".lng")){
//+1 because of the virtual entry "default" at top
langKey = langFile.substring(0, langFile.length() -4);
langName = langNames.get(langKey);
@ -137,7 +153,6 @@ public class ConfigLanguage_p {
}
count++;
}
}
prop.put("langlist", (count + 1));
//is done by Translationtemplate

Loading…
Cancel
Save