Category Archives: Programming

Oddtale – Writing with strangers

So to take a break in my writing, I decided to start a new project. It was first supposed to be an Easter project, but it turned out to take a lot more time than I first thought. It’s a game called “Oddtale” where anyone can register with their name and email (no password needed, yet) and write a chapter in the current story. Authors are picked at random from the current pool of registered users, and the one who gets picked can write as little or as much (there are limitations, but they are big enough to write an okay chapter) as they want. Each author, except the first one, gets a hint from the previous chapter, to make things a little easier.

One story has ten chapters, and when the current story finishes, it gets automatically published on the site for everyone to view. A few hours later, the next story starts and people can join and write on that one as well. I’m planning more advanced features like private/public writing groups for people who don’t want to wait to get picked in the main one, as well as more advanced writing tools like a wysiwyg editor with the support for bbcode tags. There are more features planned, but these two are the biggest ones that are currently in the works. I wont publish a new version for a while though as I want to see if the main idea with the site in its current state, can draw any attention. The game is pretty pointless if no one wants to play.

The address for the game is: https://oddtale.net/

Oh, and we also have a mascot (who you will see a lot more of if the game gets an active player base). The mascot was made by Nicole (Bunnico) on Fiverr.

Uploading dangers

A few weeks ago I was reading a forum thread about file upload scripts in the PHP scripting language. The people in the thread were discussing different ways of handling different file types when allowing users on their websites to upload files to the server. Security wasn’t really on the topic here, but there were still mentions of it. The most common problem that is mentioned when it comes to file uploading is that there is a need to somehow restrict what kind of files the users are allowed to upload, how to handle them once they are on the server and so on.

In this case their solution was to disallow users from uploading files with the php extension, and then by using a PHP function called ImageJpeg they would verify that the users were uploading valid pictures (The forum user in question was making an image upload script for his community website). Now, as a developer I can see why this seems like a pretty nice idea, since the data would be verified and changed in the ImageJpeg function. If the file was not a valid image then the function would return false and the file would not be properly uploaded. And even if a malicious user were to put code within the data part of the image, that data would always be changed when the ImageJpeg function has finished and saved the file to disc.

The so called “black listing” of file extensions is usually not a good idea since there exists many different alternatives to one executable extension. If we take the example above where they prevented users from uploading files with the php extension. PHP has 5 alternative extensions, these being .php3, .php4, .php5, .phtml and .phps. And if a developer of a script only restricts .php, then the other 5 can be used instead to upload malicious code to the server.

I found it an interesting topic and decided to see if I can somehow bypass their protection and upload executable code to my test server using their upload scripts. The first thing that came to mind was that jpeg images allow so called “exif” data that can hold comments for image viewers and editors to display in different ways. Although this bubble burst rather quickly as I discovered that the ImageJpeg function always overwrites the exif data with its own, including the comments.

So now I had to fire up a hex editor and get to work, and see if I can insert data into the image itself, while making sure it’s still a valid image that would pass through the ImageJpeg function. The difficulty with this, just as discussed in the thread, was that the data was always changed and thus my code was not intact when the file was saved to disc. The image would in almost all cases be a valid one, although a bit distorted due to my meddling.

After hours of playing around with this I managed to get an image that when injected with code and run through the function, the code would still be intact and executable on my server.

hex

So after even more hours of trying to perfect this method, making sure the image is always a valid one and that it’s not too distorted from the changes, I wrote a script that injects the code automatically and makes sure that the code will still be there after being changed with different image handling tools, like the ImageJpeg function (It was also tested with tools that performs resize on the picture, and although this worked in many cases it was significantly harder to retain the code after processing).

Below is the picture before the injection

logo

Followed by the picture after the injection (notice how in this example, the picture got a little bit distorted at the end. This varies from case to case). Don’t worry, the code can’t execute in its current form.

logo_mod

So to summarize. After a few days I did manage to bypass their protection followed by writing a script to automate it all. Some example output from the script can be seen below.


[+] Jumping to end byte
[+] Searching for valid injection point
[+] Injection completed successfully
[+] Filename: result.phtml

And to top it up I also made a small script to send commands to the file once it has been uploaded to a server, parse the results out of the image data once returned and display it.


uname -a
Linux truesechp01 3.13.0-29-generic #53-Ubuntu SMP Wed Jun 4 21:00:20 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

And this shows how very easy it is for things to go wrong with file upload functionality. There are so very many ways to do bad things with it, and a motivated attacker can in many cases spend days, months or even years to find a way around your protection mechanisms. The trick I have showed you in this article today is not limited to PHP, but can be applied in other environments as well. There are a few measures that can be good enough depending on the situation when handling uploaded files to a server, but there’s no silver bullet as there are in many cases ways to circumvent them as well, the best example being that the developer who implements it simply does it wrongly (classic one is that they only check for the presence of .jpg in a filename, which would then allow the uploading of a file.jpg.php).

For those who decide to solve all this by using blacklisting and block file extensions like .php,.phtml,.php4,.php4,.php5. Be aware, PHP 6 will be released eventually 😉

Wrote an EAN13 barcode program

I decided to write a barcode generator in Java “for no apparent reason”, that can currently generator EAN13 barcodes. It’s available here in this post, but if you want the latest code then I suggest you check it out on github.

Github repo:
https://github.com/jra89/barcode

Usage:

[code]
java -jar barcode.jar numbers path barwidth barheight
[/code]

Example:

[code]
java -jar barcode.jar 999990000020 /home/user/Desktop/EAN_IMG.png 2 60
[/code]

Main.java

[code lang=”java”]
package barcode;

public class Main
{
public static void main(String[] args)
{
String code;
String path;
int barWidth;
int barHeight;

if(args.length <= 1)
{
System.out.println("Not enough parameters");
}

try
{
code = args[0];
}
catch(NullPointerException e)
{
code = "9999900000207";
}

try
{
path = args[1];
}
catch(NullPointerException e)
{
path = "/tmp/barcode.png";
}

try
{
barWidth = Integer.parseInt(args[2]);
}
catch(NullPointerException e)
{
barWidth = 1;
}

try
{
barHeight = Integer.parseInt(args[3]);
}
catch(NullPointerException e)
{
barHeight = 100;
}

Ean13 ean = new Ean13(code, path, barWidth, barHeight);
ean.createBarcodePNG();

}
}
[/code]

Ean13.java

[code lang=”java”]
package barcode;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class Ean13
{
/**
* -=Structure=-
*
* Fist, First Six, Last Six
* LGR = 012
* 0 LLLLLL RRRRRR
* 1 LLGLGG RRRRRR
* 2 LLGGLG RRRRRR
* 3 LLGGGL RRRRRR
* 4 LGLLGG RRRRRR
* 5 LGGLLG RRRRRR
* 6 LGGGLL RRRRRR
* 7 LGLGLG RRRRRR
* 8 LGLGGL RRRRRR
* 9 LGGLGL RRRRRR
*
* -=Encodings=-
*
* Digit L-code G-code R-code
* 0 0001101 0100111 1110010
* 1 0011001 0110011 1100110
* 2 0010011 0011011 1101100
* 3 0111101 0100001 1000010
* 4 0100011 0011101 1011100
* 5 0110001 0111001 1001110
* 6 0101111 0000101 1010000
* 7 0111011 0010001 1000100
* 8 0110111 0001001 1001000
* 9 0001011 0010111 1110100
**/

private String code;
private String path;
private BufferedImage bi;
private Graphics2D ig2;
private int barPos;
private int barPosBin;
private int imgPixelPos;
private int barWidth;
private int barHeight;
private int imgWidth;
private int imgHeight;
private int[][] barcodeBinary;

private int[][] firstSix = {
{0,0,0,0,0,0}, //LLLLLL
{0,0,1,0,1,1}, //LLGLGG
{0,0,1,1,0,1}, //LLGGLG
{0,0,1,1,1,0}, //LLGGGL
{0,1,0,0,1,1}, //LGLLGG
{0,1,1,0,0,1}, //LGGLLG
{0,1,1,1,0,0}, //LGGGLL
{0,1,0,1,0,1}, //LGLGLG
{0,1,0,1,1,0}, //LGLGGL
{0,1,1,0,1,0} //LGGLGL
};

private int[] lastSix = {2, 2, 2, 2, 2, 2};

private int[][][] encodings = {
{
{0,0,0,1,1,0,1},
{0,1,0,0,1,1,1},
{1,1,1,0,0,1,0}
},
{
{0,0,1,1,0,0,1},
{0,1,1,0,0,1,1},
{1,1,0,0,1,1,0}
},
{
{0,0,1,0,0,1,1},
{0,0,1,1,0,1,1},
{1,1,0,1,1,0,0}
},
{
{0,1,1,1,1,0,1},
{0,1,0,0,0,0,1},
{1,0,0,0,0,1,0}
},
{
{0,1,0,0,0,1,1},
{0,0,1,1,1,0,1},
{1,0,1,1,1,0,0}
},
{
{0,1,1,0,0,0,1},
{0,1,1,1,0,0,1},
{1,0,0,1,1,1,0}
},
{
{0,1,0,1,1,1,1},
{0,0,0,0,1,0,1},
{1,0,1,0,0,0,0}
},
{
{0,1,1,1,0,1,1},
{0,0,1,0,0,0,1},
{1,0,0,0,1,0,0}
},
{
{0,1,1,0,1,1,1},
{0,0,0,1,0,0,1},
{1,0,0,1,0,0,0}
},
{
{0,0,0,1,0,1,1},
{0,0,1,0,1,1,1},
{1,1,1,0,1,0,0}
}
};

Ean13(String code, String path,int barWidth, int barHeight)
{
this.code = code;
this.path = path;
this.barPos = 12;
this.barPosBin = 7;
this.imgPixelPos = 0;
this.barcodeBinary = new int[barPos][barPosBin];
this.barWidth = barWidth;
this.barHeight = barHeight;
this.imgWidth = ((12*7) + (2*9) + (2*3) + (1*5)) * this.barWidth;
this.imgHeight = this.barHeight;
}

public void createBarcodePNG()
{
this.code += Integer.toString(calculateControlDigit(this.code));
generateBinaryMap();
generateBarcodePNG();
}

private void generateBinaryMap()
{
int first = Integer.parseInt(String.valueOf(this.code.charAt(0)));

//i = 1, first digit is not welcome to the bar
for(int i = 1; i < 13; ++i)
{
int current = Integer.parseInt(String.valueOf(this.code.charAt(i)));

if(i < 7)
this.barcodeBinary[i-1] = this.encodings[current][this.firstSix[first][i-1]];
else
this.barcodeBinary[i-1] = this.encodings[current][this.lastSix[i-7]];
}
}

private void generateBarcodePNG()
{
try {
// TYPE_INT_ARGB specifies the image format: 8-bit RGBA packed
// into integer pixels
bi = new BufferedImage(this.imgWidth, this.imgHeight, BufferedImage.TYPE_INT_ARGB);
ig2 = bi.createGraphics();

ig2.setPaint(Color.white);
ig2.fillRect ( 0, 0, bi.getWidth(), bi.getHeight() );

//Draw quiet zone
drawSpecial(0);

//Draw lead
drawSpecial(1);

//Draw first group
drawGroup(1);

//Draw separator
drawSpecial(2);

//Draw second group
drawGroup(2);

//Draw lead
drawSpecial(1);

//Draw quiet zone
drawSpecial(0);

ImageIO.write(bi, "PNG", new File(path));

} catch (IOException ie) {
ie.printStackTrace();
}
}

private void drawGroup(int groupPart)
{
int i = 0, length = 0;
if(groupPart == 1)
{
i = 0;
length = (this.barcodeBinary.length/2);
}
else if(groupPart == 2)
{
i = 6;
length = this.barcodeBinary.length;
}

for(; i < length; ++i)
{
for(int n = 0; n < this.barcodeBinary[i].length; ++n)
{
if(this.barcodeBinary[i][n] == 0)
{
ig2.setPaint(Color.white);
ig2.setStroke(new BasicStroke(this.barWidth));
}
else
{
ig2.setPaint(Color.black);
ig2.setStroke(new BasicStroke(this.barWidth));
}

int pos = this.imgPixelPos;
ig2.drawLine(pos,0,pos,this.barHeight);
this.imgPixelPos += this.barWidth;
}
}
}

private void drawSpecial(int type)
{

/*
Special Symbol Pattern
Quite Zone 000000000
Lead / Trailer 101
Separator 01010
*/

int[] quiteZone = {0,0,0,0,0,0,0,0,0};
int[] leadtrail = {1,0,1};
int[] separator = {0,1,0,1,0};
int binaryArrLength = 0;
int[] arr;

if(type == 0)
{
binaryArrLength = quiteZone.length;
arr = quiteZone;
}
else if(type == 1)
{
binaryArrLength = leadtrail.length;
arr = leadtrail;
}
else
{
binaryArrLength = separator.length;
arr = separator;
}

for(int n = 0; n < binaryArrLength; ++n)
{
if(arr[n] == 0)
ig2.setPaint(Color.white);
else
ig2.setPaint(Color.black);

int pos = this.imgPixelPos;
ig2.drawLine(pos,0,pos,this.barHeight);
this.imgPixelPos += this.barWidth;
}
}

public int calculateControlDigit(String ean)
{
int sum = 0;
for(int i = 0; i < 12; ++i)
{
int val = charToInt(ean.charAt(i));
if((i+1)%2 == 0)
sum += val*3;
else
sum += val*1;
}

return (10 – (sum % 10));
}

private int charToInt(char c)
{
return Integer.parseInt(String.valueOf(c));
}
}
[/code]