您现在的位置是:首页 > 技术教程 正文

[江苏工匠杯]easyphp

admin 阅读: 2024-03-18
后台-插件-广告管理-内容页头部广告(手机)

先看源码

  1. <?php
  2. highlight_file(__FILE__);
  3. $key1 = 0;
  4. $key2 = 0;
  5. $a = $_GET['a'];
  6. $b = $_GET['b'];
  7. if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
  8.   if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
  9.       $key1 = 1;
  10.       }else{
  11.           die("Emmm...再想想");
  12.       }
  13.   }else{
  14.   die("Emmm...");
  15. }
  16. $c=(array)json_decode(@$_GET['c']);
  17. if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
  18.   if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
  19.       $d = array_search("DGGJ", $c["n"]);
  20.       $d === false?die("no..."):NULL;
  21.       foreach($c["n"] as $key=>$val){
  22.           $val==="DGGJ"?die("no......"):NULL;
  23.       }
  24.       $key2 = 1;
  25.   }else{
  26.       die("no hack");
  27.   }
  28. }else{
  29.   die("no");
  30. }
  31. if($key1 && $key2){
  32.   include "Hgfks.php";
  33.   echo "You're right"."\n";
  34.   echo $flag;
  35. }

先看第一部分

要求get 传参a和b

intval — 获取变量的整数值

  1. ?id='1000' //"1000"或(1000)皆可
  2. ?id=125<<3 //左移
  3. ?id=680|320 //按位或
  4. ?id=992^8 //按位异或
  5. ?id=~~1000 //两次取反
  6. ?id=0x3e8 //十六进制
  7. ?id=0b1111101000 //二进制

要求a的值大于6000000且长度小于等于3

可以使用科学计数法绕过

a=3e8 #得到300000000大于6000000且长度小于等于3

再看传参b

'8b184b' === substr(md5($b),-6,6)

要求传参经过md5后的从截取密文后6位等于“8b184b”,这里就是一个简单的哈希碰撞,我们写一个Python脚本跑一下

从别的师傅copy

  1. import random
  2. import hashlib
  3. value = "8b184b"
  4. while 1:
  5.   plainText = random.randint(10**11, 10**12 - 1)
  6.   plainText = str(plainText)
  7.   MD5 = hashlib.md5()
  8.   MD5.update(plainText.encode(encoding='utf-8'))
  9.   cipherText = MD5.hexdigest()
  10.   if cipherText[-6:]==value :
  11.       print("碰撞成功:")
  12.       print("密文为:"+cipherText)
  13.       print("明文为:"+plainText)
  14.       break
  15.   else:
  16.       print("碰撞中.....")

跑出来的密文和明文分别为:

密文:842fc2485a1faa0681f78d3e098b184b

明文:792616362347

所以我们传入b=792616362347

接下来第二部分

  1. $c=(array)json_decode(@$_GET['c']);
  2. if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
  3.   if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
  4.       $d = array_search("DGGJ", $c["n"]);
  5.       $d === false?die("no..."):NULL;
  6.       foreach($c["n"] as $key=>$val){
  7.           $val==="DGGJ"?die("no......"):NULL;
  8.       }
  9.       $key2 = 1;
  10.   }else{
  11.       die("no hack");
  12.   }
  13. }else{
  14.   die("no");
  15. }

c需要传入一个json格式的字符串

其中key为m的value不能为数字,且要大于数字2022

当字符串与数字进行比较时,会将字符串强制转化为整型

所以我们可以传入一个123456a,在进行比较时会被强制转换为123456与2022进行比较

count():返回数组中元素的数目

再看key为n的value必须是一个数组,且value的数量必须为2,且第一个value也必须是一个数组

接着往下看

第一次用array_search搜索n中是否有"DGGJ",有的话才能开启下一步

第二次使用foreach循环搜索n中的值是否含有"DGGJ",没有的话才会使key2的值为1

这里就矛盾起来了,既要求n中有"DGGJ",又要求n中没有"DGGJ"

所以我们必须要绕过其中一个函数,array_search函数是可以绕过的

当函数将字符串与数字进行匹配时,其中是==这种弱等于,会将字符串强制转换为整型进行比较,"DGGJ"转化为整型为0

而注意第二个是===强等于,不仅比较值相等还会比较值得类型,所以就可以绕过第二个条件了

具体看下测试

image-20240315103553365

所以c={"m":"123456a","n":[["6"],0]} 最后的payload:

?a=3e8&b=792616362347&c={"m":"123456a","n":[[6],0]}

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索