企业管理系统定制开发攻防世界web新手区easyphp题解writeup

  • 写在前面

       企业管理系统定制开发最近在学习CTF web相关知识,顺带学习php,企业管理系统定制开发在攻防世界平台上做做题。企业管理系统定制开发遇到了一道名为easyphp的题目,企业管理系统定制开发对我这个新手一点也不easy,企业管理系统定制开发于是决定把过程记录下来。   

      参考了官网上shuita111师傅的WP,这里主要写得更加完整详细一些。

  • 正文部分

       首先看代码,大概能够看出需要咱们传入的a、b、c满足中间那些条件,然后可以获得key1和key2,最后得到flag。

  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"."\";
  34. echo $flag;
  35. }
  36. ?> Emmm...
  • 第一个if块(解决a和b)

条件1:这里对提交的a需要满足a非空 且 a的数值大于该数 且 a的长度不超过3。

if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3)


分析思路:intval函数就是将我们输入的字符串类型转化成整数,这里可以查看php intval函数的用法(根据菜鸟教程intval(‘1e5’)输出的是1,但我测试了下实际输出和php版本有关,另外在官网找到一个相同的Notes httpfs://www.php.net/manual/en/function.intval也是一个例子。在题目中例如intval(‘1e5’)就是10000。因此,科学计数法表示的1e7/8/9可以满足上述三个条件。

条件2:这里对提交的b需要满足b非空,并且b的md5值的倒数6位为8b184b。

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

 这个没什么妙招,只能写个脚本进行爆破了,最后发现(53724)符合条件。

  • 第二个if块(解决c)

        变量c也需要我们get上去,但是需要json格式。在确定了之后进行json编码即可。

条件1:c非空 且 不是数值类型(前面有个感叹号) 且 c的m键值要大于2022。

  1. $c=(array)json_decode(@$_GET['c']);
  2. if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022)

分析思路:这里主要考察is_numeric函数的用法,is_numeric在php中判断参数是否是数值类型是否是数字或数字字符串。注意is_numeric("a123")返回false,is_numeric("123a")也返回false;单看这里还不能下结论。

再看后面,c的m键值后面还要做比较,因此不能直接简单构造一个is_numreric为false的字符串。例如,'123a'和一个整数作比较时,它会转换成123;'a123'和整数作比较时,由于第一个位置是a,非整数,php则规定其值为0,即变成了0和123比较(关于这个部分可以参考 php中字符串和整数比较 相关知识)。于是可以构造出一个c:{"m":"12345a"}等等。

条件2:c还有个n键,其值是一个array类型,大小为2,并且第一个元素是一个数组类型。即类似于:[[*,*...],*]。

  1. if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
  2. $d = array_search("DGGJ", $c["n"]);
  3. $d === false?die("no..."):NULL;
  4. foreach($c["n"] as $key=>$val){
  5. $val==="DGGJ"?die("no......"):NULL;
  6. }
  7. $key2 = 1;
  8. }else{
  9. die("no hack");

分析思路:后面语句查找n键中是否有字符串'DGGJ',如果找到指定的键值,则返回对应的键名,否则返回 FALSE。看到这里,?:运算符找不到的情况下直接die(退出),因此这里应该让它找到,故n键第二个值为'DGGJ'。

但是,后面foreach遍历时候有'DGGJ'反而直接die,看到这里,发现这两个是矛盾的。

这个问题想了半天,最后终于明白了。回到array_search函数,查找是否有,那不就是比较吗!而且前文说到将一个字符串和一整数比较时会将字符串向整数转化,这个'DGGJ'一点整数的影子都找不到,因此只能判断为0。由此可知,第一种思路直接在c的第二个位置填上字符串'DGGJ'比较成功,第二种思路填一个数字0比较成功。第一种思路前面已经pass,因此选择第二种思路。

最后根据json编码格式对c进行编码即可。

到此为止,就已经执行完了key1和key2的赋值语句,顺着下去直接可以得到flag。

最终构造的payload:http://ip:port/?a=1e9&b=53724&c={"m":"12345a","n":[[0,1,2],0]}

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发