HNCTF-2025-部分web复现
Really_Ez_Rce
源码如下
1 | |
首先是请求参数Number,限制其不能含有数字,并且还要利用intval()转化成整数的返回值要为真,才能继续执行下面的代码,这里可以利用数组绕过,传参时写成Number[]=1的形式,既满足不是纯数字,又满足转化成整数返回值为真
1 | |

然后是POST参数cmd,存在WAF对其内容进行限制,这里可以利用空变量$@进行绕过
1 | |

也可以利用变量拼接绕过
1 | |

然后是读取flag.txt中的flag,虽然cat可以利用上面的方法进行绕过,但是这里把点.也过滤了,这里可以考虑使用base64编码进入绕过

1 | |

ez_php
源码如下
1 | |
首先是在GOGOGO类中有一个__destruct()魔术方法,会执行下面这个语句,
1 | |
这里会把$this->dengchao当作字符串调用,刚好可以触发DouBao类中的__toString()魔术方法,在这个方法中会先有个MD5和Sha1强比较,这里可以利用数组绕过,然后执行下面的语句
1 | |
最后看第三个类HeiCaFei,存在一个__call魔术方法,在调用一个不存在的方法会触发,触发后会执行下面这个语句
1 | |
这里可以利用这个代码执行命令,这使用的是call_user_func_array()函数,在这个函数中第一个参数是$this->HongCaFei,会作为函数,这里可以写成system用于后续执行命令
第二个参数是[0 => $name],是将name作为唯一参数传给函数,最后执行这个函数,这里的name是传入魔术方法__call的第一个参数,是不存在的方法名,所以我们要调用的不存在的方法名可以写成要执行的命令
1 | |
最后还有一个异常函数需要绕过,不绕过代码不会执行,没有回显,可以借鉴文章:https://xz.aliyun.com/news/11289
最后可以得到的绕过方法就是加上下面这个代码
1 | |
然后将最后运行得到的序列化数据最后末尾的i:1;i:0;改为i:0;i:0;
最终exp
1 | |
1 | |
然后将末尾的i:1;i:0;改为i:0;i:0;
1 | |

DeceptiFlag
随便输入内容利用bp抓包,会发现存在三个参数


题目提示两个答案都要拼音

根据页面的背景猜测值是xiyangyang和huitailang,POST中第二个参数是Lang,猜测值为huitailang,其他俩都是xiyangyang

发送请求后会得到tips.php路径,放包跳转到该路径


并且会发现有个GET参数file,可以利用伪协议读取到flag,在cookie中有个base64编码的提示

1 | |

可以得到flag的路径是/var/flag/flag.txt
1 | |

1 | |
进行base64解码

奇怪的咖啡店
所给附件源码如下
1 | |
在/add路由中存在原型链污染,具体地方是下面这段代码
1 | |
这里定义一个merge的递归函数,可以将一个字典的内容或字典对象合并到另一个对象中
举个例子,有个源字典src和一个目标对象dst
1 | |
调用merge(src, dst)这个函数后,会将目标对象变为
1 | |
题目提示源码不完全

在本题中可以利用这个函数进行原型链污染,污染 _static_folder,从而实现任意文件读取,从而获取完整的源码
在 Flask 框架中,static_folder是应用初始化时的一个参数,指定静态文件的存储路径,默认值为项目根目录下的 static 文件夹,如果将其污染为根目录\,就相当于将所有静态文件的存储路径改为根目录,从而可以直接通过URL访问到服务器的所有文件,如通过访问http://xxx.com/etc/passwd直接读取/etc/passwd文件
在 Flask 框架中,在内部实现上,Flask 会把用户传入的 static_folder 参数赋值给 _static_folder 属性,所以我们可以直接污染_static_folder
exp
1 | |
访问/add,随便输入商品名称和价格,利用bp进行抓包

发现污染失败,存在waf过滤,对payload进行unicode 编码,注意使用\u005f这种,而不是%u005f,否则不会污染成功
1 | |

回显 “ 你无法添加商品 ” 是因为以下代码,无论是否污染成功都会回显这句话
1 | |
回到浏览器就可以通过 URL 直接访问服务器文件,先读完整源码
1 | |

1 | |
有个非预期,直接访问下载得到环境变量文件environ
1 | |

下面是预期解
存在黑名单,可以污染掉
1 | |
1 | |
1 | |

看到有个/aaadminnn路由
1 | |
注意其中的这段代码可以打SSTI,设置好permission为payload即可
1 | |
要满足session中的name为admin,permission不为0,可以看以下这段代码
1 | |
这里设置了SECRET_KEY是一个随机数,在/路由下会把name设置成customer,把permission设置为0
思路:可以将SECRET_KEY污染成一个具体的固定值,然后利用污染后的SECRET_KEY伪造session,使name为admin,permission为打SSTI的payload,从而可以访问/aaadminnn并进行RCE
首先污染SECRET_KEY为固定值123
1 | |
1 | |

利用污染的SECRET_KEY进行 Flask 框架的伪造session,利用工具
项目地址:https://github.com/noraj/flask-session-cookie-manager
先对原本的session进行解密
1 | |

伪造session,payload如下
记得引号前加上转义符\

1 | |
带着session去访问aaadminnn,这里要GET请求,因为POST请求会执行以下这个代码,直接return结束了


最后就是读4flloog

1 | |

Watch

提示flag在D盘中(其实是key),带上Token访问赛题环境

可以进行文件读取
1 | |

尝试直接目录穿越到D盘,不过失败
1 | |

在所给附件中的go.mod文件中可知GO版本是1.20,该版本存在一个CVE漏洞:CVE-2023-45283
就是\??\c:\x会被当作c:\x,所以可以构造出\??\d:\,即d:\,前面进行一次目录穿越从而进入d盘
1 | |

访问读取key.txt文件
1 | |

得到key
1 | |
