1. 程式人生 > >PHP黑魔法(該篇文章轉自:http://www.91ri.org/12634.html 目的是作為自己的筆記方便查找)

PHP黑魔法(該篇文章轉自:http://www.91ri.org/12634.html 目的是作為自己的筆記方便查找)

open Once font 註意 not 條件 思維 資料 echo

那些年我們學過的PHP黑魔法

作者:Matrix_ling

這裏必須得說一下==和===這倆貨的重要性。
==是比較運算,它不會去檢查條件式的表達式的類型
===是恒等,它會檢查查表達式的值與類型是否相等
NULL,0,”0″,array()使用==和false比較時,都是會返回true的,而使用===卻不會
這個基礎知識點大家應該都知道,所以提一下,下面就不會再拿出來說了。

數組

0x01
很多時候,PHP數組都發揮了至關重要的作用,先來看下BOSTEN KEYPARTY中的一道題:

Default
1 2 3 4 5 6 7 8 if (isset($_GET[‘name‘]) and isset($_GET[‘password‘])) { if ($_GET[‘name‘] == $_GET[‘password‘]) print ‘Your password can not be your name.‘; else if (sha1($_GET[‘name‘]) === sha1($_GET[‘password‘]))
die(‘Flag: ‘.$flag); else print ‘Invalid password‘; }

這道題,我們首先要確保name和password的值不能相同,其次,sha1加密之後的name和password的值又必須完全相同 我們知道,這時的a[0] = 1;所以name[] = 1和password[]= 2相比較,可以跳過第一個判斷,而如果使用sha1對一個數組進行加密,返回的將是NULL,NULL===NULL,這是成立的,所以構造兩個數組,成功拿到flag

0x02
再看bosten keyparty上的另外一道題:

Default
1 2 3 4 5 6 if (isset($_GET[‘password‘])) { if (strcmp($_GET[‘password‘], $flag) == 0) die(‘Flag: ‘.$flag); else print ‘Invalid password‘; }

這裏,使用strcmp去比較password和flag,如果==0的話,就給出flag,但是strcmp比較,如果相等才會返回0,如果不相等的話,要麽大於0,要麽小於0,但是strcmp只會處理字符串參數,如果給個數組的話呢,就會返回NULL,而判斷使用的是==,NULL==0是bool(true)的,所以,這道題還是一如既往構造一個數組進去

0x03
bosten keyparty上的又又一道題:

Default
1 2 3 4 5 6 7 8 if (isset ($_GET[‘password‘])) { if (ereg ("^[a-zA-Z0-9]+[ DISCUZ_CODE_2 ]quot;, $_GET[‘password‘]) === FALSE) echo ‘You password must be alphanumeric‘; else if (strpos ($_GET[‘password‘], ‘--‘) !== FALSE) die(‘Flag: ‘ . $flag); else echo ‘Invalid password‘; }

這道題有兩種做法,我們還是先說數組 ereg是處理字符串的,所以,按照原理,我們將password構造一個arr[],傳入之後,ereg是返回NULL的,===判斷NULL和FALSE,是不相等的,所以可以進入第二個判斷,而strpos處理數組,也是返回NULL,註意這裏的是!==,NULL!==FALSE,條件成立,拿到flag, 第二種做法,ereg讀到%00的時候,就截止了,所以可以構造s%00–,也能拿到flag(這也算是一個黑魔法嗎?哈哈)

數字的比較

0x01
wechall上的一道題:

Default
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function noother_says_correct($number) { $one = ord(‘1‘); $nine = ord(‘9‘); // Check all the input characters! for ($i = 0; $i < strlen($number); $i++) { // Disallow all the digits! $digit = ord($number{$i}); if ( ($digit >= $one) && ($digit <= $nine) ) { // Aha, digit not allowed! return false; } } return $number == "3735929054"; }

這裏,它不讓輸入1到9的數字,但是後面卻讓比較一串數字,平常的方法肯定就不能行事了,大家都知道計算機中的進制轉換,當然也是可以拿來比較的,0x開頭則表示16進制,將這串數字轉換成16進制之後發現,是deadc0de,在開頭加上0x,代表這個是16進制的數字,然後再和十進制的3735929054比較,答案當然是相同的,返回true拿到flag

0x02
看安全寶約寶妹的一道題:

Default
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 $flag = "THIS IS FLAG"; if ("POST" == $_SERVER[‘REQUEST_METHOD‘]) { $password = $_POST[‘password‘]; if (0 >= preg_match(‘/^[[:graph:]]{12,}$/‘, $password)) { echo ‘Wrong Format‘; exit; } while (TRUE) { $reg = ‘/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/‘; if (6 > preg_match_all($reg, $password, $arr)) break; $c = 0; $ps = array(‘punct‘, ‘digit‘, ‘upper‘, ‘lower‘); foreach ($ps as $pt) { if (preg_match("/[[:$pt:]]+/", $password)) $c += 1; } if ($c < 3) break; if ("42" == $password) echo $flag; else echo ‘Wrong password‘; exit; } }

在烏雲zone上,X總已經對其進行分析了

傳送門,這塊是數學的東西了。。 42.00e+0000000000,10的00000次方。。等於42.000000…. 結果其實就是42,不過有時候這些東西也會出奇跡的是不是。。

switch沒有break

在wechall上有一道題:

Default
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 if (isset($_GET[‘which‘])) { $which = $_GET[‘which‘]; switch ($which) { case 0: case 1: case 2: require_once $which.‘.php‘; break; default: echo GWF_HTML::error(‘PHP-0817‘, ‘Hacker NoNoNo!‘, false); break; } }

讓我們包含當前目錄中的solution文件,這裏會發現在case 0和case 1的時候,沒有break,按照常規思維,應該是0比較不成功,進入比較1,然後比較2,再然後進入default,但是事實卻不是這樣,事實上,在case 0的時候,進入了case 0的方法體,但是卻沒有break,這個時候,默認判斷已經比較成功了,而如果匹配成功之後,會繼續執行後面的語句,這個時候,是不會再繼續進行任何判斷的。也就是說,我們which傳入solution的時候,case 0比較進入了方法體,但是沒有break,默認已經匹配成功,往下執行不再判斷,進入2的時候,執行了require_once solution.php,查閱資料之後發現, 這個黑魔法是繼承於C語言,paper傳送陣:傳送陣

小結

至此,就我自己遇到過的很有意思的php黑魔法就這麽點了,若大家有其他猥瑣的trick或者屌炸天的黑魔法,大家一起交流交流咯,無形裝逼,最為致命,摸摸大。

【via@Sco4x0】

PHP黑魔法(該篇文章轉自:http://www.91ri.org/12634.html 目的是作為自己的筆記方便查找)