BRGproj docu

Als ich 2008 das BRG Viktring Schülerforum abschaltete, planten wir von Anfang an eine informative Nachlassseite, die unsere gemeinsame Zeit dokumentieren soll. Dieses Ziel wurde jetzt für mich erreicht und ich möchte eine Dokumentation der abgeschalteten BRGproj veröffentlichen. Dies inkludiert:

  • BRG_HP (homepage)
  • BRG3 / BRG4 (board)
  • BRGblog (weblog)
  • BRGwiki (wiki)
  • BMS (blog management system)
  • BDB (BRGproj development blog)

>>> zur Dokumentation

Sie zeigt Zeitleisten, Statistiken und beschreibt die Ereignisse rund um meine ersten Softwareprojekte.

Großer Dank an Peter, Stefan und Toja! :-)

Aren’t we supposed to check for SQL-injection?

> 2) Aren’t we supposed to check for SQL-injection?
No, the course has nothing to do with security.

via tugraz Newsgroup.

<IMHO>I agree, that you should not mix up course contents. But I disagree that good practice should not be taught. So: Disagree.</IMHO>

How FLOSS does not work

Pythonists are working on a stackoverflow alternative publicly available in the pypi ([pypi] [website] [github]). At the same time a company is working on a stackoverflow alternative privately for a customer.

Please repeat yourself and reinvent the wheel. This is where the software industry is going nowadays. The boundaries between company contexts and voluntary projects are too broad to be crossed in a copyright-driven society.

The top 10 signs you’re a computer scientist

  1. You explain your kids the clock using the word “modulo”
  2. If you terminate all your sentences with a NULL byte\0
  3. If you extend your 101-keys-keyboard for 42 more keys
  4. If you answer infinity calculations in math courses with “BufferOverflow”
  5. If you have to andl $-16, %esp your priority queue if your boss assigns you a new task
  6. If you think you know more about inheritance than biologists
  7. If execution, command and kill are harmless words for you
  8. If you think that 2 spaces are missing in the source code, but you cannot explain the why to someone else.
  9. If (0.1 + 0.7) * 10 is anything else than 8 for you
  10. You expected a list with 102 elements here

based on spikedmath:456.

Harvard CS75

Just some short notes/comparisons about watching the CS 75 course of Harvard university (you can download it at cs75.tv):

  • There is more interaction between students and professors than here. Students here prefer not to question lecture content and questions to the audience have higher response times than in Harvard. I think one of the major reasons include the missing reaction to problems (“XY at slide Z is incorrect” will be ignored even though the lecturer agreed at the lecture).
  • The professor is well prepared and has a specific topic to finish in one lecture. Whereas the second is true in most cases here, the first one cannot be satisfied by slides of previous years and out-dated course websites
  • Specifically about this topic: The first OOP source code of PHP you will see here is out-dated PHP 4. Even though there are more lectures, topics like scalability are not part of the course here.

Liked it :-)

First marzipan experiments

Marzipan figures animals photo

Marzipan Animals

Marzipan figures animals 2nd photo

Marzipan animals

Inkscape PDF Export stopped working

Save As Copy with extension pdf worked very well for almost a year. Suddenly it stopped working. PDF export resulted in File {FILENAME}.pdf could not be saved. Very uncomfortable for me as far as I am using SVGs on a regular basis.

The internet is filled up the bug reports… some are having specific plugin problems, some only get blank PDF pages. Well… this Inkscape 0.47 bug report got the solution for me. Remove the preferences.xml file (for me ~/.config/inkscape/preferences.xml) and Inkscape will create a new one when starting up.

What is the reason? I think some important package got upgraded and Inkscape is holding some old, conflicting information about this package.

Tags: Inkscape 0.47 pdf export SVG could not be saved preferences cairo

switch/case in assembly

Because of a discussion with my brother I got curious about the internal handling of switch/case statements in assembly. So I compiled the stuff and studied it. Furthermore I wrote an article about it. I thought an external document is a better approach:

“switch in amd64 assembly” [HTML]

Twiki and 8 character passwords

At university, TWiki is a pretty common software. At least at the second Google search results page (for “twiki” as search term) I can see some twiki running at our university’s webserver. TWiki is written in perl and I will refer to the deprecated 4.1.x version which was my test system. I got annoyed by limited security for passwords. Passwords are limited to 8 characters.

Login Managers

During installation you will face a select field like this (in the “Security Setup” section):

Twiki Loginmanager in Installation

All those selections refer to different password management backends. Twiki::Client::ApacheLogin is implemented by /twiki/lib/TWiki/Users/ApacheHtPasswdUser.pm and Twiki::Client::TemplateLogin is implemented by /twiki/lib/TWiki/Users/HtpasswdUser.pm. In /twiki/lib/TWiki/Users/Password.pm the interface is defined. You can check out funny source code sequences like this:

86 —++ ObjectMethod checkPassword( $user, $passwordU ) -> $boolean
87
88 Finds if the password is valid for the given login.
89
90 Returns 1 on success, undef on failure.
91
92 =cut
93
94 sub checkPassword {
95 return 1;
96 }

Well… this is our interface. Let’s have deeper look into the implementation.

Twiki::Client::ApacheLogin

ApacheLogin uses the Apache interface to send 401 HTTP Status codes. If the client receives one of those status codes, a Username and Password Dialog pops up.

Password Dialog for 401 Status Codes

Using this dialog, the login information will be sent to the server. Using a loop in perl, we can print out what the server receives as CGI variables (the ones defined by the server and given to the perl interpreter). I have put the following source code into /twiki/lib/Twiki/Users/HtPasswdUser.pm subroutine new (don’t forget to include Data::Dumper).

my $key;
foreach $key (sort(keys %ENV)) {
print STDERR Data::Dumper->Dump([ $ENV{$key} ], [$key]);
}

From the Apache log, we will get the following information.

[...]
HTTP_COOKIE = 'TWIKISID=d00fe404e65832f9d95658d6d9112bec';, referer: /twiki/bin/logon/TWiki/TWikiRegistration
[...]
REDIRECT_REMOTE_USER = 'LukasProkop';, referer: /twiki/bin/logon/TWiki/TWikiRegistration
[...]
REDIRECT_STATUS = '401';, referer: /twiki/bin/logon/TWiki/TWikiRegistration
[...]

Actually I was looking for REMOTE_USER, which is a CGI variable only defined when Authorization was done. The cookie is not really interesting, but REDIRECT_STATUS approves that auth was done. REDIRECT_REMOTE_USER seems to be REMOTE_USER I am looking for… in some way. Alright… so what do we have here? Well… password and username associations are tested automatically by the Apache server and perl will not receive the password itself. Perl can assume that auth was done successfully and does not recognize it any further. Alright. So we have to determine where the passwords are stored.

Passwords for mod_auth are stored in .htpasswd files. A small UNIX find will return /twiki/data/.htpasswd. This file is updated for each change by the perl script.

LukasProkop:11/Yysc0Op9D2:unixuser@localhost

So the password is stored as a hash associated with the Login name and the local user name. Now let’s come to our real topic: Passwords with more than 8 characters. Let us create some additional accounts.

Username Password
KarlOrff 1234567
CamrinaBurana 123456789
DiesIrae 123456789123456789
SixteAjoutee 1234567689123456780

Well… our .htpasswd says:

CarminaBurana:UXjIprwRygc1.:unixuser@localhost
DiesIrae:UtCp6NoUsQdaQ:unixuser@localhost
KarlOrff:7kQC9KJ/39yA.:unixuser@localhost
LukasProkop:11/Yysc0Op9D2:unixuser@localhost
SixteAjoutee:R07ipKyeiYlho:unixuser@localhost

Now let’s log in with various accounts. As far as Twiki does not support a Logout button, the most comfortable way is to delete the cookie (see above) and refresh the page. Now we can see our problem: SixteAjoutee and DiesIrae can log in with each other ones password. The strange thing is, that their hashes are different. Our source code journey goes on…

Violation of second-preimage resistance?

$TWiki::cfg{Htpasswd}{Encoding} = 'crypt';

Our configuration file at /twiki/lib/LocalSite.cfg defines a variable for the various encoding algorithms. Of course such a variable is a perfect name to search for. The configure uses this variable, but HtPasswdUser.pm is the only other file.

The file encrypting the password is HtPasswdUser.pm at line 134. This file will apply the crypt function with a random salt to the password. The salt is 2 characters in length and stored at the front of the actually stored password. A small test script reveals the truth:

print crypt("123456789123456789", "Ut") eq "UtCp6NoUsQdaQ";
print crypt("123456789123456780", "R0") eq "R07ipKyeiYlho";

So there we have our problem. crypt uses the DES algorithm from the operating system and is limited to an input of 8 characters.

print crypt("12345678B", "Ut") eq "UtCp6NoUsQdaQ";
print crypt("12345678A", "R0") eq "R07ipKyeiYlho";

The collision-free solution

Of course the algorithm is the problem and a selection of another algorithm like sha1 (nope, no MD5!) would solve the problem. We do not rely on the operating system or missing implementations of other crypto algorithms.

#!/usr/bin/perl -wT

require MIME::Base64;
import MIME::Base64 qw( encode_base64 );
require Digest::SHA1;
import Digest::SHA1 qw( sha1 );

sub get
{
my( $passwd ) = @_;

my $encodedPassword = '{SHA}'.
MIME::Base64::encode_base64( Digest::SHA1::sha1( $passwd ) );
$encodedPassword =~ s/\s+$//;
return $encodedPassword;
}

print get("1234568B"), "\n";
print get("1234568A"), "\n";

This program returns two different hashes:

{SHA}sgDumzcRNpPJL8tCgM18JIR1ayc=
{SHA}RsUxZFkQgYAeTdsPmIixTYEdFgg=

Migration

How can thousands of user accounts be migrated to another algorithm? As far as the hash is stored as a one-way encrypted string, the encryption of the real password with another algorithm is almost impossible. I have written a small crypt() cracking program in python (sorry, Perl ;-) ), but of course it is way too slow; even for a single password. So the only solution is to reset all passwords of all users. First call the /twiki/bin/configure script and change the algorithm setting (“{Htpasswd}{Encoding}” in the “Security Setup” section) [0] and secondly, BulkResetPassword will help you reset the passwords for all users. It takes some effort and time, but in the end you will gain a higher level of security :-)

[0] It is also possible to directly modify the $TWiki::cfg{Htpasswd}{Encoding} line in /twiki/lib/LocalSite.cfg

HowTo: Bugfix file too large for wordpress importer

During the update to WordPress 3.2, I encountered (like many other people) the problem with limitation of the filesize for file uploads. Per default PHP will set it to 2MB whereas my wordpress export backup file (XML) has already 4MB. No, reconfiguring PHP’s upload_max_filesize was no option for me as far as the backup was already stored as a dump at the server. So my only thing to do was to replace the uploaded file with the already existing at the harddisk and make WordPress recognizing it. And this was not that difficult if you know where to look for. So here is my patch to get the wordpress-importer import a file already stored at the server hard disk. The wordpress export file to load has to be stored at wp-content/uploads/wordpress.import.xml.

diff --git a/wp-content/plugins/wordpress-importer/wordpress-importer.php b/wp-content/plugins/wordpress-importer/wordpress-importer.php
index 5e38484..e0cace0 100644
--- a/wp-content/plugins/wordpress-importer/wordpress-importer.php
+++ b/wp-content/plugins/wordpress-importer/wordpress-importer.php
@@ -102,6 +102,7 @@ class WP_Import extends WP_Importer {
         * @param string $file Path to the WXR file for importing
         */
        function import( $file ) {
+               $file = ABSPATH . 'wp-content/uploads/wordpress.import.xml'; #wp_import_handle_upload();
                add_filter( 'import_post_meta_key', array( $this, 'is_valid_meta_key' ) );
                add_filter( 'http_request_timeout', array( &$this, 'bump_request_timeout' ) );

@@ -132,7 +133,7 @@ class WP_Import extends WP_Importer {
        function import_start( $file ) {
                if ( ! is_file($file) ) {
                        echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />';
-                       echo __( 'The file does not exist, please try again.', 'wordpress-importer' ) . '</p>';
+                       echo __( 'The file '.htmlspecialchars($file).' does not exist, please try again.', 'wordpress-importer' ) . '</p>';
                        $this->footer();
                        die();
                }
@@ -188,7 +189,7 @@ class WP_Import extends WP_Importer {
         * @return bool False if error uploading or invalid file, true otherwise
         */
        function handle_upload() {
-               $file = wp_import_handle_upload();
+               $file = array('id' => 4869, 'file' => ABSPATH . 'wp-content/uploads/wordpress.import.xml'); #wp_import_handle_upload();

                if ( isset( $file['error'] ) ) {
                        echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />';

I did not put any further (compatibility) research into that issue. Worked for me™ with WordPress Version 3.2 and PHP Version 5.3.

WordPress FAQ: Import and Export