I am trying to build defense against Java deserialization vulnerability by using Apache API ValidatingObjectInputStream.
But it is failing with following exception and not sure what could be missing here:
Object has been serialized
IOException is caught
java.io.StreamCorruptedException: invalid stream header: 74000732
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:863)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:355)
at org.apache.commons.io.serialization.ValidatingObjectInputStream.<init>(ValidatingObjectInputStream.java:59)
at com.apple.ctbdp.controller.Test.deSerialize(Test.java:44)
at com.apple.ctbdp.controller.Test.main(Test.java:28)
Test.java
class Test {
public static void main(String[] args) {
String object = new String("2323232");
String filename = "file.ser";
serialize(object, filename);
deSerialize(filename);
}
private static void deSerialize(String filename) {
String object1 = null;
try {
// Reading the object from a file
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream in = new ObjectInputStream(fis);
final ValidatingObjectInputStream objectInStream = new ValidatingObjectInputStream(fis);
objectInStream.accept(String.class);
// Method for deserialization of object
object1 = (String) objectInStream.readObject();
in.close();
fis.close();
System.out.println("Object has been deserialized ");
System.out.println("Test.deSerialize() " + object1);
}
catch (IOException ex) {
ex.printStackTrace();
System.out.println("IOException is caught");
}
catch (ClassNotFoundException ex) {
System.out.println("ClassNotFoundException is caught");
}
}
private static void serialize(String object, String filename) {
// Serialization
try {
// Saving of object in a file
FileOutputStream file = new FileOutputStream(filename);
ObjectOutputStream out = new ObjectOutputStream(file);
// Method for serialization of object
out.writeObject(object);
out.close();
file.close();
System.out.println("Object has been serialized");
}
catch (IOException ex) {
System.out.println("IOException is caught");
}
}
}
Appreciate your hint/suggestion in this regard.
I did not close the ValidatingObjectInputStream object, but instead was closing the ObjectInputStream object. With this change, it is now working.
Updated code:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import org.apache.commons.io.serialization.ValidatingObjectInputStream;
class Test {
public static void main(String[] args) {
String object = new String("2323232");
String filename = "file.ser";
serialize(object, filename);
deSerialize(filename);
}
private static void deSerialize(String filename) {
String object1 = null;
try {
// Reading the object from a file
FileInputStream fis = new FileInputStream(filename);
final ValidatingObjectInputStream objectInStream = new ValidatingObjectInputStream(fis);
objectInStream.accept(String.class);
// Method for deserialization of object
object1 = (String) objectInStream.readObject();
objectInStream.close();
fis.close();
System.out.println("Object has been deserialized ");
System.out.println("Test.deSerialize() " + object1);
}
catch (IOException ex) {
ex.printStackTrace();
System.out.println("IOException is caught");
}
catch (ClassNotFoundException ex) {
System.out.println("ClassNotFoundException is caught");
}
}
private static void serialize(String object, String filename) {
// Serialization
try {
// Saving of object in a file
FileOutputStream file = new FileOutputStream(filename);
ObjectOutputStream out = new ObjectOutputStream(file);
// Method for serialization of object
out.writeObject(object);
out.close();
file.close();
System.out.println("Object has been serialized");
}
catch (IOException ex) {
System.out.println("IOException is caught");
}
}
}
Related
I create a client similarity, where clients register an account (an object is created) which is stored in a file.
Objects are written to the file as required, I override the writeStreamHeader() method. But when I try to read them all, their file throws an exception.
Write the objects to the file here.
public static void saveAccaunt(LoginAndPass gamers) {
boolean b = true;
FileInputStream fis = null;
try{
fis = new FileInputStream("student.ser");
fis.close();
}
catch (FileNotFoundException e)
{
b = false;
} catch (IOException e) {
e.printStackTrace();
}
try {
FileOutputStream fileOutputStream = new FileOutputStream("student.ser",true);
ObjectOutputStream os = null;
if(b = true){
os = new AppendingObjectOutputStream(fileOutputStream);
System.out.println("Объект добавлен!");
}else {
os = new ObjectOutputStream(fileOutputStream);
System.out.println("Создан");
}
os.writeObject(gamers);
os.close();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream("student.ser");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
test = new ArrayList<>();
while (true){
test.add(objectInputStream.readObject());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(test.get(0));
}
Here is the error log for the exception thrown:
java.io.StreamCorruptedException: invalid stream header: 79737200
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:866)
at java.io.ObjectInputStream.(ObjectInputStream.java:358)
at Registratsiya.AllGamers.main(AllGamers.java:48)
Exception in thread "main" java.lang.NullPointerException
at Registratsiya.AllGamers.main(AllGamers.java:61)
This question already has answers here:
Appending to an ObjectOutputStream
(6 answers)
Closed 5 years ago.
I have a program utilizing the memento design pattern and want to save the state of each object into a file using serialization and return the object back. The problem is that I get a "java.io.StreamCorruptedException: invalid type code: AC" exception due to corrupt headers. I looked at Appending to an ObjectOutputStream and tried to implement the class but still can't get the program to work properly. Multiple objects should be saved in a file and the user passes a string into a function which should match part of the object's string representation.
public class Caretaker implements Serializable {
public void addMemento(Memento m) {
try {
// write object to file
FileOutputStream fos = new FileOutputStream("ConeOutput1.txt", true);
BufferedOutputStream outputBuffer = new BufferedOutputStream(fos);
AppendableObjectOutputStream objectStream = new AppendableObjectOutputStream(outputBuffer);
objectStream.writeObject(m);
objectStream.reset();
objectStream.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public Memento getMemento(String temp) {
try {
Memento result = null;
FileInputStream fis = new FileInputStream("ConeOutput1.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
result = (Memento) ois.readObject();
while (result != null) {
Matcher m = Pattern.compile(temp).matcher(result.toString());
if (m.find()) {
return result;
}
else {
result = (Memento) ois.readObject();
}
ois.close();
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
public class AppendableObjectOutputStream extends ObjectOutputStream {
public AppendableObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
#Override
protected void writeStreamHeader() throws IOException {}
}
You should only use the appending ObjectOutputStream if the file already exists with data in it. If the file is new it needs the object stream header.
Please consider these codes: Is it possible to use FileWriter and FileReader with object of class student?
Student s1 = new Student();
s1.input();//I want to write this method in a File
FileWriter out2 = new FileWriter("input.txt");
out2.write();
out2.flush();
out2.close();
s1.display();//I want to Read this method in a File
FileReader in2 = new FileReader("input.txt");
in2.read();
in2.close();
Yes, you can save any Object you like with FileOutputStream and get it with FileInputStream (as Object, you need casting after this). Just try it out.
As an example:
FileOutputStream fos = null;
ObjectOutputStream writer = null;
Student data = new Student();
try{
fos = new FileOutputStream(fileName);
writer = new ObjectOutputStream(fos);
writer.writeObject(data);
}
catch (IOException ex){
ex.printStackTrace();
}
Just remember closing it and doing the exception exercise :-).
Since I found an old full-working example-class you may want have a look into it (that's pretty ugly code, but it does the job):
import java.io.*;
public class Test {
static boolean checkFile(File file) {
if (file != null) {
if(file.isFile()){
return true;
}
try {
file.createNewFile();
} catch (IOException e) {
System.err.println("Error creating " + file.toString());
}
if (file.isFile() && file.canWrite() && file.canRead())
return true;
}
return false;
}
static boolean writeFile(String dat, Object data){
FileOutputStream fos = null;
ObjectOutputStream writer = null;
try{
fos = new FileOutputStream(dat);
writer = new ObjectOutputStream(fos);
writer.writeObject(data);
}
catch (IOException ex){
ex.printStackTrace();
return false;
}
finally{
try{
if(writer!=null){
writer.close();
}
}
catch (IOException ex){
ex.printStackTrace();
}
try{
if(fos!=null){
fos.close();
}
}
catch (IOException ex){
ex.printStackTrace();
}
}
return true;
}
static Student readFile(String dat){
FileInputStream fis = null;
ObjectInputStream reader = null;
Student student = null;
try{
fis = new FileInputStream(dat);
reader = new ObjectInputStream(fis);
student = (Student) reader.readObject();
}
catch (Exception ex){
ex.printStackTrace();
}
finally{
try{
if(reader!=null){
reader.close();
}
}
catch (IOException ex){
ex.printStackTrace();
}
try{
if(fis!=null){
fis.close();
}
}
catch (IOException ex){
ex.printStackTrace();
}
}
return student;
}
public static void main(String[] args){
Student student = new Student("Horst");
String filename = "input.txt";
boolean worked = false;
if(checkFile(new File(filename)))
worked=writeFile(filename, student);
student = new Student("not Horst");
if(worked)
student= (Student) readFile(filename);
System.out.println("Student : " + student.name);
}
}
class Student implements Serializable{
public String name;
public Student(String name){
this.name=name;
}
}
List ll=new LinkedList();
Student temp;
int size = obj.readInt();
System.out.println(size);
for (int i = 0; i <size; ++i) {
ll.add((Student) obj.readObject());
}
obj.close();
System.out.println(ll);
}
it causes the run time exception as
"Exception in thread "main" java.io.EOFException
at java.io.DataInputStream.readInt(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.readInt(Unknown Source)
at java.io.ObjectInputStream.readInt(Unknown Source)
at p1.DeSerializeDemo1.main(DeSerializeDemo1.java:18)"
Please give me solution for this.
EOFException in ObjectInputStream.readInt means that there are less than 4 bytes left in the file after current position.
Just handle the Exception
try{
int size = obj.readInt();
}catch(EOFException ex){}
Why don't you create a class and save/load the entire object (that class needs to implement Serializable though (and all objects used it that class too)), then get the information you want using that object you can cast it afterwards:
public static Object load(String path) throws FileNotFoundException, Exception {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path))) {
final Object result = ois.readObject();
ois.close();
return result;
}
}
public static void save(Object obj, String path) throws Exception {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path))) {
oos.writeObject(obj);
oos.flush();
oos.close();
}
}
Exception cause is that you are not calling ObjectOutputStream.writeInt(int) before writing objects. As far as I understand you are trying to store number of objects, which is stored in the file. So, you should do it like this: obj.writeInt(2);
public class Test implements Serializable {
private static final long serialVersionUID = 243705916609512381L;
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static void main(String[] args) {
Test s = new Test();
s.setName("Test");
Test s1 = new Test();
s1.setName("Test 2");
ObjectOutputStream oos = null;
FileOutputStream fileOutputStream = null;
FileInputStream fileInputStream = null;
ObjectInputStream ois = null;
try {
fileOutputStream = new FileOutputStream("C:\\test.txt");
oos = new ObjectOutputStream(fileOutputStream);
oos.writeInt(2);
oos.writeObject(s1);
oos.writeObject(s);
oos.flush();
oos.close();
fileOutputStream.close();
fileInputStream = new FileInputStream("C:\\test.txt");
ois = new ObjectInputStream(fileInputStream);
int readInt = ois.readInt();
System.out.println("Read int " + readInt);
Test readObject = (Test) ois.readObject();
System.out.println(readObject.getName());
Test readObject2 = (Test) ois.readObject();
System.out.println(readObject2.getName());
ois.close();
fileInputStream.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// close everything
}
}
My idea is that I want to read an object from a serialized file located in a server. How to do that?
I can only read .txt file using the following code :
void getInfo() {
try {
URL url;
URLConnection urlConn;
DataInputStream dis;
url = new URL("http://localhost/Test.txt");
// Note: a more portable URL:
//url = new URL(getCodeBase().toString() + "/ToDoList/ToDoList.txt");
urlConn = url.openConnection();
urlConn.setDoInput(true);
urlConn.setUseCaches(false);
dis = new DataInputStream(urlConn.getInputStream());
String s;
while ((s = dis.readLine()) != null) {
System.out.println(s);
}
dis.close();
} catch (MalformedURLException mue) {
System.out.println("Error!!!");
} catch (IOException ioe) {
System.out.println("Error!!!");
}
}
You can do this with this method
public Object deserialize(InputStream is) {
ObjectInputStream in;
Object obj;
try {
in = new ObjectInputStream(is);
obj = in.readObject();
in.close();
return obj;
}
catch (IOException ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
catch (ClassNotFoundException ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
feed it with urlConn.getInputStream() and you'll get the Object. DataInputStream is not fit to read serialized objets that are done with ObjectOutputStream. Use ObjectInputStream respectively.
To write an object to the file there's another method
public void serialize(Object obj, String fileName) {
FileOutputStream fos;
ObjectOutputStream out;
try {
fos = new FileOutputStream(fileName);
out = new ObjectOutputStream(fos);
out.writeObject(obj);
out.close();
}
catch (IOException ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}