How to resolve "Deserialization of untrusted data" issue? - java

I am getting "Deserialization_of_Untrusted_Data" issue in SonarQube in the below part of my code.
public Configuration deserializeConfiguration(final InputStream xml) {
Configuration config = null;
exception = null;
try {
final XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(xml), null, e -> {
});
config = (Configuration) decoder.readObject();
decoder.close();
} catch (final Exception e) {
exception = new Exception(e);
}
return config;
}
I tried to use class loader but it didn't resolve the issue.
public Configuration deserializeConfiguration(final InputStream xml) {
Configuration config = null;
exception = null;
try {
final XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(xml), this.getClass().getClassLoader(), e -> {});
config = (Configuration) decoder.readObject();
decoder.close();
} catch (final Exception e) {
exception = new Exception(e);
}
return config;
}
Please suggest what I can do here without impacting other parts of the project.
This is my first time on this platform, so please ignore if there's any mistake.

Related

How to convert this method from using java.io.File to java.nio.file?

Basically I have this method that I got off a tutorial (My main goal is to simply return the images from the spring boot server so that I could dynamically view them in Angular)
#RestController
public class FileController {
#Autowired
ServletContext context;
#GetMapping(path = "/allImages")
public ResponseEntity<List<String>> getImages(){
List<String> images = new ArrayList<String>();
String filesPath = context.getRealPath("/images");
File fileFolder = new File(filesPath);
if(fileFolder!=null) {
for(final File file : fileFolder.listFiles()) {
if(!file.isDirectory()) {
String encodeBase64 = null;
try {
String extention = FilenameUtils.getExtension(file.getName());
FileInputStream fileInputStream = new FileInputStream(file);
byte[] bytes = new byte[(int)file.length()];
encodeBase64 = Base64.getEncoder().encodeToString(bytes);
images.add("data:image/"+extention+";base64,"+encodeBase64);
fileInputStream.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
return new ResponseEntity<List<String>>(HttpStatus.OK);
}
With the current code, when I try to return the files, I get:
java.lang.NullPointerException: Cannot read the array length because the return value of "java.io.File.listFiles()" is null
I've been searching around and noticed that people recommend using java.nio.file instead but I'm a little lost on how would I implement this here. Any help is appreciated.
Example with nio:
public List<String> readImages() throws IOException {
return Files.list(Path.of("/images"))
.filter(Files::isRegularFile)
.map(this::encode)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
private String encode(Path file) {
try {
String extension = FilenameUtils.getExtension(file.getFileName().toString());
String encodeBase64 = Base64.getEncoder().encodeToString(Files.readAllBytes(file));
return "data:image/"+extension+";base64,"+encodeBase64;
} catch (Exception e) {
return null;
}
}
First get a Path to your folder:
Path folderPath = Paths.get(filesPath);
If your Path points to a directory, you can get a Stream<Path> of its contents using Files.list:
if (Files.isDirectory(folderPath)) {
List<Path> files = Files.list(folderPath)
.filter(path -> !Files.isDirectory(path))
.collect(Collectors.toList());
// Do something with the files.
}
It doesn't look like you are using the FileInputStream for anything, so you shouldn't need to translate that part. To get the file extension of your path, you probably need to convert the Path to a string, and extract the extension yourself.
I solved this issue with this code:
#Autowired
ServletContext context;
#GetMapping(path = "/allImages")
public List<String> readImages() throws IOException {
return Files.list(Paths.get(context.getRealPath("/images")))
.filter(Files::isRegularFile)
.map(this::encode)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
private String encode(Path file) {
try {
String extension = FilenameUtils.getExtension(file.getFileName().toString());
String encodeBase64 = Base64.getEncoder().encodeToString(Files.readAllBytes(file));
return "data:image/"+extension+";base64,"+encodeBase64;
} catch (Exception e) {
return null;
}
}
Thank you to everyone who helped.

Spring sftp - failed to read file; nested exception is 4

Every now and then I get the exception pointed out in the title. Does anyone know what exception 4 means or where this is documented? I've looked at questions relating to this and I've learned that there's exception 2 which apparently means "No such file" and exception 3 which is "Permission Denied". However, when I get nested exception is 4, there is no description so I'm not sure what this means. Is it just a generic read time out? This happens very infrequently, and it's difficult to reproduce, as some of our users have no issues at all, while some run into this issue every now and then.
org.springframework.core.NestedIOException: failed to read file /ftadv:D=IBM-037,C=UTF-8/__'MAIN.FRAME.DATASET'; nested exception is 4:
at org.springframework.integration.sftp.session.SftpSession.readRaw(SftpSession.java:143)
at org.springframework.integration.file.remote.session.CachingSessionFactory$CachedSession.readRaw(CachingSessionFactory.java:268)
at org.springframework.integration.file.remote.session.CachingSessionFactory$CachedSession.readRaw(CachingSessionFactory.java:268)
at com.my.package.FTPService.ftpStoreAuthData(FTPService.java:166)
at com.my.package.FTPService.ftpStoreNetAuthData(FTPService.java:59)
at com.my.package.FTPEndpoint.ftpStoreNetAuthData(FTPEndpoint.java:27)
Here's my config if it helps.
#Configuration
class SftpConfiguration {
#Inject
private Environment env;
SessionFactory<LsEntry> getSftpSessionFactory() {
DefaultSftpSessionFactory sftpSessionFactory =
new DefaultSftpSessionFactory(Boolean.parseBoolean(env.getRequiredProperty("sftp.isSharedSession")));
sftpSessionFactory.setHost(env.getRequiredProperty("sftp.host"));
sftpSessionFactory.setPort(Integer.parseInt(env.getRequiredProperty("sftp.port")));
sftpSessionFactory.setUser(env.getRequiredProperty("sftp.id"));
sftpSessionFactory.setPrivateKey(new FileSystemResource(env.getRequiredProperty("sftp.keyPath")));
sftpSessionFactory.setPrivateKeyPassphrase(env.getRequiredProperty("sftp.passphrase"));
sftpSessionFactory.setTimeout(Integer.parseInt(env.getRequiredProperty("sftp.timeout")));
sftpSessionFactory.setAllowUnknownKeys(Boolean.parseBoolean(env.getRequiredProperty("sftp.allowUnknownKeys")));
return new CachingSessionFactory<LsEntry>(sftpSessionFactory);
}
CachingSessionFactory getCachingSessionFactory(){
CachingSessionFactory cachingSessionFactory = new CachingSessionFactory(getSftpSessionFactory());
cachingSessionFactory.setSessionWaitTimeout(Integer.parseInt(env.getRequiredProperty("sftp.sessionWaitTimeout")));
cachingSessionFactory.setPoolSize(Integer.parseInt(env.getRequiredProperty("sftp.poolSize")));
return cachingSessionFactory;
}
}
And here's an example of the calling code:
#Service
class FTPService {
private static final org.apache.logging.log4j.Logger logger = LogManager.getLogger(FTPEndpoint.class);
private CachingSessionFactory cachingSessionFactory;
private String adviceString;
#Inject
private FTPService(SftpConfiguration sftpConfig) {
this.cachingSessionFactory = sftpConfig.getCachingSessionFactory();
this.adviceString = sftpConfig.getAdviceString();
}
private String ftpStoreAuthData() {
Session session = this.cachingSessionFactory.getSession();
String mainframeDataSet = "'MAIN.FRAME.DATASET'";
try(BufferedInputStream inputStream = new BufferedInputStream(session.readRaw(adviceString + mainframeDataSet));
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))
{
Stream<String> lines = reader.lines());
return doThingsWithFTPData(lines);
} catch (IOException ex) {
LogException.writeToFile(ex.getMessage(),ex.getStackTrace(), env.getProperty("sftp.exceptionsPath"));
}finally {
try {
if (session.isOpen()) {
session.finalizeRaw();
session.close();
}
}catch (IOException ioe){
System.out.println(ioe.getLocalizedMessage() + ioe.getCause().toString());
LogException.writeToFile(ioe.getMessage(),ioe.getStackTrace(), env.getProperty("sftp.exceptionsPath"));
throw new IOException();
}
}
return "test";
}
}

Freemarker encoding wrong

I have project it's jetty server which use freemarker. I use russian letters in my templates and receive ?. All subjects i have read before didn't help me.
I use in my code
.setContentType("text/html;charset=utf-8");
.setCharacterEncoding("UTF-8");
all my files is utf-8.
My Freemarker page genertor servlet
public class PageGenerator {
private static PageGenerator pageGenerator;
private Configuration cfg;
public static PageGenerator instance() {
if (pageGenerator == null)
pageGenerator = new PageGenerator();
return pageGenerator;
}
public String getPage(String filename, Map<String, Object> data) {
Writer stream = new StringWriter();
try {
Template template = cfg.getTemplate(filename);
template.process(data, stream);
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
return stream.toString();
}
private PageGenerator() {
cfg = setCfg();
}
private Configuration setCfg(){
cfg = new Configuration(Configuration.VERSION_2_3_20);
try {
cfg.setDirectoryForTemplateLoading(new File("templates/"));
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
} catch (IOException e) {
e.printStackTrace();
}
return cfg;
}
}
But in brouser my page in windows-1252 encoding.
Thanks for idea ddekany I used debag mode and find out that Class Response that extends HttpServletResponse has "magic" method .setCharacterEncoding() which set Character Encoding in response stream

Test using Mockito

Here is my code and I want to know what's the best way to test using Mockito as I am creating couple of objects using new keyword. can anyone guide me ?
public static PDDocument generatePDF(final String reportString, final String requestId) throws IOException {
final PDDocument document = new PDDocument();
final byte[] byteStr = reportString.getBytes(StandardCharsets.UTF_8);
final String str = new String(byteStr,
StandardCharsets.UTF_8);
final BufferedReader reader = new BufferedReader(new StringReader(str));
try {
// PDF box ceremony
final TextToPDF textToPdf = new TextToPDF();
textToPdf.setFont(PDType1Font.COURIER);
textToPdf.setFontSize(10);
textToPdf.createPDFFromText(document, reader);
reader.close();
} catch (final IOException ioException) {
LOGGER.error("IO Exception while generating PDF for request id " + requestId, ioException.getMessage());
throw ioException;
} catch (final Exception e) {
LOGGER.error("Exception while generating PDF for request id " + requestId, e.getMessage());
throw e;
} finally {
reader.close();
}
return document;
}
Mockito is intended to mock the collaborators of the class/method you want to test. Note that it should be used only to mock the types you own.
In this case, you don't actually need Mockito.
An example, similar to yours, in which you could use Mockito, is this:
class PDFGenerator {
private ITextToPdf textToPdf; // This is an hypotetical interface provided by you, for example used as a wrapper to easily change the underling framework
public void setTextToPdf(ITextToPdf textToPdf) {
this.textToPdf = textToPdf;
}
public static PDDocument generatePDF(final String reportString, final String requestId) throws IOException {
final byte[] byteStr = reportString.getBytes(StandardCharsets.UTF_8);
final String str = new String(byteStr,
StandardCharsets.UTF_8);
final BufferedReader reader = new BufferedReader(new StringReader(str));
try {
IDocument document = textToPdf.createPDFFromText(reader);
reader.close();
return document;
} catch (final IOException ioException) {
LOGGER.error("IO Exception while generating PDF for request id " + requestId, ioException.getMessage());
throw ioException;
} catch (final Exception e) {
LOGGER.error("Exception while generating PDF for request id " + requestId, e.getMessage());
throw e;
} finally {
reader.close();
}
}
}
In this case, the test would be:
#Test
public void testGeneratePdf() throws Exception {
ITextToPdf textToPdfMock Mockito.mock(ITextToPdf.class);
PDFGenerator pdfGenerator = new PDFGenerator();
pdfGenerator.setTextToPdf(textToPdfMock);
Mockito.when(textToPdfMock.createPDFFromText(Mockito.any())).thenReturn(something);
IDocument generatedDocument = pdfGenerator.generatePDF(createReportString(), "TestId");
Mockito.verify(textToPdfMock, Mockito.times(1)).createPDFFromText(Mockito.any());
Mockito.verifyNoMoreInteractions(textToPdfMock);
// Do also some standard junit asserts on the generatedDocument
}

Vaadin with JasperReports?

I'm looking for a solution to create reports using JasperReports for my application. I found some examples but still could not make it work. I'm using Vaadin7
I'm trying this
public class Report {
public Report(){
createShowReport();
}
private void createShowReport(){
final Map map = new HashMap();
StreamResource.StreamSource source = new StreamResource.StreamSource() {
public InputStream getStream() {
byte[] b = null;
try {
b = JasperRunManager.runReportToPdf(getClass().getClassLoader().getResourceAsStream("br/ind/ibg/reports/report3.jasper"), map, new JREmptyDataSource());
} catch (JRException ex) {
ex.printStackTrace();
}
return new ByteArrayInputStream(b);
}
};
StreamResource resource = new StreamResource(source, "report3.pdf");
resource.setMIMEType("application/pdf");
VerticalLayout v = new VerticalLayout();
Embedded e = new Embedded("", resource);
e.setSizeFull();
e.setType(Embedded.TYPE_BROWSER);
v.addComponent(e);
Window w = getWindow();
w.setContent(v);
UI.getCurrent().addWindow(w);
}
private Window getWindow(){
Window w = new Window();
w.setSizeFull();
w.center();
return w;
}
}
Any idea ?
Problem seems to be on the JasperPrint printer = JasperFillManager.fillReport(file, parametros,dados); line.
Make sure that your report is found (file is not null).
In order to show the report, what I usually do is put the resulted pdf in a stream, then create a streamResource with mimeType='application\pdf' and use window.open(resource) to show it.
Example:
StreamResource.StreamSource source = new StreamResource.StreamSource() {
public InputStream getStream() {
byte[] b = null;
try {
b = JasperRunManager.runReportToPdf(getClass().getClassLoader().getResourceAsStream("reports/report3.jasper"), map, con);
} catch (JRException ex) {
ex.printStackTrace();
}
return new ByteArrayInputStream(b);
}
};
StreamResource resource = new StreamResource(source, "report3.pdf", getApplication());
resource.setMIMEType("application/pdf");
getApplication().getMainWindow().open(resource, "_new");

Categories

Resources