php弱类型问题总结

流过昼夜 提交于 2020-11-08 18:23:46

No.1

声明

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。

雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。


No.2

弱类型介绍

php是特别方便的一个语言,在申明一个变量的时候,并不需要指明它保存的数据类型,但是由于其自身弱类型语言的特性以及内置函数对于传入参数的松散处理,会带来很多的安全问题,这里将进行简要介绍。

弱类型语言对变量的数据类型没有限制,可以将变量赋值成其他类型变量,同时变量可以转换成任意其他类型的数据。


No.3

弱类型会产生的问题

使用PHP函数对变量$x进行比较:

==比较两个变量的值,不比较数据类型。

===比较两个变量的值和类型。


类型转换问题

类型转换是无法避免的问题。例如需要将GET或者是POST的参数转换为int类型,或者是两个变量不匹配的时候,PHP会自动地进行变量转换。但是PHP是一个弱类型的语言,导致在进行类型转换的时候会存在很多意想不到的问题。

var_dump("abc" == 0); //bool(true)
var_dump("1ab" == 1); //bool(true)
var_dump("ab1" == 1); //bool(false)
var_dump("ab0" == 0); //bool(true)

1.int转string:

$var = 5;
方式1:$item = (string)$var;
方式2:$item = strval($var);

2.string转int:intval()函数

var_dump(intval('2')) //2
var_dump(intval('3abcd')) //3
var_dump(intval('abcd')) //0

在intval()转换的时候,会将从字符串的开始进行转换知道遇到一个非数字的字符。即使出现无法转换的字符串,intval()不会报错而是返回0。

3.Hash比较

"0e132456789"=="0e7124511451155" //true
"0e123456abc"=="0e1dddada" //false
"0e1abc"=="0" //true

在进行比较运算时,如果遇到了0e\d+这种字符串,就会将这种字符串解析为科学计数法。所以上面例子中2个数的值都是0因而就相等了。如果不满足0e\d+这种模式就不会相等。

4.十六进制转换

"0x1e240"=="123456" //true
"0x1e240"==123456 //true
"0x1e240"=="1e240" //false

当其中的一个字符串是0x开头的时候,PHP会将此字符串解析成为十进制然后再进行比较,0x1240解析成为十进制就是123456,所以与int类型和string类型的123456比较都是相等。

5.函数松散性

  • switch

如果switch是数字类型的case的判断时,switch会将其中的参数转换为int类型。

$abc = "1ab";
switch ($abc) {
case 1:
echo "this is 1."; //输出
break;
case 2:
echo "this is 2.";
break;
case 3:
echo "this is 3.";
break;
}

$abc = "abc";
switch ($abc) {
case 0:
echo "this is 1."; //输出
break;
case 1:
echo "this is 2.";
break;
case 2:
echo "this is 3.";
break;
}

这里再说一下switch函数没有break的情况,它会一直向下执行。

$abc = "abc";
switch ($abc) {
case 0:
echo "this is 1."; //输出
case 1:
echo "this is 2."; //输出
case 2:
echo "this is 3."; //输出
}

  • md5

0e开头的全部相等(绕过==判断),两个字符串转换成MD5值时都是0e开头,0e 纯数字这种格式的字符串在判断相等的时候会被认为是科学计数法的数字,先做字符串到数字的转换。

var_dump(md5('240610708') == md5('QNKCDZO')); //bool(true)

纯数字类:

240610708
0e462097431906509019562988736854

314282422
0e990995504821699494520356953734

571579406
0e972379832854295224118025748221

903251147
0e174510503823932942361353209384

1110242161
0e435874558488625891324861198103

1320830526
0e912095958985483346995414060832

1586264293
0e622743671155995737639662718498

2302756269
0e250566888497473798724426794462

2427435592
0e067696952328669732475498472343

2653531602
0e877487522341544758028810610885

3293867441
0e471001201303602543921144570260

3295421201
0e703870333002232681239618856220

3465814713
0e258631645650999664521705537122

3524854780
0e507419062489887827087815735195

3908336290
0e807624498959190415881248245271

4011627063
0e485805687034439905938362701775

4775635065
0e998212089946640967599450361168

4790555361
0e643442214660994430134492464512

5432453531
0e512318699085881630861890526097

5579679820
0e877622011730221803461740184915

5585393579
0e664357355382305805992765337023

6376552501
0e165886706997482187870215578015

7124129977
0e500007361044747804682122060876

7197546197
0e915188576072469101457315675502

7656486157
0e451569119711843337267091732412

大写字母类:

QLTHNDT
0e405967825401955372549139051580

QNKCDZO
0e830400451993494058024219903391

EEIZDOI
0e782601363539291779881938479162

TUFEPMC
0e839407194569345277863905212547

UTIPEZQ
0e382098788231234954670291303879

UYXFLOI
0e552539585246568817348686838809

IHKFRNS
0e256160682445802696926137988570

PJNPDWY
0e291529052894702774557631701704

ABJIHVY
0e755264355178451322893275696586

DQWRASX
0e742373665639232907775599582643

DYAXWCA
0e424759758842488633464374063001

GEGHBXL
0e248776895502908863709684713578

GGHMVOE
0e362766013028313274586933780773

GZECLQZ
0e537612333747236407713628225676

NWWKITQ
0e763082070976038347657360817689

NOOPCJF
0e818888003657176127862245791911

MAUXXQC
0e478478466848439040434801845361

MMHUWUV
0e701732711630150438129209816536

md5()中的需要是一个string类型的参数。但是当你传递一个array时,md5()`不会报错,只是会无法正确地求出array的md5值,返回false,这样就会导致任意2个array的md5值都会相等。(绕过===判断)

$array1=array(1,2,3);
$array2=array(4,5,6);
var_dump(md5($array1)===md5($array2)) //true

  • sha1

sha1函数和md5函数一样不能判断数组的值。

$array1=[1,2,3];
$array2=[4,5,6];
var_dump(sha1($array1)===sha1($array2)); //true

  • strcmp

strcmp()函数在PHP官方手册中的描述是int strcmp ( string $str1 , string $str2 ) ,需要给strcmp()传递2个string类型的参数。如果str1小于str2,返回-1,相等返回0,否则返回1。strcmp函数比较字符串的本质是将两个变量转换为ascii,然后进行减法运算,然后根据运算结果来决定返回值。

$array=[1,2,3];
var_dump(strcmp($array,'123')); //null,如果是==比较的话,null就等于false

  • josn(这个不符合松散性)

json_decode()对 JSON 格式的字符串进行解码

<?php
if (isset($_POST['message'])) {
$message = json_decode($_POST['message']);
$key ="*********";
if ($message->key == $key) {
echo "flag";
}
else {
echo "fail";
}
}
else{
echo "~~~~";
}
?>

输入一个json类型的字符串,json_decode函数解密成一个数组,判断数组中key的值是否等于 $key的值,但是$key的值我们不知道,但是可以利用0和字符串==比较相等绕过。

6.最终payload为:message={"key":0}

  • in_array/array_search

在PHP手册中,in_array()函数的解释是bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] ) ,如果strict参数没有提供,那么in_array就会使用松散比较来判断$needle是否在$haystack中。当strince的值为true时,in_array()会比较needls的类型和haystack中的类型是否相同。

$array=[0,1,2,'3'];
var_dump(in_array('abc', $array)); //true
var_dump(in_array('1bc', $array)); //true

可以看到上面的情况返回的都是true,因为'abc'会转换为0,'1bc'转换为1。

  • is_numeric

is_numeric() 函数用于检测变量是否为数字或数字字符串。在这里我们的payload需要是一个大于1336的数字后面加上非数字即可(%00也可以),如1337+,他不是数字或数字字符串,但是与数字1336进行比较时,又会把前面的1337当成数字来运算。

<?php
error_reporting(0);
$flag = "flag{test}";
$temp = $_GET['password'];
is_numeric($temp)?die("no numeric"):NULL;
if($temp>1336){
echo $flag;
}
?>

  • intval

Intval()函数最大的值取决于操作系统。32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。64 位系统上,最大带符号的 integer 值是 9223372036854775807。

一个数值超出限制的话依然会返回最大值

echo intval('9223372036854775807000'); //输出2147483647


No.4

总结

弱类型确实提升了程序员书写代码的效率,但是也带来了严重的安全问题。在使用PHP的比较时,注意合理利用松散比较与严格比较的区别和规范传入的参数类型,防止漏洞的出现。


安全服务部华北大区致力于天津、山西、内蒙以及河北四地安全服务业务支撑,主要提供渗透测试、红蓝对抗、溯源取证、安全咨询等领域的安全服务业务。拥有专业级安全技术、应急响应以及丰富的攻防演练和红蓝对抗经验,致力于打造一个规范、安全、高效、诚信、专业的安全服务团队。


No.5

招聘启事

安全服务售前工程师
————————
工作地点:天津
【岗位职责】
1.负责售前工作,配合销售人员参与投标项目,负责撰写投标方案技术文件部分和过程中的技术应答文件,完成现场讲标、答疑等整个投标过程工作;
2.负责挖掘和引导客户服务需求,为客户提供合理有效的安全解决方案;与用户进行现场交流,包括初次交流、具体项目交流和投标交流;
3.针对客户网络架构和安全服务需求,制定合理的安全服务解决方案;
4.负责和参与对用户的短期培训和讲座等;
5.作为对销售部门售前过程的唯一接口,负责帮助销售协调售前支持和其他部门的资源。

【任职要求】
1.具有较强的沟通能力、学习能力、灵活的处事能力、文档编写能力,擅长PPT编写和演示;
2.熟悉安全服务业务(漏洞扫描、渗透测试、风险评估、安全评估、安全培训、代码审计、应急响应、网络安保等)服务内容及流程;
3.熟悉主流安全技术和流行安全产品(防火墙、防毒、入侵检测、漏洞扫描等)的应用部署方案;
4.熟悉网络攻击、黑客攻防等安全技术;了解国内外网络、安全界发展现状;了解各主流安全厂家厂家安全服务的技术优劣势。
5.较强的敬业精神与工作责任心。
优先考虑的条件:
1.具有CISSP、CISA、CSSLP、ISO27001、ITIL、PMP、COBIT、Security+、CISP证书者优先;
2.具有运营商、金融、央企、政府等行业工作经验或从事2年以上行业安全服务售前工作。
3.具备行业安全标准、政策者,同类安全公司从业经验者优先;

简历投递至:youyo.li@dbappsecurity.com.cn

安全服务工程师(实习)
————————
工作地点:天津
【岗位职责】
1.参与渗透测试、安全加固、应急响应等安全服务项目实施工作;
2.对Web应用、APP应用、数据库、主机等进行安全评估,并给出解决方案;
3.负责安全攻防渗透相关技术研究;

【任职要求】
1.2021年毕业,对网络安全攻防有浓厚兴趣。
2.熟练掌握渗透测试技巧,熟悉渗透测试步骤、方法、流程,熟练运用各类安全软件、安全测试工具等;
3.熟悉常见web安全漏洞的原理、测试方法、加固方法;
4.熟悉Linux常见命令及网络基本协议如TCP/IP等;
5.备优秀的沟通协调能力、学习能力、抗压能力;

优先考虑的条件:
1.有web开发经验或熟悉PHP/C#/Java/Python任意一种语言者优先;
2.有CTF、攻防比赛获得奖项者优先;
3.有知名SRC、漏洞平台、CVE、CNVD、CNNVD漏洞提交证明者优先;
4.本科学历优先;

简历投递至:youyo.li@dbappsecurity.com.cn

安全服务工程师
————————
工作地点:天津
【岗位职责】
1.具备良好的职业道德,具备良好的团队合作精神,自学能力;
2.熟悉渗透测试的步骤、方法、流程、熟练掌握各种渗透测试工具的使用;
3.熟悉常见的Web代码,熟悉SQL注入、XSS等常见的安全漏洞的评估方法、利用及修复。
4.熟悉常见的主机系统和网络的攻击、防御方法、网络渗透技术;
5.负责对客户系统进行渗透测试、安全基线、安全加固、应急响应、安全培训等安全服务实施工作。
6.负责安全攻防渗透相关技术研究;

【任职要求】
1.熟悉内网渗透;熟悉Owasp Top10漏洞原理、攻击、防御手法;
2.熟悉常见的主机系统和网络的攻击、防御方法、网络渗透技术;
3.至少熟悉一种编程语言(php/java/python/c),并可以编写POC;
4.熟悉操作系统、中间件、数据库、框架等常见问题;
5.热爱网络安全、好学、抗压能力强;
6.执行力强,沟通协调能力强,能独立处理一般性分歧和日常事务协调,具备一定的情绪控制能力和抗压能力。
7.良好的语言表达能力、文档编写能力。

优秀考虑的条件:
1、有CNVD、CNNVD等漏洞证书、CVE或CTF比赛获奖者优先;
2、本科学历优先;

简历投递至:youyo.li@dbappsecurity.com.cn


专注渗透测试技术

全球最新网络攻击技术

END

本文分享自微信公众号 - 雷神众测(thorsrc)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!