最最休斯敦

……记录休斯敦之行的一些有趣的东东


最人性
闹钟。住旅馆里有一个GE牌很古老的收音机闹钟。每天早上会用美国乡村音乐和叽叽呱呱的西班牙文把我弄醒,感觉比国内的闹钟好很多。可惜国内很难买到,国外用的电源又不一样,否则就带一个回来了。


最可爱
Texas胖子多,越胖越爱吃糖。在德州餐馆的桌子上,糖自是必不可少,不过美国科技发达,吃的糖竟然大多不是用糖做的,都是0卡路里的。于是在一包真正的糖上看到了这样一句可爱的广告词:This sugar is made of sugar so it taste like sugar!


最少
出租车,想要像上海一样招手即来是想都别想的事情。


最长
等出租车,在休斯敦叫出租车我可吃了不少苦头。有一次在一家意大利餐馆吃完饭,那个waitress帮我们叫好出租车,把我们送到门口,祝我们have a nice evening以后……漫长地等待开始了……三个小时后这个waitress都下班了,看到我们四个中国人还坐在外面enjoy this very nice evening……


最逗
美国的小孩子真是很可爱,上海的小孩子从小受到的教育是“不和陌生人讲话”,美国的小孩子正好反过来,是“见到陌生人就朝你乐”。


最怪
在高速路边上看到壮汉乞丐,乞讨水平也不怎么样,一张牌子上写了几个字翻成中文意思就是:请给我99美分吃饭的钱。这如果是在中国…太没竞争力。


最美味
德州牛排顶呱呱。最好的 Steak House 叫做“Salt Grass”。


最便宜
在美国shopping一下也没多少东西会比中国便宜了,毕竟都是中国制造的,除了Levis的牛仔裤,碰上正好是打折,加上税才$20。


最酷
德州名言:You may all go to hell, and I will go to Texas.


最尴尬
莫过于在墨西哥餐馆面对菜单上一堆莫名的西班牙文了。本想点烤肉串的,但一时想不起英文单词,于是说到:Can you give me something like this, it has some meat on a stick. 侍者点头意会,过不多久拿了一只热狗过来说:I think this is what you want, meat on a stick~~


最搞笑
鸭鸭。美国人不吃鸭肉,美国的鸭子一般都是在社区的小湖边当宠物养的,于是美国的鸭鸭有两大特点:一长相比较花,二看到人会很主动地一摇一摆跑过来跟你打招呼,另外也顺便看看你是不是准备了吃的给它们。


最奇特
在美国看到一家土地面积堪比家乐福超市的’Container Store’,也就是卖容器的商店,里面有大大小小各式各样的盒子,最小的比如装药片的一个小盒,还要按照周一到周日分成七个格子,看来美国人都是整理狂。


最中国
一次坐出租,看到出租司机位子边上放着一本正在自学的书,书名叫“Feng Shui”。

Attack ericfish.com

第一次攻击,从自己的网站开始。


我几天前对自己刚写完的这个blog程序做了安全性测试,之所以现在贴出来是因为这两天把这些个问题都fix掉了,否则贴出来给大家攻击就不好了:)


基本信息:


PHP + MySQL


1. Blind SQL Injection


古老的欺骗


b) 因为这个show_id的值肯定是一个整数,而由request传入的是string,所以用(int)强制转换,PHP会把100001 AND ‘z’>’a’ 转换成100001


c) 如果数据库中没有这个id,直接转到404 error page:header(“location:404.php”);



2. Cross-Site Script


http://cyberai.com/inputfilter/


b) 过滤 <> 符号,<>符号是html代码的内容,可以用str_replace函数把他们替换成 &lt; 和 &gt;
$foo = str_replace(“<“,”&lt;”,$_REQUEST[‘info’]);
$foo = str_replace(“>”,”&gt;”,$foo);



小节,这是两个主要的应用开发的漏洞,其它比如Directory Listing 等属于服务器设置的问题。

Windows中安装mcrypt扩展库

前一篇文章详细讲了mcrypt,并提到了mcrypt在Linux中的安装,这里在简单提一下mcrypt 这个PHP extension 在windows环境的Apache上的安装方法。


1. php_mcrypt.dll需要libmcrypt.dll库支持,所以先下载这个库(http://ftp.emini.dk/pub/php/win32/mcrypt/libmcrypt.dll)


2.要使用该库,需将PHP5的安装目录添加到系统环境变量%PATH%中。


3.在php.ini 中找到
;extension=php_mcrypt.dll
改为:
extension=php_mcrypt.dll


4.重启Apache,搞定。


PS: 如果重启时报找不到libmcrypt.dll或者php_mcrypt.dll文件的错,可以尝试把这两个文件放到%windir%system32 目录下,应该也能解决问题。

PHP的加密函数库Mcrypt使用介绍

翻译文章,原文链接:
 
PHP Cryptography: An Introduction Using Mcrypt
作者:Robert Peake
翻译:ericfish


此文介绍双向加密算法,解释它于其它常用PHP函数的不同,比如md5和rot13,以及如何在单向哈希算法和双向加密之间做出正确的选择。同时介绍作为可动态加载php插件mcrypt的安装。文中将以加密cookies和数据库信息(如信用卡卡号)作为应用实例,以脚本语言的形式给出加密/解密方案,并提供编码、源码编译命令和创建新的插件的解决方案。


为什么要使用密码?
The human heart has hidden treasures,
In secret kept, in silence sealed.
-Charlotte Bront?, Evening Solace


人的本性中有着隐藏的欲望,从计算的角度来讲,这就是密码学。


密码学定义
英文牛津字典里的描述是:一种秘密的写作习惯…只有那些拥有密钥的人才能理解。
从现代定义应该是:用数学的方法将一种形式转换成另一种新的形式(加密),然后可以将新的形式转换回原来的形式(解密)。


比较
Scheme  Direction  Security        Results  Key?   Type 
md5        one-way    secure         same      no       hashing 
rot13       two-way     not secure  same      no       mapping 
mcrypt    two-way     secure         different  yes     encryption


首先必须指出的是mcrypt是一个双向加密算法,虽然它也有可以生成单向的哈希,但我们的主要用途还是能够同时加密和解密的能力。Md5则是一个单向的加密算法。
一个最简单的单向算法,比如把每个字符的ASCII码求和。示例如下:


Listing 1: A simple one-way mapping (one_way.php)


<?php


//return an ordinal summation
function one_way ($string){
for ($i=0; $i < strlen($string); $i++) {
$result += ord(substr($string,$i));
}
return $result;
}


$test_1 = “Hello, world.”;
$test_2 = “(%PHP Int’l Mag%)”;
$test_3 = “foo”;


print $test_1;
print ‘ = ‘;
print one_way($test_1);
print ‘<br />’;


print $test_2;
print ‘ = ‘;
print one_way($test_2);
print ‘<br />’;


print $test_3;
print ‘ = ‘;
print one_way($test_3);


?>


Listing 2: Browser Output


Hello, world. = 1174
(%PHP Int’l Mag%) = 1174
foo = 324


正如例子中所显示的,使用单向机密算法所得到的加密的值所对应的原文可能并不唯一。但md5和上面最简单的示例不同,它是一种能够保证输出唯一的算法。
md5的原则是:对每个输入a,它能够生产对应的一个b,但对每一个b而言,要把它在还原成a是很困难的。这就是为什么我们认为用单向算法生成唯一的hashes是安全的。Md5通常被用于创建唯一的文件签名并用来与其它的签名进行比较。
我还见过使用md5来加密用户在数据库中的密码。当用户输入他们的密码后,系统创建对应的md5 hash码,并与系统中存储的md5 hash码进行比较。如果他们相同,那么绝大部分情况下它们所对应的明文也是相同的。在PHP的加密算法中使用来DES来实现这一功能,DES是UNIX中/etc/passwd存储密码所使用的加密标准。这一点有时是很有用的,比如在php与htaccess间创建接口,或与/etc/password本身。


rot13是一种最简单的双向机密算法。该算法的规则是对26个字母分别使用其在字母表中右边第十三个字母替换。


Listing 3: A simple rot13 test (rot13.php)


<?php
$s = ‘abcdefghijklmonpqrstuvwxyz’;
$s_0 = str_rot13($s);


print ‘<code>’;
print $s;
print “<br />n”;
print $s_0;
print ‘</code>’;
?>



Listing 4: Output


abcdefghijklmonpqrstuvwxyz
nopqrstuvwxyzbacdefghijklm



很显然,rot13虽然简单但不安全。rot13一般用于世界性的新闻组网络系统中模糊一些敏感性文字,使它们必须通过解码才能被阅读。
需要指出的是一些更高级的算法比如base_64和rawurlencode 和rot13一样都属于映射的类型。它们都通过表格中一对一的字符映射实现。正因如此它们只能被用于暂时模糊数据。因为在数学上对这些类型的加密进行方向解密是比较容易实现的,所以它们不应该被视为一种安全的方案。
相比而言,mcrypt中提供的算法通过引入密钥的概念正好实现了以上两种算法的优点。一般来说密钥即密码的意思,它是可以由任何字符组成的针对特定算法定长的字符串。通过结合密钥和注入的随机数(称为’IV’),mcrypt加密算法的过程为每个待加密的唯一值a,加密后另外一个不同的值b被生成,这个b值如果要它还原成a,就必须将密钥和与加密时相同的随机数组返回给mcrypt解密算法。这才是真正意义上的加密,也是mcrypt库提供给我们的。


合理的使用
何时使用mcrypt?何时使用哈希或者映射?


如果你只是需要简单的模糊信息,那么映射就可以满足。所谓模糊,也就是说使数据不能被直接阅读。但如果你传输的是敏感数据,则不要用映射,因为数据并没有被真正地加密,它只是用一种可被预知的方式映射字符。
如果你只是需要比较数据,那么可以使用md5。它可以被用来比较文件、密码、甚至比较那些你不希望被别人猜到和复制的唯一键。你还可以使用md5用来作为对安全加密算法的附加安全手段,我们回在下面的文中提到。
如果你有信息被存储在不安全的地方,你的信息将会横穿互联网(如电子邮件),或者其它一些安全需求比较高的信息,那么就需要使用到mcrypt所提供的双向密钥加密算法了。


安装
此安装主要针对Linux系统,但对于UNIX(包括Mac OS X)和Windows系统也同样适用。对于Debian的用户,安装mcrypt也一样简单。


# apt-get install php4-mcrypt
# apacectl restart


我建议将mcrypt做为动态加载的插件安装到PHP中。它将使得PHP更容易维护和升级,因为你不用一直去重新编译。如果你一定要把mcrypt包含到PHP中,在命令行配置时可以用mcrypt=’/path/to/mcrypt’ 来加载。
但无论如何,首先你需要安装libmcrypt. Libmcrypt可以在SourceForge被下载。使用root用户输入:


# wget -c
‘http://path/to/nearest/sourceforge/mirror/
for/latest/libmcrypt’
# gunzip libmcrypt-X.X.X.tar.gz
# tar -xvf libmcrypt-X.X.X.tar
# cd libmcrypt-X.X.X
# ./configure


现在你应该已经把libmcrypt作为一个共享组件了(但不是一个PHP的共享组件)。运行命令:


# ldconfig


它将使得共享对象可以在C/C++开发中被使用。下面把mcrypt动态组件编译到PHP中。首先,你需要PHP-devel 包中包含的 ‘phpize‘ 命令。


当你当前运行的PHP中已经有了 PHP-devel 后,输入:


# cd ext/mcrypt
# phpize
# aclocal
# ./configure
# make clean
# make
# make install


现在/usr/lib/php4 目录下面应该有了mcrypt.so 的文件,在 /etc/php.ini 添加:


extension=mcrypt.so


然后输入命令:


# apachectl restart


这样我们就已经将mcrypt功能安装成功了。



测试Mcrypt
我写了一个嵌套循环的php页面,可以用于检验libmcrypt安装的完整性


Listing 5: A simple loop to test all ciphers and modes (mcrypt_check_sanity.php)


<?php
/* run a self-test through every listed
* cipher and mode
*/
function mcrypt_check_sanity() {
 $modes = mcrypt_list_modes();
 $algorithms = mcrypt_list_algorithms();


 foreach ($algorithms as $cipher) {
  if(mcrypt_module_self_test($cipher)) {
   print $cipher.” ok.<br />n”;
  }
  else {
   print $cipher.” not ok.<br />n”;
  }
  foreach ($modes as $mode) {
   if($mode == ‘stream’) {
    $result = “not tested”;
   }
   else if(mcrypt_test_module_mode($cipher,$mode)) {
    $result = “ok”;
   }
   else {
    $result = “not ok”;
   }
   print $cipher.” in mode”.$mode.” “.$result.”<br />n”;
  }
 }
}


// a variant on the example posted in
// mdecrypt_generic
function mcrypt_test_module_mode($module,$mode) {
 /* Data */
 $key = ‘this is a very long key, even too
 long for the cipher’;
 $plain_text = ‘very important data’;


 /* Open module, and create IV */
 $td = mcrypt_module_open($module,”,$mode, ”);
 $key = substr($key, 0,mcrypt_enc_get_key_size($td));
 $iv_size = mcrypt_enc_get_iv_size($td);
 $iv = mcrypt_create_iv($iv_size,MCRYPT_RAND);


 /* Initialize encryption handle */
 if (mcrypt_generic_init($td, $key, $iv) != -1) {


  /* Encrypt data */
  $c_t = mcrypt_generic($td, $plain_text);
  mcrypt_generic_deinit($td);


  // close the module
  mcrypt_module_close($td);


  /* Reinitialize buffers for decryption*/
  /* Open module, and create IV */
  $td = mcrypt_module_open($module, ”,$mode, ”);
  $key = substr($key, 0,mcrypt_enc_get_key_size($td));


  mcrypt_generic_init($td, $key, $iv);
  $p_t = trim(mdecrypt_generic($td,$c_t)); //trim to remove padding


  /* Clean up */
  mcrypt_generic_deinit($td);
  mcrypt_module_close($td);
 }


 if (strncmp($p_t, $plain_text,strlen($plain_text)) == 0) {
  return TRUE;
 }
 else {
  return FALSE;
 }
}


// function call:
mcrypt_check_sanity();
?>


如果其中的一些算法(英文叫cipher)能够正常工作,那么我们就开始将这些算法应用到实例中了。如果它们还不能工作,那么你还需要花一点时间在php.net上的mcrypt说明。


加密 Cookies
Cookies长久以来一直被打上来间谍软件(spyware)的烙印。这是因为大多数情况下它们在一种可预见的方式下使用。很多流行的站点将用户信息通过明文的方式存储在cookie里。恶意站点可以通过伪装成原站点的手段来获取这些信息。
这种方法还能引起原站点的安全性问题,比如在cookie中设置对该站点进行攻击的数据。
无论是第三方的站点窃取cookie信息,还是恶意用户通过更改cookie来攻击站点,都可以通过加密来避免。一个加密的cookie信息对于第三方是毫无用处的,而且它几乎不可能被篡改。
并不著名的PHP sessions也提供了一种安全存储cookie的方法,可以通过于session关联来保证安全。(However, brute force attacks using the common cookie value ‘PHPSESSID’ would soon defeat this layer of “security.” )更多关于session安全的问题可以阅读Chris Shiflett的文章:”The Truth About Sessions” ( www.php-mag.net/itr/online_artikel/psecom,id,513,nodeid,114.html ).
使用真正的加密算法的好处是你不被限制在使用一个唯一键值上。当你需要把一些重要的信息(如密码)放到cookie中,使用加密是最合适的方法。
最好将密钥的信息存放在服务器一端。
在Listing 6 中我们将用最简单的方法来实现两个方法,使用’ecb’模式的’blowfish’算法。因为ecb模式不需要IV,使得过程能够尽量的简单。


Listing 6: cookie encryption/decryption functions (twofish_cookie.php)


<?php


function my_encrypt($string) {
 $key = ‘supersecret’;
 $key = md5($key);


 /* Open module, trim key to max length */
 $td = mcrypt_module_open(‘twofish’,”,’ecb’, ”);
 $key = substr($key, 0,mcrypt_enc_get_key_size($td));


 /* Initialize encryption handle
 * (use blank IV)
 */
 if (mcrypt_generic_init($td, $key, ”) != -1) {
  /* Encrypt data */
  $c_t = mcrypt_generic($td, $string);
  mcrypt_generic_end($td);
  mcrypt_module_close($td);
  return $c_t;
 } //end if
}


function my_decrypt($string) {
$key = ‘supersecret’;
$key = md5($key);


/* Open module, trim key to max length */
$td = mcrypt_module_open(‘twofish’,”,’ecb’, ”);
$key = substr($key, 0,mcrypt_enc_get_key_size($td));


/* Initialize encryption handle
* (use blank IV)
*/
if (mcrypt_generic_init($td, $key, ”) !=-1) {


/* Encrypt data */
$c_t = mdecrypt_generic($td, $string);
mcrypt_generic_end($td);
mcrypt_module_close($td);
return trim($c_t); //trim to remove
//padding
} //end if
}


function my_encryptcookie($string) {
return base64_encode(my_encrypt($string));
}


function my_decryptcookie($string) {
return my_decrypt(base64_decode($string));
}


?>


注意我们使用了md5来加密字符串”supersecret”来生成密钥。并且算法的输出是定长的,并将不够的长度用空格代替,所以我们需要用trim()去掉这些返回的空格来还原它。
在加密后需要将字节输出转换成字符串,但在把密文传给解密函数前需要把它还原为字节码。这点在设置cookies和用于邮件传输协议数据的时候是很重要的。
接下来我们可以测试输出了:


<?php
include(“twofish_cookie.php”);
print my_decrypt(my_encrypt
(“Hello, world.<br />n”));
print my_decryptcookie
(my_encryptcookie(“Hello, world.<br />n”));
?>


因为加密解密函数的可逆性,我们同样还可以写成:


<?php
include(“twofish_cookie.php”);
print my_encrypt(my_decrypt(“Hello, world.”));
?>


但不能将base_64的函数用到加密中去,否则加密会出现问题:


<?php
include(“twofish_cookie.php”);
print my_encryptcookie(my_decryptcookie(“Hello, world.”));
?>



此时浏览器会输出:


Hello+worlc


因为base64是一个交迭的映射方法,此时base64_decrypt方法被使用在一个已解密的字符串上。因为在加密和解密中映射的相同,所以在rot13中交迭的部分是没有逻辑的,但base64中不同。我们来看一个设置cookie的例子,Listing 7.


Listing 7: set_twofish_cookie.php


<?php
include(“twofish_cookie.php”);
if($_COOKIE[‘test’]) print
my_decryptcookie($_COOKIE[‘test’]);
else {
$s = my_encryptcookie(“Hello, world.”);
if(setcookie(‘test’, $s, time()+3600)) {
print ‘Cookie set.’;
}
}
?>


当页面第一次载入的时候会设置一个加密的名为 ‘test’的cookie,在接下去再次从同一客户端访问时它将会返回解密后的cookie。
现在你已经成功的将一个加密的cookie值保存到了客户端浏览器中,并且成功的在应用中解密了这个信息。这种方法比起用base64或者URL来编码你的信息要更为有效得多,而且它比使用session的安全性要高得多。



加密SQL数据
现在我们来考虑一个更高技得应用。假如你在运营一个涉及信用卡信息得电子商务公司。你需要一个地方去存储这些信息,一般来讲SQL数据库是比较常见得选择。你可能会在每次交易 进行的时候存储这些数据,或者你需要更长时间的存储来实现一些预定的服务。而这些信息在数据库里面的时间越长,它们积累的可能性就高,你的数据库被恶意入侵的可能性也越高。如果所有数据都是用明文的方式存储在数据库中,那么一旦数据库被入侵,所有这些信息马上可以被入侵者所掌握。
另外,随着网上大量使用PHPMyAdmin来管理MySQL数据库,黑客就有了另外一种不涉及系统权限的入侵途径,它们能够在PHPMyAdmin下面建立目录的权限就足够了。如果数据是明文的,黑客只需要用本机浏览器就能够方便的获得这些敏感信息。
那么解决方法是什么呢?双向加密使你能够安全的保存和获得数据,因为当它们在数据库里,它们使加密的,当它们被显示给授权的用户时它们才被解密。(见 Listing 8)


Listing 8: AES Encryption (aes_sql.php)


<?php
function my_encrypt($string) {
 srand((double) microtime() * 1000000);
 //for sake of MCRYPT_RAND


 $key = ‘supersecret’;
 $key = md5($key);


 /* Open module, and create IV */
 $td = mcrypt_module_open(‘rijndael-128′,”,’cfb’, ”);
 $key = substr($key, 0,mcrypt_enc_get_key_size($td));
 $iv_size = mcrypt_enc_get_iv_size($td);
 $iv = mcrypt_create_iv($iv_size,MCRYPT_RAND);


 /* Initialize encryption handle */
 if (mcrypt_generic_init($td, $key, $iv) !=-1) {
  /* Encrypt data */
  $c_t = mcrypt_generic($td, $string);
  mcrypt_generic_deinit($td);
  mcrypt_module_close($td);
  $c_t = $iv.$c_t;
  return $c_t;
 } //end if
}


function my_decrypt($string,$key) {
 $key = md5($key);


 /* Open module, and create IV */
 $td = mcrypt_module_open(‘rijndael-128′,”,’cfb’, ”);
 $key = substr($key, 0,mcrypt_enc_get_key_size($td));
 $iv_size = mcrypt_enc_get_iv_size($td);
 $iv = substr($string,0,$iv_size);
 $string = substr($string,$iv_size);


 /* Initialize encryption handle */
 if (mcrypt_generic_init($td, $key, $iv) !=-1) {
  /* Encrypt data */
  $c_t = mdecrypt_generic($td, $string);
  mcrypt_generic_deinit($td);
  mcrypt_module_close($td);
  return $c_t;
 } //end if
}
?>


这里我们使用cbc模式,该模式包含了IV。所以预先生成我IV,因为它是定长,所以我们在解密前用了substr()函数。接下来是一个简单的测试。


<?php
include(“aes_sql.php”);


$string = “Hello, world.”;
print my_decrypt(my_encrypt($string),’supersecret’);
?>


注意到这里我们没有像cookie方法那样在这里创建包装函数。如果你需要将除了blob类型以外的数据存到数据库中去的时候,你需要像前面定义cookie函数那样定义包装函数,它将保证SQL屈居被正确的执行。
这个例子与前面cookie的例子另一个不同之处在于,这里的解密函数需要将密钥传进去。在网站系统中,可以将这个密钥与系统的密码关联。这种将密码传入解密函数的方法,为你的应用增加了一个安全级别,因为攻击者必须要知道这个密码才行。
然而如果入侵者可以进入到你的系统中,那么发现这个密码应该也不会是一件很困难的事情,因为它以明文方式写在你的PHP脚本之中。


接下去我们将讨论如何用加密的函数来模糊密码,从而进一步提高安全性。
你可以使用一些其它的数据库中的信息,也可以对密钥再进行加密,但这种方式变成了一种无限地循环。
The process of creating an automatic encryption scheme that is impervious to tampering if penetrated is ultimately beyond the scope of this article. We can, however, look at how to introduce some serious roadblocks.
第一种方法是考虑使用PHP encoder。第二种方法是通过编译命令行应用来做这个工作。


Listing 9: C my_crypt command line application


#include <mcrypt.h>
#include <stdio.h>
#include <stdlib.h>
/* #include <mhash.h> */
main( int argc, char *argv[] ) {
return my_crypt();
}


int my_crypt() {
MCRYPT td;
int i;
char *key;
char password[20];
char block_buffer;
char *IV;
int keysize=16; /* 128 bits */
key=calloc(1, keysize);
strcpy(password, “supersecret”);
/* Generate the key using the password */
/*
mhash_keygen( KEYGEN_MCRYPT, MHASH_MD5,
key, keysize, NULL, 0, password,
strlen(password));
*/


memmove( key, password, strlen(password));
td = mcrypt_module_open(“rijndael-128”,
“”, “cfb”, “”);
if (td==MCRYPT_FAILED) {
return 1;
}
IV = malloc(mcrypt_enc_get_iv_size(td));
/* Put random data in IV. Note these are not
* real random data, consider using
* /dev/random or /dev/urandom.
*/
/* srand(time(0)); */
for (i=0; i< mcrypt_enc_get_iv_size( td);
i++) {
IV[i]=rand();
}
i=mcrypt_generic_init( td, key, keysize,
IV);
if (i<0) {
mcrypt_perror(i);
return 1;
}
/* Encryption in CFB is performed in bytes
*/
while ( fread (&block_buffer, 1, 1, stdin)
== 1 ) {
mcrypt_generic (td, &block_buffer, 1);
fwrite ( &block_buffer, 1, 1, stdout);
}
/* Deinit the encryption thread,
* and unload the module
*/
mcrypt_generic_end(td);
return 0;
}


Listing 10: C my_decrypt command line application
#include <mcrypt.h>
#include <stdio.h>
#include <stdlib.h>
/* #include <mhash.h> */
main( int argc, char *argv[] ) {
char password[20];
if (argc < 2) {
return 1;
} else {
strcpy(password, argv[1]);
return my_decrypt(password);
}
}


int my_decrypt(char *the_pass) {
MCRYPT td;
int i;
char *key;
char password[20];
char block_buffer;
char *IV;
int keysize=16; /* 128 bits */
key=calloc(1, keysize);
strcpy(password, the_pass);
/* Generate the key using the password */
/*
mhash_keygen( KEYGEN_MCRYPT, MHASH_MD5,
key, keysize, NULL, 0, password,
strlen(password));
*/


memmove( key, password, strlen(password));
td = mcrypt_module_open(“rijndael-128”,
“”, “cfb”, “”);
if (td==MCRYPT_FAILED) {
return 1;
}
IV = malloc(mcrypt_enc_get_iv_size(td));
/* Put random data in IV.
* Note these are not real random data,
* consider using /dev/random or
* /dev/urandom.
*/
/* srand(time(0)); */
for (i=0; i< mcrypt_enc_get_iv_size( td);
i++) {
IV[i]=rand();
}
i=mcrypt_generic_init( td, key, keysize,
IV);
if (i<0) {
mcrypt_perror(i);
return 1;
}
/* Encryption in CFB is performed in bytes
*/
while ( fread (&block_buffer, 1, 1, stdin)
== 1 ) {
/* mcrypt_generic (td, &block_buffer,
1); */
/* Comment below and uncomment above to
* encrypt
*/
mdecrypt_generic (td, &block_buffer, 1);
fwrite ( &block_buffer, 1, 1, stdout);
}
/* Deinit the encryption thread, and unload
* the module */
mcrypt_generic_end(td);
return 0;
}


在PHP中可以做如下测试:


<?php
function my_crypt($string) {
return `echo “$string” | my_crypt`;
}


function my_decrypt($string,$password) {
return trim(`echo “$string” | my_decrypt
“$password”`);
}
?>


但这种方法的一个最大的弱点是因为它通过命令行调用,所以任何在系统中的用户可以输入:


# ps -aux


如果此时my_decrypt正在运行,他们就可以看到password。


所有这些说明了你可以不断的为那些进入到你的系统并想要解密你的数据的人制造障碍。但是不论如何被破解的可能性总是存在的。二战的时候英国捕获了一种叫Enigma的加密算法,不管该算法在当时来看是多么的复杂,最终它还是被解密了,并成功的获取到德国的机密信息。同样的,在计算机被入侵的情况下,加密的作用在于为了在对方解密之前,你能够重新取得计算机的控制权争取时间。



结论
现在相信你已经对mcrypt的作用有了一个不错的了解,但还有大量的关于加密算法的相关内容需要去发现。这也是我写此文的目的:帮助你获取一些关于mcrypt的信息,和一些加密算法信息,但并没有打算使它太过全面。


我们还审视了一些问题,比如如何存放密钥,因为PHP是一种明文的脚本更加加剧了这一问题,即使通过PHP编码或者编译成二进制编码也不能提供完全安全的解决方案。
我们通过两个例子:一个属于客户端的数据传输(通过cookie),另一个保存数据在服务器端(SQL)。mcrypt结合PHP能够帮助你在互联网上传输经过密钥加密的安全数据,从加密单调的数据结构到刚完成的情书。


下载原代码


Robert Peake has been a professional PHP developer and project manager since 2000. He is currently CTO for The David Allen Company. Reach him online: cyberscribe at php dot net.

This article was originally published in
Issue 03.04 of the International PHP Magazine.

Links and Literature
Please note that due to recent security concerns about colissions in MD5, SHA1 is now the preferred secure hash algorithm
For more on rot13 and Usenet see http://en.wikipedia.org/wiki/Rot13
Thanks to Eddie Urenda of UCLA for verifying the Debian libmcrypt install procedure
Much more on mcrypt is available at http://mcrypt.sourceforge.net/
For the gory details of MIME compliancy, see RFC 1521 at http://www.faqs.org/rfcs/rfc1521.html
Thanks to Derick Rethans of PHP for pointing out the significance of IV in non-ecb modes
For more on the role of Enigma in World War II see http://www.bbc.co.uk/history/war/wwtwo/enigma_04.shtml

编程挑战赛

刚刚报名参加了Google的中国编程挑战赛,感觉挺有意思的,有点像编程脑力风暴。


上次做这种事情还是7月份在找工作面试的时候,一次是某公司发给我一封邮件,里面写了程序要求和一个C#的Project代码,要我根据要求写一些东西,然后把写好的东西在第二天中午十二点前回复给它。因为我第二天还要上班,所以只好忙活了一个晚上。再后来就没有回音了,所以一直不知道正确答案,对此耿耿于怀。还有一次是现场面试,面试管出题,然后直接给我几张白纸看着我写程序,我在那怼了半天才终于写了点东西出来,发挥的并不好,不过倒的确是很好的锻炼。


所以我把这个比赛也是一个锻炼,有个目标能发现一点新的东西去思考是主要动力。


另外李开复说:做终身程序员是一件好事情 
的确是件好事情,不过在现在还是以做应用为主而非产品的中国,一辈子做程序员…不容易的。

古老的欺骗

要对PHP+Mysql的页面进行注射攻击是比较困难的,很大的原因是Mysql这个数据库功能不多,很多功能没有反倒加强了它的安全性。不过功能再怎么弱,程序上的漏洞还是不能免的,所以最近结合研究的PHP SQL Injuction 的一些问题,列举出相关可能存在的SQL安全漏洞。


php.ini中有一个参数叫 magic_quotes_gpc ,如果php.ini没有配置的默认情况下 magic_quotes_gpc=on。


它的作用是把所有从GET/POST/Cookie来的变量的单引号(‘)、双引号(“)、反斜杠backslash()以及空字元NULL(the null byte)都加上反斜杠,以使数据库能够正确查询。例如如果输入一个用户名是 a’b,传上来后反到变量里的值就是’a’b’,也就是说这个’还是存在于用户名变量中。


如果magic_quotes_gpc=off情况就不同了,这就是sql injuction有机可乘的时候。


如果原查询语句是这样的:
select * from login where user=’$HTTP_POST_VARS[user]’ and pass=’$HTTP_POST_VARS[pass]’


我们就可以在用户框和密码框输入 1′ or 1=’1 通过验证了。这是非常古董的方法了,这个语句会替换成这样:
select * from login where user=’1′ or 1=’1′ and pass=’1′ or 1=’1′
因为or 1=’1’成立,所以通过了。


解决的办法一:过滤所有不必要的字符,还有就是推荐对于从GET/POST/Cookie来的并且用在SQL中的变量加一个自定义的函数:
function gpc2sql($str) {
    if(get_magic_quotes_gpc()==1)
        return $str;
    else
        return addslashes($str);
}


解决办法二:不要用select * from login这种验证用户的方式,最好用select password from login where username=’$username’,然后再比较一下password是否相等,也同样可以避免这个注入的发生。


测试页面代码:


<?
if(isset($HTTP_POST_VARS[‘username’]))
{
 $username = $HTTP_POST_VARS[‘username’];
 $password = $HTTP_POST_VARS[‘password’];


 include(“db.php”);


 $db = mysql_connect($db_host,$db_user,$db_password);
 mysql_select_db($db_name,$db);
 $result = mysql_query(“SELECT * FROM table1 where name=’$username’ and password=’$password'”);
 $row=mysql_fetch_array($result);


 if($row)
 {
  $info = “login successfully.”;
 }
 else
 {
  $info = “login fail.”;
 }
}
?>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN” >
<HTML>
 <HEAD>
  <TITLE>Login</TITLE>
  <meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″>
 </HEAD>
 <BODY bgcolor=”#F3F3F3″>
   <table width=”450″ border=”0″ cellspacing=”0″ cellpadding=”0″ align=”left”>
     <tr>
    <td valign=”top” width=”130″></td>
    <td width=”320″>
       <br>
       <br>
       <br>
      <table width=”300″ border=”0″ cellspacing=”0″ cellpadding=”0″ bgcolor=”#F3F3F3″>
       <tr>
       <td>
       <form name=”entry” method=”post” action=”postback.php”>
     <table border=”0″ cellspacing=”0″ cellpadding=”3″ width=”100%”>
       <tr valign=”top”>
      <td colspan=4> <b>please log in: </b><br/>
      <?
      if(isset($info))
      {echo($info);}
      ?>
      </td>
       </tr>
       <tr valign=”top”>
      <td><br><br>user:</td>
      <td><br><br>
        <input type=”text” name=”username” tabindex=”1″ size=”10″ maxlength=”10″>
      </td>
      <td><br><br>pass:</td>
      <td><br><br>
        <input type=”password” name=”password” tabindex=”2″ size=”10″ maxlength=”30″ >
      </td>
       </tr>
       <tr valign=”top”>
      <td>&nbsp;</td>
      <td colspan=”3″>
        <input type=”image” border=”0″ name=”login” value=”login” width=”22″ height=”12″ alt=”press enter”>
        <input type=”image” border=”0″ value=”reset” name=”reset” width=”40″ height=”12″ alt=”reset form”>
        </td>
       </tr>
     </table>
       </form>
       </td>
       </tr>
       </table>
    </td>
     </tr>
   </table>
 </BODY>
</HTML>


参考文章:http://www.xfocus.net/articles/200107/237.html

做中学

记得上次换Blog界面是在今年的一月份,现在是十一月份,用了有差不多三百多天,说明这个“黑白鱼骨头”模板真的是很经典。看看前几次都没有那么久的 (1) (2) (3)


这次参照这个经典为我新的一个版块 _blank+Security 做了一个新的模板。
这个新的版块是一个与我现在的工作有挺大关系的地方,记录网站安全性的相关笔记,偏技术的。


每次改动Blog,都会让我重拾继续写的动力。突然发现要一直坚持做一件事情真是很不容易的,从最初的热情洋溢到后来的越写越少,很多blog都是如此。所以如果要坚持做某件事情,首先得把它做为一种习惯,同时也要不断的加入新鲜的东西进来。


这次不但设计了新的界面,连blog系统也一起换掉了。因为最近在研究php网站的完全性问题,正好在写一些php的page,所以顺带把这个也用php写出来。然后在 www.512j.com 申请了一个mysql的数据库放上来。在写这个系统的时候也正好研究了一下php的安全性问题,是一个“做中学”的好实例。


本来是用blogger.com来写的,不过已经长久不能用了,在blogger.com上写完放不到我的ftp上去。后来自己根据blogger.com的结构用C#写了一个本机的Windows程序,但因为用Access数据库,只能放在本地的一台机器上,这样我有时在公司写blog就不方便了,数据没法做到同步,发布也麻烦,所以后来也没兴趣再去维护那个东东了。