CTF:PHP弱类型常见考点总结

CTF:PHP弱类型常见考点总结

PHP弱类型比较是CTF比赛中的常见考点,当使用==进行比较时,类型转换可能导致非预期的结果。

如0 == “abc"会返回false,但"0e12345” == "0e67890"会被认为是相等的,因为都被视为科学计数法的0。另外,像true和任何非空字符串比较可能为真,如true == "non-empty string"是true。

还有MD5和SHA1的弱碰撞。如两个不同的字符串经过哈希后以0e开头,比较时会视为相等。例如,MD5(‘240610708’)是0e462097431906509019562988736854,和MD5(‘QNKCDZO’)的结果类似,这样比较时会相等。

switch和in_array的松散比较。当switch使用松散类型时,比如字符串和数字比较,比如case 0会匹配字符串"abc",因为字符串转换为数字是0。而in_array默认不开启严格模式,所以可能被绕过。比如查找字符串"abc"在数组中是否有0的情况,因为类型转换后可能匹配。

还有strcmp和数组的漏洞。如果strcmp的参数是数组,会返回0,比如strcmp( G E T [ ′ p a s s w o r d ′ ] , ′ a b c ′ ) ,如果传入 p a s s w o r d [ ] = x ,就会导致返回 0 ,从而绕过检查。同样, m d 5 ( 数组 ) 会返回 n u l l ,如果比较 m d 5 ( _GET[‘password’], ‘abc’),如果传入password[]=x,就会导致返回0,从而绕过检查。同样,md5(数组)会返回null,如果比较md5( G​ET[′password′],′abc′),如果传入password[]=x,就会导致返回0,从而绕过检查。同样,md5(数组)会返回null,如果比较md5(_GET[‘a’]) == md5($_GET[‘b’]),传入数组的话,两边都为null,从而相等。

JSON解析中的问题,比如json_decode解析数字字符串为整数,可能导致类型比较问题。例如,如果后端期望的是字符串类型的值,但传入的是数字,可能被误判。例如,{“num”: “123”}和{“num”: 123}在PHP中会被视为不同,但如果处理不当,可能被利用。

还有is_numeric的问题,比如字符串中包含十六进制或科学计数法会被认为是数字,可能导致注入或溢出。例如,0x61646d696e会被当作数字,转换为十进制后是admin的ASCII值,可能用于绕过检查。

另外,switch的松散比较和类型转换,比如当switch传入的是字符串,而case是数字时,可能导致非预期的分支执行。比如传入"1abc",转换为整数1,会匹配case 1。

还有关于=的严格比较和的区别,在CTF中常被用来设计陷阱,比如要求使用时可以通过类型转换绕过,而=则需要完全匹配。

还有数组和字符串的转换,比如当数组被当作字符串使用时,会变成"Array",而某些情况下可能被利用,比如在拼接SQL查询时,但可能这个点更多是注入相关,但弱类型可能也有涉及。

还有关于NULL和空字符串的比较,比如使用时,NULL == “” 为true,而=则为false。这可能在某些条件判断中被利用。

另外,可能涉及十六进制和八进制的字符串转换,比如"0x1a"被转换为26,或者"0123"被当作八进制,但PHP中可能在某些函数处理时需要注意。

使用sha1处理数组返回false,如果比较sha1( a ) = = s h a 1 ( a) == sha1( a)==sha1(b),当 a 和 a和 a和b都是数组时,两边都是false,从而相等。或者使用===比较时,两边都是false,但题目可能设计成松散比较,导致false == 0或者其他情况。

还有,当变量被用来进行数学运算时,自动转换为整数或浮点数,可能造成溢出或截断,比如大数字字符串转换为整数时变成负数,或者科学计数法表示,如"1e3"被转换为1000。

另外,在正则表达式匹配时,使用弱类型可能导致绕过,比如使用^0在PHP中可能因为类型转换导致匹配失败。

可能还需要考虑强制类型转换,比如在条件判断中使用加法或其他运算符,导致类型转换,例如"123abc" + 0得到123,从而绕过某些检查。

总结下来,常见的考点应该包括:

\1. 松散比较(==)的类型转换问题,包括科学计数法、字符串转数字等。

\2. 哈希比较中的0e开头字符串。

\3. switch和in_array的松散比较。

\4. strcmp等函数处理数组时的漏洞。

\5. JSON解析中的类型混淆。

\6. is_numeric的检测问题(十六进制、科学计数法)。

\7. 类型转换在条件判断或数学运算中的副作用。

\8. 某些函数返回值的类型问题,如md5数组返回null。

\9. 十六进制和八进制的转换问题。

\10. 使用恒等(=)和相等()运算符的不同。

可能还要注意PHP版本的不同,比如某些行为在PHP5和PHP7中的差异,例如在PHP7中,0e开头的数字字符串在比较时会当作数字,而某些函数的行为可能变化,但CTF题目可能仍以PHP5的环境为主。

以下是典型考点及示例:

*1. 松散比较(*==*)的类型转换***
  • 原理:PHP在==比较时会自动转换类型,导致非预期结果。

    • 科学计数法绕过"0e12345" == "0e67890"True(视为0)。
    • 字符串与数字比较"123abc" == 123True(字符串转为整型123)。
    • 布尔值陷阱true == "non-empty"Truefalse == "0"True

CTF应用

if ($_GET[‘a’] == ‘admin’) { /* 传入a=0可绕过 */ }


*2. 哈希弱碰撞(0e开头的MD5/SHA1)*
  • 原理:某些字符串哈希后以0e开头,松散比较时视为0。

    • MD5示例

      md5(‘240610708’) = 0e462097431906509019562988736854

    • md5(‘QNKCDZO’) = 0e830400451993494058024219903391

    • // 满足 KaTeX parse error: Undefined control sequence: \[ at position 6: \_GET\̲[̲‘a’\] != G E T …_GET[‘b’])

    • SHA1示例sha1('aaroZmOk')sha1('aaK1STfY')均以0e开头。


*3. 函数参数类型漏洞*
  • strcmp数组绕过
    strcmp($_POST['pass'], 'password')中,若pass为数组(pass[]=1),返回NULL,松散比较时NULL == 0
  • md5/sha1处理数组
    md5(array())返回NULL,若比较md5($_GET['a']) == md5($_GET['b']),传入数组使两边均为NULL

*4. switch/in_array的松散比较*
  • switch类型转换

    $input = “1abc”;

  • switch ($input) {

  • case 1: // 匹配成功,字符串转为整型1

  • // 执行敏感操作}

  • in_array默认松散
    in_array('abc', [0, 1, 2])True('abc’转为整型0)。


*5. JSON解析类型混淆*
  • 原理json_decode可能将字符串数字解析为整型。

    $data = json_decode(‘{“is_admin”: “0”}’);

  • if ($data->is_admin == true)

  • { // "0"转为整型0,0 == false // 被绕过}


*6. is_numeric的陷阱*
  • 十六进制/科学计数法
    is_numeric('0x1a')True(PHP5),is_numeric('1e3')True
  • 利用场景
    传入0x61646d696e(hex转ASCII为admin)绕过字符串过滤。

*7. 类型转换的数学运算*
  • 字符串转数字截断
    "123abc" + 456 = 579"abc"部分被忽略。
  • 科学计数法计算
    "1e3" == 1000True

*8. 严格比较(=)与松散比较()*
  • 绕过技巧:若代码误用==,可通过类型转换构造Payload。

if($_POST[‘code’] == 12345) {

// 传入code=12345abc 可绕过(转为整型12345)}

9.strpos 返回值的类型问题

在 PHP 中,strpos() 函数用于查找子字符串在目标字符串中首次出现的位置,其返回值类型存在特殊的类型问题,尤其在松散比较(==场景下可能导致安全漏洞。返回子字符串在目标字符串中的位置索引(从 0 开始计数),若未找到则返回 false。PHP 的松散比较(==)会将 0(整数)和 false(布尔值)视为相等。

if (strpos($_GET[‘data’], ‘ctf’) == false) {

// 认为未找到’ctf’,

但若 data=ctf123,strpos返回0,0 == false → 成立!

}

// 应使用严格比较:strpos(…) === false

*10. 空字符串与零的隐式转换*
  • 原理:空字符串 "" 在比较/运算中可能转为 0

    if ($_POST[‘code’] == 0) { // 传入 code= 或 code=“”,空字符串转为0,绕过验证}

*11. 十六进制/八进制字符串转换*
  • 原理:字符串中的十六进制/八进制格式可能被转换为数字。

    i n p u t = ′ 0 x 61646 d 696 e ′ ; / / h e x ( " a d m i n " ) i f ( i s n u m e r i c ( input = ‘0x61646d696e’; // hex(“admin”)if (is_numeric( input=′0x61646d696e′;//hex(“admin”)if(isn​umeric(input) && $input == ‘admin’) { // 0x61646d696e 转为十进制后与字符串比较,可能绕过}

*12. 浮点数精度问题*
  • 原理:浮点数比较时精度损失导致非预期结果。

    a = 0.99999999999999999 ; a = 0.99999999999999999; a=0.99999999999999999;b = 1;if ($a == $b) { // true,精度丢失后均为1 }

*13.* empty() *和* isset() *的陷阱*
  • 原理:运算符(如 .+)强制转换变量类型。

    a = " 123 a b c " + 456 ; / / 579 (字符串转整型 123 后相加) a = “123abc” + 456; // 579(字符串转整型123后相加) a=“123abc”+456;//579(字符串转整型123后相加)b = “123” . 456; // “123456”(拼接为字符串)

  • 原理empty() 认为 "0"0null 均为“空”。

    if (empty($_GET[‘auth’])) {

    // 传入 auth=0 时,empty(0) → true,绕过身份检查}

*防御建议*
  1. 使用严格比较(===)。
  2. 函数启用严格模式,如in_array(..., true)
  3. 避免直接比较哈希值,优先对比原始字符串。
  4. 对用户输入显式类型转换(如(int)$_GET['id'])。

网络安全学习资源分享:

给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

因篇幅有限,仅展示部分资料,朋友们如果有需要全套《网络安全入门+进阶学习资源包,需要点击下方链接即可前往获取

读者福利 | 优快云大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)

👉1.成长路线图&学习规划👈

要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

在这里插入图片描述
在这里插入图片描述

👉2.网安入门到进阶视频教程👈

很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,其中一共有21个章节,每个章节都是当前板块的精华浓缩。(全套教程文末领取哈)
在这里插入图片描述

在这里插入图片描述

👉3.SRC&黑客文档👈

大家最喜欢也是最关心的SRC技术文籍&黑客技术也有收录

SRC技术文籍:

在这里插入图片描述

黑客资料由于是敏感资源,这里不能直接展示哦!(全套教程文末领取哈)

👉4.护网行动资料👈

其中关于HW护网行动,也准备了对应的资料,这些内容可相当于比赛的金手指!

在这里插入图片描述

👉5.黑客必读书单👈

在这里插入图片描述

👉6.网络安全岗面试题合集👈

当你自学到这里,你就要开始思考找工作的事情了,而工作绕不开的就是真题和面试题。
在这里插入图片描述
所有资料共282G,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,可以扫描下方二维码或链接免费领取~

读者福利 | 优快云大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值